Command-line SEO analyzer with AI-powered suggestions for any website or framework.
Documentation Β· GitHub Β· Report Issue
Part of the Capyseo toolkit.
A powerful command-line SEO analyzer that scans your websites for issues and provides AI-powered suggestions to improve search rankings. Works with any framework or static site.
- π Analyze any website β Local build folders, live URLs, or crawl entire sites
- π€ AI-powered suggestions β Generate meta descriptions, alt text, and content improvements
- π Multiple output formats β Console, JSON, HTML reports, CSV, SARIF (for GitHub)
- π CI/CD integration β Fail builds on low SEO scores with exit codes
- π Generate SEO assets β Create sitemaps, robots.txt, and meta tags
- π Watch mode β Re-analyze automatically when files change
- Installation
- Quick Start
- Commands
- Output Formats
- AI-Powered Analysis
- CI/CD Integration
- Configuration File
- Examples
- Troubleshooting
Install globally to use the capyseo command anywhere:
# Using npm
npm install -g @capyseo/cli
# Using Bun
bun add -g @capyseo/cli
# Using pnpm
pnpm add -g @capyseo/cliUse npx or bunx to run without installing:
# Using npx
npx @capyseo/cli analyze ./dist
# Using bunx (faster)
bunx @capyseo/cli analyze ./distcapyseo --version
capyseo --helpAfter building your site (e.g., npm run build), analyze the output folder:
capyseo analyze ./distOutput:
Analyzing 5 pages...
/index.html
Score: 85/100
β [meta-description] Missing meta description
β Add <meta name="description" content="...">
! [open-graph] Missing og:image
β Add <meta property="og:image" content="...">
/about.html
Score: 92/100
β No issues found!
==================================================
Average Score: 88.5/100
Total Pages: 5
Total Issues: 3
capyseo analyze https://example.com# Crawl up to 50 pages following links
capyseo analyze https://example.com --max-pages 50# Using OpenAI (requires API key)
OPENAI_API_KEY=sk-xxx capyseo analyze ./dist --ai
# Using Ollama (free, local)
capyseo analyze ./dist --ai --ai-provider ollamaThe main command for SEO analysis.
capyseo analyze <target> [options]Arguments:
| Argument | Description | Examples |
|---|---|---|
target |
Path to folder, HTML file, or URL | ./dist, ./build/index.html, https://example.com |
Options:
| Option | Description | Default |
|---|---|---|
--ai |
Enable AI-powered suggestions | false |
--ai-provider <provider> |
AI provider: openai, anthropic, gemini, ollama |
openai |
--spa |
Enable JavaScript rendering for SPAs | false |
--format <format> |
Output format: console, json, html, csv, sarif |
console |
-o, --output <path> |
Write output to file | stdout |
--max-pages <n> |
Maximum pages to crawl | 100 |
--ci |
CI mode: exit with code 1 on issues | false |
--min-score <n> |
Minimum acceptable score (with --ci) |
0 |
--no-live |
Disable HTTP checks for broken links | enabled |
--exclude <patterns> |
Glob patterns to exclude | none |
--config <path> |
Path to config file | auto-detected |
-v, --verbose |
Show detailed output | false |
-q, --quiet |
Only show errors | false |
Examples:
# Basic analysis
capyseo analyze ./dist
# With AI suggestions using OpenAI
OPENAI_API_KEY=xxx capyseo analyze ./dist --ai
# With AI using local Ollama
capyseo analyze ./dist --ai --ai-provider ollama
# Generate HTML report
capyseo analyze ./dist --format html -o report.html
# CI mode with minimum score
capyseo analyze ./dist --ci --min-score 80
# Analyze SPA (renders JavaScript)
capyseo analyze https://spa.example.com --spa
# Exclude certain paths
capyseo analyze ./dist --exclude "admin/*" --exclude "api/*"Generate SEO-related files.
Generate an XML sitemap from a folder or by crawling a URL.
capyseo generate sitemap <target> --origin <url> [options]| Option | Description | Default |
|---|---|---|
--origin <url> |
Base URL for sitemap (required) | - |
-o, --output <path> |
Output file path | sitemap.xml |
--changefreq <freq> |
Default change frequency | weekly |
--priority <n> |
Default priority (0.0-1.0) | 0.5 |
Example:
# Generate sitemap from build folder
capyseo generate sitemap ./dist --origin https://example.com -o ./dist/sitemap.xml
# Crawl and generate
capyseo generate sitemap https://example.com --origin https://example.comOutput (sitemap.xml):
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://example.com/</loc>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://example.com/about</loc>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
</urlset>Generate a robots.txt file.
capyseo generate robots [options]| Option | Description | Default |
|---|---|---|
-o, --output <path> |
Output file path | robots.txt |
--sitemap <url> |
Sitemap URL to include | - |
--disallow <paths> |
Paths to disallow (can be repeated) | - |
Example:
capyseo generate robots -o ./dist/robots.txt \
--sitemap https://example.com/sitemap.xml \
--disallow /admin \
--disallow /apiOutput (robots.txt):
User-agent: *
Allow: /
Disallow: /admin
Disallow: /api
Sitemap: https://example.com/sitemap.xml
Generate meta tags using AI (requires API key).
capyseo generate meta <url> [options]| Option | Description | Default |
|---|---|---|
--ai-provider <provider> |
AI provider | openai |
Example:
OPENAI_API_KEY=xxx capyseo generate meta https://example.com/aboutOutput:
<!-- Suggested meta tags for https://example.com/about -->
<title>About Us β Example Company | Who We Are</title>
<meta name="description" content="Learn about Example Company's mission, team, and values. We've been helping customers succeed since 2010.">
<!-- Open Graph -->
<meta property="og:title" content="About Us β Example Company">
<meta property="og:description" content="Learn about Example Company's mission, team, and values.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://example.com/about">
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="About Us β Example Company">
<meta name="twitter:description" content="Learn about Example Company's mission, team, and values.">Watch for file changes and re-analyze automatically.
capyseo watch <directory> [options]| Option | Description | Default |
|---|---|---|
--debounce <ms> |
Debounce delay | 500 |
All analyze options |
Same as analyze command | - |
Example:
# Watch build folder during development
capyseo watch ./dist
# Watch with AI suggestions
OPENAI_API_KEY=xxx capyseo watch ./dist --aiCreate a configuration file interactively.
capyseo initThis creates a capyseo.config.js file in your project root.
Human-readable output for terminal:
capyseo analyze ./distMachine-readable JSON for scripting:
capyseo analyze ./dist --format json -o report.json{
"summary": {
"averageScore": 85,
"totalPages": 5,
"totalIssues": 12
},
"reports": [
{
"url": "/index.html",
"score": 85,
"issues": [
{
"rule": "meta-description",
"severity": "error",
"message": "Missing meta description"
}
]
}
]
}Interactive HTML report with charts:
capyseo analyze ./dist --format html -o report.htmlFeatures:
- Score overview chart
- Filter by severity
- Search issues
- Expandable details
- Print-friendly
Spreadsheet-compatible format:
capyseo analyze ./dist --format csv -o report.csvSARIF format for GitHub Security tab:
capyseo analyze ./dist --format sarif -o report.sarifThen upload in GitHub Actions:
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: report.sarifCapyseo can use AI to generate smart suggestions for:
- Meta descriptions β Based on page content
- Image alt text β Based on surrounding context
- Title improvements β More engaging, keyword-rich titles
- Content recommendations β Readability and keyword suggestions
# Set API key
export OPENAI_API_KEY=sk-your-key-here
# Run with AI
capyseo analyze ./dist --ai --ai-provider openaiexport ANTHROPIC_API_KEY=sk-ant-your-key-here
capyseo analyze ./dist --ai --ai-provider anthropicexport GEMINI_API_KEY=your-key-here
capyseo analyze ./dist --ai --ai-provider gemini- Install Ollama: https://ollama.ai
- Pull a model:
ollama pull deepseek-r1:8b
- Run analysis:
capyseo analyze ./dist --ai --ai-provider ollama
Recommended Ollama models by hardware:
| Hardware | Model |
|---|---|
| RTX 4090 (24GB) | deepseek-r1:70b |
| RTX 4070 (12GB) | qwen3-coder:14b |
| RTX 3070 (8GB) | deepseek-r1:8b |
| M4 Pro (48GB) | deepseek-r1:70b |
| M4 (16GB) | qwen3-coder:14b |
| CPU only | phi-3:3.8b |
# .github/workflows/seo.yml
name: SEO Check
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
seo:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install dependencies
run: bun install
- name: Build site
run: bun run build
- name: Run SEO analysis
run: bunx @capyseo/cli analyze ./dist --ci --min-score 80
- name: Upload SARIF report
if: always()
run: bunx @capyseo/cli analyze ./dist --format sarif -o seo.sarif
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: seo.sarif# .gitlab-ci.yml
seo:
stage: test
image: oven/bun:latest
script:
- bun install
- bun run build
- bunx @capyseo/cli analyze ./dist --ci --min-score 80
artifacts:
reports:
sast: seo.sarif
paths:
- seo.sarif| Code | Meaning |
|---|---|
0 |
Success (or no --ci flag) |
1 |
Score below --min-score or errors found |
Create capyseo.config.js in your project root:
// capyseo.config.js
export default {
// Rule configuration
rules: {
// Change severity levels
'meta-title': { severity: 'error' },
'meta-description': { severity: 'error' },
'open-graph': { severity: 'warning' },
// Disable rules
'twitter-card': { enabled: false },
// Custom thresholds
'content-length': { minWords: 300 },
'meta-title-length': { min: 30, max: 60 },
},
// AI configuration
ai: {
provider: 'openai', // 'openai' | 'anthropic' | 'gemini' | 'ollama'
enabled: false, // Set to true, or use --ai flag
},
// Path patterns to exclude
exclude: [
'admin/*',
'api/*',
'*.json',
],
// CI/CD settings
ci: {
minScore: 80,
failOn: ['error'], // 'error' | 'warning' | 'info'
},
// Output settings
output: {
format: 'console',
file: null,
},
};# After running `next build`
capyseo analyze ./out# After running `astro build`
capyseo analyze ./dist# After running `vite build`
capyseo analyze ./buildUsing Husky:
# .husky/pre-commit
bunx @capyseo/cli analyze ./dist --ci --min-score 70# Baseline
capyseo analyze ./dist --format json -o before.json
# Make changes, rebuild
# Compare
capyseo analyze ./dist --format json -o after.json
diff before.json after.jsonMake sure the path points to a folder containing .html files or a URL:
# Wrong: pointing to source folder
capyseo analyze ./src
# Right: pointing to build output
capyseo analyze ./dist-
Check your API key is set:
echo $OPENAI_API_KEY
-
Make sure you're using the
--aiflag:capyseo analyze ./dist --ai
Your site might render content with JavaScript. Enable SPA mode:
# Install Playwright first
npm install playwright
npx playwright install chromium
# Then analyze
capyseo analyze https://spa.example.com --spaDisable live HTTP checks if you don't need them:
capyseo analyze ./dist --no-live| Package | Description |
|---|---|
| @capyseo/core | Core analysis engine (programmatic API) |
| @capyseo/sveltekit | SvelteKit integration with Vite plugin & hooks |
- π Documentation
- βοΈ Email
- π¬ Discussions
- π Issues
See CONTRIBUTING.md for development setup and guidelines.
MIT Β© Capyseo