Runtime function tracing that turns "the test failed" into "here's exactly what happened"
AI coding agents are great at generating code and writing tests, but when tests fail, they rely on static analysis. Some bugs resist that approach: shared mutable state, swallowed exceptions, wrong values propagating through long call chains. These are the same bugs that make human developers reach for a debugger.
PyTrace Autopsy bridges that gap. It gives Claude Code runtime visibility that static analysis alone cannot provide.
The key insight: sitecustomize.py is automatically imported by Python at startup. By placing a tracer in a temp directory and prepending it to PYTHONPATH, tracing activates with zero modifications to project files.
# Option 1: Clone and copy the skill into your project
git clone https://github.com/ApartsinProjects/pytrace-autopsy
mkdir -p .claude/skills
cp -r pytrace-autopsy/skill .claude/skills/pytrace-autopsy
# Option 2: One-line install
curl -L https://raw.githubusercontent.com/ApartsinProjects/pytrace-autopsy/main/install.sh | bashAfter installation, Claude Code will automatically detect and load the skill.
Automatic: Claude auto-invokes tracing when it encounters failing tests and cannot determine the root cause from static analysis alone.
Manual: Invoke the skill directly when you want runtime insight.
/trace # trace the last failing test
/trace tests/test_cart.py # trace a specific test file
The examples/ directory contains five self-contained bug scenarios with full walkthroughs: off-by-one, None propagation, swallowed exceptions, shared state mutation, and wrong arithmetic. Each includes buggy source code, failing tests, and a WALKTHROUGH.md showing the tracing session.
The tracer is controlled by a trace_config.json file created alongside sitecustomize.py:
{
"version": 1,
"trace_targets": {
"paths": ["/absolute/path/to/src"],
"modules": ["myapp.cart"],
"functions": ["calculate_total"]
},
"output": {
"log_file": "/tmp/trace_abc123/trace_output.jsonl",
"max_entries": 10000,
"max_repr_length": 200
},
"options": {
"max_depth": 20,
"trace_args": true,
"trace_return_values": true,
"trace_exceptions": true,
"include_stdlib": false,
"trace_threads": false
}
}All fields in trace_targets are optional. Start with paths only (broadest filter) and narrow with modules or functions if the trace output is too noisy.
Each line in the JSONL log is one of three event types:
{"event":"call","call_id":1,"parent_id":null,"depth":0,"func":"paginate","module":"paginator","file":"src/paginator.py","line":4,"args":{"items":"[1, 2, 3, 4, 5]","page_size":"2"}}
{"event":"return","call_id":1,"depth":0,"func":"paginate","return_value":"[[1, 2], [3, 4]]"}
{"event":"exception","call_id":2,"depth":1,"func":"find_user","exc_type":"KeyError","exc_value":"'999'","exc_line":14}The call_id and parent_id fields reconstruct the full call tree. The depth field shows nesting level.
skill/
├── SKILL.md # Skill definition (7-phase workflow)
└── scripts/
└── tracer_template.py # The sitecustomize.py template
- Injection mechanism:
sitecustomize.pyplaced in a temp dir, activated viaPYTHONPATH - Tracing API:
sys.settracefor function-level call/return/exception events - Output format: JSONL (one JSON object per line) for streaming and partial reads
- Thread safety: All log writes are serialized through
threading.Lock - Crash safety: Entire tracer wrapped in
try/except; usesatexitfor cleanup - Chaining: Detects and loads any pre-existing
sitecustomize.pyin the original path - Zero footprint: No project files are created, modified, or left behind
claude-code claude-skill ai-dev-tools python-debugging tracing sys-settrace
