From 1d93e1a6569e4193c2b078a3d5df0bf47eeba9df Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Thu, 7 May 2026 22:09:15 -0500 Subject: fix(ai-vterm): direction-based display + per-project tmux session names Two post-ship issues blocked practical use of the new launcher. The display rule used `display-buffer-in-side-window` with `(dedicated . t)`. Side-window dedication caused `set-window-buffer` to error during `buffer-move` (C-M-arrows), which left a half-finished swap with both sides showing the claude buffer. Then `switch-to-buffer` on a non-claude buffer in that dedicated window split instead of replacing. I rewrote the rule as `display-buffer-reuse-window -> display-buffer-use-some-window -> display-buffer-in-direction (right)`. The resulting window is ordinary, not dedicated, so swap and replace work normally. I also narrowed `vterm-toggle`'s broad lambda (which matches any vterm-mode buffer) to exclude `claude [` buffers. Otherwise vterm-toggle's `:defer` made it install last and capture our buffers first with its own bottom-split + dedicated treatment. The tmux side: vterm's auto-launch hook ran a bare `tmux\n`, so each session got an auto-named one. After an Emacs crash the tmux session would survive but I couldn't find it. A second F9 just spawned another. The launcher now sends `tmux new-session -A -s -c '; exec bash'`. The `-A` reattaches to a same-named session if it already exists. The `exec bash` keeps the tmux window alive if claude itself exits. A `cj/--ai-vterm-suppress-tmux` flag tells the existing vterm hook to skip its bare tmux step so the named launch runs instead. 11 new tests across 2 files cover the session-name and launch-command helpers. I updated tests for show-or-create and the display rule. All 34 ai-vterm tests are green. --- docs/design/ai-vterm.org | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'docs/design') diff --git a/docs/design/ai-vterm.org b/docs/design/ai-vterm.org index 62bafbc8..99526b63 100644 --- a/docs/design/ai-vterm.org +++ b/docs/design/ai-vterm.org @@ -106,9 +106,22 @@ After this, all navigation is handled by existing global bindings: Shift-arrows | Side-window already showing a different =claude [...]= | =display-buffer= swaps which buffer occupies the slot; hidden one keeps running | | =vterm= not installed | Module fails to load loudly (no graceful degradation) | +** Per-project tmux sessions + +The launch command sent to a fresh AI-vterm shell is + +#+begin_example +tmux new-session -A -s -c '; exec bash' +#+end_example + +- =-A= reattaches to an existing session of the same name instead of creating a new one. So a second F9 on the same project after an Emacs crash brings the running Claude back without spawning a duplicate. +- =-s = names the session after the project's directory basename. =tmux ls= shows the active sessions by project name. +- =-c = sets the start directory for new sessions (ignored on attach). +- =exec bash= tails the shell command so the tmux window survives Claude exiting -- the session stays alive with a bare prompt for recovery, and reattach is unaffected. + ** Tmux Auto-Launch Suppression -Existing =cj/vterm-launch-tmux= on =vterm-mode-hook= types =tmux\n= unconditionally. AI vterms set a buffer-local =cj/--ai-vterm-suppress-tmux= flag before =(vterm)=; the hook checks the flag and skips tmux when set. +The existing =cj/vterm-launch-tmux= on =vterm-mode-hook= types =tmux\n= unconditionally for any vterm buffer. AI-vterm =let='s a dynamic =cj/--ai-vterm-suppress-tmux= flag around =(vterm)= so the hook skips its bare =tmux\n= and the project-named launch command (above) runs instead. ** Testing -- cgit v1.2.3