Summary
PR #432 decomposed the monolithic init wizard into composable step classes and intentionally laid architectural foundations for making netclaw init reentrant. This issue tracks the remaining work to complete that capability: re-running netclaw init should detect existing configuration and allow the user to modify it rather than starting from scratch.
PRD-004 explicitly requires this:
The wizard is reentrant — re-running netclaw init detects existing config and shows a section dashboard with status per section. Each section is independently enterable for modification. First-run guides linearly through all steps.
Foundations already in place (from #432)
1. WizardContext.ExistingConfig — deferred pre-population hook
File: src/Netclaw.Cli/Tui/Wizard/WizardContext.cs (lines 48-56)
/// Null for fresh init. When populated, steps should pre-populate their
/// fields from the existing config. (Deferred — not implemented yet.)
///
/// Re-edit UX intent: when existing config is detected, the wizard should
/// offer "Start fresh" vs "Modify existing". "Start fresh" does NOT wipe
/// existing files until the health check/validate stage completes successfully.
public Dictionary<string, object>? ExistingConfig { get; init; }
This property is declared and documented but never populated. Each step's OnEnter() would read from it to pre-fill fields.
2. ConfigFileHelper — load/merge/write utilities
File: src/Netclaw.Cli/Config/ConfigFileHelper.cs
Already supports the full merge workflow:
LoadConfigFiles(paths) — loads existing netclaw.json + secrets.json as mutable dictionaries (returns default skeleton if missing)
GetOrCreateSection(dict, key) — gets or creates nested sections, handling JsonElement deserialization
GetSectionOrNull(dict, key) — non-creating variant
WriteConfigFile(path, data) — writes merged dictionary back to disk
3. ProviderCredentialWriter — proof-of-concept merge pattern
File: src/Netclaw.Cli/Config/ProviderCredentialWriter.cs
Already demonstrates the load → merge → write pattern used by netclaw provider add:
Load existing config → GetOrCreateSection("Providers") → update entry → WriteConfigFile()
This preserves other providers and other config sections. The same pattern can be applied to WizardConfigBuilder.
4. IWizardStepViewModel.OnEnter(context, direction) — direction-aware entry
File: src/Netclaw.Cli/Tui/Wizard/IWizardStepViewModel.cs
Each step receives a NavigationDirection (Forward/Back) on entry. This same mechanism can distinguish "entering from existing config" vs "fresh entry" — steps would check context.ExistingConfig in their OnEnter() and pre-populate fields accordingly.
5. IsApplicable(WizardContext) — conditional step inclusion
File: src/Netclaw.Cli/Tui/Wizard/IWizardStepViewModel.cs
Steps are dynamically included/excluded based on context, re-evaluated on each transition. This enables a re-edit mode where only changed sections need to be shown.
6. WizardConfigBuilder — typed config sections
File: src/Netclaw.Cli/Tui/Wizard/WizardConfigBuilder.cs
Each config area (Provider, Slack, Security, Search, etc.) is an independent typed section. This makes partial updates straightforward — only populate the sections being modified.
7. WizardOrchestrator — composable step sequencing
File: src/Netclaw.Cli/Tui/Wizard/WizardOrchestrator.cs
Manages step sequencing with upfront instantiation (all 8 steps created once, preserving internal state) and dynamic applicability filtering. The orchestrator's WriteConfig() collects contributions from all steps — this is where merge-vs-overwrite behavior would be controlled.
What remains to implement
1. Detect existing config at init entry point
At the netclaw init entry point, check whether netclaw.json already exists. If so, load it and populate WizardContext.ExistingConfig.
2. "Start fresh" vs "Modify existing" UX
When existing config is detected, present a choice screen before entering the wizard steps. Per the documented intent, "Start fresh" should NOT wipe existing files until the health check/validate stage completes successfully.
3. Pre-population logic in each step's OnEnter()
Each of the 8 step ViewModels needs to check context.ExistingConfig on forward entry and pre-fill their fields from the matching config section:
| Step |
Config section to read |
ProviderStepViewModel |
Providers, Models |
SecurityPostureStepViewModel |
Security |
SlackStepViewModel |
Slack |
ChannelsStepViewModel |
channel audience data |
SearchStepViewModel |
Search |
BrowserAutomationStepViewModel |
McpServers |
IdentityStepViewModel |
identity files on disk |
HealthCheckStepViewModel |
N/A (final validation) |
Step files are all in src/Netclaw.Cli/Tui/Wizard/Steps/.
4. Change WizardConfigBuilder.WriteConfigFile() to merge instead of overwrite
Currently WriteConfigFile() builds a fresh dictionary and overwrites the file. For reentrant mode, it should load the existing config first and merge step contributions into it, preserving sections that weren't modified. The pattern from ProviderCredentialWriter can be followed.
5. Section dashboard for re-edit mode (PRD-004)
PRD-004 describes a section dashboard showing per-section status, where each section is independently enterable. This would be a new view that replaces the linear wizard flow when existing config is detected.
6. Secrets file merging
WizardSecretsBuilder.WriteSecretsFile() also builds fresh and overwrites. Same merge treatment needed as the config builder, preserving secrets for sections not being re-configured.
Key files map
src/Netclaw.Cli/Tui/Wizard/
├── WizardContext.cs # ExistingConfig property (deferred)
├── WizardOrchestrator.cs # Step sequencing + WriteConfig()
├── WizardConfigBuilder.cs # Config assembly (needs merge mode)
├── IWizardStepViewModel.cs # Step interface + NavigationDirection
├── HealthCheckRunner.cs # Health check collection
└── Steps/
├── ProviderStepViewModel.cs
├── SecurityPostureStepViewModel.cs
├── SlackStepViewModel.cs
├── ChannelsStepViewModel.cs
├── SearchStepViewModel.cs
├── BrowserAutomationStepViewModel.cs
├── IdentityStepViewModel.cs
└── HealthCheckStepViewModel.cs
src/Netclaw.Cli/Config/
├── ConfigFileHelper.cs # Load/merge/write utilities (ready to use)
└── ProviderCredentialWriter.cs # Merge pattern proof-of-concept
docs/prd/PRD-004-cli-onboarding-and-config.md # Reentrant init requirement
References
Summary
PR #432 decomposed the monolithic init wizard into composable step classes and intentionally laid architectural foundations for making
netclaw initreentrant. This issue tracks the remaining work to complete that capability: re-runningnetclaw initshould detect existing configuration and allow the user to modify it rather than starting from scratch.PRD-004 explicitly requires this:
Foundations already in place (from #432)
1.
WizardContext.ExistingConfig— deferred pre-population hookFile:
src/Netclaw.Cli/Tui/Wizard/WizardContext.cs(lines 48-56)This property is declared and documented but never populated. Each step's
OnEnter()would read from it to pre-fill fields.2.
ConfigFileHelper— load/merge/write utilitiesFile:
src/Netclaw.Cli/Config/ConfigFileHelper.csAlready supports the full merge workflow:
LoadConfigFiles(paths)— loads existingnetclaw.json+secrets.jsonas mutable dictionaries (returns default skeleton if missing)GetOrCreateSection(dict, key)— gets or creates nested sections, handlingJsonElementdeserializationGetSectionOrNull(dict, key)— non-creating variantWriteConfigFile(path, data)— writes merged dictionary back to disk3.
ProviderCredentialWriter— proof-of-concept merge patternFile:
src/Netclaw.Cli/Config/ProviderCredentialWriter.csAlready demonstrates the load → merge → write pattern used by
netclaw provider add:This preserves other providers and other config sections. The same pattern can be applied to
WizardConfigBuilder.4.
IWizardStepViewModel.OnEnter(context, direction)— direction-aware entryFile:
src/Netclaw.Cli/Tui/Wizard/IWizardStepViewModel.csEach step receives a
NavigationDirection(Forward/Back) on entry. This same mechanism can distinguish "entering from existing config" vs "fresh entry" — steps would checkcontext.ExistingConfigin theirOnEnter()and pre-populate fields accordingly.5.
IsApplicable(WizardContext)— conditional step inclusionFile:
src/Netclaw.Cli/Tui/Wizard/IWizardStepViewModel.csSteps are dynamically included/excluded based on context, re-evaluated on each transition. This enables a re-edit mode where only changed sections need to be shown.
6.
WizardConfigBuilder— typed config sectionsFile:
src/Netclaw.Cli/Tui/Wizard/WizardConfigBuilder.csEach config area (Provider, Slack, Security, Search, etc.) is an independent typed section. This makes partial updates straightforward — only populate the sections being modified.
7.
WizardOrchestrator— composable step sequencingFile:
src/Netclaw.Cli/Tui/Wizard/WizardOrchestrator.csManages step sequencing with upfront instantiation (all 8 steps created once, preserving internal state) and dynamic applicability filtering. The orchestrator's
WriteConfig()collects contributions from all steps — this is where merge-vs-overwrite behavior would be controlled.What remains to implement
1. Detect existing config at init entry point
At the
netclaw initentry point, check whethernetclaw.jsonalready exists. If so, load it and populateWizardContext.ExistingConfig.2. "Start fresh" vs "Modify existing" UX
When existing config is detected, present a choice screen before entering the wizard steps. Per the documented intent, "Start fresh" should NOT wipe existing files until the health check/validate stage completes successfully.
3. Pre-population logic in each step's
OnEnter()Each of the 8 step ViewModels needs to check
context.ExistingConfigon forward entry and pre-fill their fields from the matching config section:ProviderStepViewModelProviders,ModelsSecurityPostureStepViewModelSecuritySlackStepViewModelSlackChannelsStepViewModelSearchStepViewModelSearchBrowserAutomationStepViewModelMcpServersIdentityStepViewModelHealthCheckStepViewModelStep files are all in
src/Netclaw.Cli/Tui/Wizard/Steps/.4. Change
WizardConfigBuilder.WriteConfigFile()to merge instead of overwriteCurrently
WriteConfigFile()builds a fresh dictionary and overwrites the file. For reentrant mode, it should load the existing config first and merge step contributions into it, preserving sections that weren't modified. The pattern fromProviderCredentialWritercan be followed.5. Section dashboard for re-edit mode (PRD-004)
PRD-004 describes a section dashboard showing per-section status, where each section is independently enterable. This would be a new view that replaces the linear wizard flow when existing config is detected.
6. Secrets file merging
WizardSecretsBuilder.WriteSecretsFile()also builds fresh and overwrites. Same merge treatment needed as the config builder, preserving secrets for sections not being re-configured.Key files map
References
docs/prd/PRD-004-cli-onboarding-and-config.md— reentrant init requirement