Packmind
FreeNot checkedA second brain for Claude Code: project memory, estimated token & cost activity, semantic recall, and active guardrails.
About
A second brain for Claude Code: project memory, estimated token & cost activity, semantic recall, and active guardrails.
README
PackMind
A second brain for Claude Code.
Project memory, estimated token & cost activity, local semantic recall, and active guardrails - through lifecycle hooks and an MCP server. Zero workflow changes.
Contents
- What PackMind does
- Install and quick start
- How it works
- Lifecycle hooks
- MCP tools
- CLI reference
- What lives in .packmind/
- Configuration
- Scheduled maintenance
- Privacy
- Security
- Requirements
- Contributing
- License
What PackMind does
Claude Code works without persistent project context: it can't tell a 50-token
config from a 2,000-token module before opening it, re-reads the same files, and
forgets what it learned last session. PackMind fixes that with a small state
directory (.packmind/) maintained by lifecycle hooks, plus an MCP server that
exposes the project's memory as tools Claude can query directly.
- Project map - every file gets a one-line description, a token estimate, and
an estimated read cost, so Claude reads
map.mdinstead of opening files blind. - Estimated token & cost activity - fast local estimates always, priced per
model into a running dollar total. Exact reconciliation via Anthropic's
count-tokens API is opt-in (
packmind scan --exact), so nothing leaves your machine by default. - Local semantic recall - an on-device embedding index (nothing leaves your
machine) lets Claude
recall(...)past decisions, solutions, and code by meaning. - Active guardrails - a policy engine warns (or hard-blocks, opt-in) before a write touches a secret file or violates a project rule.
- Practice packs - installable sets of engineering reflexes (tests, CI, release
hygiene, security) that nudge at the right moment. Session-level checks like
"
src/**changed but no test written" can be satisfied with therecord_evidencetool so they stay quiet once you've done the thing. Manage withpackmind practice. - Lean mode - a reuse-first decision ladder that nudges Claude to build less
(
off/lite/full), with apackmind:shortcut convention you harvest viadebt. - Reversible compression - shelve a large non-source output (log, JSON, command dump)
with
compress(...)and pull the exact original back withretrieve(hash), to keep the session's context lean. - Session-aware - accounting and reminders are keyed to Claude's real session id, so
concurrent sessions and worktrees are tracked separately (no shared global file). Resume
and compaction continue a session,
/clearstarts a fresh one, and each closes into its own usage-ledger row onSessionEnd. - Live change intelligence - PackMind tracks the net set of files changed during a
session (add / modify / delete / rename) from ANY source - Write/Edit, Bash, generators,
parallel tool batches, or external editors - and keeps the map, recall, and practice checks
in sync with it. Inspect it with
packmind changesor thechangesMCP tool.
Install and quick start
npm install -g packmind # or: pnpm add -g packmind
cd your-project
packmind init # sets up .packmind/, hooks, and the MCP server
packmind index # builds the local semantic index (first run fetches the embed model)
Then use claude as normal - the hooks and MCP server do their work in the
background. To skip the optional local-recall dependency entirely (smaller,
CVE-clean install), use npm install -g packmind --omit=optional and set
recall.enabled: false.
Commit the durable brain files (map.md, knowledge.md, config.json,
policy.json) so your whole team shares the same project memory. See
What lives in .packmind/ for the full commit guide.
How it works
PackMind has three moving parts, all local:
- Lifecycle hooks - small, zero-dependency Node scripts copied into
.packmind/hooks/and registered in.claude/settings.json(tagged_managedBy: packmindso they are preserved and removable cleanly). Claude Code runs them on its own events (session start/end, prompt submit, before and after each Read/Write, and turn stop). They maintain the map, journal, usage ledger, and session state, and feed short reminders back into the model. - MCP server - registered in
.mcp.json, it exposes the brain as tools Claude can call directly (recall,remember,record_solution, and more). - State directory -
.packmind/, a set of plain files (Markdown + JSON) you can read, diff, and commit.
Nothing runs as a daemon and nothing opens a network port except the opt-in
packmind dashboard (loopback only). The CLI is how you inspect and maintain the
brain from the terminal.
Change-tracking coverage
Live change intelligence is event-assisted and reconciliation-backed: hook events make updates appear quickly, and reconciliation establishes correctness.
- Git projects reconcile in-process at the end of each turn, so Bash, generator,
parallel-batch, and external-editor changes are reflected in the net change set,
the map, recall, and practice checks - not just direct
Write/Editcalls. - Non-git projects capture a bounded file-fingerprint baseline at session start
and reconcile fully via that manifest when you run
packmind reconcileorpackmind maintain. (packmind changesis read-only - it displays the last reconciled set without recomputing.) - Only eligible files are tracked - the same secret, binary, size, and
(in git projects) gitignore rules as the project map; non-git manifest walks are
additionally bounded by
map.maxFiles. Ignored, secret, binary, oversized, symlinked-out-of-root, and out-of-root files never enter the change set. - External-edit watching (
FileChanged) depends on the host emitting watch paths; reconciliation, not file watching, is the completeness mechanism, so PackMind never claims to watch every possible future file or to prevent a change that a post-change hook only observes after it happened.
Lifecycle hooks
Installed into .packmind/hooks/ and wired into .claude/settings.json by
packmind init. Each is standalone and fail-safe (an error never blocks your
tool call).
| Event | Hook | What it does |
|---|---|---|
SessionStart |
session-start.js |
Opens or reattaches this session's record (keyed by the real session_id), injects the handoff note, a "check map.md first" reminder, and the session id into context. resume/compact continue the session; /clear folds the old one into the ledger and starts a fresh incarnation. |
UserPromptSubmit |
prompt-submit.js |
Lexically matches your prompt against recorded solutions and surfaces likely-relevant past fixes before Claude even calls a tool. |
PreToolUse: Read |
pre-read.js |
Before a read: warns if the file was already read unchanged this session (wasteful re-read), surfaces its map.md description + token estimate, and suggests compress() for large non-source files. |
PreToolUse: Write/Edit/MultiEdit |
pre-write.js |
Before a write: evaluates the guardrail policy (warn, or hard-block secrets/rules when enabled), surfaces relevant recorded solutions and knowledge.md never-do notes, and emits the lean-mode reuse nudge. |
PostToolUse: Read |
post-read.js |
After a read: reconciles the token and cost accounting for that file. |
PostToolUse: Write/Edit/MultiEdit |
post-write.js |
After a write: refreshes the file's map.md entry, appends to the journal, updates accounting, queues the file for recall re-embedding, and nudges after repeated edits to the same file. |
PostToolBatch |
post-tool-batch.js |
After a batch of (possibly parallel) tool calls: coalesces direct writes into change candidates and flags a reconcile when Bash, a file-writing MCP tool, or an unknown tool ran. Inspects tool names/inputs only, never the tool response. |
FileChanged |
file-changed.js |
A watched file changed on disk (add/change/unlink) outside the direct tools: records an eligible, in-root change candidate. Fires for the paths SessionStart emits via watchPaths. |
Stop |
stop.js |
End of each turn: reconciles the net change set (git), syncs map + recall, folds usage into the lifetime ledger, refreshes the handoff, and emits at-most-once reminders. |
SessionEnd |
session-end.js |
When a session ends: a final reconcile, folds into the ledger, then on a terminal end removes the live session file and refreshes the handoff; on resume it suspends and keeps the file. |
MCP tools
Registered automatically in .mcp.json. Claude can call:
| Tool | Purpose |
|---|---|
recall(query) |
Semantic search across knowledge, journal, solutions, and source code (uses the local vector index). |
remember(note, kind) |
Save a durable Preferences / Decisions / Never Do / Notes / Debt entry into knowledge.md. |
record_solution(error, cause, fix, tags, file?) |
Log a bug and its fix so it is never rediscovered; recording the same error again bumps its occurrence count. |
record_evidence(check, detail?, session_id?) |
Mark a practice check satisfied this session so its Stop-hook nudge stays quiet. Pass session_id (shown at SessionStart) when several sessions are active. |
project_map(filter?) |
List mapped files with descriptions and token estimates, optionally filtered. |
usage_report() |
Model, session count, reads/writes, tokens, and dollar cost for the project. |
insights() |
Estimated savings, map coverage, heaviest files, upkeep flags, and the compression store. |
handoff(action, content?) |
Read or update the session resume note (get / set). |
debt() |
List packmind: deferred-shortcut markers left in the code. |
changes(session_id?) |
The session's net change set (files different from session start, from any source) with per-file map and recall status. Read-only. |
review(base?) |
Package the current git diff with the lean decision ladder for an over-engineering review. |
compress(content, kind?) |
Shelve a large non-source output and get a compact, reversible preview plus a retrieval hash. |
retrieve(hash) |
Return the full original a compress call stored. |
CLI reference
Run any command inside a project (a directory with .packmind/). packmind <command> --help prints usage.
Setup and lifecycle
| Command | What it does |
|---|---|
packmind init |
Create .packmind/ (config + seed brain files + hooks), register the lifecycle hooks in .claude/settings.json, register the MCP server in .mcp.json, wire a snippet into CLAUDE.md, resolve the effective guard set, and run an initial map scan. Idempotent - safe to re-run. |
packmind update [--dry-run] [--list] [--project <name>] |
Update every registered project to the current PackMind version: snapshot first, re-copy the hooks, re-register, and refresh the effective guard set, all while preserving config.json. --dry-run shows what would change; --list lists registered projects; --project limits to one. |
packmind upgrade [--check] |
Upgrade PackMind itself to the latest published version: detect the package manager (npm/pnpm/yarn), install packmind@latest, then refresh registered projects via packmind update. --check only reports whether a newer version exists and prints the command to run. (Note: update refreshes projects; upgrade bumps the installed package.) |
packmind doctor |
Diagnose registered projects, hook installation, and MCP registration; report what is installed, stale, or missing. |
packmind mcp |
Run the MCP server over stdio. Claude Code invokes this for you - you rarely run it by hand. |
Map and accounting
| Command | What it does |
|---|---|
packmind scan [--check] [--exact] |
Rebuild map.md by walking the project (honoring .gitignore, secret globs, and size caps), describing each file with a token and cost estimate. --check exits 1 if the map is stale (for CI). --exact reconciles counts via Anthropic count-tokens (needs ANTHROPIC_API_KEY). |
packmind status |
Print token usage, dollar cost, session count, and project health from the usage ledger. |
packmind insights |
Show where tokens go and what PackMind saved: estimated savings, re-reads avoided, map coverage, heaviest files, upkeep flags, and the compression store. |
Memory and recall
| Command | What it does |
|---|---|
packmind index |
Build the local semantic recall index. The first run downloads the embedding model (cached under ~/.packmind/models); everything after is offline. |
packmind recall <query...> |
Semantic search across knowledge, journal, solutions, and source from the terminal. |
packmind solutions <term> |
Search recorded bug solutions by term. |
packmind debt |
List packmind: deferred-shortcut markers (the lean-mode debt ledger). |
Change intelligence
| Command | What it does |
|---|---|
packmind changes [--session <id>] [--json] |
Show the current session's net change set: files added, modified, deleted, or renamed since the session started, from any source, with per-file map and recall status. --session selects one when several are active; --json prints the raw ChangeSetV1. |
packmind reconcile [--session <id>] [--json] |
Force a full reconciliation (git status, or a file-fingerprint manifest for non-git projects) and synchronize the map and recall queue. Succeeds even when there are no changes. |
Guardrails and practices
| Command | What it does |
|---|---|
packmind policy check |
Lint policy.json guardrail rules and report any invalid entries. |
packmind practice list |
List the bundled practice packs and which are active. |
packmind practice add <pack> |
Activate a practice pack (adds its rules and session checks to the effective guard set). |
packmind practice remove <pack> |
Deactivate a practice pack. |
packmind practice explain <path> |
Show which rules and checks apply to a given path. |
Backups and maintenance
| Command | What it does |
|---|---|
packmind backup [--list] |
Snapshot .packmind/ to ~/.packmind/backups/<project>/<timestamp> (skipping the regenerable vector index). --list lists existing snapshots. |
packmind restore [timestamp] |
Restore .packmind/ from a backup. Takes a pre-restore snapshot and swaps atomically so a failed restore can't lose your brain. Omit the timestamp to list available backups. |
packmind maintain [--quiet] [--keep-backups <n>] |
One-shot upkeep: refresh the map, rebuild the recall index, archive an overgrown journal, and prune old backups and stale session files. --quiet for unattended runs; --keep-backups sets how many snapshots to keep (default 10). Cron-friendly. |
packmind dashboard [--port <port>] [--no-open] |
Launch the local web dashboard (Overview, Insights, Project Map, Journal, Recall, Config). Binds to loopback only and is token-protected. --port sets a preferred port (default 7878); --no-open skips auto-opening the browser. |
What lives in .packmind/
| File | Role | Commit? |
|---|---|---|
map.md |
File map with tokens & cost | yes |
knowledge.md |
Preferences, decisions, never-do list | yes |
identity.md |
Persistent project identity notes | yes |
config.json |
Configuration | yes |
policy.json |
Guardrail rules (your local overrides) | yes |
PACKMIND.md |
Protocol Claude follows | yes |
guard.effective.json |
Resolved guard set (default + packs + policy.json) | no (derived) |
journal.md |
Action log + session summaries | optional |
solutions.json |
Recorded fixes | optional |
usage.json |
Token & cost ledger | no (per-dev) |
handoff.md |
Session resume note | no (per-dev) |
state/sessions/ |
Per-session live state (keyed by session id) | no (per-dev) |
compress/ |
Reversible shelved-output store | no (per-dev) |
recall/ |
Local vector index | no (per-dev) |
Configuration
.packmind/config.json is deep-merged over defaults, so it survives packmind update and stays forward-compatible. Notable keys:
model- drives cost pricing (claude-opus-4-8by default).cost.exact- whenscanreconciles to exact counts:never(default, no network) |auto(exact whenANTHROPIC_API_KEYis set) |always. You can always force it per-run withpackmind scan --exact. Hooks always use the fast local estimate.cost.prices- override the built-in (approximate) per-model rates, e.g.{ "claude-opus-4-8": { "inputPerMTok": 5, "outputPerMTok": 25 } }. The defaults are best-effort; set this to your account's actual pricing.recall.enabled/recall.embedModel- local embeddings; fully offline.guard.blockSecrets- settrueto hard-block writes to secret files.guard.practices- active practice packs (e.g.quality-core,release-manager), managed withpackmind practice add|remove|list|explain.guard.lean.mode- the reuse-first nudge before writes:off|lite|full(defaultlite).map.respectGitignore,map.extraSecretGlobs- control what gets mapped.
Scheduled maintenance (no daemon)
Instead of a background daemon, PackMind ships a single maintain command you
schedule yourself - it refreshes the map, rebuilds the recall index, archives an
overgrown journal, and prunes old backups and stale sessions. Wire it into your
own scheduler:
# crontab -e - keep a project's brain fresh every night at 2am
0 2 * * * cd /path/to/project && packmind maintain --quiet
No persistent process, no open ports, no state to leak.
Privacy
Embeddings run locally via an on-device model cached under ~/.packmind/models;
your code is never sent anywhere for recall. The only optional network call is
Anthropic's count-tokens endpoint, off by default and used only when you opt into
exact counting (cost.exact other than never, or packmind scan --exact).
Security
- Dependency CVEs are scanned on every CI run (
pnpm audit): the build gates on the core/shipped tree at--audit-level=high; a full-tree audit runs as informational. - Core dependencies carry no known high/critical advisories. The only source
of transitive advisories is the optional local-recall dependency
(
@xenova/transformers), which bundles an older ML runtime. It is never required - install without it (npm install packmind --omit=optional) for a CVE-clean tree, or setrecall.enabled: false. Migrating recall to the maintained@huggingface/transformersis tracked future work. - Code scanning via CodeQL runs when the repository is public (or has GitHub Advanced Security); the workflow is skipped, not failed, otherwise.
- Found something? See the repo issues.
Requirements
- Node.js 20+
- Claude Code
Contributing
Issues and pull requests are welcome. Development uses pnpm and Vitest:
pnpm install
pnpm build # compiles the ESM library and the CommonJS hooks
pnpm test # runs the Vitest suite
See CONTRIBUTING.md and CODE_OF_CONDUCT.md.
License
Install Packmind in Claude Desktop, Claude Code & Cursor
unyly install packmindInstalls into Claude Desktop, Claude Code, Cursor & VS Code — handles npx, uvx and build-from-source repos for you.
First time? Get the CLI: curl -fsSL https://unyly.org/install | sh
Or configure manually
Run in your terminal:
claude mcp add packmind -- npx -y packmindFAQ
Is Packmind MCP free?
Yes, Packmind MCP is free — one-click install via Unyly at no cost.
Does Packmind need an API key?
No, Packmind runs without API keys or environment variables.
Is Packmind hosted or self-hosted?
Self-hosted: the server runs locally on your machine via the install command above.
How do I install Packmind in Claude Desktop, Claude Code or Cursor?
Open Packmind on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
GitHub
PRs, issues, code search, CI status
by GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
by mcpdotdirectCompare Packmind with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All development MCPs
