---
title: Claude Code
description: Learn how to use the Claude Code harness adapter.
url: "https://ai-sdk.dev/providers/ai-sdk-harnesses/claude-code"
docs_index: /llms.txt
---

> For an index of all documentation, see [/llms.txt](/llms.txt).

The Claude Code harness adapter connects `HarnessAgent` to Claude Code through
`@anthropic-ai/claude-agent-sdk`. The adapter runs a bridge inside the sandbox
and streams Claude Code events back to the host over a sandbox-exposed
WebSocket.

Harness packages are **experimental**. Expect breaking changes between
releases as this early API gets further refined.

## Setup

```bash
pnpm add @ai-sdk/harness @ai-sdk/harness-claude-code @ai-sdk/sandbox-vercel
```

The adapter bootstraps the Claude Code bridge dependencies inside the sandbox
when the first session starts.

## Import

```ts
import { claudeCode, createClaudeCode } from '@ai-sdk/harness-claude-code';
```

`claudeCode` is equivalent to `createClaudeCode()` with its default configuration.

## Basic Usage

```ts
import { HarnessAgent } from '@ai-sdk/harness/agent';
import { claudeCode } from '@ai-sdk/harness-claude-code';
import { createVercelNetworkSandboxSession } from '@ai-sdk/sandbox-vercel';

const agent = new HarnessAgent({
  harness: claudeCode,
  model: 'claude-sonnet-4-6',
});

const sandboxSession = await createVercelNetworkSandboxSession({
  runtime: 'node24',
  ports: [4000],
  template: await agent.getSandboxTemplate(),
});
const session = await agent.createSession({ sandboxSession });

let exitCode = 0;
try {
  const result = await agent.stream({
    session,
    prompt: 'Check the test failures and fix the production code.',
  });

  for await (const part of result.stream) {
    if (part.type === 'text-delta') {
      process.stdout.write(part.text);
    }
  }
} catch (err) {
  exitCode = 1;
  console.error(err);
} finally {
  await session.destroy();
  await sandboxSession.destroy();
  process.exit(exitCode);
}
```

To use this agent, ensure environment variables include `VERCEL_OIDC_TOKEN` for
Vercel Sandbox, and one of the variables listed under [authentication](#authentication)
for Claude Code.

## Adapter Settings

Use `createClaudeCode()` to configure the runtime:

```ts
const harness = createClaudeCode({
  maxTurns: 10,
  env: {
    DEPLOYMENT_ENV: 'staging',
  },
  thinking: {
    type: 'adaptive',
    display: 'summarized',
  },
});
```

Settings:

- `auth`: authentication mode (`auto`, `direct`, or `ai-gateway`) or an
  isolated authentication environment.
- `credentialForwarding`: optional synchronous or asynchronous callback that
  customizes each credential immediately before the harness adapter forwards it
  into a sandbox process. It receives the credential value that would otherwise
  be forwarded (either the real credential or a masked value) and the
  environment variable name used to expose it. This callback only controls the
  value forwarded into the sandbox process. It does not restrict which
  credentials the harness adapter can discover, read, or otherwise access in
  the host process.
- `mcpServers`: MCP server definitions keyed by server name.
- `strictMcpConfig`: only use the servers from `mcpServers` and ignore other
  MCP configuration, such as a project `.mcp.json` or user settings.
- `toolHints`: Claude Code hints for host tools, keyed by tool name.
  `readOnly: true` marks a tool without side effects, so Claude Code can run
  its calls in parallel and allows it in plan mode; calls to other host tools
  run one at a time. `alwaysLoad: true` sends the tool's definition from the
  first request when Claude Code's tool search is on, instead of deferring it
  until the model looks it up.
- `maxTurns`: maximum internal turns before yielding.
- `skillOverrides`: per-skill visibility overrides. Values can be `on`,
  `name-only`, `user-invocable-only`, or `off`.
- `maxBudgetUsd`: maximum estimated spend in USD for each Claude query. When it
  is exceeded, the query stops and the turn ends with an error.
- `questionTimeoutMs`: maximum time in milliseconds Claude waits for an answer
  to an `AskUserQuestion` question before the question fails. Defaults to the
  Claude Code default.
- `excludeDynamicSections`: moves per-session sections (working directory,
  memory, git status) out of the Claude Code system prompt into the first user
  message, so the system prompt can be cached across sessions.
- `agentProgressSummaries`: enables periodic AI-generated summaries for running
  sub-agents. Summaries are available on raw `task_progress` stream parts.
- `forwardSubagentText`: forwards sub-agent text and thinking messages as raw
  stream parts, in addition to the tool activity forwarded by default.
- `env`: environment variables for the Claude Code process. Values are merged
  over the sandbox bridge process environment and take precedence.
- `thinking`: extended-thinking configuration. `type` can be `enabled`,
  `disabled`, or `adaptive`. For enabled or adaptive thinking, `display` can be
  `summarized` or `omitted`. Defaults to
  `{ type: 'adaptive', display: 'summarized' }`.
- `port`: bridge port override.
- `startupTimeoutMs`: maximum time to wait for the bridge to start.
- `turnStartTimeoutMs`: maximum time from submitting a turn's start to its first
  bridge event, defaulting to 120 seconds. If no event arrives, the turn fails
  and the connection closes. This is not a timeout on the complete turn.
- `hostDisconnectTimeoutMs`: aborts a running turn when the host disconnects
  and no host reconnects within this many milliseconds. A suspended turn is
  not aborted. When unset, a turn keeps running in the sandbox after its host
  disconnects, including when the host process is gone for good, until the
  turn finishes or the sandbox stops.
- `reconnect`: reconnect timing after an established bridge WebSocket
  connection drops. `maxElapsedMs` controls the total retry window, including
  connection establishment and backoff delays, and defaults to 30 seconds.
  `initialDelayMs` defaults to 50 milliseconds, and `maxDelayMs` defaults to
  2 seconds. These retries use exponential backoff and are separate from
  `startupTimeoutMs`. They cannot recover when the sandbox, bridge process, or
  bridge endpoint is permanently unavailable.
  Pending turn starts are retried with the same identifier when the bridge
  supports idempotent starts, so a dropped frame does not leave the turn
  waiting forever or launch the agent twice. An older bridge that is still
  waiting for a lost start causes the turn to fail instead of retrying unsafely.
  A turn submitted while disconnected queues its start for first delivery on
  reconnection; this first delivery also works with older bridges.
- `onDebug`: callback for bridge connection lifecycle events:
  `reconnect-attempt`, `reconnected`, and `reconnect-failed`. `reconnect-failed`
  means the connection is closed for good, so a host that caches idle sessions
  can detach and reattach before sending the next prompt. The `cause` of a
  failed reconnect can contain connection details, so avoid logging it as is.
- `mintBridgeToken`: synchronous function that receives the sandbox id and
  returns the bridge authentication token. By default, the adapter generates a
  random 32-byte token. Custom implementations must return a suitably secret
  token.

### Skill Overrides

Use `skillOverrides` to control how named skills are exposed to Claude Code
without changing shared user-level configuration. Values can be `'on'`,
`'name-only'`, `'user-invocable-only'`, or `'off'`:

```ts
const harness = createClaudeCode({
  skillOverrides: {
    'update-config': 'off',
    'fewer-permission-prompts': 'off',
    'keybindings-help': 'off',
    init: 'off',
  },
});
```

Skills without an override keep their Claude Code defaults, so other bundled
skills such as `code-review`, `simplify`, and `claude-api` remain available
when provided by the installed Claude Code runtime.

## Structured Output

Claude Code supports schema-backed [`HarnessAgent` structured output](/docs/ai-sdk-harnesses/harness-agent#generate-structured-output).
The adapter passes the JSON Schema through the Agent SDK's native
`outputFormat` option and returns its `structured_output` value as JSON text.

## Authentication

The `auth` setting selects how credentials are resolved from the host
environment:

- `auto` (default): use AI Gateway credentials when available, then fall back
  to direct Anthropic credentials.
- `direct`: use Anthropic credentials.
- `ai-gateway`: use AI Gateway credentials.

When the sandbox supports additive request transformations, the bridge receives
placeholders and the adapter injects credentials into matching outbound
requests. Sandboxes without that capability retain direct credential
forwarding.

Supported environment variables:

- `VERCEL_OIDC_TOKEN`
- `AI_GATEWAY_API_KEY`
- `AI_GATEWAY_BASE_URL`
- `ANTHROPIC_API_KEY`
- `ANTHROPIC_AUTH_TOKEN`
- `ANTHROPIC_BASE_URL`

If no applicable credential environment variable is set, the adapter attempts
to resolve a native subscription from the host system unless AI Gateway
authentication is selected.

Select a specific authentication mode when you do not want automatic detection:

```ts
const directHarness = createClaudeCode({ auth: 'direct' });
const gatewayHarness = createClaudeCode({ auth: 'ai-gateway' });
```

Pass an authentication environment to use programmatically resolved
credentials without reading `process.env`:

```ts
const harness = createClaudeCode({
  auth: { ANTHROPIC_API_KEY: await resolveAnthropicToken() },
});
```

The supplied record replaces the host environment for authentication
discovery. Only recognized authentication variables are forwarded.

## Sandbox

Claude Code requires a network sandbox with at least one exposed port,
e.g. `@ai-sdk/sandbox-vercel`:

```ts
const sandboxSession = await createVercelNetworkSandboxSession({
  runtime: 'node24',
  ports: [4000],
  template: await agent.getSandboxTemplate(),
});
```

## Built-in Tools

The adapter exposes these common Claude Code built-ins through `agent.tools`:

- `read`
- `write`
- `edit`
- `bash`
- `glob`
- `grep`
- `webSearch`

Additional Claude Code built-ins may also appear in `agent.tools` when they do
not fit a common tool shape.

Claude Code supports built-in tool approval requests when `permissionMode` is
`allow-reads` or `allow-edits`. A call waiting for approval is kept in the
Claude Code session, so an approval answered after a resume runs that same
call, even in a new sandbox. Claude Code waits for one approval at a time, so
parallel calls that need approval run one after another.

In these modes, file reads are automatically approved only within the session
workdir or an active skill's directory. `allow-edits` automatically approves
file changes only within the workdir. Paths outside those directories, including
symlink targets, and paths that cannot be resolved require host approval.
`allow-all` remains unrestricted. These approval rules are not a filesystem
sandbox, and approved shell commands can access paths outside the workdir.

## Known Limitations

Claude Code does not allow toggling whether to discover project-level skills
and `AGENTS.md` files individually from project-level configuration and hooks.
Since the adapter disables reading project-level configuration and hooks for
security reasons, it means Claude Code will not discover project-level skills
and `AGENTS.md` instructions natively.

## Related

- [HarnessAgent](/docs/ai-sdk-harnesses/harness-agent)
- [Harness tools](/docs/ai-sdk-harnesses/tools)
- [Harness adapters](/docs/ai-sdk-harnesses/harness-adapters)

---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)