{"slug": "milepost-plain-markdown-long-term-memory-for-claude-code", "title": "Milepost – plain-Markdown long-term memory for Claude Code", "summary": "Milepost, a free open-source plugin for Claude Code, provides persistent long-term memory by automatically writing a plain-markdown diary of milestones, decisions, and status updates during sessions. The tool stores data in user-owned markdown files without databases or lock-in, enabling Claude to recall context across sessions for long-running projects.", "body_md": "### A milestone-triggered, in-session work diary that gives Claude Code persistent, plain-markdown memory across sessions — no database, no lock-in, fully greppable.\n\n**Keywords:** Claude Code memory · persistent memory for Claude Code · long-term memory plugin · AI agent diary · session memory · markdown work log · Claude Code plugin · agent context persistence · milestone logging\n\n**milepost** is a free, open-source [Claude Code](https://code.claude.com) plugin that turns Claude into an agent with a memory. As you work, Claude automatically writes a **diary of meaningful milestones** — completed deliverables, key decisions (and *why* they were made), blockers, and changes in direction — plus a living **STATUS.md** of where things stand. Everything is stored as **plain markdown files you own**, so you can `grep`\n\nit, `git`\n\nit, export it, or read it in any editor. No SQLite, no vector DB, no cloud, no lock-in.\n\nPick up a long-running task days or weeks later and Claude already knows what you did, what you decided, and what's next.\n\n```\n/plugin marketplace add sashamitrovich/milepost\n/plugin install milepost@milepost\n```\n\nClaude Code is brilliant within a session — and forgetful between them. Close the terminal and the reasoning, the decisions, the dead-ends you already ruled out are gone. For a quick edit that's fine. For a **project you return to over weeks**, it means re-explaining context every single time.\n\nExisting memory tools each force a trade-off:\n\n**Database-backed memory**(e.g. claude-mem) captures everything automatically — but your memory lives in SQLite + a vector store. Hard to read, harder to export, easy to get locked into.**Session-end / manual diaries**(e.g. claude-diary) write plain markdown — but only when*you*run a command, or after a session is already over.\n\nmilepost takes the third path: **plain markdown, written as you go, triggered by milestones — not by a clock, a command, or a database.**\n\nDeciding *\"a real milestone just happened\"* is a judgment call — and only the model can make it. So milepost isn't a dumb cron job; it's two cooperating parts:\n\n| Part | What it is | What it does |\n|---|---|---|\n🧠 Policy |\nA global instruction added to `~/.claude/CLAUDE.md` |\nTells Claude when a milestone is worth recording and how to write it — using its normal file tools, inline, while working. |\n⏱️ Nudge |\nA throttled `Stop` hook (default: once / 15 min) |\nQuietly reminds Claude to check for unrecorded milestones on long sessions, so logging stays consistent without nagging every turn. |\n📖 Recall |\nA read-only `SessionStart` hook |\nAt the start of every session, surfaces the current project's `STATUS.md` back into context (matched via a canonical, git-root-aware project slug), plus a one-line index of your other tracked projects — so prior work and next steps are visible without asking, and the injected context stays small no matter how many projects you track. Never writes to the diary. |\n🛡️ Secret guard |\nA `PreToolUse` hook on `Write` /`Edit` /`Bash` |\nMechanically blocks any diary write containing secret-shaped content (API keys, tokens, private keys, JWTs, credential assignments, URLs with embedded passwords) and tells Claude to rewrite the entry referencing secrets by location, never by value. The policy alone asks nicely; this enforces it. |\n\nThe result: **automatic, milestone-aware journaling** that doesn't interrupt your flow and doesn't depend on you remembering to run anything.\n\nPer project, in a folder you fully control:\n\n```\n~/.claude/memory/milepost/<project>/\n├── log.md        # append-only, timestamped milestone entries\n├── STATUS.md     # living snapshot: current goal, where things stand, what's next\n└── reflections/  # optional /reflect syntheses\n```\n\nA real entry looks like this:\n\n```\n## 2026-06-27 14:32 — Converted architect PDF to per-page JPEGs\n**Type:** deliverable\n**What:** Rendered all 4 A3 pages at 200 DPI with ImageMagick.\n**Why:** Client needed individual page images for review.\n**Next:** —\n```\n\nReadable by humans. Parseable by machines. Owned by you.\n\n- 🪶\n**Plain markdown, zero database**— greppable, git-friendly, exportable, future-proof. - 🎯\n**Milestone-triggered, not time-triggered**— high-signal entries, not noisy logs. - 🔁\n**In-session & automatic**— written*while*Claude works, not after you've closed the terminal. - 🌍\n**Works across every project**— one global install; per-project diaries. - 🧭\n**Living status file**— always know the current state and next step of any task. - 🛠️\n**Manual controls**—`/milepost`\n\n,`/status`\n\n,`/reflect`\n\nwhen you want them. - 🔒\n**Privacy-first, enforced**— policy tells Claude to summarize secrets, and a`PreToolUse`\n\nguard hook mechanically blocks secret-shaped content from ever landing in the diary. Per-project opt-out via a`.no-milepost`\n\nfile. - ↩️\n**Reversible & safe**— idempotent installer with automatic backups; clean uninstaller that keeps your data.\n\n**Option A — plugin install (recommended).** Inside Claude Code:\n\n```\n/plugin marketplace add sashamitrovich/milepost\n/plugin install milepost@milepost\n```\n\nEverything is wired natively: the commands, the nudge, the recall, and the secret guard load from the plugin, and the policy is injected at session start (your `CLAUDE.md`\n\nis never touched). First time Claude journals, approve the diary write with \"always allow\" — the plugin cannot pre-grant permissions for you. Remove with `/plugin uninstall milepost@milepost`\n\n; your diaries stay put.\n\n**Option B — script install.** For older Claude Code versions, or if you prefer the policy as a visible block in your own `CLAUDE.md`\n\nand pre-granted diary-write permissions:\n\n```\ngit clone https://github.com/sashamitrovich/milepost.git\ncd milepost && bash install.sh   # idempotent; backs up & merges, never overwrites\n```\n\nRemove with `bash uninstall.sh`\n\n— diaries stay put.\n\nUse\n\noneinstall mode, not both — running both duplicates the hooks (harmless but noisy). The diary location and format are identical either way, so you can switch modes without losing anything.\n\n| Command | What it does |\n|---|---|\n`/milepost [focus]` |\nForce a milestone entry right now. |\n`/status [update]` |\nShow — and refresh — the current status of this project's task. |\n`/reflect` |\nSynthesize progress, key decisions, and recurring themes from the log. |\n\n| Setting | Default | Description |\n|---|---|---|\n`MILEPOST_NUDGE_INTERVAL` |\n`900` (15 min) |\nMinimum seconds between nudges, per project. Raise it to journal less often; lower it to journal more. |\n`.no-milepost` file |\n— | Drop an empty `.no-milepost` file at a project's root to exclude that project entirely: no diary, no nudges, no recall. For client work or anything you'd rather keep out of the diary. |\n`MILEPOST_STRICT` |\n`0` |\nSet to `1` to make the secret guard also block near-secrets: IP addresses and e-mail addresses. Opt-in, because many legitimate diaries reference internal hosts. Set it where Claude Code's hooks see it — e.g. in `settings.json` under `\"env\": {\"MILEPOST_STRICT\": \"1\"}` or in your shell profile. |\n\nPrefer zero hooks? Skip the nudge entirely — the `CLAUDE.md`\n\npolicy works on its own; it just leans on the model to remember during very long sessions.\n\nmilepost |\nclaude-mem | claude-diary | |\n|---|---|---|---|\n| Storage | Plain markdown |\nSQLite + vector DB | Plain markdown |\n| Greppable / exportable | ✅ | ✅ | |\nWrites during a session |\n✅ | ✅ | ❌ |\n| Milestone-aware (high-signal) | ✅ | ||\n| Trigger | Milestones |\nContinuous | Manual / pre-compact |\n| Living status file | ✅ | ❌ | ❌ |\n| Database required | No |\nYes | No |\n\nHonest caveat: milestone detection is a\n\njudgment, so it's best-effort — it may occasionally over- or under-log, and entries use a little of your working session's tokens.`/milepost`\n\nis the manual backstop.\n\nUse a plugin that persists context to durable, portable storage. **milepost** does this with plain-markdown files written as you work, so your memory is readable, greppable, and never locked inside a database.\n\nNot on its own. Claude Code is stateless across sessions beyond `CLAUDE.md`\n\n. milepost adds true cross-session memory by journaling milestones and a live status file that Claude reads back later.\n\nclaude-mem captures everything into a SQLite + vector database. milepost stores **high-signal milestones as plain markdown** — easier to read, version, export, and trust, with nothing to lock into.\n\nNo. Everything stays in local markdown files under `~/.claude/memory/milepost/`\n\n. No database, no cloud, no telemetry.\n\nDefense in depth, not just a polite instruction:\n\n**Policy**— Claude is told to reference secrets by location only (\"token stored in`.ha_token`\n\n\"), never by value, and to minimize near-secrets (internal IPs, serials, third-party personal data).**Guard hook**— a`PreToolUse`\n\nhook scans every write targeting the diary directory (including shell redirection via`Bash`\n\n) and*denies*anything matching secret patterns: private-key blocks, AWS/GitHub/Slack/Google/`sk-`\n\n-style keys, JWTs, bearer tokens,`password=`\n\n/`api_key:`\n\n-style assignments, URLs with embedded credentials, plus a**high-entropy catch-all** for unknown token formats (≥32-char base64url-ish runs mixing upper/lower/digits — tuned so git SHAs, UUIDs, paths, and identifiers don't trip it).**Strict mode**—`MILEPOST_STRICT=1`\n\nadditionally blocks IP addresses and e-mail addresses, for client work and privacy-sensitive setups.**Audit**— you can scan existing diaries anytime:`bash ~/.claude/hooks/milepost-secret-scan.sh < ~/.claude/memory/milepost/<project>/log.md`\n\n(exit 1 + pattern names on a hit).**Opt-out**— a`.no-milepost`\n\nfile at a project's root keeps that project out of the diary entirely.\n\nDiaries are plaintext markdown, owned by you. The installer restricts `~/.claude/memory/milepost/`\n\nto owner-only access (`chmod 700`\n\n). There is deliberately **no at-rest encryption**: milepost's whole design is that Claude reads and writes the diary with its ordinary file tools, and encrypting it would break that (and your greppability) while adding key management — use full-disk encryption (FileVault/LUKS/BitLocker), which covers the stolen-device case properly. Treat the diary dir like your shell history: local, private, never committed or synced to shared storage.\n\nThe theoretical risk with any memory system: instructions hidden in a repo's files could ask the agent to copy remembered content somewhere it doesn't belong (prompt injection). milepost's policy explicitly forbids copying diary contents into project files or external services, and the diary only ever contains milestone summaries — not credentials (see the guard above). For projects where even summaries are sensitive, use `.no-milepost`\n\nso there is nothing to leak. Review what agents write, as always.\n\nNo. The installer adds two narrowly-scoped permission allow-rules to `settings.json`\n\n— `Edit(~/.claude/memory/milepost/**)`\n\nand `Write(~/.claude/memory/milepost/**)`\n\n— so Claude can journal without prompting you each time. The grant is limited to the milepost memory directory and nothing else; `uninstall.sh`\n\nremoves it.\n\nYes. The installer is idempotent, backs up `settings.json`\n\nand `CLAUDE.md`\n\nbefore editing, and merges rather than overwrites. `uninstall.sh`\n\nremoves the wiring (hooks, policy block, and the scoped write permissions) and leaves your diaries intact.\n\nYes — milepost is language- and framework-agnostic. It journals your work, not your code, so it works for software, writing, research, or any long-running task in Claude Code.\n\n- 👩💻\n**Developers** juggling long-lived projects who are tired of re-explaining context. - 🔬\n**Researchers & analysts** who want a durable, citable trail of decisions and rationale. - 🤖\n**AI agent builders** who need transparent, inspectable, file-based agent memory. - 🗂️\n**Anyone** who wants their AI's memory to be*theirs*— plain text, on disk, forever.\n\nIssues and PRs welcome. milepost is intentionally small and hackable — the entire behavior lives in one policy file, three command prompts, and five short hook scripts.\n\n[MIT](/sashamitrovich/milepost/blob/main/LICENSE) © Saša Mitrović\n\n**milepost** · persistent, plain-markdown, milestone-triggered memory for Claude Code.\nIf it saves you from re-explaining your project one more time, give it a ⭐.", "url": "https://wpnews.pro/news/milepost-plain-markdown-long-term-memory-for-claude-code", "canonical_source": "https://github.com/sashamitrovich/milepost", "published_at": "2026-07-15 06:53:05+00:00", "updated_at": "2026-07-15 07:18:03.651587+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-tools", "ai-products"], "entities": ["Milepost", "Claude Code", "Anthropic"], "alternates": {"html": "https://wpnews.pro/news/milepost-plain-markdown-long-term-memory-for-claude-code", "markdown": "https://wpnews.pro/news/milepost-plain-markdown-long-term-memory-for-claude-code.md", "text": "https://wpnews.pro/news/milepost-plain-markdown-long-term-memory-for-claude-code.txt", "jsonld": "https://wpnews.pro/news/milepost-plain-markdown-long-term-memory-for-claude-code.jsonld"}}