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

@debugtalk/opencode-dap

v0.2.0

Published

DAP (Debug Adapter Protocol) client for OpenCode AI coding agent

Downloads

43

Readme

opencode-dap

DAP (Debug Adapter Protocol) client for OpenCode — ported from oh-my-pi.

Lets AI coding agents debug programs via the Debug Adapter Protocol — supports 14 debug adapters covering ~18 languages. Drop it into OpenCode with a single plugin entry or use it as a standalone Bun/Node library.

Quick Start

opencode plugin @debugtalk/opencode-dap

Restart OpenCode. The debug tool is available with 30+ actions. Debug sessions are automatically cleaned up on session idle/deleted.

Upgrade

opencode plugin @debugtalk/opencode-dap --force

Verify

grep "opencode-dap" ~/.local/share/opencode/log/opencode.log

Then in OpenCode, run debug action=sessions to confirm the tool is registered.

Manual install (not recommended)

npm install @debugtalk/opencode-dap --save-dev

Then add to opencode.json:

{ "plugin": ["@debugtalk/opencode-dap"] }

Install debug adapters

pip install debugpy          # Python
brew install llvm            # macOS: C/C++/Rust/Swift (lldb-dap)
go install github.com/go-delve/delve/cmd/dlv@latest  # Go
npm install -g @vscode/js-debug      # JavaScript / TypeScript
npm install -g @vscode/bash-debug    # Bash / Shell

Standalone API

For use outside OpenCode or when building custom integrations:

import { DapSessionManager, selectLaunchAdapter } from "@debugtalk/opencode-dap";

const cwd = process.cwd();
const adapter = selectLaunchAdapter("src/main.py", cwd);
if (!adapter) throw new Error("No debug adapter available");

const mgr = new DapSessionManager();

// Launch
const snapshot = await mgr.launch({ adapter, program: "src/main.py", cwd });
console.log("Status:", snapshot.status);

// Set breakpoint
const bp = await mgr.setBreakpoint("src/main.py", 10);

// Continue
const outcome = await mgr.continue();

// Evaluate when stopped
const result = await mgr.evaluate("myVar", "repl", undefined);
console.log("myVar =", result.evaluation.result);

// Terminate
await mgr.terminate();

To build a custom tool, import DapSessionManager, selectLaunchAdapter, etc. from the library. See src/plugin.ts for the reference implementation.

Supported Adapters

| Adapter | Languages | Command | Install | |---|---|---|---| | gdb | C, C++, Rust | gdb -i dap | system package | | lldb-dap | C, C++, ObjC, Swift, Rust, Zig | lldb-dap | brew install llvm (macOS), apt install lldb | | codelldb | C, C++, Rust, Zig | codelldb | VS Code extension | | debugpy | Python | python -m debugpy.adapter | pip install debugpy | | dlv | Go | dlv dap | go install github.com/go-delve/delve/cmd/dlv@latest | | js-debug-adapter | JavaScript, TypeScript | js-debug-adapter | npm install -g @vscode/js-debug | | netcoredbg | C#, F# | netcoredbg --interpreter=vscode | GitHub | | kotlin-debug-adapter | Kotlin | kotlin-debug-adapter | GitHub | | rdbg | Ruby | rdbg --open --command -- | gem install debug | | php-debug-adapter | PHP | php-debug-adapter | VS Code extension | | bash-debug-adapter | Bash/Shell | bash-debug-adapter | npm install -g @vscode/bash-debug | | dart-debug-adapter | Dart | dart debug_adapter | Dart SDK | | flutter-debug-adapter | Dart (Flutter) | dart debug_adapter | Flutter SDK | | elixir-ls-debugger | Elixir | elixir-ls-debugger | GitHub |

Adapter auto-selection works by file extension and project root markers. For example, .py files → debugpy, .go files → dlv, Cargo.tomllldb-dap or gdb.

API Reference

DapSessionManager

Stateful orchestrator. Holds a single active session at a time.

| Method | Description | |---|---| | launch(options, signal?, timeoutMs?) | Start a debug session. Returns DapSessionSummary. | | attach(options, signal?, timeoutMs?) | Attach to a running process. Returns DapSessionSummary. | | terminate(signal?, timeoutMs?) | Terminate the active session. Returns DapSessionSummary \| null. | | getActiveSession() | Get summary of the active session, or null. | | listSessions() | List all session summaries. | | getCapabilities() | Get adapter capabilities, or null. |

Execution control:

| Method | Description | |---|---| | continue(signal?, timeoutMs?) | Continue execution. Returns DapContinueOutcome with state. | | pause(signal?, timeoutMs?) | Pause execution. | | stepIn(signal?, timeoutMs?) | Step into. Returns DapContinueOutcome. | | stepOut(signal?, timeoutMs?) | Step out. Returns DapContinueOutcome. | | stepOver(signal?, timeoutMs?) | Step over (next). Returns DapContinueOutcome. |

Breakpoints:

| Method | Description | |---|---| | setBreakpoint(file, line, condition?, signal?, timeoutMs?) | Set a source breakpoint. | | removeBreakpoint(file, line, signal?, timeoutMs?) | Remove a source breakpoint. | | setFunctionBreakpoint(name, condition?, signal?, timeoutMs?) | Set a function breakpoint. | | removeFunctionBreakpoint(name, signal?, timeoutMs?) | Remove a function breakpoint. | | setInstructionBreakpoint(instructionReference, offset?, condition?, hitCondition?, signal?, timeoutMs?) | Set an instruction breakpoint. | | removeInstructionBreakpoint(instructionReference, offset?, signal?, timeoutMs?) | Remove an instruction breakpoint. | | dataBreakpointInfo(name, variablesReference?, frameId?, signal?, timeoutMs?) | Get data breakpoint info for a variable. | | setDataBreakpoint(dataId, accessType?, condition?, hitCondition?, signal?, timeoutMs?) | Set a data breakpoint. | | removeDataBreakpoint(dataId, signal?, timeoutMs?) | Remove a data breakpoint. |

State inspection:

| Method | Description | |---|---| | stackTrace(frameCount?, signal?, timeoutMs?) | Get stack frames. | | scopes(frameId?, signal?, timeoutMs?) | Get scopes for a frame. | | variables(variablesReference, signal?, timeoutMs?) | Get variables in a scope. | | evaluate(expression, context, frameId?, signal?, timeoutMs?) | Evaluate an expression. | | threads(signal?, timeoutMs?) | List threads. | | getOutput(limitBytes?) | Get captured stdout/stderr. |

Memory & introspection:

| Method | Description | |---|---| | disassemble(memoryReference, instructionCount, offset?, instructionOffset?, resolveSymbols?, signal?, timeoutMs?) | Disassemble instructions. | | readMemory(memoryReference, count, offset?, signal?, timeoutMs?) | Read memory. | | writeMemory(memoryReference, data, offset?, allowPartial?, signal?, timeoutMs?) | Write memory. | | modules(startModule?, moduleCount?, signal?, timeoutMs?) | List modules. | | loadedSources(signal?, timeoutMs?) | List loaded sources. | | customRequest(command, args?, signal?, timeoutMs?) | Send an arbitrary DAP request. |

Adapter Resolution

| Function | Description | |---|---| | getAvailableAdapters(cwd) | List all adapters resolvable from $PATH or local bins. | | resolveAdapter(adapterName, cwd) | Resolve a specific adapter by name. | | selectLaunchAdapter(program, cwd, adapterName?, programKind?) | Auto-select the best adapter for a program. | | selectAttachAdapter(cwd, adapterName?, port?) | Auto-select the best adapter for attach. | | resolveLaunchOverrides(adapter, program, programKind) | Get adapter-specific launch arguments (e.g., dlv mode). | | getAdapterConfigs() | Get the raw adapter config map from the bundled catalog. |

Key Types

| Type | Description | |---|---| | DapSessionSummary | Snapshot of session state (status, stop location, breakpoint counts, output stats). | | DapContinueOutcome | Result of continue/step: { snapshot, state, timedOut }. | | DapResolvedAdapter | Adapter with resolved binary path, file types, root markers. | | DapCapabilities | Adapter-reported capabilities (what features it supports). | | DapClient | Low-level DAP wire protocol client. Direct use is rare; prefer DapSessionManager. |

How It Works

┌─────────────────────────────────────────────────────┐
│ opencode plugin (opencode.json)                     │
│   "plugin": ["@debugtalk/opencode-dap"]             │
└──────────────────┬──────────────────────────────────┘
                   │
┌──────────────────▼──────────────────────────────────┐
│ DapSessionManager (singleton)                       │
│   session lifecycle, breakpoint serialization,      │
│   step/continue orchestration, event handling       │
└──────────────────┬──────────────────────────────────┘
                   │
┌──────────────────▼──────────────────────────────────┐
│ DapClient (per-session)                             │
│   Content-Length framing, request/response matching,│
│   async event dispatch, reverse request handling    │
└──────────────────┬──────────────────────────────────┘
                   │  stdio pipe or Unix/TCP socket
┌──────────────────▼──────────────────────────────────┐
│ Debug Adapter (external process)                    │
│   debugpy, dlv, lldb-dap, gdb, js-debug-adapter ... │
└─────────────────────────────────────────────────────┘

Wire Protocol

The DAP client implements the full Debug Adapter Protocol framing:

Content-Length: {byteCount}\r\n
\r\n
{JSON body}

Messages are typed as request, response, or event. Requests are matched to responses by seq/request_seq. Events are dispatched to registered handlers.

Connection Modes

  • stdio (default): Spawn adapter as child process, communicate via stdin/stdout.
  • socket: For adapters that use network sockets (e.g., dlv on Unix domain sockets on Linux, TCP on macOS).

Safety

  • Non-interactive environment: All debugger child processes inherit TERM=dumb, disabled pagers, and CI flags to prevent SIGTTIN.
  • Request timeout: Every DAP request times out at 30s by default.
  • Breakpoint serialization: Concurrent breakpoint mutations are queued to prevent setBreakpoints from silently overwriting each other.
  • Race-condition safety: Event subscriptions are registered before sending commands that trigger them.

Troubleshooting

"No debug adapter available for this program"

Install the appropriate adapter for your language (see the Supported Adapters table). You can check which adapters are available on your system:

import { getAvailableAdapters } from "@debugtalk/opencode-dap";
console.log(getAvailableAdapters(process.cwd()).map(a => a.name));

"Failed to launch debug adapter"

Common causes:

  • Adapter binary not in $PATH or project-local bin directory.
  • Python virtual environment not activated — the resolver checks .venv/bin/, venv/bin/, and .env/bin/ for Python projects.
  • Missing runtime (e.g., python not found when using debugpy).

"Time out" during launch/attach

Some adapters are slow to initialize. Increase the timeout:

await mgr.launch(options, undefined, 60_000); // 60 seconds

"Not a tty" or hung processes

The package sets non-interactive environment variables automatically (TERM=dumb, disabled pagers). If your adapter still hangs, ensure it doesn't try to read from /dev/tty.

"Adapter exited unexpectedly"

Check stderr from the adapter process. Common causes:

  • Missing dependencies (e.g., debugpy not installed: pip install debugpy).
  • Wrong architecture (e.g., 64-bit adapter on 32-bit binary).
  • Permission issues when attaching to a process.