Skip to main content

pentimento

Status, intent, and lineage for Claude Code and Cursor plan files.

check PyPI Python versions

demo

Claude Code and Cursor 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.

Three kinds of plan are worth finding again:

  • The long one: an infrastructure migration designed over months grows subplans, absorbs decisions made in discussion, and leaves behind the branches you rejected — the part you want back a quarter later. A superseded plan is a decision record, not garbage, which is why superseded is the one status no derivation produces or overwrites; tree <id> brings the whole thread back, tags or no tags.
  • The finished one that is not over: execution ends with findings you will not 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 again.
  • The one that already answered your question: a plan from another project holds the reasoning behind a decision your current change would undo — why a CI matrix was cut, why one service avoids a library. A memory exists only if an agent chose to write one, and project docs only if you did; a plan exists whenever a decision was planned. list --title and list --grep search every project's plans at once, and the prior-plans skill has the agent run that search itself before it proposes a change.

A pentimento is the earlier composition showing through a repainted canvas; that is what a plans directory is.

Built with Claude Code.

Install

pip install pentimento
# or from source:
pip install git+https://github.com/kjiwa/pentimento.git

Tab completion for bash, zsh, and fish is in docs/reference.md#shell-completion.

Quick start

Point AGENT_PLANS_DIR at your plans directory (it defaults to ~/.claude/plans), then:

pentimento backfill      # derive status/intent/created/parent/project once
pentimento list          # see the corpus
pentimento set some-plan-id --intent active
pentimento list --starred

To park a finished plan you mean to return to, tag it and set an intent, then find it by tag later:

pentimento set some-plan-id --add-tag auth --intent someday
pentimento list --tag auth

To pull one thread of subplans back out by lineage, rather than by tag:

pentimento tree some-plan-id
pentimento tree some-plan-id --ancestors

To 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:

pentimento list --title 'github actions|\bGHA\b'
pentimento list --grep 'concurrency group' --status complete
pentimento show some-plan-id --full
pentimento list --status complete --since 1w

docs/workflows.md walks each of these end to end.

Sources and their default directories are covered in docs/integrations.md; Cursor's caveats are in docs/troubleshooting.md.

The samples below are regenerated by sh demo/capture.sh.

list

PLAN shows the short id, such as abundant-rabbit for is-it-possible-to-abundant-rabbit. Below the width a table needs, each plan prints as a short record with every field kept; --columns (or PENTIMENTO_COLUMNS) chooses which columns show and in what order; see Columns. list and tree share their filters, listed in the synopsis.

PLAN                  STATUS       INTENT     PROJECT   SOURCE  TITLE                           TAGS             CREATED     UPDATED
style-guide           superseded   abandoned  platform  claude  Write a docs style guide                         2026-07-31       6w
auth-redesign         complete     abandoned  platform  claude  Redesign the auth API           [auth, +1]       2026-08-05       5w
dunning-copy          complete     someday    billing   claude  Rewrite dunning email copy      [billing]        2026-08-20       3w
auth-rollout          partial      active     platform  claude  Roll out the new auth API       [auth, +1]       2026-08-25       2w
auth-cleanup          not-started  queued     platform  claude  Remove the old auth API         [auth, +1]       2026-08-30       2w
auth-docs             not-started  unset      platform  claude  Document the new auth API                        2026-09-02       1w
invoice-retry         unknown      unset      billing   claude  Retry failed invoice charges    [billing]        2026-09-04       1w
relevance-tuning      not-started  active     billing   claude  Tune search relevance           [search]         2026-09-09       5d
onboarding-checklist  unknown      unset                claude  Write the onboarding checklist                   2026-09-13       1d

9 plans

Below the table threshold, list stacks each plan and drops nothing; see the layout rule.

Write a docs style guide
  style-guide  superseded  abandoned  platform  claude  2026-07-31  6w
Redesign the auth API
  auth-redesign  complete  abandoned  platform  claude  [auth, security]
  2026-08-05  5w
Rewrite dunning email copy
  dunning-copy  complete  someday  billing  claude  [billing]  2026-08-20  3w
Roll out the new auth API
  auth-rollout  partial  active  platform  claude  [auth, security]  2026-08-25
  2w
Remove the old auth API
  auth-cleanup  not-started  queued  platform  claude  [auth, security]
  2026-08-30  2w
Document the new auth API
  auth-docs  not-started  unset  platform  claude  2026-09-02  1w
Retry failed invoice charges
  invoice-retry  unknown  unset  billing  claude  [billing]  2026-09-04  1w
Tune search relevance
  relevance-tuning  not-started  active  billing  claude  [search]  2026-09-09
  5d
Write the onboarding checklist
  onboarding-checklist  unknown  unset  claude  2026-09-13  1d

9 plans

tree

Plans nested under their parents, grouped by project. Plain tree renders the whole corpus this way; tree <id> roots it at one plan instead — that plan plus everything beneath it, resolved against the whole corpus, so --project is unnecessary. --ancestors also walks up to <id>'s topmost ancestor, spine only, for pulling a single thread out of a larger forest.

(no project)
`-- Write the onboarding checklist
      onboarding-checklist  unknown  unset  2026-09-13  1d

billing
|-- Rewrite dunning email copy
|     dunning-copy  complete  someday  [billing]  2026-08-20  3w
|-- Retry failed invoice charges
|     invoice-retry  unknown  unset  [billing]  2026-09-04  1w  (parent elided: no-such-plan)
`-- Tune search relevance
      relevance-tuning  not-started  active  [search]  2026-09-09  5d

platform
|-- Write a docs style guide
|     style-guide  superseded  abandoned  2026-07-31  6w
`-- Redesign the auth API
      auth-redesign  complete  abandoned  [auth, security]  2026-08-05  5w
    `-- Roll out the new auth API
          auth-rollout  partial  active  [auth, security]  2026-08-25  2w
        |-- Remove the old auth API
        |     auth-cleanup  not-started  queued  [auth, security]  2026-08-30  2w
        `-- Document the new auth API
              auth-docs  not-started  unset  2026-09-02  1w

9 plans
platform
`-- Redesign the auth API
      auth-redesign  complete  abandoned  [auth, security]  2026-08-05  5w
    `-- Roll out the new auth API
          auth-rollout  partial  active  [auth, security]  2026-08-25  2w
        |-- Remove the old auth API
        |     auth-cleanup  not-started  queued  [auth, security]  2026-08-30  2w
        `-- Document the new auth API
              auth-docs  not-started  unset  2026-09-02  1w

4 of 9 plans

show

# Roll out the new auth API

id: api-auth-rollout
path: ~/.claude/plans/api-auth-rollout.md
status: partial   intent: active   tags: [auth, security]
parent: api-auth-redesign   project: platform
created: 2026-08-25   source: claude   modified: 2026-08-25 12:30

Progress

[x] Ship behind a feature flag
[ ] Flip the flag for all tenants

Context

Tenants opt in via the auth_v2 flag in tenant_settings. Watch error rates before flipping the
remaining cohort. See the rollout runbook.

Cohort    Status
internal  complete
beta      in progress

check

check validates the whole corpus and exits 1 on any finding; it takes no plan id. PLAN uses the short id, and a line under the summary gives the fix for each CODE. --format json|tsv emits the full id in id and the fix in hint. To work through findings, see Working through check; docs/troubleshooting.md explains each CODE.

CODE                    PLAN                  MESSAGE
dangling-parent         invoice-retry         parent 'no-such-plan' does not resolve to a plan
underivable-status      invoice-retry         '## Progress' has no checkboxes or recognized phrase
status-behind-history   auth-cleanup          status 'not-started' but 1 later session worked this plan
status-behind-progress  onboarding-checklist  status 'unknown' but '## Progress' derives 'not-started'
unadopted-tag           auth-docs             no tags, but its thread carries [auth, security]

9 plans checked, 5 findings
dangling-parent: pentimento set <id> --parent <id>, or --clear-parent
status-behind-history: pentimento history <id>, then pentimento set <id> --status <value>
status-behind-progress: pentimento backfill, or pentimento show <id>, then pentimento set <id> --status <value>
unadopted-tag: pentimento set <id> --add-tag <tag>
underivable-status: add a checklist to '## Progress', or pentimento show <id>, then pentimento set <id> --status <value>
narrow with: pentimento list --finding <code>

history

history shows which sessions touched a plan's file: the session whose id matches the plan's own id authored it; any later session that read, edited, or delegated work on it worked it. For an empty result, see history is empty.

WHEN              WHAT      SESSION                                TOUCHES
2026-08-30 12:30  authored  api-auth-cleanup                             1
2026-09-11 12:30  worked    implement-api-auth-cleanup-eager-wolf        1

Frontmatter

---
pentimento:
  status: not-started | partial | complete | superseded | unknown
  pinned: true                  # omitted unless set
  intent: active | queued | someday | abandoned | unset
  tags: [auth, security]        # omitted if untagged
  parent: some-other-plan-id    # omitted for roots
  project: platform             # omitted if undetermined
  created: 2026-09-08
---

The vocabulary lives in one place: pentimento/vocabulary.py.

Field Set by How
status derived Every backfill run (including the per-write pentimento hook, which caps it at partial) recomputes it from ## Progress checkboxes. set --status overrides it directly and pins it (see pinned); it is the only way to set superseded, which no derivation produces or overwrites.
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 and check reports only pin-behind-progress for it.
intent operator Gap-filled to unset by backfill the first time it sees the plan, then left alone. Only set --intent changes it after that.
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.
parent derived, or operator backfill fills it in from a plan reference (see 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.
project derived, or operator backfill derives it from a session's cwd. set --project/--clear-project set or clear it directly; --project . resolves to the current directory's name.
created derived once A local date, set once and then immutable except through backfill --recreate.
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.

Lineage and source discovery are covered in full in docs/integrations.md and docs/troubleshooting.md. Cursor plans get body-only lineage and no project at all.

Commands

Command Does
list flat table of plans
tree [<id>] lineage tree, grouped by project
show <id> H1, frontmatter, and the rendered body
set <id>... rewrite frontmatter in place
backfill gap-fill intent/created/project/parent; advance status
hook run as a Claude Code PostToolUse hook; reads the payload on stdin
index write INDEX.md into the plans directory
check validate lineage, vocabulary, status, and tags; exits 1 on any finding
history <id> session-touch history for a plan
completion <shell> print a shell integration script

Full flags for every command, plus the environment variables, are in docs/reference.md. Run pentimento <command> --help for that command's own examples.

Scope

pentimento is built for one operator's corpus on one machine. Shared, concurrent, or multi-author planning is out of scope and not a gap this tool intends to close — project, session-prompt lineage, and modified are all derived from local Claude Code transcripts, and deriving them across authors would need a different source, a sync, and an identity model.

Keeping the plans directory in git does get you review and history, and part of the derived state travels with the files: status, operator-set frontmatter, and body-referenced parent survive a checkout anywhere; project, prompt-derived parent, and session history do not. See docs/workflows.md for the details, and pentimento index for an INDEX.md worth committing.

Prior art

ccplan and planc track Claude Code plans by a status you set by hand, ccplan in a sidecar file and planc in frontmatter through a TUI. claude-plan-viewer browses and searches them in a web UI. planning-with-files keeps an agent's plan on disk while it works and recovers it after /clear or compaction; it manages the files it creates, not a directory of finished ones. None of them records which plan replaced which. pentimento reads a corpus it did not author and derives status, project, and parent across it. The longer comparison is in Managing Claude Code plan files.

Requirements and limitations

Stdlib-only Python 3.9+, zero runtime dependencies, no PyYAML.

pentimento enriches modified and lineage by reading Claude Code's session transcripts (~/.claude/projects/*.jsonl), an undocumented, private format. If that format changes, or the transcripts are absent, this enrichment degrades to file mtimes and plain body/preamble references — it does not break, and the frontmatter itself stays plain, hand-editable markdown either way.

Development

python3 -m unittest discover
uvx ruff check
uvx ruff format --check

CI (.github/workflows/check.yml) runs all three on Ubuntu and macOS.

Docs

  • docs/reference.md — every command's full flags, and the environment variables.
  • docs/integrations.md — wiring backfill and pentimento hook into Claude Code and Cursor, a slash command, a skill that searches past plans before a new one, a triage-nudge pattern, check in CI.
  • docs/workflows.md — triage, picking a plan back up, reusing a past decision, supersession, lineage trees, working through check, scripting with --format json.
  • docs/troubleshooting.md — every empty field and check finding, explained.

Release files for pentimento 0.1.16

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pentimento 0.1.16
File Size Uploaded
pentimento-0.1.16.tar.gz 868.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pentimento 0.1.16
File Interpreter ABI Platform
pentimento-0.1.16-py3-none-any.whl Python 3 none any Details

Total release size: 936.8 kB

Release files / pentimento-0.1.16.tar.gz

Download URL pentimento-0.1.16.tar.gz
Size 868.3 kB
Tags Source
SHA-256 checksum
How to use checksums
cc77154ad812147775443c67162656b4858ef748e22ea3024332bedfb51af244
BLAKE2b-256 checksum
How to use checksums
f2234e76bc1a8a48d6960c36a558ccce5f02aa06f5474746fb0f5ee0c9a84c4e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / pentimento-0.1.16-py3-none-any.whl

Download URL pentimento-0.1.16-py3-none-any.whl
Size 68.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a725e32fe1a509656a2ef7f5e1f61ec68bbdcc2c0cb8028e5c2dcea2d1df55c3
BLAKE2b-256 checksum
How to use checksums
4c0a535e5ddd72b7b3529f9c6e9018821d61b74363ff8881ac24e36f854f4bf9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.17

2 release files

This release

0.1.16 This release

2 release files

0.1.15

2 release files

0.1.14

2 release files

0.1.13

2 release files

0.1.12

2 release files

0.1.11

2 release files

0.1.10

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page