Skip to main content

pentimento

Status, intent, and lineage over agent plan files.

check PyPI Python versions

demo

Coding agents 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.

The plans worth keeping are the long ones. An infrastructure migration you have been designing for months grows subplans, absorbs decisions made in discussion, and leaves behind the branches you rejected — which is 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. 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

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

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: the shortest trailing hyphen-segment run that's unique across the corpus, so is-it-possible-to-abundant-rabbit displays as abundant-rabbit.

STATUS       INTENT     PROJECT   SOURCE  PLAN                  TITLE                           UPDATED
superseded   abandoned  platform  claude  style-guide           Write a docs style guide             6w
complete     abandoned  platform  claude  auth-redesign         Redesign the auth API                5w
complete     someday    billing   claude  dunning-copy          Rewrite dunning email copy           3w
partial      active     platform  claude  auth-rollout          Roll out the new auth API            2w
not-started  queued     platform  claude  auth-cleanup          Remove the old auth API              2w
unknown      unset      billing   claude  invoice-retry         Retry failed invoice charges         1w
not-started  active     billing   claude  relevance-tuning      Tune search relevance                5d
unknown      unset                claude  onboarding-checklist  Write the onboarding checklist       1d

8 plans

tree

(no project)
└─ Write the onboarding checklist
     onboarding-checklist  unknown  unset  1d

billing
├─ Rewrite dunning email copy
│    dunning-copy  complete  someday  [billing]  2026-08-20  3w
├─ Retry failed invoice charges (parent elided: no-such-plan)
│    invoice-retry  unknown  unset  [billing]  2026-09-04  1w
└─ 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

8 plans

show

# Roll out the new auth API

id: api-auth-rollout
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

✓ 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 corpus and exits 1 on any finding. It takes no plan id — it always checks the whole corpus. The table's PLAN column uses the same short id as list/tree; --format json|tsv emits the full id in its plan_id field. See docs/troubleshooting.md for what each CODE means and how to fix it.

CODE                   PLAN           MESSAGE
dangling-parent        invoice-retry  parent 'no-such-plan' does not resolve to a plan
status-behind-history  auth-cleanup   status 'not-started' but 1 later session worked this plan; see `pentime…
8 plans checked, 2 findings

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. An empty result prints no session history for <id> — that means no matching transcript was found on this machine, never a claim the plan wasn't worked.

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) recomputes it from ## Progress checkboxes. The hook caps the result at partial; only a full backfill sweep advances it to complete. set --status overrides it directly — the only way to set superseded, which no derivation ever produces or overwrites — and pins it (see pinned).
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.
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. 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 session-prompt or body reference to an earlier same-project, same-source plan. --rederive recomputes it from scratch, including removing one that no longer resolves. set --parent/--clear-parent set or clear it directly; set --parent rejects a value that would create a cycle.
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, one line each.
tree Plans nested under their parents, grouped by project.
show <id> One plan's title, frontmatter, and rendered body.
set <id> Rewrite one plan's frontmatter in place.
backfill Derive and write missing frontmatter across the corpus.
hook Run as a Claude Code PostToolUse hook, reading the payload on stdin.
index Write INDEX.md into the plans directory.
check Validate lineage and vocabulary; exits 1 on any finding.
history <id> Every session that touched one plan, oldest first.

Full flags for every command, plus the environment variables, are in docs/reference.md. Run pentimento <command> --help for the same information from the CLI itself.

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.

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

Release files for pentimento 0.1.4

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.4
File Size Uploaded
pentimento-0.1.4.tar.gz 1.3 MB Details

Built distribution (wheel)

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

Total release size: 1.3 MB

Release files / pentimento-0.1.4.tar.gz

Download URL pentimento-0.1.4.tar.gz
Size 1.3 MB
Tags Source
SHA-256 checksum
How to use checksums
027cd82d1b96696d4c17825031c377098ad0698a731b354d8a8614278ee67163
BLAKE2b-256 checksum
How to use checksums
0fe295a57f191bc094b4e69378a6d1043166bf3ac4eefe419079c5ce13c3320a
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 15, 2026.

Transparency log

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

Download URL pentimento-0.1.4-py3-none-any.whl
Size 51.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8391038c4844897f556e1989d462494400e696bcc80145d2c0171573cf7d6d2a
BLAKE2b-256 checksum
How to use checksums
eca94e7a50dd0b0212fd4343d962f02eb619f9cb689bc4782e5d1985ccad18a2
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 15, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.17

2 release files

0.1.16

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

This release

0.1.4 This release

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