python-debugpy – skill Lập trình cho agent AI
Gỡ lỗi Python: REPL pdb + debugpy từ xa (DAP).
Cài skill python-debugpy bằng một lệnh
Chọn công cụ bạn đang dùng, copy lệnh và dán vào terminal. Skill sẽ nằm trong thư mục skills của công cụ đó và sẵn sàng dùng ở phiên làm việc tiếp theo.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/python-debugpy-e0c2b.tgz | tar xz -C ~/.claude/skills
Gọi trong Claude Code: /python-debugpy – rồi mô tả công việc bạn muốn làm.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/python-debugpy-e0c2b.tgz | tar xz -C ~/.codex/skills
Gọi trong Codex: $python-debugpy – rồi mô tả công việc bạn muốn làm.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/python-debugpy-e0c2b.tgz | tar xz -C ~/.hermes/skills
Gọi trong Hermes Agent: /python-debugpy – rồi mô tả công việc bạn muốn làm.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/python-debugpy-e0c2b.tgz | tar xz -C ~/.deepcode/skills
Gọi trong DeepSeek: /python-debugpy – rồi mô tả công việc bạn muốn làm.
Nội dung SKILL.md
Nội dung SKILL.md gốc bằng tiếng Anh.
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 + yRun 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 pyRecipe 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) cRecipe 3: Debug a pytest test
Use terminal and the canonical runner for noninteractive diagnostics:
# Show locals in tracebacks without pdb:
scripts/run_tests.sh tests/path/to/test_file.py --showlocals --tb=longscripts/run_tests.sh captures each file in a separate subprocess, so --pdb
or --trace cannot provide an interactive prompt there. For an interactive
debugger only, use the independent development/test interpreter prepared in
Recipe 5 (never a production generation):
.venv/bin/python -m pytest tests/foo_test.py::test_bar --pdbThis 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 exceptionOr set a global hook in a repl/jupyter:
import sys
def excepthook(etype, value, tb):
import pdb; pdb.post_mortem(tb)
sys.excepthook = excepthookRecipe 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
For Hermes, use a separate development checkout and data home, not a live
production generation. Follow the
[PM developer workflow](https://hermes-agent.nousresearch.com/docs/reference/package-management#developer-workflow)
and activate that checkout — PowerShell: . .\activate.ps1. The declared dev
extra includes debugpy, which PM activation does not sync (all excludes it).
Through terminal, build a fresh, caller-owned debug/test environment with the
prepared checkout's Python:
source ./activate
python -m pm.build_env --source . --out .venv --group dev --group test
.venv/bin/python -c "import debugpy; print(debugpy.__file__)"The output must not already exist. Stop its processes and intentionally remove
only that disposable environment before rebuilding. Keep the same isolated
HERMES_HOME for the debug target. .venv/bin/python is this explicitly built
debug environment, not a guessed application venv, and the patterns below run
through it. Do not add debugpy to a running production environment; reproduce
there only with an already-prepared debug target or arrange a restart in the
development environment.
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 attachedStart the process; it blocks on wait_for_client().
Pattern B: No source edit — launch with -m debugpy
.venv/bin/python -m debugpy --listen 127.0.0.1:5678 --wait-for-client your_script.py arg1Equivalent for module entry:
.venv/bin/python -m debugpy --listen 127.0.0.1:5678 --wait-for-client -m your.modulePattern C: Attach to an already-running process
Needs the PID and debugpy preinstalled in the target's environment:
.venv/bin/python -m debugpy --listen 127.0.0.1:5678 --pid <pid>
# debugpy injects itself into the process. Then attach a client as below.Some kernels/security configs block the ptrace-based injection (/proc/sys/kernel/yama/ptrace_scope). Fix with:
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scopeConnecting a client from the terminal
The easiest terminal-side DAP client is VS Code CLI or a small script. From inside Hermes you have two practical options:
Option 1: debugpy's own CLI REPL — not an official feature, but a tiny DAP client script:
# ~/.hermes/cache/scratch/dap_client.py
import socket, json, itertools, time, sys
HOST, PORT = "127.0.0.1", 5678
s = socket.create_connection((HOST, PORT))
seq = itertools.count(1)
def send(msg):
msg["seq"] = next(seq)
body = json.dumps(msg).encode()
s.sendall(f"Content-Length: {len(body)}\r\n\r\n".encode() + body)
def recv():
header = b""
while b"\r\n\r\n" not in header:
header += s.recv(1)
length = int(header.decode().split("Content-Length:")[1].split("\r\n")[0].strip())
body = b""
while len(body) < length:
body += s.recv(length - len(body))
return json.loads(body)
send({"type": "request", "command": "initialize", "arguments": {"adapterID": "python"}})
print(recv())
send({"type": "request", "command": "attach", "arguments": {}})
print(recv())
send({"type": "request", "command": "setBreakpoints",
"arguments": {"source": {"path": sys.argv[1]},
"breakpoints": [{"line": int(sys.argv[2])}]}})
print(recv())
send({"type": "request", "command": "configurationDone"})
# ... loop reading events and sending continue/stepIn/etc.This is fine for one-off automation but painful as an interactive UX.
Option 2: Attach from VS Code / Cursor / Zed — if the user has one open, they can add a launch.json:
{
"name": "Attach to Hermes",
"type": "debugpy",
"request": "attach",
"connect": { "host": "127.0.0.1", "port": 5678 },
"justMyCode": false,
"pathMappings": [
{ "localRoot": "${workspaceFolder}", "remoteRoot": "<hermes-agent-repo>" }
]
}Option 3: Ditch DAP, use remote-pdb — usually what you actually want from a terminal agent:
For an independently owned Python project, declare remote-pdb in that
project's development dependencies and prepare its debug environment through
the project's package manager. This is not a Hermes SDK install recipe. For
Hermes, prefer the declared debugpy dependency; the remote-pdb examples below
require a separately declared, freshly built debug environment, never an
in-place pip insta
… (nội dung đầy đủ có trong gói tải về)
Skill liên quan
- context-driven-development – Hướng dẫn triển khai và duy trì ngữ cảnh như một artifact được quản lý cùng với mã…
- convex – Chuyên gia backend reactive Convex: thiết kế schema, hàm TypeScript, đăng ký real-time…
- convex-backend – Xây dựng backend reactive với hàm Convex, kiểm tra schema, tích hợp auth và quy trình…
- copilot-delegate – Chỉ giao tác vụ viết code cho GitHub Copilot CLI (`copilot`) khi người dùng yêu cầu rõ…
- copilot-sdk – Xây dựng ứng dụng tương tác với GitHub Copilot theo cách lập trình. SDK bao bọc Copilot…
- screen-reader-testing – Kiểm thử ứng dụng web với trình đọc màn hình gồm VoiceOver, NVDA và JAWS. Dùng khi kiểm…
- cowork-to-code-bridge – Dùng cầu nối cowork-to-code đã cài sẵn và được xác minh độc lập để chạy các hành động…
- cpp – Hướng dẫn super-code riêng cho ngôn ngữ cpp.