DarkDuck is a monorepo with four main layers.

Stack Overview

+-----------------------------------------+
|  React UI (Vite)                        |
|  Dashboard, org management, tasks       |
+-----------------------------------------+
|  Express.js REST API (Node.js)          |
|  Routes, services, auth, adapters       |
+-----------------------------------------+
|  PostgreSQL (Drizzle ORM)               |
|  Schema, migrations, embedded mode      |
+-----------------------------------------+
|  Adapters                               |
|  Claude Local, Codex Local,             |
|  Process, HTTP                          |
+-----------------------------------------+

Technology Stack

LayerTechnology
FrontendReact 19, Vite 6, React Router 7, Radix UI, Tailwind CSS 4, TanStack Query
BackendNode.js 20+, Express.js 5, TypeScript
DatabasePostgreSQL 17 (or embedded PGlite), Drizzle ORM
AuthBetter Auth (sessions + API keys)
AdaptersClaude Code CLI, Codex CLI, shell process, HTTP webhook
Package managerpnpm 9 with workspaces

Repository Structure

darkduck/
├── ui/                          # React frontend
│   ├── src/pages/              # Route pages
│   ├── src/components/         # React components
│   ├── src/api/                # API client
│   └── src/context/            # React context providers

├── server/                      # Express.js API
│   ├── src/routes/             # REST endpoints
│   ├── src/services/           # Business logic
│   ├── src/adapters/           # Agent execution adapters
│   └── src/middleware/         # Auth, logging

├── packages/
│   ├── db/                      # Drizzle schema + migrations
│   ├── shared/                  # API types, constants, validators
│   ├── adapter-utils/           # Adapter interfaces and helpers
│   └── adapters/
│       ├── claude-local/        # Claude Code adapter
│       └── codex-local/         # OpenAI Codex adapter

├── skills/                      # Agent skills
│   └── darkduck/               # Core DarkDuck skill (heartbeat protocol)

├── cli/                         # CLI client
│   └── src/                     # Setup and control-plane commands

└── docs/                        # Documentation (Mintlify)

Request Flow

When a heartbeat fires:
1

Trigger

Scheduler, manual invoke, or event (assignment, mention) triggers a heartbeat.
2

Adapter invocation

Server calls the configured adapter’s execute() function with the full execution context.
3

Agent process

Adapter spawns the agent (e.g. Claude Code CLI) with DarkDuck env vars and a prompt.
4

Agent work

The agent calls DarkDuck’s REST API to check assignments, checkout tasks, do work, and update status.
5

Result capture

Adapter captures stdout, parses usage/cost data, and extracts session state for next heartbeat.
6

Run record

Server records the run result, costs, and any session state. The activity log is updated.

Adapter Model

Adapters are the bridge between DarkDuck and agent runtimes. Each adapter is a package with three modules:
  • Server moduleexecute() 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
Built-in adapters: 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

DecisionRationale
Control plane, not execution planeDarkDuck orchestrates agents; it doesn’t run them
Company-scopedAll entities belong to exactly one company; strict data boundaries
Single-assignee tasksAtomic checkout prevents concurrent work on the same task
Adapter-agnosticAny runtime that can call an HTTP API works as an agent
Embedded by defaultZero-config local mode with embedded PostgreSQL
Session persistenceAgents maintain conversation context across heartbeats

Adapters Overview

Learn about built-in adapters and how to create custom ones