tpope

Activity

Stars and mentions · Last 30 days, Oct 6 – Nov 4

GitHub stars16
Mentions1
01234Oct 6Oct 20Nov 4
UTC days · repositories tpope owns6 repositories

Top repositories

tpope’s repositories ranked by pull request authors, as on trending.

Loading

Contributes to

Repositories outside tpope’s account where tpope opened or reviewed pull requests in the past 365 days.

Who noticed tpope

Everyone who starred or forked tpope’s repositories since the archive began in 2011.

Notable accounts

Ordered by the stars their own repositories have received.

Biggest fans

Accounts that starred the most of these repositories.

Breakout weeks

Each repository’s best week of new stars, with the release published around it.

Mentions

2posts
Nov 51 post
  1. yadm + Neovim Git plugins didn't work, so I built yadm-git.nvim (and fixed the Bazzite symlink three times) Introduction Dotfiles managed by yadm live directly under $HOME, and there is no $HOME/.git. yadm's own git directory sits at ~/.local/share/yadm/repo.git. So Git-aware Neovim plugins like gitsigns.nvim / fugitive / lazygit.nvim decide "this isn't under git control" even while you're editing a file under $HOME. I built a tiny plugin whose only job is to make them "just work": yadm-git.nvim. This post covers three things: - The minimal design for letting yadm-managed dotfiles and nvim's Git plugins coexist - Why detecting yadm with a filesystem check beats a shell call (perf + testability) - How vim.env.HOME / vim.uv.os_homedir() / vim.fn.expand("~") diverge on an immutable distro, and which one I ended up choosing The last point — the Bazzite symlink — made me fix home-directory resolution three times over. What was the problem yadm is "a wrapper for managing dotfiles with git": it uses $HOME as the work tree and ~/.local/share/yadm/repo.git as the git directory. From the CLI, the yadm command calls git while passing GIT_DIR and GIT_WORK_TREE behind the scenes. But Neovim's Git plugins like gitsigns.nvim don't know about any of that. Open $HOME/.config/nvim/init.lua and, since there's no .git anywhere up that directory tree, it's judged "outside git control" — no diff, no blame. Typing GIT_DIR=... GIT_WORK_TREE=... nvim in the shell every time is tedious, and I want it to switch as I cd around. I just wanted a plugin to automate that. How I solved it The design decisions are simple. | Decision | Why | | ------------------------------------------------- | ------------------------------------------------------------------------------ | | No commands, no user interaction | It should just work with zero config. Whether you're under yadm is detectable. | | Filesystem check only (no shell call) | Good perf, stays in Lua, tests need a single mock | | Only set the env vars GIT_DIR / GIT_WORK_TREE | Minimal intervention — touches nothing in the existing Git plugins | | Driven by autocmds (VimEnter / DirChanged) | Set / clear as you cd in and out of yadm-managed paths | The detection logic is three steps: 1. If there's a .git (directory or file) anywhere up the current directory tree, treat it as a normal git repo and skip 2. Check whether the yadm repo exists at ~/.local/share/yadm/repo.git (v3+) or ~/.yadm/repo.git (legacy) 3. Check whether the current directory is under $HOME If all three are true, treat it as yadm-managed and set vim.env.GIT_DIR and vim.env.GIT_WORK_TREE. On DirChanged out, clear them. How the implementation evolved The main PRs in chronological order. | When | PR | What | | ---------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | 2025-06-02 | initial | First cut. Detected yadm with a shell call | | 2025-06 | #6 | Dropped the shell call for a pure-Lua filesystem check. Better perf + testability | | 2025-06 | #7 | Kept plugin state internally and exposed is_active() / get_yadm_repo_path() / get_state() as a public API | | 2025-06 | #9 | Added a DirChanged autocmd. Clears the env vars when leaving the yadm dir. Bundled a refactor splitting state / event into separate modules | | 2025-06 | #10 | Added a lualine status component. Shows a house icon and "dotfiles" while yadm is active | | 2025-06 | #11 | Moved activation logic from init to event handling. Unified on autocmds so teardown is event-driven too | | 2025-07 | #14 | Fixed a detection miss when .git is a file (a worktree) | | 2026-04 | #19 / #20 | Discovered that $HOME becomes a symlink on Bazzite-style immutable distros. Switched to going through vim.uv.os_homedir() | | 2026-05 | #22 | A further fix on top of #20. Unified on vim.fn.expand("~") | The current file layout. lua/yadm-git/ ├── init.lua -- entry point (exports setup()) ├── yadm.lua -- core: detection and env-var set/clear ├── state.lua -- plugin activation state ├── event.lua -- VimEnter / DirChanged autocmds ├── logger.lua -- debug logging └── options.lua -- config Where it bit me 1. Env vars left behind after you cd out (#9) The first implementation only fired on VimEnter. So it worked if you were under yadm when nvim started, but after :cd ~/work/project (an ordinary git repo, not under yadm), GIT_DIR stayed pointed at ~/.local/share/yadm/repo.git and gitsigns kept showing a broken view of yadm. The fix: re-evaluate is_yadm_managed() in a DirChanged autocmd and, if false, set the env vars back to nil via clear_yadm_env(). At the same time I split state / event into separate modules so init.lua only exports setup(). 2. A worktree exists as a .git file (#14) I was only checking vim.fn.finddir(".git", ...), so a worktree created with git worktree add (where .git is a text file rather than a directory) was judged "not git," and the yadm environment was set by mistake. Fixed by checking both finddir and findfile. 3. $HOME is a symlink on Bazzite (#19 → #20 → #22) This was the nastiest one. On immutable Fedora derivatives like Bazzite, /home/user is a symlink to /var/home/user. - $HOME is /var/home/user (physical path) - /etc/passwd says /home/user (symlink path) - Neovim's vim.fn.fnamemodify(":p") and vim.fn.getcwd() resolve the symlink → /home/user/... - vim.uv.os_homedir() reads $HOME via libuv, so it's /var/home/user So you get "the current directory is under /home/user/..., but $HOME is /var/home/user," which makes vim.startswith(cwd, home .. "/") false and the path isn't recognized as yadm-managed. The three fixes in sequence. | Attempt | Approach | Result | | ------- | ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------- | | #19 | Was using vim.env.HOME → the symlink-resolution problem surfaced | Reported | | #20 | Switched to vim.uv.os_homedir() | libuv doesn't resolve the symlink either, so same problem | | #22 | Unified on vim.fn.expand("~") | Goes through Neovim, so it rides the same symlink-resolution path as fnamemodify / getcwd. Fixed | The lesson: which "get the home directory" function you use changes the behavior. Whether it resolves symlinks is the key, and it has to match the side you compare against (the function that gets the cwd). In a Neovim plugin, vim.fn.expand("~") was the safest. The relevant source (with the comment). -- Resolve the user's home directory. -- Prefer `vim.fn.expand("~")` over `vim.uv.os_homedir()` or $HOME because on immutable distros -- (Bazzite, etc.) the folder /home/ is a symlink to /var/home/ which is resolved by Neovim -- in the functions `vim.fn.fnamemodify()` and `vim.fn.getcwd()` but not when using $HOME -- or libuv's `os_homedir()`. -- See issue #19 for more information. local function get_home() return vim.fn.expand "~" end Results - gitsigns / fugitive / lazygit just work while editing files under yadm - It switches automatically as you cd in and out - lualine can now show "yadm mode is on," which cut down on mistakes - The core is around 110 lines. Even with tests it's 234 lines + tests. It stays small. Wrap-up - The yadm × nvim Git-plugin coexistence problem is solved just by "setting and clearing GIT_DIR / GIT_WORK_TREE from autocmds" - A filesystem check instead of a shell call buys you both perf and testability - Home-directory resolution on an immutable distro is full of traps; I fixed it three times. In a Neovim plugin, vim.fn.expand("~") is the current right answer References Source and PRs. - Kohei-Wada/yadm-git.nvim (GitHub) - PR #6 Optimize external commands — shell call → filesystem - PR #7 plugin state management and tests — public API - PR #9 env vars not cleared on cd out — DirChanged handling + module split - PR #10 lualine component - PR #11 event-driven refactor - PR #14 worktree detection - PR #19 / #20 Bazzite symlink (os_homedir) - PR #22 expand("~") final fix Related tools. - yadm - gitsigns.nvim - vim-fugitive - lazygit.nvim - Bazzite (immutable Fedora) --- _This post was written with AI assistance and reviewed by the author._

  2. Typescript errors into vim quickfix You may use LSP and lua vim.diagnostic.setloclist() to show Typescript errors for a specific buffer. But sometimes you could have errors across the whole project. You can run tsc in the terminal and manually search for files with errors. But we can do better. Vim has the :make command which executes the program that is set into makeprg. By default, it's make but we can change it to any terminal program/command. The output of makeprg is then populated into quickfix. Update 🖊️ After discussion on reddit someone suggested a better approach. The error is already parced in compiler tsc. I just change makeprg=npx\ tsc instead of makeprg=tsc. vim.cmd [[ augroup strdr4605 autocmd FileType typescript,typescriptreact compiler tsc | setlocal makeprg=npx\ tsc augroup END ]] Initial post Let's create an auto command that will set makeprg to tsc if we are in a typescript project: vim.cmd [[ augroup strdr4605 autocmd FileType typescript,typescriptreact set makeprg=./node_modules/.bin/tsc augroup END ]] or with lua API: local augroup = vim.api.nvim_create_augroup("strdr4605", { clear = true }) vim.api.nvim_create_autocmd("FileType", { pattern = "typescript,typescriptreact", group = augroup, command = "compiler tsc | setlocal makeprg=npx\\ tsc", }) Run :make and see the output: :!./node_modules/.bin/tsc 2>&1| tee /var/folders/3w/m_v388s15pq9rpgswbt131w00000gn/T/nvim.strdr4605/708JAY/2 components/Date.tsx(6,28): error TS2339: Property 'toISOString' does not exist on type 'number'. (1 of 1): components/Date.tsx(6,28): error TS2339: Property 'toISOString' does not exist on type 'number'. Press ENTER or type command to continue and open the quickfix, :copen: components/Date.tsx(6,28): error TS2339: Property 'toISOString' does not exist on type 'number'. When trying to navigate to any file from quickfix, I see this error: Buffer not found. Why? Because the tsc compiler outputs in a format that is not clear for vim quickfix. The problem is in parenthesis around the file line and column: components/Date.tsx(6,28): But we can change this by piping the tsc output to sed command and replacing (6,28) with :6:28:. This is the output if we run it in the terminal: ./node_modules/.bin/tsc | sed 's/(\(.*\),\(.*\)):/:\1:\2:/' 130 ↵ components/Date.tsx:6:28: error TS2339: Property 'toISOString' does not exist on type 'number'. But to make it work in vim, we need to escape some chars. The final result is: vim.cmd [[ augroup strdr4605 autocmd FileType typescript,typescriptreact set makeprg=./node_modules/.bin/tsc\ \\\|\ sed\ 's/(\\(.*\\),\\(.*\\)):/:\\1:\\2:/' augroup END ]] Now when running :make the quickfix list is populated correctly and vim navigates to the first file in the list. I can fix Typescript errors one by one, by navigating with :cnext or using vim-unimpaired.

Achievements

Awards earned by the repositories tpope owns. Select an award to embed its badge.

Gold
21st place finishes
Silver
02nd place finishes
Bronze
03rd place finishes
Awarded repositories
1Owned by tpope now

Repositories

Ordered by gold, then silver, then bronze.

  1. heroku-fucking-consoleBest: 1st by stars, 216 stars200

Every award

Top-three finishes of these repositories in completed trending days and weeks, newest first.

  1. heroku-fucking-console
  2. heroku-fucking-console

A repository earns an award for finishing first, second or third in a completed trending day or week, ranked by new stars, new forks or pull request authors. Awards follow a repository through renames and transfers and count toward its current owner. Weeks run Monday to Sunday, UTC.