Skip to content
Development
Skill

/python-debugpy

Debug Python: pdb REPL + debugpy remote (DAP).

From plugin
kevinnft-ai-agent-skills
14169 skills
Install
$ npx -y skills add kevinnft/ai-agent-skills --skill python-debugpy --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/python-debugpy

Context preview

The summary Claude sees to decide when to auto-load this skill.

Debug Python: pdb REPL + debugpy remote (DAP).

SKILL.md

python-debugpy.SKILL.md
name: python-debugpy
description: "Debug Python: pdb REPL + debugpy remote (DAP)."
version: 1.0.0
author: Hermes Agent
license: MIT
metadata:
  hermes:
    tags: [debugging, python, pdb, debugpy, breakpoints, dap, post-mortem]
    related_skills: [systematic-debugging, node-inspect-debugger, debugging-hermes-tui-commands]
origin: original
source_repo: kevinnft/ai-agent-skills
source_url: https://github.com/kevinnft/ai-agent-skills
source_license: MIT
language: en

Python Debugger (pdb + debugpy)

Overview

Three tools, picked by situation:

| Tool | When | |---|---| | **`breakpoint()` + pdb** | Local, interactive, simplest. Add `breakpoint()` in the source, run normally, get a REPL at that line. | | **`python -m pdb`** | Launch an existing script under pdb with no source edits. Useful for quick poking. | | **`debugpy`** | Remote / headless / "attach to already-running process." Talks DAP, scriptable from terminal, works for long-lived processes (gateway, daemon, PTY children). |

**Start with `breakpoint()`.** It's the cheapest thing that works.

When to Use

  • A test fails and the traceback doesn't reveal why a value is wrong
  • You need to step through a function and watch a collection mutate
  • A long-running process (hermes gateway, tui_gateway) misbehaves and you can't restart it
  • Post-mortem: an exception fired in prod-ish code and you want to inspect locals at the crash site
  • A subprocess / child (Python `_SlashWorker`, PTY bridge worker) is the actual bug site

**Don't use for:** things `print()` / `logging.debug` solve in under a minute, or things `pytest -vv --tb=long --showlocals` already reveals.

pdb Quick Reference

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) | | `l` / `ll` | list source around current line / full function | | `w` | where (stack trace) | | `u` / `d` | move up / down in the stack | | `a` | print args of the current function | | `p expr` / `pp expr` | print / pretty-print expression | | `display expr` | auto-print expr on every stop | | `b file:line` | set breakpoint | | `b func` | break on function entry | | `b file:line, cond` | conditional breakpoint | | `cl N` | clear breakpoint N | | `tbreak file:line` | one-shot breakpoint | | `!stmt` | execute arbitrary Python (assignments included) | | `interact` | drop into full Python REPL in current scope (Ctrl+D to exit) | | `q` | quit |

The `interact` command is the most powerful — you can import anything, inspect complex objects, even call methods that mutate state. Locals are read-only by default; use `!x = 42` from the `(Pdb)` prompt to mutate.

Recipe 1: Local breakpoint

Easiest. Edit the file:

def compute(x, y):
    result = some_helper(x)
    breakpoint()           # <-- drops into pdb here
    return result + y

Run the code normally. You land at the `breakpoint()` line with full access to locals.

**Don't forget to remove `breakpoint()` before committing.** Use `git diff` or a pre-commit grep:

rg -n 'breakpoint\(\)' --type py

Recipe 2: Launch a script under pdb (no source edits)

python -m pdb path/to/script.py arg1 arg2
# Lands at first line of script
(Pdb) b path/to/script.py:42
(Pdb) c

Recipe 3: Debug a pytest test

The hermes test runner and pytest both support this:

# Drop to pdb on failure (or on any raised exception):
scripts/run_tests.sh tests/path/to/test_file.py::test_name --pdb

# Drop to pdb at the START of the test:
scripts/run_tests.sh tests/path/to/test_file.py::test_name --trace

# Show locals in tracebacks without pdb:
scripts/run_tests.sh tests/path/to/test_file.py --showlocals --tb=long

Note: `scripts/run_tests.sh` uses xdist (`-n 4`) by default, and pdb does NOT work under xdist. Add `-p no:xdist` or run a single test with `-n 0`:

scripts/run_tests.sh tests/foo_test.py::test_bar --pdb -p no:xdist
# or
source .venv/bin/activate
python -m pytest tests/foo_test.py::test_bar --pdb

This bypasses the hermetic-env guarantees — fine for debugging, but re-run under the wrapper to confirm before pushing.

Recipe 4: Post-mortem on any exception

import pdb, sys
try:
    run_the_thing()
except Exception:
    pdb.post_mortem(sys.exc_info()[2])

Or wrap a whole script:

python -m pdb -c continue script.py
# When it crashes, pdb catches it and you're in the frame of the exception

Or set a global hook in a repl/jupyter:

import sys
def excepthook(etype, value, tb):
    import pdb; pdb.post_mortem(tb)
sys.excepthook = excepthook

Recipe 5: Remote debug with debugpy (attach to running process)

For long-lived processes: Hermes gateway, tui_gateway, a daemon, a process that's already misbehaving and can't be restarted clean.

Setup

source /home/bb/hermes-agent/.venv/bin/activate
pip install debugpy

Pattern A: Source-edit — process waits for debugger at launch

Add near the top of the entry point (or inside the function you want to debug):

import debugpy
debugpy.listen(("127.0.0.1", 5678))
print("debugpy listening on 5678, waiting for client...", flush=True)
debugpy.wait_for_client()
debugpy.breakpoint()       # optional: pause immediately once attached

Start the process; it blocks on `wait_for_client()`.

Pattern B: No source edit — launch with `-m debugpy`

python -m debugpy --listen 127.0.0.1:5678 --wait-for-client your_script.py arg1

Equivalent for module entry:

python -m debugpy --listen 127.0.0.1:5678 --wait-for-client -m your.module

Pattern C: Attach to an already-running process

Needs the PID and debugpy preinstalled in the target's environment:

python -m debugpy --listen 127.0.0.1:5678 --pid <pid>
# debugpy injects itself into the process
Read more
Ships withkevinnft-ai-agent-skills

191 attribution-first agent skills for Hermes Agent, Claude Code, Cursor — one installer, 28 categories, searchable catalog. See NOTICE for upstream attribution.

Get the whole plugin

Other skills on kevinnft-ai-agent-skills.