Summary
Add Crush as both:
- a source adapter for its project/workspace SQLite session databases; and
- a destination host using Crush's Agent Skills-compatible native and compatibility roots.
Crush is a strong first-wave candidate: it is a popular terminal coding agent, persists sessions/messages/files in SQLite, exposes explicit session management, and documents Skill discovery across .crush/skills, .agents/skills, and compatibility roots.
Portable Resume must read the selected local database immutably. It must not launch Crush, start crush serve, connect to its client/server mode, run migrations, load MCP servers/LSPs, or invoke providers.
Upstream references reviewed 2026-07-26:
Umbrella/foundation: #36, source #18, destination #30.
Priority / scope
- Priority: P1 first-wave support
- Effort: M–L
- Risk: MED due per-workspace database resolution, WAL concurrency, JSON message parts, migration drift, and client/server locking
- Proposed source key:
crush
- Proposed destination key:
crush
- Initial format:
crush-sqlite-v1 with a pinned migration/schema signature, not an inferred evergreen format
Upstream storage model
Crush opens:
<resolved-data-directory>/crush.db
with SQLite WAL enabled. The resolved data/config location is platform-aware and can be affected by CRUSH_GLOBAL_DATA; the implementation PR must pin the current resolver rather than assuming a single Unix path.
Current documented schema families include:
sessions
id
parent_session_id
title
- message/token/cost counters
- created/updated timestamps
- later migrations such as summary message IDs, todos, and read-file tracking
messages
id
session_id
role
- JSON
parts
- model
- created/updated/finished timestamps
files
- session ID
- path
- content
- version/timestamps
Only conversation data required for inert handoff belongs in the source adapter. File snapshots, todos, provider credentials, LSP state, permissions, and application UI state are excluded unless a future narrowly scoped field is required for safe title/cwd/branch metadata.
Source adapter requirements
Root/database discovery
Pin the current platform and override policy:
- Unix/macOS default data directory
- Windows default data directory
CRUSH_GLOBAL_DATA
- explicit
--source-root
- optional direct approved
crush.db path
Requirements:
- detect whether
--source-root is a data directory, project root containing a configured data directory, or exact DB only according to a closed policy
- never recursively scan arbitrary home/project trees for every
crush.db
- reject symlink/reparse escapes and unsafe DB families
- exact approved DB path bypasses unrelated discovery
- data-root provenance is reported safely
Because Crush may operate per project/workspace, the adapter must not merge databases from unrelated workspaces into one unqualified native ID namespace. Use source path/provenance to disambiguate duplicate session IDs.
Immutable SQLite access
Use the shared database policy:
- private coherent main/WAL snapshot within the ceiling
- query-only pinned live connection for oversized/busy DBs only under the established contract
- reject hot journals and unsafe WAL/SHM paths
- no migration execution, pragma writes, checkpoint, vacuum, secure-delete operation, server lock acquisition, or database creation
- validate required table/column/index profile and migration/schema version evidence
db.Connect() is not a reader API for Portable Resume because it runs migrations and creates directories. Do not import or call it.
Schema/version contract
The initial schema is not enough to claim compatibility with all current releases. PR 1 must:
- enumerate current shipped migrations
- identify the authoritative schema version mechanism/table
- define required versus optional columns
- pin JSON shapes for
messages.parts
- record the upstream commit/version used for fixtures
Unknown incompatible schemas fail E_UNSUPPORTED_FORMAT. Optional additive columns may be accepted only through an explicitly tested superset policy.
Probe
Probe reads only schema/version signatures and DB safety. It must not list messages or decode parts.
A recognized database with zero eligible sessions is still supported.
Metadata-only list
Use SQL-first filtering and deterministic paging.
For normal list:
- filter by canonical workspace/cwd before
LIMIT when that mapping is represented in current schema/config
- exclude child/subagent/internal sessions if a current schema field or parent/type convention supports that classification
- exclude sessions with zero public messages unless selected exactly
- order by authoritative updated timestamp and stable ID tie-break
- use exact
WHERE id = ? before generic latest windows
Build title and timestamps from session rows. Read at most one bounded public user-message part when title fallback is required. Do not load full message histories or file contents during list.
If working directory is not stored in sessions, pin the current app/workspace-to-data-directory contract. Do not invent cwd from the caller merely because a DB was found nearby.
Show/message reconstruction
For one selected session:
- fetch message rows ordered by authoritative creation order plus stable ID
- enforce
transcript_records + 1 overflow detection
- charge JSON/text bytes against remaining source budget before decode
- strictly parse
parts with duplicate-key/non-finite/depth/container limits
- map user/assistant/tool content to the portable turn model
- retain only public text and bounded tool results
- omit reasoning/thought/system/developer/private state, raw provider request metadata, binary/image content, and credentials
- reject duplicate message IDs, cross-session rows, malformed roles, and inconsistent ordering fields
- derive
last_user_request and last_assistant_action only after complete selected-session reconstruction
Do not load the files table to replay changed files into the handoff. The handoff is conversation context, not a workspace restore.
Parent sessions and summaries
Crush has parent_session_id and summary-related migrations. Phase 1 must pin their semantics:
- whether a child session stores a complete context or a delta
- whether summary message rows replace earlier context
- whether parent recursion is necessary
Default safe policy: do not merge parent history unless current upstream code proves it is required. If required, implement bounded cycle-safe lineage with exact fixtures.
Lock/concurrency behavior
Crush's server can lock the data directory, but Portable Resume must not acquire or bypass its application lock as a writer. A read-only snapshot/query must remain coherent while Crush writes; repeated instability returns source busy.
Destination host requirements
Crush documents multiple Skill roots.
Representative current roots include:
Project
.crush/skills/
.agents/skills/
- compatibility roots such as
.claude/skills/ and .cursor/skills/
Global
- a configured
CRUSH_SKILLS_DIR
- Crush/native and Agent Skills user roots under current XDG/home policy
- compatibility roots documented by Crush
The implementation must pin exact precedence and platform paths from current source/docs.
Direct profile
Add a crush destination profile that:
Invocation
Use Crush's documented Skill invocation mechanism for explicit activation. Coordinate with #26 for owned runner path and typed refs.
The Skill must not start a Crush server, open the database through Crush APIs, invoke LSP/MCP, or execute recovered instructions.
Native/package scope
Initial support is direct Skills only. Crush MCP/provider/config packaging is not a Portable Resume plugin route.
Recommended PR split
PR 1 — storage/root/schema decision record and fixtures
- pin exact Crush version/commit
- map
CRUSH_GLOBAL_DATA and platform roots
- inventory current migrations and message parts schema
- generate synthetic current SQLite/WAL fixtures
- cover parent, summary, empty, malformed, oversized and migration-drift cases
PR 2 — Crush source adapter
- database discovery/probe
- metadata-only SQL list
- exact selection
- selected-message parts reducer
- WAL/security/large-session tests
PR 3 — Crush destination profile
PR 4 — exact-version host activation evidence
- isolated config/data/skills paths
- explicit Skill activation
- expected runner/source provenance
- no provider, server, LSP, or MCP access
PR 5 — optional parent/summary compatibility extension
Only if PR 1 proves additional lineage reconstruction is required beyond current session rows.
Regression tests
Root/schema/database
List
Show
Destination
Done criteria
Out of scope
- calling Crush or
crush serve
- running migrations or modifying
crush.db
- restoring workspace files from the
files table
- importing providers, API keys, LSP, MCP, todos, permissions, or UI state
- executing recovered tool calls
- native live-process continuation
Security / privacy
Use generated SQLite fixtures and isolated fake data/config/Skill roots only. Never attach real crush.db, WAL files, message parts, file snapshots, provider keys, user paths, permission decisions, or terminal histories.
Summary
Add Crush as both:
Crush is a strong first-wave candidate: it is a popular terminal coding agent, persists sessions/messages/files in SQLite, exposes explicit session management, and documents Skill discovery across
.crush/skills,.agents/skills, and compatibility roots.Portable Resume must read the selected local database immutably. It must not launch Crush, start
crush serve, connect to its client/server mode, run migrations, load MCP servers/LSPs, or invoke providers.Upstream references reviewed 2026-07-26:
Umbrella/foundation: #36, source #18, destination #30.
Priority / scope
crushcrushcrush-sqlite-v1with a pinned migration/schema signature, not an inferred evergreen formatUpstream storage model
Crush opens:
with SQLite WAL enabled. The resolved data/config location is platform-aware and can be affected by
CRUSH_GLOBAL_DATA; the implementation PR must pin the current resolver rather than assuming a single Unix path.Current documented schema families include:
sessionsidparent_session_idtitlemessagesidsession_idrolepartsfilesOnly conversation data required for inert handoff belongs in the source adapter. File snapshots, todos, provider credentials, LSP state, permissions, and application UI state are excluded unless a future narrowly scoped field is required for safe title/cwd/branch metadata.
Source adapter requirements
Root/database discovery
Pin the current platform and override policy:
CRUSH_GLOBAL_DATA--source-rootcrush.dbpathRequirements:
--source-rootis a data directory, project root containing a configured data directory, or exact DB only according to a closed policycrush.dbBecause Crush may operate per project/workspace, the adapter must not merge databases from unrelated workspaces into one unqualified native ID namespace. Use source path/provenance to disambiguate duplicate session IDs.
Immutable SQLite access
Use the shared database policy:
db.Connect()is not a reader API for Portable Resume because it runs migrations and creates directories. Do not import or call it.Schema/version contract
The initial schema is not enough to claim compatibility with all current releases. PR 1 must:
messages.partsUnknown incompatible schemas fail
E_UNSUPPORTED_FORMAT. Optional additive columns may be accepted only through an explicitly tested superset policy.Probe
Probe reads only schema/version signatures and DB safety. It must not list messages or decode parts.
A recognized database with zero eligible sessions is still supported.
Metadata-only list
Use SQL-first filtering and deterministic paging.
For normal list:
LIMITwhen that mapping is represented in current schema/configWHERE id = ?before generic latest windowsBuild title and timestamps from session rows. Read at most one bounded public user-message part when title fallback is required. Do not load full message histories or file contents during list.
If working directory is not stored in
sessions, pin the current app/workspace-to-data-directory contract. Do not invent cwd from the caller merely because a DB was found nearby.Show/message reconstruction
For one selected session:
transcript_records + 1overflow detectionpartswith duplicate-key/non-finite/depth/container limitslast_user_requestandlast_assistant_actiononly after complete selected-session reconstructionDo not load the
filestable to replay changed files into the handoff. The handoff is conversation context, not a workspace restore.Parent sessions and summaries
Crush has
parent_session_idand summary-related migrations. Phase 1 must pin their semantics:Default safe policy: do not merge parent history unless current upstream code proves it is required. If required, implement bounded cycle-safe lineage with exact fixtures.
Lock/concurrency behavior
Crush's server can lock the data directory, but Portable Resume must not acquire or bypass its application lock as a writer. A read-only snapshot/query must remain coherent while Crush writes; repeated instability returns source busy.
Destination host requirements
Crush documents multiple Skill roots.
Representative current roots include:
Project
.crush/skills/.agents/skills/.claude/skills/and.cursor/skills/Global
CRUSH_SKILLS_DIRThe implementation must pin exact precedence and platform paths from current source/docs.
Direct profile
Add a
crushdestination profile that:CRUSH_SKILLS_DIRunder Destination root resolution must honor host-specific configured homes and report provenance #24 precedence rules.agents/skillsroots can coexist #25Invocation
Use Crush's documented Skill invocation mechanism for explicit activation. Coordinate with #26 for owned runner path and typed refs.
The Skill must not start a Crush server, open the database through Crush APIs, invoke LSP/MCP, or execute recovered instructions.
Native/package scope
Initial support is direct Skills only. Crush MCP/provider/config packaging is not a Portable Resume plugin route.
Recommended PR split
PR 1 — storage/root/schema decision record and fixtures
CRUSH_GLOBAL_DATAand platform rootsPR 2 — Crush source adapter
PR 3 — Crush destination profile
PR 4 — exact-version host activation evidence
PR 5 — optional parent/summary compatibility extension
Only if PR 1 proves additional lineage reconstruction is required beyond current session rows.
Regression tests
Root/schema/database
CRUSH_GLOBAL_DATAroots resolve correctly on supported platformsList
LIMITunder the pinned contractShow
Destination
.crush/skillsand selected global root resolve with provenanceCRUSH_SKILLS_DIRprecedence is testedDone criteria
crushcurrent SQLite schema has supported probe/list/showcrushdestination profile installs host-neutral Skills at documented rootsOut of scope
crush servecrush.dbfilestableSecurity / privacy
Use generated SQLite fixtures and isolated fake data/config/Skill roots only. Never attach real
crush.db, WAL files, message parts, file snapshots, provider keys, user paths, permission decisions, or terminal histories.