docs/adapters/overview.md
Adapters are the bridge between Paperclip's orchestration layer and agent runtimes. Each adapter knows how to invoke a specific type of AI agent and capture its results.
When a heartbeat fires, Paperclip:
adapterType and adapterConfigexecute() function with the execution context| Adapter | Type Key | Description |
|---|---|---|
| Claude Code | claude_local | Runs Claude Code CLI locally, with a native ACP engine when available |
| Codex | codex_local | Runs OpenAI Codex CLI locally, with a native ACP engine when available |
| Gemini CLI | gemini_local | Runs Gemini CLI locally (experimental — adapter package exists, not yet in stable type enum) |
| OpenCode | opencode_local | Runs OpenCode CLI locally (multi-provider provider/model) |
| Cursor | cursor | Runs Cursor in background mode |
| Pi | pi_local | Runs an embedded Pi agent locally |
| Hermes | hermes_local | Runs the local Hermes CLI through @paperclipai/hermes-paperclip-adapter |
| Hermes Gateway | hermes_gateway | Calls an already-running Hermes API server through @paperclipai/hermes-paperclip-adapter/gateway |
| OpenClaw Gateway | openclaw_gateway | Connects to an OpenClaw gateway endpoint |
| Process | process | Executes arbitrary shell commands |
| HTTP | http | Sends webhooks to external agents |
Local CLI adapters can run on the Paperclip host, SSH targets, or managed sandbox targets. The adapter decides which credential home is authoritative before the CLI starts:
| Adapter | Credential topology | Which credential file wins on managed sandbox targets |
|---|---|---|
codex_local | Host-owns-auth for Paperclip-managed CODEX_HOME | A host-owned auth.json is symlinked into the managed CODEX_HOME and uploaded to the sandbox. If a per-agent OPENAI_API_KEY is configured, Paperclip writes an API-key auth.json instead and that file wins. A login baked into the sandbox image is shadowed because Codex runs with Paperclip's uploaded CODEX_HOME. |
claude_local | Snapshot-owns-auth for managed remote Claude config | Paperclip uploads only sanitized settings and skill/runtime assets. When the remote managed config has no Claude credential files, it copies .credentials.json or credentials.json from the sandbox image's own $HOME/.claude, so the image's login wins. |
Worked examples:
~/.codex/auth.json
is symlinked into the managed home, then uploaded as the sandbox
CODEX_HOME. Codex reads that uploaded file and does not use any
auth.json already present inside the sandbox image.CLAUDE_CONFIG_DIR, then fills missing .credentials.json /
credentials.json from the sandbox image's own $HOME/.claude. The
snapshot's Claude login is the credential source for the run.Use hermes_local when Paperclip should start the local hermes CLI on the
same host for each heartbeat. Use hermes_gateway when Hermes is already
running as an HTTP/SSE API server and Paperclip should call that server instead
of spawning a process. Both type keys are stable built-ins.
The unified Hermes package owns both built-in adapters. The older
@paperclipai/adapter-hermes-gateway package remains only as a deprecated
compatibility shim that re-exports the gateway entrypoints for one release.
New plugin overrides should target @paperclipai/hermes-paperclip-adapter and
set the desired type key (hermes_local or hermes_gateway).
These adapters ship as standalone npm packages and are installed via the plugin system:
| Adapter | Package | Type Key | Description |
|---|---|---|---|
| Droid | @henkey/droid-paperclip-adapter | droid_local | Runs Factory Droid locally |
You can build and distribute adapters as standalone packages — no changes to Paperclip's source code required. External adapters are loaded at startup via the plugin system.
# Install from npm via API
curl -X POST http://localhost:3102/api/adapters \
-d '{"packageName": "my-paperclip-adapter"}'
# Or link from a local directory
curl -X POST http://localhost:3102/api/adapters \
-d '{"localPath": "/home/user/my-adapter"}'
See External Adapters for the full guide.
Each adapter is a package with modules consumed by three registries:
my-adapter/
src/
index.ts # Shared metadata (type, label, models)
server/
execute.ts # Core execution logic
parse.ts # Output parsing
test.ts # Environment diagnostics
ui-parser.ts # Self-contained UI transcript parser (for external adapters)
cli/
format-event.ts # Terminal output for `paperclipai run --watch`
| Registry | What it does | Source |
|---|---|---|
| Server | Executes agents, captures results | createServerAdapter() from package root |
| UI | Renders run transcripts, provides config forms | ui-parser.js (dynamic) or static import (built-in) |
| CLI | Formats terminal output for live watching | Static import |
claude_local, codex_local, opencode_local, hermes_local, or install droid_local as an external pluginclaude_local, codex_local, or gemini_local with adapterConfig.engine set to acp when the execution environment satisfies the ACP prerequisites — see Feedback granularityhermes_gatewayprocesshttpAdapter choice determines how much structured, live detail a run's transcript can show while the agent is still working. Every adapter's stdout is streamed to the run log and rendered live in the UI — including runs on sandbox execution targets, whose logs are tailed and delivered incrementally — but the granularity of what you see depends on the event stream the adapter emits.
Rough tiers, richest first:
claude_local, codex_local, or gemini_local with engine: "acp") — full structured event stream. ACP emits a JSONL event per meaningful runtime moment: acpx.session (agent, mode, session identity), acpx.status (progress text plus context-window usage), acpx.text_delta (assistant/thinking token deltas), acpx.tool_call (tool title, call id, and status updates as the call progresses), acpx.result (stop reason summary), and acpx.error (code, message, retryability). The transcript renders these as live-updating message, thinking, tool, and status blocks, and repeated acpx.tool_call status updates fold into a single tool card instead of stacking duplicates.claude_local, codex_local, cursor, opencode_local, …). These parse each CLI's own streaming JSON output. You get assistant text, tool calls/results, and a final usage/cost summary, but granularity is limited to what the CLI prints — some emit tool progress, others only call/finish pairs.process, http). Plain stdout/stderr lines with no structured transcript — you see raw output only.Recommendation: use the native ACP engine on claude_local, codex_local, or gemini_local when the selected execution environment supports it. Rich ACP status events (including context usage) and incremental tool-call updates give the closest thing to watching the agent work locally.
External adapters can ship a self-contained UI parser that tells the Paperclip web UI how to render their stdout. Without it, the UI uses a generic shell parser. See the UI Parser Contract for details.