{"_id":"@dwahdany/open-claude","_rev":"6-d0dc2408c01923d560db5f164f5f362a","name":"@dwahdany/open-claude","dist-tags":{"latest":"0.3.3"},"versions":{"0.1.0":{"name":"@dwahdany/open-claude","version":"0.1.0","keywords":["claude","claude-code","opencode","tui","agent","anthropic"],"license":"MIT","_id":"@dwahdany/open-claude@0.1.0","maintainers":[{"name":"dwahdany","email":"npmjs.overpass@r.wahdany.eu"}],"homepage":"https://github.com/dwahdany/open-claude#readme","bugs":{"url":"https://github.com/dwahdany/open-claude/issues"},"bin":{"open-claude":"bin/open-claude.mjs"},"dist":{"shasum":"8de0eaf385dc00c845b39fa7203acfe591518145","tarball":"https://registry.npmjs.org/@dwahdany/open-claude/-/open-claude-0.1.0.tgz","fileCount":13,"integrity":"sha512-0lg4culkgeKccrH6VhZIwuGwzR859FKYYmGG9H/iJdX9/aV1l7nYPygijAIc3t91ZEPWkqiJM2mjsWXKkgZ79Q==","signatures":[{"sig":"MEUCIGWRZ078E+u6gj/W6j9DJnvPji8rsjjimeLcY6pqeTk9AiEAu1NWtBd2CqPTM+8tuHJDQ9Ofo8nHtReZKgF4bDMKGG4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":81663},"type":"module","shasum":"8de0eaf385dc00c845b39fa7203acfe591518145","engines":{"bun":">=1.3.0"},"scripts":{"start":"bun run index.ts","typecheck":"tsc --noEmit -p tsconfig.json","prepublishOnly":"bun run typecheck"},"_npmUser":{"name":"dwahdany","email":"npmjs.overpass@r.wahdany.eu"},"_integrity":"sha512-0lg4culkgeKccrH6VhZIwuGwzR859FKYYmGG9H/iJdX9/aV1l7nYPygijAIc3t91ZEPWkqiJM2mjsWXKkgZ79Q==","repository":{"url":"git+https://github.com/dwahdany/open-claude.git","type":"git"},"_npmVersion":"10.8.3","description":"Run the opencode TUI on a Claude Code backend — an opencode v1.17.19 API server over the Claude Agent SDK","directories":{},"_nodeVersion":"24.3.0","dependencies":{"hono":"^4.12.30","@anthropic-ai/claude-agent-sdk":"0.3.207"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest","typescript":"^7.0.2","@opencode-ai/sdk":"1.17.19"},"_npmOperationalInternal":{"tmp":"tmp/open-claude_0.1.0_1784044652768_0.04755053825352529","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@dwahdany/open-claude","version":"0.2.0","keywords":["claude","claude-code","opencode","tui","agent","anthropic"],"license":"MIT","_id":"@dwahdany/open-claude@0.2.0","maintainers":[{"name":"dwahdany","email":"npmjs.overpass@r.wahdany.eu"}],"homepage":"https://github.com/dwahdany/open-claude#readme","bugs":{"url":"https://github.com/dwahdany/open-claude/issues"},"bin":{"open-claude":"bin/open-claude.mjs"},"dist":{"shasum":"dd7913034493fe3517d891ec4ab4cbf1771e1b80","tarball":"https://registry.npmjs.org/@dwahdany/open-claude/-/open-claude-0.2.0.tgz","fileCount":13,"integrity":"sha512-b1u5zL7dcUwoLu6n8nCygjNaP7R4i9kA50+uhSw0JC5odPqeYtQeBy+q8RNwTnUWwqdQCoqqjEwF4dF47OQWxg==","signatures":[{"sig":"MEYCIQDyORDn52mNgRXQg8bQP5ZrEGi8GvcAAC7NnGCzad7m0QIhAIHFm+xWtR0T1q5tsURbKZE9wxQ8jXjF5LcZpsg4Qmrf","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":82695},"type":"module","shasum":"dd7913034493fe3517d891ec4ab4cbf1771e1b80","engines":{"bun":">=1.3.0"},"scripts":{"start":"bun run index.ts","typecheck":"tsc --noEmit -p tsconfig.json","prepublishOnly":"bun run typecheck"},"_npmUser":{"name":"dwahdany","email":"npmjs.overpass@r.wahdany.eu"},"_integrity":"sha512-b1u5zL7dcUwoLu6n8nCygjNaP7R4i9kA50+uhSw0JC5odPqeYtQeBy+q8RNwTnUWwqdQCoqqjEwF4dF47OQWxg==","repository":{"url":"git+https://github.com/dwahdany/open-claude.git","type":"git"},"_npmVersion":"10.8.3","description":"Run the opencode TUI on a Claude Code backend — an opencode v1.17.19 API server over the Claude Agent SDK","directories":{},"_nodeVersion":"24.3.0","dependencies":{"hono":"^4.12.30","@anthropic-ai/claude-agent-sdk":"0.3.207"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest","typescript":"^7.0.2","@opencode-ai/sdk":"1.17.19"},"_npmOperationalInternal":{"tmp":"tmp/open-claude_0.2.0_1784131061285_0.12259689269667517","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@dwahdany/open-claude","version":"0.2.2","keywords":["claude","claude-code","opencode","tui","agent","anthropic"],"license":"MIT","_id":"@dwahdany/open-claude@0.2.2","maintainers":[{"name":"dwahdany","email":"npmjs.overpass@r.wahdany.eu"}],"homepage":"https://github.com/dwahdany/open-claude#readme","bugs":{"url":"https://github.com/dwahdany/open-claude/issues"},"bin":{"open-claude":"bin/open-claude.mjs"},"dist":{"shasum":"2f11bd3836dd79208b131381404f43da98478f7e","tarball":"https://registry.npmjs.org/@dwahdany/open-claude/-/open-claude-0.2.2.tgz","fileCount":13,"integrity":"sha512-quS2cjIa/xjXeUy5TpgYOQKkGNdIu24PI28RjisFFSpY+Ihvh0VE03xJDe9fkaP+PktvLOwEJGi8EUhtrTuZvA==","signatures":[{"sig":"MEUCIQCXDUEctgJMDaEM8GOUG1I+ftdVtAXGdPHqkNo3MsIcCAIgSJZdMBjnt0JPgleleaWOEPY8+wPPdgcvLSNgUG6XHO0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":83636},"type":"module","shasum":"2f11bd3836dd79208b131381404f43da98478f7e","engines":{"bun":">=1.3.0"},"scripts":{"start":"bun run index.ts","typecheck":"tsc --noEmit -p tsconfig.json","prepublishOnly":"bun run typecheck"},"_npmUser":{"name":"dwahdany","email":"npmjs.overpass@r.wahdany.eu"},"_integrity":"sha512-quS2cjIa/xjXeUy5TpgYOQKkGNdIu24PI28RjisFFSpY+Ihvh0VE03xJDe9fkaP+PktvLOwEJGi8EUhtrTuZvA==","repository":{"url":"git+https://github.com/dwahdany/open-claude.git","type":"git"},"_npmVersion":"10.8.3","description":"Run the opencode TUI on a Claude Code backend — an opencode v1.17.19 API server over the Claude Agent SDK","directories":{},"_nodeVersion":"24.3.0","dependencies":{"hono":"^4.12.30","@anthropic-ai/claude-agent-sdk":"0.3.207"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest","typescript":"^7.0.2","@opencode-ai/sdk":"1.17.19"},"_npmOperationalInternal":{"tmp":"tmp/open-claude_0.2.2_1784138707170_0.590693397884146","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@dwahdany/open-claude","version":"0.3.0","keywords":["claude","claude-code","opencode","tui","agent","anthropic"],"license":"MIT","_id":"@dwahdany/open-claude@0.3.0","maintainers":[{"name":"dwahdany","email":"npmjs.overpass@r.wahdany.eu"}],"homepage":"https://github.com/dwahdany/open-claude#readme","bugs":{"url":"https://github.com/dwahdany/open-claude/issues"},"bin":{"open-claude":"bin/open-claude.mjs"},"dist":{"shasum":"ae11bee63d5df2808efbf08d815ed7609192e754","tarball":"https://registry.npmjs.org/@dwahdany/open-claude/-/open-claude-0.3.0.tgz","fileCount":15,"integrity":"sha512-pDY2CYnWx5Ey8LwAgc7/9Y6GkI8T4OFRZWNVblEEO5v7Ji/MJUk6e37FJtAsC0g7Shb1cPuXSwmSL2wc2Fex3g==","signatures":[{"sig":"MEUCIQCtRl/ahCtHUgSC28/Ode6u1E3IXDndTJ26plau4i6x6wIgObspgvoEuVDjCDcHAwAzB5UHUXvmeG2hECh8bAFUaq8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":145418},"type":"module","shasum":"ae11bee63d5df2808efbf08d815ed7609192e754","engines":{"bun":">=1.3.0"},"scripts":{"start":"bun run index.ts","typecheck":"tsc --noEmit -p tsconfig.json","prepublishOnly":"bun run typecheck"},"_npmUser":{"name":"dwahdany","email":"npmjs.overpass@r.wahdany.eu"},"_integrity":"sha512-pDY2CYnWx5Ey8LwAgc7/9Y6GkI8T4OFRZWNVblEEO5v7Ji/MJUk6e37FJtAsC0g7Shb1cPuXSwmSL2wc2Fex3g==","repository":{"url":"git+https://github.com/dwahdany/open-claude.git","type":"git"},"_npmVersion":"10.8.3","description":"Run the opencode TUI on a Claude Code backend — an opencode v1.17.19 API server over the Claude Agent SDK","directories":{},"_nodeVersion":"24.3.0","dependencies":{"hono":"^4.12.30","@anthropic-ai/claude-agent-sdk":"0.3.207"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest","typescript":"^7.0.2","@opencode-ai/sdk":"1.17.19"},"_npmOperationalInternal":{"tmp":"tmp/open-claude_0.3.0_1784153736795_0.046194551206534706","host":"s3://npm-registry-packages-npm-production"}},"0.3.2":{"name":"@dwahdany/open-claude","version":"0.3.2","keywords":["claude","claude-code","opencode","tui","agent","anthropic"],"license":"MIT","_id":"@dwahdany/open-claude@0.3.2","maintainers":[{"name":"dwahdany","email":"npmjs.overpass@r.wahdany.eu"}],"homepage":"https://github.com/dwahdany/open-claude#readme","bugs":{"url":"https://github.com/dwahdany/open-claude/issues"},"bin":{"open-claude":"bin/open-claude.mjs"},"dist":{"shasum":"0ebb17396ab2c94b6122a742a4b50a09d4b8304d","tarball":"https://registry.npmjs.org/@dwahdany/open-claude/-/open-claude-0.3.2.tgz","fileCount":17,"integrity":"sha512-Qvr51N0bSiSCLLmq/UcMHWNEyKznqhrrWcsuu7tscnmh98OgonAd43Njq9+nvAzFybM1WD5mRE12AOlDc6E6cA==","signatures":[{"sig":"MEUCIQCHO9hVnkxTsR9kLCqgHfcSzGUWjtzNPjN5XGjkxZhgvgIgLee92IRvyWAQEwwyiqE+Tjr6XKOvZ8HJ01OeY8Vzpsg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dwahdany%2fopen-claude@0.3.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":159376},"type":"module","engines":{"bun":">=1.3.0"},"gitHead":"df817ca69d8f74cd2700dcab3e99943017d29a63","scripts":{"start":"bun run index.ts","typecheck":"tsc --noEmit -p tsconfig.json","prepublishOnly":"bun run typecheck"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:bf74c382-df1a-47a0-b3f1-7c0c412007d6"}},"repository":{"url":"git+https://github.com/dwahdany/open-claude.git","type":"git"},"_npmVersion":"12.0.1","description":"Run the opencode TUI on a Claude Code backend — an opencode v1.17.19 API server over the Claude Agent SDK","directories":{},"_nodeVersion":"24.18.0","dependencies":{"hono":"^4.12.30","@anthropic-ai/claude-agent-sdk":"0.3.207"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest","typescript":"^7.0.2","@opencode-ai/sdk":"1.17.19"},"_npmOperationalInternal":{"tmp":"tmp/open-claude_0.3.2_1784199051969_0.37137933607775797","host":"s3://npm-registry-packages-npm-production"}},"0.3.3":{"name":"@dwahdany/open-claude","version":"0.3.3","publishConfig":{"access":"public"},"description":"Run the opencode TUI on a Claude Code backend — an opencode v1.17.19 API server over the Claude Agent SDK","type":"module","license":"MIT","bin":{"open-claude":"bin/open-claude.mjs"},"keywords":["claude","claude-code","opencode","tui","agent","anthropic"],"engines":{"bun":">=1.3.0"},"repository":{"type":"git","url":"git+https://github.com/dwahdany/open-claude.git"},"homepage":"https://github.com/dwahdany/open-claude#readme","bugs":{"url":"https://github.com/dwahdany/open-claude/issues"},"scripts":{"start":"bun run index.ts","typecheck":"tsc --noEmit -p tsconfig.json","prepublishOnly":"bun run typecheck"},"devDependencies":{"@opencode-ai/sdk":"1.17.19","@types/bun":"latest","typescript":"^7.0.2"},"dependencies":{"@anthropic-ai/claude-agent-sdk":"0.3.207","hono":"^4.12.30"},"gitHead":"29bc92dfc23ce3d1ffe8e65c30a302e3b7694744","_id":"@dwahdany/open-claude@0.3.3","_nodeVersion":"24.18.0","_npmVersion":"12.0.1","dist":{"integrity":"sha512-4WfIlVGhhMKkYPZClZ3R/gj5y01HSMALs3STbYf577hGIT77efJF4BnG5qLPQTQCgC7JyE+Xr/xkR8hjkieJqw==","shasum":"15829d2ab2facbe74f484f29e0c48d826a57c3b2","tarball":"https://registry.npmjs.org/@dwahdany/open-claude/-/open-claude-0.3.3.tgz","fileCount":19,"unpackedSize":182045,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dwahdany%2fopen-claude@0.3.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCfKTuMMBWga64WAs+uz0uv49J6ahirmFU1y++93DpYoQIgPNYymCqCZO9lP83kTUQPeLTOcEmH88UMDhvvFEw62UY="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:bf74c382-df1a-47a0-b3f1-7c0c412007d6"}},"directories":{},"maintainers":[{"name":"dwahdany","email":"npmjs.overpass@r.wahdany.eu"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/open-claude_0.3.3_1784211271046_0.9474621005658075"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-14T15:57:32.448Z","modified":"2026-07-16T14:14:31.510Z","0.1.0":"2026-07-14T15:57:32.968Z","0.2.0":"2026-07-15T15:57:41.433Z","0.2.2":"2026-07-15T18:05:07.317Z","0.3.0":"2026-07-15T22:15:36.944Z","0.3.2":"2026-07-16T10:50:52.107Z","0.3.3":"2026-07-16T14:14:31.184Z"},"bugs":{"url":"https://github.com/dwahdany/open-claude/issues"},"license":"MIT","homepage":"https://github.com/dwahdany/open-claude#readme","keywords":["claude","claude-code","opencode","tui","agent","anthropic"],"repository":{"type":"git","url":"git+https://github.com/dwahdany/open-claude.git"},"description":"Run the opencode TUI on a Claude Code backend — an opencode v1.17.19 API server over the Claude Agent SDK","maintainers":[{"name":"dwahdany","email":"npmjs.overpass@r.wahdany.eu"}],"readme":"# open-claude\n\nRun the **opencode** frontend (its TUI, and by extension its web/desktop clients) on top\nof a **Claude Code** backend.\n\nopencode has a strict client/server split: every frontend is a thin client of a local\nHTTP + SSE API, and `opencode attach <url>` points the stock TUI at any server that speaks\nthat API. `open-claude` is that server — it reimplements the opencode v1.17.19 wire\ncontract and drives the [Claude Agent SDK](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk)\n(the real Claude Code engine) underneath. So you get opencode's renderer with Claude Code's\nagent, prompts, tools, and permission model.\n\n```\n┌────────────────┐  HTTP + SSE (opencode API)  ┌──────────────┐   stream-json   ┌─────────────┐\n│ opencode TUI   │ ───────────────────────────▶│  open-claude │ ───────────────▶│ Claude Code │\n│ (stock, v1.17) │ ◀─────────────────────────── │  (this repo) │ ◀───────────────│ (Agent SDK) │\n└────────────────┘    server.connected /        └──────────────┘   SDK messages  └─────────────┘\n                      message.* / permission.*\n```\n\n## Requirements\n\n- [Bun](https://bun.sh) ≥ 1.3\n- `opencode` CLI **v1.17.19** (the contract is pinned to this version — `opencode upgrade`)\n- Claude auth: either a Claude Pro/Max subscription (`claude /login`) or `ANTHROPIC_API_KEY`\n  in the environment. The Agent SDK picks up whichever is present.\n\n## Usage\n\n```sh\nbunx @dwahdany/open-claude\n```\n\nThat's the whole quickstart: it starts the server and drops you straight into the opencode\nTUI, attached. Quitting the TUI stops the server. (open-claude itself is just the server —\nthe TUI always connects via opencode's own `opencode attach <url>`; the default merely runs\nthat for you.)\n\nThe server listens on `127.0.0.1` with an OS-assigned free port (same defaults as\n`opencode serve`), so multiple instances run side by side without colliding. Pass\n`--port <n>` if you need a stable address.\n\nTo run the server standalone and connect clients yourself, pass `--serve` (this also\nhappens automatically when opencode isn't installed or stdout isn't a terminal):\n\n```sh\nbunx @dwahdany/open-claude --serve --directory /path/to/your/project\n# prints e.g. \"open-claude listening on http://127.0.0.1:52341\" — in another terminal:\nopencode attach http://127.0.0.1:52341\n```\n\nFrom a checkout: `bun install && bun run start`.\n\n`--directory` is the working directory the Claude Code agent operates in (defaults to the\nshim's cwd). Then use the opencode TUI exactly as normal: type prompts, watch streaming\ntext and tool calls, approve/deny permission prompts. First `bunx` run downloads the\nbundled Claude Code engine (~230MB, cached); later runs start instantly.\n\nOn the very first interactive run, open-claude offers to save an `oclaude` shell alias\n(one appended line in your `~/.zshrc` / `~/.bashrc` / fish config, pointing at however you\nlaunched it — global install, `bunx`, or a checkout). Answer once and it never asks again;\nset `OPENCLAUDE_NO_ALIAS_PROMPT=1` to suppress the offer entirely.\n\n### Config\n\n| Env var | Effect |\n|---|---|\n| `OPENCLAUDE_SETTING_SOURCES=none` | Ignore your `~/.claude` allowlists so **every** gated tool routes through opencode's permission dialog (clean-room prompts). Default: load your Claude Code settings, matching normal Claude Code behavior. |\n| `OPENCLAUDE_ULTRACODE=1` | Enable Claude Code's ultracode mode (`Settings.ultracode`): xhigh effort plus standing workflow orchestration. Only takes effect when your account has workflows enabled and the model supports xhigh. |\n| `OPENCLAUDE_NO_ALIAS_PROMPT=1` | Never offer the first-run `oclaude` shell alias. |\n| `OPENCLAUDE_NO_UPDATE_CHECK=1` | Never check npm for a newer version. |\n| `OPENCLAUDE_NO_QUESTION_NOTES=1` | Drop the synthetic \"Notes\" tab from question dialogs — restores one-keystroke submit on single questions; free text is still available via \"Type your own answer\". |\n\n### Updating\n\nopen-claude updates through whatever runs it — there is no self-updater, by design:\n\n| How you run it | Update with |\n|---|---|\n| Global install | `bun add -g @dwahdany/open-claude@latest` (or `npm i -g …@latest`) |\n| `bunx` / `npx` | `bunx @dwahdany/open-claude@latest` — the bare spec reuses the cached copy, so pass `@latest` when you want the newest |\n| Source checkout | `git pull` |\n\nAt most once a day (interactive runs only) open-claude asks npm whether a newer version\nexists and prints a one-line notice with the command matching your launch mode — in serve\nlogs, or after the TUI hands the terminal back, never during a session. Offline or slow\nregistries are ignored silently. `OPENCLAUDE_NO_UPDATE_CHECK=1` (or `CI`) disables it.\n\n## What works\n\n- Boot: `opencode attach` reaches the interactive home screen; model picker lists Claude models.\n- Prompt round-trip: streaming text + reasoning render live; cost/context gauge update; Esc-Esc interrupts.\n- Tools: bash/read/edit/write/glob/grep/todowrite/… render with opencode's per-tool views.\n- Permissions: Claude Code's `canUseTool` gate ↔ opencode's `permission.asked` dialog ↔ reply round-trip.\n- **Agents** (Tab to cycle): `build` (default mode), `plan` (plan mode), `auto` (Claude Code's\n  `auto` permission mode — a model classifier handles permission prompts; anything it escalates\n  still surfaces as an opencode permission dialog).\n- **Reasoning effort**: the model variant picker (low/medium/high/xhigh/max) maps to Agent SDK\n  `effort`. First pick applies at query start; later changes apply mid-session via the\n  flag-settings layer (which has no `max` member, so `max` picked after turn 1 clamps to `xhigh`;\n  reverting to \"no variant\" falls back to the session's initial effort, not the global default).\n- **Mid-session switching**: model and build↔plan agent changes on later turns ride\n  `setModel`/`setPermissionMode`; turns are serialized per session; Esc-Esc aborts map to\n  `MessageAbortedError` (no error toast) and in-flight tool parts are errored out. The TUI's\n  model picker is authoritative: the engine tracks the CLI's *actual* model every turn and\n  re-asserts the picker's choice if anything drifts CLI-side, and each assistant message is\n  stamped with the model that actually served it (so the context gauge divides by the right\n  window even across a drifted turn).\n- **Subagents**: Task/Agent runs (and workflow-spawned agents with a spawning tool call) mirror\n  into opencode **child sessions** — the task tool part links via `metadata.sessionId`, so the\n  TUI shows live progress and \"view subagents\" navigates into the child transcript.\n- **Workflows**: `Workflow` tool runs render through the same Task view — spinner + live\n  phase/agent line while running, and a child session containing a progress log\n  (`task_progress` ticks, with `agentProgressSummaries` AI status lines, closed by the\n  completion summary). Requires the account-gated Workflows feature.\n- **Questions**: `AskUserQuestion` maps to opencode's question dialog; selected labels return\n  to the model via `updatedInput.answers`. Option **previews** (mockups, code snippets) fold\n  into the option description as quote-barred lines (line-budgeted so the dialog can't outgrow\n  the terminal, which would clip with no scroll). A trailing **Notes** tab lets you attach a\n  free-text note to your answer — it returns via `updatedInput.annotations`, which the CLI\n  renders into the tool result (` notes: …`), and shows in the transcript as `note: …`.\n  Disable with `OPENCLAUDE_NO_QUESTION_NOTES=1`.\n- **`/config`**: bare `/config` renders your current Claude Code settings (with the file each\n  value comes from) instantly in the transcript — headless, the CLI could only print its usage\n  dump. `/config key=value` still passes through to the CLI and persists.\n- **`/model`**: intercepted as a read-only view (current model, catalog, pointer to `/models`).\n  The CLI's session-scoped switch could never stick here — the picker re-sends its model with\n  every prompt — so forwarding it would only desync the footer from the model actually serving\n  the turns.\n- Session hydration: reopening a session replays its transcript.\n\n## Verified\n\n- `test/sdk-smoke.ts` — Agent SDK runs under Bun with local auth.\n- `test/tool-permission.ts` — HTTP+SSE permission bridge (Write tool → dialog → approve → file written).\n- `test/subagent-session.ts` — Task subagent → child session over SSE, task part linked via\n  `metadata.sessionId`, child transcript fetchable, busy→idle lifecycle.\n- `test/question-bridge.ts` — AskUserQuestion → `question.asked` → reply → answer reaches the model.\n- `test/live-question-notes.ts` — option previews fold into descriptions (quote-barred, budget-clamped,\n  raw `preview` on the wire), Notes tab note returns via `updatedInput.annotations` and lands in the\n  tool_result + transcript metadata, \"No note\"/loose reply shapes/kill-switch all round-trip.\n- `test/pty_question.py` — the real TUI renders folded previews and the Notes tab; a typed note\n  round-trips on-screen (CLI-side contract in `test/probe-question-annotations.ts`).\n- `test/live-model-sync.ts` — `/model` intercept (read-only view, session never busy) and\n  model-drift self-heal: a raw `/model` passthrough flips the CLI, the drifted turn's message\n  is restamped with the serving model, the next turn re-asserts the picker's choice\n  (CLI-side contract in `test/probe-model-switch.ts`).\n- `test/workflow-render.ts` — Workflow run → task part linked to a child session with a live\n  progress log, busy→idle on completion.\n- `test/sdk-subagent-probe.ts` — documents how the SDK forwards subagent content (complete\n  messages with `parent_tool_use_id`; never partial stream events).\n- `test/pty_attach.py` / `test/pty_permission.py` — the **stock opencode TUI** driven in a PTY:\n  boots against the shim, renders a streamed answer (including a Task subagent turn with the\n  \"view subagents\" affordance), renders + approves a permission dialog.\n\n## Known limitations / not yet wired\n\n- **Subagent transcripts arrive per-block**: child sessions update as each subagent message\n  completes (no token-level streaming — the Agent SDK doesn't forward subagent partials).\n- **Workflow inner agents render as a progress log, not transcripts**: their conversations\n  never cross the SDK stream at all (only phase-level `task_progress` does). Full per-agent\n  transcripts exist only on disk (`transcriptDir`) — deliberately not tailed.\n- **Compaction**: emits the boundary only; no summary text.\n- **Single project per instance**: `/global/event` is unfiltered; run one shim per directory.\n- **Pinned to opencode v1.17.19** — the API is mid v1→v2 migration; other versions may drift.\n\n## How it's built\n\nThe complete reverse-engineered wire contract lives in [`docs/contract/`](docs/contract/)\n(bootstrap endpoints, SSE event vocabulary, v1 writes, v2 reads, data model + ID scheme,\nstubs, and the Agent-SDK→opencode event mapping), extracted from the pinned opencode source.\nStart with [`docs/contract/00-overview.md`](docs/contract/00-overview.md).\n\nSource layout:\n\n| File | Role |\n|---|---|\n| `src/ids.ts` | opencode-compatible identifier generation (sortable, direction-aware) |\n| `src/catalog.ts` | static provider/model/agent/config bootstrap JSON |\n| `src/bus.ts` | SSE event bus + exact `data:`-only framing |\n| `src/store.ts` | in-memory sessions/messages/parts; keeps REST state and SSE in sync |\n| `src/engine.ts` | one Claude Agent SDK `query()` per session; maps SDK stream → opencode events |\n| `src/tools.ts` | Claude Code tool name/input → opencode tool rendering contract |\n| `src/config-view.ts` | read-only `/config` bridge: current-settings view from the CLI's three config files |\n| `src/server.ts` | Hono routes (bootstrap, SSE, session CRUD, prompt, permissions, stubs) |\n| `index.ts` | entry point |\n","readmeFilename":"README.md"}