You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There is no way for a running Claude Code session to know its own session ID. This makes it impossible for automation (hooks, commit trailers, logging) to reference the current session without asking the user to manually copy-paste the ID.
The session ID is only revealed after the session ends, in the "Resume this session with: claude --resume <uuid>" line. By then it's too late for anything inside the session to use it.
Use case
Our CLAUDE.md instructs Claude to include a Session-Id: git trailer in commits. Currently, Claude has to ask the user for the session ID on every first commit — a poor experience. We want a wrapper or alias that makes the session ID available automatically.
What we tried
1. --session-id <uuid> flag (pre-set the ID)
Result: does not control the local session ID in interactive mode.
In -p (print/non-interactive) mode, --session-id correctly controls the persistence ID — the .jsonl file is named with the injected UUID, and session_id in JSON output matches.
In interactive mode, --session-id sets a separate API/telemetry ID, but the CLI generates its own internal UUID for local persistence. The --resume line shows a different ID than the one injected.
$ CLAUDE_SESSION_ID=$(uuidgen) claude --session-id "$CLAUDE_SESSION_ID"
# Inside session, $CLAUDE_SESSION_ID = 669f77f5-...
# But "Resume this session with" shows: 9ecddef3-...
# Persistence file: 9ecddef3-....jsonl (not 669f77f5)
This means --session-id is usable as a synthetic tag for commit trailers, but it is not the actual session ID. This is confusing — the flag name implies it sets the session identity.
This works but adds complexity and doesn't handle the common case of starting a fresh interactive session without a prompt.
3. Capture resume line via expect (PTY automation)
Result: the resume line is never written to the PTY.
We tried spawning claude in expect's PTY, sending /exit, and capturing the "Resume this session with" output. Multiple approaches were tested:
expect alone: /exit is received (autocomplete menu shows "Exit the REPL"), session exits cleanly (exit code 0, .jsonl file created), but no resume line appears in the PTY output.
script -c wrapping expect: same result — Script done. appears but no resume line.
screen with stuff command injection: same result.
strace -f -e write: confirmed zero write() syscalls containing "Resume" — the code never even attempts to print the line.
Root cause (from binary analysis)
The resume-line printing function (HF8 in the minified source) has this guard:
if(process.stdout.isTTY&&CT()&&!lk())
The process.stdout.isTTY check, or one of the other conditions (CT(), !lk()), evaluates to false under expect/script/screen PTYs. This is surprising because these are real PTYs — isatty(1) returns true on the slave fd. The conditions may involve terminal feature detection (DA1/XTVERSION query responses), TERM_PROGRAM, or other environment checks.
4. Filesystem approach (newest .jsonl file)
Result: works reliably.
After claude exits, the newest .jsonl file in ~/.claude/projects/<project-dir>/ is the session that was just created. Its filename (minus .jsonl) is the real session ID, and it is resumable:
BEFORE=$(ls -t ~/.claude/projects/$PROJECT/*.jsonl | head -1)# ... start and exit claude via expect ...
AFTER=$(ls -t ~/.claude/projects/$PROJECT/*.jsonl | head -1)
SID=$(basename "$AFTER" .jsonl)
claude --resume "$SID"# works
This is our current workaround but it's fragile (race conditions with concurrent sessions, requires deriving the project directory path encoding).
Make --session-id actually control the local session ID in interactive mode (not just -p mode). Currently the flag's behavior is inconsistent between modes.
Print the resume line in PTY environments: The current guard that suppresses it under expect/script/screen PTYs prevents legitimate automation. If isatty(1) is true, the resume line should be printed.
A command or API to query the session ID: e.g., claude session-id that prints the current session's ID, or a /session-id slash command.
Problem
There is no way for a running Claude Code session to know its own session ID. This makes it impossible for automation (hooks, commit trailers, logging) to reference the current session without asking the user to manually copy-paste the ID.
The session ID is only revealed after the session ends, in the "Resume this session with: claude --resume
<uuid>" line. By then it's too late for anything inside the session to use it.Use case
Our
CLAUDE.mdinstructs Claude to include aSession-Id:git trailer in commits. Currently, Claude has to ask the user for the session ID on every first commit — a poor experience. We want a wrapper or alias that makes the session ID available automatically.What we tried
1.
--session-id <uuid>flag (pre-set the ID)Result: does not control the local session ID in interactive mode.
-p(print/non-interactive) mode,--session-idcorrectly controls the persistence ID — the.jsonlfile is named with the injected UUID, andsession_idin JSON output matches.--session-idsets a separate API/telemetry ID, but the CLI generates its own internal UUID for local persistence. The--resumeline shows a different ID than the one injected.This means
--session-idis usable as a synthetic tag for commit trailers, but it is not the actual session ID. This is confusing — the flag name implies it sets the session identity.2.
-pmode bootstrap +--resume(two-phase approach)Result: works for the prompt case, but requires a throwaway first message for the no-prompt case.
Since
-pmode respects--session-idfor persistence, we can:claude -p "$prompt" --session-id "$UUID" --output-format json→ captures answer, persists sessionclaude --resume "$UUID"→ continues interactivelyThis works but adds complexity and doesn't handle the common case of starting a fresh interactive session without a prompt.
3. Capture resume line via
expect(PTY automation)Result: the resume line is never written to the PTY.
We tried spawning claude in expect's PTY, sending
/exit, and capturing the "Resume this session with" output. Multiple approaches were tested:expectalone:/exitis received (autocomplete menu shows "Exit the REPL"), session exits cleanly (exit code 0,.jsonlfile created), but no resume line appears in the PTY output.script -cwrappingexpect: same result —Script done.appears but no resume line.screenwithstuffcommand injection: same result.strace -f -e write: confirmed zerowrite()syscalls containing "Resume" — the code never even attempts to print the line.Root cause (from binary analysis)
The resume-line printing function (
HF8in the minified source) has this guard:The
process.stdout.isTTYcheck, or one of the other conditions (CT(),!lk()), evaluates to false under expect/script/screen PTYs. This is surprising because these are real PTYs —isatty(1)returns true on the slave fd. The conditions may involve terminal feature detection (DA1/XTVERSION query responses),TERM_PROGRAM, or other environment checks.4. Filesystem approach (newest
.jsonlfile)Result: works reliably.
After claude exits, the newest
.jsonlfile in~/.claude/projects/<project-dir>/is the session that was just created. Its filename (minus.jsonl) is the real session ID, and it is resumable:This is our current workaround but it's fragile (race conditions with concurrent sessions, requires deriving the project directory path encoding).
Feature request
Any of the following would solve this cleanly:
Environment variable: Set
CLAUDE_SESSION_ID(or similar) in the session's environment so tools, hooks, and the AI itself can read it. This was requested in [Feature Request] Expose Session Metadata via Environment Variables and API #17188.Make
--session-idactually control the local session ID in interactive mode (not just-pmode). Currently the flag's behavior is inconsistent between modes.Print the resume line in PTY environments: The current guard that suppresses it under expect/script/screen PTYs prevents legitimate automation. If
isatty(1)is true, the resume line should be printed.A command or API to query the session ID: e.g.,
claude session-idthat prints the current session's ID, or a/session-idslash command.Environment