Documentation

Everything the plugin does, what it costs and how to control it. No account needed to read any of this.

Install

Unstale needs WordPress 7.0 or newer and PHP 8.1 or newer. WordPress 7.0 is the floor because the plugin runs on the AI Client that ships with it. Unstale works with Gutenberg and the Classic editor, on posts, pages and public custom post types.

2:07 · Install, connect Google, watch the checklist tick steps 1 and 2 · Plays from YouTube
  1. In your WordPress admin, go to Plugins → Add Plugin, search for Unstale and install it. You can also download the zip from wordpress.org and upload it.
  2. Activate the plugin. A new Unstale menu appears with six screens: Get started, Review queue, Content health, Journal, AI Agent and Settings. See In the admin.
  3. Go to Settings → Connectors and connect an AI provider if you have not already. Unstale uses whatever you set up there and stores no key of its own. See API keys below.
  4. Open Unstale → Settings and pick a default model and a default refresh level. Balanced is the default and is available on the free plugin.
  5. Open any post list. The Unstale column shows the status of the last refresh and its age, coloured by how far it has drifted, with a Refresh link that shows the estimate and asks you to confirm before it queues a new one.
  6. The job lands in the Review queue. Read the side-by-side diff, then approve or reject. Nothing is published before you approve, unless you switch on automatic publishing, which is off by default.
2:07 · Steps 5 and 6 on a real post: estimate, refresh, diff, approve, live at the same URL · Plays from YouTube

Prefer the command line? Unstale ships a WP-CLI command and a REST namespace, and an AI agent can drive it too: see Connect an AI agent.

# Refresh one post at the Balanced level
wp unstale refresh 1234 --level=balanced

# Queue the whole archive
wp unstale refresh --all --level=balanced

The REST namespace is unstale/v1, with routes for jobs, run, approve and estimate. Every step runs through Action Scheduler with a budget under 90 seconds per API call, so a long article can never hit a PHP timeout: the job resumes where it stopped.

Install Pro

Unstale Pro is an add-on, not a separate plugin: it hooks into the free plugin and needs it installed and active first, in version 1.36.0 or newer. It is not distributed on wordpress.org, so you install it by uploading a zip once, and WordPress updates it on its own from then on.

  1. Get the zip. Your purchase email carries a direct download link valid for 30 days. Once it expires, go to unstale.ai/download and enter your license key to get a fresh one.
  2. In your WordPress admin, go to Plugins → Add Plugin → Upload Plugin, pick the zip and install it.
  3. Activate it. A Licence entry appears under the Unstale menu.
  4. Open Unstale → Settings, paste your license key into the licence field and click Activate. The same field is available under Unstale → Licence, which also shows your plan and renewal date.
  5. Strong and Maximal appear in the level slider straight away, along with scheduled automation, bulk refresh from the Posts list and per-category rules.

Pro does not change how a refresh is billed. It uses the same provider you connected in Settings → Connectors, on your own account, so API keys and costs below apply to Pro exactly as they do to the free plugin.

Updates

Once the licence is active, Unstale Pro updates through the normal WordPress updates screen, like any plugin from the directory. Nothing to re-download. If the licence lapses or is refunded, updates stop; the version you have keeps working.

Moving Pro to another site

Plans are counted in sites: 1, 5 or unlimited. Activating uses one slot, and a plan that is full refuses a new site rather than silently deactivating an old one. To move a site off a plan, open Unstale → Licence on that site and click Deactivate this site, which frees the slot immediately. You can also switch plans at any time from the pricing page.

If the key is refused and the licence is neither refunded nor lapsed, write to support@unstale.ai from the address you paid with.

Compatibility

Unstale fits the stack you already run instead of asking you to change it. Everything below is detected at runtime, with no setting to switch on: if the plugin is active, Unstale uses it; if it is not, Unstale falls back to WordPress core.

Plugins and editors Unstale integrates with
Works with What Unstale does about it
Page builders
Elementor, Divi, SeedProd
The refresh reads the text out of the builder’s own data, rewrites only that text and writes it back where it came from, so your layout, styling and builder settings come back as they were. Images stay in place, but an alt text already set on one counts as text and can be rewritten. Unstale never re-serialises the page: it replaces the text where it found it and leaves every other byte alone. On a SeedProd page using SeedProd Pro blocks, the new text lands in the builder and the live page waits for you to reopen it and save; the job log says so.
SEO plugins
Yoast SEO, Rank Math, All in One SEO, SEOPress
The rewritten meta title and description are written into that plugin’s own fields, and Unstale adds its own Article JSON-LD to posts only, never to pages, and only when the published page carries none, so it never adds a second Article schema next to theirs. It reads the published page to check. If the page cannot be loaded, it adds its Article only when none of these four plugins is active. With none of them active, Unstale writes the metas itself.
Cache plugins
WP Rocket, W3 Total Cache, LiteSpeed Cache, WP Super Cache, WP Fastest Cache, SG Optimizer
After publishing, the refreshed post is purged through that plugin’s own public purge API. The purge is always aimed at the post, never a full-site flush, so the rest of your cache stays warm. Anything outside this list, a CDN for instance, hooks onto the unstale_purged action.
Editors and content types
Gutenberg, Classic editor
Posts, pages and public custom post types. A job is scoped to what you can already edit, so a user only ever sees and refreshes content they have rights on.

A builder outside this list has no adapter. When Unstale recognises one, it warns you first and goes ahead only if you choose Refresh anyway, which rewrites the standard WordPress content rather than the page your visitors see. A builder it does not recognise at all gets no warning, and its page is refreshed the same way. Adding an adapter takes two filters, unstale_builder_detectors to recognise the page and unstale_pipeline_steps to swap in your own extract and publish steps.

In the admin

Unstale adds one menu with six screens, a column in your post lists and a block under the editor. Everything on this page is in the free plugin unless it says otherwise.

Get started

A checklist that reads your site and never asks you to tick anything: an AI provider connected in WordPress, a default model that provider actually serves, a first refresh on one of the posts that waited longest (with its estimate before anything is spent), and the diff to review. One action at a time, and an empty review queue sends you back here until the four steps are done. Once they are, the screen folds into three shortcuts: Content health, the review queue, and another post to refresh. The setup video shows the first two steps ticking on their own, and the first refresh video the last two.

Review queue

Every refresh waits here with its side-by-side diff until you approve or reject it, unless you switch on automatic publishing, which is off by default. When something is waiting, a notice says so from wherever you are in the admin: with one refresh pending it opens that diff directly, with several it opens the queue. So a refresh that finishes while you work on something else no longer waits unnoticed. The first refresh video reads one diff from the fact-check to the approval, and the batch video approves a whole batch, row by row.

Content health

Your published content sorted by how long it has gone without an update, in three bands derived from the staleness threshold you set in Settings. Pick up to 50 posts per batch and queue them. Show all puts the whole list on one page.

Tick the posts, choose Refresh selected under Bulk actions and click Apply: a confirmation screen shows the total estimate before anything runs. Confirm refresh queues one refresh per post, and they run one after another in the background. The page does not update itself, so reload it to follow along. Each refresh then lands in the review queue on its own row, with its cost.

2:07 · Three stale posts in one batch: estimate, run, review, approve each one · Plays from YouTube

To run a batch later, choose Schedule refresh under Bulk actions instead and click Apply. The same screen shows the estimate and a Refresh on field: pick a date and time, up to a year ahead, click Schedule refresh, and you can close the tab. WordPress runs scheduled tasks when the site receives a visit, so the refreshes start by themselves on the next visit after that time. They take turns in the background, the Journal shows Started on schedule, and each rewrite waits in the review queue for your approval. Nothing is spent until the scheduled time.

2:07 · Three stale posts scheduled for later: pick a date, close the tab, approve each one · Plays from YouTube

Journal

Every refresh with its tokens and their cost, web search fees not included since no provider reports its search count yet, filterable by post, with running totals for all time and for the current month. A refresh you scheduled says Started on schedule in its journal, as the scheduled refresh video shows. Export CSV gives you the same rows as plain numbers a spreadsheet can add up, and it carries whatever filter you are looking at.

Settings

Default model, default refresh level, staleness threshold and the publishing options. The level slider shows what each level costs per 1,000 words, and the figure follows both the slider and the model you pick, so you can compare the two decisions together. The levels reserved for Pro show their cost as well, so you can see what they would cost before deciding.

The Unstale column and the editor block

In any post list, the Unstale column carries the status of the last refresh and its age, coloured on the same bands as Content health, so one glance down the list shows what has drifted. Under the editor, the Unstale block starts a refresh, follows it step by step and then lists everything it changed.

Once a refresh is published, a Restore the previous version link in that block puts the post back as it was before it: the text (the layout on Elementor and SeedProd, from the job’s own snapshot), the publish date the refresh moved, and the SEO title and description it wrote. It opens a confirmation screen that names exactly what will go back. If the content was edited since, Restore refuses and your edits stay; a date or meta goes back only if it still holds what the refresh wrote.

Connect an AI agent

Claude Code, Codex, Hermes Agent or any other client that speaks the Model Context Protocol (MCP) can drive Unstale on your site: find the stale posts, estimate a refresh, start it, follow it and read what it changed. The agent talks to your WordPress site and nothing else. Unstale still does the rewriting, on the AI provider you connected in WordPress, and nothing passes through an Unstale server. All of this is in the free plugin.

Unstale declares its actions as WordPress abilities, the API that ships with WordPress 7.0. The official MCP Adapter plugin turns them into MCP tools. It is distributed on GitHub, not on wordpress.org, and Unstale works without it: the abilities stay reachable through the REST API.

  1. Download mcp-adapter.zip from the latest MCP Adapter release, install it from Plugins → Add Plugin → Upload Plugin and activate it.
  2. Open Unstale → AI Agent (up to version 1.25, a section of Unstale → Settings). The screen says whether the adapter is found and gives the address of your Unstale server, ready to copy.
  3. Create an application password for the user the agent acts as, in Users → Profile → Application Passwords. That user needs to be able to edit other people's posts, and the agent only sees and refreshes what that user can edit.
  4. Give your client the address and the password, as below. The address is https://your-site.com/wp-json/unstale/mcp, or https://your-site.com/index.php?rest_route=/unstale/mcp when your permalinks are set to Plain.

The clients below send the password in a standard HTTP Basic header, your username and application password joined by a colon and Base64-encoded. <BASE64> stands for that result:

macOS and Linux

printf '%s' '<login>:xxxx xxxx xxxx xxxx xxxx xxxx' | base64 | tr -d '\n'

Windows PowerShell

[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes('<login>:xxxx xxxx xxxx xxxx xxxx xxxx'))

Claude Code

claude mcp add --transport http unstale "https://your-site.com/wp-json/unstale/mcp" --header "Authorization: Basic <BASE64>"

Codex, in ~/.codex/config.toml

[mcp_servers.unstale]
url = "https://your-site.com/wp-json/unstale/mcp"
http_headers = { "Authorization" = "Basic <BASE64>" }

Hermes Agent, in ~/.hermes/config.yaml

mcp_servers:
  unstale:
    url: "https://your-site.com/wp-json/unstale/mcp"
    headers:
      Authorization: "Basic <BASE64>"

Or connect over SSH

If your agent can open an SSH session on the server and WP-CLI is installed there, it starts the Unstale server itself, without an application password, and acts as the user named in the command. Anyone who holds that shell already has full control of the site.

ssh <ssh-host> "wp --path='/var/www/example' mcp-adapter serve --server=unstale --user='<login>'"

For instance in Claude Code:

claude mcp add --transport stdio unstale -- ssh <ssh-host> "wp --path='/var/www/example' mcp-adapter serve --server=unstale --user='<login>'"

If a client cannot connect directly

The adapter answers MCP over plain HTTP requests and does not stream. A client that needs streaming, or cannot send a custom header, connects through the @automattic/mcp-wordpress-remote proxy, which runs on your machine:

{
  "mcpServers": {
    "unstale": {
      "command": "npx",
      "args": ["-y", "@automattic/mcp-wordpress-remote@latest"],
      "env": {
        "WP_API_URL": "https://your-site.com/wp-json/unstale/mcp",
        "WP_API_USERNAME": "your-username",
        "WP_API_PASSWORD": "your-application-password"
      }
    }
  }
}

What the agent can do

The tools of the Unstale MCP server
Tool What it does
unstale-get-settings Levels, models and defaults, whether a custom instruction is available, whether agents may review, whether automatic publishing is on.
unstale-list-stale-content Your stale posts by age band, with the last refresh of each, 50 at most per page.
unstale-list-jobs Refreshes by status or by post.
unstale-get-job One refresh: status, fact-check, changes and log. The old and new content only when asked.
unstale-estimate-refresh The cost, web searches and words of one refresh, before it runs.
unstale-start-refresh Starts a refresh, with an optional custom instruction on Pro.
unstale-manage-job Cancels, retries or unsticks a refresh.
unstale-review-job Approves or rejects a refresh, only when the site allows agents to.

Approval stays with a person by default

An agent prepares refreshes, it does not publish them. Approving or rejecting stays in Unstale → Review queue until you tick Let AI agents approve or reject refreshes in the same settings section, and the lock holds even when the agent calls the REST API with its application password. With automatic publishing on, a refresh publishes itself, as it always has.

Custom instruction Pro

With Unstale Pro, a refresh can carry an instruction of up to 1,000 characters, sent by the agent or typed in the Unstale block of the editor: a keyword to target, a section to add. It reaches research, rewrite and enrichment, and it outranks the level's rules on structure, length and tone, never the HTML, the shortcodes, the facts or the web search budget. Fact-check and verification ignore it, so they still catch a figure invented to please it. A retry keeps it; a new, scheduled or automatic refresh starts without one. The cost estimate does not count it, so an instruction that adds content costs a little more than shown.

Site instructions Pro

With Unstale Pro, Unstale → Settings carries a Writing section with a permanent instructions field: persona, writing style, tone, form of address, up to 2,000 characters. It applies to every level, on every refresh, unlike the instruction above which is set once per refresh. When both are set, the per-refresh instruction wins. Otherwise, the site instructions win over the voice measured from the original article, so telling the site to address readers formally overrides an article originally written informally.

Quiz Pro

The same Writing section carries a checkbox, Add a quiz at the end of refreshed articles, checked by default. Each article can also override it from its own Unstale box in the editor, with a list of three choices: Follow site setting, Always and Never. The choice is saved the moment you change it, no need to save the article. The quiz only ever appears at the Strong and Maximal levels; turn it off and it stops appearing from the article's next Strong or Maximal refresh onward.

API keys

Unstale is strictly bring-your-own-key on every plan, free and Pro: you need a key from at least one AI provider, and that provider bills you directly, on your own account, with no markup and no credit system in between.

What changed in WordPress 7.0 is where the key lives. Providers and their credentials are now managed by WordPress itself, in Settings → Connectors, so Unstale stores no key of its own: it hands its prompts to the WordPress AI Client, which routes them to the provider you connected there. The plugin never sees, proxies or logs your key, and neither your key nor your content ever reaches an Unstale server.

Unstale → Settings shows which provider WordPress reports as connected, and lets you pick the default model. The admin screens run every refresh on that default model; WP-CLI (--model), the REST API and an AI agent can pass another one per run. Upgrading from a version of Unstale that stored its own keys deletes them automatically.

Anthropic

Create a key at console.anthropic.com, then connect it in Settings → Connectors. It stays with WordPress; Unstale only reads that the provider is ready. Model ID: claude-sonnet-5-5 (Claude Sonnet 5.5).

Anthropic's current Sonnet, generally available. Writing quality close to Opus, follows SEO instructions literally, 1M token context and 128k output. Best choice when the rewrite quality matters more than the bill. It replaces Claude Sonnet 5 at the same rates, and a site set to Sonnet 5, the default model before Gemini 3.8 Flash, moves to it on its own.

OpenAI

Create a key at platform.openai.com, then connect it in Settings → Connectors. It stays with WordPress; Unstale only reads that the provider is ready. Model ID: gpt-6-sol (GPT-6 Sol).

The cost-efficient high-end model of the GPT-6 family, generally available: the model you pick is the model that runs. It replaces GPT-5.6 Terra at a lower output rate, the same as Claude Sonnet 5.5, and a site set to Terra moves to it on its own.

Google default

Create a key at aistudio.google.com, then connect it in Settings → Connectors. It stays with WordPress; Unstale only reads that the provider is ready. Model ID: gemini-3.8-flash (Gemini 3.8 Flash). See it done in the setup video.

Default model on new installs. Fastest of the three and the cheapest by a wide margin, at less than half the Claude Sonnet 5.5 input rate. Multimodal, and the first 5,000 grounded searches each month are free. An update never switches an existing site to it: the model you had stays selected.

Model IDs and rates are not hardcoded in the plugin. Unstale fetches a remote catalogue at https://unstale.ai/api/v1/models.json once a day, keeps it cached for 48 hours and falls back to the bundled copy if the fetch fails. When a provider ships a new model or changes a price, your estimates follow without a plugin update.

Refresh levels

One slider, four presets. Every level fixes errors, fact-checks figures against live web results, adds internal links and republishes safely; the higher levels progressively take more editorial liberty with your copy.

Minimal and Balanced ship in the free plugin. Strong and Maximal require Unstale Pro.

What each refresh level does
Action Minimal Balanced Strong Maximal
Spelling and grammar fixes Yes Yes Yes Yes
Fact-check of figures, dates and prices (live web) Yes Yes Yes Yes
Internal linking (up to 15 links, one link per target page) Yes Yes Yes Yes
Em dashes removed Yes Yes Yes Yes
Date bump and same-URL republish Yes Yes Yes Yes
Original structure and tone (what the model is told) Keep Keep Adapt to persona Rewrite
SEO and business optimisations, missing sections added Not included Yes Yes Yes
Meta title (50-60 chars) and description (145-160 chars) Not included Yes Yes Yes
Key takeaway boxes Not included Yes Yes Yes
JSON-LD (Article, only when the page has none) Not included Yes Yes Yes
Key sentence per paragraph in bold, scannability pass Not included Yes Yes Yes
Tighter, more human copy written for the persona Not included Not included Yes Yes
Secondary queries all covered Not included Not included Yes Yes
TL;DR at the top Not included Not included Yes Yes
CTAs (in-text, visual, closing) to your products Not included Not included Yes Yes
Interactive quiz when relevant Not included Not included Yes Yes
Slide structure and first-person E-E-A-T signals Not included Not included Yes Foundation
Full rewrite from the best available sources Not included Not included Not included Yes

Internal linking is best-effort: Unstale never forces a link. If it finds no relevant target, the refresh still succeeds with fewer links, or none.

Before you pick a level for a post that still ranks, check what it is told to do with the outline: Minimal and Balanced are told to keep your heading structure, Strong to keep your sections in order while it may reword a heading, and only Maximal is told to rebuild the plan. The evidence on AI rewriting and rankings has its own page.

What happens during a refresh

  1. Analysis: main keyword, language, and the products or services the article mentions.
  2. Research: live web search for the top results, search intent, expected format, secondary queries, persona and gaps against competitors. Skipped at Minimal, which searches the web only to check facts.
  3. Fact-check: figures, prices, dates and feature claims verified against official sources.
  4. Rewrite: per the level you picked, section by section on long articles.
  5. Enrichment: metas, JSON-LD, takeaway boxes, TL;DR, CTAs and quiz, depending on the level.
  6. Internal linking: up to 15 links to your own published content, varied anchors, one link per target page.
  7. Cleanup: em dashes removed and line endings normalised.
  8. Review: the job waits in the queue with a side-by-side diff. Approve or reject. Automatic publishing, which skips this step, is off by default and switched on in the settings.
  9. Publish: same slug and same URL (a refresh never moves it), optional date bump, the version before it kept in the revision history when revisions are on (block or classic editor, Divi) or in the job’s snapshot for Restore (Elementor, SeedProd), a cache purge aimed at the post and never a full flush, and a log of steps, tokens, costs and links.

Costs

Two separate bills, and only one of them is ours. The Unstale licence is a flat annual fee with no rewrite quota. The AI usage is billed to you by your provider at their published rates.

Published provider rates, USD per million tokens
Model ID Provider Input / MTok Output / MTok Web search
claude-sonnet-5-5 Anthropic $2.00 $10.00 $10 / 1k
Standard rate, the same as Claude Sonnet 5, which it replaces.
gpt-6-sol OpenAI $2.00 $10.00 $10 / 1k
Generally available since 2026-09-22. Replaces gpt-5.6-terra ($2.00 / $12.00), which a site set to it now follows.
gemini-3.8-flash Google $0.75 $3.75 $14 / 1k
First 5,000 grounded searches per month are free

Provider rates as published on 2026-08-22. The plugin always estimates from the live catalogue, not from this table.

How the estimate is calculated

Unstale shows the estimate before a refresh you confirm from the editor, the posts list or Content health, per article and per batch:

estimated cost = estimated tokens (article length x level)
                 x model rate
               + estimated searches
                 x search rate

Article length and the level set the token estimate; the level also sets how many web searches the pipeline expects to run. Minimal searches least, Maximal most. Once the job finishes, the log records the tokens and what they cost, web search fees aside, so you can compare the estimate against real runs on your own archive rather than trusting a number on a marketing page.

Two levers if a bill runs higher than you want: switch the model (Gemini 3.8 Flash bills input at less than half the Claude Sonnet 5.5 rate, and its first 5,000 grounded searches each month are free), or drop a level. Neither is a subscription change, because Unstale never meters rewrites.

For any length, level and number of posts, the cost calculator runs the same estimate.

FAQ

Do I need a paid plan to use AI rewrites?

No. The free plugin on wordpress.org performs real AI rewrites at the Minimal and Balanced levels using your own API key, on one post at a time or on a batch of up to 50 picked from its content health screen. Unstale Pro adds the Strong and Maximal levels, scheduled automation, batches of up to 100 posts at the level you pick on its Bulk refresh screen or at your automation level from the Posts list, and per-category rules. See the pricing page.

Where is my API key stored?

In WordPress, not in Unstale. You still bring your own key, but since WordPress 7.0 providers and their credentials are managed by the core, in Settings > Connectors. Unstale hands its prompts to the WordPress AI Client, which routes them to the provider you connected there, so the plugin never sees, stores or transmits your key. If you used an older version of Unstale, the keys it had stored are deleted automatically when you update.

Who pays for the AI usage?

You do, directly to Anthropic, OpenAI or Google on your own account. Unstale charges a licence fee only, so there are no credits, no rewrite quota and no markup on tokens.

Will a refresh break my URLs or my rankings?

A refresh does not change the slug, and it skips the date bump when the new date would change a dated address. On default settings it waits for your approval with its diff. In the WordPress editor, block or classic, and on Divi, with revisions turned on, the version before it stays in the native revision history; Restore puts it back as long as the post content has not been edited since. No tool can promise rankings, and Unstale does not.

Can I see the cost before a refresh runs?

Yes. Unstale shows an estimate before a refresh you confirm from the editor, the posts list or Content health, per article and per batch, based on article length, the level you picked, the current rates for your model and the expected number of web searches. The job log then records the tokens and their cost. That cost leaves out web search fees for now: no provider reports its search count to WordPress yet, so your provider bill can come in slightly higher.

What are the requirements?

WordPress 7.0 or newer and PHP 8.1 or newer. WordPress 7.0 is the floor because Unstale runs on the AI Client that ships with it. Unstale works with both Gutenberg and the Classic editor, on posts, pages and public custom post types.

The free plugin runs the full pipeline on your own key, up to the Balanced level. Install it, refresh one stale post and read the diff before deciding anything.