Skip to content

Resolve

aichat resolve turns a session name, a full ID, a partial ID (prefix, middle, or suffix fragment), or a session-file name fragment (e.g. a codex rollout timestamp) into one canonical session record — for both Claude Code and Codex. It is built so an agent can resolve a session non-interactively, but it prints a readable panel for humans too.

This is distinct from the interactive Search TUI and the legacy find commands: it does not browse, it resolves a single identifier to a single answer.

Terminal window
aichat resolve <query> [--agent claude|codex] \
[--home PATH] [--json | --pretty]
OptionDescription
<query>Session name (/rename), full or partial id, or a filename fragment.
--agentclaude (default) or codex.
--homeOverrides $CLAUDE_CONFIG_DIR / $CODEX_HOME and the default homes.
--jsonForce JSON output.
--prettyForce the human-readable panel.

Output auto-detects its destination: JSON when piped or captured (agent-facing), a Rich panel on a terminal. Pass --json / --pretty to override.

The name is the title you set with /rename inside a session:

  • Claude: the custom-title recorded in the transcript — not the auto-generated ai-title.
  • Codex: the thread_name recorded in the home-level session_index.jsonl. When a thread has no explicit name, the title column of the Codex threads database is used instead — that one is auto-captured from your first message, not chosen by you.

The query is resolved through ordered tiers; the first non-empty tier wins:

TierMatchmatched_by
1exact full IDid
2exact namename
3ID prefixpartial-id
4ID substring (middle or suffix)id-substring
5session-file name substringfilename
6name substringname

So an exact ID or name is never shadowed by an incidental substring match, and an ID prefix match always beats a mid-ID substring match. The filename tier ranks above name substrings because filename fragments are structural: a timestamp fragment identifies one rollout file, while session names are free text that may incidentally quote the same fragment (dozens of sessions can mention a timestamp in their first message) and would otherwise drown the precise match.

ID tiers (3–4) require at least 4 characters from the hex/dash id charset; the filename tier (5) requires at least 4 characters. The filename tier is what makes codex rollout fragments like 2026-03-25T14-50 (the timestamp in the rollout file name) or a rollout-2026-03-25... prefix resolvable. Queries are always matched as literal substrings — never as glob patterns — and a query containing a path separator (/, \) or a glob metacharacter (*, ?, [, ]) matches nothing in any tier.

On a unique match, resolve prints one JSON object and exits 0:

{
"agent": "claude",
"session_id": "a15f9ced-88e9-43d7-9e2c-4a10d01f1644",
"name": "session-finder",
"directory": "/Users/you/Git/claude-code-tools",
"home": "/Users/you/.claude",
"session_file": ".../a15f9ced-....jsonl",
"matched_by": "name",
"modified": "2026-07-14T11:00:08-04:00",
"archived": false
}
FieldDescription
agentclaude or codex
session_idThe resolved session UUID
name/rename title, or null
directorySession working directory
homeResolved home that was searched
session_fileAbsolute path to the session file
matched_byid, partial-id, id-substring, name, or filename
modifiedSession file mtime (ISO-8601)
archivedCodex archived flag (false for Claude)

You rarely need to call resolve by hand first. These commands accept the same queries directly:

  • aichat <session> and menu
  • trim, smart-trim, trim-in-place, and resume
  • export, export-claude, export-codex, info, and copy
  • move, delete, query, clone, rollover, and lineage
  • find-original, find-derived, and port

trim-in-place and the two agent-specific exporters constrain the resolver to the agent named by the command. move-account uses the same tiers across several source homes and includes the source home in its picker.

Terminal window
# All of these name one session
aichat move session-finder ~/Git/other-repo
aichat info a15f9ced
aichat lineage 88e9-43d7

Except for the constrained variants above, these commands search both agent homes and detect the agent themselves. Where a command offers --agent, the option narrows the search. It may come before or after the session argument, and --agent=codex works as well as --agent codex.

Pass a session file path and no home is searched at all: the agent comes from the file’s own content, and --agent then requires the file to be that agent’s. A file that sits inside an agent home but does not read as a session is rejected, rather than trusted because of where it lives.

In an interactive terminal, an ambiguous action query opens a Rich table with the candidates newest first. Choose a number to continue with that session, or enter q to cancel. Ctrl-C and end-of-input also cancel before the command changes anything. Non-interactive and JSON callers still fail deterministically with the candidate list instead of guessing or prompting.

--claude-home and --codex-home before the subcommand apply to any of these commands, and carry through the interactive menus into whatever action you pick:

Terminal window
aichat --claude-home ~/.claude-work info my-session

resume also takes both flags itself; trim and smart-trim take their own --claude-home. A command-local flag wins over the root-level one.

The lookup avoids the resolver’s full scan whenever it safely can, because that scan reads every transcript in both homes — on a home with a few thousand sessions it costs on the order of ten seconds.

  • A unique full id normally answers in well under a second. It is the top match tier, so no weaker tier can outrank it and nothing else has to be read.
  • A partial id costs a second or two: before trusting a filename match, the lookup rules out a session whose exact name is that same string, since an exact name outranks a partial id.
  • A name, or anything else, goes through the full scan.

None of this changes which session you get — it only changes how much work is done to be sure of it.

port uses the same resolver and picker. It has no --agent, so use --claude-home and --codex-home to choose the searched homes.

CodeMeaning
0Resolved — one match, record printed
1Not found, or an input/home error
2Ambiguous — multiple matches

On an ambiguous query, resolve exits 2 and prints the candidates (newest first) so the caller can disambiguate:

{"error": "ambiguous", "query": "tmux-fix",
"agent": "claude", "match_count": 2,
"candidates": [ /* full records */ ]}

Expected input errors — an empty or missing query, an unsupported --agent, or a --home that is not a directory — exit 1 with a structured {"error": ..., "detail": ...} object, never a traceback.

Terminal window
# By /rename name (pretty panel in a terminal)
aichat resolve session-finder
# By partial id, as JSON for an agent
aichat resolve a15f9ced --json
# By a MID-ID fragment (id-substring tier)
aichat resolve 88e9-43d7 --json
# A Codex session by its rollout timestamp fragment
# (filename tier)
aichat resolve 2026-03-25T14-50 --agent codex --json
# A Codex session by name
aichat resolve "my codex thread" --agent codex --json
# Search a non-default home
aichat resolve <id> --home ~/.claude-rja --json
# Agent-facing: captured output is JSON automatically
aichat resolve session-finder | jq .session_file