A native Swift macOS 27 desktop agent harness: chat with LLM providers, run isolated sandboxed agent actions in Docker, build connector plugins, schedule background jobs, and manage messaging connectors — with human-in-the-loop approvals and a security-first execution model.
License: Apache 2.0
| Area | Description |
|---|---|
| Chat | Multi-tab conversations with OpenAI, Gemini, and other configured models |
| Tools (MCP) | Model Context Protocol tool host inside the headless daemon |
| Scripts | Agent-generated Swift executed in isolated Docker containers Includes secondary agent code reviewer and approvals flow. |
| Plugin factory | LLM-assisted creation of versioned, reviewed connector plugins |
| Jobs | Scheduled and deferred tool/agent runs that survive app quit |
| Messaging | Connector plugins (e.g. Slack) with threads, history, and live sync |
| Policy & HITL | Approvals for tools, network access, usage limits, and credentials |
┌─────────────────────────────────────────────────────────────┐
│ Derrick.app (UI) — SwiftUI client only │
│ Chat · Messaging · Plugins · Settings · Approval modals │
└───────────────────────────┬─────────────────────────────────┘
│ 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 │
└────────────────┘ └───────────┬────────────┘
│
┌───────────▼────────────┐
│ Swift guest 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 Swift for
script_exec, plugin factory builds, and approved plugin invocations.
See docs/adr-headless-backend.md and docs/services-plan.md.
Derrick treats model output and guest code as untrusted.
- Guest programs run in
swiftlang/swift:nightlycontainers with--network none. - No shell,
Process,URLSession, or credentials inside the guest. - The host dispatches
http.requestenvelopes, attaches secrets, and enforces egress policy. - Documented in 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)
Instructions live in ui/SharedAgentRuntime/Resources/script_reviewer_instructions.md. A static Swift 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 / PolicyInterceptor evaluate tool calls and agent behavior against stored rules before execution.
Connector plugins declare role: connector in the manifest. Messages are persisted in SQLite; connector plugins sync and send through the guest runtime. 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/Plugin |
Agent plugin manifest, factory, envelope protocol |
packages/DerrickBackend |
Daemon runtime, notifications, HITL polling |
packages/DockerRunnerXPC |
Constrained Docker helper |
packages/PolicyEngine |
Policy evaluation |
packages/LLMAgentClient |
Provider clients (OpenAI, Gemini, …) |
packages/ServiceContracts |
Shared DTOs and XPC codecs |
- 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.