Repository navigation
A session named in Claude Code is known to Animus by that name - #6
Conversation
A session started with `claude --name` or renamed with `/rename` now gets that name in Animus, at start and, after a `/rename` at the terminal, on the next prompt (no hook fires on /rename itself). Two sessions in one project folder no longer look alike, such as a lead and a builder. The title is applied only when it differs from the one last applied, so a rename through the plugin's own `rename` command stands until the user renames the session again. A title another session already holds gets this session's id suffix (lead-57) instead of taking the name over. A title with nothing a name can use, or no title, keeps the folder and session id prefix. Closes #5 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
⚠ medic encountered an error
Resume by pushing a new commit or @-mentioning this bot after the issue is fixed. |
|
@endgame-code-triage please review. |
There was a problem hiding this comment.
Review: Session title naming for Animus mailbox
Solid PR. The core idea — surfacing session_title from Claude Code hooks so Animus knows a session by its Claude Code name — is cleanly done, and the invariant "last explicit act wins" is the right choice. The move_pointer extraction and titled helper are well factored. The five new tests cover the critical paths: title at start, title on prompt after /rename, collision suffix, plugin-rename persistence, and empty-sanitizing titles.
A few observations, none blocking:
1. Docstring on titled is hard to parse
The triple-negative opening sentence took me a couple reads:
"The name a session title the user gave in Claude Code makes, or None when it is unchanged since last applied (so a later rename here stands) or has nothing a name can use."
Something like:
"The display name derived from the hook's
session_title, orNonewhen the title is unchanged since we last applied it (so a pluginrenamestands) or when it sanitizes to nothing."
would read more naturally.
2. Double negation in session_start (pre-existing, not introduced here)
if not name or not (not pointer_path(name).exists() or points_to(pointer_path(name), mailbox)):This is equivalent to if not name or (pointer_path(name).exists() and not points_to(pointer_path(name), mailbox)) — the latter expressing "the pointer exists but no longer points here." Not introduced in this PR, but worth simplifying when you're next in the area.
3. titled mutates state["title"] before checking pointer ownership
If pointer_path(base).exists() and not points_to(...) triggers choose_name, the returned name differs from base. The mutation still stands (which is correct — the title string is unchanged, only the display name got a suffix). Just noting that the side-effect and the return are not atomic with respect to the pointer check, which is fine because the hook path never exits with an error.
4. retitle mutates state but only saves when a name changes
When titled returns None (title unchanged or empty), retitle returns early without calling save. But titled did state["title"] = title on the previous call, and on the current call it short-circuits before the mutation (title == state.get("title") → returns None). So the state on disk is consistent. Correct behavior, just worth noting the invariant.
No suggestions to change. The logic, tests, docs, and version bump all line up. Approve.
What and why
Closes #5. The plugin named every session
<folder>-<session id prefix>, so two sessions in one project folder (a lead and a builder) looked alike to Animus, and a message meant for one reached the other.Claude Code's SessionStart and UserPromptSubmit hook inputs carry
session_titlewhen the user named the session (claude --name,/rename). No hook fires on/renameitself. Now:session_titlewhose sanitized form is non-empty becomes the session's name, so a terminal/renametakes effect on the next prompt.state["title"]records the last title applied, and a title is applied only when it differs from it. A rename through the plugin's ownrenamecommand therefore stands until the user renames the session again (last explicit act wins).lead-57) throughchoose_name; a live session's name is never taken over. The hook path never exits with an error; the CLIrenamekeeps its collision exit.<folder>-<session id prefix>as before.sanitizetakes anemptyfallback; the pointer move is factored out ofrename()intomove_pointer, shared with the hooks.docs/agent-mailbox.mdsay a named session uses its Claude Code name and a terminal/renametakes effect on the next prompt.version0.2.0 -> 0.3.0 so installed copies get the change.Checks
python3 -m unittest discover -s testspasses (25 tests, 5 new: title at start, title on prompt after /rename, collision suffix, plugin rename not undone by the unchanged title, empty-sanitizing title)claude plugin validate --strict .passesscripts/mailbox.pyclaude --plugin-dir:--name trial-leadshowed astrial-lead; after/rename trial-twoand one prompt it showed astrial-twodocs/agent-mailbox.mdupdated🤖 Generated with Claude Code