anthropics / anthropics/claude-code-action

max_turns is never passed to SDK in run.ts, defaults to 10

Open
#1,177 2 comments 0 reactions 0 assignees View on GitHub
bug p2
Dominant language
TypeScript
Stars
8.9k
Forks
2.1k
Avg merge
3d 9h
Merged PRs (30d)
10

Description

## Bug Description

`maxTurns` is never wired through to the SDK in `src/entrypoints/run.ts`, causing all runs to hit the SDK's default limit of 10 turns regardless of configuration.

## Root Cause

`src/entrypoints/run.ts` line 268 calls `runClaude()` without passing `maxTurns`:

```ts
const claudeResult: ClaudeRunResult = await runClaude(promptConfig.path, {
claudeArgs: prepareResult.claudeArgs,
appendSystemPrompt: process.env.APPEND_SYSTEM_PROMPT,
model: process.env.ANTHROPIC_MODEL,
pathToClaudeCodeExecutable: process.env.INPUT_PATH_TO_CLAUDE_CODE_EXECUTABLE,
showFullOutput: process.env.INPUT_SHOW_FULL_OUTPUT,
// maxTurns is MISSING
});
```

The `ClaudeOptions` type in `base-action/src/run-claude.ts` supports `maxTurns`, and `parse-sdk-options.ts` correctly parses it:

```ts
maxTurns: options.maxTurns ? parseInt(options.maxTurns, 10) : undefined,
```

But since `run.ts` never provides it, `sdkOptions.maxTurns` is always `undefined`, and the SDK defaults to 10.

Notably, the `base-action/src/index.ts` entrypoint **does** pass it correctly:
```ts
maxTurns: process.env.INPUT_MAX_TURNS,
```

But the main action uses `src/entrypoints/run.ts`, not the base-action entrypoint.

## Why `--max-turns` in `claude_args` doesn't work either

Passing `--max-turns 50` via `claude_args` puts the value into `extraArgs["max-turns"]`, which is passed through to the CLI subprocess. However, the SDK enforces its own turn counter from `sdkOptions.maxTurns` (which is `undefined` → 10), so the CLI never gets a chance to process more than 10 turns.

## Error

```
Claude Code returned an error result: Reached maximum number of turns (10)
at readMessages (/home/runner/work/_actions/anthropics/claude-code-action/v1/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs:58:14849)
```

## Suggested Fix

Add `maxTurns` to the `runClaude()` call in `src/entrypoints/run.ts`, and add a `max_turns` input to `action.yml`:

**action.yml:**
```yaml
max_turns:
description: "Maximum number of conversation turns for the SDK"
required: false
```

**src/entrypoints/run.ts:**
```ts
const claudeResult: ClaudeRunResult = await runClaude(promptConfig.path, {
claudeArgs: prepareResult.claudeArgs,
appendSystemPrompt: process.env.APPEND_SYSTEM_PROMPT,
model: process.env.ANTHROPIC_MODEL,
maxTurns: process.env.INPUT_MAX_TURNS, // <-- add this
pathToClaudeCodeExecutable: process.env.INPUT_PATH_TO_CLAUDE_CODE_EXECUTABLE,
showFullOutput: process.env.INPUT_SHOW_FULL_OUTPUT,
});
```

And wire `INPUT_MAX_TURNS` in the run step env:
```yaml
INPUT_MAX_TURNS: ${{ inputs.max_turns }}
```

Same issue likely applies to `systemPrompt`, `allowedTools`, `disallowedTools`, `mcpConfig`, and `fallbackModel` — all supported by `ClaudeOptions` but not passed from `run.ts`.

## Reproduction

1. Create a workflow using `anthropics/claude-code-action@v1`
2. Set `claude_args: "--max-turns 50"` or `max_turns: 50`
3. Trigger the action with a task requiring more than 10 turns
4. Observe: `Reached maximum number of turns (10)`

## Environment

- Action version: `anthropics/claude-code-action@v1`
- Claude Code version installed by action: `2.1.92`

Contributor guide

Open the contributing guide

Research direction

Read src/entrypoints/run.ts and action.yml, then compare the existing wiring in base-action/src/index.ts with the ClaudeOptions and parse-sdk-options.ts references mentioned in the issue. Done means the max_turns input is exposed and reaches runClaude through the run entrypoint, so configured runs are no longer capped by the SDK default of 10.

Written by the indexing model from the issue text.

Assessment

Tech stack
github-actions, typescript
Domain
ci-cd
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.