Skip to content

Latest commit

 

History

43 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

switchyard.nvim

ci Neovim Lua git worktree Claude Code License: MIT

Git worktrees and AI coding sessions in one picker for Neovim.

What it does

Lists the worktrees of the current repository alongside the AI sessions that ran in them, previews what each session was about, and switches your whole workspace to the one you pick.

  • Worktree-centric picker — branch, dirty state, ahead/behind, session count
  • Session recap in the preview — title, where you left off, files touched
  • Full workspace switch — buffers, session layout, LSP roots and the file tree all follow, so no stale buffers from another worktree
  • Safe delete — reports uncommitted changes and unmerged commits before removing

Installation

With lazy.nvim:

{
  "werdin/switchyard.nvim",
  dependencies = { "folke/snacks.nvim", "folke/persistence.nvim" },
  opts = {
    worktree_dir = ".claude/worktrees",
  },
  keys = {
    { "<leader>gw", "<cmd>Switchyard<cr>", desc = "Worktrees & sessions" },
  },
}

opts is passed to require("switchyard").setup(); :Switchyard opens the worktree picker for the repository containing the current directory.

Keys

In the worktree picker:

Key Action
<CR> switch the workspace to this worktree
<C-s> list the sessions of this worktree
<C-n> create a worktree from a branch
<C-d> delete this worktree, after a report of what is lost
<C-y> copy the worktree path

In the session list: <CR> switches the workspace to the session's worktree and resumes that session in a terminal; <C-o> goes back to the worktree list.

Configuration

Defaults, passed to setup():

require("switchyard").setup({
  worktree_dir = ".claude/worktrees",
  providers = { "claude" },
  claude = { cmd = { "claude" } },
})
  • worktree_dir — path, relative to the repository root, where <C-n> creates new worktrees (<worktree_dir>/<branch-slug>).
  • providers — names of the session providers to enable. Each listed name is required as switchyard.providers.<name>; an unknown or misconfigured provider is skipped with a warning instead of aborting setup().
  • claude — options forwarded to the claude provider:
    • claude.cmd — base command used to resume a session (--resume <id> is appended). Override this to point at a wrapper script or a non-default binary.

Events

Two User autocmd patterns fire around a workspace switch, for other plugins (lualine, tabby, lazygit, …) to hook:

Pattern When
SwitchyardLeavePre before the current workspace is torn down
SwitchyardEnter after the new worktree is active; data.path holds the path
vim.api.nvim_create_autocmd("User", {
  pattern = "SwitchyardEnter",
  callback = function(args)
    print("switched to " .. args.data.path)
  end,
})

What "switching" actually does

Picking a worktree is a full workspace replacement, not a :cd. In order:

  1. If any buffer has unsaved changes, prompt to save, discard, or cancel. Cancelling aborts the switch and leaves the workspace untouched.
  2. Save the current persistence.nvim session (if there is anything worth saving).
  3. Change directory to the target worktree.
  4. Close every buffer.
  5. Restore that worktree's own persistence.nvim session.
  6. Restart LSP clients, so they relaunch with the new root and attach correctly.

Buffers from the previous worktree do not survive the switch — this is deliberate. Worktree paths differ from the main repository by one path segment (.claude/worktrees/<branch>), so a picker or buffer list mixing files from two worktrees makes it easy to edit the wrong copy of a file without noticing. Each worktree gets its own persistence.nvim session (keyed by getcwd()), so nothing is lost — the previous worktree's buffers are exactly as you left them next time you switch back to it.

Requirements

  • Neovim >= 0.10 (uses vim.uv, vim.system, vim.lsp.get_clients)
  • snacks.nvim (picker)
  • persistence.nvim (workspace switching)
  • git >= 2.30

neo-tree.nvim is optional: when it is loaded, its root follows a switch. Run :checkhealth switchyard to verify the setup.

Documentation

:help switchyard after installation, or doc/switchyard.txt here. docs/design.md covers the full design and the reasoning behind it.

Contributing

make test          # plenary specs, headless
make lint          # luacheck
make format        # stylua

All three run in CI on every push and pull request.

License

MIT

About

Git worktrees and AI coding sessions in one picker for Neovim

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages