<feed xmlns='http://www.w3.org/2005/Atom'>
<title>dotemacs/tests/test-ai-vterm--show-or-create.el, branch load-graph-classify-start</title>
<subtitle>My Emacs configuration
</subtitle>
<id>https://git.cjennings.net/dotemacs/atom?h=load-graph-classify-start</id>
<link rel='self' href='https://git.cjennings.net/dotemacs/atom?h=load-graph-classify-start'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/'/>
<updated>2026-05-11T18:27:26+00:00</updated>
<entry>
<title>feat(ai-vterm): order the project picker by most-recently-used</title>
<updated>2026-05-11T18:27:26+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-11T18:27:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=c14d6c8d0f669d694dd765d6f592ce6eb72c50f5'/>
<id>urn:sha1:c14d6c8d0f669d694dd765d6f592ce6eb72c50f5</id>
<content type='text'>
The picker's active group (projects with a live tmux session) used to sort alphabetically. It now leads with projects opened this session, most-recent first, then the rest of the active group alpha, then the no-session group alpha. An in-session list (`cj/--ai-vterm-mru'), pushed to the front by `cj/--ai-vterm-show-or-create' on every open, drives the order. An empty list reproduces the old alphabetical behavior.

I also pulled in a fix: `cj/--ai-vterm-tmux-session-name' now sanitizes `.' and `:' in the basename to `_'. tmux disallows those chars in session names and silently rewrites them, so `.emacs.d' really runs in session `aiv-_emacs_d', not `aiv-.emacs.d'. The computed name never matched, so `.emacs.d' was wrongly treated as having no session and landed in the no-session picker group. (A crash-recovery would also spawn a duplicate instead of reattaching.) Sanitizing the same way tmux does keeps the names in sync.
</content>
</entry>
<entry>
<title>refactor(ai-vterm): rename Claude-specific names to a generic "agent"</title>
<updated>2026-05-11T12:18:20+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-11T12:18:20+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=59b0854464ef29511a0d09f1e76fd1140e675833'/>
<id>urn:sha1:59b0854464ef29511a0d09f1e76fd1140e675833</id>
<content type='text'>
I may add other terminal agents to this launcher (aider, an open-source LLM TUI), so the buffer prefix, the user knob, and the internal helpers shouldn't say "Claude". The module name (ai-vterm) and the `cj/ai-vterm-*` customs were already generic. This finishes the job:

- buffer prefix `claude [&lt;basename&gt;]` -&gt; `agent [&lt;basename&gt;]` (the `defconst` and the matching display-buffer-alist regex move together)
- `cj/ai-vterm-claude-command` -&gt; `cj/ai-vterm-agent-command` (the default still runs the `claude` CLI, with a docstring note on swapping it)
- `cj/--ai-vterm-claude-buffers` / `-displayed-claude-window` / `-reuse-existing-claude` -&gt; `-agent-*`, and their test files renamed to match
- prose in the module commentary and docstrings, plus the matching test docstrings and buffer-name literals

`vterm-config.el` hardcodes the same buffer prefix in `cj/--vterm-toggle-buffer-p` (F12 excludes agent buffers from its candidate set), so that literal moved too. Collapsing it into the shared `cj/--ai-vterm-name-prefix` is a cleanup for another day.

After a reload, a project's buffer opens as `agent [foo]` instead of `claude [foo]`. Old buffers keep their names until killed. I also corrected two stale `eshell-vterm-config.el` references in ai-vterm.el docstrings (that module was split into `vterm-config.el`).

Two things keep saying "Claude": the `cj/ai-vterm-agent-command` default value (the actual CLI), and the "Claude Code" example in `vterm-config.el`'s cursor-restore docstring (a concrete TUI example, not branding).

90 tests pass. `make validate-modules` clean.
</content>
</entry>
<entry>
<title>feat(ai-vterm): F9 toggle/redisplay/pick + persistent split geometry</title>
<updated>2026-05-09T00:21:26+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-09T00:21:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=eab070e5b542f525340ee7f07ea0560944639721'/>
<id>urn:sha1:eab070e5b542f525340ee7f07ea0560944639721</id>
<content type='text'>
F9 was a single command that always opened the project picker. Three small frustrations stacked up. With one claude buffer open and not visible, F9 was a redundant prompt to pick a project that already had a session. With claude visible, there was no way to bury it without M-x quit-window. With two projects' buffers alive, swapping between them was a buffer-switch chore.

F9 is now a dispatch:

- Claude visible in this frame: quit the window (toggle off) and capture the geometry first.
- Exactly one claude buffer alive but hidden: re-display it (DWIM single-buffer case).
- Zero or two-plus alive: fall through to the project picker.

C-F9 is the always-pick-project entry point for explicit project switches. M-F9 is a buffer picker over the alive claude buffers. If a claude window is currently shown, the picked buffer replaces it in that window so the split orientation and size carry over. The shown buffer sorts last in the picker with a [shown] marker so RET picks "the other one."

Split geometry persists across toggles. Two module-level vars (cj/--ai-vterm-last-direction, cj/--ai-vterm-last-size) capture at toggle-off and feed a custom display action. After M-S-t flips claude from right to bottom, F9 toggle-off-then-on returns it at the bottom. After a mouse resize, the next toggle restores that fraction. State is per-session. Restarts reset to default right/0.5.

Two display-buffer fixes came out of testing:

- save-window-excursion around (vterm name) keeps the dashboard from being buried on a fresh F9 at startup. vterm calls pop-to-buffer-same-window internally, which would otherwise replace the selected window's buffer before the alist could route the new one.
- The action chain swaps display-buffer-use-some-window for a more specific cj/--ai-vterm-reuse-existing-claude. The generic version stole non-claude windows on C-F9 when the user was focused inside claude (claude on bottom, code on top -&gt; new project landed in the code window). The specific version only reuses windows that already show a claude buffer.

I reclaimed C-F9 from the gptel toggle in ai-config.el. C-; a t still binds gptel.

I added eight new test files (claude-buffers, displayed-claude-window, dispatch, pick-buffer-candidates, window-geometry, capture-state, display-saved, reuse-existing-claude) plus a regression test on cj/--ai-vterm-show-or-create for the dashboard-preservation fix. All 73 ai-vterm tests pass and the full make test suite is green.
</content>
</entry>
<entry>
<title>fix(ai-vterm): direction-based display + per-project tmux session names</title>
<updated>2026-05-08T03:09:15+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-08T03:09:15+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=1d93e1a6569e4193c2b078a3d5df0bf47eeba9df'/>
<id>urn:sha1:1d93e1a6569e4193c2b078a3d5df0bf47eeba9df</id>
<content type='text'>
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 -&gt; display-buffer-use-some-window -&gt; 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 &lt;basename&gt; -c &lt;dir&gt; '&lt;claude&gt;; 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.
</content>
</entry>
<entry>
<title>feat(ai-vterm): add Claude launcher with vertical-split vterm</title>
<updated>2026-05-08T00:25:18+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-08T00:25:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=47b218ed15acd00c18cbc3bef604c4f2e0050a08'/>
<id>urn:sha1:47b218ed15acd00c18cbc3bef604c4f2e0050a08</id>
<content type='text'>
The new module picks a Claude-template project from a filtered completing-read list. It scans the same roots the `ai` shell launcher uses, then opens or reuses a vterm buffer named `claude [&lt;repo&gt;]` on the right. F9 launches it. The prior `cj/toggle-gptel` binding moves from F9 to C-F9 so both AI tools share the same physical key.

The display rule chains reuse-window -&gt; use-some-window -&gt; in-direction (right). The resulting window isn't dedicated. That matters because side-window dedication was breaking `buffer-move` (C-M-arrows) and `switch-to-buffer` replacement on the claude buffer. I also narrowed `vterm-toggle`'s display rule to skip `claude [` buffers. Otherwise it claimed them first with its bottom-split + dedicated treatment.

I added 23 tests across 5 files: the buffer-name transform, candidate walker, show-or-create dispatch, picker, and display rule. Design lives at docs/design/ai-vterm.org.
</content>
</entry>
</feed>
