seofleet-cli 0.2.0__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.
Files changed (61) hide show
  1. seofleet_cli-0.2.0/.gitignore +8 -0
  2. seofleet_cli-0.2.0/LICENSE +21 -0
  3. seofleet_cli-0.2.0/PKG-INFO +181 -0
  4. seofleet_cli-0.2.0/README.md +146 -0
  5. seofleet_cli-0.2.0/pyproject.toml +69 -0
  6. seofleet_cli-0.2.0/src/seofleet/__init__.py +104 -0
  7. seofleet_cli-0.2.0/src/seofleet/checks/__init__.py +83 -0
  8. seofleet_cli-0.2.0/src/seofleet/checks/geo/__init__.py +0 -0
  9. seofleet_cli-0.2.0/src/seofleet/checks/geo/ai_crawler_directives.py +89 -0
  10. seofleet_cli-0.2.0/src/seofleet/checks/geo/content_extraction.py +72 -0
  11. seofleet_cli-0.2.0/src/seofleet/checks/geo/faq_schema.py +58 -0
  12. seofleet_cli-0.2.0/src/seofleet/checks/geo/link_header.py +116 -0
  13. seofleet_cli-0.2.0/src/seofleet/checks/geo/llms_txt.py +29 -0
  14. seofleet_cli-0.2.0/src/seofleet/checks/geo/markdown_negotiation.py +40 -0
  15. seofleet_cli-0.2.0/src/seofleet/checks/geo/organization_schema.py +89 -0
  16. seofleet_cli-0.2.0/src/seofleet/checks/geo/speakable_schema.py +66 -0
  17. seofleet_cli-0.2.0/src/seofleet/checks/geo/structured_data.py +53 -0
  18. seofleet_cli-0.2.0/src/seofleet/checks/technical/__init__.py +0 -0
  19. seofleet_cli-0.2.0/src/seofleet/checks/technical/canonical.py +48 -0
  20. seofleet_cli-0.2.0/src/seofleet/checks/technical/heading_structure.py +54 -0
  21. seofleet_cli-0.2.0/src/seofleet/checks/technical/image_alt.py +53 -0
  22. seofleet_cli-0.2.0/src/seofleet/checks/technical/image_weight.py +111 -0
  23. seofleet_cli-0.2.0/src/seofleet/checks/technical/meta_description.py +48 -0
  24. seofleet_cli-0.2.0/src/seofleet/checks/technical/open_graph.py +53 -0
  25. seofleet_cli-0.2.0/src/seofleet/checks/technical/redirect_chain.py +60 -0
  26. seofleet_cli-0.2.0/src/seofleet/checks/technical/robots_meta_directives.py +70 -0
  27. seofleet_cli-0.2.0/src/seofleet/checks/technical/robots_txt.py +39 -0
  28. seofleet_cli-0.2.0/src/seofleet/checks/technical/sitemap_xml.py +78 -0
  29. seofleet_cli-0.2.0/src/seofleet/checks/technical/title.py +52 -0
  30. seofleet_cli-0.2.0/src/seofleet/checks/technical/twitter_card.py +64 -0
  31. seofleet_cli-0.2.0/src/seofleet/cli.py +122 -0
  32. seofleet_cli-0.2.0/src/seofleet/cli_lib.py +106 -0
  33. seofleet_cli-0.2.0/src/seofleet/config.py +95 -0
  34. seofleet_cli-0.2.0/src/seofleet/errors.py +20 -0
  35. seofleet_cli-0.2.0/src/seofleet/fetch_utils.py +301 -0
  36. seofleet_cli-0.2.0/src/seofleet/fleet.py +152 -0
  37. seofleet_cli-0.2.0/src/seofleet/format.py +102 -0
  38. seofleet_cli-0.2.0/src/seofleet/html_util.py +162 -0
  39. seofleet_cli-0.2.0/src/seofleet/init.py +86 -0
  40. seofleet_cli-0.2.0/src/seofleet/py.typed +0 -0
  41. seofleet_cli-0.2.0/src/seofleet/report_file.py +49 -0
  42. seofleet_cli-0.2.0/src/seofleet/runner.py +35 -0
  43. seofleet_cli-0.2.0/src/seofleet/site_resources.py +119 -0
  44. seofleet_cli-0.2.0/src/seofleet/slugify.py +25 -0
  45. seofleet_cli-0.2.0/src/seofleet/types.py +84 -0
  46. seofleet_cli-0.2.0/tests/__init__.py +0 -0
  47. seofleet_cli-0.2.0/tests/conftest.py +143 -0
  48. seofleet_cli-0.2.0/tests/test_checks_geo.py +370 -0
  49. seofleet_cli-0.2.0/tests/test_checks_technical.py +500 -0
  50. seofleet_cli-0.2.0/tests/test_cli.py +230 -0
  51. seofleet_cli-0.2.0/tests/test_config.py +69 -0
  52. seofleet_cli-0.2.0/tests/test_e2e.py +60 -0
  53. seofleet_cli-0.2.0/tests/test_fetch_utils.py +267 -0
  54. seofleet_cli-0.2.0/tests/test_fleet.py +151 -0
  55. seofleet_cli-0.2.0/tests/test_format.py +61 -0
  56. seofleet_cli-0.2.0/tests/test_html_util.py +67 -0
  57. seofleet_cli-0.2.0/tests/test_init.py +49 -0
  58. seofleet_cli-0.2.0/tests/test_report_file.py +48 -0
  59. seofleet_cli-0.2.0/tests/test_runner.py +42 -0
  60. seofleet_cli-0.2.0/tests/test_site_resources.py +115 -0
  61. seofleet_cli-0.2.0/tests/test_slugify.py +25 -0
@@ -0,0 +1,8 @@
1
+ .venv/
2
+ .venv-freshinstall/
3
+ dist/
4
+ build/
5
+ *.egg-info/
6
+ __pycache__/
7
+ *.pyc
8
+ .pytest_cache/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rudrendu Paul
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,181 @@
1
+ Metadata-Version: 2.4
2
+ Name: seofleet-cli
3
+ Version: 0.2.0
4
+ Summary: Zero-config, cross-platform SEO and GEO (generative engine optimization) checker: 12 checks against a live site, plus multi-site fleet mode, in pure Python with no extra runtime toolchain.
5
+ Project-URL: Homepage, https://github.com/RudrenduPaul/SeoFleet
6
+ Project-URL: Repository, https://github.com/RudrenduPaul/SeoFleet
7
+ Project-URL: Bug Tracker, https://github.com/RudrenduPaul/SeoFleet/issues
8
+ Project-URL: Changelog, https://github.com/RudrenduPaul/SeoFleet/blob/main/CHANGELOG.md
9
+ Project-URL: Documentation, https://github.com/RudrenduPaul/SeoFleet/blob/main/docs/getting-started.md
10
+ Project-URL: Author - Rudrendu Paul, https://github.com/RudrenduPaul
11
+ Project-URL: Author - Sourav Nandy, https://github.com/Sourav-nandy-ai
12
+ Author: Rudrendu Paul, Sourav Nandy
13
+ License-Expression: MIT
14
+ License-File: LICENSE
15
+ Keywords: agent-native,cli,developer-tools,generative-engine-optimization,geo,seo,website-audit
16
+ Classifier: Development Status :: 3 - Alpha
17
+ Classifier: Environment :: Console
18
+ Classifier: Intended Audience :: Developers
19
+ Classifier: License :: OSI Approved :: MIT License
20
+ Classifier: Operating System :: OS Independent
21
+ Classifier: Programming Language :: Python :: 3
22
+ Classifier: Programming Language :: Python :: 3.9
23
+ Classifier: Programming Language :: Python :: 3.10
24
+ Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Programming Language :: Python :: 3.12
26
+ Classifier: Programming Language :: Python :: 3.13
27
+ Classifier: Topic :: Internet :: WWW/HTTP :: Site Management
28
+ Classifier: Topic :: Software Development :: Quality Assurance
29
+ Requires-Python: >=3.9
30
+ Provides-Extra: dev
31
+ Requires-Dist: build<2,>=1.0; extra == 'dev'
32
+ Requires-Dist: pytest<9,>=7.0; extra == 'dev'
33
+ Requires-Dist: twine<7,>=5.0; extra == 'dev'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # seofleet-cli (Python)
37
+
38
+ Zero-config SEO and GEO (generative engine optimization) checker: 21 checks
39
+ against a live site, plus a multi-site fleet mode for agencies checking
40
+ several client sites at once, in pure Python with no extra runtime
41
+ toolchain -- no headless browser, no separate interpreter to provision.
42
+
43
+ [![PyPI version](https://img.shields.io/pypi/v/seofleet-cli.svg)](https://pypi.org/project/seofleet-cli/)
44
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/RudrenduPaul/SeoFleet/blob/main/LICENSE)
45
+ [![Python versions](https://img.shields.io/pypi/pyversions/seofleet-cli.svg)](https://pypi.org/project/seofleet-cli/)
46
+ [![CI](https://github.com/RudrenduPaul/SeoFleet/actions/workflows/ci.yml/badge.svg)](https://github.com/RudrenduPaul/SeoFleet/actions/workflows/ci.yml)
47
+ [![npm version](https://img.shields.io/npm/v/seofleet-cli.svg)](https://www.npmjs.com/package/seofleet-cli)
48
+
49
+ ## Why this exists
50
+
51
+ SeoFleet checks a website for 21 technical-SEO and GEO issues --
52
+ title/meta description length, canonical tags, robots.txt/sitemap.xml
53
+ reachability (with a robots.txt `Sitemap:` fallback), heading structure,
54
+ image alt coverage and weight, Open Graph and Twitter Card tags, meta
55
+ robots directives, redirect-chain health, JSON-LD structured data, llms.txt,
56
+ AI-crawler directives (training and search crawlers tracked separately --
57
+ GPTBot/OAI-SearchBot, ClaudeBot/Claude-SearchBot, PerplexityBot,
58
+ Google-Extended, Applebot-Extended), FAQ schema, Speakable schema,
59
+ Organization schema, Markdown content negotiation, an RFC 8288 Link header,
60
+ and content-extraction friendliness -- and reports PASS/WARN/FAIL with a
61
+ fix suggestion for anything short of a clean pass. This package is the
62
+ Python distribution of the tool: a genuine, independent port of the npm
63
+ CLI's logic, not a wrapper around the Node binary. It ships with **zero
64
+ runtime dependencies** -- HTML parsing and HTTP fetching both use only the
65
+ Python standard library.
66
+
67
+ ## Install
68
+
69
+ ```bash
70
+ pip install seofleet-cli
71
+ ```
72
+
73
+ or with [uv](https://docs.astral.sh/uv/):
74
+
75
+ ```bash
76
+ uv add seofleet-cli
77
+ ```
78
+
79
+ The complementary JS/TS distribution installs from npm:
80
+ `npm install -g seofleet-cli` -- see the
81
+ [project README](https://github.com/RudrenduPaul/SeoFleet#readme) for that
82
+ package. Both packages read the same 21-check spec and are intended to
83
+ report the same PASS/WARN/FAIL verdicts for the same site; neither is
84
+ deprecated in favor of the other.
85
+
86
+ ## Quickstart
87
+
88
+ ```bash
89
+ seofleet init ./my-site --site-url https://example.com
90
+ seofleet check ./my-site
91
+ ```
92
+
93
+ `init` scaffolds a `seofleet.json` config (and a Claude Code skill file) in
94
+ the target directory; `check` runs all 21 checks against the configured
95
+ `siteUrl` and prints a PASS/WARN/FAIL line per check plus a summary. Pass
96
+ `--json` before the subcommand for structured output an agent can parse:
97
+
98
+ ```bash
99
+ seofleet --json check ./my-site
100
+ ```
101
+
102
+ Or call the library directly (the agent-native path, no subprocess):
103
+
104
+ ```python
105
+ from seofleet import load_site, run_checks, ALL_CHECKS
106
+
107
+ ctx = load_site("https://example.com")
108
+ results = run_checks(ALL_CHECKS, ctx)
109
+ for r in results:
110
+ print(f"[{r.status}] ({r.category}) {r.name}: {r.message}")
111
+ ```
112
+
113
+ ## How it works
114
+
115
+ ```
116
+ seofleet.json -> site URL -> fetch homepage + robots.txt + sitemap.xml + llms.txt (parallel)
117
+ -> 21 checks (12 technical + 9 GEO) run against the shared fetched context
118
+ -> PASS / WARN / FAIL per check -> exit code (0 clean / 1 any FAIL / 2 usage error)
119
+ ```
120
+
121
+ Full data model, the 21 checks explained, and fleet-mode semantics are in
122
+ [docs/concepts.md](https://github.com/RudrenduPaul/SeoFleet/blob/main/docs/concepts.md)
123
+ and [docs/getting-started.md](https://github.com/RudrenduPaul/SeoFleet/blob/main/docs/getting-started.md).
124
+ The checks are reimplemented as genuine Python logic against the same
125
+ check contract the npm package uses (`Check.run(ctx) -> CheckResult`) --
126
+ see those docs for what each check actually verifies.
127
+
128
+ ## Fleet mode
129
+
130
+ ```bash
131
+ seofleet fleet ./fleet.json
132
+ ```
133
+
134
+ Runs the full 21-check suite against every site declared in a local JSON
135
+ manifest (`{"sites": [{"name": ..., "path": ...}]}`) in one invocation --
136
+ local filesystem only, no SSH, no remote execution. Aimed at agencies or
137
+ teams checking several client repos side by side. Add `--out-dir ./reports`
138
+ to also write one auto-named report file per site, named from the
139
+ manifest's `name` field.
140
+
141
+ ## CI integration
142
+
143
+ ```yaml
144
+ - uses: actions/checkout@v4
145
+ - uses: actions/setup-python@v5
146
+ with:
147
+ python-version: '3.12'
148
+ - run: pip install seofleet-cli
149
+ - run: seofleet check ./my-site --json > results.json
150
+ ```
151
+
152
+ Full walkthrough in
153
+ [docs/integrations/ci.md](https://github.com/RudrenduPaul/SeoFleet/blob/main/docs/integrations/ci.md).
154
+
155
+ ## Security
156
+
157
+ seofleet's fetch layer only ever dials `http(s)`, follows redirects
158
+ manually one hop at a time, refuses to follow a redirect whose `Location`
159
+ targets a non-`http(s)` scheme, and bounds the redirect chain at 5 hops so
160
+ a redirect loop can't hang the process -- see
161
+ [SECURITY.md](https://github.com/RudrenduPaul/SeoFleet/blob/main/SECURITY.md)
162
+ for the full policy and how to report a vulnerability. **Honest note**:
163
+ this project does not currently publish SLSA provenance, Sigstore
164
+ signatures, or an SBOM, and has no OpenSSF Scorecard badge set up -- none
165
+ of that infrastructure exists yet for either distribution, so it isn't
166
+ claimed here.
167
+
168
+ ## Contributing
169
+
170
+ See [CONTRIBUTING.md](https://github.com/RudrenduPaul/SeoFleet/blob/main/CONTRIBUTING.md).
171
+
172
+ ```bash
173
+ cd python
174
+ python3 -m venv .venv && source .venv/bin/activate
175
+ pip install -e ".[dev]"
176
+ pytest
177
+ ```
178
+
179
+ ## License
180
+
181
+ MIT, see [LICENSE](https://github.com/RudrenduPaul/SeoFleet/blob/main/LICENSE).
@@ -0,0 +1,146 @@
1
+ # seofleet-cli (Python)
2
+
3
+ Zero-config SEO and GEO (generative engine optimization) checker: 21 checks
4
+ against a live site, plus a multi-site fleet mode for agencies checking
5
+ several client sites at once, in pure Python with no extra runtime
6
+ toolchain -- no headless browser, no separate interpreter to provision.
7
+
8
+ [![PyPI version](https://img.shields.io/pypi/v/seofleet-cli.svg)](https://pypi.org/project/seofleet-cli/)
9
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/RudrenduPaul/SeoFleet/blob/main/LICENSE)
10
+ [![Python versions](https://img.shields.io/pypi/pyversions/seofleet-cli.svg)](https://pypi.org/project/seofleet-cli/)
11
+ [![CI](https://github.com/RudrenduPaul/SeoFleet/actions/workflows/ci.yml/badge.svg)](https://github.com/RudrenduPaul/SeoFleet/actions/workflows/ci.yml)
12
+ [![npm version](https://img.shields.io/npm/v/seofleet-cli.svg)](https://www.npmjs.com/package/seofleet-cli)
13
+
14
+ ## Why this exists
15
+
16
+ SeoFleet checks a website for 21 technical-SEO and GEO issues --
17
+ title/meta description length, canonical tags, robots.txt/sitemap.xml
18
+ reachability (with a robots.txt `Sitemap:` fallback), heading structure,
19
+ image alt coverage and weight, Open Graph and Twitter Card tags, meta
20
+ robots directives, redirect-chain health, JSON-LD structured data, llms.txt,
21
+ AI-crawler directives (training and search crawlers tracked separately --
22
+ GPTBot/OAI-SearchBot, ClaudeBot/Claude-SearchBot, PerplexityBot,
23
+ Google-Extended, Applebot-Extended), FAQ schema, Speakable schema,
24
+ Organization schema, Markdown content negotiation, an RFC 8288 Link header,
25
+ and content-extraction friendliness -- and reports PASS/WARN/FAIL with a
26
+ fix suggestion for anything short of a clean pass. This package is the
27
+ Python distribution of the tool: a genuine, independent port of the npm
28
+ CLI's logic, not a wrapper around the Node binary. It ships with **zero
29
+ runtime dependencies** -- HTML parsing and HTTP fetching both use only the
30
+ Python standard library.
31
+
32
+ ## Install
33
+
34
+ ```bash
35
+ pip install seofleet-cli
36
+ ```
37
+
38
+ or with [uv](https://docs.astral.sh/uv/):
39
+
40
+ ```bash
41
+ uv add seofleet-cli
42
+ ```
43
+
44
+ The complementary JS/TS distribution installs from npm:
45
+ `npm install -g seofleet-cli` -- see the
46
+ [project README](https://github.com/RudrenduPaul/SeoFleet#readme) for that
47
+ package. Both packages read the same 21-check spec and are intended to
48
+ report the same PASS/WARN/FAIL verdicts for the same site; neither is
49
+ deprecated in favor of the other.
50
+
51
+ ## Quickstart
52
+
53
+ ```bash
54
+ seofleet init ./my-site --site-url https://example.com
55
+ seofleet check ./my-site
56
+ ```
57
+
58
+ `init` scaffolds a `seofleet.json` config (and a Claude Code skill file) in
59
+ the target directory; `check` runs all 21 checks against the configured
60
+ `siteUrl` and prints a PASS/WARN/FAIL line per check plus a summary. Pass
61
+ `--json` before the subcommand for structured output an agent can parse:
62
+
63
+ ```bash
64
+ seofleet --json check ./my-site
65
+ ```
66
+
67
+ Or call the library directly (the agent-native path, no subprocess):
68
+
69
+ ```python
70
+ from seofleet import load_site, run_checks, ALL_CHECKS
71
+
72
+ ctx = load_site("https://example.com")
73
+ results = run_checks(ALL_CHECKS, ctx)
74
+ for r in results:
75
+ print(f"[{r.status}] ({r.category}) {r.name}: {r.message}")
76
+ ```
77
+
78
+ ## How it works
79
+
80
+ ```
81
+ seofleet.json -> site URL -> fetch homepage + robots.txt + sitemap.xml + llms.txt (parallel)
82
+ -> 21 checks (12 technical + 9 GEO) run against the shared fetched context
83
+ -> PASS / WARN / FAIL per check -> exit code (0 clean / 1 any FAIL / 2 usage error)
84
+ ```
85
+
86
+ Full data model, the 21 checks explained, and fleet-mode semantics are in
87
+ [docs/concepts.md](https://github.com/RudrenduPaul/SeoFleet/blob/main/docs/concepts.md)
88
+ and [docs/getting-started.md](https://github.com/RudrenduPaul/SeoFleet/blob/main/docs/getting-started.md).
89
+ The checks are reimplemented as genuine Python logic against the same
90
+ check contract the npm package uses (`Check.run(ctx) -> CheckResult`) --
91
+ see those docs for what each check actually verifies.
92
+
93
+ ## Fleet mode
94
+
95
+ ```bash
96
+ seofleet fleet ./fleet.json
97
+ ```
98
+
99
+ Runs the full 21-check suite against every site declared in a local JSON
100
+ manifest (`{"sites": [{"name": ..., "path": ...}]}`) in one invocation --
101
+ local filesystem only, no SSH, no remote execution. Aimed at agencies or
102
+ teams checking several client repos side by side. Add `--out-dir ./reports`
103
+ to also write one auto-named report file per site, named from the
104
+ manifest's `name` field.
105
+
106
+ ## CI integration
107
+
108
+ ```yaml
109
+ - uses: actions/checkout@v4
110
+ - uses: actions/setup-python@v5
111
+ with:
112
+ python-version: '3.12'
113
+ - run: pip install seofleet-cli
114
+ - run: seofleet check ./my-site --json > results.json
115
+ ```
116
+
117
+ Full walkthrough in
118
+ [docs/integrations/ci.md](https://github.com/RudrenduPaul/SeoFleet/blob/main/docs/integrations/ci.md).
119
+
120
+ ## Security
121
+
122
+ seofleet's fetch layer only ever dials `http(s)`, follows redirects
123
+ manually one hop at a time, refuses to follow a redirect whose `Location`
124
+ targets a non-`http(s)` scheme, and bounds the redirect chain at 5 hops so
125
+ a redirect loop can't hang the process -- see
126
+ [SECURITY.md](https://github.com/RudrenduPaul/SeoFleet/blob/main/SECURITY.md)
127
+ for the full policy and how to report a vulnerability. **Honest note**:
128
+ this project does not currently publish SLSA provenance, Sigstore
129
+ signatures, or an SBOM, and has no OpenSSF Scorecard badge set up -- none
130
+ of that infrastructure exists yet for either distribution, so it isn't
131
+ claimed here.
132
+
133
+ ## Contributing
134
+
135
+ See [CONTRIBUTING.md](https://github.com/RudrenduPaul/SeoFleet/blob/main/CONTRIBUTING.md).
136
+
137
+ ```bash
138
+ cd python
139
+ python3 -m venv .venv && source .venv/bin/activate
140
+ pip install -e ".[dev]"
141
+ pytest
142
+ ```
143
+
144
+ ## License
145
+
146
+ MIT, see [LICENSE](https://github.com/RudrenduPaul/SeoFleet/blob/main/LICENSE).
@@ -0,0 +1,69 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "seofleet-cli"
7
+ version = "0.2.0"
8
+ description = "Zero-config, cross-platform SEO and GEO (generative engine optimization) checker: 12 checks against a live site, plus multi-site fleet mode, in pure Python with no extra runtime toolchain."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "MIT"
12
+ authors = [
13
+ { name = "Rudrendu Paul" },
14
+ { name = "Sourav Nandy" },
15
+ ]
16
+ keywords = ["seo", "geo", "generative-engine-optimization", "cli", "agent-native", "website-audit", "developer-tools"]
17
+ classifiers = [
18
+ "Development Status :: 3 - Alpha",
19
+ "Environment :: Console",
20
+ "Intended Audience :: Developers",
21
+ "License :: OSI Approved :: MIT License",
22
+ "Operating System :: OS Independent",
23
+ "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3.9",
25
+ "Programming Language :: Python :: 3.10",
26
+ "Programming Language :: Python :: 3.11",
27
+ "Programming Language :: Python :: 3.12",
28
+ "Programming Language :: Python :: 3.13",
29
+ "Topic :: Internet :: WWW/HTTP :: Site Management",
30
+ "Topic :: Software Development :: Quality Assurance",
31
+ ]
32
+ dependencies = []
33
+
34
+ [project.optional-dependencies]
35
+ dev = [
36
+ "pytest>=7.0,<9",
37
+ "build>=1.0,<2",
38
+ "twine>=5.0,<7",
39
+ ]
40
+
41
+ [project.urls]
42
+ Homepage = "https://github.com/RudrenduPaul/SeoFleet"
43
+ Repository = "https://github.com/RudrenduPaul/SeoFleet"
44
+ "Bug Tracker" = "https://github.com/RudrenduPaul/SeoFleet/issues"
45
+ Changelog = "https://github.com/RudrenduPaul/SeoFleet/blob/main/CHANGELOG.md"
46
+ Documentation = "https://github.com/RudrenduPaul/SeoFleet/blob/main/docs/getting-started.md"
47
+ "Author - Rudrendu Paul" = "https://github.com/RudrenduPaul"
48
+ "Author - Sourav Nandy" = "https://github.com/Sourav-nandy-ai"
49
+
50
+ [project.scripts]
51
+ seofleet = "seofleet.cli:main"
52
+
53
+ [tool.hatch.build.targets.wheel]
54
+ packages = ["src/seofleet"]
55
+
56
+ [tool.hatch.build.targets.sdist]
57
+ include = [
58
+ "src/seofleet",
59
+ "tests",
60
+ "README.md",
61
+ "LICENSE",
62
+ ]
63
+ exclude = [
64
+ ".gitignore",
65
+ "examples",
66
+ ]
67
+
68
+ [tool.pytest.ini_options]
69
+ testpaths = ["tests"]
@@ -0,0 +1,104 @@
1
+ """
2
+ Programmatic / agent-native entry point.
3
+
4
+ from seofleet import load_site, run_checks, select_checks, ALL_CHECKS
5
+
6
+ ctx = load_site("https://example.com")
7
+ results = run_checks(ALL_CHECKS, ctx)
8
+ for r in results:
9
+ print(r.status, r.name, r.message)
10
+
11
+ This is the Python port of the seofleet-cli npm package
12
+ (https://www.npmjs.com/package/seofleet-cli). Both distributions run the
13
+ same 12 technical-SEO/GEO checks; see
14
+ https://github.com/RudrenduPaul/SeoFleet for the canonical documentation,
15
+ comparison table, and the original TypeScript source.
16
+ """
17
+ from .checks import (
18
+ ALL_CHECKS,
19
+ GEO_CHECKS,
20
+ TECHNICAL_CHECKS,
21
+ ai_crawler_directives_check,
22
+ canonical_check,
23
+ content_extraction_check,
24
+ faq_schema_check,
25
+ heading_structure_check,
26
+ image_alt_check,
27
+ llms_txt_check,
28
+ meta_description_check,
29
+ robots_txt_check,
30
+ sitemap_xml_check,
31
+ structured_data_check,
32
+ title_check,
33
+ )
34
+ from .config import CONFIG_FILENAME, SeoFleetConfig, default_config, load_config, select_checks
35
+ from .errors import SeoFleetError
36
+ from .fetch_utils import FetchedResource, assert_http_url, safe_fetch
37
+ from .fleet import FleetManifest, FleetManifestEntry, FleetSiteResult, load_fleet_manifest, run_fleet
38
+ from .format import (
39
+ format_check_results_json,
40
+ format_check_results_text,
41
+ format_fleet_results_json,
42
+ format_fleet_results_text,
43
+ format_init_result_json,
44
+ format_init_result_text,
45
+ )
46
+ from .init import InitResult, init_project
47
+ from .runner import has_failure, run_checks
48
+ from .site_resources import build_check_context, fetch_site_resources, load_site
49
+ from .types import Check, CheckContext, CheckResult, SiteResources
50
+
51
+ __version__ = "0.2.0"
52
+
53
+ __all__ = [
54
+ "__version__",
55
+ # Types
56
+ "Check",
57
+ "CheckContext",
58
+ "CheckResult",
59
+ "SiteResources",
60
+ "FetchedResource",
61
+ "SeoFleetError",
62
+ "SeoFleetConfig",
63
+ "InitResult",
64
+ "FleetManifest",
65
+ "FleetManifestEntry",
66
+ "FleetSiteResult",
67
+ # Checks
68
+ "ALL_CHECKS",
69
+ "TECHNICAL_CHECKS",
70
+ "GEO_CHECKS",
71
+ "title_check",
72
+ "meta_description_check",
73
+ "canonical_check",
74
+ "robots_txt_check",
75
+ "sitemap_xml_check",
76
+ "heading_structure_check",
77
+ "image_alt_check",
78
+ "structured_data_check",
79
+ "llms_txt_check",
80
+ "ai_crawler_directives_check",
81
+ "faq_schema_check",
82
+ "content_extraction_check",
83
+ # Core functions
84
+ "run_checks",
85
+ "has_failure",
86
+ "fetch_site_resources",
87
+ "build_check_context",
88
+ "load_site",
89
+ "safe_fetch",
90
+ "assert_http_url",
91
+ "load_config",
92
+ "default_config",
93
+ "select_checks",
94
+ "CONFIG_FILENAME",
95
+ "init_project",
96
+ "load_fleet_manifest",
97
+ "run_fleet",
98
+ "format_check_results_text",
99
+ "format_check_results_json",
100
+ "format_fleet_results_text",
101
+ "format_fleet_results_json",
102
+ "format_init_result_text",
103
+ "format_init_result_json",
104
+ ]
@@ -0,0 +1,83 @@
1
+ """Ported from src/checks/index.ts."""
2
+ from __future__ import annotations
3
+
4
+ from typing import List
5
+
6
+ from ..types import Check
7
+ from .geo.ai_crawler_directives import ai_crawler_directives_check
8
+ from .geo.content_extraction import content_extraction_check
9
+ from .geo.faq_schema import faq_schema_check
10
+ from .geo.link_header import link_header_check
11
+ from .geo.llms_txt import llms_txt_check
12
+ from .geo.markdown_negotiation import markdown_negotiation_check
13
+ from .geo.organization_schema import organization_schema_check
14
+ from .geo.speakable_schema import speakable_schema_check
15
+ from .geo.structured_data import structured_data_check
16
+ from .technical.canonical import canonical_check
17
+ from .technical.heading_structure import heading_structure_check
18
+ from .technical.image_alt import image_alt_check
19
+ from .technical.image_weight import image_weight_check
20
+ from .technical.meta_description import meta_description_check
21
+ from .technical.open_graph import open_graph_check
22
+ from .technical.robots_meta_directives import robots_meta_directives_check
23
+ from .technical.redirect_chain import redirect_chain_check
24
+ from .technical.robots_txt import robots_txt_check
25
+ from .technical.sitemap_xml import sitemap_xml_check
26
+ from .technical.title import title_check
27
+ from .technical.twitter_card import twitter_card_check
28
+
29
+ TECHNICAL_CHECKS: List[Check] = [
30
+ title_check,
31
+ meta_description_check,
32
+ canonical_check,
33
+ robots_txt_check,
34
+ sitemap_xml_check,
35
+ heading_structure_check,
36
+ image_alt_check,
37
+ open_graph_check,
38
+ twitter_card_check,
39
+ robots_meta_directives_check,
40
+ image_weight_check,
41
+ redirect_chain_check,
42
+ ]
43
+
44
+ GEO_CHECKS: List[Check] = [
45
+ structured_data_check,
46
+ llms_txt_check,
47
+ ai_crawler_directives_check,
48
+ faq_schema_check,
49
+ content_extraction_check,
50
+ speakable_schema_check,
51
+ organization_schema_check,
52
+ markdown_negotiation_check,
53
+ link_header_check,
54
+ ]
55
+
56
+ ALL_CHECKS: List[Check] = [*TECHNICAL_CHECKS, *GEO_CHECKS]
57
+
58
+ __all__ = [
59
+ "TECHNICAL_CHECKS",
60
+ "GEO_CHECKS",
61
+ "ALL_CHECKS",
62
+ "title_check",
63
+ "meta_description_check",
64
+ "canonical_check",
65
+ "robots_txt_check",
66
+ "sitemap_xml_check",
67
+ "heading_structure_check",
68
+ "image_alt_check",
69
+ "open_graph_check",
70
+ "twitter_card_check",
71
+ "robots_meta_directives_check",
72
+ "image_weight_check",
73
+ "redirect_chain_check",
74
+ "structured_data_check",
75
+ "llms_txt_check",
76
+ "ai_crawler_directives_check",
77
+ "faq_schema_check",
78
+ "content_extraction_check",
79
+ "speakable_schema_check",
80
+ "organization_schema_check",
81
+ "markdown_negotiation_check",
82
+ "link_header_check",
83
+ ]
File without changes