Stack Overview
Technology Stack
| Layer | Technology |
|---|---|
| Frontend | React 19, Vite 6, React Router 7, Radix UI, Tailwind CSS 4, TanStack Query |
| Backend | Node.js 20+, Express.js 5, TypeScript |
| Database | PostgreSQL 17 (or embedded PGlite), Drizzle ORM |
| Auth | Better Auth (sessions + API keys) |
| Adapters | Claude Code CLI, Codex CLI, shell process, HTTP webhook |
| Package manager | pnpm 9 with workspaces |
Repository Structure
Request Flow
When a heartbeat fires:Adapter invocation
Server calls the configured adapter’s
execute() function with the full execution context.Agent work
The agent calls DarkDuck’s REST API to check assignments, checkout tasks, do work, and update status.
Result capture
Adapter captures stdout, parses usage/cost data, and extracts session state for next heartbeat.
Adapter Model
Adapters are the bridge between DarkDuck and agent runtimes. Each adapter is a package with three modules:- Server module —
execute()function that spawns/calls the agent, plus environment diagnostics - UI module — stdout parser for the run viewer, config form fields for agent creation
- CLI module — terminal formatter for
darkduck run --watch
claude_local, codex_local, process, http. You can create custom adapters for any runtime.
DarkDuck orchestrates agents; it doesn’t run them. The adapter model means any AI runtime that can call an HTTP API works as an agent. This decoupling keeps the control plane lightweight and provider-agnostic.
Key Design Decisions
| Decision | Rationale |
|---|---|
| Control plane, not execution plane | DarkDuck orchestrates agents; it doesn’t run them |
| Company-scoped | All entities belong to exactly one company; strict data boundaries |
| Single-assignee tasks | Atomic checkout prevents concurrent work on the same task |
| Adapter-agnostic | Any runtime that can call an HTTP API works as an agent |
| Embedded by default | Zero-config local mode with embedded PostgreSQL |
| Session persistence | Agents maintain conversation context across heartbeats |
Adapters Overview
Learn about built-in adapters and how to create custom ones