Abstract
dev-session is a tmux workflow that puts nvim in the top pane and an AI coding agent in the bottom pane, with both editing the same live buffer. The agent reaches nvim through a msgpack-rpc socket (nvim --listen /tmp/nvim-dev.pipe) using pynvim – no terminal injection, no fake keypresses, and no fighting over the keyboard. This tutorial walks through the full setup: tmux configuration, the dev-session launcher, the nvim keymaps, and the agent-side skills that drive nvim over the socket.
Prerequisites
- macOS with Homebrew (
brew). - tmux:
brew install tmux(verify withtmux -V). - nvim: any recent version (
brew install neovim). - pynvim:
pip3 install pynvim– on the machine this tutorial was written on, pynvim must be installed into~/Miniforge3/bin/python3specifically, because that is the only python with pynvim and the agent scripts pin that interpreter. - At least one agent CLI on PATH:
hermes(preferred) orclaude.
Step 1: Install the tmux configuration
Create ~/.tmux.conf:
set -g mouse on
set -g prefix C-a
bind C-a send-prefix
# Prefix-free pane navigation
bind -n C-k select-pane -U
bind -n C-j select-pane -D
Reload it:
tmux source-file ~/.tmux.confWhy these choices: mouse on lets you click any pane to focus it. The prefix is Ctrl-a instead of the default Ctrl-b because nvim captures Ctrl-b. And Ctrl-j/Ctrl-k are bound without a prefix so you can switch panes from anywhere, including from inside nvim normal mode or the agent’s prompt.
Step 2: Add the nvim split-navigation keymaps
In ~/.config/nvim/init.lua, add keymaps for nvim’s own splits, plus a fallback that opens the agent in a nvim terminal split when you are not in dev-session:
vim.keymap.set("n", "<C-h>", "<C-w>h")
vim.keymap.set("n", "<C-j>", "<C-w>j")
vim.keymap.set("n", "<C-k>", "<C-w>k")
vim.keymap.set("n", "<C-l>", "<C-w>l")
vim.keymap.set("t", "<C-h>", "<C-\\><C-n><C-w>h")
vim.keymap.set("t", "<C-j>", "<C-\\><C-n><C-w>j")
vim.keymap.set("t", "<C-k>", "<C-\\><C-n><C-w>k")
vim.keymap.set("t", "<C-l>", "<C-\\><C-n><C-w>l")
vim.keymap.set("n", "<leader>cl", function()
vim.cmd("belowright split | terminal hermes")
vim.cmd("startinsert")
end)Note: inside dev-session, Ctrl-j/Ctrl-k are claimed by tmux and switch panes; inside a plain nvim window they navigate nvim splits.
Step 3: Install the dev-session launcher
Create ~/av/bin/dev-session (or any bin directory on PATH):
#!/bin/bash
# Launch a tmux dev session: nvim (top) + agent (bottom).
# nvim listens on /tmp/nvim-dev.pipe so the agent can interact via pynvim.
#
# Usage:
# dev-session # start or attach to "dev" session
# dev-session [file] # open nvim on a specific file
# dev-session -k # kill the session
#
# The bottom pane runs `hermes` by default. To use another agent
# (e.g. claude), override: AGENT=claude dev-session
SESSION="dev"
NVIM_SOCKET="/tmp/nvim-dev.pipe"
AGENT="${AGENT:-hermes}"
if [[ "$1" == "-k" ]]; then
tmux kill-session -t "$SESSION" 2>/dev/null && echo "Session '$SESSION' killed." || echo "No session '$SESSION' running."
exit 0
fi
FILE="${1:-}"
if tmux has-session -t "$SESSION" 2>/dev/null; then
tmux attach-session -t "$SESSION"
exit 0
fi
# Create session -- top pane: nvim
tmux new-session -d -s "$SESSION" -n "main" -x "$(tput cols)" -y "$(tput lines)"
if [[ -n "$FILE" ]]; then
tmux send-keys -t "${SESSION}:0.0" "nvim --listen ${NVIM_SOCKET} $(printf '%q' "$FILE")" Enter
else
tmux send-keys -t "${SESSION}:0.0" "nvim --listen ${NVIM_SOCKET}" Enter
fi
# Bottom pane: $AGENT (30% height)
tmux split-window -t "${SESSION}:0.0" -v -p 30
tmux send-keys -t "${SESSION}:0.1" "$AGENT" Enter
# Focus nvim
tmux select-pane -t "${SESSION}:0.0"
tmux attach-session -t "$SESSION"Make it executable and link it onto PATH:
chmod +x ~/av/bin/dev-session
ln -s ~/av/bin/dev-session ~/.local/bin/dev-sessionStep 4: Install the agent-side skill
For Hermes, install the nvim-send skill. It ships a single driver script that talks to the socket; operations are check, read, open, ex, append, and goto. The skill’s script is pinned to ~/Miniforge3/bin/python3 because that is the only python with pynvim installed on this machine:
~/Miniforge3/bin/python3 -m pip install pynvimFor Claude Code, install ~/.claude/commands/nvim-send.md following the reference implementation in the repo tutorial (the socket protocol is identical; only the invocation differs).
Step 5: Start the session
dev-session # empty nvim
dev-session ~/path/to/file.md # nvim opens that file
AGENT=claude dev-session # Claude instead of hermesThe layout:
+--------------------------------------+
| nvim --listen /tmp/nvim-dev.pipe |
| (top pane, 70%) |
+--------------------------------------+
| hermes (bottom pane, 30%) |
+--------------------------------------+
Switch panes with Ctrl-j (down) and Ctrl-k (up), or click with the mouse. Zoom a pane with Ctrl-a z. Detach with Ctrl-a d; re-attach with dev-session. Kill with dev-session -k.
Verification
dev-sessionopens a tmux session nameddevwith nvim on top.tmux list-panes -t devshows two panes: pane 0 is nvim, pane 1 is the agent.- The socket exists:
ls /tmp/nvim-dev.pipe. - From the agent pane, invoke the nvim-send skill’s
checkoperation and confirm it prints “socket OK” – this proves the agent can reach nvim. - Ask the agent to
readthe buffer; confirm it prints the file’s contents. Then ask it to append a line and confirm the line appears in nvim when you switch to the top pane.
Notes
Want to stay in touch?
- Signal (announcements): https://signal.group/#CjQKIGLn7xDB0uOXMMlbKlsKEG0CmkmL9gk3U0SeIX0KlKRZEhDoqIluCXo84TrBz-2tMJD7
- Signal (discussion): https://signal.group/#CjQKIDA0v6tUciWe-3jRArkbYttju8xfuoczTOfMrGuvhmEZEhCrOnPk-IWFmFmipdI1EHxv
- Signal: archerships.43 (https://signal.me/#eu/9JUc8x9c-QA0_-QR9qQd0HUmjsnAG1BeOJM2nDo5DopjIPq5bThAJYr99lsh0cPP)
- Mailing list: https://archerships.substack.com/subscribe
- Email: [email protected]
- Website: https://archerships.com
- Substack: https://substack.com/@archerships
- Twitter: https://x.com/archerships
- Facebook: https://www.facebook.com/archerships
- Yahihonne: https://yakihonne.com/profile/nprofile1qqsgr0xn6vvr8su9ptzj4n50j8vzmczzayed0wcl5rdnvh0tc6xhqncy6jrjw
- Nostr-npub:
npub1sx7d85ccx0pc2zk99t8glywc9hsy96fj67a3lgxmxew7h35dwp8shak49e - Odysee: https://odysee.com/@archerships:6
- TikTok: https://www.tiktok.com/@archertships
Support my work
- Donations (crypto): https://trocador.app/anonpay/?ticker_to=xmr&network_to=Mainnet&address=85e4n5bgLTWiAWZbkjbbF5MLrwyiU8kjxHWHL9t6vDE5MyNUCPzBuZUNDcvbCisC5iW5PPBP9ETRQUWQQjMuvAhHRFaYCeM&donation=True&simple_mode=True&name=Archerships&[email protected]&ticker_from=xmr&network_from=Mainnet&bgcolor=000000ff
- Donations (fiat): https://ko-fi.com/archerships
- Consulting: privacy / crypto / censorship consulting – email or Signal