Skip to content

Commit e4012b9

Browse files
fix: add permission mode to Claude Code adapter
Default to bypassPermissions for automated non-interactive workflows. Without this, Claude Code in -p mode cannot edit files and produces no code changes. Add CLAUDE_CODE_PERMISSION_MODE env var with options: default, acceptEdits, bypassPermissions, dontAsk, plan.
1 parent bbeb02c commit e4012b9

4 files changed

Lines changed: 45 additions & 0 deletions

File tree

.env.example

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ AGENT_BACKEND=claude-code
3131
# Claude Code max conversation turns (0 = unlimited)
3232
# CLAUDE_CODE_MAX_TURNS=50
3333

34+
# Claude Code permission mode: default, acceptEdits, bypassPermissions, dontAsk, plan
35+
# bypassPermissions is recommended for automated workflows
36+
# CLAUDE_CODE_PERMISSION_MODE=bypassPermissions
37+
38+
# Claude Code allowed tools (comma-separated, leave empty for all)
39+
# CLAUDE_CODE_ALLOWED_TOOLS=Read,Write,Bash
40+
3441
# Codex-specific
3542
CODEX_MODEL=
3643
CODEX_MODEL_PLAN=

src/core/config.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ function buildEnvBase(cwd: string): ProjectRuntimeConfig {
125125
model: normalizeOptionalValue(env.CLAUDE_CODE_MODEL),
126126
maxTurns: parseOptionalPositiveInt(env.CLAUDE_CODE_MAX_TURNS),
127127
allowedTools: parseCommaList(env.CLAUDE_CODE_ALLOWED_TOOLS),
128+
permissionMode: normalizePermissionMode(env.CLAUDE_CODE_PERMISSION_MODE),
128129
},
129130
dryRun: env.PIV_DRY_RUN === "1",
130131
};
@@ -834,3 +835,30 @@ function normalizeAgentBackend(
834835
`Invalid AGENT_BACKEND value: '${value}'. Must be 'codex' or 'claude-code'.`,
835836
);
836837
}
838+
839+
type ClaudePermissionMode = NonNullable<
840+
NonNullable<ResolvedProjectConfig["agent"]>["permissionMode"]
841+
>;
842+
843+
const VALID_PERMISSION_MODES: readonly ClaudePermissionMode[] = [
844+
"default",
845+
"acceptEdits",
846+
"bypassPermissions",
847+
"dontAsk",
848+
"plan",
849+
];
850+
851+
function normalizePermissionMode(
852+
value: string | undefined,
853+
): ClaudePermissionMode | undefined {
854+
if (!value) {
855+
return undefined;
856+
}
857+
const normalized = value.trim();
858+
if ((VALID_PERMISSION_MODES as readonly string[]).includes(normalized)) {
859+
return normalized as ClaudePermissionMode;
860+
}
861+
throw new Error(
862+
`Invalid CLAUDE_CODE_PERMISSION_MODE value: '${value}'. Must be one of: ${VALID_PERMISSION_MODES.join(", ")}.`,
863+
);
864+
}

src/core/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ export interface ProjectRuntimeConfig {
8787
model?: string;
8888
maxTurns?: number;
8989
allowedTools?: string[];
90+
permissionMode?:
91+
| "default"
92+
| "acceptEdits"
93+
| "bypassPermissions"
94+
| "dontAsk"
95+
| "plan";
9096
};
9197
skills: {
9298
root: string;

src/services/claude-code-adapter.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,13 @@ export class ClaudeCodeAdapter implements AgentAdapter {
4242
}
4343

4444
private buildCommonArgs(): string[] {
45+
const permissionMode =
46+
this.config.agent?.permissionMode ?? "bypassPermissions";
4547
return [
4648
"--output-format",
4749
"json",
50+
"--permission-mode",
51+
permissionMode,
4852
...this.buildModelArgs(),
4953
...this.buildMaxTurnsArgs(),
5054
...this.buildAllowedToolsArgs(),

0 commit comments

Comments
 (0)