Skip to content

fix(codex): mergeCodexConfig Case 2 duplicates [features] on update #882

@flowerornament

Description

@flowerornament

GSD Version

1.22.1

Runtime

Codex

What happened?

After the first install, every subsequent run of install.js --codex --global produces a duplicate [features] section in config.toml. Codex fails on startup:

Error loading config.toml:
/Users/.../.codex/config.toml:46:2: duplicate key
   |
46 | [features]
   |  ^^^^^^^^

What did you expect?

A single [features] section with both the user's keys and GSD's keys preserved.

Steps to reproduce

  1. Have a config.toml with your own [features] keys before installing GSD:
model = "gpt-5.3-codex"

[features]
unified_exec = true
shell_snapshot = true
skills = true
  1. Run node bin/install.js --codex --global — first install works (Case 3 correctly merges into existing [features]).
  2. Run node bin/install.js --codex --global again — now the GSD marker exists, so Case 2 runs. It truncates at the marker (preserving the user's [features]), then appends the full gsdBlock which includes its own [features]. Result: two [features] sections.

Root cause

In mergeCodexConfig(), Case 3 (first install, no marker) detects an existing [features] and only appends from [agents] onward. Case 2 (update, has marker) doesn't — it blindly concatenates before + gsdBlock, and gsdBlock always includes [features].

Suggested fix

Four lines in Case 2 — same pattern Case 3 already uses:

// Case 2: Has GSD marker — truncate and re-append
if (markerIndex !== -1) {
    const before = existing.substring(0, markerIndex).trimEnd();
    const hasFeatures = /^\[features\]\s*$/m.test(before);
    const block = hasFeatures
      ? GSD_CODEX_MARKER + '\n' + gsdBlock.substring(gsdBlock.indexOf('[agents]'))
      : gsdBlock;
    const newContent = before ? before + '\n\n' + block + '\n' : gsdBlock + '\n';
    fs.writeFileSync(configPath, newContent);
    return;
}

Disclosure

This issue was written with assistance from Claude Code (Claude Opus 4.6). The root cause analysis, suggested fix, and reproduction steps were verified by running the patched code against the actual installer source at commit 57f2761.

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-triageNew issue awaiting maintainer review

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions