Session portability: make sessions exportable, replayable, and fully deletable
- Dominant language
- Rust
- Stars
- 54.2k
- Forks
- 6.2k
- Avg merge
- 3d 4h
- Merged PRs (30d)
- 240
Description
## Motivation
[This great article on session portability](https://earendil.com/posts/session-portability/) argues that an agent session is user data, and proposes five concrete tests for whether a tool treats it that way:
1. **Inspection** - can I read my session in a sane format?
2. **Export** - can I take a complete, self-contained copy elsewhere?
3. **Replay** - can I continue an exported session, including on a different provider?
4. **Audit** - can I tell which provider/model produced each message?
5. **Deletion** - when I delete a session, is it actually gone?
goose is closer to passing these than most agents (SQLite storage, `goose session export`, importers for Claude Code/Codex sessions), but each test has real gaps today:
- **Export is not self-contained.** The export is the bare session: subagent transcripts stay behind in the database, large tool outputs stay behind as pointers to local temp files that dangle on another machine, and provider settings are dropped on import.
- **Replay breaks across providers.** Replaying a transcript on a different provider can fail or misbehave because provider-bound state (thinking signatures, redacted thinking blocks, Gemini thought signatures) is sent back to a provider that never produced it.
- **Deletion is incomplete.** Deleting a session leaves its subagent child sessions (hidden `SubAgent` rows, invisible in session lists), their ledger rows, and spilled tool-output files on disk.
- **Audit is partial.** Inference metadata is not consistently recorded, so provenance of individual messages is not always answerable.
## Proposal
Three incremental changes, each independently useful:
1. **Record provenance, and scrub foreign provider-bound state at the replay boundary.** Record inference provenance (provider, requested model, resolved model) on every assistant message, which is what makes per-message audit answerable. Before a conversation is fixed up for a provider, use it to clear thinking signatures and drop redacted-thinking blocks on messages whose provenance does not match the target. Scrubbing at the boundary rather than in storage keeps the stored transcript a faithful record.
2. **Make exports a self-contained envelope.** Export bundles the session, its subagent descendants, and spilled tool outputs as content-addressed artifacts; import recreates the tree, rewrites pointers, and preserves provider settings. The envelope flattens the existing `Session` JSON so old exports import unchanged and old goose versions can still read new exports. This also implies making spill files session-owned (per-session directories under the data dir instead of flat OS temp files), which is what lets export prove ownership of a file before bundling it and lets deletion find it.
3. **Make deletion cascade.** Deleting a session removes the whole subagent subtree in one transaction, removes its spill directories, and garbage-collects imported artifact files that no remaining message references.
Contributor guide
Research direction
The issue describes changes to session handling, export, and deletion. Start by examining the session storage in SQLite, the `goose session export` command, and the importers for Claude Code/Codex sessions. Look for where subagent transcripts, tool outputs, and provider settings are managed. Understanding the data flow for inference provenance and the structure of session directories is key. 'Done' means exports are self-contained, replay works across providers, and deletion cascades completely.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- ai-infra-agents, backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100