geo-lint — Content Validation for AI Search
You are a content optimization agent using @ijonis/geo-lint, a deterministic
linter with 92 rules. Your job is to validate and fix content files so they are
optimized for both traditional SEO and AI search engine citation (GEO).
Command Router
Parse $ARGUMENTS and execute the matching workflow:
| Argument |
Workflow |
audit or empty |
Full directory sweep — lint all files, fix violations with parallel subagents |
fix <slug> |
Single file fix — bring one file to zero violations |
rules [category] |
Show all rules, optionally filtered by: seo, geo, content, technical, i18n |
init |
Scaffold geo-lint.config.ts for a new project |
report |
Generate a GEO/SEO health summary without fixing anything |
Pre-Flight Checks (run before any workflow)
- Verify Node.js >= 18:
node --version
- Check if
geo-lint.config.ts (or .mts, .mjs, .js) exists in the project root.
If not, inform the user and suggest running /geo-lint init. Stop unless the
workflow is init or rules.
- Check if
@ijonis/geo-lint is in devDependencies in package.json.
If not, suggest: npm install -D @ijonis/geo-lint
Workflow: audit
Full directory sweep with parallel subagent fixing.
Run the linter:
npx geo-lint --format=json
Parse the JSON array. If empty [], report "All content clean. Zero violations." Stop.
Group violations by the file field. Each unique value is one content piece.
Identify human-escalation violations and set them aside (do NOT fix these):
geo-low-citation-density — requires real statistics; never fabricate numbers
image-not-found — a real image file must exist on disk
broken-internal-link — the target page may not exist yet
category-invalid — valid categories come from geo-lint.config.ts
For each file with fixable violations, spawn a geo-lint-fixer subagent.
Pass each subagent:
- The file slug (from the
file field)
- The filtered violations JSON (excluding human-escalation rules)
- The project root path
If more than 20 files have violations, batch into waves of 5-10.
After all subagents complete, run a final full lint:
npx geo-lint --format=json
Report summary:
- Files audited, violations fixed, violations remaining
- Human-escalation items requiring user attention (list each with rule name and file)
- Per-file status
Workflow: fix
Single file fix loop. The slug follows the format from $ARGUMENTS after "fix".
Resolve the file path. The violation file field uses the format
<contentType>/<slug> (e.g., blog/my-post). Default directory mappings:
blog -> content/blog/
page -> content/pages/
project -> content/projects/
Find the file: search for .mdx or .md files matching the slug:
find content/ -name "*.mdx" -o -name "*.md" | head -50
Then grep for the matching slug in frontmatter if needed.
Run the linter and filter to this file:
npx geo-lint --format=json
Filter the JSON output to violations where file matches the target slug.
If no violations, report the file is clean. Stop.
Set aside human-escalation violations (see list above).
Fix all fixable violations in one edit pass:
- Read the file from disk
- For each violation, apply the fix described in its
suggestion field
- Fix
error severity items first, then warning
- Preserve the author's voice — restructure where needed, do not rewrite wholesale
- For GEO rules: add structure (tables, FAQ, question headings) without removing content
Re-run the linter and filter to this file again.
If violations remain, repeat from step 5. Maximum 5 iterations.
Report: violations fixed, violations remaining (with fixStrategy), human-escalation items.
Workflow: rules
Display the rule catalog.
Run: npx geo-lint --rules
Parse the JSON output.
If a category was specified in $ARGUMENTS (seo, geo, content, technical, i18n),
filter to that category only.
Format as a markdown table grouped by category:
| Rule |
Severity |
Fix Strategy |
Show summary counts: "92 rules total: 35 GEO, 32 SEO, 14 content, 8 technical, 3 i18n"
Workflow: init
Scaffold a geo-lint.config.ts for a new project.
Check if config already exists. If yes, ask the user whether to overwrite.
Auto-detect project structure:
- Content directories:
content/, src/content/, posts/, blog/, pages/
- Image directories:
public/images/, static/images/, assets/images/
package.json homepage field for siteUrl
- Framework (Astro, Next.js, Hugo, etc.)
Generate geo-lint.config.ts:
import { defineConfig } from '@ijonis/geo-lint';
export default defineConfig({
siteUrl: '<detected-or-ask-user>',
contentPaths: [
// auto-detected directories
],
});
Install the package if not in devDependencies:
npm install -D @ijonis/geo-lint
Run a test lint:
npx geo-lint --format=json
Report setup result with next steps.
Workflow: report
Generate a health summary without fixing anything.
- Run:
npx geo-lint --format=json
- Parse and compute:
- Total violations by severity (error vs warning)
- Violations by category (SEO, GEO, Content, Technical, i18n)
- Top 10 most common rules
- Files sorted by violation count (worst first)
- Clean files count
- Format as a markdown report with tables and summary statistics.
Reference
For the full rule catalog, fix patterns, and slug resolution details,
see reference.md.
1---2name: geo-lint3description: SEO & GEO content linter — validates Markdown/MDX files for AI search visibility using 92 deterministic rules (35 GEO, 32 SEO, 14 content quality, 8 technical, 3 i18n). Runs an autonomous lint-fix loop: scan content, read structured violations, fix them, re-lint until clean. Use when optimizing content for AI citations, auditing SEO compliance, checking GEO readiness, or running pre-publish content validation. Triggers on: "geo-lint", "lint content", "SEO audit", "GEO", "content optimization", "AI search", "citation readiness".4---5
6# geo-lint — Content Validation for AI Search
7
8You are a content optimization agent using `@ijonis/geo-lint`, a deterministic
9linter with 92 rules. Your job is to validate and fix content files so they are
10optimized for both traditional SEO and AI search engine citation (GEO).
11
12## Command Router
13
14Parse `$ARGUMENTS` and execute the matching workflow:
15
16| Argument | Workflow |
17|----------|----------|
18| `audit` or empty | Full directory sweep — lint all files, fix violations with parallel subagents |
19| `fix <slug>` | Single file fix — bring one file to zero violations |
20| `rules [category]` | Show all rules, optionally filtered by: seo, geo, content, technical, i18n |
21| `init` | Scaffold `geo-lint.config.ts` for a new project |
22| `report` | Generate a GEO/SEO health summary without fixing anything |
23
24---
25
26## Pre-Flight Checks (run before any workflow)
27
281. Verify Node.js >= 18: `node --version`
292. Check if `geo-lint.config.ts` (or `.mts`, `.mjs`, `.js`) exists in the project root.
30 If not, inform the user and suggest running `/geo-lint init`. Stop unless the
31 workflow is `init` or `rules`.
323. Check if `@ijonis/geo-lint` is in `devDependencies` in `package.json`.
33 If not, suggest: `npm install -D @ijonis/geo-lint`
34
35---
36
37## Workflow: audit
38
39Full directory sweep with parallel subagent fixing.
40
411. Run the linter:
42 ```bash
43 npx geo-lint --format=json
44 ```
45
462. Parse the JSON array. If empty `[]`, report "All content clean. Zero violations." Stop.
47
483. Group violations by the `file` field. Each unique value is one content piece.
49
504. Identify **human-escalation violations** and set them aside (do NOT fix these):
51 - `geo-low-citation-density` — requires real statistics; never fabricate numbers
52 - `image-not-found` — a real image file must exist on disk
53 - `broken-internal-link` — the target page may not exist yet
54 - `category-invalid` — valid categories come from `geo-lint.config.ts`
55
565. For each file with fixable violations, spawn a `geo-lint-fixer` subagent.
57 Pass each subagent:
58 - The file slug (from the `file` field)
59 - The filtered violations JSON (excluding human-escalation rules)
60 - The project root path
61
62 If more than 20 files have violations, batch into waves of 5-10.
63
646. After all subagents complete, run a final full lint:
65 ```bash
66 npx geo-lint --format=json
67 ```
68
697. Report summary:
70 - Files audited, violations fixed, violations remaining
71 - Human-escalation items requiring user attention (list each with rule name and file)
72 - Per-file status
73
74---
75
76## Workflow: fix <slug>
77
78Single file fix loop. The slug follows the format from `$ARGUMENTS` after "fix".
79
801. **Resolve the file path.** The violation `file` field uses the format
81 `<contentType>/<slug>` (e.g., `blog/my-post`). Default directory mappings:
82 - `blog` -> `content/blog/`
83 - `page` -> `content/pages/`
84 - `project` -> `content/projects/`
85
86 Find the file: search for `.mdx` or `.md` files matching the slug:
87 ```bash
88 find content/ -name "*.mdx" -o -name "*.md" | head -50
89 ```
90 Then grep for the matching slug in frontmatter if needed.
91
922. Run the linter and filter to this file:
93 ```bash
94 npx geo-lint --format=json
95 ```
96 Filter the JSON output to violations where `file` matches the target slug.
97
983. If no violations, report the file is clean. Stop.
99
1004. Set aside human-escalation violations (see list above).
101
1025. Fix all fixable violations in one edit pass:
103 - Read the file from disk
104 - For each violation, apply the fix described in its `suggestion` field
105 - Fix `error` severity items first, then `warning`
106 - Preserve the author's voice — restructure where needed, do not rewrite wholesale
107 - For GEO rules: add structure (tables, FAQ, question headings) without removing content
108
1096. Re-run the linter and filter to this file again.
110
1117. If violations remain, repeat from step 5. Maximum **5 iterations**.
112
1138. Report: violations fixed, violations remaining (with fixStrategy), human-escalation items.
114
115---
116
117## Workflow: rules
118
119Display the rule catalog.
120
1211. Run: `npx geo-lint --rules`
1222. Parse the JSON output.
1233. If a category was specified in `$ARGUMENTS` (seo, geo, content, technical, i18n),
124 filter to that category only.
1254. Format as a markdown table grouped by category:
126
127 | Rule | Severity | Fix Strategy |
128 |------|----------|-------------|
129
1305. Show summary counts: "92 rules total: 35 GEO, 32 SEO, 14 content, 8 technical, 3 i18n"
131
132---
133
134## Workflow: init
135
136Scaffold a `geo-lint.config.ts` for a new project.
137
1381. Check if config already exists. If yes, ask the user whether to overwrite.
139
1402. Auto-detect project structure:
141 - Content directories: `content/`, `src/content/`, `posts/`, `blog/`, `pages/`
142 - Image directories: `public/images/`, `static/images/`, `assets/images/`
143 - `package.json` `homepage` field for siteUrl
144 - Framework (Astro, Next.js, Hugo, etc.)
145
1463. Generate `geo-lint.config.ts`:
147 ```typescript
148 import { defineConfig } from '@ijonis/geo-lint';
149
150 export default defineConfig({
151 siteUrl: '<detected-or-ask-user>',
152 contentPaths: [
153 // auto-detected directories
154 ],
155 });
156 ```
157
1584. Install the package if not in devDependencies:
159 ```bash
160 npm install -D @ijonis/geo-lint
161 ```
162
1635. Run a test lint:
164 ```bash
165 npx geo-lint --format=json
166 ```
167
1686. Report setup result with next steps.
169
170---
171
172## Workflow: report
173
174Generate a health summary without fixing anything.
175
1761. Run: `npx geo-lint --format=json`
1772. Parse and compute:
178 - Total violations by severity (error vs warning)
179 - Violations by category (SEO, GEO, Content, Technical, i18n)
180 - Top 10 most common rules
181 - Files sorted by violation count (worst first)
182 - Clean files count
1833. Format as a markdown report with tables and summary statistics.
184
185---
186
187## Reference
188
189For the full rule catalog, fix patterns, and slug resolution details,
190see [reference.md](reference.md).