context-linter 2.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- context_linter-2.0.1/LICENSE +21 -0
- context_linter-2.0.1/PKG-INFO +423 -0
- context_linter-2.0.1/README.md +380 -0
- context_linter-2.0.1/pyproject.toml +98 -0
- context_linter-2.0.1/setup.cfg +4 -0
- context_linter-2.0.1/src/context_cli/__init__.py +8 -0
- context_linter-2.0.1/src/context_cli/cli/__init__.py +1 -0
- context_linter-2.0.1/src/context_cli/cli/audit.py +590 -0
- context_linter-2.0.1/src/context_cli/cli/benchmark.py +145 -0
- context_linter-2.0.1/src/context_cli/cli/compare.py +35 -0
- context_linter-2.0.1/src/context_cli/cli/generate.py +152 -0
- context_linter-2.0.1/src/context_cli/cli/history.py +82 -0
- context_linter-2.0.1/src/context_cli/cli/leaderboard.py +124 -0
- context_linter-2.0.1/src/context_cli/cli/mcp_cmd.py +16 -0
- context_linter-2.0.1/src/context_cli/cli/radar.py +72 -0
- context_linter-2.0.1/src/context_cli/cli/retail.py +97 -0
- context_linter-2.0.1/src/context_cli/cli/watch.py +130 -0
- context_linter-2.0.1/src/context_cli/core/__init__.py +0 -0
- context_linter-2.0.1/src/context_cli/core/auditor.py +406 -0
- context_linter-2.0.1/src/context_cli/core/batch.py +107 -0
- context_linter-2.0.1/src/context_cli/core/benchmark/__init__.py +12 -0
- context_linter-2.0.1/src/context_cli/core/benchmark/cost.py +58 -0
- context_linter-2.0.1/src/context_cli/core/benchmark/dispatcher.py +76 -0
- context_linter-2.0.1/src/context_cli/core/benchmark/judge.py +90 -0
- context_linter-2.0.1/src/context_cli/core/benchmark/loader.py +84 -0
- context_linter-2.0.1/src/context_cli/core/benchmark/metrics.py +103 -0
- context_linter-2.0.1/src/context_cli/core/cache.py +34 -0
- context_linter-2.0.1/src/context_cli/core/checks/__init__.py +21 -0
- context_linter-2.0.1/src/context_cli/core/checks/content.py +128 -0
- context_linter-2.0.1/src/context_cli/core/checks/content_usage.py +66 -0
- context_linter-2.0.1/src/context_cli/core/checks/eeat.py +183 -0
- context_linter-2.0.1/src/context_cli/core/checks/llms_txt.py +58 -0
- context_linter-2.0.1/src/context_cli/core/checks/robots.py +77 -0
- context_linter-2.0.1/src/context_cli/core/checks/rsl.py +96 -0
- context_linter-2.0.1/src/context_cli/core/checks/schema.py +42 -0
- context_linter-2.0.1/src/context_cli/core/ci/__init__.py +1 -0
- context_linter-2.0.1/src/context_cli/core/ci/baseline.py +133 -0
- context_linter-2.0.1/src/context_cli/core/ci/thresholds.py +73 -0
- context_linter-2.0.1/src/context_cli/core/compare.py +73 -0
- context_linter-2.0.1/src/context_cli/core/config.py +58 -0
- context_linter-2.0.1/src/context_cli/core/cost.py +42 -0
- context_linter-2.0.1/src/context_cli/core/crawler.py +188 -0
- context_linter-2.0.1/src/context_cli/core/discovery.py +251 -0
- context_linter-2.0.1/src/context_cli/core/generate/__init__.py +17 -0
- context_linter-2.0.1/src/context_cli/core/generate/batch.py +90 -0
- context_linter-2.0.1/src/context_cli/core/generate/compiler.py +133 -0
- context_linter-2.0.1/src/context_cli/core/generate/llm.py +23 -0
- context_linter-2.0.1/src/context_cli/core/generate/profiles.py +85 -0
- context_linter-2.0.1/src/context_cli/core/generate/prompts.py +108 -0
- context_linter-2.0.1/src/context_cli/core/history.py +117 -0
- context_linter-2.0.1/src/context_cli/core/llm.py +135 -0
- context_linter-2.0.1/src/context_cli/core/models.py +977 -0
- context_linter-2.0.1/src/context_cli/core/plugin.py +109 -0
- context_linter-2.0.1/src/context_cli/core/radar/__init__.py +22 -0
- context_linter-2.0.1/src/context_cli/core/radar/analyzer.py +185 -0
- context_linter-2.0.1/src/context_cli/core/radar/domains.py +81 -0
- context_linter-2.0.1/src/context_cli/core/radar/parser.py +124 -0
- context_linter-2.0.1/src/context_cli/core/radar/query.py +73 -0
- context_linter-2.0.1/src/context_cli/core/recommend.py +234 -0
- context_linter-2.0.1/src/context_cli/core/regression.py +81 -0
- context_linter-2.0.1/src/context_cli/core/retail/__init__.py +5 -0
- context_linter-2.0.1/src/context_cli/core/retail/auditor.py +74 -0
- context_linter-2.0.1/src/context_cli/core/retail/feed_spec.py +100 -0
- context_linter-2.0.1/src/context_cli/core/retail/parsers/__init__.py +83 -0
- context_linter-2.0.1/src/context_cli/core/retail/parsers/amazon.py +198 -0
- context_linter-2.0.1/src/context_cli/core/retail/parsers/base.py +47 -0
- context_linter-2.0.1/src/context_cli/core/retail/parsers/blibli.py +195 -0
- context_linter-2.0.1/src/context_cli/core/retail/parsers/generic.py +228 -0
- context_linter-2.0.1/src/context_cli/core/retail/parsers/lazada.py +137 -0
- context_linter-2.0.1/src/context_cli/core/retail/parsers/shopee.py +147 -0
- context_linter-2.0.1/src/context_cli/core/retail/parsers/tiktok_shop.py +193 -0
- context_linter-2.0.1/src/context_cli/core/retail/parsers/tokopedia.py +146 -0
- context_linter-2.0.1/src/context_cli/core/retail/parsers/zalora.py +199 -0
- context_linter-2.0.1/src/context_cli/core/retail/scoring.py +262 -0
- context_linter-2.0.1/src/context_cli/core/retry.py +78 -0
- context_linter-2.0.1/src/context_cli/core/scoring.py +256 -0
- context_linter-2.0.1/src/context_cli/core/webhook.py +42 -0
- context_linter-2.0.1/src/context_cli/formatters/__init__.py +1 -0
- context_linter-2.0.1/src/context_cli/formatters/ci_summary.py +122 -0
- context_linter-2.0.1/src/context_cli/formatters/compare.py +94 -0
- context_linter-2.0.1/src/context_cli/formatters/csv.py +88 -0
- context_linter-2.0.1/src/context_cli/formatters/html.py +300 -0
- context_linter-2.0.1/src/context_cli/formatters/leaderboard.py +130 -0
- context_linter-2.0.1/src/context_cli/formatters/markdown.py +132 -0
- context_linter-2.0.1/src/context_cli/formatters/recommendations.py +106 -0
- context_linter-2.0.1/src/context_cli/formatters/rich_output.py +198 -0
- context_linter-2.0.1/src/context_cli/formatters/verbose.py +206 -0
- context_linter-2.0.1/src/context_cli/formatters/verbose_panels.py +414 -0
- context_linter-2.0.1/src/context_cli/main.py +30 -0
- context_linter-2.0.1/src/context_cli/py.typed +0 -0
- context_linter-2.0.1/src/context_cli/server.py +219 -0
- context_linter-2.0.1/src/context_linter.egg-info/PKG-INFO +423 -0
- context_linter-2.0.1/src/context_linter.egg-info/SOURCES.txt +176 -0
- context_linter-2.0.1/src/context_linter.egg-info/dependency_links.txt +1 -0
- context_linter-2.0.1/src/context_linter.egg-info/entry_points.txt +2 -0
- context_linter-2.0.1/src/context_linter.egg-info/requires.txt +20 -0
- context_linter-2.0.1/src/context_linter.egg-info/top_level.txt +1 -0
- context_linter-2.0.1/tests/test_answer_first.py +114 -0
- context_linter-2.0.1/tests/test_auditor.py +250 -0
- context_linter-2.0.1/tests/test_auditor_coverage.py +514 -0
- context_linter-2.0.1/tests/test_batch.py +465 -0
- context_linter-2.0.1/tests/test_benchmark_cli.py +476 -0
- context_linter-2.0.1/tests/test_benchmark_cost.py +235 -0
- context_linter-2.0.1/tests/test_benchmark_dispatcher.py +287 -0
- context_linter-2.0.1/tests/test_benchmark_judge.py +402 -0
- context_linter-2.0.1/tests/test_benchmark_loader.py +283 -0
- context_linter-2.0.1/tests/test_benchmark_metrics.py +335 -0
- context_linter-2.0.1/tests/test_cache.py +80 -0
- context_linter-2.0.1/tests/test_ci_baseline.py +756 -0
- context_linter-2.0.1/tests/test_ci_features.py +184 -0
- context_linter-2.0.1/tests/test_ci_summary.py +311 -0
- context_linter-2.0.1/tests/test_ci_thresholds.py +682 -0
- context_linter-2.0.1/tests/test_cli.py +140 -0
- context_linter-2.0.1/tests/test_cli_coverage.py +865 -0
- context_linter-2.0.1/tests/test_cli_errors.py +78 -0
- context_linter-2.0.1/tests/test_compare.py +462 -0
- context_linter-2.0.1/tests/test_config.py +232 -0
- context_linter-2.0.1/tests/test_content_boundaries.py +101 -0
- context_linter-2.0.1/tests/test_content_chunks.py +102 -0
- context_linter-2.0.1/tests/test_content_usage.py +141 -0
- context_linter-2.0.1/tests/test_crawler_coverage.py +221 -0
- context_linter-2.0.1/tests/test_crawler_errors.py +81 -0
- context_linter-2.0.1/tests/test_custom_bots.py +236 -0
- context_linter-2.0.1/tests/test_discovery.py +143 -0
- context_linter-2.0.1/tests/test_discovery_coverage.py +315 -0
- context_linter-2.0.1/tests/test_eeat.py +184 -0
- context_linter-2.0.1/tests/test_formatters.py +319 -0
- context_linter-2.0.1/tests/test_generate_batch.py +417 -0
- context_linter-2.0.1/tests/test_generate_batch_cli.py +373 -0
- context_linter-2.0.1/tests/test_generate_cli.py +161 -0
- context_linter-2.0.1/tests/test_generate_compiler.py +268 -0
- context_linter-2.0.1/tests/test_generate_llm.py +174 -0
- context_linter-2.0.1/tests/test_generate_models.py +164 -0
- context_linter-2.0.1/tests/test_generate_profiles.py +111 -0
- context_linter-2.0.1/tests/test_generate_prompts.py +135 -0
- context_linter-2.0.1/tests/test_github_summary.py +90 -0
- context_linter-2.0.1/tests/test_heading_structure.py +141 -0
- context_linter-2.0.1/tests/test_history.py +228 -0
- context_linter-2.0.1/tests/test_history_cli.py +177 -0
- context_linter-2.0.1/tests/test_html_report.py +488 -0
- context_linter-2.0.1/tests/test_leaderboard_cli.py +475 -0
- context_linter-2.0.1/tests/test_leaderboard_formatter.py +502 -0
- context_linter-2.0.1/tests/test_llms_txt_edge_cases.py +286 -0
- context_linter-2.0.1/tests/test_mcp_expansion.py +218 -0
- context_linter-2.0.1/tests/test_mcp_server.py +149 -0
- context_linter-2.0.1/tests/test_models.py +268 -0
- context_linter-2.0.1/tests/test_page_weight_edges.py +63 -0
- context_linter-2.0.1/tests/test_plugin.py +259 -0
- context_linter-2.0.1/tests/test_radar_analyzer.py +379 -0
- context_linter-2.0.1/tests/test_radar_cli.py +489 -0
- context_linter-2.0.1/tests/test_radar_domains.py +159 -0
- context_linter-2.0.1/tests/test_radar_parser.py +232 -0
- context_linter-2.0.1/tests/test_radar_query.py +186 -0
- context_linter-2.0.1/tests/test_readability.py +130 -0
- context_linter-2.0.1/tests/test_recommend.py +402 -0
- context_linter-2.0.1/tests/test_regression.py +160 -0
- context_linter-2.0.1/tests/test_retail_auditor.py +292 -0
- context_linter-2.0.1/tests/test_retail_cli.py +479 -0
- context_linter-2.0.1/tests/test_retail_feed_spec.py +189 -0
- context_linter-2.0.1/tests/test_retail_parsers.py +1010 -0
- context_linter-2.0.1/tests/test_retail_parsers2.py +1273 -0
- context_linter-2.0.1/tests/test_retail_scoring.py +617 -0
- context_linter-2.0.1/tests/test_retry.py +138 -0
- context_linter-2.0.1/tests/test_robots_edge_cases.py +100 -0
- context_linter-2.0.1/tests/test_rsl.py +152 -0
- context_linter-2.0.1/tests/test_save_flag.py +233 -0
- context_linter-2.0.1/tests/test_schema_edge_cases.py +105 -0
- context_linter-2.0.1/tests/test_schema_weighting.py +117 -0
- context_linter-2.0.1/tests/test_scoring_integration.py +158 -0
- context_linter-2.0.1/tests/test_scoring_lint.py +329 -0
- context_linter-2.0.1/tests/test_shared_llm.py +253 -0
- context_linter-2.0.1/tests/test_site_audit.py +192 -0
- context_linter-2.0.1/tests/test_sitemap_parsing.py +109 -0
- context_linter-2.0.1/tests/test_spider.py +124 -0
- context_linter-2.0.1/tests/test_timeout.py +318 -0
- context_linter-2.0.1/tests/test_verbose_output.py +1701 -0
- context_linter-2.0.1/tests/test_watch.py +254 -0
- context_linter-2.0.1/tests/test_webhook.py +377 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 AEO-CLI Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: context-linter
|
|
3
|
+
Version: 2.0.1
|
|
4
|
+
Summary: Context CLI — LLM Readiness Linter for token efficiency and RAG readiness
|
|
5
|
+
Author: Hansel Wahjono
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/hanselhansel/context-cli
|
|
8
|
+
Project-URL: Repository, https://github.com/hanselhansel/context-cli
|
|
9
|
+
Project-URL: Issues, https://github.com/hanselhansel/context-cli/issues
|
|
10
|
+
Keywords: llm,ai,linter,token-waste,rag,robots-txt,schema-org,llms-txt
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
19
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: typer>=0.9
|
|
25
|
+
Requires-Dist: rich>=13.0
|
|
26
|
+
Requires-Dist: httpx>=0.27
|
|
27
|
+
Requires-Dist: beautifulsoup4>=4.12
|
|
28
|
+
Requires-Dist: pydantic>=2.0
|
|
29
|
+
Requires-Dist: crawl4ai>=0.4
|
|
30
|
+
Requires-Dist: fastmcp>=2.0
|
|
31
|
+
Requires-Dist: pyyaml>=6.0
|
|
32
|
+
Provides-Extra: generate
|
|
33
|
+
Requires-Dist: litellm>=1.40; extra == "generate"
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
36
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
37
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
38
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
39
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
40
|
+
Requires-Dist: litellm>=1.40; extra == "dev"
|
|
41
|
+
Requires-Dist: types-PyYAML>=6.0; extra == "dev"
|
|
42
|
+
Dynamic: license-file
|
|
43
|
+
|
|
44
|
+
# Context CLI
|
|
45
|
+
|
|
46
|
+
[](https://github.com/hanselhansel/context-cli/actions/workflows/test.yml)
|
|
47
|
+
[](https://www.python.org/downloads/)
|
|
48
|
+
[](LICENSE)
|
|
49
|
+
[](https://pypi.org/project/context-cli/)
|
|
50
|
+
|
|
51
|
+
**Lint any URL for LLM readiness. Get a 0-100 score for token efficiency, RAG readiness, and LLM extraction quality.**
|
|
52
|
+
|
|
53
|
+
## What is Context CLI?
|
|
54
|
+
|
|
55
|
+
Context CLI is an LLM Readiness Linter that checks how well a URL is structured for AI consumption. As LLM-powered search engines, RAG pipelines, and AI agents become primary consumers of web content, your pages need to be optimized for token efficiency, structured data extraction, and machine-readable formatting.
|
|
56
|
+
|
|
57
|
+
Context CLI analyzes your content across four pillars and returns a structured score from 0 to 100.
|
|
58
|
+
|
|
59
|
+
## Features
|
|
60
|
+
|
|
61
|
+
- **Robots.txt AI bot access** -- checks 13 AI crawlers (GPTBot, ClaudeBot, DeepSeek-AI, Grok, and more)
|
|
62
|
+
- **llms.txt & llms-full.txt** -- detects both standard and extended LLM instruction files
|
|
63
|
+
- **Schema.org JSON-LD** -- extracts and evaluates structured data with high-value type weighting (Product, Article, FAQ, HowTo)
|
|
64
|
+
- **Content density** -- measures useful content vs. boilerplate with readability scoring, heading structure analysis, and answer-first detection
|
|
65
|
+
- **Batch mode** -- lint multiple URLs from a file with `--file` and configurable `--concurrency`
|
|
66
|
+
- **Custom bot list** -- override default bots with `--bots` for targeted checks
|
|
67
|
+
- **Verbose output** -- detailed per-pillar breakdown with scoring explanations and recommendations
|
|
68
|
+
- **Rich CLI output** -- formatted tables and scores via Rich
|
|
69
|
+
- **JSON / CSV / Markdown output** -- machine-readable results for pipelines
|
|
70
|
+
- **MCP server** -- expose the linter as a tool for AI agents via FastMCP
|
|
71
|
+
- **Context Compiler** -- LLM-powered `llms.txt` and `schema.jsonld` generation, with batch mode for multiple URLs
|
|
72
|
+
- **CI/CD integration** -- `--fail-under` threshold, `--fail-on-blocked-bots`, per-pillar thresholds, baseline regression detection, GitHub Step Summary
|
|
73
|
+
- **GitHub Action** -- composite action for CI pipelines with baseline support
|
|
74
|
+
- **Citation Radar** -- query AI models to see what they cite and recommend, with brand tracking and domain classification
|
|
75
|
+
- **Share-of-Recommendation Benchmark** -- track how often AI models mention and recommend your brand vs competitors, with LLM-as-judge analysis
|
|
76
|
+
|
|
77
|
+
## Installation
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install context-linter
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Context CLI uses a headless browser for content extraction. After installing, run:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
crawl4ai-setup
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Development install
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
git clone https://github.com/your-org/context-cli.git
|
|
93
|
+
cd context-cli
|
|
94
|
+
pip install -e ".[dev]"
|
|
95
|
+
crawl4ai-setup
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Quick Start
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
context-cli lint example.com
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
This runs a full lint and prints a Rich-formatted report with your LLM readiness score.
|
|
105
|
+
|
|
106
|
+
## CLI Usage
|
|
107
|
+
|
|
108
|
+
### Single Page Lint
|
|
109
|
+
|
|
110
|
+
Lint only the specified URL (skip multi-page discovery):
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
context-cli lint example.com --single
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Multi-Page Site Lint (default)
|
|
117
|
+
|
|
118
|
+
Discover pages via sitemap/spider and lint up to 10 pages:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
context-cli lint example.com
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Limit Pages
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
context-cli lint example.com --max-pages 5
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### JSON Output
|
|
131
|
+
|
|
132
|
+
Get structured JSON for CI pipelines, dashboards, or scripting:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
context-cli lint example.com --json
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### CSV / Markdown Output
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
context-cli lint example.com --format csv
|
|
142
|
+
context-cli lint example.com --format markdown
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Verbose Mode
|
|
146
|
+
|
|
147
|
+
Show detailed per-pillar breakdown with scoring explanations:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
context-cli lint example.com --single --verbose
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Timeout
|
|
154
|
+
|
|
155
|
+
Set the HTTP timeout (default: 15 seconds):
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
context-cli lint example.com --timeout 30
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Custom Bot List
|
|
162
|
+
|
|
163
|
+
Override the default 13 bots with a custom list:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
context-cli lint example.com --bots "GPTBot,ClaudeBot,PerplexityBot"
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Batch Mode
|
|
170
|
+
|
|
171
|
+
Lint multiple URLs from a file (one URL per line, `.txt` or `.csv`):
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
context-cli lint --file urls.txt
|
|
175
|
+
context-cli lint --file urls.txt --concurrency 5
|
|
176
|
+
context-cli lint --file urls.txt --format csv
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### CI Mode
|
|
180
|
+
|
|
181
|
+
Fail the build if the score is below a threshold:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
context-cli lint example.com --fail-under 60
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Fail if any AI bot is blocked:
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
context-cli lint example.com --fail-on-blocked-bots
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
#### Per-Pillar Thresholds
|
|
194
|
+
|
|
195
|
+
Gate CI on individual pillar scores:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
context-cli lint example.com --robots-min 20 --content-min 30 --overall-min 60
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Available: `--robots-min`, `--schema-min`, `--content-min`, `--llms-min`, `--overall-min`.
|
|
202
|
+
|
|
203
|
+
#### Baseline Regression Detection
|
|
204
|
+
|
|
205
|
+
Save a baseline and detect score regressions in future lints:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
# Save current scores as baseline
|
|
209
|
+
context-cli lint example.com --single --save-baseline .context-baseline.json
|
|
210
|
+
|
|
211
|
+
# Compare against baseline (exit 1 if any pillar drops > 5 points)
|
|
212
|
+
context-cli lint example.com --single --baseline .context-baseline.json
|
|
213
|
+
|
|
214
|
+
# Custom regression threshold
|
|
215
|
+
context-cli lint example.com --single --baseline .context-baseline.json --regression-threshold 10
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Exit codes: 0 = pass, 1 = score below threshold or regression detected, 2 = bots blocked.
|
|
219
|
+
|
|
220
|
+
When running in GitHub Actions, a markdown summary is automatically written to `$GITHUB_STEP_SUMMARY`.
|
|
221
|
+
|
|
222
|
+
### Quiet Mode
|
|
223
|
+
|
|
224
|
+
Suppress output, exit code 0 if score >= 50, 1 otherwise:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
context-cli lint example.com --quiet
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Use `--fail-under` with `--quiet` to override the default threshold:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
context-cli lint example.com --quiet --fail-under 70
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Start MCP server
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
context-cli mcp
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Launches a FastMCP stdio server exposing the linter as a tool for AI agents.
|
|
243
|
+
|
|
244
|
+
## MCP Integration
|
|
245
|
+
|
|
246
|
+
To use Context CLI as a tool in Claude Desktop, add this to your Claude Desktop config (`claude_desktop_config.json`):
|
|
247
|
+
|
|
248
|
+
```json
|
|
249
|
+
{
|
|
250
|
+
"mcpServers": {
|
|
251
|
+
"context-cli": {
|
|
252
|
+
"command": "context-cli",
|
|
253
|
+
"args": ["mcp"]
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Once configured, Claude can call the `audit_url` tool directly to check any URL's LLM readiness.
|
|
260
|
+
|
|
261
|
+
## Context Compiler (Generate)
|
|
262
|
+
|
|
263
|
+
Generate `llms.txt` and `schema.jsonld` files from any URL using LLM analysis:
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
pip install context-linter[generate]
|
|
267
|
+
context-cli generate example.com
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
This crawls the URL, sends the content to an LLM, and writes optimized files to `./context-output/`.
|
|
271
|
+
|
|
272
|
+
### Batch Generate
|
|
273
|
+
|
|
274
|
+
Generate assets for multiple URLs from a file:
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
context-cli generate-batch urls.txt
|
|
278
|
+
context-cli generate-batch urls.txt --concurrency 5 --profile ecommerce
|
|
279
|
+
context-cli generate-batch urls.txt --json
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Each URL's output goes to a subdirectory under `--output-dir`.
|
|
283
|
+
|
|
284
|
+
### BYOK (Bring Your Own Key)
|
|
285
|
+
|
|
286
|
+
The generate command auto-detects your LLM provider from environment variables:
|
|
287
|
+
|
|
288
|
+
| Priority | Env Variable | Model Used |
|
|
289
|
+
|----------|-------------|------------|
|
|
290
|
+
| 1 | `OPENAI_API_KEY` | gpt-4o-mini |
|
|
291
|
+
| 2 | `ANTHROPIC_API_KEY` | claude-3-haiku-20240307 |
|
|
292
|
+
| 3 | Ollama running locally | ollama/llama3.2 |
|
|
293
|
+
|
|
294
|
+
Override with `--model`:
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
context-cli generate example.com --model gpt-4o
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Industry Profiles
|
|
301
|
+
|
|
302
|
+
Tailor the output with `--profile`:
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
context-cli generate example.com --profile saas
|
|
306
|
+
context-cli generate example.com --profile ecommerce
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Available: `generic`, `cpg`, `saas`, `ecommerce`, `blog`.
|
|
310
|
+
|
|
311
|
+
## Citation Radar
|
|
312
|
+
|
|
313
|
+
Query AI models to see what they cite and recommend for any search prompt:
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
pip install context-linter[generate]
|
|
317
|
+
context-cli radar "best project management tools" --brand Asana --brand Monday --model gpt-4o-mini
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Options:
|
|
321
|
+
- `--brand/-b`: Brand name to track (repeatable)
|
|
322
|
+
- `--model/-m`: LLM model to query (repeatable, default: gpt-4o-mini)
|
|
323
|
+
- `--runs/-r`: Runs per model for statistical significance
|
|
324
|
+
- `--json`: Output as JSON
|
|
325
|
+
|
|
326
|
+
## Share-of-Recommendation Benchmark
|
|
327
|
+
|
|
328
|
+
Track how AI models mention and recommend your brand across multiple prompts:
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
pip install context-linter[generate]
|
|
332
|
+
context-cli benchmark prompts.txt -b "YourBrand" -c "Competitor1" -c "Competitor2"
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Options:
|
|
336
|
+
- `prompts.txt`: CSV (with `prompt,category,intent` columns) or plain text (one prompt per line)
|
|
337
|
+
- `--brand/-b`: Target brand to track (required)
|
|
338
|
+
- `--competitor/-c`: Competitor brand (repeatable)
|
|
339
|
+
- `--model/-m`: LLM model to query (repeatable, default: gpt-4o-mini)
|
|
340
|
+
- `--runs/-r`: Runs per model per prompt (default: 3)
|
|
341
|
+
- `--yes/-y`: Skip cost confirmation prompt
|
|
342
|
+
- `--json`: Output as JSON
|
|
343
|
+
|
|
344
|
+
## GitHub Action
|
|
345
|
+
|
|
346
|
+
Use Context CLI in your CI pipeline:
|
|
347
|
+
|
|
348
|
+
```yaml
|
|
349
|
+
- name: Run Context Lint
|
|
350
|
+
uses: hanselhansel/context-cli@main
|
|
351
|
+
with:
|
|
352
|
+
url: 'https://your-site.com'
|
|
353
|
+
fail-under: '60'
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
With baseline regression detection:
|
|
357
|
+
|
|
358
|
+
```yaml
|
|
359
|
+
- name: Run Context Lint
|
|
360
|
+
uses: hanselhansel/context-cli@main
|
|
361
|
+
with:
|
|
362
|
+
url: 'https://your-site.com'
|
|
363
|
+
baseline-file: '.context-baseline.json'
|
|
364
|
+
save-baseline: '.context-baseline.json'
|
|
365
|
+
regression-threshold: '5'
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
The action sets up Python, installs context-cli, and runs the lint. Outputs `score` and `report-json` for downstream steps. See [docs/ci-integration.md](docs/ci-integration.md) for full documentation.
|
|
369
|
+
|
|
370
|
+
## Score Breakdown
|
|
371
|
+
|
|
372
|
+
Context CLI returns a score from 0 to 100, composed of four pillars:
|
|
373
|
+
|
|
374
|
+
| Pillar | Max Points | What it measures |
|
|
375
|
+
|---|---|---|
|
|
376
|
+
| Content density | 40 | Quality and depth of extractable text content |
|
|
377
|
+
| Robots.txt AI bot access | 25 | Whether AI crawlers are allowed in robots.txt |
|
|
378
|
+
| Schema.org JSON-LD | 25 | Structured data markup (Product, Article, FAQ, etc.) |
|
|
379
|
+
| llms.txt presence | 10 | Whether a /llms.txt file exists for LLM guidance |
|
|
380
|
+
|
|
381
|
+
### Scoring rationale (2026-02-18)
|
|
382
|
+
|
|
383
|
+
The weights reflect how AI search engines (ChatGPT, Perplexity, Claude) actually consume web content:
|
|
384
|
+
|
|
385
|
+
- **Content density (40 pts)** is weighted highest because it's what LLMs extract and cite when answering questions. Rich, well-structured content with headings and lists gives AI better material to work with.
|
|
386
|
+
- **Robots.txt (25 pts)** is the gatekeeper -- if a bot is blocked, it literally cannot crawl. It's critical but largely binary (either you're blocking or you're not).
|
|
387
|
+
- **Schema.org (25 pts)** provides structured "cheat sheets" that help AI understand entities. High-value types (Product, Article, FAQ, HowTo, Recipe) receive bonus weighting. Valuable but not required for citation.
|
|
388
|
+
- **llms.txt (10 pts)** is an emerging standard. Both `/llms.txt` and `/llms-full.txt` are checked. No major AI search engine heavily weights it yet, but it signals forward-thinking AI readiness.
|
|
389
|
+
|
|
390
|
+
## AI Bots Checked
|
|
391
|
+
|
|
392
|
+
Context CLI checks access rules for 13 AI crawlers:
|
|
393
|
+
|
|
394
|
+
- GPTBot
|
|
395
|
+
- ChatGPT-User
|
|
396
|
+
- Google-Extended
|
|
397
|
+
- ClaudeBot
|
|
398
|
+
- PerplexityBot
|
|
399
|
+
- Amazonbot
|
|
400
|
+
- OAI-SearchBot
|
|
401
|
+
- DeepSeek-AI
|
|
402
|
+
- Grok
|
|
403
|
+
- Meta-ExternalAgent
|
|
404
|
+
- cohere-ai
|
|
405
|
+
- AI2Bot
|
|
406
|
+
- ByteSpider
|
|
407
|
+
|
|
408
|
+
## Development
|
|
409
|
+
|
|
410
|
+
```bash
|
|
411
|
+
# Install with dev dependencies
|
|
412
|
+
pip install -e ".[dev]"
|
|
413
|
+
|
|
414
|
+
# Run tests
|
|
415
|
+
pytest
|
|
416
|
+
|
|
417
|
+
# Lint
|
|
418
|
+
ruff check src/ tests/
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
## License
|
|
422
|
+
|
|
423
|
+
MIT
|