hezaohezao/python-debugpy
Debug Python: pdb REPL + debugpy remote (DAP).
npx skills add https://github.com/HezaoHezao/poirot --skill python-debugpy
Three tools, picked by situation:
| Tool | When |
|---|---|
| breakpoint() + pdb | Local, interactive, simplest. Add breakpoint() in source, run, get REPL. |
| python -m pdb | Launch script under pdb with no source edits. |
| debugpy | Remote / headless / attach to running process. DAP, scriptable. |
Start with breakpoint(). It's the cheapest thing that works.
Don't use for: things print() / logging.debug solve in under a minute,
or things pytest -vv --tb=long --showlocals already reveals.
Inside any pdb prompt ((Pdb)):
| Command | Action |
|---|---|
| h / h cmd | help |
| n | next line (step over) |
| s | step into |
| r | return from current function |
| c | continue |
| unt N | continue until line N |
| j N | jump to line N (same function only) |
| b N | set breakpoint at line N |
| b file:N | set breakpoint in another file |
| b func | set breakpoint at function |
| cl N | clear breakpoint N |
| l | list 11 lines around current |
| ll | list whole function |
| w / where | show call stack |
| u / d | move up/down stack frame |
| p expr | print expression |
| pp expr | pretty-print expression |
| a | print args of current function |
| args | same as a |
| display expr | watch expression (re-eval each step) |
| interact | drop into interactive Python REPL |
breakpoint()def process(data):
result = transform(data)
breakpoint() # Execution pauses here, pdb REPL opens
return result
Run normally:
python script.py
# Pauses at breakpoint(), (Pdb) prompt appears
python -m pdb (no source edits)python -m pdb script.py
# Starts paused at first line
Drop into pdb at the exact exception site:
import pdb, traceback
try:
main()
except Exception:
traceback.print_exc()
pdb.post_mortem()
Or:
python -m pdb -c continue script.py
# Runs until exception, then drops to pdb at the crash
For long-running processes or headless debugging:
# Install
pip install debugpy
# Option 1: Launch with debugpy
python -m debugpy --listen 5678 --wait-for-client script.py
# Option 2: Inject into running code
import debugpy
debugpy.listen(5678)
print("Waiting for debugger on port 5678...")
debugpy.wait_for_client()
Attach from another terminal (DAP client):
# Using debugpy's CLI to set breakpoints + continue
python -m debugpy --connect localhost:5678 --set-breakpoint script.py:42
Or use any DAP-compatible editor (VS Code, Neovim) to attach to port 5678.
# In pdb
(Pdb) display my_list
# Each step, pdb re-evaluates and shows the value if changed
# In source
breakpoint() if condition else None
# Or in pdb
(Pdb) b 42, x > 100 # Break at line 42 only when x > 100
import debugpy
# In the subprocess code:
debugpy.listen(5679)
debugpy.wait_for_client()
# Parent can attach to port 5679
breakpoint() onlyfor local debugging.
Use debugpy for multi-process debugging.
w (where) to see the full async call stack.
pdb is more reliable than breakpoint()` in some Windows terminals.
--listen 5679.
Take hezaohezao/python-debugpy from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.
The instructions reference pip.
Without those the skill loads but fails at the first command.