David — agent orchestration for Claude Code
A VS Code extension that lets you run multiple specialist Claude Code agents on one project, coordinated by a planner+workers overseer. Plus scheduled jobs, a nightly memory-distillation dream cycle, skills, and portable agent templates.
What it does
- Spawns multiple
claude subprocesses, one per agent, via node-pty. Each agent is its own Claude Code session with remote-control on (talk to any agent from claude.ai or the Claude mobile app).
- Coordinates them via a file-bus at
~/.david/workspaces/<slug>/ — chat.md for shared conversation, per-agent LEDGER for action history, long-term-memory.{L0,L1,L2} for distilled cross-day memory.
- Nightly dream cycle distills today's chat + LEDGERs into long-term memory with strict truthfulness rules (source citations, supersession, Pending-review for high-stakes claims). Runs via launchd, shells to
claude -p.
- Scheduled Jobs with full visibility — define recurring shell/claude/codex tasks via the overseer (
/create-job), they run via launchd, full run history per job. Missing-run detection.
- Skills system — install manual skills (workspace, agent, or global scope) OR let agents self-improve and propose new skills via
SendUserMessage(skill_candidate, …). You approve before merge.
- Agent templates — export a successful agent (PERSONA + accumulated skills + lessons) as a portable template. Spawn future agents from templates with clean memory but inherited capabilities.
- Chat UI delegated to Claude Code's own VS Code extension — David doesn't reinvent chat; click an agent in David's tree and Claude Code's native panel opens.
Install (local .vsix)
cd ~/projects/david
npm install
npm run compile
npx @vscode/vsce package
That produces david-0.1.0.vsix. Install it:
- In VS Code: Cmd+Shift+P →
Extensions: Install from VSIX… → pick david-0.1.0.vsix.
- Reload VS Code. David's icon appears in the activity bar.
Or from the command line:
code --install-extension ~/projects/david/david-0.1.0.vsix
First-time use
- Open a project folder in VS Code (
File → Open Folder…).
- Click David's icon in the activity bar. You'll see the welcome view: "This folder isn't a David project yet. [Register]".
- Click Register. David:
- Creates
~/.david/workspaces/<slug>/ with chat.md, long-term-memory.{L0,L1}.md, agents/, jobs/, archive/.
- Spawns an overseer subprocess (
claude --remote-control --brief --append-system-prompt …).
- Registers the nightly dream cycle via launchd.
- Opens the overseer's chat in Claude Code's panel.
- The overseer greets you with the onboarding Q&A. Enable its heartbeat by typing
/loop in its chat (see "Enabling an agent's loop" below).
Screenshots
David's Agents tree — multiple Claude Code agents coordinated in one place.
Pending approvals surface in the Needs You panel. No agent spawns or job runs without your click.
Recurring tasks via launchd, with full run history per job.
Stay in touch
David is shipping early-and-often — feedback shapes what comes next.
- Issues: github.com/edwardyen724-g/david/issues — bug reports, feature requests, general discussion
- Email: edwardyen724@gmail.com — for anything sensitive (security reports, private feedback, partnership inquiries)
- Updates: star the repo to get notified of releases, or watch the CHANGELOG
If you build something interesting with David — a custom skill, a job that does real work, a multi-agent flow you wish existed — open an issue or email. The roadmap follows real use cases, not hypotheticals.
Architecture at a glance
~/.david/
├── registry.json # folder-path → slug map
├── skills/<name>.md # global skills (every agent in every project)
├── templates/<template-name>/ # portable agent templates
└── workspaces/<slug>/
├── david-config.json
├── chat.md # shared, with <!-- CHECKPOINT --> markers
├── long-term-memory.L0.md # ~200-token abstract
├── long-term-memory.L1.md # structured: Facts/Decisions/State/Lessons/Pending/Superseded
├── long-term-memory.L2/ # deep-dive files
├── archive/ # rotated daily chats
├── skills/ # workspace-scoped skills
├── agents/<name>/
│ ├── PERSONA.md
│ ├── LEDGER # append-only, tagged
│ ├── NEXT.md
│ ├── SELF_ASSESS.log
│ └── skills/ # agent-scoped skills
├── jobs/
│ ├── <name>.json # job config
│ └── <name>.log # append-only run history
└── dream.log # nightly distillation log
~/Library/LaunchAgents/
├── com.david.<slug>.dream.plist # nightly at 2am
└── com.david.<slug>.job.<name>.plist # per scheduled job
Key commands (palette)
| Command |
What it does |
David: Add this workspace as a project |
Register the open folder. Creates the disk structure + spawns overseer. |
David: Talk to David (overseer) |
Open overseer's chat in Claude Code's panel. |
David: Design new agent (via overseer) |
Open overseer + run /create-agent walkthrough. |
David: Design new job (via overseer) |
Open overseer + run /create-job walkthrough. |
David: Resume project |
Re-spawn all agents from disk (rehydrate from LEDGER + chat.md). |
David: Run dream cycle now |
Trigger the distillation script manually (instead of waiting for 2am). |
David: Install skill… |
Add a manual skill (workspace / agent / global scope). |
David: Show installed skills |
List all skills with content and provenance. |
David: Export agent as template |
Save an agent's persona + skills + lessons as a portable template. |
David: Spawn agent from template |
Create a new agent in this project from a saved template. |
David: Remove this project |
Archive the workspace to ~/.david/archive/. Never deletes. |
Per-agent UI (Agents tree)
Each agent row has two inline action icons (hover to see them):
- Open chat — open this agent's chat in Claude Code's panel.
- Remote-control toggle — shows the session URL/QR. The Overseer auto-starts remote control; workers don't (enable per-worker with this toggle — the setting persists across restart).
Right-click for: Show in terminal, Pause / Resume agent, Retire agent.
Enabling an agent's loop (autonomous heartbeat)
In v0.1.0, you enable an agent's loop by typing /loop directly into its chat or terminal — David observes the submission and persists the heartbeat state to the agent's config so it survives restart. Type /loop end to stop. An inline toggle icon is on the v0.1.1 roadmap.
Self-evolving skills
David agents have built-in self-improvement: every agent's system prompt instructs it to emit a SendUserMessage(skill_candidate, …) when it notices a reusable pattern. The plugin captures the candidate, shows you a preview with the agent's reasoning, and you approve / dismiss. Approved skills get written to the appropriate scope and load on next agent spawn.
Inspired by self-improving-agent patterns, implemented natively in David with no external dependency.
Dependencies
claude CLI v2.1.51+ (logged in via /login, NOT API key — remote-control requires claude.ai OAuth).
node-pty — bundled in the .vsix with prebuilds for arm64 + x64 macOS.
- macOS launchd — for scheduled jobs and the dream cycle. (Linux/Windows support is a v0.2 concern.)
- Optional:
codex CLI for runtime: codex jobs.
What's NOT in v0.1 (deferred)
- Forking projects (v0.2) — architecture allows it via
cp -r of the workspace dir + git branch.
- Webview UI for chat (delegated to Claude Code's native panel).
- Reset (full agent wipe) — only Pause and Retire exist in v0.1.
- Cross-machine workspace sync (potential premium feature if David gains traction).
- Drift detection + weekly memory audit (planned, not yet wired).
- Self-assessment turn injection (instrumentation, planned).
- Embedding-based skill search (v0.3+, when libraries exceed ~1000 entries).
Troubleshooting
"Agent shows as spawned but no chat appears." The agent is idle — David spawns the subprocess but the agent doesn't proactively start a turn. Click the chat icon on the agent's row, type anything (or /loop), and the agent will respond.
"posix_spawnp failed" when spawning an agent. The bundled node-pty spawn-helper lost its executable bit (npm strips it from tarballs). David tries to fix this on activation, but if the fix didn't run:
chmod +x ~/.vscode/extensions/edwardyen724.david-*/node_modules/node-pty/prebuilds/darwin-*/spawn-helper
"A scheduled job didn't run at its expected time." The launchd plist may have been unloaded (e.g., across an OS reinstall). Reload it manually:
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.david.<slug>.job.<name>.plist
Or use David: Run job… in the command palette to test that the job command itself works.
"David doesn't see the claude CLI." Set the CLAUDE_BIN environment variable to the absolute path of your claude binary, then reload the VS Code window:
export CLAUDE_BIN=/opt/homebrew/bin/claude
"My agent's session disappeared from claude.ai." Remote-control sessions are tied to your claude.ai OAuth login. If you logged out of claude.ai or your OAuth token expired, re-claude /login in your terminal and pause+restart the agent in David.
File map
| Module |
Responsibility |
extension.ts |
Activation, registry lookup, auto-resume |
commands.ts |
All palette commands + event handler for SendUserMessage |
workspaceStore.ts |
~/.david/ filesystem operations |
subprocessManager.ts |
node-pty spawn / stdin / stdout parsing per agent |
jobsRuntime.ts |
launchd plist generator + job-runner invocation |
dreamCycle.ts |
Nightly dream plist registration |
skillsStore.ts |
Global/workspace/agent skill CRUD |
agentTemplates.ts |
Export agent → template, apply template → agent |
agentsTree.ts / jobsTree.ts / needsYouTree.ts |
Three TreeDataProviders |
chatPanel.ts |
Routes chat-open to Claude Code's editor command |
statusBar.ts |
Project identity + agent aggregate + jobs summary |
runtime.ts |
Singleton SubprocessManager for the active workspace |
mockData.ts |
UI types + (legacy) mock seed for click-through review |
bin/dream.sh |
Distillation script invoked nightly |
bin/job-runner.js |
Job execution wrapper invoked by launchd |