← Back to PRs

#13849: fix(configure): preserve custom config keys across wizard sections

by mcaxtr open 2026-02-11 03:21 View on GitHub →
commands size: M trusted-contributor experienced-contributor
## Summary Fixes #9632 The configure wizard was overwriting the entire config file when modifying a single section, dropping custom keys the wizard doesn't manage (e.g., `tools.media.audio`, `gateway.auth.allowTailscale`, disabled `skills.entries`). **Root cause**: The wizard reads config through `readConfigFileSnapshot()`, which returns a Zod-validated + defaults-applied version. This processed config was used as the base for writes, meaning: - Zod-processed sections replaced raw file values (adding defaults the user never set) - `${VAR}` env references were substituted with literal values - `$include` directives were resolved to inline content **Fix**: Added `mergeWizardOutput()` which uses reference equality between `baseConfig` and `nextConfig` to detect which top-level sections the wizard actually modified. Only wizard-modified sections use the wizard's output; unmodified sections preserve their raw file values from `snapshot.parsed`. - Unmodified sections keep raw file values (no injected defaults) - `${VAR}` references preserved in unmodified sections - `$include` at top level falls back to current behavior (separate concern) - Both local and remote wizard paths use the merge function ## Test plan - [x] `mergeWizardOutput` unit tests: preserves raw values, uses wizard values for modified keys, preserves keys not in nextConfig, falls back with `$include`, adds new wizard keys - [x] Integration tests: preserves tools/skills/logging when configuring only `model`, `gateway`, or interactive loop - [x] Edge case: handler that drops keys → recovered from rawParsed - [x] Edge case: rawParsed differs from baseConfig (minimal raw vs defaults-injected) → unmodified sections use raw values - All 11 tests fail before fix, pass after <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR updates the configure wizard to avoid rewriting the entire config when only one wizard section changes. It introduces `mergeWizardOutput()` and uses it in both local/remote wizard flows so that top‑level sections the wizard didn’t modify are preserved from the raw parsed file (keeping user custom keys, `${VAR}` references, and un-expanded `$include` content), while modified sections come from the wizard output. The accompanying tests expand coverage for preserving raw values, recovering keys dropped by section handlers, and `$include` fallback behavior. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk. - Changes are narrowly scoped to how the wizard merges its output back into the raw parsed config, with explicit handling for default-only sections and `$include` fallback; unit/integration tests cover the key regressions described in the PR. - No files require special attention <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs