#Agent session imports

Shared reference for the agent-session import subcommands:

Each source-native message becomes one memory, named msg_<message_id> under a per-session tree node. Re-running the same command only inserts newly-seen messages — the (tree, name) slot makes re-imports idempotent.

#Shared options

All three subcommands accept the same flags (with one extra flag on the Claude importer).

Option Description
--source <dir> Override the default source directory for this tool. For OpenCode, this may be the data directory, a direct opencode.db path, or a legacy storage directory.
--project <cwd> Only import sessions whose cwd equals or is below this path.
--since <iso> Only import sessions started at or after this ISO 8601 timestamp.
--until <iso> Only import sessions started at or before this ISO 8601 timestamp.
--tree-root <path> Tree root under which <slug>/<sessions-node-name> nodes are placed. Default: the private ~/projects (your own home). Accepts ltree labels ([A-Za-z0-9_-]) separated by /, with an optional leading ~ for your home.
--sessions-node-name <name> Per-project node name for imported agent sessions. Default: agent_sessions. Must match [a-z0-9_]+.
--full-transcript Also store reasoning, tool calls, and tool results as their own message memories (default: user + assistant text only).
--include-temp-cwd Include sessions whose cwd is a system temp directory (/tmp, /private/var/folders/...). Off by default.
--include-trivial Include sessions with fewer than 2 user messages (one-shot queries, warm-up pings, aborted sessions). Off by default.
--dry-run Parse and report what would be imported without writing anything.
-v, --verbose Per-session progress lines.

me claude import additionally accepts:

Option Description
--include-sidechains Include subagent sessions (agent-*.jsonl). Off by default.

#Tree layout

Each session is its own tree node, and each message is a named leaf under it:

<tree-root>/<project_slug>/<sessions-node-name>/<session_id>/msg_<message_id>

For example, a Claude message from a session run in /Users/me/dev/memory-engine ends up at ~/projects/memory_engine/agent_sessions/<session_id>/msg_<message_id> by default — under your private home tree, visible only to you. Each session is browsable as a folder, and an individual message is addressable by its path (me get '~/projects/memory_engine/agent_sessions/<session_id>/msg_<message_id>'). The session id is normalized to an ltree label for the node; the raw id is also kept in meta.source_session_id.

The whole run imports into a single target: the space resolved from --space / ME_SPACE (else your active space), on the server from --server / ME_SERVER (else your default server). Each session still gets its own project node — its recorded cwd yields a project slug and the session nests under <tree-root>/<slug>/<sessions-node-name>/…, the private ~/projects unless you pass --tree-root. Scope a run to one repository with --project <path>.

Sessions are skipped and tallied (not fatal) when a filter excludes them — a system temp cwd (see --include-temp-cwd), a trivial session under two user messages (--include-trivial), a Claude subagent sidechain (--include-sidechains), or a --since / --until bound — and parse errors are counted separately. --verbose lists each skip; --dry-run reports the plan without writing.

Project slugs come from the git origin repository name when available, then the git repo root directory name, then basename(cwd). Slug collisions (two different cwds that normalize to the same label) are resolved automatically by appending a 4-char hash suffix -- the first cwd seen gets the plain slug, subsequent ones get slug_<hash>. The full cwd is always preserved in meta.source_cwd.

#Idempotency

Idempotency is keyed on (tree, name) — the per-session node plus the msg_<message_id> leaf. (The id is a timestamp-prefixed UUIDv7 with a random tail, so messages still sort chronologically by id; the same message gets a fresh id each run, but the (tree, name) slot keeps it on the existing row.) Re-imports reconcile server-side: every planned message is submitted with onConflict: 'replace', which inserts new slots and rewrites an existing one only when content/meta/temporal differ. Since meta.importer_version is part of meta, an importer-version bump makes meta differ and re-renders previously-imported messages in the same batched pass, while an unchanged re-import is a no-op. There is no per-session lookup and no session-size limit — a session with tens of thousands of imported messages reconciles exactly like a small one.

Source files are append-only for all three tools, so re-importing an in-progress session simply inserts its newly-appended messages on the next run. The live-capture hook additionally narrows each submission to the messages after the newest already-imported one (a single limit 1 search) — purely a bandwidth optimization; correctness never depends on it.

--dry-run reports every parsed message as a would-be insert: without submitting, there is no server classification into inserted/updated/skipped.

#Content shape

Each memory's content is the raw text of the message. Role, session id, project, git state, and block kinds live in meta.

  • Default mode keeps only the text blocks of each message. Messages with no text blocks (for example, a Claude user event that only carries a tool_result) are skipped.
  • --full-transcript keeps every block kind. Messages are rendered as their blocks joined with blank lines, and standalone reasoning / tool-call / tool-result items (for example, Codex response items of those types) are stored as their own memories.

#Metadata

Each imported memory carries:

Key Description
type Always "agent_session".
source_tool "claude" / "codex" / "opencode".
source_session_id Tool-native session identifier.
source_session_title Session title when the source supplies one.
source_message_id Source-native message id (or a stable synthesized id for Codex items with no native id).
source_message_role user / assistant / reasoning / tool_call / tool_result / system.
source_message_block_kinds Ordered list of block kinds composing this message.
source_cwd Absolute working directory.
source_project_slug ltree-safe project label (same as the tree subnode).
source_git_root Git repo root (if detected and distinct from cwd).
source_git_branch Branch at session start.
source_git_commit Commit hash at session start.
source_git_repo Git remote URL.
source_tool_version CLI version string.
source_model Model id (e.g. claude-opus-4-5, gemini-3-pro-preview).
source_provider Model provider (anthropic, openai, google, ...).
source_agent_mode OpenCode agent mode (e.g. plan).
source_tool_name Tool name for tool_call / tool_result messages.
source_file Absolute path of the session file on disk.
content_mode "default" or "full_transcript".
importer_version Version tag of the importer schema.
$prev Path of the previous message in the session (absent on the first message).
$thread The session id, shared by every message — the thread grouping key.

$prev and $thread are the reserved thread-link keys: they let the web UI walk a session with Previous / Next buttons and pull up the whole session via Entire thread. $next is not stored — it is derived from $prev. Because $prev is a memory path (not an id) it stays stable across re-imports.

Temporal is a point-in-time at the message's timestamp.