No way to access session ID from within a running session

Resolved 💬 4 comments Opened Apr 7, 2026 by overseers-desk Closed Apr 11, 2026

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.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.

2. -p mode bootstrap + --resume (two-phase approach)

Result: works for the prompt case, but requires a throwaway first message for the no-prompt case.

Since -p mode respects --session-id for persistence, we can:

  1. claude -p "$prompt" --session-id "$UUID" --output-format json → captures answer, persists session
  2. claude --resume "$UUID" → continues interactively

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).

Feature request

Any of the following would solve this cleanly:

  1. 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 #17188.
  1. 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.
  1. 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.
  1. 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.

Environment

  • Claude Code v2.1.92
  • Linux x86_64
  • Binary: ELF (compiled/SEA)

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗