#16301: fix: preserve custom config keys during configure wizard
commands
stale
size: S
Cluster:
Config Redaction Improvements
## Summary
- Fix `openclaw configure` silently dropping custom config keys not managed by the wizard (e.g. `tools.media.audio`, disabled skills, `gateway.auth.allowTailscale`)
- Use `snapshot.resolved` (pre-defaults config) instead of `snapshot.config` (with runtime defaults) as the write base, matching the pattern established by the `config set` fix (#6070)
- Add test verifying custom keys survive a wizard run and runtime defaults don't leak
## Root Cause
The configure wizard built `nextConfig` from `snapshot.config`, which includes runtime defaults (`agents.defaults.maxConcurrent`, model defaults, etc.). When `writeConfigFile(nextConfig)` was called, the config passed in was bloated with defaults the user never set, while user-specified keys outside the wizard's managed sections were lost.
The `config set` command had the same bug (#6070) and was fixed by switching to `snapshot.resolved` — the config after `$include` and `${ENV}` resolution but before runtime defaults are applied. This PR applies the same fix to the configure wizard.
## Changes
**`src/commands/configure.wizard.ts`:**
- Added `resolvedConfig` derived from `snapshot.resolved`
- Changed `nextConfig` base from `{ ...baseConfig }` to `structuredClone(resolvedConfig)`
- Changed `promptRemoteGatewayConfig` call to use `resolvedConfig`
- `baseConfig` (with defaults) is still used for display values and prompt defaults
**`src/commands/configure.wizard.e2e.test.ts`:**
- Added test: "preserves custom keys not managed by the wizard"
- Updated existing test mocks to include `resolved` field
## Test plan
- [x] New test verifies `tools.media.audio`, `skills.entries` (disabled skills), and `gateway.auth.allowTailscale` survive a wizard run
- [x] New test verifies runtime defaults (`agents.defaults.maxConcurrent`) do NOT leak into written config
- [x] Existing wizard tests pass (3/3)
- [x] All config tests pass (386/386)
- [x] All command tests pass (52/52)
Closes #9632
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Fixes the configure wizard silently dropping custom config keys by switching from `snapshot.config` (includes runtime defaults) to `snapshot.resolved` (pre-defaults config) as the write base. This matches the pattern from PR #6070 which fixed the same issue in `config set`/`unset` commands. The change preserves user-specified keys like `tools.media.audio`, `gateway.auth.allowTailscale`, and disabled skills while preventing runtime defaults from leaking into the written config file.
**Key changes:**
- Uses `structuredClone(resolvedConfig)` instead of `{ ...baseConfig }` as the base for `nextConfig`
- Passes `resolvedConfig` to `promptRemoteGatewayConfig` instead of `baseConfig`
- `baseConfig` (with defaults) is still correctly used for display values and prompt defaults
- Comprehensive test coverage verifying custom keys survive and runtime defaults don't leak
<h3>Confidence Score: 5/5</h3>
- Safe to merge with no concerns
- The fix directly mirrors the established pattern from PR #6070, uses the correct `snapshot.resolved` field as documented in the type definitions, and includes comprehensive test coverage that validates both preservation of custom keys and prevention of runtime defaults leaking. The changes are minimal, well-commented, and the test explicitly covers the bug scenario.
- No files require special attention
<sub>Last reviewed commit: d63770e</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#13849: fix(configure): preserve custom config keys across wizard sections
by mcaxtr · 2026-02-11
88.1%
#21124: fix(config): preserve missing keys from original in restoreRedacted...
by Marvae · 2026-02-19
76.3%
#21240: fix: GH#20607 prevent doctor from dropping custom config sections
by theognis1002 · 2026-02-19
76.3%
#11602: fix(config): skip stale legacy config files when openclaw.json exists
by akoscz · 2026-02-08
75.6%
#22408: fix: doctor --fix now persists config when removing unrecognized keys
by astroclaw · 2026-02-21
75.3%
#14179: fix(config): resolve $include directives before validation in setup...
by ken2190 · 2026-02-11
75.1%
#4897: fix: config logic issues (#4689, #4654)
by lailoo · 2026-01-30
74.7%
#22342: fix(doctor): --fix now actually removes unrecognized config keys
by MisterGuy420 · 2026-02-21
74.2%
#16991: fix(config): add missing defaults to config snapshot path
by AI-Reviewer-QS · 2026-02-15
74.1%
#23085: fix(workspace): respect OPENCLAW_STATE_DIR for workspace paths, fix...
by charojo · 2026-02-22
73.7%