@nhtio/adk/batteries/llm/claude_code_cli/adapter
Cross-environment executor adapter that wraps the Claude Code CLI as a DispatchExecutorFn destination.
Remarks
The first battery in the "CLI harness" family: rather than a direct wire-format provider, this adapter drives an external coding-agent CLI binary that is itself a complete agent loop. Since a subprocess must be spawned anyway, ALL Claude-Code-specific complexity — spawning the real claude binary, hosting an MCP bridge server, translating its stream-json — lives in a dedicated wrapper process (wrapper.ts, shipped as a sibling dist asset); this adapter only ever spawns and drives that wrapper over the small, harness-agnostic protocol in ./wire.
Every dispatch iteration is stateless and self-contained: the full accumulated history renders into one -p prompt string (buildClaudeCodeCliPrompt), a fresh wrapper is spawned, and real ADK tools are bridged into the CLI's own tool loop via MCP — but actual execution always happens on the ADK side, through tool.executor(ctx)(args), exactly like every other LLM battery.
Classes
| Class | Description |
|---|---|
| ClaudeCodeCliAdapter | Opinionated CLI-harness LLM adapter that drives the Claude Code CLI as a DispatchExecutorFn destination. |
Functions
| Function | Description |
|---|---|
| __resolveWrapperPathViaSelfReference | Resolve the wrapper asset's sibling path relative to THIS PACKAGE's own already-published main entry, rather than relative to the (possibly relocated-by-bundling) adapter module. Node's package self-reference feature — a package resolving its own name as a bare specifier — is depth-independent within @nhtio/adk's own tree, so this survives the adapter code being moved around WITHIN the package by a bundler. It only breaks once the calling code has been physically bundled OUTSIDE @nhtio/adk's own directory tree (e.g. into a consumer's Electron main-process bundle) — at that point self-reference falls back to ordinary node_modules bare-specifier resolution, which succeeds exactly when @nhtio/adk is still installed as a resolvable dependency from the bundled code's new location. That is the same "normal case" the published wrapperPath override already exists for, so this fallback is a strict improvement with no new failure mode: when it can't resolve, behavior degrades to the pre-existing "throw a clear error" path below rather than a worse outcome. |
| __resolveWrapperPathWithFallback | Internal, non-public resolver used by the executor call site (never resolveDefaultWrapperPath itself, which stays synchronous and unchanged for backwards compatibility with any caller that already imports it directly). Tries the existing relative-to-module resolution FIRST — zero behavior change for the common unbundled case — and only falls back to the self-reference lookup when that candidate does not exist on disk (bundling relocated the adapter). Throws E_CLAUDE_CODE_CLI_WRAPPER_NOT_FOUND naming every path tried — the relative candidate (or its resolution error) AND every self-reference candidate/reason from resolveWrapperPathViaSelfReference — when neither resolves, rather than letting a bundled consumer hit an opaque MODULE_NOT_FOUND/ENOENT deep inside execa, or a truncated error that hides what the self-reference fallback actually attempted. |
| resolveDefaultWrapperPath | Resolve the built wrapper asset's on-disk path relative to this module's own compiled location. adapter.ts carries its own @module tag (per the per-file tagging convention every other multi-file battery uses), so it compiles to dist/batteries/llm/claude_code_cli/adapter.mjs — three directories below the package root, where the wrapper (an explicit, un-tagged vite.config.mts entry key) compiles to dist/claude-code-cli-wrapper.mjs. |