textual-debugger 0.2.8__tar.gz → 0.2.12__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/PKG-INFO +422 -84
- {textual_debugger-0.2.8/src/tdb → textual_debugger-0.2.12}/README.md +419 -81
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/pyproject.toml +3 -3
- {textual_debugger-0.2.8 → textual_debugger-0.2.12/src/tdb}/README.md +419 -81
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/__init__.py +1 -1
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/_timeouts.py +11 -0
- textual_debugger-0.2.12/src/tdb/adapters/perl/padwalker.py +286 -0
- textual_debugger-0.2.12/src/tdb/adapters/perl/padwalker_src/Makefile.PL +38 -0
- textual_debugger-0.2.12/src/tdb/adapters/perl/padwalker_src/PadWalker.pm +160 -0
- textual_debugger-0.2.12/src/tdb/adapters/perl/padwalker_src/PadWalker.xs +645 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/perl/session.py +15 -0
- textual_debugger-0.2.12/src/tdb/adapters/powershell/__init__.py +3 -0
- textual_debugger-0.2.12/src/tdb/adapters/powershell/__main__.py +23 -0
- textual_debugger-0.2.12/src/tdb/adapters/powershell/locate.py +121 -0
- textual_debugger-0.2.12/src/tdb/adapters/powershell/output.py +80 -0
- textual_debugger-0.2.12/src/tdb/adapters/powershell/server.py +913 -0
- textual_debugger-0.2.12/src/tdb/adapters/powershell/tdb_launch.ps1 +14 -0
- textual_debugger-0.2.12/src/tdb/adapters/seqs.py +62 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/app.py +31 -16
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/app_handlers/dap_events.py +3 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/app_handlers/inspection.py +71 -1
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/app_handlers/routing.py +36 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/app_handlers/ui_panels.py +39 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/app_helpers.py +51 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/breakpoint_hook.py +16 -1
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/cli.py +398 -26
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/dap/client.py +77 -1
- textual_debugger-0.2.12/src/tdb/eval_mode.py +314 -0
- textual_debugger-0.2.12/src/tdb/examine.py +302 -0
- textual_debugger-0.2.12/src/tdb/go_concurrency/analyzer.py +112 -0
- textual_debugger-0.2.12/src/tdb/go_concurrency/classifier.py +59 -0
- textual_debugger-0.2.12/src/tdb/go_concurrency/collector.py +122 -0
- textual_debugger-0.2.12/src/tdb/go_concurrency/models.py +123 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/languages/base.py +25 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/languages/errors.py +210 -0
- textual_debugger-0.2.12/src/tdb/languages/go.py +217 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/languages/ocaml.py +78 -3
- textual_debugger-0.2.12/src/tdb/languages/powershell.py +124 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/languages/registry.py +26 -3
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/mcp/server.py +24 -9
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/mcp/session.py +1 -1
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/replay.py +28 -8
- textual_debugger-0.2.12/src/tdb/replay_tui.py +311 -0
- textual_debugger-0.2.12/src/tdb/run_mode.py +514 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/server/handlers.py +24 -3
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/server/runner.py +4 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/session/controller.py +173 -19
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/session/inspect_service.py +12 -3
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/session/state.py +7 -0
- textual_debugger-0.2.12/src/tdb/widgets/__init__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/widgets/evaluate_console.py +12 -7
- textual_debugger-0.2.12/src/tdb/widgets/goroutines_modal.py +354 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/textual_debugger.egg-info/PKG-INFO +422 -84
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/textual_debugger.egg-info/SOURCES.txt +22 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/textual_debugger.egg-info/requires.txt +2 -2
- textual_debugger-0.2.8/src/tdb/run_mode.py +0 -271
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/LICENSE +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/setup.cfg +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/__main__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/__init__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/bash/__init__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/bash/__main__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/bash/declares.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/bash/server.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/bash/session.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/bash/tdb_harness.sh +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/ocaml/__init__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/ocaml/lldb_formatters.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/perl/Devel/TdbCompile.pm +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/perl/Devel/TdbRemote.pm +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/perl/__init__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/perl/__main__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/perl/helpers.pl +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/perl/protocol.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/perl/refs.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/perl/server.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/ruby/__init__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/ruby/__main__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/ruby/server.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/tcsh/__init__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/tcsh/__main__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/tcsh/breakpoints.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/tcsh/cli.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/tcsh/guardian.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/tcsh/inspect.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/tcsh/instrumenter.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/tcsh/models.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/tcsh/protocol.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/tcsh/runtime.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/tcsh/scanner.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/tcsh/server.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/tcsh/session.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/adapters/tcsh/transport.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/app_handlers/__init__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/dap/__init__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/dap/messages.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/dap/protocol.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/dap/reverse.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/dap/types.py +0 -0
- {textual_debugger-0.2.8/src/tdb/server → textual_debugger-0.2.12/src/tdb/go_concurrency}/__init__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/inspection.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/inspection_full.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/keybindings/__init__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/languages/__init__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/languages/bash.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/languages/cpp.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/languages/perl.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/languages/python.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/languages/ruby.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/languages/rust.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/languages/tcsh.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/mcp/__init__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/mcp/__main__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/persist.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/post_mortem.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/processes_cache.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/rust_concurrency/__init__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/rust_concurrency/analyzer.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/rust_concurrency/classifier.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/rust_concurrency/collector.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/rust_concurrency/models.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/rust_concurrency/probes/__init__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/rust_concurrency/probes/base.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/rust_concurrency/probes/gdb.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/rust_concurrency/probes/gdb_script.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/rust_concurrency/probes/lldb.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/rust_concurrency/probes/lldb_script.py +0 -0
- {textual_debugger-0.2.8/src/tdb/session → textual_debugger-0.2.12/src/tdb/server}/__init__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/server/app.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/server/event_handler.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/server/rpc_types.py +0 -0
- {textual_debugger-0.2.8/src/tdb/widgets → textual_debugger-0.2.12/src/tdb/session}/__init__.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/session/child_processes.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/session/errors.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/session/event_bus.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/session/messages.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/session/post_mortem_loader.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/session/recorder.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/session/statement_stepper.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/session/terminal.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/session/textual_handler.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/source_analysis.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/widgets/_inspection_modal.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/widgets/async_tasks_modal.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/widgets/breakpoint_view.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/widgets/code_view.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/widgets/console_view.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/widgets/full_contents_modal.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/widgets/menu_bar.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/widgets/modals.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/widgets/processes_modal.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/widgets/rust_concurrency_modal.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/widgets/stack_view.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/widgets/status_bar.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/widgets/threads_modal.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/tdb/widgets/variable_view.py +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/textual_debugger.egg-info/dependency_links.txt +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/textual_debugger.egg-info/entry_points.txt +0 -0
- {textual_debugger-0.2.8 → textual_debugger-0.2.12}/src/textual_debugger.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: textual-debugger
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.12
|
|
4
4
|
Summary: A TUI debugger for Python, Perl, and other languages. Based on textual.
|
|
5
5
|
Author-email: Al Danial <al.danial@gmail.com>
|
|
6
6
|
License: textual-debugger is licensed to you under the MIT/X Consortium license:
|
|
@@ -49,11 +49,11 @@ Requires-Python: >=3.11
|
|
|
49
49
|
Description-Content-Type: text/markdown
|
|
50
50
|
License-File: LICENSE
|
|
51
51
|
Requires-Dist: textual>=8.0.0
|
|
52
|
-
Requires-Dist: debugpy>=1.8.
|
|
52
|
+
Requires-Dist: debugpy>=1.8.12
|
|
53
53
|
Requires-Dist: pygments>=2.17.0
|
|
54
54
|
Requires-Dist: fastapi>=0.115.0
|
|
55
55
|
Requires-Dist: uvicorn>=0.30.0
|
|
56
|
-
Requires-Dist: mcp<
|
|
56
|
+
Requires-Dist: mcp<3.0.0,>=2.0.0
|
|
57
57
|
Provides-Extra: dev
|
|
58
58
|
Requires-Dist: pytest; extra == "dev"
|
|
59
59
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
@@ -79,6 +79,8 @@ with a Debug Adapter Protocol (DAP) implementation. In addition to Python,
|
|
|
79
79
|
- Tcsh (via source instrumentation of a stock `tcsh`)
|
|
80
80
|
- Ruby (via the [debug gem](https://github.com/ruby/debug)'s `rdbg`; debug ≥ 1.9)
|
|
81
81
|
- OCaml (native via `lldb-dap`/`gdb`, bytecode via [ocamlearlybird](https://github.com/hackwaly/ocamlearlybird))
|
|
82
|
+
- Go (via [Delve](https://github.com/go-delve/delve)'s `dlv dap`)
|
|
83
|
+
- PowerShell 7 (via [PowerShell Editor Services](https://github.com/PowerShell/PowerShellEditorServices); Linux/macOS, Windows experimental)
|
|
82
84
|
|
|
83
85
|
`tdb` is built with [textual](https://github.com/Textualize/textual) and speaks
|
|
84
86
|
DAP to a pluggable debug adapter.
|
|
@@ -99,8 +101,9 @@ MIT License. Copyright 2026 by Al Danial.
|
|
|
99
101
|
the richest feature set), C/C++ (via `gdb -i dap` or `lldb-dap`), Rust (via `gdb` or
|
|
100
102
|
`lldb-dap`), Perl (via `perl -d`),
|
|
101
103
|
Bash (via bash's own `DEBUG` trap), Tcsh (via source instrumentation of a
|
|
102
|
-
stock `tcsh`), Ruby (via the debug gem's `rdbg`),
|
|
103
|
-
`lldb-dap`/`gdb`, bytecode via ocamlearlybird)
|
|
104
|
+
stock `tcsh`), Ruby (via the debug gem's `rdbg`), OCaml (native via
|
|
105
|
+
`lldb-dap`/`gdb`, bytecode via ocamlearlybird), Go (via Delve's `dlv
|
|
106
|
+
dap`), and PowerShell 7 (via PowerShell Editor Services). Most languages are
|
|
104
107
|
auto-detected from the target; Rust intentionally requires `--lang rust`
|
|
105
108
|
(ref. [Multi-Language Debugging](#multi-language-debugging)).
|
|
106
109
|
|
|
@@ -110,9 +113,9 @@ It specifically supports modules
|
|
|
110
113
|
- `threading` (with a thread inspector)
|
|
111
114
|
- `multiprocessing` / `concurrent.futures` (with automatic child process attachment and a process inspector)
|
|
112
115
|
|
|
113
|
-
- supports remote attachment to Python, Perl, Ruby, Rust,
|
|
116
|
+
- supports remote attachment to Python, Perl, Ruby, Rust, C/C++, and Go programs
|
|
114
117
|
|
|
115
|
-
- includes a JSON-RPC server mode, an MCP mode, and a `SKILL.md` file that enable
|
|
118
|
+
- includes a JSON-RPC server mode, an MCP (v2) mode, and a `SKILL.md` file that enable
|
|
116
119
|
programmatic debug control, making it suitable for
|
|
117
120
|
automated, headless debugging workflows and AI-assisted debugging
|
|
118
121
|
|
|
@@ -126,28 +129,6 @@ to have `tdb` pop open automatically at the first uncaught exception
|
|
|
126
129
|
making it suitable for operation in non-graphical environments (mouse support is
|
|
127
130
|
available in graphical environments)
|
|
128
131
|
|
|
129
|
-
## Acknowledgments
|
|
130
|
-
|
|
131
|
-
Thank you:
|
|
132
|
-
|
|
133
|
-
- Will McGugan for the amazing `textual` module.
|
|
134
|
-
`tdb` would be a pale shadow of itself had I used any other TUI framework.
|
|
135
|
-
Fantastic work, Will.
|
|
136
|
-
|
|
137
|
-
- Microsoft for the Debug Adapter Protocol (DAP) and releasing
|
|
138
|
-
its implementation in `debugpy` and the Python Debugger extension for Visual Studio Code
|
|
139
|
-
as open source.
|
|
140
|
-
|
|
141
|
-
- Anthropic, for providing access to Claude Code through the
|
|
142
|
-
[Claude for Open Source](https://claude.com/contact-sales/claude-for-oss) program.
|
|
143
|
-
`tdb` was made almost entirely with Claude Code.
|
|
144
|
-
|
|
145
|
-
- OpenAI, for providing access to Codex through the
|
|
146
|
-
[Codex for Open Source](https://developers.openai.com/community/codex-for-oss) program.
|
|
147
|
-
|
|
148
|
-
This project was inspired by Andreas Klöckner's excellent [pudb](https://pypi.org/project/pudb/)
|
|
149
|
-
Python debugger.
|
|
150
|
-
|
|
151
132
|
## Gallery
|
|
152
133
|
<p align="center">
|
|
153
134
|
<img src="https://github.com/AlDanial/tdb/blob/main/gallery/async_breakpoint.png" alt="at breakpoint" width="300">
|
|
@@ -187,6 +168,10 @@ uvx --from textual-debugger tdb my_program.py
|
|
|
187
168
|
# show comprehensive documentation in a terminal-based Markdown viewer
|
|
188
169
|
tdb --doc
|
|
189
170
|
|
|
171
|
+
# show where tdb is installed, where its bundled Perl PadWalker module
|
|
172
|
+
# lives, and the Help > About text
|
|
173
|
+
tdb --info
|
|
174
|
+
|
|
190
175
|
# debug a script (stops at first line by default)
|
|
191
176
|
tdb my_program.py
|
|
192
177
|
|
|
@@ -212,6 +197,10 @@ tdb -k 20 -k 35 -k module.py:14 my_program.py arg1 arg2
|
|
|
212
197
|
# sessions (-t is -k minus the persistence)
|
|
213
198
|
tdb -t 20 my_program.py
|
|
214
199
|
|
|
200
|
+
# no TUI: run at (almost) full speed, printing nr each time line 25 is
|
|
201
|
+
# reached, then continuing (-e may be repeated; see "Eval Mode" below)
|
|
202
|
+
tdb --eval my_program.py:25 "print(f'{nr=}')" my_program.py
|
|
203
|
+
|
|
215
204
|
# use a specific virtualenv
|
|
216
205
|
tdb --python /path/to/venv/bin/python my_program.py
|
|
217
206
|
|
|
@@ -238,6 +227,11 @@ tdb -r remotehost:5678 -k my_program.py:42
|
|
|
238
227
|
# than code on the remote host
|
|
239
228
|
tdb -r remotehost:5678 --local-root /my/code/dir --remote-root /app -k my_program.py:42
|
|
240
229
|
|
|
230
|
+
# attach to a program that pauses itself (debugpy.breakpoint() right after
|
|
231
|
+
# debugpy.wait_for_client()); without this flag tdb pauses the program on
|
|
232
|
+
# attach, which can leave it suspended after tdb quits
|
|
233
|
+
tdb -r remotehost:5678 --no-pause-on-attach
|
|
234
|
+
|
|
241
235
|
# separate tdb arguments from debuggee arguments with `--`
|
|
242
236
|
tdb --python /path/to/venv/bin/python -- my_program.py -k 17 --max 23.3
|
|
243
237
|
```
|
|
@@ -250,7 +244,7 @@ python -m tdb my_program.py
|
|
|
250
244
|
|
|
251
245
|
## Multi-Language Debugging
|
|
252
246
|
|
|
253
|
-
`tdb` debugs any language that has a Debug Adapter Protocol backend.
|
|
247
|
+
`tdb` debugs any language that has a Debug Adapter Protocol backend. Ten
|
|
254
248
|
languages are supported out of the box:
|
|
255
249
|
|
|
256
250
|
| Language | Adapter(s) | Dependencies | Feature level |
|
|
@@ -262,33 +256,42 @@ languages are supported out of the box:
|
|
|
262
256
|
| Bash | bash-tdb (bundled) | bash ≥ 4.4 on PATH | core debugging (no remote attach) |
|
|
263
257
|
| Tcsh | tcsh-tdb (bundled) | tcsh on PATH | core debugging (no remote attach, no conditional breakpoints, no pause) |
|
|
264
258
|
| Ruby | `rdbg` (the [debug gem](https://github.com/ruby/debug)) | `rdbg` ≥ 1.9 on PATH | core debugging + remote attach |
|
|
265
|
-
| OCaml (native executable) | `lldb-dap` (default), `gdb` (alternate) |
|
|
266
|
-
| OCaml (bytecode executable) | `ocamlearlybird` (default) |
|
|
259
|
+
| OCaml (native executable) | `lldb-dap` (default), `gdb` (alternate) | `lldb-dap` ships with LLVM ≥ 17; `gdb -i dap` requires GDB ≥ 14 | core debugging + domains-as-threads; Variables view shows no OCaml locals (upstream DWARF limitation); evaluate console is lldb/C-level, not OCaml |
|
|
260
|
+
| OCaml (bytecode executable) | `ocamlearlybird` (default) | `opam install earlybird` | core debugging + rich OCaml locals; no pause/`--run`, no evaluate responses, no fatal-error modal (ocamlearlybird 1.3.6 limitations); single-domain only |
|
|
261
|
+
| Go | `dlv` (the [Delve](https://github.com/go-delve/delve) DAP server) | Delve ≥ 1.21 on PATH (`go install github.com/go-delve/delve/cmd/dlv@latest`) | core debugging + goroutine inspection (wait graph, findings) + remote attach (no `--terminal`) |
|
|
262
|
+
| PowerShell 7 | `pses` (PowerShell Editor Services, driven by tdb's bundled proxy) | `pwsh` ≥ 7.2 on PATH + the PSES module (see [PowerShell](#powershell)) | core debugging (breakpoints incl. conditional/hit-count/log, stepping, stack, variables, evaluate console) + `--run`; no `--terminal`, no remote attach; Windows untested |
|
|
267
263
|
|
|
268
264
|
### Language detection and selection
|
|
269
265
|
|
|
270
266
|
The language is auto-detected from the debug target:
|
|
271
267
|
|
|
272
|
-
1.
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
268
|
+
1. A directory → Go, if it contains any `*.go` file (a Go package
|
|
269
|
+
directory, e.g. `tdb ./pkg`); otherwise an error naming `--lang`.
|
|
270
|
+
2. File extension: `.py` → Python; `.go` → Go; `.pl` / `.pm` / `.t` → Perl;
|
|
271
|
+
`.sh` / `.bash` → Bash; `.csh` / `.tcsh` → Tcsh; `.rb` → Ruby; `.ps1` /
|
|
272
|
+
`.psm1` → PowerShell. (`.ml` / `.mli` do *not* auto-select OCaml, see
|
|
273
|
+
point 6.)
|
|
274
|
+
3. Native executables (ELF, Mach-O, PE magic bytes) → C/C++, unless
|
|
275
|
+
byte-checking finds an OCaml marker (a native binary's
|
|
277
276
|
`caml_program`/`caml_startup` runtime symbols, a bytecode file's
|
|
278
|
-
trailing `Caml1999` marker, or a `#!...ocamlrun` shebang
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
277
|
+
trailing `Caml1999` marker, or a `#!...ocamlrun` shebang) → OCaml
|
|
278
|
+
(native or bytecode respectively), or a Go buildinfo blob (the marker
|
|
279
|
+
`go version` itself locates, scanned in the first 16MB of the file) →
|
|
280
|
+
Go. A stripped native OCaml binary, or a Go binary whose buildinfo
|
|
281
|
+
blob sits beyond the 16MB scan window, that byte-checking can't
|
|
282
|
+
identify falls back to C/C++; force it with `--lang ocaml` or `--lang
|
|
283
|
+
go` respectively. Rust is never inferred from an executable; select it
|
|
284
|
+
explicitly with `--lang rust`.
|
|
285
|
+
4. A `#!...python`, `#!...perl`, `#!...bash`, `#!...csh`/`#!...tcsh`,
|
|
286
|
+
`#!...ruby`, or `#!...pwsh` shebang → Python / Perl / Bash / Tcsh / Ruby /
|
|
287
|
+
PowerShell respectively.
|
|
288
|
+
5. C/C++/Rust *source* files (`.c`, `.cpp`, `.rs`, …) produce an error with a
|
|
286
289
|
hint: compile with debug info (`g++ -g -O0`) and debug the binary.
|
|
287
|
-
|
|
290
|
+
6. `.ml` / `.mli` (OCaml source) produce an error too: build the project
|
|
288
291
|
first (dune's dev profile keeps debug info) and pass the **built
|
|
289
292
|
executable** to `tdb` (`tdb ./_build/default/bin/main.exe`), never the
|
|
290
293
|
`.ml` file.
|
|
291
|
-
|
|
294
|
+
7. Anything else produces an error naming the `--lang` override.
|
|
292
295
|
|
|
293
296
|
`--lang` forces the language; `--adapter` picks a non-default adapter within
|
|
294
297
|
it (`tdb --lang cpp --adapter lldb-dap ./myprog`). Rust always requires the
|
|
@@ -316,23 +319,29 @@ non-standard location, or change a language's default adapter, add to
|
|
|
316
319
|
Core debugging works identically for every language: breakpoints (incl.
|
|
317
320
|
conditions and persistence), stepping, continue/pause, run-to-cursor, stack
|
|
318
321
|
navigation, variable inspection, the evaluate console, syntax highlighting,
|
|
319
|
-
and the JSON-RPC / MCP programmatic modes.
|
|
322
|
+
and the JSON-RPC / MCP (v2) programmatic modes.
|
|
320
323
|
|
|
321
324
|
Python-specific features are hidden or return "not supported for this
|
|
322
325
|
language" message when debugging other languages: statement-granularity
|
|
323
|
-
stepping (non-Python languages
|
|
324
|
-
|
|
326
|
+
stepping (non-Python languages step at their debugger's native granularity
|
|
327
|
+
— per line, except PowerShell, whose debugger stops per statement, see
|
|
328
|
+
[PowerShell](#powershell)), the async task / process inspectors and wait
|
|
329
|
+
graph, the evaluate console's trailing-`?` help,
|
|
325
330
|
`--python`/`--pv`, `--no-subprocess`, automatic child-process attachment, and
|
|
326
331
|
the post-mortem / `tdb.breakpoint()` hooks (those hooks live inside Python
|
|
327
332
|
programs by nature). Remote attach (`-r`) also works for Perl (see
|
|
328
333
|
[Perl](#perl), `Devel::TdbRemote` in place of `debugpy.listen()`), Ruby
|
|
329
|
-
(see [Ruby](#ruby), `rdbg --open` in place of `debugpy.listen()`),
|
|
334
|
+
(see [Ruby](#ruby), `rdbg --open` in place of `debugpy.listen()`), Go (see
|
|
335
|
+
[Go](#go), `dlv dap --listen` in place of `debugpy.listen()`), and for
|
|
330
336
|
Rust and C/C++ native binaries (against a gdbserver/lldb-server stub, with
|
|
331
337
|
a local symbol-bearing executable; see [Rust](#rust) — the same flags work
|
|
332
|
-
for a C/C++ target without `--lang`), but not for Bash, Tcsh,
|
|
338
|
+
for a C/C++ target without `--lang`), but not for Bash, Tcsh, OCaml, or
|
|
339
|
+
PowerShell. `--terminal` works for every launch-mode
|
|
333
340
|
language — Python, Perl, Bash, Tcsh, Ruby, and C/C++, OCaml native, or Rust
|
|
334
341
|
sessions via `--adapter lldb-dap` — see
|
|
335
|
-
[External Terminal Support](#external-terminal-support).
|
|
342
|
+
[External Terminal Support](#external-terminal-support). Go and PowerShell do
|
|
343
|
+
not support `--terminal` yet (`dlv dap` and PSES have no terminal-routing
|
|
344
|
+
mode).
|
|
336
345
|
|
|
337
346
|
**Bash limitations (v1):** the bash adapter uses bash's own `DEBUG` trap and
|
|
338
347
|
has a smaller feature set than Python:
|
|
@@ -397,7 +406,30 @@ picture:
|
|
|
397
406
|
reaches `tdb`). Run the program outside the debugger to see the
|
|
398
407
|
backtrace instead.
|
|
399
408
|
- No Windows support, no remote attach, and a stripped native binary that
|
|
400
|
-
byte-
|
|
409
|
+
byte-checking can't identify needs `--lang ocaml`.
|
|
410
|
+
|
|
411
|
+
**Go limitations (v1):**
|
|
412
|
+
|
|
413
|
+
- `--terminal` is not supported (`dlv dap` has no terminal-routing mode).
|
|
414
|
+
- The Goroutines workspace's wait graph shows channel-send/-receive,
|
|
415
|
+
mutex, and `WaitGroup` edges; a goroutine parked in a `select` is
|
|
416
|
+
classified but contributes no wait edge (Delve can't tell which of the
|
|
417
|
+
`select`'s cases it's waiting on).
|
|
418
|
+
- No mutex-holder identification: Go's `sync.Mutex` doesn't record an
|
|
419
|
+
owner at the runtime level, so unlike Python's Lock/Semaphore inspector
|
|
420
|
+
the wait graph can name what a goroutine is blocked on but never who
|
|
421
|
+
holds it.
|
|
422
|
+
- Goroutines spawned by `exec.Command` (child OS processes) are not
|
|
423
|
+
automatically attached or debugged, unlike Python's automatic
|
|
424
|
+
multiprocessing child attach.
|
|
425
|
+
- Detection of a Go binary via buildinfo check scans only the first
|
|
426
|
+
16MB of the file; a huge binary whose buildinfo blob sits beyond that
|
|
427
|
+
falls back to C/C++ — force it with `--lang go`.
|
|
428
|
+
- `-a`/`--attach`'s language auto-detection (reading the target pid's
|
|
429
|
+
buildinfo from `/proc/PID/exe`) is Linux-only; on macOS/Windows pass
|
|
430
|
+
`--lang go` alongside `-a`.
|
|
431
|
+
|
|
432
|
+
See [Go](#go) below for launch details.
|
|
401
433
|
|
|
402
434
|
### C/C++ tips
|
|
403
435
|
|
|
@@ -491,6 +523,24 @@ metadata for broader primitives and stronger ownership evidence.
|
|
|
491
523
|
`perl` ≥ 5.18 on `PATH`. It drives stock `perl5db` under the
|
|
492
524
|
hood, so it works with any Perl already on the system.
|
|
493
525
|
|
|
526
|
+
The [PadWalker](https://metacpan.org/pod/PadWalker) module v2.5, by Robin Houston,
|
|
527
|
+
is bundled with `tdb`. PadWalker provides a more complete view of lexical variables
|
|
528
|
+
in outer/caller frames and therefore provides a richer debugging experience.
|
|
529
|
+
PadWalker is an XS (compiled) module, so the bundled copy has to be built
|
|
530
|
+
against the exact perl that runs your program. `tdb` does this for you on the
|
|
531
|
+
first Perl launch: if the perl in use cannot already load PadWalker (from CPAN
|
|
532
|
+
or a distro package), `tdb` compiles the bundled sources, caches the result
|
|
533
|
+
per interpreter under its config directory (`~/.config/tdb/padwalker/` on
|
|
534
|
+
Linux/macOS, `%APPDATA%\\tdb\\padwalker\\` on Windows), and prepends that
|
|
535
|
+
directory to the debuggee's `PERL5LIB`. The build takes about a second and
|
|
536
|
+
needs perl's headers (`libperl-dev` on Debian/Ubuntu, `perl-devel` on
|
|
537
|
+
Fedora/RHEL) plus a C compiler; Strawberry Perl on Windows ships both. When
|
|
538
|
+
the build is not possible, `tdb` prints a one-line notice on the console and
|
|
539
|
+
falls back to a read-only pad walk, so outer-frame lexicals degrade but
|
|
540
|
+
debugging otherwise proceeds. `tdb --info` reports the source directory, the
|
|
541
|
+
cache directory, and whether a build exists for the `perl` on your `PATH`.
|
|
542
|
+
`TDB_PADWALKER_CACHE` overrides the cache location.
|
|
543
|
+
|
|
494
544
|
**Launching a script:**
|
|
495
545
|
|
|
496
546
|
```bash
|
|
@@ -587,13 +637,6 @@ export PERL5LIB=/opt/tdb-perl:$PERL5LIB
|
|
|
587
637
|
the two files in the same relative layout shown above; `helpers.pl` is a
|
|
588
638
|
sibling of the `Devel/` directory, not inside it.)
|
|
589
639
|
|
|
590
|
-
**PadWalker (optional but recommended):** inspecting lexical (`my`)
|
|
591
|
-
variables in the *current* frame always works. Lexicals in outer/caller
|
|
592
|
-
frames need the `PadWalker` module installed on the debuggee's Perl; without
|
|
593
|
-
it, tdb falls back to a read-only pad walk that can't reach fully into
|
|
594
|
-
enclosing scopes, and outer-frame variable listings degrade accordingly.
|
|
595
|
-
Install with `cpanm PadWalker` (or your distro's package) for full fidelity.
|
|
596
|
-
|
|
597
640
|
**Pause is unavailable in attach mode.** Launch-mode sessions (`tdb
|
|
598
641
|
script.pl`) support pausing a running program at any time. Remote-attach
|
|
599
642
|
sessions don't. Asynchronous pause (as Python gets via `debugpy`) needs a control channel
|
|
@@ -703,18 +746,35 @@ does). Always pass the **built executable** to `tdb`, never the `.ml`
|
|
|
703
746
|
source, as in `tdb ./_build/default/bin/main.exe`, not `tdb main.ml` (which
|
|
704
747
|
errors with this exact guidance).
|
|
705
748
|
|
|
749
|
+
Earlybird additionally as a fragile relative path matching so for
|
|
750
|
+
best results provide a fully quallified path to the source files.
|
|
751
|
+
|
|
752
|
+
```
|
|
753
|
+
ocamlc -g -o my_program.byte "$PWD/my_program.ml"
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
Then, to ensure transition from bytecode to OCaml source in the
|
|
757
|
+
Code view, provide an explicit temporary breakpoint (`-t`)
|
|
758
|
+
at the first line of execution:
|
|
759
|
+
|
|
760
|
+
```
|
|
761
|
+
tdb --lang ocaml --adapter ocamlearlybird -t "$PWD/my_program.ml:2" ./my_program.byte
|
|
762
|
+
```
|
|
763
|
+
|
|
706
764
|
**OCaml version:** tdb requires **OCaml ≥ 4.12**. Older runtimes print
|
|
707
765
|
`Printexc` backtraces without function names, which the fatal-error
|
|
708
766
|
modal's parser does not understand (frames would be dropped and the
|
|
709
767
|
modal would wrongly suggest recompiling with `-g`).
|
|
710
768
|
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
769
|
+
With native GDB, the default entry stop is translated to the first
|
|
770
|
+
executable line in project OCaml source; the generated C/ELF startup code is
|
|
771
|
+
not shown.
|
|
772
|
+
Unfortunately OCaml's native debug information does not always identify
|
|
773
|
+
tihs line correctly.
|
|
774
|
+
`--no-stop-on-entry` and explicit CLI breakpoints retain their
|
|
775
|
+
usual behavior.
|
|
716
776
|
|
|
717
|
-
A stripped native binary that byte-
|
|
777
|
+
A stripped native binary that byte-checking can't identify as OCaml falls
|
|
718
778
|
back to C/C++; force it with `--lang ocaml`. Override the adapter or point
|
|
719
779
|
at a non-`PATH` install in `config.json` (see
|
|
720
780
|
[Configuration](#configuration)):
|
|
@@ -774,6 +834,139 @@ sessions can't `pause` a running program (so `--run` is unavailable for
|
|
|
774
834
|
bytecode. Native sessions support `--run` normally); `Unix.fork` and Eio
|
|
775
835
|
fibers are out of scope (only OCaml 5 domains are presented as threads).
|
|
776
836
|
|
|
837
|
+
### Go
|
|
838
|
+
|
|
839
|
+
`tdb` debugs Go through [Delve](https://github.com/go-delve/delve)'s own
|
|
840
|
+
DAP server, `dlv dap` (Delve ≥ 1.21). Install it with:
|
|
841
|
+
|
|
842
|
+
```bash
|
|
843
|
+
go install github.com/go-delve/delve/cmd/dlv@latest
|
|
844
|
+
```
|
|
845
|
+
|
|
846
|
+
`dlv` must be on `PATH`, or point tdb at it with
|
|
847
|
+
`{"adapters": {"dlv": "/path/to/dlv"}}` in `config.json`.
|
|
848
|
+
|
|
849
|
+
**Launch modes** — `tdb` picks the right Delve mode automatically:
|
|
850
|
+
|
|
851
|
+
```bash
|
|
852
|
+
tdb main.go # source file: `go run`-style debug mode
|
|
853
|
+
tdb ./pkg # package directory: `go run`-style debug mode
|
|
854
|
+
tdb ./binary # pre-built Go binary (buildinfo-detected): exec mode
|
|
855
|
+
tdb --test ./pkg # Go test package: Delve test mode
|
|
856
|
+
tdb -a PID # attach to a running local Go process by pid
|
|
857
|
+
tdb -r host:port --lang go # attach to a `dlv dap --listen` already running remotely
|
|
858
|
+
```
|
|
859
|
+
|
|
860
|
+
`tdb --test ./pkg` debugs the package's tests under Delve's `test` mode;
|
|
861
|
+
pass test-binary flags after `--`, e.g. `tdb --test ./pkg -- -run TestFoo`.
|
|
862
|
+
`-a`/`--attach` currently supports Go only; on Linux, and only on Linux,
|
|
863
|
+
`tdb` can identify the target as Go from `/proc/PID/exe`'s buildinfo
|
|
864
|
+
without `--lang` (elsewhere pass `--lang go` alongside `-a`). Attaching
|
|
865
|
+
stops the process immediately so you get control right away.
|
|
866
|
+
|
|
867
|
+
**Remote attach:** start Delve's own DAP server against your program
|
|
868
|
+
first —
|
|
869
|
+
|
|
870
|
+
```bash
|
|
871
|
+
dlv dap --listen=host:port ./binary
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
— then connect from `tdb`:
|
|
875
|
+
|
|
876
|
+
```bash
|
|
877
|
+
tdb -r host:port --lang go
|
|
878
|
+
```
|
|
879
|
+
|
|
880
|
+
Do not expose the port to an untrusted network; prefer an SSH tunnel.
|
|
881
|
+
|
|
882
|
+
**Goroutine inspection:** in a Go session the Threads action (`Alt+T`, or
|
|
883
|
+
the **Goroutines (N)** menu label) opens the Goroutines workspace while
|
|
884
|
+
the debuggee is stopped — a fresh, bounded snapshot of goroutines, wait
|
|
885
|
+
edges, and findings, the same shape as the Rust Concurrency workspace.
|
|
886
|
+
Goroutines parked entirely in Go-runtime internals (GC workers,
|
|
887
|
+
finalizers, netpoll) are hidden by default; press `a` to reveal them
|
|
888
|
+
alongside the rest. The **Wait Graph** tab groups goroutines by the
|
|
889
|
+
channel, mutex, or `WaitGroup` they're blocked on; the **Findings** tab
|
|
890
|
+
surfaces stuck channels, mutex convoys, and likely leaks with a
|
|
891
|
+
confidence level (`confirmed` vs `probable`) — Go mutexes never record an
|
|
892
|
+
owner, so, unlike Python's Lock/Semaphore inspector, findings can name
|
|
893
|
+
what's blocked but not who holds it. The snapshot collects up to 150
|
|
894
|
+
goroutines; a busier program reports the header
|
|
895
|
+
`Goroutines (150) — N more not collected` rather than silently truncating.
|
|
896
|
+
Refresh (`r`) after the next stop to collect a new snapshot.
|
|
897
|
+
|
|
898
|
+
**Limitations (v1):** `--terminal` is not supported (`dlv dap` has no
|
|
899
|
+
terminal-routing mode); a goroutine parked in a `select` is classified but
|
|
900
|
+
contributes no wait edge (Delve can't tell which case it's waiting on);
|
|
901
|
+
no mutex-holder identification (impossible for Go's runtime); goroutines
|
|
902
|
+
spawned indirectly via `exec.Command` child OS processes are not
|
|
903
|
+
automatically attached; buildinfo-based binary detection scans only the
|
|
904
|
+
first 16MB of the file (`--lang go` overrides for anything larger); `-a`'s
|
|
905
|
+
`/proc`-based language auto-detection is Linux-only (pass `--lang go`
|
|
906
|
+
alongside `-a` on macOS/Windows).
|
|
907
|
+
|
|
908
|
+
### PowerShell
|
|
909
|
+
|
|
910
|
+
tdb debugs PowerShell 7 scripts through [PowerShell Editor Services](https://github.com/PowerShell/PowerShellEditorServices)
|
|
911
|
+
(PSES), the Debug Adapter Protocol server behind the VS Code PowerShell
|
|
912
|
+
extension. You need `pwsh` (>= 7.2; https://aka.ms/powershell) on PATH
|
|
913
|
+
and the PSES module. tdb looks for the module in this order:
|
|
914
|
+
|
|
915
|
+
1. `{"adapters": {"pses": "/path/to/PowerShellEditorServices"}}` in `config.json`
|
|
916
|
+
2. the `TDB_PSES_PATH` environment variable
|
|
917
|
+
3. the copy bundled with an installed VS Code PowerShell extension
|
|
918
|
+
(`~/.vscode/extensions/ms-vscode.powershell-*/modules/PowerShellEditorServices`)
|
|
919
|
+
|
|
920
|
+
Without VS Code, download the release once:
|
|
921
|
+
|
|
922
|
+
```bash
|
|
923
|
+
mkdir -p ~/.local/share/tdb/pses && cd ~/.local/share/tdb/pses
|
|
924
|
+
curl -sLO https://github.com/PowerShell/PowerShellEditorServices/releases/download/v4.7.0/PowerShellEditorServices.zip
|
|
925
|
+
unzip -q PowerShellEditorServices.zip
|
|
926
|
+
export TDB_PSES_PATH=~/.local/share/tdb/pses/PowerShellEditorServices
|
|
927
|
+
```
|
|
928
|
+
|
|
929
|
+
A `pwsh` that isn't on PATH can be named with `{"adapters": {"pwsh": "/path/to/pwsh"}}`.
|
|
930
|
+
|
|
931
|
+
```bash
|
|
932
|
+
tdb script.ps1 # launch, stop at the first statement
|
|
933
|
+
tdb --run script.ps1 # run immediately, debug on demand (pause works)
|
|
934
|
+
```
|
|
935
|
+
|
|
936
|
+
Notes:
|
|
937
|
+
|
|
938
|
+
- Entry stop lands on the first statement of your script (comments and
|
|
939
|
+
function definitions are skipped): PSES has no native `stopOnEntry` for
|
|
940
|
+
this launch shape, so tdb sets a synthetic breakpoint on the bundled
|
|
941
|
+
launcher, steps in, and clears it — no line-1 breakpoint appears in the
|
|
942
|
+
Breakpoint view.
|
|
943
|
+
- The script runs inside that small bundled launcher (`tdb_launch.ps1`) so
|
|
944
|
+
tdb can report the script's exit code. In the Stack view, top to bottom:
|
|
945
|
+
PSES's `<Breakpoint>` marker frame (the frame to inspect — it tracks the
|
|
946
|
+
accurate current position), your script's own frames, the launcher's
|
|
947
|
+
`<ScriptBlock>`, and a source-less `Interactive Session` frame at the
|
|
948
|
+
bottom.
|
|
949
|
+
- Stepping is statement-granular, as in VS Code: a line containing a
|
|
950
|
+
`$( ... )` subexpression takes two `next` presses to clear, and `stepIn`
|
|
951
|
+
first lands on the called function's declaration line before its body.
|
|
952
|
+
- An uncaught terminating error ends the script with exit code 1 and opens
|
|
953
|
+
the fatal-error modal from pwsh's concise error text. Non-terminating
|
|
954
|
+
errors (`Write-Error`, failing cmdlets without `-ErrorAction Stop`) print
|
|
955
|
+
the same concise error block to the Console as stderr and let the script
|
|
956
|
+
continue with exit code 0, as in pwsh itself; there is no break-on-error
|
|
957
|
+
yet. The error block names the launcher's `& $Script` line rather than
|
|
958
|
+
your script's actual line for some error kinds (a known cosmetic
|
|
959
|
+
limitation).
|
|
960
|
+
- The fatal-error modal is gated on a non-zero exit code, since pwsh prints
|
|
961
|
+
the identical block for terminating and non-terminating errors. A script
|
|
962
|
+
that reports a non-terminating error and then `exit 3` can therefore still
|
|
963
|
+
raise the modal, showing the last error block that names a file of yours;
|
|
964
|
+
blocks attributed to tdb's own `tdb_launch.ps1` are skipped, so a bare
|
|
965
|
+
`Write-Error` before the `exit` opens no modal at all.
|
|
966
|
+
- `--terminal` and remote attach are not supported for PowerShell yet.
|
|
967
|
+
- Windows PowerShell 5.1 is not supported (pwsh 7 only). Running tdb *on*
|
|
968
|
+
Windows against pwsh is designed for but not yet verified (experimental).
|
|
969
|
+
|
|
777
970
|
## Layout
|
|
778
971
|
|
|
779
972
|
```
|
|
@@ -900,7 +1093,9 @@ stops on each physical line--useful for inspecting how a complex expression is b
|
|
|
900
1093
|
The choice is saved to `~/.config/tdb/config.json`.
|
|
901
1094
|
|
|
902
1095
|
Statement mode requires a source-language model and is currently Python-only;
|
|
903
|
-
other languages
|
|
1096
|
+
other languages step at their debugger's native granularity — per line,
|
|
1097
|
+
except PowerShell, whose debugger stops per statement, see
|
|
1098
|
+
[PowerShell](#powershell) (the Step Mode menu says so if you try).
|
|
904
1099
|
|
|
905
1100
|
### Breakpoints
|
|
906
1101
|
|
|
@@ -1266,12 +1461,14 @@ sessions via `--adapter lldb-dap`. Neither `gdb -i dap` (the default C/C++
|
|
|
1266
1461
|
adapter, and an alternate for native OCaml) nor `ocamlearlybird` (the
|
|
1267
1462
|
bytecode OCaml adapter) has any terminal integration -- `tdb` rejects
|
|
1268
1463
|
`--terminal` up front for both, with an error pointing at `--adapter
|
|
1269
|
-
lldb-dap` instead.
|
|
1270
|
-
|
|
1271
|
-
|
|
1464
|
+
lldb-dap` instead. Go and PowerShell don't support `--terminal` either
|
|
1465
|
+
(`dlv dap` has no terminal-routing mode; PSES likewise). `--terminal` also
|
|
1466
|
+
only applies when `tdb` launches the program itself; it is rejected for
|
|
1467
|
+
remote-attach (`-r`), since there's no program for `tdb` to spawn a
|
|
1468
|
+
terminal around.
|
|
1272
1469
|
|
|
1273
1470
|
The debuggee runs in a separate window of the specified terminal, including
|
|
1274
|
-
all of its stdin/stdout/stderr
|
|
1471
|
+
all of its stdin/stdout/stderr. Keyboard input, program output, and
|
|
1275
1472
|
anything the program itself draws to the terminal all happen in that
|
|
1276
1473
|
window, not in `tdb`'s Console View. Supported choices:
|
|
1277
1474
|
`xterm`, `konsole`, `gnome-terminal`, `ghostty`, `kitty`, `iterm2`, `warp`,
|
|
@@ -1309,10 +1506,58 @@ tdb --run my_program.py; echo $? # my_program.py's own exit code
|
|
|
1309
1506
|
**Interrupting:** press Ctrl-C in the terminal (any platform), or, on Unix, send
|
|
1310
1507
|
`SIGUSR1` to `tdb`'s pid from another terminal: `kill -USR1 <tdb pid>`. Either one pauses
|
|
1311
1508
|
the debuggee at its currently executing line and opens the TUI with full debugging
|
|
1312
|
-
available
|
|
1509
|
+
available (breakpoints, stepping, variable inspection, the evaluate console). The
|
|
1313
1510
|
debuggee itself never receives the signal (`tdb`'s adapter runs in its own process
|
|
1314
1511
|
group), so its own `SIGINT` handling is undisturbed.
|
|
1315
1512
|
|
|
1513
|
+
**Examining without opening the TUI:** press `Ctrl-\` in the terminal (`Ctrl-Break` on
|
|
1514
|
+
Windows), or, on Unix, send `SIGUSR2` to `tdb`'s pid: `kill -USR2 <tdb pid>`.
|
|
1515
|
+
|
|
1516
|
+
**Windows caveat:** the Ctrl-Break trigger is untested. Unlike Ctrl-C, a console
|
|
1517
|
+
Ctrl-Break is delivered to every process attached to the console, including the debug
|
|
1518
|
+
adapter and the program itself, so it may terminate the program instead of snapshotting
|
|
1519
|
+
it. There is no signal-based alternative on Windows.
|
|
1520
|
+
|
|
1521
|
+
`tdb` pauses the program, writes one JSON line describing the call stack of every thread
|
|
1522
|
+
(plus asyncio tasks and multiprocessing children for Python, goroutines for Go, and
|
|
1523
|
+
the concurrency snapshot for Rust), and resumes the program. Ctrl-C behavior is
|
|
1524
|
+
unchanged. By default the line goes to stdout; `--examine-log DEST` sends it to a file
|
|
1525
|
+
instead (`-` means stdout; repeat the flag to write to several places):
|
|
1526
|
+
|
|
1527
|
+
```bash
|
|
1528
|
+
tdb --run --examine-log hang.jsonl my_program.py # file only, appended
|
|
1529
|
+
tdb --run --examine-log - --examine-log hang.jsonl my_program.py # both
|
|
1530
|
+
```
|
|
1531
|
+
|
|
1532
|
+
Each record looks like (abridged):
|
|
1533
|
+
|
|
1534
|
+
```json
|
|
1535
|
+
{"schema":1,"seq":1,"trigger":"SIGQUIT","status":"ok",
|
|
1536
|
+
"requested_at":"2026-09-07T14:02:11.482-07:00","landed_at":"2026-09-07T14:02:11.511-07:00",
|
|
1537
|
+
"elapsed_s":87.3,"language":"python","program":"/home/al/work/app.py",
|
|
1538
|
+
"processes":[{"pid":41213,"role":"parent","name":null,
|
|
1539
|
+
"threads":[{"id":1,"name":"MainThread","frames":[
|
|
1540
|
+
{"function":"wait","file":"/usr/lib/python3.13/threading.py","line":359},
|
|
1541
|
+
{"function":"main","file":"/home/al/work/app.py","line":42}]}],
|
|
1542
|
+
"tasks":[{"name":"worker-2","state":"PENDING","awaiting":"Lock.acquire","frames":["run (/home/al/work/app.py:18)"]}]}],
|
|
1543
|
+
"errors":[]}
|
|
1544
|
+
```
|
|
1545
|
+
|
|
1546
|
+
Frames are innermost first. `tasks` appears only for Python programs with live asyncio
|
|
1547
|
+
tasks; `goroutines` only for Go; `rust_concurrency` only for Rust. `status` is
|
|
1548
|
+
`"pending"` when the pause could not land within a few seconds (the program is blocked
|
|
1549
|
+
inside a single call) -- a second record with the same `seq` and `status: "ok"` follows
|
|
1550
|
+
when it does land. If you press Ctrl-C or the program exits before it lands, no
|
|
1551
|
+
completing record is written. `errors` lists any sub-collector that failed, so a partial
|
|
1552
|
+
record is explicit about what is missing. A stderr line confirms each capture and where
|
|
1553
|
+
it went.
|
|
1554
|
+
|
|
1555
|
+
Narrow a long capture with `jq`, for example only threads with a frame in your own code:
|
|
1556
|
+
|
|
1557
|
+
```bash
|
|
1558
|
+
jq -c '.processes[].threads[] | select(any(.frames[]; .file != null and (.file|test("/work/"))))' hang.jsonl
|
|
1559
|
+
```
|
|
1560
|
+
|
|
1316
1561
|
**Quitting an adopted session** adds a third choice to the usual quit dialog:
|
|
1317
1562
|
- `d` (or `q`) -- detach and resume: the program keeps running headlessly; interrupt it
|
|
1318
1563
|
again later the same way.
|
|
@@ -1327,18 +1572,61 @@ nonzero `sys.exit()`, which `debugpy` treats as an uncaught `SystemExit` -- `tdb
|
|
|
1327
1572
|
the TUI at the point of failure instead of exiting silently, so you can inspect the
|
|
1328
1573
|
crash. Exit-code passthrough applies only to a clean exit during the headless phase.
|
|
1329
1574
|
|
|
1330
|
-
Supported languages: Python, Perl, Bash, Tcsh, Ruby, C/C++
|
|
1331
|
-
`lldb-dap`), and native OCaml (both `gdb` and `lldb-dap`;
|
|
1332
|
-
|
|
1333
|
-
for those). `--run` is rejected up front for any other
|
|
1575
|
+
Supported languages: Python, Perl, Bash, Tcsh, Ruby, PowerShell 7, C/C++
|
|
1576
|
+
(both `gdb` and `lldb-dap`), and native OCaml (both `gdb` and `lldb-dap`;
|
|
1577
|
+
bytecode/`ocamlearlybird` sessions don't support pause, so `--run` is
|
|
1578
|
+
unavailable for those). `--run` is rejected up front for any other
|
|
1579
|
+
language.
|
|
1334
1580
|
|
|
1335
1581
|
**Limitation:** pausing is cooperative. If the debuggee is blocked inside a single
|
|
1336
1582
|
blocking external call or syscall, the pause can't land until that call returns --
|
|
1337
1583
|
`tdb` prints a notice and opens the TUI once the stop actually arrives.
|
|
1338
1584
|
|
|
1339
|
-
**Incompatible flags:** `-r`, `-k`/`-t`, `--record`, `--replay`, `--server`,
|
|
1585
|
+
**Incompatible flags:** `-r`, `-k`/`-t`, `--record`, `--replay`, `--replay-tui`, `--server`,
|
|
1340
1586
|
`--headless`, `--mcp`, `--terminal`.
|
|
1341
1587
|
|
|
1588
|
+
### Eval Mode (`-e`/`--eval`)
|
|
1589
|
+
|
|
1590
|
+
Eval mode automates a common debugging loop--set a breakpoint, run to it,
|
|
1591
|
+
evaluate an expression in the Evaluate console, continue--without
|
|
1592
|
+
opening the TUI. `-e` takes two arguments, a location and an expression:
|
|
1593
|
+
|
|
1594
|
+
```bash
|
|
1595
|
+
tdb --eval examples/digits_of_pi.py:25 "print(f'{nr=}')" examples/digits_of_pi.py
|
|
1596
|
+
```
|
|
1597
|
+
|
|
1598
|
+
sets a breakpoint at line 25, runs the program, and each time that line is
|
|
1599
|
+
reached evaluates `print(f'{nr=}')` in the stopped frame, then continues.
|
|
1600
|
+
Program output and evaluation output both stream to the terminal; when the
|
|
1601
|
+
program exits, `tdb` exits with the same code (and with `1` if the session
|
|
1602
|
+
ends without one--as with a crash or killed adapter--so a scripted `tdb -e ...
|
|
1603
|
+
&& next` can trust the exit status). `Ctrl-C` stops the program and exits
|
|
1604
|
+
`130`. Under `multiprocessing`, an eval point placed in child code is
|
|
1605
|
+
evaluated in each child process that reaches it.
|
|
1606
|
+
|
|
1607
|
+
- The location is `FILE:LINE`, or a bare `LINE` of the program being debugged,
|
|
1608
|
+
and is snapped to the start of a logical statement just like `-k`.
|
|
1609
|
+
- `-e` may be repeated to plant several eval points in one run.
|
|
1610
|
+
- The expression is evaluated through the debug adapter (DAP `evaluate`,
|
|
1611
|
+
context `repl`), just like the Evaluate console: side effects are real
|
|
1612
|
+
and persist in the running program, for example
|
|
1613
|
+
`-e my_program.py:25 "limit = 10"` changes `limit` from line 25 onward.
|
|
1614
|
+
- A bare expression's result is printed to stdout; statement-style
|
|
1615
|
+
expressions (`print(...)`, assignments) print nothing beyond their own
|
|
1616
|
+
output. An expression error is reported on stderr and the run continues --
|
|
1617
|
+
a typo isn't fatal, matching the Evaluate console.
|
|
1618
|
+
- Saved breakpoints are ignored, and any other stop (e.g. an
|
|
1619
|
+
uncaught-exception stop) is continued untouched, so the program runs to
|
|
1620
|
+
completion unattended.
|
|
1621
|
+
- For non-Python debuggees the expression must be in the debug adapter's
|
|
1622
|
+
own syntax, for example gdb's `print x` / `set var x=3` for C/C++, and not
|
|
1623
|
+
necessarily the debuggee's language. The adapter may bind the breakpoint
|
|
1624
|
+
to the next executable line (gdb moves one off a declaration or brace);
|
|
1625
|
+
the eval point matches that bound line, so the expression still runs.
|
|
1626
|
+
|
|
1627
|
+
**Incompatible flags:** `--run`, `-r`, `-a`, `-k`/`-t`, `--record`,
|
|
1628
|
+
`--replay`, `--replay-tui`, `--server`, `--headless`, `--mcp`, `--terminal`.
|
|
1629
|
+
|
|
1342
1630
|
### Keybinding Schemes
|
|
1343
1631
|
|
|
1344
1632
|
```bash
|
|
@@ -1459,14 +1747,29 @@ written to `session.jsonl` as
|
|
|
1459
1747
|
JSON-RPC commands. Works with launch mode (any language) and `-r`
|
|
1460
1748
|
remote attach.
|
|
1461
1749
|
|
|
1462
|
-
Replay it
|
|
1463
|
-
|
|
1750
|
+
Replay it three ways:
|
|
1751
|
+
|
|
1752
|
+
- `tdb --replay-tui session.jsonl` opens the normal TUI on the recorded
|
|
1753
|
+
program and performs every recorded action in front of you, at the
|
|
1754
|
+
recorded pace: breakpoints appear in the Code View, steps and continues
|
|
1755
|
+
move the cursor, Evaluate entries echo into the console with their
|
|
1756
|
+
results, stack navigation and variable expansion play out in their
|
|
1757
|
+
panels. The title bar shows progress (`tdb ▶ session.jsonl 3/11`) and a
|
|
1758
|
+
toast announces each action (`--replay-quiet` turns those toasts off).
|
|
1759
|
+
A failed action raises an error toast and replay continues. When the recording does not end with `quit`, the
|
|
1760
|
+
debugger stays open at the final stop for you to carry on by hand.
|
|
1761
|
+
`--replay-interval S` waits a fixed S seconds before each action
|
|
1762
|
+
instead of reproducing the recorded gaps. `--replay-timeout S` bounds
|
|
1763
|
+
each stop-wait (default 30 s). Exit code 0
|
|
1764
|
+
iff every action succeeded. Don't type into the TUI while it is
|
|
1765
|
+
replaying: stray keystrokes interleave with the recorded actions.
|
|
1464
1766
|
- `tdb --replay session.jsonl` launches the recorded
|
|
1465
1767
|
program headless, feeds every recorded command through the same RPC
|
|
1466
1768
|
dispatch `tdb --server` uses, and prints a transcript (recorded time,
|
|
1467
1769
|
command, verbatim result, interleaved program output). Exit code 0 iff
|
|
1468
1770
|
every command succeeded. Add `--timing` to reproduce the original
|
|
1469
|
-
pacing
|
|
1771
|
+
pacing or `--replay-interval S` for a fixed delay before each command,
|
|
1772
|
+
`--replay-timeout S` to bound each stop-wait (default 30 s).
|
|
1470
1773
|
- Against a live server: start `tdb --server prog.py`, then feed line 2
|
|
1471
1774
|
onward of the file to `POST /rpc` . Each line is a valid request body:
|
|
1472
1775
|
|
|
@@ -1483,9 +1786,10 @@ lists), breakpoint enable/disable toggles, variable expansions when the
|
|
|
1483
1786
|
adapter reports no `evaluateName` (currently the Perl adapter), and
|
|
1484
1787
|
File > Open program switches.
|
|
1485
1788
|
|
|
1486
|
-
## MCP Integration
|
|
1789
|
+
## MCP v2 Integration
|
|
1487
1790
|
|
|
1488
|
-
tdb ships a Model Context Protocol (MCP)
|
|
1791
|
+
tdb ships a Model Context Protocol (MCP), version 2,
|
|
1792
|
+
server (`tdb-mcp`) that exposes
|
|
1489
1793
|
the debugger as a curated set of tools an AI agent can call. The MCP
|
|
1490
1794
|
server is a third in-process consumer of the same dispatch handlers the
|
|
1491
1795
|
TUI and the HTTP server use so an agent gets the same lock semantics,
|
|
@@ -1583,7 +1887,7 @@ usage: tdb [-h] [-v] [-r [HOST:]PORT] [--cwd CWD] [--no-stop-on-entry]
|
|
|
1583
1887
|
[--keybindings {default,vim,emacs}]
|
|
1584
1888
|
[--terminal {xterm,konsole,gnome-terminal,ghostty,kitty,iterm2,warp,wezterm,terminator}]
|
|
1585
1889
|
[--local-root PATH] [--remote-root PATH]
|
|
1586
|
-
[--server] [--headless] [-k FILE:LINE|LINE] [--server-port SERVER_PORT] [-d] [--doc-text]
|
|
1890
|
+
[--server] [--headless] [-k FILE:LINE|LINE] [--server-port SERVER_PORT] [-d] [--doc-text] [--info]
|
|
1587
1891
|
[program] [args ...]
|
|
1588
1892
|
```
|
|
1589
1893
|
|
|
@@ -1610,6 +1914,14 @@ usage: tdb [-h] [-v] [-r [HOST:]PORT] [--cwd CWD] [--no-stop-on-entry]
|
|
|
1610
1914
|
| `--server` | Enable JSON-RPC server alongside TUI |
|
|
1611
1915
|
| `--headless` | JSON-RPC server only, no TUI |
|
|
1612
1916
|
| `--server-port PORT` | Server port (default: 8150) |
|
|
1917
|
+
| `--record FILE` | Record this TUI session's debugging actions to FILE (JSON-RPC lines) |
|
|
1918
|
+
| `--replay FILE` | Replay a recording headless, printing a transcript (no program argument) |
|
|
1919
|
+
| `--replay-tui FILE` | Replay a recording inside the TUI at the recorded pace, so you can watch it |
|
|
1920
|
+
| `--replay-quiet` | With `--replay-tui`: no per-action toasts (errors and the final summary still show) |
|
|
1921
|
+
| `--timing` | With `--replay`: reproduce the recorded pacing (`--replay-tui` always does) |
|
|
1922
|
+
| `--replay-interval S` | With `--replay`/`--replay-tui`: fixed S-second delay before each action instead of the recorded gaps |
|
|
1923
|
+
| `--replay-timeout S` | With `--replay`/`--replay-tui`: per-action stop-wait timeout (default 30) |
|
|
1924
|
+
| `--examine-log DEST` | With --run: write each Ctrl-\ / SIGUSR2 stack snapshot to DEST (- = stdout; repeatable) |
|
|
1613
1925
|
|
|
1614
1926
|
## Configuration
|
|
1615
1927
|
|
|
@@ -1634,6 +1946,10 @@ found; it's Python code, not an external executable), so
|
|
|
1634
1946
|
`{"adapters": {"perl": "/path/to/perl"}}`. Use this when the `perl` on
|
|
1635
1947
|
`PATH` is too old (< 5.18) or you need a specific `perlbrew`/`plenv` version.
|
|
1636
1948
|
|
|
1949
|
+
**PowerShell** follows the same pattern with two keys: `adapters.pwsh` names
|
|
1950
|
+
the interpreter and `adapters.pses` names the PowerShell Editor Services
|
|
1951
|
+
module directory (see [PowerShell](#powershell)).
|
|
1952
|
+
|
|
1637
1953
|
Breakpoints are saved on exit and restored when debugging a program in the same
|
|
1638
1954
|
directory. Each project's breakpoints are independent. Breakpoints set with
|
|
1639
1955
|
`-t`/`--to-line` are the exception: they behave like `-k` breakpoints during
|
|
@@ -1666,6 +1982,28 @@ fires as expected.
|
|
|
1666
1982
|
|
|
1667
1983
|
MIT
|
|
1668
1984
|
|
|
1985
|
+
## Acknowledgments
|
|
1986
|
+
|
|
1987
|
+
Thank you:
|
|
1988
|
+
|
|
1989
|
+
- Will McGugan for the amazing `textual` module.
|
|
1990
|
+
`tdb` would be a pale shadow of itself had I used any other TUI framework.
|
|
1991
|
+
Fantastic work, Will.
|
|
1992
|
+
|
|
1993
|
+
- Microsoft for the Debug Adapter Protocol (DAP) and releasing
|
|
1994
|
+
its implementation in `debugpy` and the Python Debugger extension for Visual Studio Code
|
|
1995
|
+
as open source.
|
|
1996
|
+
|
|
1997
|
+
- Anthropic, for providing access to Claude Code through the
|
|
1998
|
+
[Claude for Open Source](https://claude.com/contact-sales/claude-for-oss) program.
|
|
1999
|
+
`tdb` was made almost entirely with Claude Code.
|
|
2000
|
+
|
|
2001
|
+
- OpenAI, for providing access to Codex through the
|
|
2002
|
+
[Codex for Open Source](https://developers.openai.com/community/codex-for-oss) program.
|
|
2003
|
+
|
|
2004
|
+
This project was inspired by Andreas Klöckner's excellent [pudb](https://pypi.org/project/pudb/)
|
|
2005
|
+
Python debugger.
|
|
2006
|
+
|
|
1669
2007
|
|
|
1670
2008
|
## Known Problems
|
|
1671
2009
|
|