-
Notifications
You must be signed in to change notification settings - Fork 34
Description
Bug
nightshift setup writes provider config fields using Go struct field names (lowercased) instead of the mapstructure tag names. This causes the config to silently break — the fields are written but never read back correctly on subsequent runs.
Root Cause
In cmd/nightshift/commands/setup.go line 1920:
v.Set("providers", cfg.Providers)When viper serializes a Go struct, it lowercases Go field names rather than using mapstructure tags. So DangerouslySkipPermissions becomes dangerouslyskippermissions in YAML, but the struct expects dangerously_skip_permissions (from mapstructure:"dangerously_skip_permissions").
Affected Fields
| Go field | Written as (wrong) | Expected (mapstructure tag) |
|---|---|---|
DataPath |
datapath |
data_path |
DangerouslySkipPermissions |
dangerouslyskippermissions |
dangerously_skip_permissions |
DangerouslyBypassApprovalsAndSandbox |
dangerouslybypassapprovalsandsandbox |
dangerously_bypass_approvals_and_sandbox |
Impact
After running nightshift setup:
dangerously_skip_permissions: trueis silently lost — defaults tofalse- All tasks fail with permission denials across all iterations, then get abandoned
- Projects are marked "processed today" despite zero work being done
- The config passes
nightshift config validate(validation doesn't check field name correctness) nightshift configoutput doesn't display the permission flags at all, making it hard to diagnose
Suggested Fix
Replace the bulk struct set with individual key sets, matching the mapstructure tags:
// Instead of: v.Set("providers", cfg.Providers)
v.Set("providers.claude.enabled", cfg.Providers.Claude.Enabled)
v.Set("providers.claude.data_path", cfg.Providers.Claude.DataPath)
v.Set("providers.claude.dangerously_skip_permissions", cfg.Providers.Claude.DangerouslySkipPermissions)
v.Set("providers.claude.dangerously_bypass_approvals_and_sandbox", cfg.Providers.Claude.DangerouslyBypassApprovalsAndSandbox)
v.Set("providers.codex.enabled", cfg.Providers.Codex.Enabled)
v.Set("providers.codex.data_path", cfg.Providers.Codex.DataPath)
v.Set("providers.codex.dangerously_skip_permissions", cfg.Providers.Codex.DangerouslySkipPermissions)
v.Set("providers.codex.dangerously_bypass_approvals_and_sandbox", cfg.Providers.Codex.DangerouslyBypassApprovalsAndSandbox)
v.Set("providers.preference", cfg.Providers.Preference)Alternatively, use yaml struct tags alongside mapstructure tags, or use mapstructure.Decode in reverse to produce correct keys.
Reproduction
- Set correct field names manually in
~/.config/nightshift/config.yaml - Run
nightshift setup, complete the wizard - Inspect config — field names are now wrong
- Run
nightshift run— all tasks fail with permission denials
Environment
- nightshift v0.3.2
- Go module:
github.com/marcus/nightshift@v0.3.2 - OS: Linux (Arch)