anthropics / anthropics/claude-code

~/.claude/sessions/<pid>.json's sessionId not updated on /clear (inconsistent with #88845)

Open
#95,439 0 comments 0 reactions 0 assignees View on GitHub
area:core bug
Dominant language
Python
Stars
145k
Forks
23.1k
PR merge metrics
PR metrics pending

Description

## Summary

`~/.claude/sessions/.json`'s `sessionId` field is not updated when the user runs `/clear`, even though `/clear` internally generates a new session UUID and starts a new JSONL file. External consumers that reverse-map "sessionId → pid" via the runtime registry route to the pre-`/clear` (now-frozen) transcript instead of the current live one.

Related to #88845 (which acknowledges the `sessionId` field IS updated on some paths — specifically after `/rename + /clear + return-to-original`) — showing the behavior is inconsistent, not universally absent.

## Reproduction

Run on macOS/Linux with any recent Claude Code (verified across v2.1.117, v2.1.123, v2.1.204):

```bash
# 1. Start Claude Code
claude
```

In another terminal:

```bash
# 2. Observe the pid and current sessionId
CLAUDE_PID=$(pgrep -n claude)
cat ~/.claude/sessions/${CLAUDE_PID}.json | jq -r .sessionId
# → prints, e.g., "aaaaaaaa-1111-1111-1111-111111111111"

# 3. Observe the current active JSONL
ls -t ~/.claude/projects/*/*.jsonl | head -1
# → e.g., .../aaaaaaaa-1111-1111-1111-111111111111.jsonl
```

Back in Claude Code:

```
you> (type anything, e.g. "hello")
```

```
you> /clear
you> (type anything, e.g. "hello again")
```

Back in the other terminal:

```bash
# 4. Same pid, but the ACTIVE JSONL is now a different sid
ls -t ~/.claude/projects/*/*.jsonl | head -1
# → .../bbbbbbbb-2222-2222-2222-222222222222.jsonl (NEW sid)

# 5. But the runtime registry still says the OLD sid
cat ~/.claude/sessions/${CLAUDE_PID}.json | jq -r .sessionId
# → "aaaaaaaa-1111-1111-1111-111111111111" ← STALE
```

The `updatedAt` field of the registry file bumps, but `sessionId` does not.

## Expected

After `/clear`, `~/.claude/sessions/.json`'s `sessionId` field should equal the UUID of the JSONL Claude is currently writing to.

## Actual

`sessionId` is frozen at the value present when the process started (or was last set by a path like `/rename + return-to-pre-clear` per #88845). It does not track the current active JSONL when `/clear` creates a new session UUID.

## Impact

Any external tool that reverse-maps sessionId → pid via this registry routes to a stale, no-longer-being-written JSONL. This affects session viewers, automation hooks, and terminal integrations that need to correlate current sid with a pid.

Multiple third-party Claude Code clients have independently built workarounds because `~/.claude/sessions/.json` cannot be trusted for "current sid" — e.g. [mnemo-desktop #73](https://github.com/xyrlan/mnemo-desktop/issues/73) chose to reverse-map pid → sid via `claude agents --json --all` rather than the runtime file, and [mnemo #288](https://github.com/xyrlan/mnemo/issues/288) introduced a daemon-side `roster.json` for the same purpose. That different consumers converge on rolling their own mapping infrastructure suggests the runtime file's `sessionId` semantics are widely regarded as unreliable.

Workarounds specifically for the `/clear` staleness require:

- Scanning `~/.claude/projects//*.jsonl` for new sibling files with `type: "file-history-snapshot"` on line 0 as the `/clear` marker
- Cross-checking that the pid's cwd matches and that only one claude is in the cwd

None of this should be necessary if the registry file were kept authoritative.

## Related issues

- **#88845** — describes that `sessionId` IS updated in the `/rename + /clear + return` path. The inconsistency (updated in some paths, not in `/clear`) suggests the write mechanism exists; extending it to fire on `/clear` should be small.
- **#44607** — "No way to access session ID from within a running session." External consumers rely on `sessions/.json` as the workaround; that workaround is broken by this bug.
- **#95029, #71437, #37451, #27329, #36113** — assorted `/clear` semantics complaints (session name reset / new-session-created), some of which may share the same underlying "which state should follow the new sid" ambiguity.

## Suggested fix

At the point where `/clear` calls `setConversationId(randomUUID())` (or equivalent), also rewrite `~/.claude/sessions/.json`'s `sessionId` field. Atomically, matching whatever path already handles the update in #88845's scenario.

If there's a reason not to (e.g., `sessions/.json` is intended to reflect the process's *original* session and not the current one), please document it — currently the field's meaning is ambiguous, and third-party consumers reasonably assume "current."

## Version

Reproduced on Claude Code v2.1.117, v2.1.123, v2.1.204 (macOS 14.5).

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce the stale sessionId after /clear using the ~/.claude/sessions/.json and JSONL paths shown in the issue. Find the /clear handler where setConversationId(randomUUID()) is called, then compare its registry update behavior with the path discussed in #88845. Done means the registry sessionId matches the currently written JSONL after /clear, with the existing update behavior preserved.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.