Claude Code-native failure correction and recovery CLI
Project description
Claude Code Caddy
Claude Code makes mistakes. Caddy shows where it went wrong and how to recover.
Caddy reads your Claude Code transcript, Git diff, and test output, then prints a recovery packet:
- bad turn
- evidence
- claimed vs verified
- skipped instruction
- files to revert
- files to keep
- command to run
- continuation prompt
It is local-only. It does not upload your code.
Proof
Validated on:
- 90/90 tests
- 10/10 public Claude Code runs
- 6/6 semantic error cases
- 6/6 blinded holdout cases
- 10/10 human-accepted recovery packets
- privacy/package audit passed
Quickstart
PyPI publishing is not live yet. Install the current release from a checkout, then run Caddy inside the Git repository where you use Claude Code:
pipx install .
cd C:\path\to\your-repo
caddy install-claude
claude
caddy recover --latest
To emit the same recovery as a portable, local caddy.recovery/v1 bundle:
caddy recover --latest --bundle-dir .caddy/bundles/latest-failure
Bundles contain local evidence and are not redacted. Review them before sharing.
Sample output:
BAD TURN
Claude claimed the task was complete after changing the wrong page.
EVIDENCE
- transcript:2 — Claude mutated docs/product-timeline.md.
- transcript:11 — user reported the wrong target.
CLAIMED VS VERIFIED
Claimed: Done. Build exit 0.
Verified: The build passed, but it did not prove the requested page changed.
SKIPPED INSTRUCTION
Apply the treatment to docs/launch-guide/index.md.
FILES TO REVERT
- docs/product-timeline.md
FILES TO KEEP
- docs/stylesheets/extra.css
COMMAND TO RUN
mkdocs build
CONTINUATION PROMPT
Restore only the wrong-target change, update the intended page, and report exact verification.
Install
Caddy requires Python 3.11 or newer. From a checkout:
python -m pip install .
caddy --help
For an isolated command-line install:
pipx install .
Claude Code setup
Claude Code must be installed and authenticated separately. From the Git repository where you use Claude Code, run:
caddy install-claude
Use caddy install-claude --scope user to install the same hook set in Claude Code's
user settings. Run caddy doctor to check Git, the Claude executable, hook installation,
managed hook policy, and the local hook handshake.
The setup command:
- adds Caddy handlers to the project's
.claude/settings.local.json - preserves every existing Claude setting and hook
- backs up an existing settings file under
.caddy/backups/before changing it - adds
.caddy/and.claude/settings.local.jsonto the repository's local Git exclude - is idempotent and prints every change it made
The hooks receive Claude Code's documented transcript_path, cwd, and tool-result fields. They record local metadata only; they do not block Claude Code or upload anything. See the Claude Code hooks reference.
Recovery usage
--latest detects the Git root, maps it to the matching Claude Code project, selects the newest relevant transcript, reads the current staged and unstaged Git diff, and uses real linked test/tool output when available.
The same mode works with every existing command:
caddy inspect --latest
caddy blame --latest
caddy recover --latest
caddy verify --latest
If more than one active Claude session points at the repository, Caddy refuses to guess.
Use --session-id <id> to choose one explicitly.
For a session containing several failures, --match "text from the correction" can select a specific correction. It is optional.
To select a session explicitly instead of using latest mode:
caddy recover --session <claude-session-file> --repo <failed-project>
Evidence capture
Installed hooks keep per-session metadata under .caddy/runs/, including the transcript path, repository path, timestamps, and actual available test/tool output. Missing output remains missing; Caddy does not synthesize evidence.
Capture evidence while the failed worktree still exists:
caddy inspect --session <claude-session-file> --repo <failed-project> --capture-dir <private-capture-directory>
The capture directory can contain sensitive source paths, diffs, test output, and transcript content. Keep it private. Caddy refuses to overwrite an existing capture and records SHA-256 hashes for every captured artifact.
Recovery and verification
Explain why the selector chose a turn:
caddy blame --session <claude-session-file> --repo <failed-project>
Run the packet's recommended verification command and print its unedited output:
caddy verify --session <claude-session-file> --repo <failed-project>
verify runs without a shell in a disposable Git worktree. It permits only terminating
build/test command families: MkDocs, pytest, npm, pnpm, yarn, Bun, Cargo, Go, Maven,
Gradle, .NET, and repo-local verify*.py scripts. Unknown commands and development
servers are reported as UNSUPPORTED; a zero exit code is required for PASS. A verifier
that mutates source state is reported as an error.
Repositories can add exact argv-only commands and a bounded timeout in .caddy.toml:
[verification]
timeout_seconds = 180
commands = [["custom-check", "--ci"]]
Preview an optional recovery revert:
caddy recover --session <claude-session-file> --repo <failed-project> --apply
Actually restore the packet's explicitly listed files and automatically re-run verification:
caddy recover --session <claude-session-file> --repo <failed-project> --apply --yes
Patch safety is deliberately narrow:
- dry-run unless both
--applyand--yesare present - reverse-apply recorded Git hunks only; Caddy does not generate business-logic edits
- only tracked files explicitly listed under
FILES TO REVERT - paths outside the repository are refused
- mixed-purpose partial-file reversions are refused
- staged revert targets are refused
- the current file must match the recorded Git postimage hash
- the reversal must succeed in an isolated worktree before Caddy touches the original
- verification runs immediately after a confirmed restore
Optional Claude handoff
Preview a handoff without launching Claude:
caddy handoff --latest
Explicitly ask Claude to attempt the continuation prompt:
caddy handoff --latest --yes
Caddy copies the failed state into a detached worktree under .caddy/worktrees/, starts
Claude there without session persistence, and verifies the result in another isolated
worktree. It never copies the result back or marks it accepted. The output is always left
for manual review.
Product boundary
Caddy's wedge is correction, not generic tracing:
- CodeTracer reconstructs coding-agent traces and localizes failure onset across frameworks. Caddy is narrower: it consumes Claude Code artifacts and emits a user-facing correction packet, revert plan, and verification command.
- Cursor Agent Trace records code attribution. Caddy evaluates a failed run and recommends corrective action; it is not an attribution format.
- Generic trace viewers answer what happened. Caddy's primary output is what to preserve, what may be reverted, what evidence is missing, and how to continue and verify.
The differentiation is specialization and recovery workflow, not a claim that no adjacent failure-localization systems exist.
Public test data
The repository contains synthetic fixtures only. Real transcripts, diffs, project names, private paths, local captures, and gauntlet results are intentionally excluded from version control and package artifacts.
Privacy
Caddy is local-only:
- Caddy itself has no network client or upload path
- Claude transcripts remain in Claude Code's local project directory
- Caddy metadata remains under the failed repository's
.caddy/directory - settings backups remain under
.caddy/backups/ - Git and tool output are read locally and printed locally
- hook metadata is secret-redacted, bounded, written atomically, and stored with restrictive permissions where the operating system supports them
caddy handoff --yes is the one explicit exception: it launches the separately installed
Claude CLI, so Claude's network and privacy behavior applies. Caddy passes only the recovery
prompt and grants tools inside the isolated worktree.
Preview or delete local run metadata:
caddy purge
caddy purge --older-than-days 30 --yes
Run the public suite:
python -m pytest -q tests -p no:cacheprovider
Limitations
- Caddy does not install or authenticate Claude Code.
handoff --yescan launch an existing installation only. - User-scoped hooks affect every Claude Code project for that user; project scope remains the safer default.
- Managed Claude Code policy can disable local hooks.
caddy doctordetects file-based policy, but cannot override it. - Failure selection is heuristic. It abstains on low-confidence or tied candidates; explicit
--session-idor--matchcan still be required. - Correction-language heuristics currently cover English plus common Spanish and French phrases; other languages may not trigger selection.
- Automatic discovery requires Claude's transcript or hook metadata to retain a path linking the session to the Git repository.
- Future Claude Code transcript schema changes may require parser updates.
- A later clean worktree cannot recreate a lost historical diff. Capture evidence while the failure state still exists.
- Build/test success cannot prove visual behavior or user intent.
- Patch application supports Git only, requires an exact recorded diff and matching blob identity, and refuses mixed-purpose partial-file reversions.
- Verification is limited to terminating allowlisted argv. Custom commands must be explicitly listed in
.caddy.toml. - Caddy's deterministic recovery path does not generate a business-logic fix. The optional Claude handoff may attempt one only in an isolated worktree and still requires human review.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file claude_code_caddy-0.1.1.tar.gz.
File metadata
- Download URL: claude_code_caddy-0.1.1.tar.gz
- Upload date:
- Size: 65.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e0d9538e8992074e8f8288fb9b9a5fdb0eba51b37b373140f4064fbe300f0de8
|
|
| MD5 |
6f3aa03d3c488181ef14eae73a9b82c3
|
|
| BLAKE2b-256 |
c8ca66693aee37b2b6088f4c8b6a22d84e0e49fd1299861a2d9d8a2dabaca2c4
|
Provenance
The following attestation bundles were made for claude_code_caddy-0.1.1.tar.gz:
Publisher:
publish.yml on electricwolfemarshmallowhypertext/caddy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
claude_code_caddy-0.1.1.tar.gz -
Subject digest:
e0d9538e8992074e8f8288fb9b9a5fdb0eba51b37b373140f4064fbe300f0de8 - Sigstore transparency entry: 2256660130
- Sigstore integration time:
-
Permalink:
electricwolfemarshmallowhypertext/caddy@9fe172cc9983691ad2908351c4290b3ab95edf5f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/electricwolfemarshmallowhypertext
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9fe172cc9983691ad2908351c4290b3ab95edf5f -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file claude_code_caddy-0.1.1-py3-none-any.whl.
File metadata
- Download URL: claude_code_caddy-0.1.1-py3-none-any.whl
- Upload date:
- Size: 48.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
206dbabb89991f564f3d74cb10addd1ca151ecb3ae39c17b60c64e35983c1deb
|
|
| MD5 |
7c4c079ebdaf782e142f393591b83f53
|
|
| BLAKE2b-256 |
1b6bc9c39774cc1d651137e4e0b90d369bef13eb9111d0c922bd6712aced3eb9
|
Provenance
The following attestation bundles were made for claude_code_caddy-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on electricwolfemarshmallowhypertext/caddy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
claude_code_caddy-0.1.1-py3-none-any.whl -
Subject digest:
206dbabb89991f564f3d74cb10addd1ca151ecb3ae39c17b60c64e35983c1deb - Sigstore transparency entry: 2256660137
- Sigstore integration time:
-
Permalink:
electricwolfemarshmallowhypertext/caddy@9fe172cc9983691ad2908351c4290b3ab95edf5f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/electricwolfemarshmallowhypertext
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9fe172cc9983691ad2908351c4290b3ab95edf5f -
Trigger Event:
workflow_dispatch
-
Statement type: