| name | memory-sync |
| description | Import durable memory from local agent session history into Titan. Use when the user says memory sync, claude sync, codex sync, wants Claude Code/Codex memories imported, wants to backfill Titan from agent sessions, or wants cross-agent continuity through Titan. |
Memory Sync
Memory Sync is a safe local-agent memory import workflow. It reads local session history from coding agents such as Claude Code and Codex, extracts durable memories, and stores distilled summaries in Titan using trace packets.
This skill is not a daemon, not a new database, and not a direct file-level sync engine. Titan is the shared memory layer. Source agents remain untouched.
Historical note: this workflow was originally called Claude Sync. Treat claude-sync as a legacy alias. Prefer the name Memory Sync going forward.
Hard Rules
- Never modify files under
~/.claude.
- Never modify files under
~/.codex.
- Never read auth files, token files, key files,
.env files, or credential blobs.
- Never store raw transcripts in Titan.
- Never store API keys, OAuth tokens, cookies, passwords, private keys, or full environment dumps.
- Always inventory first before importing.
- Always ask for user approval before the first import write in a session.
- Always use a dry-run summary for large imports before writing memories.
- Always prefer distilled trace packets over verbatim session logs.
- Always record imported and skipped session fingerprints in a manifest so repeated runs skip duplicates.
- Always verify retrieval after import by querying Titan for representative imported topics.
- Always tag every stored memory with its source agent (
[source:codex], [source:claude-code], etc.) so future queries can filter by origin.
Core Mental Model
Treat Memory Sync as an ETL pipeline:
Inventory -> Normalize -> Filter -> Cluster -> Distill -> Redact -> Store -> Manifest -> Verify
Do not mechanically import every file. The job is to preserve useful durable knowledge while avoiding transcript sludge, secrets, duplicates, and low-signal startup noise.
Source Locations
Inspect these paths if they exist. Missing paths are normal and should not be treated as errors.
Claude Code paths:
~/.claude/history.jsonl
~/.claude/sessions/
~/.claude/projects/
~/.claude/skills/
Codex paths:
~/.codex/history.jsonl
~/.codex/session_index.jsonl
~/.codex/sessions/
~/.codex/memories/
~/.codex/AGENTS.md
Primary Memory Sync manifest path:
~/.titan/imports/memory-sync/manifest.jsonl
Legacy Claude Sync manifest path to inspect for duplicate prevention:
~/.titan/imports/claude-sync/manifest.jsonl
Never read these paths except to note that they exist if needed:
~/.codex/auth.json
~/.claude.json
~/.claude/**/*.key
~/.claude/**/*.pem
~/.codex/**/*.key
~/.codex/**/*.pem
**/.env
**/.env.*
Slash Command Behavior
When invoked through /memory-sync, treat the user's arguments as import preferences.
Legacy /claude-sync prompts may still appear in old installs. If invoked, run this Memory Sync workflow and recommend /memory-sync going forward.
Examples:
/memory-sync
/memory-sync last 20
/memory-sync codex last 50
/memory-sync claude project-only
/memory-sync all dry-run
/memory-sync since 2026-05-01
If no arguments are provided, run inventory and recommend a safe default.
Default recommendation:
Import the last 20 sessions per available agent, scoped to the current project when session cwd/project metadata is available.
Do not import all sessions unless the user explicitly approves it after seeing the inventory.
Workflow
1. Inventory
First collect a read-only inventory.
Use shell commands like these, adapted to the user's machine:
printf 'Claude Code candidates:\n'
find "$HOME/.claude" -maxdepth 6 -type f \
\( -name '*.jsonl' -o -name '*.json' -o -name 'history.jsonl' \) \
! -name 'auth.json' ! -name '*.key' ! -name '*.pem' 2>/dev/null | sort | head -200
printf '\nCodex candidates:\n'
find "$HOME/.codex" -maxdepth 8 -type f \
\( -name '*.jsonl' -o -name '*.md' \) \
! -name 'auth.json' ! -name '*.key' ! -name '*.pem' 2>/dev/null | sort | head -300
Also inspect both manifests if present:
test -f "$HOME/.titan/imports/memory-sync/manifest.jsonl" && tail -50 "$HOME/.titan/imports/memory-sync/manifest.jsonl"
test -f "$HOME/.titan/imports/claude-sync/manifest.jsonl" && tail -50 "$HOME/.titan/imports/claude-sync/manifest.jsonl"
Summarize:
- discovered Claude Code files
- discovered Codex files
- date range if inferable from filenames or metadata
- likely projects/cwds
- already-imported count from primary manifest
- already-imported count from legacy manifest
- source quality for each agent
- recommended import scope
2. Normalize Session Formats
Agent history formats drift over time. Never assume a single JSONL schema.
Codex may use newer records like:
{"type":"session_meta","payload":{"id":"...","cwd":"..."}}
{"type":"response_item","payload":{"type":"message","role":"user","content":[...]}}
Codex may also use older records like:
{"type":"message","role":"user","content":[{"type":"input_text","text":"..."}]}
{"type":"function_call","name":"shell","arguments":"..."}
Claude Code storage can vary by version. Common useful locations are:
~/.claude/history.jsonl for prompt history and session ids
~/.claude/sessions/*.json for session metadata
~/.claude/projects/**/*.jsonl when present for project transcripts
Before import, inspect a small sample from each discovered source family and adapt parsing. If a schema is unknown, classify it as unknown_schema and report it rather than guessing.
3. Ask Approval
Ask the user what scope to import unless they already gave a clear, bounded scope.
Good choices:
1. Last 20 sessions per agent, current project only when detectable. Recommended.
2. Last 50 sessions per agent.
3. Codex only.
4. Claude Code only.
5. Dry-run all sessions and ask again before importing.
If the user asks for all sessions and there are many, warn that the import may be slow and propose batching.
4. Read Selected Sessions
Read only selected files. For each session, extract metadata first:
- source agent:
claude-code or codex
- session id
- timestamp/date
- cwd/project path
- thread/title if available
- model/provider if available
- file path
- content fingerprint
- schema family
- signal quality
Do not bulk-load all raw transcript text into the final response. Read enough to extract durable memory safely.
5. Filter Low-Signal Sessions
Not every session deserves memory.
Classify as skipped_low_signal when the session contains only:
/exit
- login/model commands only
- startup/environment context only
- empty assistant messages
- shell setup with no durable decision
- duplicated context blocks without user intent
Do not store standalone Titan memories for low-signal sessions. Still write a manifest record saying they were reviewed and skipped.
6. Cluster Before Store
Cluster related sessions by task/project before storing.
Prefer clusters like:
titan-mem-ingestion-debugging
openclaw-persona-loading
pipx-packaging-cleanup
backend-redesign
beginner-python-learning
low-signal-reviewed
Use one trace packet per meaningful cluster instead of one memory per session when sessions are tightly related. This reduces noise and improves retrieval.
7. Extract Durable Memory
For each selected session or cluster, extract only durable information.
Save these categories:
- project decisions
- architecture choices
- implementation outcomes
- debugging root causes
- recurring bugs or pitfalls
- user preferences
- standing workflow instructions
- important unresolved todos
- repo-specific context that future agents need
- source-quality observations about the agent history itself
Skip these categories:
- one-off shell output with no future value
- raw stack traces unless the root cause matters
- private credentials or secrets
- auth/config contents
- huge pasted files
- transient chit-chat
- repeated environment blocks
- messages that are already clearly in Titan
Good memory shape:
Root cause was store-path drift: MCP inherited stale TITAN_BASE_DIR and read the wrong store.
Bad memory shape:
The user ran a command and saw a long stack trace.
Good memory shape:
OpenClaw does not auto-inject arbitrary karu.md; put persona in SOUL.md and identity in IDENTITY.md.
Bad memory shape:
The user asked about OpenClaw.
8. Redact Before Storing
Before calling Titan, redact suspicious content.
Patterns to remove or summarize:
sk-...
ghp_...
gho_...
ghu_...
ghs_...
ghr_...
xoxb-...
BEGIN RSA PRIVATE KEY
BEGIN OPENSSH PRIVATE KEY
Authorization: Bearer ...
api_key=...
API_KEY=...
password=...
secret=...
token=...
~/.ssh/*
If a session appears credential-heavy, skip it and report that it was skipped for safety.
9. Source Tag Every Memory
Every memory stored from an import MUST carry source provenance. Titan currently stores all memories from a Pi session under a single session ID with no distinction between "memory about the import process" and "memory extracted from the source agent's sessions." Without explicit tagging, imported memories drown in process noise and become unqueryable.
Tagging rule: Prefix every individual finding in the thoughts field with the source agent so Titan's extraction pipeline embeds the tag into each extracted memory text.
Correct format for thoughts:
[source:codex] Kuwo is a beginner learning Python and benefits from direct, simple commands.
[source:codex] Root cause of Titan-Mem issue was store-path drift: MCP inherited stale TITAN_BASE_DIR.
[source:codex] OpenClaw does not auto-inject arbitrary karu.md; put persona in SOUL.md and identity in IDENTITY.md.
For Claude Code:
[source:claude-code] Kuwo prefers direct instructions; when told "commit and push", just do it without overthinking.
[source:claude-code] The local Claude Code data on this machine is sparse — mostly metadata, few full project transcripts.
Why this matters: The earlier Codex import on 2026-05-30 stored 83 learnings in Titan but they were unqueryable because they shared the same session ID as the ~99 process-level memories about npm publish and git commits. The source tag makes imported memories distinguishable from import-process noise.
10. Store In Titan
In Pi, use the native tool:
titan_store_trace_packet
Use one trace packet per meaningful session or per cluster of tightly related sessions. Do not create dozens of tiny memories from the same session unless the user explicitly wants a deep import.
Trace packet format (with source tagging):
{
"goal": "Import Codex session cluster into Titan (source:codex): <cluster name>",
"thoughts": "[source:codex] Decision: ... [source:codex] Root cause: ... [source:codex] User preference: ... [source:codex] Architecture: ... Redactions: none.",
"outcome": "Stored <N> source-tagged memories from Codex sessions <ids> into Titan. Query with '[source:codex]' to retrieve only Codex memories."
}
For Claude Code:
{
"goal": "Import Claude Code history into Titan (source:claude-code)",
"thoughts": "[source:claude-code] Durable finding 1... [source:claude-code] Durable finding 2... Source quality: sparse metadata on this machine.",
"outcome": "Backfilled Titan with source-tagged Claude Code context while leaving Claude files unchanged."
}
If Titan tools are unavailable, stop and tell the user to install/start the Titan Pi package. Do not fake a memory import.
10a. Future: Scene-Based Import (Ideal Architecture)
The current approach bundles an entire cluster of sessions into one trace packet. While this works with source tagging, the ideal architecture mirrors Titan's own pipeline:
- Each imported source session becomes a synthetic Titan session with ID like
import-codex-<original-session-id>.
- The source session's conversational turns are broken into Titan scenes (as Titan does for Pi conversations).
- Titan's normal extraction pipeline extracts memories from those scenes.
- The session and all its scenes/memories carry
source_agent: "codex" metadata natively.
- On query,
titan_query_memories can filter by source_agent without relying on text-prefix matching.
This is the long-term architecture. Today, the [source:agent] text prefix achieves the same outcome within Titan's current tool surface. When Titan gains native source-agent metadata support, this skill should adopt it.
11. Write Manifest
After a successful Titan write, append one manifest record per processed source session.
Primary path:
~/.titan/imports/memory-sync/manifest.jsonl
Record shape:
{
"imported_at": "2026-05-30T00:00:00Z",
"source_agent": "codex",
"session_id": "019c75ed-47d4-70a1-870b-eda732caadde",
"session_file": "~/.codex/sessions/2026/02/19/rollout-...jsonl",
"fingerprint": "sha256:...",
"project": "/Users/mohammadsaad/Desktop/Code/Titan-Mem...",
"thread_name": "Explain titan-go duplicate events",
"timestamp": "2026-02-19T12:43:30.644Z",
"schema_family": "codex-new-jsonl",
"signal_quality": "high",
"titan_method": "titan_store_trace_packet",
"status": "imported_cluster",
"cluster": "titan-mem-ingestion-debugging",
"notes": "Stored as part of a distilled Memory Sync cluster trace packet."
}
Supported status values:
imported_cluster
imported_single
skipped_low_signal
skipped_duplicate
skipped_secret_heavy
skipped_unknown_schema
failed_titan_store
Only write imported_* manifest records after the Titan store call succeeds. For skipped records, write after the reason is known.
12. Verify Retrieval (With Source Filtering)
After import, query Titan for representative topics from the imported clusters. Always include the source tag in queries to isolate imported memories from process noise.
Query examples:
[source:codex] Titan-Mem store-path drift
[source:codex] OpenClaw SOUL.md IDENTITY.md
[source:codex] pipx-only packaging Titan-Mem
[source:claude-code] Kuwo preferences
Also try broader semantic queries to confirm the memories are discoverable:
what did we learn from Codex about Titan-Mem architecture
what did Kuwo prefer in Codex sessions about project structure
Report whether imported memories appear in retrieval. If storage succeeded but retrieval fails, say so and recommend re-indexing/restarting Titan if applicable.
Success criteria: Imported memories should surface in semantic search when queried with source-related terms, not just when searched by exact source-tag prefix.
13. Final Report
Report concisely:
- imported sessions count
- skipped sessions count
- source agents covered
- projects covered
- clusters created
- source quality notes
- redactions/skips
- manifest path
- verification queries and whether they retrieved results
- next recommended import if any
Import Granularity
Use this default batching:
- Small session: one trace packet.
- Long session: one trace packet with structured summary.
- Many related sessions for the same task: one cluster trace packet.
- Large all-history import: batch by 10 sessions and ask before continuing after each batch if import looks noisy.
Duplicate Detection
A session is already imported if either:
- its session id exists in the primary Memory Sync manifest for the same source agent
- its file fingerprint exists in the primary Memory Sync manifest
- its session id exists in the legacy Claude Sync manifest for the same source agent
- its file fingerprint exists in the legacy Claude Sync manifest
If no manifest exists, use Titan query as a weak secondary check by searching for the session id or exact project/task name. Still create the primary Memory Sync manifest after import.
Source Quality Report
Always report source quality. Example:
Codex: rich transcripts, multiple project clusters, high import value.
Claude Code: sparse metadata only on this machine, no rich ~/.claude/projects transcripts found.
This prevents pretending that every agent source has equal memory value.
Current-Project Scoping
When the user asks for project-only, include sessions where:
- session cwd equals current cwd
- session cwd is an ancestor/descendant of current cwd
- session project field matches current repo path
- history record project field matches current repo path
If cwd/project metadata is missing, classify the session as unknown-project and ask before importing it in project-only mode.
Process Learnings To Preserve
The Memory Sync workflow itself can produce important reusable knowledge. If an import reveals better parsing, filtering, clustering, or verification rules, store those learnings in Titan and update this skill when the user asks.
Patterns worth preserving:
- Schema drift is normal across agent versions.
- Source quality is asymmetric; one agent may have rich transcripts while another has only metadata.
- Low-signal filtering is necessary to keep Titan useful.
- Clustered memories are more useful than one trace packet per file.
- A manifest should track imported and skipped sessions, not just successes.
- Import success means stored and retrievable, not merely that
titan_store_trace_packet returned successfully.
- Raw transcript import is almost always the wrong default.
- Source tagging is mandatory. Without
[source:codex] or [source:claude-code] prefixes on every stored finding, imported memories share the same Titan session ID as the import process conversation and become unqueryable. This was discovered during the 2026-05-30 first import run: 83 Codex learnings were stored but couldn't be surfaced because 99 process-level memories drowned them out.
- Future architecture: When Titan natively supports
source_agent metadata on sessions, scenes, and memories, switch from text-prefix tagging to native metadata fields for cleaner filtering.
Mental Model
This workflow does not make agents share hidden model memory. It makes Titan remember the useful parts of prior agent sessions by reading local session archives once and converting them into durable trace packets.
The safe path is:
Agent session files, read-only
-> schema-aware parsing
-> low-signal filtering
-> task clustering
-> redacted trace packets
-> Titan memory
-> manifest for dedupe
-> retrieval verification