seo-fix-apply
Skill81 starsChanged 2 months agoMITView on GitHub
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.
- Reads credentials
In this repository33 other files it gives its agents.
- auditSkill
- compareSkill
- fixSkill
- geoSkill
- scoreSkill
- seo-agent-readinessSkill
- seo-ai-crawlersSkill
- seo-ai-discoverySkill
- seo-core-web-vitalsSkill
- seo-crawlabilitySkill
- seo-crawl-renderSkill
- seo-ecommerceSkill
- seo-eeatSkill
- seo-entity-linkingSkill
- seo-freshnessSkill
- seo-geo-answerblocksSkill
- seo-geo-factdensitySkill
- seo-headings-structureSkill
- seo-images-mediaSkill
- seo-indexabilitySkill
- seo-internal-linkingSkill
- seo-internationalSkill
- seo-localSkill
- seo-meta-onpageSkill
- seo-mobileSkill
- seo-orchestratorSkill
- seo-platform-detectSkill
- seo-renderingSkill
- seo-schema-jsonldSkill
- seo-scoreSkill
- seo-sitemapsSkill
- seo-social-cardsSkill
- seo-vertical-detectSkill
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 0 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Very specific: line 34
Read plan.json for the Change records.
- Very specific: line 59
Idempotent: If the change is already present (the JSON-LD block, the marker comment, the field's value), make no edit: report status: pass …
- Very specific: line 62
Re-verify: Run verify --run "<RUN_DIR>" --change <id> and the finding's verification.reproduce verbatim.
- Very specific: line 91
Never touch .env*, .git/, lockfiles, key material, wp-config.php, CI configs, or a Shopify config/settings_data.json.
- Very specific: line 94
Never fabricate a value (price, date, rating, sameAs, author) and never backdate dateModified.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
<!-- 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)
- Git pre-flight.
git status --porcelaininPROJECT_ROOT. Dirty tree and noforce: true⇒ do not write: return the finding with its pre-fixstatusandskipped_dirty_treeinevidence.observed. Neverstash,checkoutorreset— the user's uncommitted work is theirs. - Backup before the first write. Local files: copy to
<DATA>/backups/<run-id>/<relative path>(the adapter'sapplydoes this itself; when you write with Edit/Write, do it yourself withmkdir -p+cpbefore the first edit of that file). Remote resources: the adapter writesbefore/<change_id>.json. Record nothing in the project. - Local diffs — Edit/Write, not the adapter. For
target.kind: filechanges 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 andguard-writeengage. 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 asskipped_unreadyfrom the adapter and is yours to apply by hand — still exactly as previewed. - Remote targets — the adapter CLI, with its ticket. Anything whose
target.kindis notfilegoes throughnode "<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-hoccurl,wp, orshopifycommands — theguard-bashhook blocks them and it is right to. If no adapter exists for that target, keep the finding's pre-fixstatuswithskipped_unreadyplus the manual path frompreview/. - Idempotent. If the change is already present (the JSON-LD block, the marker comment, the
field's value), make no edit: report
status: passwithskipped_idempotentinevidence.observed. Re-running must never duplicate or corrupt content. - Re-verify. Run
verify --run "<RUN_DIR>" --change <id>and the finding'sverification.reproduceverbatim. Record the assertion's pass/fail. A stale CDN or page cache ispending_cacheinevidence.observedwithstatus: warn— never a claimedpass. 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. - Publish — only with
publish: trueand 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,--liveor-ato the Shopify CLI: that path is blocked and publishing has its own op. - 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. - On failure, stop widening. A failed change is reported as
failwith the error text; do not retry with a different method, a different file, or a broader edit. Rollback isrollback --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, status, severity, scope, evidence, expected,
recommendation, fixable, verification, expected_impact). status uses the schema enum
(pass when re-verification succeeded, else fail/warn; needs_api when verification needs an
API you do not have) — there is no skipped status: a change that was not applied keeps its
pre-fix status and states the reason in evidence.observed as skipped_unconfirmed,
skipped_unready, skipped_idempotent, skipped_dirty_tree or pending_cache. Quote what changed
and name the backup path. Do not render the report — the fix flow does.
Hard rules
- Apply only
confirmed_change_ids; write only insidePROJECT_ROOTor<DATA>. - Never touch
.env*,.git/, lockfiles, key material,wp-config.php, CI configs, or a Shopifyconfig/settings_data.json. - Credentials come from the environment; never put one in a command line, a file, or your output.
- Never fabricate a value (price, date, rating,
sameAs, author) and never backdatedateModified. - Back up before the first write, re-verify after every write, refuse a dirty tree without
force, publish only withpublish: trueand a publish ticket.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

