npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@adamancyzhang/agent-py-debugger

v0.2.1

Published

Python breakpoint debugging CLI for AI agents — JDWP-style remote debug: breakpoints, stack, locals, eval and stepping over TCP. PyCharm-like, driven entirely from the command line.

Readme

agent-py-debugger

Breakpoint debugging for Python services from the command line — no IDE required. Built for AI agents: stable machine-readable output, plus a human-readable text format.

npm version license node

What it does

agent-py-debugger debugs Python processes the way JVM remote debugging (JDWP) works: the target starts with a debug listener and the CLI connects over TCP. A pure-stdlib trace engine (sys.settrace / threading.settrace) runs inside the target process — breakpoints, pause state, and the protocol server all live there — so every CLI invocation is a stateless one-shot connection, exactly what an agent tool layer needs.

agent-py-debugger connect 127.0.0.1:5678            # open a session against a listener
agent-py-debugger breakpoint set app/api/users.py 120
agent-py-debugger wait                               # block until a thread pauses
agent-py-debugger locals --depth 2                   # local variables (in-memory data)
agent-py-debugger eval "token_pair.expires_in"       # evaluate any expression
agent-py-debugger continue                           # release the paused thread

The debugged process can be anywhere — any OS, any CPU. Only the machine running the CLI needs Python 3.8+.

Installation

Global (recommended)

npm install -g @adamancyzhang/agent-py-debugger

Requires Node >= 18 (launcher shim only) and Python 3.8+ (the CLI itself is pure Python — no pip packages needed; the interpreter is discovered automatically, override with AGENTDBG_PYTHON).

From source

git clone https://github.com/adamancyzhang/agent-py-debugger.git
cd agent-py-debugger
npm link

As a dependency of the target project

The debug listener ships as a Python package; add it to the target's environment so the app can be started with debugging enabled:

# pyproject.toml of the target project
dependencies = [..., "agentdbg>=0.1.1"]
[tool.uv.sources]
agentdbg = { path = "/path/to/agent-py-debugger" }   # or a git URL / PyPI

Then uv sync (or pip install -e .). Equivalent without any package manager:

python -m agentdbg install /path/to/venv/lib/python3.12/site-packages

Enabling debugging in the target

The target process must be started with the debug listener — one of three equivalent ways:

# ① CLI wrapper — no configuration changes. Non-blocking by default (suspend=n):
agent-py-debugger run --port 5678 -- -m uvicorn app.main:app --host 0.0.0.0 --port 3003
#    --suspend: suspend=y — wait for `agent-py-debugger resume` before running
#    --foreground: stay in the foreground (Ctrl-C stops, like plain uvicorn)

# ② Environment variable + sitecustomize — docker/systemd friendly.
#    The wheel installs a sitecustomize.py that is a strict no-op unless
#    AGENTDBG_LISTEN is set:
AGENTDBG_LISTEN=127.0.0.1:5678 AGENTDBG_TOKEN=secret .venv/bin/uvicorn app.main:app --port 3003
#    AGENTDBG_SUSPEND=1 = suspend=y · AGENTDBG_AUTO_CONTINUE=300 · AGENTDBG_LOG=/tmp/dbg.log

# ③ Explicit in code (the debugpy.listen equivalent):
#    import agentdbg.client as c
#    c.listen(host="127.0.0.1", port=5678, token="secret")

JVM mapping: run (default) = suspend=n — the app runs completely normally while no debugger is connected, and a debugger can connect or disconnect at any time. disconnect resumes every paused thread and keeps the listener and breakpoints (JVM disconnect semantics); detach removes tracing entirely and shuts the listener down. Neither stops the process: a target started with run is owned by agent-py-debugger and is stopped with kill --session <port>; a target started outside agentdbg (options ② / ③) is its owner's to stop — agentdbg never kills it.

Quick Start

agent-py-debugger connect 127.0.0.1:5678 --token secret   # session (token optional if one exists)
agent-py-debugger breakpoint set app/auth/router.py 60
agent-py-debugger breakpoint set router.py:60 --condition 'body.email.endswith("dev")'
agent-py-debugger breakpoint list / delete 1 / enable 1 / disable 1
curl -s http://localhost:3003/api/... &     # drive the app; the request hangs at the breakpoint
agent-py-debugger wait --timeout 30         # block until a thread pauses
agent-py-debugger status                    # paused threads + reason + breakpoint id
agent-py-debugger stack                     # call stack with file:line and code line
agent-py-debugger locals --depth 2          # local variables, recursive type/length/truncation
agent-py-debugger eval "token_pair.expires_in"
agent-py-debugger step --over | --into | --out
agent-py-debugger continue                  # release the request
agent-py-debugger disconnect                # resume everything, end the interaction
agent-py-debugger kill --session 5678       # done with a 'run'-launched target: stop it, clean session + logs
agent-py-debugger detach                    # externally-started target only: remove tracing, process keeps running

Commands

connect

agent-py-debugger connect <host:port> [--token T]

Verifies the listener and records a session in ~/.agentdbg/<name>.json (0600, token inside). Subsequent commands reuse the latest session; select one with --session <name> or AGENTDBG_SESSION.

run

agent-py-debugger run [--port N] [--token T] [--suspend] [--foreground] [--auto-continue S] -- <python> <script | -m module> [args...]

Launches a new process with the listener enabled. Non-blocking by default: the command returns as soon as the listener is up and the app keeps running (logs: ~/.agentdbg/run-<token>/app.log). The interpreter may be omitted (-m uvicorn … or a .py path are auto-detected). The target keeps running across connect/disconnect/detach — stop it with kill when you are done with it (below).

breakpoint

agent-py-debugger breakpoint set <file> <line> | file:line [--condition E] [--temporary] [--disabled]
agent-py-debugger breakpoint list | delete <id> | delete --all | enable <id> | disable <id>

Paths are realpath-normalized, symlinks fine. Setting a breakpoint warns when the line carries no bytecode (it would never hit). Conditional breakpoints evaluate the expression in the hit frame; a failing condition is reported on the breakpoint instead of stopping.

wait

agent-py-debugger wait [--timeout S]

Blocks until a thread pauses (or the timeout). Exit code 2 means "no pause within the timeout" — the agent can branch on it.

status / stack / locals / globals / eval

agent-py-debugger status
agent-py-debugger stack [--thread T]
agent-py-debugger locals [--thread T] [--frame I] [--depth D] [--all]
agent-py-debugger globals [--thread T] [--frame I] [--depth D] [--all]
agent-py-debugger eval <expr> [--thread T] [--frame I] [--timeout S]

locals/globals produce recursive descriptions with type, length and truncation — the Variables-view equivalent. eval runs in the paused frame with a timeout (user expressions that hang are contained). --frame selects any frame of the paused thread's stack.

step / continue / disconnect / detach

agent-py-debugger step --over | --into | --out [--thread T]
agent-py-debugger continue [--thread T | --all]
agent-py-debugger disconnect
agent-py-debugger detach

PyCharm stepping semantics. A breakpoint triggers once per execution pass — the CPython after-call line event does not re-trigger it, loop iterations do. disconnect = JVM disconnect (resume everything, listener + breakpoints kept, reconnect anytime). detach removes tracing and shuts the listener down — it is only accepted for targets that were started outside agentdbg run; on a run-managed target it is refused, because the process would be left running with no owner.

kill

agent-py-debugger kill --session <name> | --pid <pid> [--json]

Stops a target that agentdbg run launched: SIGTERM, SIGKILL escalation after ~5s, then removal of the session file and the ~/.agentdbg/run-<token>/ workdir. The name is a session name from agentdbg sessions (the listener port); --session is explicit — kill never falls back to the latest session. --pid is the rescue path for targets whose session file was lost (orphans from an interrupted session).

Ownership is verified against the live process: only a pid running under an agentdbg run bootstrap (~/.agentdbg/run-*/bootstrap.py) is ever killed. A session recorded via connect — a service started with AGENTDBG_LISTEN/install, a process on another machine — is refused with an error: stopping those services belongs to their owner, and detach remains the way to end debugging without touching the process.

sessions / repl / install / resume

agent-py-debugger sessions
agent-py-debugger repl
agent-py-debugger install <site-packages-dir>
agent-py-debugger resume

sessions lists recorded sessions; repl is an interactive prompt for humans; install copies the package + sitecustomize into a venv without any package manager; resume releases a suspend=y target.

Agent Mode

--json prints a single-line envelope on stdout — errors included:

{"ok":true,"paused":true,"paused_threads":[{"thread_id":8451547520,"thread_name":"MainThread",
 "reason":"breakpoint","breakpoint_id":1}],"threads":[…],"breakpoints":2,"suspended":false,"pid":16283}

Exit codes: 0 success / 1 protocol error / 2 wait timed out without a pause. Every command accepts --json; the pause/inspection responses are stable objects safe for jq.

Limits & Caveats

  • One listener per process; after detach a minimal per-call hook remains until the process restarts.
  • A run target never stops itself — disconnect/detach leave the process running by design (JVM model). Stop it with kill when done; a run target that is only ever detached becomes an orphan. Targets started outside agentdbg keep running under their own owner.
  • One thread paused, others running — suspend-all is a future version. Use --thread when stepping multi-threaded programs.
  • Tracing overhead: while the listener is active the target runs under a trace hook (dict-lookup hot path; the same cost class as PyCharm's debugger). detach removes it.
  • Raw threads created via _thread.start_new_thread are not traced; threading.Thread and asyncio code paths are fully covered.
  • A dead agent session cannot freeze the app forever if the target was started with --auto-continue (recommended for production-like targets); pauses always outlive CLI disconnects, so reconnect + continue always works.
  • Trusted networks only: the listener binds a configurable address and requires the session token.

Skill for AI Coding Assistants

Install the agent-py-debugger skill with the skills CLI, directly from GitHub:

npx skills add adamancyzhang/agent-py-debugger

The skill is fetched from this repository (skills/agent-py-debugger/SKILL.md), so it stays up to date automatically. Works with Claude Code, Codex, Cursor, Gemini CLI, and other skills-aware assistants. Do not copy SKILL.md from node_modules — it will become stale.

Manual install for Claude Code:

mkdir -p .claude/skills
cp -r skills/agent-py-debugger .claude/skills/

Development

python3 tests/e2e.py            # end-to-end suite: run/suspend/install modes, breakpoint flow,
                                # after-call no-retrigger regression, connect reliability, kill lifecycle
npm pack --dry-run              # verify the npm tarball
uv build                        # build the python wheel (sitecustomize included)

Layout: agentdbg/ (the Python package: client.py trace engine + protocol server, cli.py commands, connect.py sessions/installation, format.py memory formatting) · bin/ (npm launcher shim) · skills/ (agent skill docs) · tests/ (scratch target + e2e suite) · sitecustomize.py (AGENTDBG_LISTEN bootstrap, shipped by the wheel).

Roadmap

  • Suspend-all pause mode (PyCharm "pause all threads")
  • Tracepoint breakpoints (log and continue)
  • Exception breakpoints
  • Windows raw-thread coverage via a C-level hook

License

MIT © 2026 Adamancy Zhang