feat: inject effort as soft default via CLI flags instead of env var (#104)

CLAUDE_CODE_EFFORT_LEVEL hard-locks effort for the whole session and makes
Claude reject in-session /effort switching (incl. ultracode). Carry effort
as a dedicated payload field instead, injected at spawn as a soft default:

- regular levels (incl. max) -> claude --effort <level>
  (the settings effortLevel key is enum([low,medium,high,xhigh]) with
  .catch(undefined), so max would be silently dropped there)
- ultracode -> claude --settings '{"ultracode":true}'
  (dedicated boolean settings key, rejected by the --effort flag)

Changes:
- add effort enum field to create/quick-start/ralph-loop schemas and thread
  it through Session -> CreateSessionOptions/RespawnPaneOptions -> spawn
- buildEffortCliArgs() in session-cli-builder, shared by tmux spawn command
  and direct-PTY fallback args
- frontend: buildEnvOverrides() no longer emits CLAUDE_CODE_EFFORT_LEVEL;
  validated effort goes into payloads via getEffortSetting()
- settings UI: add Ultracode option to the Thinking Effort dropdown
- legacy migration: Session constructor extracts CLAUDE_CODE_EFFORT_LEVEL
  from persisted envOverrides; applyEnvOverrides() unsets the stale tmux
  session var so respawned panes are no longer locked
- tests: test/effort-injection.test.ts (13 cases)

Co-authored-by: Teigen <teigenzhang@gmail.com>
This commit is contained in:
Tenggan Zhang
2026-06-07 04:33:11 +02:00
committed by GitHub
co-authored by Teigen
parent e3c496e1a4
commit b2f8b03b3c
15 changed files with 294 additions and 23 deletions
+11 -2
View File
@@ -268,8 +268,16 @@ export function registerRalphRoutes(
);
}
const { caseName, taskDescription, completionPhrase, maxIterations, enableRespawn, planItems, envOverrides } =
parseBody(RalphLoopStartSchema, req.body);
const {
caseName,
taskDescription,
completionPhrase,
maxIterations,
enableRespawn,
planItems,
envOverrides,
effort,
} = parseBody(RalphLoopStartSchema, req.body);
const casePath = join(CASES_DIR, caseName);
@@ -315,6 +323,7 @@ export function registerRalphRoutes(
claudeMode: rlClaudeModeConfig.claudeMode,
allowedTools: rlClaudeModeConfig.allowedTools,
envOverrides,
effort,
});
// Configure Ralph tracker
+3
View File
@@ -335,6 +335,7 @@ export function registerSessionRoutes(
openCodeConfig: mode === 'opencode' ? body.openCodeConfig : undefined,
resumeSessionId: validatedResumeId,
envOverrides: body.envOverrides,
effort: body.effort,
});
ctx.addSession(session);
@@ -1106,6 +1107,7 @@ export function registerSessionRoutes(
mode = 'claude',
openCodeConfig,
envOverrides,
effort,
} = parseBody(QuickStartSchema, req.body);
// Check OpenCode availability if requested
@@ -1186,6 +1188,7 @@ export function registerSessionRoutes(
allowedTools: qsClaudeModeConfig.allowedTools,
openCodeConfig: mode === 'opencode' ? openCodeConfig : undefined,
envOverrides,
effort,
});
// Auto-detect completion phrase from CLAUDE.md BEFORE broadcasting