Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -437,10 +437,15 @@ gctools find-replace <apiURL> <adminAPIKey> --tag world-news --find 'Old text' -

# Custom delay between API calls
gctools find-replace <apiURL> <adminAPIKey> --find 'Old text' --replace 'New text' --delayBetweenCalls 100

# Replace a string without creating post revisions
gctools find-replace <apiURL> <adminAPIKey> --find 'Old text' --replace 'New text' --no-saveRevision
```

Use `-V` (`--verbose`) for detailed output showing which fields matched or were replaced in each post.

By default, `--saveRevision` is enabled, which creates a post revision for each edited post (lexical posts only). Use `--no-saveRevision` to disable this.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

Ghost GitHub issue 26677 save_revision false not taking effect

💡 Result:

In Ghost v6.20.0, this is a confirmed bug: the Admin API can create new post revisions even when you send ?save_revision=false (or 0). The issue report (#26677, opened Mar 3, 2026) explains that Ghost’s revision logic picks the wrong “latest” revision due to an ordering mismatch (revisions are fetched newest-first, but the code treats the last array element as “latest”). That makes the “background save” time check almost always pass, so revisions get saved whenever content changes—ignoring save_revision=false. [1]

What you can do

  • If you need it fixed now: patch your Ghost install/fork so “latestRevision” uses the newest revision (e.g., the first element when ordered DESC), or adjust sorting so the newest revision is selected. (That’s the root cause described in the issue.) [1]
  • Otherwise: you’ll likely have to wait for an upstream fix (the issue is labeled needs:triage and, as of the report, has no assignee/milestone). [1]

Note

You may see save_revision=1 in normal Ghost Admin traffic—Ghost Admin appears to always send save_revision=true, which masks this bug for most UI usage. [1][2]

Sources: GitHub issue #26677 [1], related Ghost editor request example showing save_revision usage [2].


Document known Ghost limitation with --no-saveRevision.

Line 447 documents --no-saveRevision without noting that this feature is non-functional due to a confirmed bug in Ghost v6.20.0+ (issue #26677). The Admin API ignores the save_revision=false parameter due to a revision ordering logic error. Users should be warned that revisions will be saved regardless until Ghost upstream releases a fix. Consider adding a brief note to manage expectations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` at line 447, Add a brief note next to the --no-saveRevision flag
documentation warning that Ghost v6.20.0+ has a known bug (issue `#26677`) where
the Admin API ignores save_revision=false due to revision ordering logic, so
revisions will still be created; reference the Ghost version and issue number
and suggest users expect revisions to be saved until upstream fixes the bug.


Available `where` fields are:

* `all`
Expand Down
4 changes: 4 additions & 0 deletions commands/find-replace.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ const setup = (sywac) => {
defaultValue: 50,
desc: 'The delay between API calls, in ms'
});
sywac.boolean('--saveRevision', {
defaultValue: true,
desc: 'Create a post revision for each edited post (lexical posts only)'
});
};

// What to do when this command is executed
Expand Down
6 changes: 6 additions & 0 deletions prompts/find-replace.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ const options = [
value: 'codeinjection_foot'
}
]
},
{
type: 'confirm',
name: 'saveRevision',
message: 'Create a post revision for each edited post? (lexical posts only)',
default: true
}
];

Expand Down
3 changes: 2 additions & 1 deletion tasks/find-replace.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ const getFullTaskList = (options) => {
delete post.matchesByField;

try {
let result = await ctx.api.posts.edit(post);
let queryParams = ctx.args.saveRevision ? {save_revision: true} : {};
let result = await ctx.api.posts.edit(post, queryParams);
Comment on lines +144 to +145

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Enforce saveRevision default in task-layer defaults.

Line 144 relies on ctx.args.saveRevision being provided by callers. Add saveRevision: true to initialise() defaults so the safety default is preserved even if this task runner is reused outside current CLI/prompt flows.

💡 Suggested patch
             let defaults = {
                 verbose: false,
                 tag: false,
-                delayBetweenCalls: 50
+                delayBetweenCalls: 50,
+                saveRevision: true
             };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tasks/find-replace.js` around lines 144 - 145, The task uses
ctx.args.saveRevision (see the edit call in find-replace.js where queryParams =
ctx.args.saveRevision ? {save_revision: true} : {}) but initialise() doesn't set
a default; update the initialise() defaults to include saveRevision: true so the
task-layer enforces the safety default even if caller omits it (modify the
initialise() function/object that seeds ctx.args to add saveRevision: true).

ctx.updated.push(result.url);
return Promise.delay(options.delayBetweenCalls).return(result);
} catch (error) {
Expand Down
Loading