ADR 0037 built createCliClient in all eight ports: a closed CliStyles enum (Claude, Codex,
Copilot, Opencode, Devin, Gemini, Goose), one shared JSON file per vendor (argv, prompt mode,
ACP args, a devin system hint), a one-shot CLI transport with a prompt preamble and a six-step
reply parser, a permission allow-list keyed on how each vendor titles a tool call, a stdio↔HTTP
bridge, and — in the follow-up drafts — isolation flags per vendor and model lists.
It worked, live, against six agents. It is also the wrong thing for this library to own:
toolnexus ships three vendor-neutral pieces (SPEC §8C) and documents the rest as recipes.
Kept, all eight ports:
createInProcessClient with the streaming generate (generateStream(req, emit)), so any
model source — an ACP agent, a local runtime, a test double — streams for real.loadACP): spawn, initialize, session/new with caller-supplied
mcpServers / _meta / args / env passed through untouched, optional model passthrough,
session/prompt, streaming of agent_message_chunk (and thoughts / agent tool events,
via:"acp"), the permission hook, prompt failure when the agent exits, -32601 for requests
it does not implement, process-group teardown.toolkit.asMcpServer() → {url, token, close}: the §7C server on loopback with a per-call
bearer token — the smallest thing that lets an agent call the toolkit. The caller writes the
mcpServers entry in whatever shape its agent accepts.Dropped: the CliStyles enum and createCliClient, conformance/cli-styles/*.json, the
one-shot CLI transport, preamble and reply parsing, the load_skill rename, the vendor-title
permission allow-list, the devin system hint, isolation flags, toolnexus mcp-bridge, model lists.
Recipes — "drive Claude Code / Codex / Copilot / opencode / … through toolnexus" — live in the docs site and are written against the three pieces above. They may name vendors; the library may not.
conformance/ without a
vendor binary (conformance/acp-client/cases.json, all fakes).7cb7460 on #138, 9ec1830 on #145) loses
createCliClient/CliStyles; the migration is: loadACP({command, args, mcpServers:[entry from asMcpServer]}) + createInProcessClient({generateStream: acp.generateStream}).generate that runs their CLI — the seam exists for exactly that.Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |