Files
kandev/apps/backend/cmd/acpdbg
Carlos Florêncio bc218dfbbe feat: add workspace sources from files panel (#1900)
* feat: add workspace sources from files panel

* fix: preserve worktree identity during recovery

* feat: unify workspace source actions

* fix: validate recovered workspace repositories

* fix: harden workspace source filesystem boundaries

* test: split workspace repository chip coverage

* fix: restrict repository rescan recovery paths

* fix: stabilize workspace source CI checks

* test: canonicalize workspace source paths

* test: align workspace source container paths

* fix: populate direct workspace repository names

* test: preserve git fixture rewrites across restarts

* test: isolate backend git fixture config

* fix: resume remote workspace executions before creation

* fix: preserve ssh agent identity during resume

* fix: preserve SSH workspace across backend restart

* fix: simplify workspace actions trigger

* fix: refine add workspace repositories UX

* docs: narrow workspace source UX updates

* fix: avoid phantom turn on session resume

* test(web): normalize workspace source request headers

* feat(web): streamline workspace source picker

* docs: remove trailing spaces from workspace source plan

* fix: prevent resume status from creating phantom turns

* fix(web): stabilize workspace source attachment

* refactor(web): extract workspace source store contract

* fix: avoid phantom turns on idle agent resume

* fix: address backend static analysis findings

* fix: preserve agentctl readiness status value

* fix: preserve resume messages without active turns

* fix: resume agents from promoted workspace root

* chore: merge origin/main into feature/add-new-repo-folder-d97

* feat(web): explain workspace source consequences

* test(websocket): count session activity subscription
2026-07-25 21:29:53 +01:00
..

acpdbg

Headless CLI that speaks raw ACP JSON-RPC to any registered kandev agent (or an arbitrary binary) and records every wire frame to a JSONL file. Useful for answering "what models/modes does this agent advertise?", "does session/load work?", or "what does the prompt stream actually look like?" without spinning up the full kandev backend.

Build

make acpdbg ARGS=list              # from repo root
make -C apps/backend build-acpdbg  # just build

Binary lands at apps/backend/bin/acpdbg.

Usage

make acpdbg ARGS="<subcommand> [flags]"

Or invoke the binary directly: apps/backend/bin/acpdbg <subcommand> [flags].

Sub-commands

Command Purpose
list Enumerate registered ACP agents with their spawn command
probe <agent> initialize → session/new → close. Shows models, modes, auth methods.
probe --exec "<cmd> [args...]" Same but against an arbitrary binary not in the registry
prompt <agent> --prompt "..." [--model M] [--mode M] Full prompt round-trip, collects text chunks from session/update
session-load <agent> --session-id <id> [--prompt "..."] Load an existing session in --workdir, then optionally verify it with a prompt
matrix Probe every registered ACP agent in parallel, write one JSONL per agent + matrix-summary.json

Shared flags

  • --out DIR — JSONL output directory (default ./acp-debug/)
  • --file PATH — exact JSONL path, overrides --out
  • --timeout DUR — overall run timeout (default 30s; use 60s+ for matrix since npx-spawned agents are slow to cold-start)
  • --workdir PATH — child cwd (default: fresh /tmp/kandev-acpdbg-<pid>-*)
  • --verbose — mirror frames to stderr as they're sent/received
  • --stderr — capture child stderr into the JSONL (useful when an agent crashes before the handshake completes)

Verify resume under a different working directory

Create a session in one directory, then load it from another and ask the agent to report its working directory:

apps/backend/bin/acpdbg prompt codex-acp \
  --workdir /tmp/folder-a \
  --prompt "Reply with pwd only" \
  --file /tmp/codex-new.jsonl

apps/backend/bin/acpdbg session-load codex-acp \
  --session-id <session-id-from-first-run> \
  --workdir /tmp/folder-b \
  --prompt "Reply with pwd only" \
  --file /tmp/codex-load.jsonl

session-load sends the selected --workdir as the ACP cwd parameter. The JSONL wire frames are authoritative when a provider replays earlier session messages during load.

JSONL format

One JSON object per line, chronologically ordered. direction is one of:

direction Meaning
meta acpdbg marker (event: start with agent/command/workdir, event: close with exit_code/reason)
sent Frame written to child stdin
received Frame read from child stdout
stderr Child stderr line (only with --stderr)

jq recipes

# Full initialize response
jq -c 'select(.direction == "received" and .frame.id == 1)' acp-debug/<file>.jsonl

# Just the advertised models
jq -r 'select(.direction == "received") | .frame.result.models.availableModels[]?.modelId' acp-debug/<file>.jsonl

# Close event (exit code + reason)
jq -c 'select(.direction == "meta" and .event == "close")' acp-debug/<file>.jsonl

Design notes

  • Agent registry is the source of truth. acpdbg imports internal/agent/registry directly, so adding/removing agents in internal/agent/agents/*.go automatically updates the CLI. No parallel config file.
  • Raw JSON-RPC, not the SDK. Uses a custom line-delimited framer (internal/agent/acpdbg/framer.go) so the recorded frames are authoritative wire bytes, not SDK-parsed events.
  • Env inheritance. The child process inherits the parent shell's env and credential files — if it works in kandev it works here. Auth failures are captured in the JSONL.
  • Agent-initiated requests (fs/read_text_file, session/request_permission, etc.) are auto-replied to with -32601 method not found so sessions don't hang. For real permission flows, use the full kandev backend.

See .agents/skills/acp-debug/SKILL.md for the agent-facing usage guide.