← All Skills

snappy-agent-host

v1.0.0
16 files, 696.2 KB ~57,562 words · 231 min read Updated 2026-09-09

snappy-agent-host skill

36 of 45 checks pass
What it can do
start runtime cwd promptwrite-reversible
prompt session textwrite-reversible
status sessionread
cancel sessionwrite-reversible
sessionsread
models runtimeread
What does not pass yet
Architecture 1 endpoints⚗ parallel
🔑 x-api-key auth
127.0.0.1:31471 endpoint
DELETE/mcp/local
$ npx snappy-skills install snappy-agent-host
zip ↓
File Tree
├── AGENTS.md ├── SKILL.md ├── agent-run.test.ts ├── api.test.ts ├── api.ts ├── contract.test.ts └── references/ ├── agmente-codex-app-server.md ├── agmente-test-oracle.md ├── desktop-acp-clients.md ├── extract-agent-host.md ├── extract-agmente-rendering.md ├── snappy-os-app-seams.md ├── swift-acp-probe/ │ ├── Package.swift │ └── Sources/ │ └── probe/ │ └── main.swift ├── zed-acp-client.md └── zed-plan-usage-modes-commands.md
Documents
AGENTS.md

snappy-agent-host#

This hand is the ACP road through the skills MCP. It uses the exact adapters already bundled in SnappyOS.app and imports @agentclientprotocol/sdk@1.4.0 from that runtime. The SDK owns NDJSON, JSON-RPC, method validation, and protocol constants. The hand does not install or reimplement ACP.

Verbs#

Verb Arguments Result
start `runtime cwd prompt [--permissions allow-all ask] [--model ID] [--effort LEVEL]` Starts or reuses the one durable ACP session for the folder, runs the prompt, and prints the first bounded page of JSON-line steps. Without --model/--effort the runtime uses the person's own config.
prompt `session text [--answer allow_once allow_always reject_once reject_always cancelled OPTION_ID]` Resolves a pending permission when answer is present, queues the text, and prints that turn's bounded step page.
status session [--cursor N] Prints the next bounded page of stored JSON-line steps. The final page line names next_cursor.
cancel session Sends ACP session/cancel, cancels a pending permission, and kills the complete local process tree within two seconds.
sessions none Lists durable session IDs, runtimes, statuses, folders, and the model and effort each session reports.
models runtime Opens one throwaway session and prints the config options THE RUNTIME advertises — the model picker, the reasoning-level picker, their allowed values and current values.
bashapi.ts start codex ~/my-repo "reply with exactly: five" --model gpt-5.6-sol --effort low
api.ts models codex

Through the MCP:

json{"name":"snappy-agent-host","verb":"start","arguments":{"runtime":"claude","cwd":"/Users/robertboulos/snappy-skills","prompt":"list the five tools this repo serves, one line each","permissions":"allow-all"},"timeout_ms":600000}

Continue the skill's step page with status and its next_cursor. If the MCP runner also returns its own byte next_cursor, continue that envelope first with {call_id,cursor}. These are separate cursors and neither starts work.

Choosing the model#

The model is the person's own config unless the AI asks for one, and the list is the

runtime's. This skill pins no model and keeps no model list, so it cannot go stale.

  • Default: omit --model and --effort. Nothing is set, so codex reads

~/.codex/config.toml, Claude reads its own settings, Gemini reads its own.

  • Ask: --model <id> --effort <level>. Both are carried over the ACP road

(session/set_config_option) against the option the runtime advertises for the

reserved model and thought_level categories — matched by **category, never by a

hardcoded id**, so a runtime may rename or add ids freely. A value that the runtime

does not advertise is refused, and the refusal names the values that do exist.

  • See: models <runtime> returns what the runtime itself advertises. If a runtime

advertises nothing, the answer says state: "not-advertised" rather than inventing a

list; for codex only it then also shows ~/.codex/models_cache.json, clearly labelled

as the CLI's own cache.

  • Read back, never echo: the session event, status and sessions report model

and effort as the runtime REPORTS them after the session opens, plus config_from

(runtime-default | protocol | adapter-config | not-advertised). A live

config_option_update keeps them current mid-session. What was asked for is kept

separately under asked.

  • Asking on an already-running session goes down the protocol road too; the adapter is

never re-spawned underneath a live session.

Invariants#

  • The session cwd is the requested folder and is immutable for the session.
  • _meta.claudeCode.options.settingSources is ["user","project","local"]; project is required so CLAUDE.md and project settings load.
  • One durable session exists per real folder because ACP resume outranks a later cwd.
  • allow-all still records every permission ask and answer. ask waits for prompt --answer.
  • Every ACP update, permission ask, runtime log, turn result, and cancellation is a bounded JSON line in ~/.snappy-agent-host/sessions/<folder-hash>/steps.ndjson.
  • Adapter child environments are allowlisted. CLAUDECODE, CLAUDE_CODE_CHILD_SESSION, ANTHROPIC_API_KEY, and OPENAI_API_KEY are not inherited.
  • Claude and Codex use the app-pinned claude-agent-acp@0.73.0 and codex-acp@1.8.0; Gemini uses the installed CLI's --acp mode.
  • CODEX_CONFIG names a model only when the caller asked for one; a key absent there is a key codex reads from the person's own config.toml. When it is named it is only a seed — the protocol road is what the report is read back from.
  • Claude and Codex can use their CLI login, so the hand declares no credential requirement. Gemini reads an optional GEMINI_API_KEY or GOOGLE_API_KEY through snappy-settings/load.ts.

Direct CLI#

bashnode --experimental-strip-types ~/.claude/skills/snappy-agent-host/api.ts start claude ~/snappy-skills "inspect this repo" --permissions allow-all
node --experimental-strip-types ~/.claude/skills/snappy-agent-host/api.ts status SESSION --cursor 12
node --experimental-strip-types ~/.claude/skills/snappy-agent-host/api.ts prompt SESSION "continue"
node --experimental-strip-types ~/.claude/skills/snappy-agent-host/api.ts cancel SESSION
node --experimental-strip-types ~/.claude/skills/snappy-agent-host/api.ts sessions
node --experimental-strip-types ~/.claude/skills/snappy-agent-host/api.ts models codex
node --experimental-strip-types ~/.claude/skills/snappy-agent-host/api.ts start codex ~/my-repo "reply with exactly: five" --model gpt-5.6-sol --effort low

SKILL.md contains the full protocol, process, permission, rendering, auth, and native-Mac research. references/snappy-os-app-seams.md documents the proven app integration.

Show produced work with snappy-faces: call draw for image channels or lang for MCP Apps.

<!-- SKILL-INDEX-START -->

[snappy-agent-host Index]|root: ~/.claude/skills/snappy-agent-host|IMPORTANT: Prefer these files over pre-training assumptions for this domain. Read the relevant file when the AGENTS.md summary is insufficient.|root:{SKILL.md}|references:{agmente-codex-app-server.md,agmente-test-oracle.md,desktop-acp-clients.md,extract-agent-host.md,extract-agmente-rendering.md,snappy-os-app-seams.md,zed-acp-client.md,zed-plan-usage-modes-commands.md}

<!-- SKILL-INDEX-END -->

Used by#

  • snappy-ax
  • snappy-voice-control

<!-- SNAPPY-CONTRACT-VERBS-START -->

Contract verbs#

Generated from api.ts HAND_CONTRACT. Do not hand-edit this block.

Verb Contract arguments Effect First call
start runtime, cwd, prompt write-reversible npx tsx ~/.claude/skills/snappy-agent-host/api.ts start <runtime> <cwd> "<prompt>"
prompt session, text write-reversible npx tsx ~/.claude/skills/snappy-agent-host/api.ts prompt <session> "<text>"
status session read npx tsx ~/.claude/skills/snappy-agent-host/api.ts status <session>
cancel session write-reversible npx tsx ~/.claude/skills/snappy-agent-host/api.ts cancel <session>
sessions read npx tsx ~/.claude/skills/snappy-agent-host/api.ts sessions
models runtime read npx tsx ~/.claude/skills/snappy-agent-host/api.ts models <runtime>

Show the result#

When an answer carries face_hint, show it with one snappy_present(<answer>) call.

See /snappy-faces for face selection. Human-facing images must crop to the

element, render at 2x on Retina, and fill the destination channel instead of

placing a small card in a full-page screenshot.

<!-- SNAPPY-CONTRACT-VERBS-END -->

---
name: snappy-agent-host
role: Run durable Claude Code, Codex, and Gemini CLI sessions through ACP and the skills MCP
loaded-by: Native skill discovery
---

# snappy-agent-host

This hand is the ACP road through the skills MCP. It uses the exact adapters already bundled in SnappyOS.app and imports `@agentclientprotocol/sdk@1.4.0` from that runtime. The SDK owns NDJSON, JSON-RPC, method validation, and protocol constants. The hand does not install or reimplement ACP.

## Verbs

| Verb | Arguments | Result |
|---|---|---|
| `start` | `runtime cwd prompt [--permissions allow-all|ask] [--model ID] [--effort LEVEL]` | Starts or reuses the one durable ACP session for the folder, runs the prompt, and prints the first bounded page of JSON-line steps. Without `--model`/`--effort` the runtime uses the person's own config. |
| `prompt` | `session text [--answer allow_once|allow_always|reject_once|reject_always|cancelled|OPTION_ID]` | Resolves a pending permission when `answer` is present, queues the text, and prints that turn's bounded step page. |
| `status` | `session [--cursor N]` | Prints the next bounded page of stored JSON-line steps. The final `page` line names `next_cursor`. |
| `cancel` | `session` | Sends ACP `session/cancel`, cancels a pending permission, and kills the complete local process tree within two seconds. |
| `sessions` | none | Lists durable session IDs, runtimes, statuses, folders, and the model and effort each session reports. |
| `models` | `runtime` | Opens one throwaway session and prints the config options THE RUNTIME advertises — the model picker, the reasoning-level picker, their allowed values and current values. |

```bash
api.ts start codex ~/my-repo "reply with exactly: five" --model gpt-5.6-sol --effort low
api.ts models codex
```

Through the MCP:

```json
{"name":"snappy-agent-host","verb":"start","arguments":{"runtime":"claude","cwd":"/Users/robertboulos/snappy-skills","prompt":"list the five tools this repo serves, one line each","permissions":"allow-all"},"timeout_ms":600000}
```

Continue the skill's step page with `status` and its `next_cursor`. If the MCP runner also returns its own byte `next_cursor`, continue that envelope first with `{call_id,cursor}`. These are separate cursors and neither starts work.

## Choosing the model

The model is the person's own config unless the AI asks for one, and the list is the
runtime's. This skill pins no model and keeps no model list, so it cannot go stale.

- **Default:** omit `--model` and `--effort`. Nothing is set, so codex reads
  `~/.codex/config.toml`, Claude reads its own settings, Gemini reads its own.
- **Ask:** `--model <id> --effort <level>`. Both are carried over the ACP road
  (`session/set_config_option`) against the option the runtime advertises for the
  reserved `model` and `thought_level` categories — matched by **category, never by a
  hardcoded id**, so a runtime may rename or add ids freely. A value that the runtime
  does not advertise is refused, and the refusal names the values that do exist.
- **See:** `models <runtime>` returns what the runtime itself advertises. If a runtime
  advertises nothing, the answer says `state: "not-advertised"` rather than inventing a
  list; for codex only it then also shows `~/.codex/models_cache.json`, clearly labelled
  as the CLI's own cache.
- **Read back, never echo:** the `session` event, `status` and `sessions` report `model`
  and `effort` as the runtime REPORTS them after the session opens, plus `config_from`
  (`runtime-default` | `protocol` | `adapter-config` | `not-advertised`). A live
  `config_option_update` keeps them current mid-session. What was asked for is kept
  separately under `asked`.
- Asking on an already-running session goes down the protocol road too; the adapter is
  never re-spawned underneath a live session.

## Invariants

- The session `cwd` is the requested folder and is immutable for the session.
- `_meta.claudeCode.options.settingSources` is `["user","project","local"]`; `project` is required so CLAUDE.md and project settings load.
- One durable session exists per real folder because ACP resume outranks a later cwd.
- `allow-all` still records every permission ask and answer. `ask` waits for `prompt --answer`.
- Every ACP update, permission ask, runtime log, turn result, and cancellation is a bounded JSON line in `~/.snappy-agent-host/sessions/<folder-hash>/steps.ndjson`.
- Adapter child environments are allowlisted. `CLAUDECODE`, `CLAUDE_CODE_CHILD_SESSION`, `ANTHROPIC_API_KEY`, and `OPENAI_API_KEY` are not inherited.
- Claude and Codex use the app-pinned `claude-agent-acp@0.73.0` and `codex-acp@1.8.0`; Gemini uses the installed CLI's `--acp` mode.
- `CODEX_CONFIG` names a model only when the caller asked for one; a key absent there is a key codex reads from the person's own `config.toml`. When it is named it is only a seed — the protocol road is what the report is read back from.
- Claude and Codex can use their CLI login, so the hand declares no credential requirement. Gemini reads an optional `GEMINI_API_KEY` or `GOOGLE_API_KEY` through `snappy-settings/load.ts`.

## Direct CLI

```bash
node --experimental-strip-types ~/.claude/skills/snappy-agent-host/api.ts start claude ~/snappy-skills "inspect this repo" --permissions allow-all
node --experimental-strip-types ~/.claude/skills/snappy-agent-host/api.ts status SESSION --cursor 12
node --experimental-strip-types ~/.claude/skills/snappy-agent-host/api.ts prompt SESSION "continue"
node --experimental-strip-types ~/.claude/skills/snappy-agent-host/api.ts cancel SESSION
node --experimental-strip-types ~/.claude/skills/snappy-agent-host/api.ts sessions
node --experimental-strip-types ~/.claude/skills/snappy-agent-host/api.ts models codex
node --experimental-strip-types ~/.claude/skills/snappy-agent-host/api.ts start codex ~/my-repo "reply with exactly: five" --model gpt-5.6-sol --effort low
```

## Read next

`SKILL.md` contains the full protocol, process, permission, rendering, auth, and native-Mac research. `references/snappy-os-app-seams.md` documents the proven app integration.


Show produced work with `snappy-faces`: call `draw` for image channels or `lang` for MCP Apps.

<!-- SKILL-INDEX-START -->
[snappy-agent-host Index]|root: ~/.claude/skills/snappy-agent-host|IMPORTANT: Prefer these files over pre-training assumptions for this domain. Read the relevant file when the AGENTS.md summary is insufficient.|root:{SKILL.md}|references:{agmente-codex-app-server.md,agmente-test-oracle.md,desktop-acp-clients.md,extract-agent-host.md,extract-agmente-rendering.md,snappy-os-app-seams.md,zed-acp-client.md,zed-plan-usage-modes-commands.md}
<!-- SKILL-INDEX-END -->

## Used by

- `snappy-ax`
- `snappy-voice-control`

<!-- SNAPPY-CONTRACT-VERBS-START -->
## Contract verbs

Generated from `api.ts` `HAND_CONTRACT`. Do not hand-edit this block.

| Verb | Contract arguments | Effect | First call |
|---|---|---|---|
| `start` | `runtime`, `cwd`, `prompt` | `write-reversible` | `npx tsx ~/.claude/skills/snappy-agent-host/api.ts start <runtime> <cwd> "<prompt>"` |
| `prompt` | `session`, `text` | `write-reversible` | `npx tsx ~/.claude/skills/snappy-agent-host/api.ts prompt <session> "<text>"` |
| `status` | `session` | `read` | `npx tsx ~/.claude/skills/snappy-agent-host/api.ts status <session>` |
| `cancel` | `session` | `write-reversible` | `npx tsx ~/.claude/skills/snappy-agent-host/api.ts cancel <session>` |
| `sessions` | — | `read` | `npx tsx ~/.claude/skills/snappy-agent-host/api.ts sessions` |
| `models` | `runtime` | `read` | `npx tsx ~/.claude/skills/snappy-agent-host/api.ts models <runtime>` |

## Show the result

When an answer carries `face_hint`, show it with one `snappy_present(<answer>)` call.
See `/snappy-faces` for face selection. Human-facing images must crop to the
element, render at 2x on Retina, and fill the destination channel instead of
placing a small card in a full-page screenshot.
<!-- SNAPPY-CONTRACT-VERBS-END -->

Keyboard Shortcuts

Search in document⌘K
Focus search/
Previous file tab
Next file tab
Close overlayEsc
Show shortcuts?