{"id":51162150,"url":"https://github.com/IJONIS/geo-lint","last_synced_at":"2026-07-14T23:00:44.053Z","repository":{"id":339164734,"uuid":"1160736689","full_name":"IJONIS/geo-lint","owner":"IJONIS","description":"The first open-source GEO linter. 92 rules for SEO, GEO, and content quality — built for AI agents to run, read, fix, and re-lint automatically.","archived":false,"fork":false,"pushed_at":"2026-03-19T10:43:47.000Z","size":1418,"stargazers_count":16,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-20T03:52:36.165Z","etag":null,"topics":["aeo","ai-agent","ai-agent-tools","ai-search","ai-search-optimization","claude","claude-code","claude-code-skills","claude-skill","cli","cli-app","cli-tool","codex","content","generative-engine-optimization","geo","linter","markdown","mdx","seo"],"latest_commit_sha":null,"homepage":"https://ijonis.com","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/IJONIS.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-18T10:06:46.000Z","updated_at":"2026-03-19T15:51:43.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/IJONIS/geo-lint","commit_stats":null,"previous_names":["ijonis/geo-lint"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/IJONIS/geo-lint","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IJONIS%2Fgeo-lint","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IJONIS%2Fgeo-lint/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IJONIS%2Fgeo-lint/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IJONIS%2Fgeo-lint/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/IJONIS","download_url":"https://codeload.github.com/IJONIS/geo-lint/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IJONIS%2Fgeo-lint/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35482263,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-14T02:00:06.603Z","response_time":114,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aeo","ai-agent","ai-agent-tools","ai-search","ai-search-optimization","claude","claude-code","claude-code-skills","claude-skill","cli","cli-app","cli-tool","codex","content","generative-engine-optimization","geo","linter","markdown","mdx","seo"],"created_at":"2026-06-26T15:00:26.467Z","updated_at":"2026-07-14T23:00:44.046Z","avatar_url":"https://github.com/IJONIS.png","language":"TypeScript","funding_links":[],"categories":["工具"],"sub_categories":["开源工具"],"readme":"# @ijonis/geo-lint\n\n**The first open-source linter for GEO (Generative Engine Optimization). Validates your content for AI search visibility -- then lets your AI agent fix it automatically.**\n\n[![npm version](https://img.shields.io/npm/v/@ijonis/geo-lint)](https://www.npmjs.com/package/@ijonis/geo-lint)\n[![CI](https://img.shields.io/github/actions/workflow/status/ijonis/geo-lint/ci.yml?branch=main\u0026label=CI)](https://github.com/IJONIS/geo-lint/actions)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/IJONIS/geo-lint/blob/main/LICENSE)\n[![Claude Code Skill](https://img.shields.io/badge/Claude_Code-Skill-blueviolet)](https://github.com/IJONIS/geo-lint)\n\n![geo-lint demo](docs/demo.gif)\n\n---\n\n## Use with Claude Code\n\nInstall the geo-lint skill in one command:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/IJONIS/geo-lint/main/install.sh | bash\n```\n\nThen in any Claude Code session:\n\n```\n/geo-lint audit        # Full sweep — find and fix all violations\n/geo-lint fix \u003cslug\u003e   # Fix a single content file\n/geo-lint rules        # Show all 97 rules with fix strategies\n/geo-lint init         # Set up geo-lint.config.ts for a new project\n/geo-lint report       # Generate a GEO/SEO health summary\n```\n\nThe skill runs an autonomous lint-fix loop: scan your content, read structured violations, fix them using each violation's `suggestion` field, and re-lint until clean. Parallel subagents handle multiple files simultaneously.\n\n### Content Creation Pipeline\n\nThe install also adds `/content-creator` -- a self-configuring content pipeline that creates SEO \u0026 GEO-optimized content matched to your project:\n\n```\n/content-creator setup      # Auto-discover your project + configure brand voice\n/content-creator create      # Create content with keyword research + validation\n/content-creator voice       # Analyze and adjust brand voice\n/content-creator calendar    # Plan monthly content calendar\n/content-creator refresh     # Update config when your project evolves\n```\n\nOn first use, the skill scans your project to learn its framework, content schema, categories, and authors. It then asks a few questions about your brand voice and audience. From that point on, every piece of content is created with full project awareness and validated against geo-lint's 97 rules until clean -- zero manual intervention for mechanical quality.\n\nOr paste this into **any** AI agent (Claude Code, Cursor, Windsurf, Copilot):\n\n```\nRun npx geo-lint --format=json, then fix every violation using each\nviolation's suggestion field. Re-run until the output is [].\n```\n\n---\n\n## Why this exists\n\nI run multiple content-heavy sites and there was no deterministic way to validate whether my content was actually optimized -- not \"probably fine,\" but actually checked against concrete rules. SEO linters exist, but they're either paid SaaS, not automatable, or completely ignore the structural patterns that AI search engines use when deciding what to cite.\n\nSo I built one. **GEO (Generative Engine Optimization)** is the practice of structuring content so it gets cited by ChatGPT, Perplexity, Google AI Overviews, and Gemini. Traditional SEO gets you into search result lists. GEO gets you **cited in AI-generated answers**. Both matter -- and no existing open-source tool checks for GEO.\n\nThe goal was simple: install one tool, point your AI agent at it, and walk away. The agent runs the linter, reads the JSON violations, fixes the content, re-lints until clean -- across an entire site, no manual input. One command, both SEO and GEO validated.\n\n**97 rules: 36 GEO, 34 SEO, 14 content quality, 10 technical, 3 i18n.** Readability analysis inspired by Yoast SEO. We researched the current state of GEO and AEO to make sure the rules reflect what actually gets content cited -- not outdated advice.\n\n---\n\n## Quick Start\n\n```bash\nnpm install -D @ijonis/geo-lint\n```\n\nCreate `geo-lint.config.ts`:\n\n```typescript\nimport { defineConfig } from '@ijonis/geo-lint';\n\nexport default defineConfig({\n  siteUrl: 'https://your-site.com',\n  contentPaths: [{\n    dir: 'content/blog',\n    type: 'blog',\n    urlPrefix: '/blog/',\n  }],\n});\n```\n\nRun it:\n\n```bash\nnpx geo-lint                  # Human-readable output\nnpx geo-lint --format=json    # Machine-readable for AI agents\n```\n\nWorks out of the box with `.md`/`.mdx` files. For Astro, HTML, or other formats, see [Custom Adapters](docs/custom-adapters.md).\n\n---\n\n## GEO in Action\n\nThree examples of what GEO rules catch and how to fix them. See [all 7 core GEO rules with examples](docs/geo-rules.md).\n\n### `geo-weak-lead-sentences`\n\nAI systems use the first sentence after a heading as the citation snippet. Filler openings get skipped.\n\n**Before:**\n```markdown\n## What is serverless computing?\n\nIn this section, we will take a closer look at serverless computing and\nwhat it means for modern development teams.\n```\n\n**After:**\n```markdown\n## What is serverless computing?\n\nServerless computing is a cloud execution model where the provider\ndynamically allocates compute resources per request, eliminating the\nneed to provision or manage servers.\n```\n\n### `geo-low-citation-density`\n\nAI answers prefer citable claims backed by numbers. Vague statements get passed over.\n\n**Before:**\n```markdown\nAdopting TypeScript significantly reduces bugs in large codebases.\n```\n\n**After:**\n```markdown\nAdopting TypeScript reduces production bugs by 38% in codebases\nexceeding 50,000 lines of code, according to a 2023 study by\nMicrosoft Research.\n```\n\n### `geo-missing-table`\n\nTables are highly structured and unambiguous -- ideal for AI extraction. Content with comparison tables is cited significantly more often than equivalent prose.\n\n**Before:**\n```markdown\nReact is component-based and uses a virtual DOM. Vue is also\ncomponent-based but uses a reactivity system. Svelte compiles\ncomponents at build time.\n```\n\n**After:**\n```markdown\n| Framework | Architecture     | Bundle Size | Learning Curve |\n|-----------|------------------|-------------|----------------|\n| React     | Virtual DOM      | 42 KB       | Moderate       |\n| Vue       | Reactivity proxy | 33 KB       | Low            |\n| Svelte    | Compile-time     | 1.6 KB      | Low            |\n```\n\n---\n\n## All 97 Rules\n\n| Category | Rules | Severity Mix | Focus |\n|----------|-------|-------------|-------|\n| SEO | 34 | 6 errors, 28 warnings | Titles, descriptions, headings, slugs, OG images, canonical URLs, keywords, links, schema, sameAs, service pages |\n| Content | 14 | 2 errors, 12 warnings | Word count, readability, dates, categories, jargon density, repetition, vocabulary diversity, transition words, sentence variety |\n| Technical | 10 | 3 errors, 7 warnings | Broken links, image files, trailing slashes, external URLs, performance, feeds, llms.txt |\n| i18n | 3 | 0 errors, 3 warnings | Translation pairs, locale metadata |\n| GEO | 36 | 0 errors, 36 warnings | AI citation readiness: E-E-A-T signals, content structure, freshness, RAG optimization, author entity type |\n\nSee the [complete rule reference](docs/rules.md) with descriptions and severity for every rule.\n\n---\n\n## Works With\n\n**AI agents**: Claude Code, Cursor, Windsurf, GitHub Copilot -- any agent that can run shell commands and edit files\n\n**Content formats**: Markdown and MDX out of the box. Astro, HTML, Nuxt, any CMS via [custom adapters](docs/custom-adapters.md)\n\n**Build tools**: Runs in any CI pipeline. JSON output for programmatic consumption\n\n**Runtime**: Node.js \u003e= 18. Zero peer dependencies\n\n---\n\n## Agent-First Design\n\nThis linter is **deterministic** -- same content in, same violations out, every time. Your AI agent provides the creativity to fix the content; geo-lint provides the guardrails to verify it's correct. The loop runs until violations hit zero.\n\n### Claude Code Plugin\n\nInstall the skill and use `/geo-lint audit` to validate and fix your entire content directory automatically. The skill runs the full lint-fix loop with parallel subagents -- one per file. See [Use with Claude Code](#use-with-claude-code) above.\n\n### Any AI Agent\n\nPaste this into **Cursor**, **Windsurf**, **Copilot**, or any AI coding agent:\n\n```\nRun npx geo-lint --format=json, then fix every violation in the reported\nfiles using each violation's suggestion field. After fixing, re-run the\nlinter and repeat until the output is an empty array []. Preserve the\nauthor's voice -- restructure, don't rewrite.\n```\n\nThat's it. The agent will iterate automatically.\n\n### What the agent sees\n\n```bash\nnpx geo-lint --format=json\n```\n\n```json\n[\n  {\n    \"file\": \"blog/my-post\",\n    \"field\": \"body\",\n    \"rule\": \"geo-no-question-headings\",\n    \"severity\": \"warning\",\n    \"message\": \"Only 1/5 (20%) H2/H3 headings are question-formatted\",\n    \"suggestion\": \"Rephrase some headings as questions (e.g., 'How does X work?') to improve LLM snippet extraction.\"\n  }\n]\n```\n\nEvery violation includes:\n- **`suggestion`** -- plain-language fix instruction the agent follows directly\n- **`fixStrategy`** -- machine-readable fix pattern for the rule\n- **`file`, `field`, `line`** -- exact location so the agent edits the right place\n\nAn empty array `[]` means zero violations -- the content is clean. The agent knows to stop.\n\nSee the full [Agent Integration Guide](docs/agent-integration.md) for per-agent setup, a Claude Code skill, and handling edge cases.\n\n---\n\n## Configuration\n\nOverride any rule's severity or disable it entirely:\n\n```typescript\nimport { defineConfig } from '@ijonis/geo-lint';\n\nexport default defineConfig({\n  siteUrl: 'https://your-site.com',\n  contentPaths: [{ dir: 'content/blog', type: 'blog', urlPrefix: '/blog/' }],\n  rules: {\n    'geo-missing-table': 'off',     // disable a rule\n    'orphan-content': 'error',      // upgrade to error\n  },\n});\n```\n\nSee the full [Configuration Reference](docs/configuration.md) for all options, thresholds, and GEO-specific settings.\n\n---\n\n## Extend It\n\n### Custom Adapters\n\nLint any content source -- Astro, HTML, a headless CMS -- by writing a small adapter:\n\n```typescript\nimport { lint, createAdapter } from '@ijonis/geo-lint';\n\nconst adapter = createAdapter(async (projectRoot) =\u003e {\n  // Map your content into ContentItem objects\n  return [{ title, slug, description, body, permalink, contentType, filePath, rawContent }];\n});\n\nawait lint({ adapter });\n```\n\nSee the [Custom Adapters Guide](docs/custom-adapters.md) for the full `ContentItem` interface and ready-to-use examples for Astro, HTML, and CMS sources.\n\n### Programmatic API\n\n```typescript\nimport { lint, lintQuiet } from '@ijonis/geo-lint';\n\nconst exitCode = await lint({ format: 'json' });          // with console output\nconst results = await lintQuiet({ projectRoot: '.' });     // raw LintResult[]\n```\n\nSee the [API Reference](docs/api.md) for all options and types.\n\n---\n\n## CLI Reference\n\n```\nUsage:\n  geo-lint [options]\n\nOptions:\n  --root=\u003cpath\u003e     Project root directory (default: cwd)\n  --config=\u003cpath\u003e   Explicit config file path\n  --format=pretty   Human-readable colored output (default)\n  --format=json     Machine-readable JSON output (for AI agents)\n  --rules           List all registered rules with fix strategies\n  -h, --help        Show this help message\n  -v, --version     Show version\n```\n\n---\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, testing, and how to add new rules. Changes are tracked in the [CHANGELOG](CHANGELOG.md).\n\n**Questions or ideas?** Open a [GitHub Discussion](https://github.com/IJONIS/geo-lint/discussions).\n**Bugs or feature requests?** Open a [GitHub Issue](https://github.com/IJONIS/geo-lint/issues).\n\n## License\n\n[MIT](LICENSE)\n\n---\n\nBuilt by [IJONIS](https://ijonis.com) -- we help companies become visible to AI search engines. This linter is extracted from the same toolchain we use on production client content.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FIJONIS%2Fgeo-lint","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FIJONIS%2Fgeo-lint","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FIJONIS%2Fgeo-lint/lists"}