claude-code - 💡(How to fix) Fix [BUG] -p mode sessions write valid .jsonl but never get registered in sessions-index.json (invisible to --resume picker / title resume)

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

When Claude Code is launched in -p (--print) mode with --output-format stream-json --input-format stream-json, the resulting conversation:

  • Does write a complete, valid ~/.claude/projects/<encoded-cwd>/<session-id>.jsonl
  • Does remain resumable via direct UUID: claude --resume <session-id> works flawlessly
  • Does NOT appear in sessions-index.json for that project — in fact, no entries[] row is ever appended for -p-created sessions
  • Cannot be resumed via --resume <title> (the title-based resolver depends on the index)
  • Cannot be discovered through the interactive --resume picker (which reads the index)

This is a discoverability gap: the conversation transcript exists on disk, has full content, and is fully resumable when you happen to know its UUID — but there is no UI / CLI surface that lists it.

Error Message

$ claude -p --resume "pong" < /dev/null Error: --resume requires a valid session ID or session title when used with --print. Provided value "pong" is not a UUID and does not match any session title.

Root Cause

…because there is no index entry to search against.

Fix Action

Fix / Workaround

Workaround (current)

Neither workaround is sustainable; the index format is internal and can change between releases.

Code Example

# fresh project dir, no prior CC state
mkdir -p /tmp/cc-pipe-repro && cd /tmp/cc-pipe-repro

# spawn a real -p stream-json session and send one message
claude -p --output-format stream-json --input-format stream-json --verbose --setting-sources "" <<'EOF'
{"type":"user","message":{"role":"user","content":[{"type":"text","text":"reply with a single word: pong"}]}}
EOF
# captures session_id from system/init, e.g. b5563b87-e7b2-45e7-a7a7-572333aa9cc6

---

$ ls -la ~/.claude/projects/-tmp-cc-pipe-repro/
-rw-------. 1 ec2-user ec2-user 6622 May 21 04:58 b5563b87-e7b2-45e7-a7a7-572333aa9cc6.jsonl
drwxrwxr-x. 2 ec2-user ec2-user    6 May 21 04:58 memory/
# ↑ jsonl is there, sessions-index.json is NOT there at all

$ cat ~/.claude/projects/-tmp-cc-pipe-repro/sessions-index.json
cat: No such file or directory

---

$ cat ~/.claude/projects/-home-ec2-user-workspace-daydream/sessions-index.json | jq '.entries[0]'
{
  "sessionId": "45799210-8e9f-4f68-b333-daf9ca6e9b62",
  "fullPath": "/home/ec2-user/.claude/projects/-home-ec2-user-workspace-daydream/45799210-8e9f-4f68-b333-daf9ca6e9b62.jsonl",
  "fileMtime": 1769990497445,
  "firstPrompt": "redis6-cli",
  "summary": "Redis CLI Tool Name Error",
  "messageCount": 2,
  "created": "2026-02-01T14:19:36.177Z",
  "modified": "2026-02-01T14:20:35.027Z",
  "gitBranch": "dev",
  "projectPath": "/home/ec2-user/workspace/daydream",
  "isSidechain": false
}

---

$ cd /tmp/cc-pipe-repro && claude -p --resume b5563b87-... --output-format stream-json --input-format stream-json --verbose --setting-sources "" <<'EOF'
{"type":"user","message":{"role":"user","content":[{"type":"text","text":"what was the previous word you said?"}]}}
EOF
# → assistant correctly replies referencing "pong" — full context is preserved

---

$ claude -p --resume "pong" < /dev/null
Error: --resume requires a valid session ID or session title when used with --print.
       Provided value "pong" is not a UUID and does not match any session title.
RAW_BUFFERClick to expand / collapse

Summary

When Claude Code is launched in -p (--print) mode with --output-format stream-json --input-format stream-json, the resulting conversation:

  • Does write a complete, valid ~/.claude/projects/<encoded-cwd>/<session-id>.jsonl
  • Does remain resumable via direct UUID: claude --resume <session-id> works flawlessly
  • Does NOT appear in sessions-index.json for that project — in fact, no entries[] row is ever appended for -p-created sessions
  • Cannot be resumed via --resume <title> (the title-based resolver depends on the index)
  • Cannot be discovered through the interactive --resume picker (which reads the index)

This is a discoverability gap: the conversation transcript exists on disk, has full content, and is fully resumable when you happen to know its UUID — but there is no UI / CLI surface that lists it.

Environment

  • Claude Code: 2.1.145 (also reproduced anecdotally on 2.1.132 / 2.1.143)
  • OS: Linux (Amazon Linux 2023, kernel 6.1)
  • Auth: Bedrock
  • Invocation: piped stdin/stdout (no TTY) — typical for SDK / gateway / IM-bridge integrations

Reproduction

# fresh project dir, no prior CC state
mkdir -p /tmp/cc-pipe-repro && cd /tmp/cc-pipe-repro

# spawn a real -p stream-json session and send one message
claude -p --output-format stream-json --input-format stream-json --verbose --setting-sources "" <<'EOF'
{"type":"user","message":{"role":"user","content":[{"type":"text","text":"reply with a single word: pong"}]}}
EOF
# captures session_id from system/init, e.g. b5563b87-e7b2-45e7-a7a7-572333aa9cc6

After the call returns:

$ ls -la ~/.claude/projects/-tmp-cc-pipe-repro/
-rw-------. 1 ec2-user ec2-user 6622 May 21 04:58 b5563b87-e7b2-45e7-a7a7-572333aa9cc6.jsonl
drwxrwxr-x. 2 ec2-user ec2-user    6 May 21 04:58 memory/
# ↑ jsonl is there, sessions-index.json is NOT there at all

$ cat ~/.claude/projects/-tmp-cc-pipe-repro/sessions-index.json
cat: No such file or directory

Compare to a project that has been used in interactive mode at least once:

$ cat ~/.claude/projects/-home-ec2-user-workspace-daydream/sessions-index.json | jq '.entries[0]'
{
  "sessionId": "45799210-8e9f-4f68-b333-daf9ca6e9b62",
  "fullPath": "/home/ec2-user/.claude/projects/-home-ec2-user-workspace-daydream/45799210-8e9f-4f68-b333-daf9ca6e9b62.jsonl",
  "fileMtime": 1769990497445,
  "firstPrompt": "redis6-cli",
  "summary": "Redis CLI Tool Name Error",
  "messageCount": 2,
  "created": "2026-02-01T14:19:36.177Z",
  "modified": "2026-02-01T14:20:35.027Z",
  "gitBranch": "dev",
  "projectPath": "/home/ec2-user/workspace/daydream",
  "isSidechain": false
}

Now confirm the session is, in fact, fully resumable when you know its UUID:

$ cd /tmp/cc-pipe-repro && claude -p --resume b5563b87-... --output-format stream-json --input-format stream-json --verbose --setting-sources "" <<'EOF'
{"type":"user","message":{"role":"user","content":[{"type":"text","text":"what was the previous word you said?"}]}}
EOF
# → assistant correctly replies referencing "pong" — full context is preserved

But title-based resume fails:

$ claude -p --resume "pong" < /dev/null
Error: --resume requires a valid session ID or session title when used with --print.
       Provided value "pong" is not a UUID and does not match any session title.

…because there is no index entry to search against.

Why this matters (real-world impact)

I maintain naozhi (github.com/KevinZhao/naozhi), a Go-based gateway that bridges Claude Code into IM channels (Feishu first, more planned). The architecture is the documented pattern from #37045 (TELAUDE) and similar projects: spawn long-lived claude -p --output-format stream-json --input-format stream-json child processes, route IM messages over stdin/stdout. We pick -p because:

  • Interactive mode (no -p) renders a TUI prompt, which breaks stream-json framing.
  • The Agent SDK is ToS-restricted for OAuth/subscription auth.
  • -p is the only documented programmatic surface that preserves native session management, MCP, plugins, hooks, etc.

The breakage:

  • A user starts a conversation in Feishu → naozhi spawns claude -p --resume <uuid> → conversation lives normally on disk under ~/.claude/projects/....
  • The user sits down at their terminal, runs claude interactively, hits /resumenone of their Feishu conversations show up. They exist, they're complete, they're resumable — but undiscoverable without copy-pasting UUIDs from a separate dashboard.
  • Same goes for claude -p --resume "<title>" for any scripted flow. Title-based search can't find what isn't indexed.

I suspect the same affects every third-party claude -p consumer (TELAUDE, OpenClaw-style bridges, custom SDKs that wrap the CLI) — they all silently produce sessions invisible to the official discovery UI.

What I think is happening (not authoritative — guessing from observed file IO)

sessions-index.json appears to be appended-to only by the path that creates "named" / interactive sessions. The -p spawn path is treated as ephemeral and skips index registration even though --no-session-persistence exists (and is opt-out, not opt-in — implying persistence is the default for -p).

Possibly relevant: --no-session-persistence's help text reads:

Disable session persistence - sessions will not be saved to disk and cannot be resumed (only works with --print)

So the public contract is that -p sessions are persisted (and the file proves they are). The contract-breaker is that "persisted" doesn't currently include "indexed."

Suggested fixes (any one would help)

  1. (Preferred) Always write a sessions-index.json entry for -p sessions when persistence is on (i.e. --no-session-persistence is NOT set). This matches the documented contract and is the smallest change.
  2. (Opt-in) Add a flag like --register-session (or --persist-session-index) so consumers can opt in explicitly without changing default behavior.
  3. (Adopt-on-demand) A claude project reindex subcommand that scans ~/.claude/projects/<cwd>/*.jsonl and rebuilds sessions-index.json from the on-disk transcripts. Useful for recovery on top of either of the above.

Option 1 has the highest leverage: it fixes the gap silently for every existing third-party tool with zero migration. Option 2 is the most conservative if there are reasons -p sessions are intentionally not indexed (please clarify if so).

Workaround (current)

Third-party tools have to:

  • Track session UUIDs themselves (we keep our own session DB keyed by {channel}:{chatType}:{id}) — fine for our internal use, but useless for end users dropping into the CLI.
  • Optionally reverse-engineer sessions-index.json schema and write entries directly. (See #58670 for a Desktop-app-side equivalent of this DIY approach — same root cause family.)

Neither workaround is sustainable; the index format is internal and can change between releases.

Related issues (similar symptoms / same family — but distinct root cause)

  • #38340 (closed/stale) — /resume picker doesn't filesystem-scan; same symptom but discusses interactive-mode index drift, not -p registration gap
  • #58670 (open) — Desktop "Code" tab missing pre-existing CLI sessions; also an index-population gap, different surface
  • #37045 (closed/stale) — TELAUDE author asking if claude -p bridging is officially supported; same use case, didn't surface this specific gap
  • #33979 (open/stale) — meta request for a built-in claude sessions manager; would subsume this if implemented

This issue is specifically the -psessions-index.json write gap, with current-version repro and a concrete fix path. Please don't auto-dedupe against the broader cluster — the fix surface is narrower and more tractable than any of those.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix [BUG] -p mode sessions write valid .jsonl but never get registered in sessions-index.json (invisible to --resume picker / title resume)