Title
settings.json is rewritten with different formatting even when logical content hasn't changed
Description
When Gemini CLI writes settings.json (either ~/.gemini/settings.json or project-level .gemini/settings.json), it rewrites the file even when the logical content hasn't changed. The rewrite also produces formatting that differs from the original file, causing the file to appear as modified in git.
The problem
The write path in commentJson.ts uses comment-json's stringify(obj, null, 2), which:
- Always expands arrays vertically — e.g.
["AGENTS.md", "GEMINI.md"] becomes:
[
"AGENTS.md",
"GEMINI.md"
]
- Does not append a trailing newline — most formatters (prettier, editors) expect a final
\n
This means any project that runs prettier (or similar formatters) on JSON files will get a formatting conflict every time Gemini CLI touches settings.json. The file flip-flops between the formatter's output and Gemini CLI's output, showing up as a dirty file in git.
Steps to reproduce
- Create a
.gemini/settings.json formatted by prettier (short arrays on one line, trailing newline):
{
"context": {
"fileName": ["AGENTS.md", "GEMINI.md"]
}
}
- Run
gemini in the project directory
- Check
git diff .gemini/settings.json — the array is now expanded vertically and/or the trailing newline is removed
Expected behavior
If the logical content of settings.json hasn't changed, the file should not be rewritten. A simple deep-equality check before writing would prevent unnecessary rewrites and preserve the user's existing formatting.
Suggested fix
In updateSettingsFilePreservingFormat(), compare the parsed existing content with the new content before writing:
const existingContent = fs.readFileSync(filePath, "utf-8");
const existingParsed = parse(existingContent);
const updatedStructure = deepMerge(existingParsed, updates);
// Skip write if nothing changed
if (JSON.stringify(existingParsed) === JSON.stringify(updatedStructure)) {
return;
}
This would also address the symlink destruction reported in #10960, since unnecessary writes are what trigger the symlink replacement.
Environment
- Gemini CLI version: latest (installed via npm)
- OS: macOS
- Project uses prettier with
printWidth: 88
Related issues
Title
settings.json is rewritten with different formatting even when logical content hasn't changed
Description
When Gemini CLI writes
settings.json(either~/.gemini/settings.jsonor project-level.gemini/settings.json), it rewrites the file even when the logical content hasn't changed. The rewrite also produces formatting that differs from the original file, causing the file to appear as modified in git.The problem
The write path in
commentJson.tsusescomment-json'sstringify(obj, null, 2), which:["AGENTS.md", "GEMINI.md"]becomes:\nThis means any project that runs prettier (or similar formatters) on JSON files will get a formatting conflict every time Gemini CLI touches
settings.json. The file flip-flops between the formatter's output and Gemini CLI's output, showing up as a dirty file in git.Steps to reproduce
.gemini/settings.jsonformatted by prettier (short arrays on one line, trailing newline):{ "context": { "fileName": ["AGENTS.md", "GEMINI.md"] } }geminiin the project directorygit diff .gemini/settings.json— the array is now expanded vertically and/or the trailing newline is removedExpected behavior
If the logical content of
settings.jsonhasn't changed, the file should not be rewritten. A simple deep-equality check before writing would prevent unnecessary rewrites and preserve the user's existing formatting.Suggested fix
In
updateSettingsFilePreservingFormat(), compare the parsed existing content with the new content before writing:This would also address the symlink destruction reported in #10960, since unnecessary writes are what trigger the symlink replacement.
Environment
printWidth: 88Related issues