A native Swift macOS desktop agent: chat, just-in-time software (plugins), messaging connectors, scheduled jobs, and human-in-the-loop approvals. Agent work runs in a headless daemon; untrusted code runs in Docker.
License: Apache 2.0
| Area | Description |
|---|---|
| Chat | Multi-tab conversations with OpenAI, Gemini, and other configured models. Talk to a named agent profile with $shortName when you want that profile; a mention of the name is not enough. |
| Just-in-time software | Describe the software you need. Derrick builds, reviews, and installs a versioned plugin for that moment — a connector, a skill, or a one-shot tool — instead of shipping a catalog of pre-written apps. |
| Messaging | Installed connectors open as Chat tabs. The host renders the plugin's ui.present tree (default messaging_inbox or a custom HostUI layout). Connectors without a screen are rejected. |
| Jobs | Scheduled and deferred runs that continue after you quit the app. |
| Tools (MCP) | Model Context Protocol tools hosted in the daemon for chat turns. |
| Scripts | Agent-written Go, compiled and run in isolated Docker containers, with a reviewer and approvals. |
| Policy & HITL | Approvals for tools, network access, usage limits, and connector credentials. |
┌───────────────────────────────────────────────────────────────────┐
│ Derrick.app (UI) — SwiftUI client only │
│ Chat · Messaging · Just-in-time software · Settings · Approvals │
└────────────────────────────────┬──────────────────────────────────┘
│ Mach XPC (signed messages)
┌────────────────────────────────▼──────────────────────────────────┐
│ derrickd (JobKeepAlive Login Item) │
│ Agent turns · Job scheduler · MCP tool host · Notifications │
└───────────────┬─────────────────────────────────┬─────────────────┘
│ in-process │ XPC
┌───────▼────────┐ ┌───────▼──────────────────┐
│ SQLite (WAL) │ │ DockerRunnerHelper XPC │
│ shared state │ │ docker CLI + pool │
└────────────────┘ └───────────┬────────────┘
│
┌───────────▼────────────┐
│ Go worker containers │
│ --network none │
└────────────────────────┘
- UI is a client: it does not own agent turns or MCP when the daemon is up.
- Daemon (
derrickd) is the single owner of OS notifications and in-process Agent/Job/MCP modules. - Docker runs untrusted Go for
script_exec, just-in-time plugin builds, and approved plugin invocations. - HostUI (
packages/HostUI) paints plugin screens from a declared schema. The host does not invent a default inbox.
See docs/adr-headless-backend.md and docs/services-plan.md.
Derrick treats model output and guest code as untrusted.
script_exec, plugins, web crawl, web search, and file extract share one Go worker imagederrick-worker:go-v1(digest-pinned,--network nonefor guests).- Plugin and script sources are compiled inside the worker container (Go 1.27.1 in the image). Users only need Docker Desktop.
- Canonical I/O types live in
packages/Structure/Sources/Contract/Resources/schemas/and are mirrored toworkers/go/internal/contract/schemas/. - No net/http, subprocess, filesystem access, or credentials inside the guest.
- The host dispatches
http.requestenvelopes, attaches secrets, and enforces egress policy. - Historical Swift guest notes: docs/adr-swift-script-runtime.md.
Before script_exec writes to disk, a configured LLM reviewer checks:
- Intent alignment with the user request
- No secret literals in source
- Safe handling of fetched content (no raw HTML leakage unless requested)
Rules live in packages/Structure/Sources/Contract/Resources/contracts/script-exec-contract.json (same pattern as connector plugins). A static Go verifier also rejects forbidden APIs.
- Host-owned HTTP (
HostHTTPClient) with egress blacklist (persisted in SQLite). - New destinations can require user approval (HITL network access modal).
- Plugins never receive tokens;
PluginDeclaredSecretAttacheradds Bearer/Basic headers on the host.
| Context | Storage |
|---|---|
| LLM API keys (dev) | ui/ui/Resources/.env when UI_SECRET_MODE=dotenv |
| LLM API keys (release) | Keychain |
| Plugin connector tokens | Keychain (PluginSecretKeychain) or .env aliases in dev |
| Inter-service XPC (debug) | MESSAGES_SECRET_KEY in .env |
| Inter-service XPC (release) | Keychain (MessagesSecretKey) |
Copy .env.example — never commit .env.
- Tool execution approvals
- Network access requests
- Plugin credential collection (Keychain save)
- Policy events (usage limits, content sensitivity)
PolicyEngine— in-process tool-call rules for chat (Structure/Policy/PolicyEngine).PolicyRuntime— persisted rules from SQLite (Structure/Policy/PolicyRuntime); implemented byStoreBacked*evaluators inpackages/PolicyRuntime.PolicyInterceptor/ToolRequestInterceptor(MemorySystem) — pipeline hooks that call those policies.
Connectors are just-in-time software with role: connector. They must emit a HostUI tree (ui.present) — copy messaging_inbox or compose their own. Messages live in SQLite; sync and send still go through the guest. See docs/messaging-design.md.
| Path | Role |
|---|---|
ui/ |
macOS app, Login Item daemon, XPC services |
packages/DBRepository |
SQLite schema, migrations, messaging tables |
packages/MCPServer |
MCP bridge, script execution, plugin runtime |
packages/Structure |
Architecture map: wire types, protocols, JSON schemas (AppLayerServices/, Policy/, Plugin/, Contract/, …) |
packages/HostUI |
Schema-driven screens for connectors and plugin present trees |
packages/Plugin |
Just-in-time software factory (builder, reviewer, release) |
packages/DerrickBackend |
Daemon runtime, notifications, HITL polling |
packages/DockerRunnerXPC |
Constrained Docker helper |
packages/PolicyRuntime |
Store-backed policy evaluators (Structure/Policy/PolicyRuntime) |
packages/LLMAgentClient |
Provider clients (OpenAI, Gemini, …) |
- macOS 27 with Xcode 27 (Swift 6.4+)
- Docker Desktop
- Apple Developer account (for signing entitlements)
- Clone the repo.
cp .env.example ui/ui/Resources/.envand add your API keys.- (Forks)
cp Config/Signing.xcconfig.example Config/Signing.xcconfigand run./scripts/configure-signing.sh. - Open
derrick.xcworkspace, select theuischeme, Run (⌘R). - Enable secret hooks:
git config core.hooksPath .githooks
Or from the terminal: ./scripts/build.sh test
See CONTRIBUTING.md and docs/development.md.
We maintain docs/opensource-plan.md for pre-release cleanup (secret audit, personal reference removal, CI).
Verify no secrets in git:
./scripts/verify-no-secrets.sh --history- Headless backend ADR
- Swift Docker runtime ADR
- Background services plan
- Messaging design
- Security policy
- Third-party notices
- Code of Conduct
“Derrick” is the project name used in this repository. Third-party names (OpenAI, Google, Slack, Docker, etc.) are trademarks of their respective owners.
See AGENTS.md for conventions used by coding agents working in this repo.