Skip to content

feat: add a claude-code provider backed by the local Claude Code CLI - #559

Open
Luis Lucio (llucio) wants to merge 1 commit into
langchain-ai:mainfrom
llucio:feat/claude-code-provider
Open

feat: add a claude-code provider backed by the local Claude Code CLI#559
Luis Lucio (llucio) wants to merge 1 commit into
langchain-ai:mainfrom
llucio:feat/claude-code-provider

Conversation

@llucio

Copy link
Copy Markdown

Summary

Adds a claude-code inference provider that routes model calls through the local Claude Code CLI instead of an Anthropic API key.

The motivating case: Claude Team and Enterprise members whose plan does not permit creating API keys currently cannot run OpenWiki at all. This gives them a keyless path, in the same spirit as the existing openai-chatgpt provider (reuses a ChatGPT login) and copilot provider (reuses a Copilot seat via gh).

OPENWIKI_PROVIDER="claude-code"
OPENWIKI_MODEL_ID="claude-opus-5"

Authentication reuses an existing claude auth login session. OpenWiki never reads, copies, or persists a token — it spawns the CLI through @anthropic-ai/claude-agent-sdk and lets the SDK use whatever session is already there. Nothing is written to ~/.openwiki/.env.

How the bridge works

Claude Code ships its own agent loop, so the provider constrains it to a single model turn and keeps tool execution with DeepAgents (preserving the virtual filesystem backend, OKF middleware, and translation middleware):

  • OpenWiki's tools are exposed through an in-process MCP server, with alwaysLoad set so they are not deferred behind ToolSearch — which would otherwise consume the turn without producing a tool call.
  • canUseTool captures the tool call and denies it with interrupt, handing it back to the OpenWiki agent loop. Nothing is added to allowedTools: a bare entry there auto-approves the call and shadows the callback, which is the only interception point available.
  • Built-in tools are refused through the same callback without interrupting, so the model retries with an OpenWiki tool inside the same turn. disallowedTools is a deny-list that cannot stay complete as the CLI gains tools, so it is defense in depth only.
  • Anthropic credentials are stripped from the spawned environment. OpenWiki loads ~/.openwiki/.env into process.env, so a previously configured ANTHROPIC_API_KEY would otherwise shadow the CLI session and bill the API — failing outright when that dead key is precisely why the user picked this provider.

Schema fidelity

Tool schemas are converted with LangChain's own toJsonSchema, which handles Zod v3 and v4 alike. Zod 4's z.toJSONSchema throws on a v3 schema; converting via a try/catch fallback silently degraded such a tool to a parameterless one, so the model could call it but never correctly. Objects declaring additionalProperties: true are kept open (z.looseObject) so openwiki_call_mcp_tool can still forward arbitrary connector arguments.

Known tradeoff

The Agent SDK accepts only user messages — there is no way to inject prior assistant turns — so a resumable session cannot be reconstructed from LangChain's message list. Each generation replays the transcript instead. That keeps the model stateless, which is what _generate promises and what makes the checkpointer, summarization middleware, and --update resume behave correctly.

The cost is speed: a wiki build is slower than the anthropic provider and draws on the subscription's rate limits. Rendering is deterministic so the prefix stays byte-stable and Claude Code's prompt cache absorbs most of the repeated cost. The README recommends anthropic with an API key for CI. If the SDK later accepts full message histories, this is the natural place to optimize.

maxTurns is set to 6 rather than 1 purely as headroom for a refused built-in before the model retries; capture still interrupts immediately, so a healthy step never reaches it.

Testing

  • test/claude-code-model.test.ts — 13 tests covering JSON-Schema→Zod conversion (required/optional, enums, arrays, nested objects, open vs closed objects), Zod v3 and v4 normalization, bindTools non-mutation, credential stripping, the built-in-refusal regression, and turn-ending classification.
  • test/claude-code-provider.test.ts — provider registry wiring, keyless auth, model-id form.
  • One existing expectation in test/constants.test.ts updated: getProvidersForKnownModelId now legitimately includes claude-code for Claude model ids.

Verified end-to-end by generating a full wiki for a real repository (a ~1.4k-file React SPA) with code --update --print: the run completed, produced a valid OKF bundle (okf_version on the root index, type/title/description front matter on concept pages, bare nested indexes), and performed correct incremental reasoning — reading git history and judging which commits left existing pages accurate.

pnpm typecheck, pnpm lint:check, and pnpm build are clean.

Adds a keyless inference provider for users who cannot provision an
Anthropic API key -- notably Claude Team and Enterprise members whose
plan does not grant API key creation. It reuses an existing
`claude auth login` session, in the same spirit as the `openai-chatgpt`
and `copilot` providers, which reuse a ChatGPT and Copilot subscription.

Claude Code ships its own agent loop, so the bridge constrains it to a
single model turn and keeps execution with DeepAgents:

- OpenWiki's tools are exposed through an in-process MCP server, with
  `alwaysLoad` set so they are not deferred behind ToolSearch (which
  would consume the turn without producing a tool call).
- `canUseTool` captures the resulting tool call and denies it with
  `interrupt`, handing it back to the OpenWiki agent loop. Nothing is
  added to `allowedTools`: a bare entry there auto-approves the call and
  shadows the callback, which is the only interception point.
- Claude Code's built-in tools are refused through the same callback
  *without* interrupting, so the model retries with an OpenWiki tool
  inside the same turn. `disallowedTools` is a deny-list that cannot
  stay complete as the CLI gains tools, so it is defense in depth only.
- Anthropic credentials are stripped from the spawned process
  environment. OpenWiki loads `~/.openwiki/.env` into `process.env`, so
  a previously configured `ANTHROPIC_API_KEY` would otherwise shadow the
  CLI session and bill the API -- failing outright when that dead key is
  the reason the user chose this provider.

Tool schemas are converted with LangChain's own `toJsonSchema`, which
handles Zod v3 and v4 alike; Zod 4's `toJSONSchema` throws on a v3
schema, which would silently degrade a tool to a parameterless one.
Objects declaring `additionalProperties: true` stay open, so
`openwiki_call_mcp_tool` can still forward arbitrary connector arguments.

The Agent SDK accepts only user messages, so prior assistant turns
cannot be injected and a session cannot be reconstructed from LangChain's
message list. Each generation replays the transcript instead, which keeps
the model stateless -- what `_generate` promises, and what makes the
checkpointer, summarization middleware, and `--update` resume behave.
Rendering is deterministic so the prefix stays byte-stable and Claude
Code's prompt cache absorbs most of the repeated cost.
@changeset-bot

changeset-bot Bot commented Jul 31, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7d6be73

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
openwiki Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@colifran

Copy link
Copy Markdown
Collaborator

Thanks for the PR Luis Lucio (@llucio)! My biggest concern is just related to ToS. I worked on #278 and we ran it by our anthropic contact internally and were told is was against their ToS. I will double check on this one too to see what they say.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants