Version
codebase-memory-mcp 0.9.0
- Independently reproduced with
codebase-memory-mcp 0.9.1-rc.1
Platform
macOS (Apple Silicon)
Install channel
GitHub release archive / install.sh (installed to ~/.local/bin)
Binary variant
standard
What happened, and what did you expect?
codebase-memory-mcp install recognizes its managed Codex SessionStart hook by the # >>> codebase-memory-mcp SessionStart >>> marker comments. If a previously installed hook is present in ~/.codex/config.toml in a semantically equivalent inline form without those markers—for example after a settings migration or another normalization step that removes comments—the installer appends another [[hooks.SessionStart]] table.
The inline assignment already defines hooks.SessionStart, so the appended array-of-tables definition makes the TOML invalid. Codex then fails to load the entire configuration instead of starting or resuming a thread.
Expected: install/update must keep config.toml parseable and remain idempotent even when formatting or comments have changed.
Reproduction
The reproduction is sandboxed: both HOME and CODEX_HOME point to a temporary directory, so the real Codex configuration is not modified.
sandbox="$(mktemp -d)"
mkdir -p "$sandbox/.codex"
cat > "$sandbox/.codex/config.toml" <<'EOF'
[hooks]
SessionStart = [{ matcher = "startup|resume|clear|compact", hooks = [{ type = "command", command = "echo \"Code discovery: prefer codebase-memory-mcp\"" }] }]
[mcp_servers.codebase-memory-mcp]
command = "/Users/me/.local/bin/codebase-memory-mcp"
EOF
# Control: the inline-only configuration is valid and Codex can load it.
CODEX_HOME="$sandbox/.codex" codex features list >/dev/null
# Reinstall into the sandbox.
HOME="$sandbox" codebase-memory-mcp install -y
# Fails after install because hooks.SessionStart is now defined twice.
CODEX_HOME="$sandbox/.codex" codex features list
Actual result: install -y exits successfully, but appends its marked [[hooks.SessionStart]] block after the existing inline hook. The subsequent Codex command fails with duplicate key.
Control case: if config.toml contains the installer's marked block and the markers remain intact, a second install replaces/skips that block correctly and the file stays valid. The current idempotency therefore depends on the marker comments surviving.
Logs
Error from the original configuration:
ChatGPT can't load config.toml, so this thread can't resume.
Fix ~/.codex/config.toml:843:9: duplicate key.
Error from the sandboxed reproduction:
Error: <sandbox>/.codex/config.toml:10:9: duplicate key
Caused by:
TOML parse error at line 10, column 9
|
10 | [[hooks.SessionStart]]
| ^^^^^^^^^^^^
duplicate key
How users hit this in practice
codebase-memory-mcp install adds the managed hook with marker comments.
- A configuration migration or normalization leaves the equivalent hook in inline
SessionStart = [...] form but does not preserve the comments.
- A later
codebase-memory-mcp install or update does not recognize the inline hook and appends another definition.
- Codex can no longer parse
config.toml until the duplicate is repaired manually.
The exact component that performed the original normalization was not isolated; the bug does not depend on it, because the sandboxed inline fixture reproduces the installer failure directly.
Expected behavior
The installer should structurally reconcile its owned Codex lifecycle hooks across supported TOML representations. After install/update:
config.toml remains parseable;
- exactly one owned
SessionStart hook is present;
- unrelated user hooks are preserved;
- a repeated install is idempotent even if comments or formatting changed.
If ownership cannot be determined safely, the installer should fail without modifying the file and report an actionable error instead of writing invalid TOML.
Workaround
For 0.9.0, remove the newly appended marked block and keep the existing equivalent inline hook, then validate the file before restarting Codex. When updating the binary while retaining an already working configuration, the GitHub installer can be run with --skip-config to avoid rewriting Codex configuration.
Related issues
Confirmations
Version
codebase-memory-mcp 0.9.0codebase-memory-mcp 0.9.1-rc.1Platform
macOS (Apple Silicon)
Install channel
GitHub release archive /
install.sh(installed to~/.local/bin)Binary variant
standard
What happened, and what did you expect?
codebase-memory-mcp installrecognizes its managed CodexSessionStarthook by the# >>> codebase-memory-mcp SessionStart >>>marker comments. If a previously installed hook is present in~/.codex/config.tomlin a semantically equivalent inline form without those markers—for example after a settings migration or another normalization step that removes comments—the installer appends another[[hooks.SessionStart]]table.The inline assignment already defines
hooks.SessionStart, so the appended array-of-tables definition makes the TOML invalid. Codex then fails to load the entire configuration instead of starting or resuming a thread.Expected: install/update must keep
config.tomlparseable and remain idempotent even when formatting or comments have changed.Reproduction
The reproduction is sandboxed: both
HOMEandCODEX_HOMEpoint to a temporary directory, so the real Codex configuration is not modified.Actual result:
install -yexits successfully, but appends its marked[[hooks.SessionStart]]block after the existing inline hook. The subsequent Codex command fails withduplicate key.Control case: if
config.tomlcontains the installer's marked block and the markers remain intact, a second install replaces/skips that block correctly and the file stays valid. The current idempotency therefore depends on the marker comments surviving.Logs
Error from the original configuration:
Error from the sandboxed reproduction:
How users hit this in practice
codebase-memory-mcp installadds the managed hook with marker comments.SessionStart = [...]form but does not preserve the comments.codebase-memory-mcp installorupdatedoes not recognize the inline hook and appends another definition.config.tomluntil the duplicate is repaired manually.The exact component that performed the original normalization was not isolated; the bug does not depend on it, because the sandboxed inline fixture reproduces the installer failure directly.
Expected behavior
The installer should structurally reconcile its owned Codex lifecycle hooks across supported TOML representations. After install/update:
config.tomlremains parseable;SessionStarthook is present;If ownership cannot be determined safely, the installer should fail without modifying the file and report an actionable error instead of writing invalid TOML.
Workaround
For
0.9.0, remove the newly appended marked block and keep the existing equivalent inline hook, then validate the file before restarting Codex. When updating the binary while retaining an already working configuration, the GitHub installer can be run with--skip-configto avoid rewriting Codex configuration.Related issues
hooks.jsonandconfig.toml; this issue creates conflicting definitions inside oneconfig.tomland prevents the config from loading at all.Confirmations