Multisession Agentic Workflow with Claude Code in Neovim
2026, 23 JanI had mixed feelings after trying Claude Code CLI for the first time. On one hand, it was a DX breakthrough—an AI that could read, navigate, and modify my codebase directly. On the other hand, actually communicating with it felt awkward.
Why Agent in Terminal Didn't Click
CLI agents shine when you can fire off a task and let them run unsupervised—push the result when done, minimal back-and-forth. But that's not how I work.
I interact with agents constantly. My workflow falls into two modes.
- Pairing Mode
Some tasks have too broad a context or are too nuanced for full autonomy. The agent might misunderstand requirements, pick a suboptimal approach, or miss edge cases. Or I might not even know what the right implementation is until I start building it. So I pair with it in real-time: I watch changes as they happen, review diffs on the fly, and course-correct early when it starts drifting. - Autonomous Mode
When a task has narrow, well-defined scope, I let the agent work independently and review the result afterward. Less hand-holding, but still requires solid communication during the review phase.
Both modes demand fluid interaction with the agent. This is where CLI tools fall apart.
The reference problem. When writing prompts or reviewing changes, I constantly need to point at specific code—"look at the function @…", "what was the reason for the change @…?". CLI @-mentions and autocomplete help a little, but the experience is clunky. It's not designed for precise, contextual references.
The context problem. The agent proposes a change and shows a diff—maybe 10 lines. But what if I need more context to evaluate it? I want to see the surrounding module, understand how this code fits into the larger picture. In a CLI, that means switching to my editor, searching for the file, finding the right spot. A hell of a friction.
The micro-edit problem. Say the agent's change is 90% right, but I want to rename a variable or tweak a condition. In a CLI, my options are: reject the change and re-prompt with corrections, or accept it and fix it myself later. There's no way to just... edit the diff directly—which would save both time and tokens.
Editor Integration
Claude Code CLI has an --ide flag that enables two-way communication with editors via JSON-RPC 2.0 protocol. It exists to integrate Claude Code into editors.
There's no official Neovim integration, but Thomas Kosiewski reverse-engineered the VSCode extension's protocol and built claudecode.nvim.
Here's how it looks in my setup:
This solves the problems I mentioned:
- References: I navigate to the file, optionally select a range, and hit a keybind. The location appears in the chat—no manual path typing.
- Context & micro-edits: When the agent proposes a change, the CLI sends it to my editor, which displays it as a proper diff. I can inspect surrounding code, tweak the diff directly, then accept or reject with a keybind.
Worth noting that the plugin supports continuing the last session or selecting any session from a list—same as the --continue and --resume flags in the CLI.
Multisession Provider
The plugin does the heavy lifting, but it's missing one feature: multisession support. By default, I can't have multiple simultaneous chats in the editor. Whether I want to run an agent on a different worktree or just spin up another conversation without closing the current one—not possible.
I noticed the plugin allows providing a custom terminal provider, so I investigated whether I could work around this limitation by building a dedicated provider myself. It required a few runtime patches to the plugin's core, but it worked. I've been using this provider without issues since. You can find the source in my dotfiles.
The provider adds two features:
- Tab-scoped sessions: Each Neovim tab gets its own independent Claude Code session. I can run multiple sessions within the same branch, or have agents working autonomously on different worktrees while I focus on something else.
- Layout switching: Sometimes I have long discussions with an agent without referencing code much. In those cases, I prefer a centered floating window over the side panel. The provider supports two layouts—
sideandfloat—and I can toggle between them with a keybind.
See the example configuration in my dotfiles.
This provider has one hard dependency—snacks.terminal. If you're not already using snacks.nvim, you'll need to add it to your plugin list.
Git Worktrees
Before diving in, I should mention I'm not sold on worktrees. I'll elaborate on my reservations later, but for now: if git worktrees work for you, they integrate nicely with the setup described above.
The idea is simple: instead of context-switching between tasks on a single branch, you create separate worktrees—each with its own working directory and branch. Claude Code's docs recommend this pattern for running parallel agent sessions without them stepping on each other's changes.
When you create a worktree, Git creates a new directory alongside your main repo. A common convention is <repo-name>--<worktree-name>:
~/projects/
├── my-app/ # main repo
├── my-app--feature-x/ # worktree for feature X
└── my-app--bugfix-y/ # worktree for bugfix YEach directory is a full working copy on its own branch, sharing the same Git history.
Neovim Integration
Neovim has a feature that makes this workflow smooth: tcd (tab-local current directory). Unlike cd which changes the working directory for the entire editor, tcd scopes it to a single tab. This means each tab can point to a different worktree without affecting the others—perfect for this use case.
With the multisession provider from the previous section, each tab also gets its own independent Claude Code session. Put them together:
- Create a worktree → open it in a new tab with
tcd→ the tab has its own working directory and its own agent session - Switch between worktrees → a picker shows existing worktrees; if one's already open in a tab, switch there; otherwise, open a new tab
- Clean up → when closing a tab, optionally remove the worktree and/or delete the branch
In my setup, I bound these to keymaps—creating worktrees from a prompt, picking from a fuzzy list, and handling cleanup with a confirmation dialog when there are uncommitted changes. You can find the implementation in my dotfiles: git-worktrees.lua and git.lua.
Pain Points
Worktrees sound great in theory—isolated environments for parallel work. But once your development setup has any complexity, the friction adds up fast.
Environment conflicts. If your app needs specific ports, local domains, or a reverse proxy (I use Traefik), you can't just spin up another instance in a worktree. The main app is already using those resources. You'd need to rearchitect your local setup to support multiple simultaneous environments—doable, but not trivial.
Cold caches. Each worktree starts fresh. No compiled artifacts, no node_modules, no build caches. For a Rust project, that means recompiling everything from scratch. For a Node project, reinstalling all dependencies. You can configure shared caches (sccache for Rust, for example), but that's additional tooling to set up and debug when things go wrong.
Missing local state. Anything in .gitignore doesn't exist in the new worktree. Config files with local overrides, generated credentials, local databases—you either recreate them manually or script their setup. Neither is seamless.
The Patch Workaround
I'm not ready for a full environment revamp, so I'm trying a patch-based workflow instead. When I need to run the app with changes from a worktree:
- I generate a patch from the worktree
- Apply it to a dedicated branch on the main repo (where the environment is already set up)
- Test the changes
- Revert the patch when done
Why patches instead of stashes?
Stashes work across worktrees, but they remove changes from the source branch. That means you'd need to restore them afterward, clean up history, etc. Patches don't touch the source worktree at all—they're just a portable snapshot you can apply and discard.
For quick, isolated tasks where you don't need to run the full app—maybe a documentation fix, a small refactor, or working on specs—worktrees are fine. That's mostly how I plan to use them. But for actual feature development where you need the app running? Either commit to the environment complexity or use patches as a bridge.
This setup has rough edges—like every other AI tooling right now—but it fully integrates the agentic workflow into the editor and minimizes friction when communicating with an agent. If you give it a try, let me know how it goes.
