Problem
The make config wizard prompts the operator for several Claude-binary-specific knobs unconditionally, even when the operator has selected goose as the agent backend. Goose has no equivalent of these settings, so the prompts at best confuse the operator and at worst cause them to set values that are silently ignored at runtime.
Verified via audit of src/kai/install.py and src/kai/pool.py:
| Env var |
Wizard line |
Currently gated? |
Backend(s) that consume it |
CLAUDE_AUTOCOMPACT_PCT |
install.py:546-557 |
No |
Claude only (ClaudeCodeBackend autocompact env override) |
CLAUDE_EFFORT_LEVEL |
install.py:559-573 |
No |
Claude only (ClaudeCodeBackend --effort flag) |
CLAUDE_USER |
install.py:388-394 |
Only by if advanced: |
Claude only (sudo isolation; Goose has no sudo path) |
The other CLAUDE_* env vars in the wizard (CLAUDE_TIMEOUT_SECONDS, CLAUDE_MAX_CONTEXT_WINDOW, CLAUDE_MAX_BUDGET_USD -> BUDGET_CEILING, DEFAULT_MODEL <- CLAUDE_MODEL) are correctly not gated on backend — both GooseBackend and ClaudeCodeBackend accept the corresponding kwargs in pool.py.
Proposed solution
Add a backend-conditional gate to each of the three prompts identified above. The pattern that works:
- Initialize the variable to its dataclass default before the conditional, so the env-emission
if value != default block downstream still works without raising NameError when goose is selected.
- Wrap the
_prompt(...) / _prompt_choice(...) call in if agent_backend == "claude":.
- The matching env-emission block in the lower half of
_cmd_config() already short-circuits on the default-value check (if claude_effort_level != "high"), so no separate emission gate is needed - but verify each one to be sure.
For CLAUDE_USER: keep the existing if advanced: gate AND add agent_backend == "claude" as an additional condition. The os_user field has no meaning for Goose.
Tests
Every fixture in tests/test_install.py currently passes "claude" as the agent backend. This audit needs at least one "goose" fixture per gated prompt that asserts the prompt is skipped (otherwise the gating regresses silently the next time someone touches the wizard). The simplest path is to extend _base_inputs with an agent_backend parameter (default "claude") and add a single new TestCmdConfig::test_goose_backend_skips_claude_only_prompts test that:
- Calls
_base_inputs(memory_block=["false"], agent_backend="goose") (omitting the autocompact, effort, and CLAUDE_USER inputs)
- Runs
_cmd_config()
- Asserts the resulting
install.conf env contains none of the three keys
Out of scope
CLAUDE_MAX_SESSION_HOURS and CLAUDE_IDLE_TIMEOUT: also Claude-only at the consumer (ClaudeCodeBackend-only kwargs in pool.py), but neither has a wizard prompt today (operators hand-edit env). Adding wizard prompts AND gating them is a separate piece of work; out of scope here.
- Re-validation that already-set CLAUDE_* values are removed from
install.conf when an operator switches an existing config from claude to goose. Today the wizard preserves prior values across backend changes; whether that should change is a separate question.
Acceptance criteria
Problem
The
make configwizard prompts the operator for several Claude-binary-specific knobs unconditionally, even when the operator has selectedgooseas the agent backend. Goose has no equivalent of these settings, so the prompts at best confuse the operator and at worst cause them to set values that are silently ignored at runtime.Verified via audit of
src/kai/install.pyandsrc/kai/pool.py:CLAUDE_AUTOCOMPACT_PCTinstall.py:546-557ClaudeCodeBackendautocompact env override)CLAUDE_EFFORT_LEVELinstall.py:559-573ClaudeCodeBackend--effortflag)CLAUDE_USERinstall.py:388-394if advanced:The other
CLAUDE_*env vars in the wizard (CLAUDE_TIMEOUT_SECONDS,CLAUDE_MAX_CONTEXT_WINDOW,CLAUDE_MAX_BUDGET_USD->BUDGET_CEILING,DEFAULT_MODEL<-CLAUDE_MODEL) are correctly not gated on backend — bothGooseBackendandClaudeCodeBackendaccept the corresponding kwargs inpool.py.Proposed solution
Add a backend-conditional gate to each of the three prompts identified above. The pattern that works:
if value != defaultblock downstream still works without raisingNameErrorwhen goose is selected._prompt(...)/_prompt_choice(...)call inif agent_backend == "claude":._cmd_config()already short-circuits on the default-value check (if claude_effort_level != "high"), so no separate emission gate is needed - but verify each one to be sure.For
CLAUDE_USER: keep the existingif advanced:gate AND addagent_backend == "claude"as an additional condition. Theos_userfield has no meaning for Goose.Tests
Every fixture in
tests/test_install.pycurrently passes"claude"as the agent backend. This audit needs at least one"goose"fixture per gated prompt that asserts the prompt is skipped (otherwise the gating regresses silently the next time someone touches the wizard). The simplest path is to extend_base_inputswith anagent_backendparameter (default"claude") and add a single newTestCmdConfig::test_goose_backend_skips_claude_only_promptstest that:_base_inputs(memory_block=["false"], agent_backend="goose")(omitting the autocompact, effort, and CLAUDE_USER inputs)_cmd_config()install.confenv contains none of the three keysOut of scope
CLAUDE_MAX_SESSION_HOURSandCLAUDE_IDLE_TIMEOUT: also Claude-only at the consumer (ClaudeCodeBackend-only kwargs inpool.py), but neither has a wizard prompt today (operators hand-edit env). Adding wizard prompts AND gating them is a separate piece of work; out of scope here.install.confwhen an operator switches an existing config fromclaudetogoose. Today the wizard preserves prior values across backend changes; whether that should change is a separate question.Acceptance criteria
CLAUDE_AUTOCOMPACT_PCTwhenagent_backend == "goose"CLAUDE_EFFORT_LEVELwhenagent_backend == "goose"CLAUDE_USERwhenagent_backend == "goose"(regardless ofadvancedsetting)goose, the resultinginstall.confcontains none of the three keys aboveclaude, all three prompts continue to fire as today (no behavior regression)tests/test_install.pyfixtures (all currently use"claude") continue to pass without changes to their input lists"goose"path and asserts the prompts are skipped