{"slug": "show-hn-pentimento-status-and-lineage-for-your-coding-agent-s-plan-files", "title": "Show HN: Pentimento – status and lineage for your coding agent's plan files", "summary": "A developer released Pentimento, an open-source command-line tool installable via `pip install pentimento` that derives status, intent and lineage for plan files left behind by Claude Code, Cursor and Antigravity, whose default plans directory is `~/.claude/plans` and is overridden with the `AGENT_PLANS_DIR` environment variable. Pentimento adds a `superseded` status that no derivation produces or overwrites, plus a `pentimento hook` to keep plan state current as an agent writes and a `prior-plans` skill that has the agent search every project's plans before proposing a change. The tool is built with Claude Code and targets the case where hundreds of randomly named plan files no longer reveal which finished, which still matter, or which plan replaced which.", "body_md": "Status, intent, and lineage for Claude Code, Cursor, and Antigravity plan files.\n\nClaude Code, Cursor, and Antigravity leave plan files behind. After a few hundred of them you cannot tell which finished, which you still care about, or which plan replaced which — the filenames are random and the files say nothing about their own state. pentimento derives that state and gives you a CLI to list, filter, and render the lot as a lineage tree.\n\nThree kinds of plan are worth finding again:\n\n- The long one: an infrastructure migration designed over months grows\nsubplans, absorbs decisions made in discussion, and leaves behind the\nbranches you rejected — the part you want back a quarter later. A\nsuperseded plan is a decision record, not garbage, which is why\n`superseded` is the one status no derivation produces or overwrites;`tree <id>` brings the whole thread back, tags or no tags.\n- The finished one that is not over: execution ends with findings you will\nnot act on today. Tag it and set an intent, and `list --tag` or`list --starred` brings it back when you are ready to pick the thread up\nagain.\n- The one that already answered your question: a plan from another project\nholds the reasoning behind a decision your current change would undo — why\na CI matrix was cut, why one service avoids a library. A memory exists only\nif an agent chose to write one, and project docs only if you did; a plan\nexists whenever a decision was planned. `list --title` and`list --grep` search every project's plans at once, and the[`prior-plans` skill](https://github.com/kjiwa/pentimento/blob/main/docs/integrations.md#prior-plans-skill) has the agent run that search itself before it proposes a change.\n\nIn harness-engineering terms, plans are the state layer: what one session\nleaves for the next. `pentimento hook` keeps that state current as the agent\nwrites it, and the `prior-plans` skill has the agent read it back.\n\nA pentimento is the earlier composition showing through a repainted canvas; that is what a plans directory is.\n\nBuilt with [Claude Code](https://claude.com/claude-code).\n\n```\npip install pentimento\n# or from source:\npip install git+https://github.com/kjiwa/pentimento.git\n```\n\nTab completion for `bash`, `zsh`, and `fish` is in\n[docs/reference.md#shell-completion](https://github.com/kjiwa/pentimento/blob/main/docs/reference.md#shell-completion).\n\nPoint `AGENT_PLANS_DIR` at your plans directory (it defaults to\n`~/.claude/plans`), then:\n\n```\npentimento list          # see the corpus; derived fields show without backfill\npentimento backfill      # persist derived fields so they outlive the transcripts\npentimento set some-plan-id --intent active\npentimento list --starred\n```\n\nTo park a finished plan you mean to return to, tag it and set an intent, then find it by tag later:\n\n```\npentimento set some-plan-id --add-tag auth --intent someday\npentimento list --tag auth\n```\n\nTo pull one thread of subplans back out by lineage, rather than by tag:\n\n```\npentimento tree some-plan-id\npentimento tree some-plan-id --ancestors\n```\n\nTo find how an earlier decision was made, search titles (or titles and bodies) across every project, then reopen the plan; to see what you finished recently, filter by date:\n\n```\npentimento list --title 'github actions|\\bGHA\\b'\npentimento list --grep 'concurrency group' --status complete\npentimento show some-plan-id --full\npentimento list --status complete --since 1w\n```\n\n[docs/workflows.md](https://github.com/kjiwa/pentimento/blob/main/docs/workflows.md)\nwalks each of these end to end.\n\nSources and their default directories are covered in\n[docs/integrations.md](https://github.com/kjiwa/pentimento/blob/main/docs/integrations.md);\nCursor's and Antigravity's rules and caveats are in the\n[Cursor](https://github.com/kjiwa/pentimento/blob/main/docs/integrations.md#cursor) and\n[Antigravity](https://github.com/kjiwa/pentimento/blob/main/docs/integrations.md#antigravity) sections.\n\nThe samples below are regenerated by `sh demo/capture.sh`.\n\n`PLAN` shows the [short\nid](https://github.com/kjiwa/pentimento/blob/main/docs/reference.md#plan-ids),\nsuch as `auth-rollout` for `api-auth-rollout`. `--columns` (or\n`PENTIMENTO_COLUMNS`) chooses which columns show and in what order; see\n[Columns](https://github.com/kjiwa/pentimento/blob/main/docs/reference.md#columns).\n`list` and `tree` share their filters, listed in the\n[synopsis](https://github.com/kjiwa/pentimento/blob/main/docs/reference.md#commands).\n\n```\nPLAN                  STATUS       INTENT     PROJECT   SOURCE  TITLE                           TAGS             CREATED     UPDATED\nstyle-guide           superseded   abandoned  platform  claude  Write a docs style guide                         2026-07-31       6w\nauth-redesign         complete     abandoned  platform  claude  Redesign the auth API           [auth, +1]       2026-08-05       5w\ndunning-copy          complete     someday    billing   claude  Rewrite dunning email copy      [billing]        2026-08-20       3w\nauth-rollout          partial      active     platform  claude  Roll out the new auth API       [auth, +1]       2026-08-25       2w\nauth-cleanup          not-started  queued     platform  claude  Remove the old auth API         [auth, +1]       2026-08-30       2w\nauth-docs             not-started  unset      platform  claude  Document the new auth API                        2026-09-02       1w\ninvoice-retry         unknown      unset      billing   claude  Retry failed invoice charges    [billing]        2026-09-04       1w\nrelevance-tuning      not-started  active     billing   claude  Tune search relevance           [search]         2026-09-09       5d\nonboarding-checklist  not-started  unset                claude  Write the onboarding checklist                   2026-09-13       1d\n\n9 plans\n```\n\nBelow the table threshold, `list` stacks each plan into a record; see\n[the layout rule](https://github.com/kjiwa/pentimento/blob/main/docs/reference.md#columns).\n\n```\nWrite a docs style guide\n  style-guide  superseded  abandoned  platform  claude  2026-07-31  6w\nRedesign the auth API\n  auth-redesign  complete  abandoned  platform  claude  [auth, security]\n  2026-08-05  5w\nRewrite dunning email copy\n  dunning-copy  complete  someday  billing  claude  [billing]  2026-08-20  3w\nRoll out the new auth API\n  auth-rollout  partial  active  platform  claude  [auth, security]  2026-08-25\n  2w\nRemove the old auth API\n  auth-cleanup  not-started  queued  platform  claude  [auth, security]\n  2026-08-30  2w\nDocument the new auth API\n  auth-docs  not-started  unset  platform  claude  2026-09-02  1w\nRetry failed invoice charges\n  invoice-retry  unknown  unset  billing  claude  [billing]  2026-09-04  1w\nTune search relevance\n  relevance-tuning  not-started  active  billing  claude  [search]  2026-09-09\n  5d\nWrite the onboarding checklist\n  onboarding-checklist  not-started  unset  claude  2026-09-13  1d\n\n9 plans\n```\n\nPlans nested under their parents, grouped by project. Plain `tree` renders\nthe whole corpus this way; `tree <id>` roots it at one plan instead — that\nplan plus everything beneath it (see\n[`tree <id>`](https://github.com/kjiwa/pentimento/blob/main/docs/reference.md#flags)).\n`--ancestors` also walks up to `<id>`'s topmost\nancestor, spine only, for pulling a single thread out of a larger forest.\n\n```\n(no project)\n`-- Write the onboarding checklist\n      onboarding-checklist  not-started  unset  2026-09-13  1d\n\nbilling\n|-- Rewrite dunning email copy\n|     dunning-copy  complete  someday  [billing]  2026-08-20  3w\n|-- Retry failed invoice charges\n|     invoice-retry  unknown  unset  [billing]  2026-09-04  1w  (parent elided: no-such-plan)\n`-- Tune search relevance\n      relevance-tuning  not-started  active  [search]  2026-09-09  5d\n\nplatform\n|-- Write a docs style guide\n|     style-guide  superseded  abandoned  2026-07-31  6w\n`-- Redesign the auth API\n      auth-redesign  complete  abandoned  [auth, security]  2026-08-05  5w\n    `-- Roll out the new auth API\n          auth-rollout  partial  active  [auth, security]  2026-08-25  2w\n        |-- Remove the old auth API\n        |     auth-cleanup  not-started  queued  [auth, security]  2026-08-30  2w\n        `-- Document the new auth API\n              auth-docs  not-started  unset  2026-09-02  1w\n\n9 plans\nplatform\n`-- Redesign the auth API\n      auth-redesign  complete  abandoned  [auth, security]  2026-08-05  5w\n    `-- Roll out the new auth API\n          auth-rollout  partial  active  [auth, security]  2026-08-25  2w\n        |-- Remove the old auth API\n        |     auth-cleanup  not-started  queued  [auth, security]  2026-08-30  2w\n        `-- Document the new auth API\n              auth-docs  not-started  unset  2026-09-02  1w\n\n4 of 9 plans\n# Roll out the new auth API\n\nid: api-auth-rollout\npath: ~/.claude/plans/api-auth-rollout.md\nstatus: partial   intent: active   tags: [auth, security]\nparent: api-auth-redesign   project: platform\ncreated: 2026-08-25   source: claude   modified: 2026-08-25 12:30\n\nProgress\n\n[x] Ship behind a feature flag\n[ ] Flip the flag for all tenants\n\nContext\n\nTenants opt in via the auth_v2 flag in tenant_settings. Watch error rates before flipping the\nremaining cohort. See the rollout runbook.\n\nCohort    Status\ninternal  complete\nbeta      in progress\n```\n\n`check` validates the whole corpus and exits 1 on any finding; it takes no\nplan id. `PLAN` uses the short id, and a line under the summary gives the fix\nfor each `CODE`. `--format json|tsv` emits the full id in `id` and the fix in\n`hint`. To work through findings, see\n[Working through `check`](https://github.com/kjiwa/pentimento/blob/main/docs/workflows.md#working-through-check);\n[docs/troubleshooting.md](https://github.com/kjiwa/pentimento/blob/main/docs/troubleshooting.md#check-findings)\nexplains each `CODE`.\n\n```\nCODE                   PLAN           MESSAGE\ndangling-parent        invoice-retry  parent 'no-such-plan' does not resolve to a plan\nunderivable-status     invoice-retry  '## Progress' has no checkboxes or recognized phrase\nstatus-behind-history  auth-cleanup   status 'not-started' but 1 later session worked this plan\nunadopted-tag          auth-docs      no tags, but its thread carries [auth, security]\n\n9 plans checked, 4 findings\ndangling-parent: pentimento set <id> --parent <id>, or --clear-parent\nstatus-behind-history: tick the plan's '## Progress', or pentimento history <id>, then pentimento set <id>\n  --status <value> (pins)\nunadopted-tag: pentimento set <id> --add-tag <tag>\nunderivable-status: add a checklist to '## Progress', or pentimento show <id>, then pentimento set <id>\n  --status <value>\nnarrow with: pentimento list --finding <code>\n```\n\n`history` shows which sessions touched a plan's file. The session whose id\nmatches the plan's own id, or failing that the session whose first touch\nwrote the plan, is `authored`; any later session that edited, wrote, or\ndelegated work on it is `worked`; one that only read it is `read`. Only Claude\nCode transcripts feed `history`.\nFor an empty result, see\n[`history` is empty](https://github.com/kjiwa/pentimento/blob/main/docs/troubleshooting.md#history-is-empty).\n\n```\nWHEN              WHAT      SESSION                                TOUCHES\n2026-08-30 12:30  authored  auth-cleanup                                 1\n2026-09-11 12:30  worked    implement-api-auth-cleanup-eager-wolf        1\n2026-09-13 12:30  read      review-api-auth-cleanup-calm-fox             1\n---\npentimento:\n  status: not-started | partial | complete | superseded | unknown\n  pinned: true                  # omitted unless set\n  intent: active | queued | someday | abandoned | unset\n  tags: [auth, security]        # omitted if untagged\n  parent: some-other-plan-id    # omitted for roots\n  project: platform             # omitted if undetermined\n  created: 2026-09-08\n---\n```\n\nThe vocabulary lives in one place:\n[pentimento/vocabulary.py](https://github.com/kjiwa/pentimento/blob/main/pentimento/vocabulary.py).\n\n| Field | Set by | How | \n|---|---|---|\n| `status` | derived | Views derive it live from status signals, first match wins; `backfill` (including the per-write`pentimento hook` , which[caps it at `partial`](https://github.com/kjiwa/pentimento/blob/main/docs/reference.md#flags) ) persists it:`## Progress` , then a Cursor plan's`todos:` , then checkboxes elsewhere in the body.`set --status` overrides it directly and pins it (see`pinned` ); it is the only way to set`superseded` , which no derivation produces or overwrites. | \n| `pinned` | operator | Never derived. `set --status` sets it to`true` automatically;`set --unpin` clears it. While set,`backfill` (with or without`--rederive` ) leaves`status` untouched; see[`check` findings](https://github.com/kjiwa/pentimento/blob/main/docs/troubleshooting.md#check-findings) for what`check` still reports. | \n| `intent` | operator | Shown as `unset` until set;`backfill` writes`unset` the first time it sees the plan, then leaves it alone. Only`set --intent` changes it after that. | \n| `tags` | operator | Never derived or written; `check` suggests them (`unadopted-tag` ).`set --add-tag` /`--remove-tag` /`--clear-tags` ; filter with`list` /`tree --tag` , which ANDs repeated tags. | \n| `parent` | derived, or operator | Views derive it from a plan reference and `backfill` persists it (see[`parent` is empty](https://github.com/kjiwa/pentimento/blob/main/docs/troubleshooting.md#parent-is-empty) ).`--rederive` recomputes it from scratch: it replaces a parent set with`set --parent` by the derived one, or removes it when no reference resolves.`set --parent` /`--clear-parent` set or clear it directly;`set --parent` rejects a value that would create a cycle. Read the chain back with`tree <id>` /`tree <id> --ancestors` . | \n| `project` | derived, or operator | Views derive it from a session's `cwd` and`backfill` persists it, which keeps it after Claude Code prunes the transcript (a Cursor or Antigravity plan's: see[Cursor](https://github.com/kjiwa/pentimento/blob/main/docs/integrations.md#cursor) and[Antigravity](https://github.com/kjiwa/pentimento/blob/main/docs/integrations.md#antigravity) ).`set --project` /`--clear-project` set or clear it directly;`--project .` resolves to the current directory's name. | \n| `created` | derived once | A local date, derived by views and persisted once by `backfill` , then immutable except through`backfill --recreate` . | \n| `modified` | derived, not stored | Not a frontmatter field: `max(session end time, file mtime)` . Neither`backfill` nor`set` bumps it when the write only touches frontmatter bookkeeping. | \n\nLineage and source discovery are covered in full in\n[docs/integrations.md](https://github.com/kjiwa/pentimento/blob/main/docs/integrations.md)\nand\n[docs/troubleshooting.md](https://github.com/kjiwa/pentimento/blob/main/docs/troubleshooting.md).\nCursor plans get `project` and prompt lineage from Cursor's agent transcripts,\nmatched by name; a `stop` hook keeps their status current. The\n[matching rule](https://github.com/kjiwa/pentimento/blob/main/docs/integrations.md#cursor)\nis in the integrations guide.\nAntigravity plans read their own conversation's transcript, so they need no\nmatching, and a `PostToolUse` hook keeps their status current\n([setup](https://github.com/kjiwa/pentimento/blob/main/docs/integrations.md#antigravity)).\n\n| Command | Does | \n|---|---|\n| `list` | flat table of plans | \n| `tree [<id>]` | lineage tree, grouped by project | \n| `show <id>` | H1, frontmatter, and the rendered body | \n| `set <id>...` | rewrite frontmatter in place | \n| `backfill` | gap-fill intent/created/project/parent; advance status | \n| `hook` | run as a PostToolUse hook; reads the payload on stdin | \n| `index` | write INDEX.md into the plans directory | \n| `check` | validate lineage, vocabulary, status, and tags; exits 1 on any finding | \n| `history <id>` | session-touch history for a plan | \n| `completion <shell>` | print a shell integration script | \n\nFull flags for every command, plus the environment variables, are in\n[docs/reference.md](https://github.com/kjiwa/pentimento/blob/main/docs/reference.md).\n\npentimento is built for one operator's corpus on one machine. Shared,\nconcurrent, or multi-author planning is out of scope and not a gap this tool\nintends to close — `project`, prompt lineage, and `modified` are all\nderived from local Claude Code transcripts, and deriving them across authors\nwould need a different source, a sync, and an identity model.\n\nKeeping the plans directory in git does get you review and history, and part\nof the derived state travels with the files: `status`, operator-set\nfrontmatter, and body-referenced `parent` survive a checkout anywhere;\n`project`, prompt-derived `parent`, and session history do not. See\n[docs/workflows.md](https://github.com/kjiwa/pentimento/blob/main/docs/workflows.md)\nfor the details, and `pentimento index` for an `INDEX.md` worth committing.\n\n[ccplan](https://github.com/sorafujitani/ccplan) and\n[planc](https://github.com/jakebf/planc) track Claude Code plans by a status\nyou set by hand, ccplan in a sidecar file and planc in frontmatter through a\nTUI. [claude-plan-viewer](https://github.com/HelgeSverre/claude-plan-viewer)\nbrowses and searches them in a web UI.\n[planning-with-files](https://github.com/OthmanAdi/planning-with-files) keeps\nan agent's plan on disk while it works and recovers it after `/clear` or\ncompaction; it manages the files it creates, not a directory of finished\nones. None of them records which plan replaced which. pentimento reads a\ncorpus it did not author and derives status, project, and parent across it.\nThe longer comparison is in\n[Managing Claude Code plan files](https://dev.to/kjiwa/managing-claude-code-plan-files-lineage-status-and-existing-tools-37b6).\n\nStdlib-only Python 3.9+, zero runtime dependencies, no PyYAML.\n\npentimento enriches `modified` and lineage by reading Claude Code's session\ntranscripts (`AGENT_SESSIONS_DIR`, default `~/.claude/projects`) and Cursor's\nagent transcripts (`CURSOR_SESSIONS_DIR`, default `~/.cursor/projects`), and\nAntigravity's conversation transcripts (next to each plan under\n`ANTIGRAVITY_BRAIN_DIR`, default `~/.gemini/antigravity/brain`), all\nundocumented, private formats. If a format changes, or the transcripts are\nabsent, this enrichment degrades to file mtimes and plain body/preamble\nreferences — it does not break, and the frontmatter itself stays plain,\nhand-editable markdown either way.\n\nSetup, checks, and CI are in\n[CONTRIBUTING.md](https://github.com/kjiwa/pentimento/blob/main/CONTRIBUTING.md).\n\n- [docs/reference.md](https://github.com/kjiwa/pentimento/blob/main/docs/reference.md) — every command's full flags, and the environment variables.\n- [docs/integrations.md](https://github.com/kjiwa/pentimento/blob/main/docs/integrations.md) — wiring`backfill` and`pentimento hook` into Claude Code, Cursor, and Antigravity, a\nslash command, a skill that searches past plans before a new one, a\ntriage-nudge pattern,`check` in CI.\n- [docs/workflows.md](https://github.com/kjiwa/pentimento/blob/main/docs/workflows.md) — triage, picking a plan back up, reusing a past decision, supersession,\nlineage trees, working through`check` , scripting with`--format json` .\n- [docs/troubleshooting.md](https://github.com/kjiwa/pentimento/blob/main/docs/troubleshooting.md) — every empty field and`check` finding, explained.", "url": "https://wpnews.pro/news/show-hn-pentimento-status-and-lineage-for-your-coding-agent-s-plan-files", "canonical_source": "https://github.com/kjiwa/pentimento", "published_at": "2026-11-10 13:44:19+00:00", "updated_at": "2026-11-10 13:53:27.527333+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "ai-products"], "entities": ["Pentimento", "Claude Code", "Cursor", "Antigravity", "pip", "AGENT_PLANS_DIR"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/show-hn-pentimento-status-and-lineage-for-your-coding-agent-s-plan-files", "markdown": "https://wpnews.pro/news/show-hn-pentimento-status-and-lineage-for-your-coding-agent-s-plan-files.md", "text": "https://wpnews.pro/news/show-hn-pentimento-status-and-lineage-for-your-coding-agent-s-plan-files.txt", "jsonld": "https://wpnews.pro/news/show-hn-pentimento-status-and-lineage-for-your-coding-agent-s-plan-files.jsonld"}}