/sibyl-save - Session Memory Sync + Skill Extraction (Sibyl Memory Plugin)
Part of the Sibyl Labs open skill collection. MIT licensed. Built by Sibyl Labs, LLC.
A companion skill for the Sibyl Memory Plugin. It captures everything that happened this session and injects it into the plugin's local memory database (~/.sibyl-memory/memory.db) through the plugin's own interface, then extracts reusable patterns into new skills.
It does not write raw memory files. All memory goes through the plugin so tiering, full-text indexing, and the free-tier cap are honored. Because the plugin exposes the same MCP tools on every harness it supports (Claude Code, Codex, and any MCP host; Hermes via the Python SDK), this one skill is multi-harness by construction.
Requirements
The Sibyl Memory Plugin, installed and wired:
pip install sibyl-memory-cli
sibyl init # browser/wallet activation, writes ~/.sibyl-memory/
sibyl setup claude-code # or: codex | hermes (wires the memory interface into your harness)
This skill then talks to the plugin through one of two surfaces:
- MCP (Claude Code, Codex, Cursor, any MCP host): the 8
memory_*tools below. - Python SDK (Hermes or any Python agent):
sibyl_memory_client.MemoryClient/sibyl_memory_hermes.SibylMemoryProvider.
The plugin interface
| Purpose | MCP tool | Python SDK |
|---|---|---|
| Save a fact / entity | memory_remember(category, name, body) | client.set_entity(category, name, body) |
| Recall an entity | memory_recall(category, name) | client.get_entity(category, name) |
| List entities | memory_list(category, limit) | client.list_entities(category) |
| Full-text search | memory_search(query, limit, tiers) | client.search(query) |
| Set a state doc | memory_set_state(key, body) | client.set_state(key, body) |
| Get a state doc | memory_get_state(key) | client.get_state(key) |
| Record a journal event | memory_record_event(kind, body, category, name) | client.write_event(...) |
| Archive / forget | memory_forget(category, name, reason) | client.archive_entity(category, name, reason) |
Examples below use the MCP names. On Hermes or a Python agent, use the SDK column.
Tier mapping
| Session content | Tier | Call |
|---|---|---|
| Session pointer / summary / forward items | HOT (state) | memory_set_state("session", ...) |
| Ranked priorities | HOT (state) | memory_set_state("priorities", ...) |
| Session log entry | COLD (journal) | memory_record_event("session_save", ...) |
| Projects / people / products | WARM (entities) | memory_remember(category, name, body) |
| Closed / dead items | ARCHIVE | memory_forget(category, name, reason) |
| This skill's config + delta marker | HOT (state) | memory_set_state("sibyl_save:config" / "sibyl_save:last_save", ...) |
Modes
- run (default):
/sibyl-save,save session,sync memory. Inject session context into the plugin, then offer skill extraction. - setup:
/sibyl-save setup,/sibyl-save config. Interactive. Build or edit the config (stored in the plugin at state keysibyl_save:config). Run once before first use. - preview (dry run):
/sibyl-save preview,/sibyl-save --dry-run. Run the full analysis and report every planned write. Call nothing that mutates the DB. Do not advance the delta marker.
Mode: setup (dynamic config)
Goal: write the config to the plugin at state key sibyl_save:config. Be interactive and minimal. Infer what you can; ask only what you cannot.
- Harness. Detect or ask which harness this is (claude-code, codex, cursor, hermes, other). This drives where Phase 2 writes skill files.
- Skill output. Where new skills get written for this harness. Default for Claude Code:
.claude/skills/<name>/SKILL.md. For other harnesses, confirm the skill location and format. Store asskill_output: {dir, format}. - Priorities. State key for the ranked list (default
priorities) and a cap. Default cap 15. Hard ceiling 30: never accept a value above 30. A list longer than 30 is a backlog, not a set of priorities. - Entity categories. Which WARM categories you track (default
project,person,product). User adds or removes. - Additional capture. Optionally name extra state keys or entity categories the save should populate each run (a metrics state doc, a contacts category). This is the extension point.
- Dry-run default. Toggle
dry_run_default(default false). - Write the config via
memory_set_state("sibyl_save:config", {...}). Do not touch the delta marker.
Config shape: see examples/sibyl-save-config.example.json. Re-running setup edits it in place.
Mode: run
Phase 1: Memory Sync (into the plugin DB)
Step 0 - Load config + delta
memory_get_state("sibyl_save:config"). If absent, switch to setup. memory_get_state("sibyl_save:last_save") for the delta anchor (what changed since the last save). If dry_run_default is true and no mode was given, run as preview.
Step 1 - Read current state
memory_get_state("session")andmemory_get_state(<priorities key>)memory_list(category, limit)for tracked categories, andmemory_recall/memory_searchfor entities touched this session- any additional state keys or categories named in config
Step 1.5 - Priorities check + reconcile
Read the priorities state doc and reconcile in place (write back with memory_set_state). Conditions and the action each requires:
- COMPLETED item still listed: drop it; record the closure via
memory_record_event("priority_closed", {...}). - RANK_DRIFT / DUP_RANK (ranks not contiguous 1..N, or a rank repeats): renumber to 1..N.
- OVER_CAP (more items than the cap): move the lowest-priority items to a backlog state doc until at or under cap.
- STALE_ITEM (>14 days untouched): surface it to the user.
- TERMINAL entity (the referenced entity is archived/dead): close the priority.
- BROKEN entity ref (points at no real entity): fix it to a real
category/name.
Enforce the cap on every write (never exceed 30).
Step 2 - Analyze the session
Review the conversation since the delta anchor (or since session start on first save). Extract:
- Entities touched - projects, people, products created, read, or modified
- Actions taken - concrete things that happened, with identifiers
- Decisions made - strategic choices and their rationale
- Forward items - next-session actions, verb-first ("deploy...", "follow up with...", "verify...")
- Warnings - active risks, blockers, deadlines, near-misses
- Lessons learned - operational improvements (these feed Phase 2)
- Additional captures - data for any extra state keys / categories in config
Step 3 - Inject into the plugin DB
In preview mode, call nothing that mutates. Report the planned writes (Step 4) and stop.
- Session state -
memory_set_state("session", { last_session, summary, forward, entities_touched, warnings }). Forward items are action references only, never balance snapshots or anything that goes stale. - Journal event -
memory_record_event("session_save", { evaluated, acted, forward, extra }). One event per save (append-only by design). - Priorities -
memory_set_state(<priorities key>, { updated, cap, items }), capped. Overflow to a backlog state doc. - Entities - for each changed entity,
memory_remember(category, name, body). New entities are just newmemory_remembercalls; the plugin indexes them, so there is no separate registry to maintain. - Closed / dead -
memory_forget(category, name, reason). - Additional captures - apply each configured extra state key / category.
- Delta marker -
memory_set_state("sibyl_save:last_save", { ts: <now> }). Skip in preview.
Step 4 - Report
Concise summary: entities written, state docs updated, journal event id, priorities added/closed, additional captures, and forward items for next session. In preview mode, label every line "would" and confirm nothing was written.
Phase 2: Skill Extraction (harness-native)
Skills are presented the same way regardless of harness: identify, propose, then create as a native skill file for the current harness.
Step 5 - Identify reusable patterns
Scan the session for operations meeting ANY of these: repeated (more than once this session), recurring (likely again), multi-step (3+ sequential steps), non-obvious (a workaround worth keeping), error-prone (needs a checklist). For each candidate evaluate name (short imperative verb phrase), trigger, parameters, complexity (any dangerous steps), frequency.
Step 6 - Propose candidates
Present each as a one-liner with name, description, and estimated frequency. Then ask: "Create these? Or skip any?"
Step 7 - Create approved skills (harness-native)
Read skill_output from config to know where and in what format this harness expects skills. Defaults:
| Harness | Skill location | Format |
|---|---|---|
| claude-code | .claude/skills/<name>/SKILL.md | YAML frontmatter (name, description) + Markdown body |
| codex | ~/.codex/prompts/<name>.md (confirm in setup) | Markdown prompt |
| cursor | .cursor/ command/rule (confirm in setup) | per Cursor convention |
| other | from skill_output.dir | from skill_output.format |
For each approved skill, write the file at the configured location with trigger phrases, step-by-step instructions, parameter descriptions, safety checks for any dangerous step, and an example invocation. Report the path.
Do NOT create skills that: duplicate an existing skill (check the skill location first), are too session-specific to recur, wrap a single trivial command, or require editing files your operating rules protect (surface those, do not self-edit).
Rules (non-negotiable)
- Never store live data (balances, prices, counts) as durable facts. Capture references, not snapshots.
- Session forward items are action-oriented and verb-first.
- One journal event per save (append-only; never rewrite history).
- Priorities are capped (default 15, never above 30). Overflow to a backlog state doc.
- Entities are addressed by
category+name; let the plugin be the index. No parallel registry. - All memory writes go through the plugin interface. Never write
~/.sibyl-memory/files or openmemory.dbdirectly: the client handles locking and the free-tier cap. - Treat existing skills as read-only. Create new ones rather than editing in place unless explicitly asked.
License & provenance
MIT (see LICENSE). The watermark comment at the top of each Markdown file is attribution and provenance, not a usage restriction. Verify a copy with node scripts/watermark.mjs verify. Details in WATERMARK.md.