Skip to content

A session named in Claude Code is known to Animus by that name - #6

Merged
parintorns merged 1 commit into
mainfrom
session-title-names
Oct 1, 2026
Merged

parintorns merged 1 commit into
mainfrom
session-title-names

Conversation

@parintorns

Copy link
Copy Markdown
Contributor

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_title when the user named the session (claude --name, /rename). No hook fires on /rename itself. Now:

  • At SessionStart, and on each prompt, a session_title whose sanitized form is non-empty becomes the session's name, so a terminal /rename takes 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 own rename command therefore stands until the user renames the session again (last explicit act wins).
  • A title another session's pointer already holds gets this session's id suffix (lead-57) through choose_name; a live session's name is never taken over. The hook path never exits with an error; the CLI rename keeps its collision exit.
  • No title, or one that sanitizes to nothing (e.g. Thai only), keeps <folder>-<session id prefix> as before.
  • sanitize takes an empty fallback; the pointer move is factored out of rename() into move_pointer, shared with the hooks.
  • SKILL.md and docs/agent-mailbox.md say a named session uses its Claude Code name and a terminal /rename takes effect on the next prompt.
  • version 0.2.0 -> 0.3.0 so installed copies get the change.

Checks

  • python3 -m unittest discover -s tests passes (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 . passes
  • Tests added or updated for changes in scripts/mailbox.py
  • Tried in a real session with claude --plugin-dir: --name trial-lead showed as trial-lead; after /rename trial-two and one prompt it showed as trial-two
  • docs/agent-mailbox.md updated

🤖 Generated with Claude Code

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>
@endgame-code-triage

Copy link
Copy Markdown

⚠ medic encountered an error

  • Stage: reviewer running on commit 4c04ddb22ffd520d18e802cc9dd8d3236bf6fca9
  • Cause: Loop stopped without calling any tool (turn end). Content types:
  • Action: Internal error — please report
  • Event: 7484

Resume by pushing a new commit or @-mentioning this bot after the issue is fixed.

@parintorns

Copy link
Copy Markdown
Contributor Author

@endgame-code-triage please review.

@endgame-code-triage endgame-code-triage Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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, or None when the title is unchanged since we last applied it (so a plugin rename stands) 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.

@parintorns
parintorns merged commit 69747d2 into main Oct 1, 2026
3 checks passed
@parintorns
parintorns deleted the session-title-names branch October 1, 2026 16:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Session names are ambiguous within one project

1 participant