anthropics / anthropics/claude-agent-sdk-typescript

Resuming through SessionStore.load degrades the loaded harness (user-level plugins, skills, commands, output styles stripped)

Aperta
#437 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub
bug
Lingua principale
Shell
Stelle
1.8k
Fork
226
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Descrizione

## Summary

When a session is resumed **through a custom `sessionStore` whose `load()` serves the transcript**, the subprocess runs against a temporary config directory and loses a large part of the harness it had on the original run: user-level plugins, skills, commands, agents, and output-style files no longer load. The same resume **without** a store (reading the SDK's own `~/.claude/projects/**.jsonl`) keeps the full harness.

Measured on 0.3.226 (2026-08) and re-measured identically on **0.3.257** (2026-09-01), macOS, Node 24.

## Reproduction (measured numbers)

All via `initializationResult()` — no billed turns needed to observe the harness surface.

| Condition | commands | agents | output styles |
|---|---|---|---|
| A. fresh run, `settingSources: ['user','project']` | 85 | 15 | 8 |
| B. store attached (append-only, `load` → `null`), no resume | 85 | 15 | 8 |
| C. `resume` only, no store | 85 | 15 | 8 |
| D. `resume` + store whose `load()` serves the entries | **51** | **6** | **5** |
| E. condition D plus explicitly declared `plugins` | 74 | 15 | 7 |

The cause is visible in the temporary config directory the SDK materializes for a store-served resume (`claude-resume-*`): it carries `settings.json`, `.claude.json`, credentials, `projects/`, `sessions/` — but no `CLAUDE.md`, no `rules/`, no `skills/`, no `commands/`, no `agents/`. It is `load()` that triggers the relocation, not the store's presence: an append-only store whose `load` returns `null` keeps the full harness while still mirroring every entry.

## Why it matters

`SessionStore.load` is the documented way for a host to own transcript durability (archive in Postgres/S3, restore on demand). As shipped, any host that uses it accepts that a resumed conversation silently runs with a weaker harness than the conversation it continues — fewer commands, missing subagents, different output style. The failure is invisible to the user: no error, just an agent that behaves differently after resume.

Hosts that need fidelity are pushed to the workaround we currently use: mirror-only via the store, and on restore write the JSONL back into `~/.claude/projects//` ourselves so a store-free `resume` finds it. That works (measured: identical harness, same session id) but requires reproducing the CLI-internal bucket-encoding rule (every non-alphanumeric → `-`, NFC-normalized realpath, 200-char truncation + `h*31+c` base-36 hash), which is not part of the public API surface and can change under any release.

## Ask

Either (a) have a `load()`-served resume run against the real config root so the harness matches a file-based resume, or (b) expose a supported way to hand the SDK a transcript for resume at full fidelity — even just a documented/exported helper for the transcript path so hosts can place the file without reproducing CLI internals.

Happy to provide the probe scripts (they use only `initializationResult()` and local session helpers).

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.