One-command context memory for Claude Code sessions.
Claude Code sessions are stateless. Every new conversation starts cold. Claude re-reads your entire CLAUDE.md, architecture docs, and context files from scratch, burning through tokens and losing the decisions, progress, and institutional knowledge from your last session.
If your project has grown any real context (and most do), you're paying for it on every single session start:
- A typical project accumulates 10-30KB of context files
- That's ~15,000-25,000 tokens loaded every session, most of it stale
- Decisions made three weeks ago get equal weight to yesterday's blockers
- There's no continuity: Claude doesn't know what it did last time
SessionAnchor replaces flat context files with a local SQLite memory store that uses tiered retrieval. One command gives your repo continuity across sessions.
Before: ~18,000 tokens loaded from markdown files every session
After: ~2,000 tokens loaded from structured memory (9x reduction)
The boot briefing is compact, current, and structured. Claude gets exactly what it needs to resume work, not a wall of historical text.
This tool is built for a specific scenario:
- You use Claude Code (Anthropic's CLI agent) on real projects
- Your projects have accumulated context that Claude needs across sessions
- You want local-only, zero-setup continuity without hosted services or API keys
- You care about token efficiency and want to measure it
It is not a general-purpose memory layer, a hosted service, or a multi-agent coordination framework. It solves one problem well: giving Claude Code repos continuity across sessions.
The broader "AI memory" space has several tools, but they solve different (bigger) problems:
| Tool | What it is | Why it's different |
|---|---|---|
| Mem0 | Hosted/self-hosted memory layer for AI apps | Platform-scale ambition. Has a cloud service, API keys, embedding models. You're adopting an infrastructure dependency, not a dev tool. |
| Letta (MemGPT) | Stateful agent framework with git-backed memory filesystem | Deep on agent internals: memory editing, inner/outer monologue, tool use. Way more than context persistence for a CLI. |
| Zep | Fast, scalable context engine with knowledge graphs | Enterprise graph-backed memory with temporal awareness. Requires a server, designed for production apps with users. |
| OpenViking | Context database with hierarchical retrieval | Full context DB: session management, retrieval strategies, embedding pipelines. Another infrastructure layer. |
SessionAnchor is none of these. It's a single pip install with zero dependencies that creates a SQLite file in your repo's .claude/ directory. No servers, no API keys, no embeddings, no hosted anything. It's closer to a .bash_history for your Claude sessions than a memory platform.
The sharp wedge:
One command gives your Claude Code repo continuity across sessions. Local-only SQLite. Measurable token savings. Nothing else.
pip install sessionanchor
# or
pipx install sessionanchor
# or
uvx sessionanchor initRequirements: Python 3.9+. No dependencies (uses Python's built-in sqlite3 with FTS5).
# 1. Initialize (run once per project)
cd your-project
sessionanchor init
# 2. At the start of every Claude Code session
sessionanchor boot
# 3. That's it. CLAUDE.md is configured to tell Claude
# to save context automatically during sessions.Context is stored in three tiers, inspired by CPU cache hierarchies. Each tier has a different loading strategy:
+-------------------------------------------+
| L0: Core Identity (~500 tokens) | Always loaded
| Project name, current phase, top 3 |
| priorities, critical deadlines |
+-------------------------------------------+
| L1: Session-Relevant (~1500 tokens) | Loaded at boot
| Last session summary, active action |
| items, recent decisions, blockers |
+-------------------------------------------+
| L2: Deep Archive (unlimited) | Loaded on demand
| Full history, completed items, old |
| decisions, technical notes, patterns |
+-------------------------------------------+
| Tier | When Loaded | Token Budget | Contains |
|---|---|---|---|
| L0 | Every boot | ~500 | Project identity, current phase, top priorities, critical deadlines |
| L1 | Every boot | ~1500 | Last session summary, active action items, recent decisions, current blockers |
| L2 | On query | Unlimited | Full history, completed items, old decisions, deep technical notes, patterns, lessons |
Boot loads L0 + L1 (~2000 tokens). L2 is only retrieved when Claude calls sessionanchor query during a session. This keeps the boot payload small while making the full history searchable.
Everything lives in a single SQLite database at .claude/memory/context.db:
- WAL mode for safe concurrent access (Claude's subagents can write while the main session reads)
- FTS5 full-text search with BM25 ranking for
querylookups - Deterministic IDs via
sha256(project:category:title)enable natural dedup through upsert - Access tracking records how often each entry is retrieved (useful for future relevance scoring)
The schema is two tables: entries (the memory items) and sessions (session metadata with token counts).
Without compaction, L1 bloats over time as decisions and action items accumulate. SessionAnchor runs automatic compaction at every boot:
| Strategy | Rule | Effect |
|---|---|---|
| Time-based | L1 entries older than 14 days | Demoted to L2 |
| Count cap | More than 20 active L1 entries | Oldest demoted to L2 |
| Completed grace | Completed items older than 3 days | Demoted to L2 |
| Superseded | Entries with a supersedes field |
Old entry archived |
This means L1 stays fresh and bounded without manual cleanup.
When a newer memory replaces an older one, save it with --supersedes <entry-id> so the next boot or compact run archives the superseded entry automatically.
The .contextignore file (created by init) uses gitignore-style patterns to exclude files from the repo indexer:
.env
.env.*
*.key
*.pem
node_modules/
.claude/memory/
Additionally, content is scanned for secret patterns before being stored. AWS keys (AKIA...), API tokens (sk-..., ghp_...), JWTs (eyJ...), and Bearer tokens are automatically replaced with [REDACTED].
init creates (or patches) your CLAUDE.md with instructions that tell Claude to:
- Boot from memory instead of reading large context files
- Save continuously via background subagents after decisions, completions, and blockers
- Never wait for session end to save (the user may close the window at any time)
- Log token counts from the boot footer for measurability
The key insight: Claude doesn't need to be told to "use the memory system." It needs to be told to save to it continuously and not read the old markdown files. The CLAUDE.md prompt handles both.
The boot command appends a token estimate footer:
# Boot tokens: ~1,247 (L0: ~480, L1: ~767)
This uses a simple heuristic (words x 1.3) that's ~90% accurate for English text. It's designed for measuring relative savings (how much smaller is boot vs. reading all your markdown files?) rather than exact billing. The session-end command can log these counts for tracking over time.
sessionanchor init performs exactly these steps:
- Detects the repo root (walks up to find
.git, or uses cwd) - Auto-detects the project name from git remote origin or directory name
- Creates
.claude/memory/directory - Creates the SQLite database with schema
- Creates
.contextignorewith sensible defaults - Creates or patches
CLAUDE.md(appends the context section if CLAUDE.md already exists) - Adds
.claude/memory/to.gitignore - Runs an initial repo structure index
- Prints a quick-start guide
It's idempotent. Running init twice won't duplicate the CLAUDE.md section or overwrite your .contextignore.
sessionanchor init # Bootstrap memory for current repo
sessionanchor boot # Print session briefing (~2000 tokens)
sessionanchor boot --full # Include stats and last session info
# Save context entries
sessionanchor save add \
--tier L1 \
--category decision \
--title "Chose Postgres" \
--content "Better JSON support than MySQL"
sessionanchor save add \
--tier L1 \
--category decision \
--title "Use OAuth PKCE" \
--content "Replaces the legacy auth callback flow" \
--supersedes 1a2b3c4d5e6f7890
sessionanchor save complete \
--title "Build auth flow" \
--category action_item
sessionanchor save session-end \
--summary "Shipped auth, started rate limiting"
# Query memory
sessionanchor query "auth" # Full-text search
sessionanchor query --category decision # By category
sessionanchor query --category action_item --status active
sessionanchor query --since 7 # Last 7 days
# Codebase index
sessionanchor index # Re-index repo structure
sessionanchor index find "auth" # Search code files
sessionanchor index map # Show structural overview
# Maintenance
sessionanchor compact # Manual L1 compaction
sessionanchor stats # Memory store statistics
sessionanchor version # Show versionEntries are organized into 13 categories. Use the one that fits:
| Category | When to use |
|---|---|
identity |
Project identity, org structure, what this repo is |
preference |
Working conventions, code style, deploy preferences |
priority |
Current goals, ranked by urgency |
decision |
Decisions made, with date and rationale |
deadline |
Time-sensitive items with expiry dates |
action_item |
Tasks with owner and status |
blocker |
Things preventing progress |
session_log |
Summary of what happened in a session |
architecture |
System design, data flow, constraints |
technical_note |
Implementation details, fixes, gotchas |
infrastructure |
Deploy config, env vars, DNS |
pattern |
Reusable problem-solution pairs |
lesson |
Things learned from mistakes or successes |
Transparency about what this tool does not do:
- No semantic search. Queries use SQLite FTS5 (keyword matching with BM25 ranking), not embeddings. This is deliberate: zero dependencies, instant results, good enough for project-scoped memory.
- No multi-user coordination. This is personal memory for one developer's Claude sessions on one repo. WAL mode handles concurrent reads/writes from subagents, but there's no semantic conflict resolution.
- No cloud sync. Memory lives in
.claude/memory/context.dbon your machine. If you want it on another machine, copy the file. - No automatic summarization. Compaction demotes old entries to L2, but doesn't summarize or merge them. That's a future direction.
- Token estimates are approximate. The word x 1.3 heuristic is ~90% accurate for English. Anthropic doesn't publish Claude's tokenizer, so exact counts aren't possible without API calls.
Contributions welcome. The codebase is intentionally small (~1,200 lines of Python, zero dependencies). If your change adds a dependency, it needs a very strong justification.
git clone https://github.com/calesthio/SessionAnchor
cd SessionAnchor
pip install -e .
pytest tests/ -vGNU AGPL v3