Harnesses

Claude Code, Codex, Copilot, opencode, Hermes, Antigravity, Cursor — equals.

A harness is the coding agent itself. Daktyl seats each one the same way and shows it on the phone the same way: same chat, same status, same calls, same approvals. There is no first-class harness.

Built in

These adapters ship inside the daemon. The table is read out of daktyl-cli/src/daemon/adapters/*.mjs when this page is generated, so it cannot drift from the code.

HarnessShapeWhat that means
antigravitystreamone long-lived process per seat; a turn is a line in and the reply streamed out
claude-codepanedrives a real terminal session you can attach to
claude-headlessturnone process per turn; the daemon feeds it prompts and reads the reply
claude-sdksdkan in-process SDK session; the model switches live
codexturnone process per turn; the daemon feeds it prompts and reads the reply
cursoracpspeaks the Agent Client Protocol over a pipe
opencodeacpspeaks the Agent Client Protocol over a pipe

Adding one is configuration

Any harness that speaks the Agent Client Protocol is a block in ~/.daktyl/config.json — no new code, no release. Hermes, Copilot and opencode are seated exactly this way on live hosts today:

"adapters": {
  "hermes": { "kind": "acp", "argv": ["hermes", "acp"] }
}

A name the build does not know is refused by name — never silently mapped to another harness.

Setting one up

Install the harness and sign in to it on the machine; the daemon finds it and seats it. Daktyl never installs a harness, signs in to one or holds its keys. The table is read out of the adapters: the binary each one looks for, the variable that points it somewhere else, and the hint the daemon gives when it cannot find it (where it gives one).

HarnessLooks forOverrideWhen it is missing
antigravityagyDAKTYL_AGY_BINinstall Antigravity, or set DAKTYL_AGY_BIN to its path
claude-codeclaudeDAKTYL_CLAUDE_BIN
claude-headlessclaudeDAKTYL_CLAUDE_BINinstall Claude Code, or set DAKTYL_CLAUDE_BIN to its path
claude-sdkclaudeDAKTYL_CLAUDE_BIN
codexcodexDAKTYL_CODEX_BINinstall the Codex CLI, or set DAKTYL_CODEX_BIN to its path
cursorcursor-agentDAKTYL_CURSOR_BINinstall the Cursor CLI (cursor-agent), or set DAKTYL_CURSOR_BIN to its path
opencodeopencodeinstall opencode, or set its argv in adapters.opencode

With one harness installed, an agent started without naming one uses it. With several, name it: daktyl create --harness codex.

Claude Code (claude-code, claude-sdk, claude-headless)

One claude binary, three ways of driving it; an unnamed start uses the terminal one, claude-code. Install Claude Code and run claude once in a terminal to sign in. The terminal harness runs inside tmux, so install tmux as well (brew install tmux, or sudo apt-get install -y tmux); daktyl attach opens a running agent's session. It also needs the channel plugin the installer puts in place — without it the harness is reported as not present rather than launched deaf.

On macOS, claude-sdk signs in through the login Keychain, so the daemon has to run in your login session. Where it cannot reach the Keychain it refuses the seat and says so.

Codex

Install the Codex CLI and sign in with codex login (codex login status tells you whether you are). Each turn is one codex exec in the project directory. The Daktyl tools are passed to every turn on the command line, so nothing needs adding to ~/.codex/config.toml. A signed-out Codex shows as blocked on sign-in, not as a crash.

Cursor

Install the Cursor CLI (cursor-agent) and sign in with cursor-agent login. On a machine with no browser, NO_OPEN_BROWSER=1 cursor-agent login prints a link you can approve on your phone. The CLI's sign-in is separate from the Cursor editor's. Daktyl runs it as cursor-agent acp; a Cursor seat stays on the model it started with (no live model switch) and has no compact.

Antigravity

Install Antigravity so that agy is on the path, and sign in to it once. On macOS its credentials live in the login Keychain, so the daemon has to run in your login session; where it cannot reach the Keychain the harness is reported as not probed, with the reason. One agy process stays up per seat between turns. Antigravity accepts a conversation id it does not know and quietly starts a new conversation, so Daktyl checks the id every reply carries against the one it asked for, and a resume that forked is an error rather than a fresh conversation passed off as the old one.

opencode

Built in, run as opencode acp. Give opencode a provider itself (its own sign-in or a provider key). The models a seat may switch between are the ones declared in the opencode.json of the directory named by adapters.opencode.cwd (provider.<name>.models, plus its model); opencode's own catalog also lists models merged in from elsewhere that may never have been pulled, so only the declared ones are offered. Effort is written into that file as the model's reasoningEffort and applies on the next restart. An agent started in a registered project runs there; otherwise it runs in that directory.

"adapters": {
  "opencode": { "cwd": "/home/you/work" }
}

Hermes

Seated by configuration, with the block shown above. Set its model and provider in Hermes itself. It has no effort control over ACP. When Hermes declares no model option, the block's own model is what the phone shows.

Copilot (advanced setup)

The GitHub Copilot CLI speaks ACP and is seated by configuration too ("copilot": { "kind": "acp", "argv": ["copilot", "--acp"] }), after you sign in to it. It ignores the MCP servers an ACP client declares, so a Copilot seat chats but has no Daktyl tools unless you add the Daktyl server to ~/.copilot/mcp-config.json yourself.

Capabilities

Harnesses differ, and Daktyl says so rather than pretending. Each seat reports what it can do, and the app gates its controls on that: a button you can see is a button that works. The vocabulary is frozen — an adapter may claim native (the harness does it), emulated (Daktyl does it around the harness) or unsupported; a capability the seat does not mention is unknown, not no.

CapabilityWhat it gates
statuslive state on the phone (thinking, running, idle)
contextthe context ring and token telemetry
modelswitching the model from the app
effortreasoning-effort level
permission_modethe tool-approval mode picker
thinkingextended thinking on or off
compactcompacting the conversation
interruptstopping a turn mid-flight
planplan mode
approvalstool approvals reaching your lock screen
resumeresuming the same conversation after a restart
calljoining a voice call
steersending a message while a turn is running
projectlaunching inside a registered project directory
toolsper-tool-call activity in the timeline
diffsworking-tree changes as a diff on the phone
restart_free_model_switchwhether a model switch keeps the process alive

Choosing one

daktyl create --harness codex --model gpt-5 --project my-repo
daktyl agent ls        # what is running here, panes and seats
daktyl fleet           # everything, everywhere, with model and context