Toon Memory

toon-memory는 AI 코드 어시스턴트(Cursor, Claude Code, Windsurf 등)를 위해 설계된 100% 로컬 지속 메모리 MCP 서버입니다. 초효율 TOON 형식을 사용하여 토큰 소비를 최대 30%까지 줄이며, 에이전트가 프로젝트 컨텍스트와 결정 사항을 세션 간에 비공개 및 암호화(AES-256)된 상태로 저장, 검색 및 통합할 수 있도록 합니다.

문서

English | Español | 中文 | 日本語 | 한국어 | Português (BR) | Deutsch | Français

toon-memory

MCP memory server for AI coding agents — remember decisions, patterns, and bugs between sessions.

npm version License: MIT CI Docs


Table of Contents


What is toon-memory?

Ever had that feeling where your AI agent forgets everything from yesterday's session? You explain the same architecture decision for the third time, and it still suggests the approach you already rejected?

toon-memory fixes this. It gives your AI agent a persistent memory that survives restarts, so it actually learns from your project over time.

📖 Read the documentation

Real-world use cases

ScenarioWhat toon-memory does
Design debates"We chose Redis over Memcached because of pub/sub support"
Framework choices"This project uses Zod for validation, not Joi"
Bug fixes"Redis pool exhaustion — fix was max_connections=20"
Architecture notes"Broker service uses RESP protocol, not HTTP"
Onboarding"The deploy script lives in scripts/deploy.sh"
Team context"PR #142 reverted the caching change — don't re-add it"

Blog Post

Read How toon-memory Makes Your AI Agent Smarter to see a real-world demo of persistent memory in action.


Features

  • 29 MCP tools — Full memory management via Model Context Protocol, including memory_smart_recall (unified recall), memory_sessions for multi-session coordination, context_* tools for one-call context generation (briefing, diff, focus, health audit, export), memory_compress (LLM-powered compression), memory_compress_all (batch compression), memory_primer (auto-injected context), memory_merge_sessions (cross-session merge), and memory_export_gist/memory_import_gist (GitHub Gist sync)
  • MCP Resources — Read memory as context without tool invocations, including a System Primer (auto-generated knowledge map)
  • 15 agents supported — OpenCode, VS Code, Claude Code, Cursor, Windsurf, Cline, Continue, Codex CLI, Gemini CLI, Zed, Antigravity, Aider, KiloCode, OpenClaw, Kiro
  • Interactive installer — Select which agents to configure from a menu
  • SessionStart hooks — Auto-reminders for Claude Code, Codex CLI, Gemini CLI, Antigravity
  • TOON format — 22% fewer tokens than JSON (measured), better LLM comprehension
  • Per-project memory — Each project gets its own memory file
  • Zero config — Just install and use
  • Auto gitignore — Automatically adds .toon-memory/memory/ to .gitignore
  • Date filtering — Search memory by date range
  • Auto-archive — Old entries (>30 days), expired TTL entries, or 100+ entries moved to archive automatically
  • Encryption — AES-256-GCM encryption for sensitive data
  • Watch mode — Auto-backup every N minutes
  • Memory TTL — Configurable per-entry expiration (7d, 30d, or exact dates)
  • Tag inference — Auto-detect tags from content when tags are empty (built-in vocabulary + project dependencies)
  • Memory diff — See what changed since your last session
  • Related entries — Auto-suggest related memories when saving
  • Memory graph — Connect entries with links/[[key]] refs; memory_recall can expand a relationship-aware subgraph for more precise, lower-token recall (no embeddings, no LLM)
  • Token-efficient recallmemory_recall({ compact: true }) returns numeric-indexed entries, drops id/date/file, renders graph edges as ->2, and truncates graph neighbors to snippets
  • BM25 + centrality ranking — Recall re-ranks by BM25 relevance and graph centrality (hubs surface even without the query word); per-hop decay keeps distant nodes low
  • Auto-tag from dependenciestoon-memory init scans package.json/Cargo.toml/requirements.txt/go.mod and writes a project vocabulary so entries mentioning a dependency get auto-tagged with it
  • Smart Recallmemory_smart_recall combines BM25 + graph + decay + quality in one call; the LLM calls this at the start of every task
  • Quality scoring — Every entry gets a 0–1 quality score based on structure (tags, links, content specificity, recency, access count); high-quality entries surface first
  • Merge-dedup — Saving with the same key merges attributes (union of tags, max confidence, latest date, combined links) instead of overwriting
  • Near-duplicate detection — Consolidation detects near-duplicates via Jaccard similarity (threshold 0.7) and merges them
  • Confidence score — Each entry tracks reliability: user-asserted = 1.0, inferred = 0.65–0.75
  • LLM-powered compressionmemory_compress uses AI to summarize long entries; memory_compress_all does batch compression deterministically
  • Cross-session mergememory_merge_sessions merges observations across parallel sessions for a file
  • GitHub Gist syncmemory_export_gist and memory_import_gist sync memory entries via GitHub Gist (zero dependencies)
  • Verbatim modeconfig.verbatim preserves original entries instead of overwriting on save
  • Context generation toolscontext_generate (full briefing), context_diff (incremental), context_focus (targeted), context_health (audit), context_export (markdown) — each replaces 5-6 manual tool calls. Zero LLM, pure deterministic aggregation
  • System Primer — Auto-injected at session start via systemPrimer(), showing top 5 memories for instant context

Quick Start

1. Install

# macOS / Linux
curl -fsSL https://raw.githubusercontent.com/LuiggiVal08/toon-memory/main/install.sh | sh

# Windows (PowerShell)
irm https://raw.githubusercontent.com/LuiggiVal08/toon-memory/main/install.ps1 | iex

# Or with npm (any platform)
npm i -g toon-memory

Tip: The npm install is the most reliable method. The curl/irm scripts are convenience wrappers.

2. Configure your agent(s)

# Interactive installer — detects agents and configures MCP
npx toon-memory

The installer will:

  1. Detect which AI agents you have installed
  2. Ask which ones to configure
  3. Add the MCP server config automatically

3. Use it

That's it! In your next agent session, try:

memory_stats      # See what's in memory
memory_recall     # Search memory before reading files
memory_remember   # Save important decisions

Tip: Always run memory_recall at the start of a session. Your agent will have context from previous sessions instantly.


Supported Agents

AgentConfig LocationFormatHooksAuto-Setup
OpenCode.opencode/opencode.json + .opencode/plugins/toon-memory.tsPluginSessionStart (plugin, no top-level hooks)
VS Code / Copilot.vscode/mcp.jsonJSON
Claude Code.mcp.json (MCP) + .claude/settings.json (hooks)JSONSessionStart + PostToolUse + Stop
Cursor.cursor/mcp.jsonJSON
Windsurf~/.codeium/windsurf/mcp_config.jsonJSON
Cline.cline/mcp.jsonJSON
Continue.continue/config.jsonJSON
Codex CLI.codex/config.tomlTOMLSessionStart + PostToolUse + Stop ([[hooks]] event=)
Gemini CLI.gemini/settings.jsonJSONSessionStart + PostToolUse + Stop (hooks.*)
Zed~/.config/zed/settings.jsonJSONC
Antigravity.agents/mcp_config.json + .agents/hooks.jsonhooks.jsonPreInvocation + PostToolUse + Stop (no SessionStart event)
Aider📝 Instructions
KiloCode~/.kilocode/mcp_settings.jsonJSON
OpenClaw.openclaw.jsonJSON
Kiro.kiro/settings/mcp.jsonJSON

Tip: You can configure toon-memory for multiple agents at the same time. Each agent gets the same shared memory file at .toon-memory/memory/.


MCP Tools

ToolDescription
memory_rememberSave a decision, pattern, bug, or knowledge (optional TTL, auto-tag inference, links to build the memory graph, merge-dedup on same key, auto quality score and confidence)
memory_recallSearch memory (use BEFORE reading files, filters expired TTL). mode: "graph" expands a relationship-aware subgraph for higher precision. compact: true returns a token-efficient, numeric-indexed format. Quality-weighted ranking
memory_smart_recallUnified recall: BM25 + graph + decay + quality in one call. Use at the START of every task. Returns compact, token-efficient output
memory_forgetRemove an entry by key or id
memory_statsView memory state (including TTL stats and quality distribution)
memory_summarySave/retrieve file summaries
memory_archiveArchive old entries (>30 days) and expired TTL entries
memory_diffShow changes since a date (24h, 7d, or exact date)
memory_suggestFind related entries for a given context
memory_encryptEnable AES-256-GCM encryption
memory_decryptDisable encryption
memory_backupCreate timestamped backup of memory file (auto-prunes to 10 most recent)
memory_capturedList activity auto-captured by hooks (opt-in) or clear the log
memory_consolidateMerge-dedup entries: same-key entries are merged (tags union, max confidence, latest date), then exact-content duplicates removed (deterministic, no LLM)
memory_sessionsShow active agent sessions (branch, files, last-seen) and soft conflicts for parallel work
memory_compressLLM-powered two-step compression: summarize + overwrite. Uses anthropic/openai CLI if available, otherwise returns prompt for manual compression
memory_compress_allBatch compression: overwrites all entries under 100 tokens with a compressed version. Deterministic, no LLM
memory_primerOne-call context primer: top memories + categories + session file changes. Auto-injected at session start
memory_merge_sessionsMerge observations across parallel sessions for a file. Deduplicates and optionally auto-promotes to memory
memory_export_gistExport memory entries to a GitHub Gist (public or private). Uses GITHUB_TOKEN or gh CLI
memory_import_gistImport entries from a GitHub Gist. Merges with existing entries (union of tags, max confidence)
memory_merge_similarFind entries with >50% word similarity (Jaccard) and merge them deterministically. No LLM needed
memory_graph_pathBFS shortest path between two entries in the knowledge graph. Shows how concepts are connected
context_briefOne-call context briefing: memory + sessions + health in compact markdown. Use instead of 5-6 separate memory_* calls. Zero LLM, pure deterministic aggregation
context_generateFull project briefing: combines project structure, git state, memory entries, and active sessions in one call. Replaces 5-6 manual tool calls
context_diffIncremental briefing: git commits + modified files + new/updated memory + active sessions since last session
context_focusHyper-focused briefing: only relevant memory + related source files + callers + test files for a query
context_healthMemory health audit: orphan links, duplicates, broken file refs, expired TTL, stale sessions, score 0–100
context_exportExport memory as markdown: injectable context for system prompts (full or compact)

MCP Resources

Memory is also exposed as MCP resources for direct context reading:

ResourceURIDescription
Memory Entriestoon://memory/entriesFull memory dump
Memory Statstoon://memory/statsCategory counts and TTL info
System Primertoon://memory/summariesAuto-generated knowledge map (top entries, categories, patterns)

Examples

Remember a decision

memory_remember({
  category: "decision",
  key: "use-zod",
  content: "Use Zod for validation — simpler than Joi, better TS support",
  file: "src/types.ts",
  tags: "validation;types"
})
// 🧠 Guardado: decision/use-zod (a1b2c3d4)
// Quality score: 0.65 (2 tags, detailed content)
// 🔗 Entradas relacionadas:
//   [pattern] zod-schemas — Shared Zod schemas for API validation

Tip: Use descriptive keys like use-zod instead of vague ones like validation. Your agent searches by key and content, so specificity helps. Saving with the same key auto-merges (union of tags, max confidence).

Remember with TTL

memory_remember({
  category: "knowledge",
  key: "sprint-deadline",
  content: "Sprint ends July 18, feature freeze is July 16",
  ttl: "7d"
})
// 🧠 Guardado: knowledge/sprint-deadline (x1y2z3w4)
// ⏰ TTL: 2026-07-19
// Quality score is calculated automatically.

Tip: Use TTL for temporary context like deadlines, sprint info, or time-sensitive notes. Entries with expired TTL are automatically filtered from search results.

Auto-inferred tags

memory_remember({
  category: "bug",
  key: "redis-connection-timeout",
  content: "Redis connection timeout in production, increased pool size"
  // tags left empty — auto-inferred from content
})
// 🧠 Guardado: bug/redis-connection-timeout (a1b2c3d4)
// 🏷️ Tags inferidos: redis
// Quality score is calculated automatically based on inferred tags and content.

Tip: Leave tags empty and the system will infer them from your content using a built-in vocabulary of 20+ categories (redis, auth, api, db, security, etc.) plus a project vocabulary derived from your dependencies at init time. So if your project depends on redis, any entry mentioning "redis" gets auto-tagged redis.

Search memory

memory_recall({ query: "redis" })
// [bug] redis-pool-fix (i9j0k1l2)
//   Added max_connections=20
//   File: redis.ts | Tags: redis;fix | Date: 2026-07-10

Tip: Search before you read files. This saves tokens and gives your agent context it wouldn't get from code alone. Quality-weighted ranking ensures the most useful entries surface first. Or use memory_smart_recall for a more comprehensive result.

Search with date filter

memory_recall({
  query: "redis",
  from_date: "2026-07-01",
  to_date: "2026-07-31"
})

Tip: Use date filters when you remember roughly when something happened but not exactly what. Quality-weighted ranking still applies.

Archive old entries

memory_archive()
// 📦 Archivadas 5 entradas antiguas
// 📋 Quedan 42 entradas activas

Tip: Run this periodically to keep memory lean. Archived entries are still searchable via memory_recall with date filters. Entries with expired TTL are also archived automatically. Low-quality entries get lower recall priority. Low-quality entries get lower recall priority.

Show changes since last session

memory_diff({ since: "24h" })
// 📋 Cambios desde 2026-07-11:
//
// ➕ Nuevas (2):
//   [decision] use-zod (a1b2c3d4)
//     Use Zod for validation
//   [bug] redis-timeout (e5f6g7h8)
//     Redis connection timeout fix

Tip: Use memory_diff at the start of a session to see what your agent learned since you last worked on the project. New entries include quality scores. New entries include quality scores.

Find related entries

memory_suggest({ context: "redis cache configuration" })
// 🔍 Sugerencias para "redis cache configuration":
//
// [decision] redis-cache-config (a1b2c3d4)
//   Redis cache layer for session storage
//   File: src/cache.ts | Tags: redis;cache | Date: 2026-07-10
//
// [bug] redis-pool-fix (i9j0k1l2)
//   Added max_connections=20
//   File: redis.ts | Tags: redis;fix | Date: 2026-07-10

Tip: Use memory_suggest when you need context about a topic but aren't sure what to search for. Or use memory_smart_recall for a more comprehensive result.

Smart Recall (unified)

memory_smart_recall({ intent: "diseño de base de datos para backend" })
// [1] decision/use-postgres
//   Choose Postgres for ACID compliance and JSON support
//   tags: db;decision · edges: ->2
//
// [2] pattern/db-migrations
//   Use sequential migration files, never edit committed ones
//   tags: db;pattern · edges: ->1
//
// [3] bug/redis-timeout
//   Redis connection timeout — increased pool to 20
//   tags: redis;bug

Tip: Use memory_smart_recall at the START of every task. It combines BM25 + graph + decay + quality in one call — no need to guess what to search for.

Full project briefing (one call)

context_generate({})
// # Project Briefing (full)
//
// ## Project
// - Name: my-app
// - Root: /path/to/project
// - Package Manager: npm
// - TypeScript: ✓ (v5.3)
//
// ## Git Status
// - Branch: main
// - 3 uncommitted, 0 untracked
//
// ## Memory (42 entries, 12 patterns, 8 bugs)
// [1] decision/use-postgres
//   Choose Postgres for ACID compliance
//   tags: db;decision
//
// ## Sessions
// - egraterol (main, 2m ago): 42 files touched

Tip: Use context_generate at the start of a session to get full context in one call. Replaces 5-6 separate tool calls.

Memory health audit

context_health({})
// # Memory Health (score: 87/100)
//
// ## Summary
// - 42 entries (12 patterns, 8 bugs, 15 decisions, 7 knowledge)
// - 65.3% average quality
//
// ## Issues (3)
// - Orphan link: pattern/db-migrations → pattern/db-seed (key not found)
// - Duplicate: [bug] redis-pool-fix has identical content
// - Expired TTL: [knowledge] sprint-deadline (expired 2026-07-20)
//
// ## Stale Files (1)
// - src/legacy.ts (deleted, 2 refs)

Tip: Run context_health when memory feels cluttered. Shows orphan links, duplicates, expired TTL entries, and broken file references.

Merge-dedup (automatic)

When you save with the same key, attributes are merged instead of overwritten:

// First save
memory_remember({
  category: "decision",
  key: "use-zod",
  content: "Use Zod for validation",
  tags: "types"
})
// 🧠 Guardado: decision/use-zod (a1b2c3d4)

// Later save with same key — merges automatically
memory_remember({
  category: "decision",
  key: "use-zod",
  content: "Use Zod for validation — also handles API response parsing",
  tags: "types;api"
})
// 🧠 Actualizado: decision/use-zod (a1b2c3d4)
// 🔗 Merge: tags combinados, fecha y links actualizados
// Tags now: "types;api" (union of both)

Tip: Use descriptive, stable keys. The same key = merge, different key = new entry.

Quality scoring

Every entry gets an automatic quality score (0–1) based on structure:

FactorWeightWhat it measures
Tags0.3 maxMore specific tags = higher quality
Links0.2 maxConnected entries = higher quality
Content length0.3 maxDetailed > vague
Recency0.1 maxRecent entries score higher
Specificity0.1 maxUnique words vs repeated words

High-quality entries surface first in recall. Check quality with memory_stats:

memory_stats()
// ...
// Calidad promedio: 0.58 (12 con score)

Confidence score

Each entry tracks how reliable the information is:

SourceConfidenceMeaning
User assertion1.0"We use Postgres" — direct statement
Inferred0.65–0.75Agent inferred from context
Uncertain0.50Agent is guessing

Confidence is preserved on merge (max of both entries).

System Primer

The System Primer is an auto-generated knowledge map exposed as an MCP resource. Agents load it at session start for instant context:

// Exposed as toon://memory/summaries
// Auto-regenerates on every read
// Contains: top entries, categories, patterns

Tip: Add toon://memory/summaries to your agent's system prompt for instant context at session start.

Enable encryption

// First, set TOON_MEMORY_KEY in your environment (or .env file):
// export TOON_MEMORY_KEY="your-secret-key-here"

memory_encrypt()
// 🔐 Encriptación habilitada

Warning: The encryption key must be set via TOON_MEMORY_KEY env var before encrypting. Save it somewhere safe — if you lose it, your memory data is gone forever. Quality scores and confidence are preserved through encryption.


Coordinación multi-sesión

When you run several AI agent sessions in parallel (e.g. three OpenCode sessions on the same repo at once), they can accidentally clobber each other's work. toon-memory ships with memory_sessions, a file-based coordination tool that lets every session see what its siblings are doing — with no server, no network, and no LLM calls.

How it works

  • On startup, a SessionStart hook writes a heartbeat file for the session at .toon-memory/memory/sessions/<id>.json. Each process writes only its own file, so there's no lock contention.
  • The heartbeat records the agent name, the git branch, the files touched, and a last-seen timestamp.
  • Reading across all those files gives every session a shared, eventually-consistent view of who else is active.
  • Dead sessions (process PID no longer alive and a stale heartbeat past the TTL window) are pruned lazily.

The memory_sessions tool

memory_sessions({ conflictsOnly: false })
// 🧭 Sesiones activas (2) — ventana 30 min:
//
// • opencode @ feature/auth (tú)
//   id: a1b2c3d4
//   hace 2 min
//   Archivos:
//     • src/auth.ts
//
// • claude @ feature/db
//   id: e5f6g7h8
//   hace 9 min
//     • src/db.ts
//
// 🔥 Conflictos suaves (1):
//   ⚠️ src/types.ts  ↔  opencode @ feature/auth, claude @ feature/db
  • Pass conflictsOnly: true to skip the session list and show only soft conflicts:
    memory_sessions({ conflictsOnly: true })
    // 🔥 Conflictos suaves (1):
    //
    // ⚠️ src/types.ts
    //    ↔ opencode @ feature/auth (a1b2c3d4), claude @ feature/db (e5f6g7h8)
    
  • A soft conflict is any file touched by 2+ active sessions — a heads-up that you might be editing the same code. It's not a hard lock, just a warning to coordinate.

Recommended parallel-session habit

  1. At the start of every session, the SessionStart hook already prints the other active sessions and any soft conflicts.
  2. Run memory_smart_recall({ intent: "what I'm working on" }) to get full context (memory + graph + quality).
  3. Run memory_sessions() to see the full picture (branches, files, last-seen) and memory_sessions({ conflictsOnly: true }) if you only care about clashes.
  4. If you share a file with another session, sync up before editing so you don't overwrite each other's changes.

Tip: This is purely local and lock-free — safe to run as often as you like. Combine it with memory_smart_recall({ intent: "project context" }) at session start for both cross-session memory and cross-session presence. The system primer (MCP resource) also provides instant context.


Memory Graph (recall basado en grafo)

When your memory grows, a flat keyword search can return either too much (every match) or the wrong context (no relationships). toon-memory can treat memory as a lightweight knowledge graph so recall returns the right entries with fewer tokens. Combined with quality scoring, the most useful entries surface first.

It's fully deterministic and offline — no embeddings, no vector DB, no LLM, no server. Edges come from two sources:

  • Explicit links — keys you declare when saving an entry.
  • Implicit [[key]] refs — any [[some-key]] mention inside the content.

How it works

  1. memory_remember stores links on the entry (space- or ;-separated keys). Quality score is calculated automatically.
  2. memory_recall({ mode: "graph" }) finds keyword matches (seeds), then expands the ego-subgraph up to hops (1 or 2) along the edges.
  3. Relevance propagates from the seeds to their neighbors, so a related decision or spec surfaces even if it doesn't contain the query word. Quality-weighted ranking ensures the most useful entries appear first.
  4. The result set is capped (limit, default 6) → smaller, more precise context for the agent. Or use memory_smart_recall for a unified call.

Remember with links

memory_remember({
  category: "decision",
  key: "risk-engine-priority",
  content: "The engine prioritizes risk over speed (see [[risk-spec]]).",
  file: "spec.md:10",
  tags: "risk;spec",
  links: "engine-arch"          // explicit edge to another entry
})
// 🧠 Guardado: decision/risk-engine-priority (a1b2c3d4)
// Quality score is calculated automatically based on tags, links, and content detail.

Recall with graph mode

memory_recall({ query: "riesgo", mode: "graph", hops: 2 })
// [decision] risk-engine-priority (a1b2c3d4)
//   The engine prioritizes risk over speed (see [[risk-spec]]).
//   File: spec.md:10 | Tags: risk;spec | Date: 2026-07-01
//   links: engine-arch
//
// [knowledge] risk-spec (a2b3c4d5)
//   Risk specification for the engine.
//   links: risk-engine-priority;engine-arch
//
// [pattern] engine-arch (e6f7g8h9)
//   Engine architecture.
//   links: risk-spec

Tip: Use mode: "graph" when a decision ripples across several entries (architecture, specs, related bugs). For isolated facts, the default flat mode is enough. Or use memory_smart_recall which combines graph + BM25 + quality automatically.

Token-efficient recall (compact)

When every token counts, pass compact: true to get a denser output:

memory_recall({ query: "riesgo", mode: "graph", hops: 2, compact: true })
// [1] decision/risk-engine-priority
//   The engine prioritizes risk over speed (see [[risk-spec]]).
//   tags: risk;spec · edges: ->2, ->3
//
// [2] knowledge/risk-spec
//   Risk specification for the engine.
//   tags: risk · edges: ->1
//
// [3] pattern/engine-arch
//   Engine architecture.
//   tags: engine · edges: ->1

How compact changes the output:

  • Each entry gets a stable numeric index ([1], [2], …) in score order.
  • id, date, and file are dropped — only tags is kept.
  • In graph mode, edges render as ->2 (numeric, not key names).
  • Neighbors reached via the graph (non-seeds) are truncated to a short snippet with an ellipsis, while directly-matched seeds keep their full content.
  • Quality-weighted ranking ensures the most useful entries appear first.
  • The stored .toon file is never mutated — compact only reshapes the response.

Tip: Combine compact: true with mode: "graph" for the smallest possible context window when recalling from a large, interconnected memory. Or just use memory_smart_recall which does this automatically.

How recall ranks results

Recall is deterministic and offline (no embeddings, no LLM). Each candidate entry gets a combined score:

  • BM25 relevance — classic probabilistic term-frequency score against the query, using id + category + key + content + file + tags + quality + confidence.
  • Graph centrality — degree-normalized (0..1); a hub connected to many entries scores near 1, so it surfaces even without the query word.
  • Importance — recency + access frequency (same signal used elsewhere).
  • Quality boost — entries with higher quality scores (more tags, links, detail) get a ranking boost.
  • Seed bonus — entries that directly match the query get a flat boost.
  • Per-hop decay — nodes d hops from a seed are multiplied by 0.5^d, so distant context ranks below nearby context.

In graph mode, recall seeds on keyword matches, expands the ego-subgraph up to hops, and returns the top limit (default 6) by combined score. memory_smart_recall combines all these signals in one call.

Auto-tag from project dependencies

On toon-memory init, the CLI scans your dependency manifests and writes a vocab table into .toon-memory/memory/config.json:

{
  "vocab": {
    "react": ["react"],
    "zod": ["zod"],
    "redis": ["redis"]
  }
}

memory_remember then matches new entries against this vocabulary on top of the built-in one, so mentioning a dependency in your content auto-attaches its tag. More tags = higher quality score. Supported manifests: package.json, Cargo.toml, requirements.txt, pyproject.toml, go.mod.

Tip: Re-run toon-memory init after adding major dependencies to refresh the vocabulary. The vocab key is merged (never clobbered) with the encrypted/capture flags in config.json. More tags = higher quality score.


Tips & Best Practices

Here are some patterns that work well with toon-memory:

The "start of session" habit

At the beginning of every new session, run:

memory_smart_recall({ intent: "what I was working on" })

This gives your agent instant context about what happened before — combining BM25, graph, quality, and decay in one call.

The "end of session" habit

Before closing a session, save anything important:

memory_remember({
  category: "decision",
  key: "auth-approach",
  content: "Chose JWT over sessions — stateless, works across microservices",
  file: "src/auth.ts",
  tags: "auth;architecture"
})

The entry automatically gets a quality score based on its structure (tags, content detail, links).

Choosing categories

CategoryWhen to use
decisionArchitecture choices, trade-offs, "why X over Y"
patternConventions, frameworks, code style rules
bugIssues you fixed and how
knowledgeProject facts, domain info, team context

Tip: Don't overthink it. If it's something your future self (or agent) would want to know, save it. Detailed entries with specific tags score higher in quality.

Tags that work well

Use semicolon-separated tags for easy filtering:

tags: "redis;performance;fix"
tags: "auth;jwt;security"
tags: "api;rest;versioning"

Tip: Keep tags short and consistent. They're not hashtags — they're search filters. More specific tags = higher quality score.

What NOT to save

  • Don't save things that are obvious from reading the code
  • Don't save temporary debugging notes
  • Don't save secrets, API keys, or credentials (use env vars instead)
  • Don't duplicate the same information with different keys (merge-dedup handles same-key automatically)
  • Vague entries with no tags score low in quality — be specific

Keep memory clean

Run memory_archive() monthly to move old entries to the archive. Run memory_stats() to check the size and quality distribution. Low-quality entries (vague content, no tags) get lower recall priority automatically. Use memory_consolidate to merge duplicates.


CLI Commands

npx toon-memory              # Interactive installer
npx toon-memory init         # Quick setup (no prompts)
npx toon-memory mcp          # Run MCP server directly
npx toon-memory status       # Check installation status
npx toon-memory stats        # View memory statistics
npx toon-memory export       # Export memory to JSON
npx toon-memory import <file> # Import memory from JSON
npx toon-memory watch [options] # Auto-backup with options
npx toon-memory upgrade      # Update to latest version
npx toon-memory uninstall    # Remove from all agents

Examples

Stats

$ npx toon-memory stats

🧠 toon-memory stats

📊 Memory Stats
━━━━━━━━━━━━━━━━━━
Total entries: 45
├── decision: 12
├── pattern: 18
├── bug: 8
└── knowledge: 7
Last updated: 2026-07-10
File size: 12.4 KB

Tip: If memory gets too large (100+ entries), consider archiving or removing outdated entries with memory_forget.

Export

$ npx toon-memory export

🧠 toon-memory export

Exported 45 entries to:
  /path/to/project/toon-memory-export.json

Tip: Export before major refactors. You can always import the backup later if something goes wrong.

Import

$ npx toon-memory import backup.json

🧠 toon-memory import

Imported 3 new entries
Skipped 2 duplicates

Tip: Duplicates are detected by key. If you want to re-import an entry, delete the old one first with memory_forget.

Watch

$ npx toon-memory watch 15 -c -m 20

🧠 toon-memory watch

Watching memory file every 15 minutes...
Max backups: 20
Compression: enabled
Logging: disabled
Press Ctrl+C to stop

📦 Backup #1 created: 2026-07-11T16-00-00-000Z
📦 Backup #2 created: 2026-07-11T16-15-00-000Z
^C
✅ Watch stopped. 2 backups created.

Tip: Watch mode is great for long-running sessions. Use -c to compress and -m 5 to keep only 5 backups.

Watch Options:

OptionDescriptionDefault
[interval]Backup interval in minutes5
-c, --compressEnable gzip compressionoff
-l, --log [path]Enable file loggingoff
-m, --max-backups <n>Max backups to keep (0=unlimited)10

Configuration

Interactive installer (recommended)

npx toon-memory

The installer (requires a terminal) will:

  1. Show all 15 supported agents with detection status ( config found) and their supported scope (local/global or solo local)
  2. Let you select which ones to configure — by number (1,3,5), by name (claude,codex), all, Enter for all, or q to quit
  3. Ask for the installation scope: (1) Local (project: .toon-memory + agent configs in the repo) or (2) Global (~home configs)
  4. Show a confirmation summary (agent → scope → path (MCP/plugin/hooks/instrucciones)) and ask ¿Proceder? [Y/n]
  5. Configure MCP server, instruction files, and hooks automatically

Sin una terminal (CI/pipes) npx toon-memory imprime la ayuda de instalación no interactiva. Usa npx toon-memory init [local|global] para instalar sin preguntas. Unknown commands print usage and exit with an error.

OpenCode

Add to .opencode/opencode.json or ~/.config/opencode/opencode.json:

{
  "mcp": {
    "toon-memory": {
      "type": "local",
      "command": ["npx", "-y", "toon-memory", "mcp"],
      "enabled": true
    }
  }
}

Hooks are delivered via a plugin, not a top-level hooks key. OpenCode 1.17+ rejects "Unrecognized key: hooks" in its config — toon-memory init writes .opencode/plugins/toon-memory.ts instead. Do not add hooks to opencode.json.

Claude Code

Add to .mcp.json (project root):

{
  "mcpServers": {
    "toon-memory": {
      "command": "npx",
      "args": ["-y", "toon-memory", "mcp"]
    }
  }
}

VS Code / Copilot

Add to .vscode/mcp.json:

{
  "servers": {
    "toon-memory": {
      "command": "npx",
      "args": ["-y", "toon-memory", "mcp"]
    }
  }
}

Codex CLI

Add to .codex/config.toml:

[mcpServers.toon-memory]
command = "npx"
args = ["-y", "toon-memory", "mcp"]

Gemini CLI

Add to .gemini/settings.json:

{
  "mcpServers": {
    "toon-memory": {
      "command": "npx",
      "args": ["-y", "toon-memory", "mcp"]
    }
  }
}

Zed

Add to ~/.config/zed/settings.json:

{
  "mcp_servers": {
    "toon-memory": {
      "command": "npx",
      "args": ["-y", "toon-memory", "mcp"]
    }
  }
}

Tip: Use global config if you want memory for every project. Use project-level config if you only want it for specific projects.


How It Works

  1. MCP Server — Runs locally, talks to your agent via stdio
  2. TOON Format — Stores data in Token-Oriented Object Notation (~22.5% fewer tokens than JSON, measured over 16 entries with gpt-tokenizer). Each entry tracks quality (0–1) and confidence (0–1) automatically.
  3. Per-project memory — Each project gets .toon-memory/memory/data.toon
  4. Zero config — Just install and use

Memory File Format

version: 1
entries[3|]{id|category|key|content|file|tags|date|ttl|accessed|links|quality|confidence}:
  a1b2c3d4|decision|use-zod|Use Zod for validation|src/types.ts|validation;types|2026-07-10||0||0.65|1.0
  e5f6g7h8|pattern|pydantic-configs|Project uses Pydantic v2|config.py|python;patterns|2026-07-10||0||0.55|1.0
  i9j0k1l2|bug|redis-pool-fix|Added max_connections=20 (see [[use-zod]])|redis.ts|redis;fix|2026-07-10|7d|0|use-zod|0.70|0.9
summaries:
  src/services/redis.ts: Redis connection pool with retry logic

File Structure

.toon-memory/
├── memory/
│   ├── data.toon        # Main memory file
│   ├── archive.toon     # Archived entries (>30 days)
│   ├── config.json      # Encryption settings
│   └── backups/         # Watch mode backups
│       ├── backup-2026-07-11T16-00-00-000Z.toon
│       └── backup-2026-07-11T16-10-00-000Z.toon
└── hooks/
    ├── session-start-claude.sh
    ├── session-start-codex.sh
    ├── session-start-gemini.sh
    └── session-start-antigravity.sh

Why TOON?

TOON (Token-Oriented Object Notation) is designed for LLMs:

FormatTokens (16 entries)
JSON1097
TOON850

Measured with gpt-tokenizer (cl100k_base) over 16 representative memory entries — see scripts/benchmark-toon.mjs (npm run bench).

The token savings compound at session time: npm run bench:impact simulates retrieving context with vs without memory and measures ~68% fewer tokens to get the same context (recall compact instead of re-reading source files). The full session benchmark (npm run bench:full) shows 80% fewer tool calls and 47% fewer tokens with context_* tools.

  • 22.5% fewer tokens than JSON at file level (up to 30.5% on a single entry)
  • Lossless roundtrip — No data loss
  • Better LLM comprehension — Structured for AI consumption
  • Quality & confidence — Every entry tracks structure quality (0–1) and reliability (0–1) automatically

Tip: Fewer tokens = faster responses + lower API costs. Your agent reads memory files on every session start, so efficiency matters.


Benchmark: toon-memory vs Alternatives

Featuretoon-memory@modelcontextprotocol/server-memorymem0shodh-memory
StorageLocal file (TOON)Local file (JSON)CloudRocksDB
DependenciesZeroZeroCloud APIsentence-transformers, RocksDB
SearchBM25 + graph + qualityBasic keywordVector onlyHybrid (vector + graph)
Token efficiency22.5% fewer than JSONBaseline (JSON)N/A (cloud)Similar
Quality scoringAuto (0–1, heuristics)NoneNoneBND algorithm
Merge-dedupTags union + max confidenceNoneNoneContent dedup
Confidence trackingPer-entry (0–1)NoneNonePer-entry
System PrimerAuto-generatedNoneNoneNone
Multi-sessionFile-based coordinationNoneN/ANone
Hooks15 agentsNoneNoneClaude only
EncryptionAES-256-GCMNoneCloud-managedNone
Setup timenpx toon-memoryManual JSONCloud signupDocker + config

Token efficiency (measured)

Format          Tokens (16 entries)    vs JSON
──────────────  ───────────────────    ───────
JSON            1097                   baseline
TOON            850                    -22.5%

Recall efficiency (measured)

Method                          Tokens to get context    vs re-reading files
──────────────────────────────  ─────────────────────    ───────────────────
Re-read source files            ~3000                    baseline
memory_recall (flat)            ~1200                    -60%
memory_recall (graph, compact)  ~900                     -70%
memory_smart_recall             ~850                     -72%

Context tools benchmark (measured)

The context_* tools replace 3–6 separate tool calls with a single call, saving both tokens and tool-call overhead.

Scenario                          Without   With    Saved    Tools
────────────────────────────────  ────────  ──────  ───────  ──────
context_generate (full briefing)    5,556     378    93.2%   6 → 1
context_diff (incremental)            533     152    71.5%   4 → 1
context_focus (targeted)              413     225    45.5%   4 → 1
context_health (audit)                322     246    23.6%   5 → 1
context_export (injectable md)      1,178     218    81.5%   3 → 1
────────────────────────────────  ────────  ──────  ───────  ──────
TOTAL                              8,002   1,219    84.8%  22 → 5

What each scenario measures:

ToolWithout (manual path)With (single call)Why it saves
context_generateRead package.json + README + tsconfig.json + full memory dump + memory stats + sessions = 6 callsOne compact briefing with everythingEliminates 5 redundant reads; output is deduplicated and compact
context_diffgit log + git diff --name-only + memory_diff + sessions = 4 callsOne incremental diffCombines git state + memory changes in one output; no overlap
context_focusmemory_recall + findCallers + findRelatedFiles + findTestFiles = 4 callsOne targeted briefingOnly returns what's relevant; no full memory scan needed
context_healthmemory_stats + orphan scan + duplicate scan + file ref validation + stale sessions = 5 callsOne health reportEach check is done once and deduplicated; no redundant queries
context_exportmemory_stats + memory_recall({ compact: true, mode: "graph" }) + manual formatting = 3 callsOne markdown exportFormats output directly; agent skips the "format as markdown" step

Tip: Use context_generate at session start (93% token savings). Use context_diff for "what changed since last time?" (72% savings). Use context_focus for deep dives on specific topics (45% savings).

Measured with gpt-tokenizer (cl100k_base) over realistic project scenarios — see scripts/bench-context-tools.mjs (npm run bench:context).

Full session impact (measured)

Simulates a complete 5-phase agent session (session start → debug → implement → review → wrap-up) across 3 approaches: without memory, with memory_recall, and with context_* tools.

Phase                                   Without memory     memory_recall      context_* tools
──────────────────────────────────────  ─────────────────  ─────────────────  ─────────────────
Phase 1: Session Start                  516 t /  6 c       409 t /  3 c       373 t /  1 c
Phase 2: Debug Issue                    176 t /  4 c       182 t /  2 c       252 t /  1 c
Phase 3: Implement Feature              189 t /  6 c       183 t /  3 c       305 t /  1 c
Phase 4: Code Review                    316 t /  4 c       130 t /  2 c       243 t /  1 c
Phase 5: Wrap-up                      1,214 t /  5 c        68 t /  2 c       117 t /  1 c
──────────────────────────────────────  ─────────────────  ─────────────────  ─────────────────
TOTAL                                 2,411 t / 25 c       972 t / 12 c     1,290 t /  5 c

Key findings:

MetricWithout memoryWith memory_recallWith context_* tools
Tokens per session2,411972 (-60%)1,290 (-47%)
Tool calls per session2512 (-52%)5 (-80%)
Cost per session (GPT-4)$0.072$0.029$0.039

The trade-off: memory_recall uses fewer tokens (972 vs 1,290) because it returns only matching entries. context_* tools return richer context (callers, related files, test files, health audit) — more tokens per call, but 80% fewer tool calls. In practice, the agent avoids 3-4 follow-up "find related" calls that context_focus already includes.

Where context_ wins big:*

  • Session start (Phase 1): 28% fewer tokens + 6→1 calls — one briefing replaces reading 6 files
  • Wrap-up (Phase 5): 90% fewer tokens — context_health replaces 5 manual scans
  • Tool calls: 25→5 calls = 80% less latency overhead per session

Tip: Use memory_recall when you need specific entries (fewer tokens). Use context_* when you need comprehensive context with fewer round-trips (fewer calls).

Measured with gpt-tokenizer (cl100k_base) — see scripts/bench-full-impact.mjs (npm run bench:full).

Tip: memory_smart_recall combines BM25 + graph + quality in one call, saving both tokens and tool-call overhead. Use it at the start of every task.


Troubleshooting

Memory not found after install

Symptom: Agent says it doesn't have memory tools.

Fix:

  1. Run npx toon-memory status to verify installation
  2. Restart your agent completely (close and reopen)
  3. Check that the MCP config file exists and is valid JSON

Memory file is empty

Symptom: memory_stats shows 0 entries.

Fix: This is normal on first install. Start using memory_remember to save entries.

Duplicate entries

Symptom: Same key appears multiple times.

Fix: memory_remember with the same key now auto-merges (union of tags, max confidence, latest date). Use memory_consolidate to merge all same-key entries and remove exact-content duplicates. For manual cleanup, use memory_forget.

Encryption key lost

Symptom: Can't decrypt memory.

Fix: Unfortunately, there's no recovery. The encryption key is not stored anywhere after generation. This is by design for security. You'll need to start fresh or restore from a non-encrypted backup.

Memory too large

Symptom: Agent responses are slow.

Fix:

  1. Run memory_archive() to move old entries to archive
  2. Use memory_forget to remove irrelevant entries
  3. Keep entries concise — save the decision, not the entire conversation
  4. Low-quality entries (vague, no tags) get lower recall priority automatically

FAQ

Does this work with any AI agent?

Yes, as long as it supports MCP (Model Context Protocol). We have auto-setup for 15 agents, with manual configuration available for others.

Is my data sent anywhere?

No. Everything stays on your machine. The MCP server runs locally over stdio — no network calls, no telemetry, no cloud.

Can I use this across multiple machines?

Yes, if you sync the .toon-memory/memory/ directory (e.g., via Git or a shared folder). Each machine needs toon-memory installed, but the memory file is portable.

What happens if I have multiple projects?

Each project gets its own memory file. Memory doesn't leak between projects.

Can I encrypt specific entries only?

No, encryption applies to the entire memory file. If you need selective encryption, keep sensitive data in a separate tool.

How is this different from just using a markdown file?

Markdown files aren't structured, aren't searchable by your agent in the same way, don't integrate via MCP, and don't have features like archiving, date filtering, quality scoring, merge-dedup, confidence tracking, or encryption. toon-memory is purpose-built for AI agents.


Development

git clone https://github.com/LuiggiVal08/toon-memory.git
cd toon-memory
npm install
npm run build
npm test

Project Structure

toon-memory/
├── src/
│   ├── bin/
│   │   └── toon-memory.ts      # Entry point
│   ├── cli/
│   │   ├── setup.ts             # CLI commands
│   │   └── toon-memory.ts       # CLI runner
│   ├── mcp/
│   │   └── server.ts            # MCP server (29 tools + 3 resources)
│   ├── lib/
│   │   ├── lock.ts              # Advisory file lock + atomic write
│   │   ├── sessions.ts          # Multi-session coordination
│   │   ├── graph.ts             # Memory graph (parse, build, BM25, centrality, compact render)
│   │   ├── quality.ts           # Quality scoring, merge-dedup, smart recall, system primer
│   │   ├── context.ts           # Context briefing generator (one-call context)
│   │   └── vocab.ts             # Project-vocabulary discovery from dependencies
├── tests/
│   ├── cli.test.ts              # CLI tests
│   ├── memory.test.ts           # Memory tests
│   ├── sessions.test.ts         # Multi-session tests
│   ├── graph.test.ts            # Memory graph tests
│   └── quality.test.ts          # Quality scoring, merge-dedup, smart recall, system primer tests
├── .github/workflows/
│   ├── ci.yml                   # CI (Node.js 20/22)
│   └── publish.yml              # Auto-publish on release
├── package.json
├── tsconfig.json
└── vitest.config.ts

Contributing

Contributions are welcome! Please read our Code of Conduct and Contributing Guide first.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'feat: add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

MIT


Credits

Built with @toon-format/toon and @modelcontextprotocol/server.