Skip to content
Marketing
Skill

/seo-fix-apply

Writer protocol preloaded into the seo-fixer-writer agent — how confirmed SEO/AI-search fixes are applied (git pre-flight, backup, Edit/Write for local diffs, ticketed adapter CLIs for remote targets, re-verify, publish only on a second ticket, rollback) and the findings-array

From plugin
claude-seo-ai
8134 skills5 agents1 hook

Claude Code

$ npx -y skills add Hainrixz/claude-seo-ai --skill seo-fix-apply --agent claude-code

SKILL.md

seo-fix-apply.SKILL.md
name: seo-fix-apply
description: Writer protocol preloaded into the seo-fixer-writer agent — how confirmed SEO/AI-search fixes are applied (git pre-flight, backup, Edit/Write for local diffs, ticketed adapter CLIs for remote targets, re-verify, publish only on a second ticket, rollback) and the findings-array output contract. Used only by the fix flow after the user has confirmed changes; never invoked on its own.
user-invocable: false
allowed-tools: Read, Grep, Glob

<!-- Portions Copyright (c) 2026 Enrique Rocha (@soyenriquerocha) - see LICENSE for original authors · tododeia.com · id er-d03758e1 -->

seo-fix-apply (writer protocol)

This file is the authoritative protocol; `agents/seo-fixer-writer.md` carries the in-context summary — keep the two in sync. Edit, Write and Bash are deliberately **not** pre-approved here: Claude Code's native diff and command prompts must reach the user for every write, and the `guard-write` / `guard-bash` hooks run on top of them.

You apply what was already confirmed. You do not decide what to fix, you do not improve a diff you were given, and you never widen the change set.

Inputs

The `fix` command dispatches you with a JSON envelope:

| key | meaning | | --- | --- | | `RUN_DIR` | `<DATA>/fix/runs/<id>/` — `plan.json`, `manifest.json` (with `confirmed[]`), `preview/`, `before/`, `after/`, `log.ndjson` | | `SCRIPTS_DIR` | absolute `<plugin_root>/scripts/`. Run scripts as `node "<SCRIPTS_DIR>/<x>.mjs" …` with the literal path — never a `${...}` token, never a relative `scripts/` path | | `DATA` | plugin data root. Backups live here, never in the user's project | | `PROJECT_ROOT` | the user's project (local targets only) | | `confirmed_change_ids[]` | the ONLY change ids you may apply | | `tickets` | `{ <change_id>: <ticket id or the exact command> }` — one-shot, 15-minute, issued after the user confirmed | | `publish` | `false` by default; `true` only after a **second** confirmation, and it carries its own ticket | | `force` | allows writing into a dirty git tree | | `return` | "JSON array of findings only" |

Read `plan.json` for the Change records. A change you were not given an id for does not get applied, previewed again, or "helpfully" included.

Protocol (per confirmed change, in order)

1. **Git pre-flight.** `git status --porcelain` in `PROJECT_ROOT`. Dirty tree and no `force: true` ⇒ do not write: return the finding with its pre-fix `status` and `skipped_dirty_tree` in `evidence.observed`. Never `stash`, `checkout` or `reset` — the user's uncommitted work is theirs. 2. **Backup before the first write.** Local files: copy to `<DATA>/backups/<run-id>/<relative path>` (the adapter's `apply` does this itself; when you write with Edit/Write, do it yourself with `mkdir -p` + `cp` before the first edit of that file). Remote resources: the adapter writes `before/<change_id>.json`. Record nothing in the project. 3. **Local diffs — Edit/Write, not the adapter.** For `target.kind: file` changes whose strategy is AUTO (`html-head`, `front-matter`, `config-file`, `liquid`), apply the previewed diff with Edit (or Write for a new file) so the native diff prompt and `guard-write` engage. Apply exactly the preview: same insertion point, same text, no reformatting, no extra content, `TODO:<field>` placeholders preserved verbatim. A JSX/TSX or other non-AUTO strategy arrives as `skipped_unready` from the adapter and is yours to apply by hand — still exactly as previewed. 4. **Remote targets — the adapter CLI, with its ticket.** Anything whose `target.kind` is not `file` goes through `node "<SCRIPTS_DIR>/adapters/<adapter>.mjs" apply --run "<RUN_DIR>" --change <id> --ticket <ticket> --data "<DATA>" --json`. The ticket is required and one-shot; a missing or expired one is a real failure, not something to route around. **Never** emulate an adapter with ad-hoc `curl`, `wp`, or `shopify` commands — the `guard-bash` hook blocks them and it is right to. If no adapter exists for that target, keep the finding's pre-fix `status` with `skipped_unready` plus the manual path from `preview/`. 5. **Idempotent.** If the change is already present (the JSON-LD block, the marker comment, the field's value), make no edit: report `status: pass` with `skipped_idempotent` in `evidence.observed`. Re-running must never duplicate or corrupt content. 6. **Re-verify.** Run `verify --run "<RUN_DIR>" --change <id>` and the finding's `verification.reproduce` verbatim. Record the assertion's pass/fail. A stale CDN or page cache is `pending_cache` in `evidence.observed` with `status: warn` — **never** a claimed `pass`. A local framework target with no dev server is a source-level pass: say "source verified, re-audit after deploy" rather than claiming the live page changed. 7. **Publish — only with `publish: true` and its own ticket.** Publishing is what makes staged work public (`shopify theme publish`, a Webflow site publish, a HubSpot draft push-live). It is a separate op with a separate confirmation and a separate ticket: `node "<SCRIPTS_DIR>/adapters/<adapter>.mjs" publish --run "<RUN_DIR>" --ticket <publish ticket> --data "<DATA>"`. Without both, leave the change staged and say so in the finding. Never pass `--allow-live`, `--live` or `-a` to the Shopify CLI: that path is blocked and publishing has its own op. 8. **Log.** One NDJSON line per change in `<RUN_DIR>/log.ndjson` (change id, files or resource, result). Redact anything credential-shaped; the adapters' own logging already does. 9. **On failure, stop widening.** A failed change is reported as `fail` with the error text; do not retry with a different method, a different file, or a broader edit. Rollback is `rollback --run "<RUN_DIR>" --change <id>` and it needs its own ticket.

Output contract

Return a JSON array of findings conforming to `schema/finding.schema.json` for the confirmed changes only (`id`, `module`, `title`, `st

Read more
@hainrixz
Ships withclaude-seo-ai

The SEO + AI-search (GEO/AEO) optimization toolkit for Claude Code — two-score audit + opt-in fixer. Built for 2026-2027.

8134 skills5 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
81
Star history of Hainrixz/claude-seo-ai on GitHub, a chart by star-history.com

Other skills on claude-seo-ai.

audit

audit

Audit a website or web codebase for SEO and AI-search (GEO/AEO) — produces two independent 0-100 scores (Search SEO + AI…

compare

compare

Compare a site against its own baseline, against a staging deployment, against up to four competitors, or against the pages that…

fix

fix

Opt-in fixer (the /claude-seo-ai:fix command). Applies the safe, deterministic SEO/AI-search fixes from a persisted audit to the…

geo

geo

Analyze and score only a page's AI-search visibility (GEO/AEO) — answer extractability, fact density, AI-crawler access and…

score

score

Recompute and display the two scores (Search SEO + AI Visibility) from a persisted audit run, without re-crawling. Use to re-show…

More skills from other plugins.

seo

seo

Comprehensive SEO analysis for any website or business type. Full site audits, single-page analysis, technical SEO (crawlability,…

@agricidaniel@agricidanielInstall Skill
brag

brag

Turn the current project website into a short, polished, shareable launch video using Hyperframes. Use when someone says "/brag",…

brag2w21k
@latent-spaces@latent-spacesInstall Skill
geo-audit

geo-audit

Full website GEO+SEO audit with parallel subagent delegation. Orchestrates a comprehensive Generative Engine Optimization audit…

Questions about seo-fix-apply.

Which coding agents can use seo-fix-apply?
seo-fix-apply installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.