SEO evidence toolkit: analyzes Screaming Frog exports, adds bounded live and infrastructure checks, and produces structured audits, task backlogs, and reports via CLI and local MCP.
Drift inferred · capture-to-capture
No drift recorded — single capability capture; advisories appear once its surface changes.
transport stdio counts 50 tools · 0 res
· 0 prompts
permission surface via code analysis
tools
-
seo_ai_bots_check
-
seo_asset_weight_check
-
seo_backlinks_check
-
seo_cdn_check
-
seo_citability_check
-
seo_compare_crawls
-
seo_crawl_site
-
seo_domain_profile
-
seo_duplicate_check
-
seo_google_keywords
-
seo_google_serp
-
seo_headers_check
-
seo_hreflang_check
-
seo_images_download
-
seo_images_optimize
-
seo_keywords_cluster
-
seo_keywords_exact
-
seo_keywords_expand
-
seo_keywords_seasonality
-
seo_links_check
-
seo_llms_txt_check
-
seo_log_analyze
-
seo_metrika_counters
-
seo_metrika_report
-
seo_metrika_setup
-
seo_mirror_check
-
seo_parse
-
seo_redirects_check
-
seo_redirects_generate
-
seo_regions_check
-
seo_regions_tree
-
seo_render_check
-
seo_report_build
-
seo_robots_check
-
seo_schema_build
-
seo_schema_check
-
seo_security_check
-
seo_serp_fetch
-
seo_site_audit
-
seo_sitemap_crawl
-
seo_social_meta_check
-
seo_soft404_check
-
seo_sources_doctor
-
seo_spend_report
-
seo_tech_detect
-
sf_audit_issues
-
sf_audit_run
-
sf_audit_summary
-
sf_audit_tasks
-
sf_list_exports
prompt-surface
shipped agent-instruction files + hidden-content / dangerous-code findings —
quoted from the analyzed source
analyzed commit 0cc5acd · analyzer v33 · 1d ago
skills & prompt files 29
- skill PavloSEO-seotools-0cc5acd/.claude/skills/analytics-console-review/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/audit-roadmap/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/backlinks-check/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/duplicate-audit/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/geo-aeo-audit/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/heading-outline/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/js-render-check/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/regional-audit/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/robots-audit/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/schema-graph/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/security-audit/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/seo-deep-audit/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/seo-recon/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/sf-analyzer/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/sf-boundaries/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/sf-config/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/sf-report/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/sf-tasks/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/silo-audit/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/site-report/SKILL.md
- skill PavloSEO-seotools-0cc5acd/.claude/skills/tech-audit/SKILL.md
- agent-rules PavloSEO-seotools-0cc5acd/AGENTS.md
- skill PavloSEO-seotools-0cc5acd/seohead/skills/article-writer/SKILL.md
- skill PavloSEO-seotools-0cc5acd/seohead/skills/seo-audit-page/SKILL.md
- skill PavloSEO-seotools-0cc5acd/seohead/skills/seo-content/SKILL.md
- skill PavloSEO-seotools-0cc5acd/seohead/skills/seo-markup/SKILL.md
- skill PavloSEO-seotools-0cc5acd/seohead/skills/seo-optimize/SKILL.md
- skill PavloSEO-seotools-0cc5acd/seohead/skills/seo-research/SKILL.md
- skill PavloSEO-seotools-0cc5acd/seohead/skills/service-landing-copy/SKILL.md
danger signals4
- dynamic code execution __import__() PavloSEO-seotools-0cc5acd/seohead/sf/cli.py :306
__import__(mod) - suspicious endpoint t.me PavloSEO-seotools-0cc5acd/tests/test_page_facts.py :85
assert "https://t.me/acmeshop" in same - suspicious endpoint 169.254.169.254 (cloud metadata) PavloSEO-seotools-0cc5acd/tests/test_public_safety.py :30
net.validate_url("http://169.254.169.254/latest/meta-data") - suspicious endpoint 93.184.216.34 PavloSEO-seotools-0cc5acd/tests/test_public_safety.py :61
url = "https://93.184.216.34/start"
evidence-backed
findings quoted directly from the published source artifact — not inferred
code files: 185
filesystem 63
- fs (weak) PavloSEO-seotools-0cc5acd/scripts/generate_checks_reference.py :15
from pathlib import Path - fs (weak) PavloSEO-seotools-0cc5acd/scripts/render_readme_visuals.py :14
from pathlib import Path - fs PavloSEO-seotools-0cc5acd/seohead/cli.py :409
with open(path, "r", encoding="utf-8") as fh: # noqa: UP015 - explicit read-only contract - fs PavloSEO-seotools-0cc5acd/seohead/crawl/collect.py :275
handle = stack.enter_context(open(out_path, "w", encoding="utf-8")) - fs PavloSEO-seotools-0cc5acd/seohead/crawl/settings.py :359
with open(path, encoding="utf-8") as handle: - fs PavloSEO-seotools-0cc5acd/seohead/crawl/spider.py :88
with open(path, encoding="utf-8") as handle: - fs PavloSEO-seotools-0cc5acd/seohead/crawl/state.py :57
with open(path, encoding="utf-8") as handle: - fs PavloSEO-seotools-0cc5acd/seohead/data_sources/credentials.py :18
from pathlib import Path - fs PavloSEO-seotools-0cc5acd/seohead/data_sources/spend.py :22
from pathlib import Path - fs PavloSEO-seotools-0cc5acd/seohead/data_sources/yandex_regions.py :21
from pathlib import Path - fs PavloSEO-seotools-0cc5acd/seohead/recon/net.py :20
import shutil - fs PavloSEO-seotools-0cc5acd/seohead/recon/tech_db.py :74
with open(cat_path, encoding="utf-8") as fh: - fs PavloSEO-seotools-0cc5acd/seohead/reports/__init__.py :21
import pathlib - fs PavloSEO-seotools-0cc5acd/seohead/reports/csvfile.py :16
import pathlib - fs PavloSEO-seotools-0cc5acd/seohead/reports/docx.py :11
import pathlib - fs PavloSEO-seotools-0cc5acd/seohead/reports/md.py :5
import pathlib - fs PavloSEO-seotools-0cc5acd/seohead/reports/xlsx.py :10
import pathlib - fs PavloSEO-seotools-0cc5acd/seohead/runlog.py :29
from pathlib import Path - fs PavloSEO-seotools-0cc5acd/seohead/servers/handlers.py :267
with open(os.path.join(out_dir, "audit.json"), "w", encoding="utf-8") as fh: - fs PavloSEO-seotools-0cc5acd/seohead/servers/sf_mcp.py :79
with open(json_path, encoding="utf-8") as fh: - fs PavloSEO-seotools-0cc5acd/seohead/sf/cli.py :221
with open(resolved, "rb") as fh: - fs PavloSEO-seotools-0cc5acd/seohead/sf/config.py :192
with open(path, encoding="utf-8") as handle: - fs PavloSEO-seotools-0cc5acd/seohead/sf/core/audit.py :32
with open(path, "rb") as fh: - fs PavloSEO-seotools-0cc5acd/seohead/sf/core/auth_proxy.py :145
with open(path, encoding="utf-8-sig", newline="") as handle: - fs PavloSEO-seotools-0cc5acd/seohead/sf/core/checks_reference.py :13
from pathlib import Path - fs PavloSEO-seotools-0cc5acd/seohead/sf/core/heuristics.py :165
with open(path, encoding="utf-8", errors="replace") as fh: - fs PavloSEO-seotools-0cc5acd/seohead/sf/core/runner.py :13
import shutil - fs PavloSEO-seotools-0cc5acd/seohead/sf/core/spiderconfig.py :124
with open(source, "rb") as fh: - fs PavloSEO-seotools-0cc5acd/seohead/sf/reporters/jsonfile.py :25
with open(tmp, "w", encoding="utf-8") as fh: - fs PavloSEO-seotools-0cc5acd/seohead/sf/reporters/md.py :139
with open(path, "w", encoding="utf-8") as fh: - fs PavloSEO-seotools-0cc5acd/seohead/sf/tasks.py :231
with open(json_path, "w", encoding="utf-8") as fh: - fs PavloSEO-seotools-0cc5acd/seohead/tools/downloader.py :199
with open(dest, "wb") as fh: - fs PavloSEO-seotools-0cc5acd/seohead/tools/excel.py :67
with open(path, encoding="utf-8-sig", newline="") as fh: - fs PavloSEO-seotools-0cc5acd/seohead/tools/logs.py :380
handle = open(path, encoding="utf-8", errors="replace") # noqa: SIM115 - report open errors - fs PavloSEO-seotools-0cc5acd/seohead/tools/optimizer.py :8
import shutil - fs (weak) PavloSEO-seotools-0cc5acd/tests/conftest.py :6
import shutil - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_check_coverage.py :39
with open(d / "internal_all.csv", "w", encoding="utf-8-sig", newline="") as f: - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_check_preconditions.py :14
import shutil - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_context.py :19
with open(p, "w", encoding="utf-8-sig", newline="") as f: - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_crawl_list_mode.py :7
from pathlib import Path - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_crawl_resume.py :65
with open(state_path, encoding="utf-8") as fh: - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_crawl_state.py :76
with open(path, encoding="utf-8") as fh: - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_crawl_validity.py :22
with open(path, "w", encoding="utf-8-sig", newline="") as fh: - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_data_sources.py :74
with journal.open("a", encoding="utf-8") as handle: - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_docs_drift.py :6
import pathlib - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_html_weight_outliers.py :20
with open(path, "w", encoding="utf-8-sig", newline="") as handle: - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_inlinks.py :7
import shutil - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_interface_binding.py :14
import pathlib - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_mcp.py :11
import shutil - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_outlinks_semantics.py :31
with open(path, "w", encoding="utf-8-sig", newline="") as handle: - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_public_safety.py :5
from pathlib import Path - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_redirect_type.py :25
with open(path, "w", encoding="utf-8-sig", newline="") as handle: - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_registration.py :15
from pathlib import Path - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_repetitive_path.py :39
with open(path, "w", encoding="utf-8-sig", newline="") as handle: - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_reporters.py :18
with open(path, encoding="utf-8") as stream: - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_robots_directives.py :71
with open(path, "w", encoding="utf-8-sig", newline="") as handle: - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_runlog.py :94
with open(journal_path, "a", encoding="utf-8") as handle: - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_runner_throttle.py :38
with open(os.path.join(seen["folder"], "internal_all.csv"), "w") as fh: - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_sf_config.py :12
with p.open("w", encoding="utf-8") as stream: - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_sf_discovery.py :107
with open(d / "internal_all.csv", "w", encoding="utf-8-sig", newline="") as f: - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_sf_sitemap_reconciliation.py :17
with open(path, "w", encoding="utf-8-sig", newline="") as handle: - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_sf_timeout.py :85
"import pathlib, subprocess, sys, time; " - fs (weak) PavloSEO-seotools-0cc5acd/tests/test_url_encoding.py :25
with open(path, "w", encoding="utf-8-sig", newline="") as handle:
shell / exec 3
- shell PavloSEO-seotools-0cc5acd/seohead/recon/net.py :22
import subprocess - shell PavloSEO-seotools-0cc5acd/seohead/sf/core/runner.py :15
import subprocess - shell (weak) PavloSEO-seotools-0cc5acd/tests/test_sf_timeout.py :12
import subprocess
network 36
- net PavloSEO-seotools-0cc5acd/seohead/audit/site.py :22
from urllib.parse import urlparse - net PavloSEO-seotools-0cc5acd/seohead/crawl/collect.py :25
from urllib.parse import urljoin, urlsplit - net PavloSEO-seotools-0cc5acd/seohead/crawl/spider.py :24
from urllib.parse import urlsplit, urlunsplit - net PavloSEO-seotools-0cc5acd/seohead/data_sources/arsenkin.py :28
import urllib.error - net PavloSEO-seotools-0cc5acd/seohead/data_sources/dataforseo.py :25
import urllib.error - net PavloSEO-seotools-0cc5acd/seohead/data_sources/metrika.py :26
import urllib.error - net PavloSEO-seotools-0cc5acd/seohead/data_sources/yandex_cloud.py :34
import urllib.error - net PavloSEO-seotools-0cc5acd/seohead/recon/backlinks.py :19
from urllib.parse import urljoin, urlsplit - net PavloSEO-seotools-0cc5acd/seohead/recon/domain.py :18
import socket - net PavloSEO-seotools-0cc5acd/seohead/recon/mirrors.py :17
from urllib.parse import urlsplit, urlunsplit - net PavloSEO-seotools-0cc5acd/seohead/recon/net.py :21
import socket - net PavloSEO-seotools-0cc5acd/seohead/recon/regions.py :27
from urllib.parse import urljoin, urlparse - net PavloSEO-seotools-0cc5acd/seohead/recon/security.py :16
from urllib.parse import urlsplit, urlunsplit - net PavloSEO-seotools-0cc5acd/seohead/recon/tech.py :730
from urllib.parse import urlsplit - net PavloSEO-seotools-0cc5acd/seohead/servers/handlers.py :528
from urllib.parse import urlsplit, urlunsplit - net PavloSEO-seotools-0cc5acd/seohead/sf/core/auth_proxy.py :19
from urllib.parse import urlsplit - net PavloSEO-seotools-0cc5acd/seohead/sf/core/heuristics.py :13
import urllib.parse - net PavloSEO-seotools-0cc5acd/seohead/sf/core/inlinks.py :12
import urllib.parse - net PavloSEO-seotools-0cc5acd/seohead/sf/core/rules.py :11
import urllib.parse - net PavloSEO-seotools-0cc5acd/seohead/sf/core/runner.py :18
from urllib.parse import urlsplit - net PavloSEO-seotools-0cc5acd/seohead/sf/core/sitemap_coverage.py :17
import urllib.parse - net PavloSEO-seotools-0cc5acd/seohead/tools/asset_weight.py :38
from urllib.parse import urljoin - net PavloSEO-seotools-0cc5acd/seohead/tools/downloader.py :24
from urllib.parse import urlsplit - net PavloSEO-seotools-0cc5acd/seohead/tools/hreflang.py :691
from urllib.parse import urljoin - net PavloSEO-seotools-0cc5acd/seohead/tools/llms_txt.py :136
from urllib.parse import urlsplit, urlunsplit - net PavloSEO-seotools-0cc5acd/seohead/tools/logs.py :37
import socket - net PavloSEO-seotools-0cc5acd/seohead/tools/page_facts.py :26
from urllib.parse import urljoin, urlparse - net PavloSEO-seotools-0cc5acd/seohead/tools/page_type.py :29
from urllib.parse import urlparse - net PavloSEO-seotools-0cc5acd/seohead/tools/parser.py :26
from urllib.parse import urljoin, urlparse - net PavloSEO-seotools-0cc5acd/seohead/tools/redirects.py :22
from urllib.parse import urljoin - net PavloSEO-seotools-0cc5acd/seohead/tools/render.py :20
from urllib.parse import urljoin, urlparse - net PavloSEO-seotools-0cc5acd/seohead/tools/robots.py :11
from urllib.parse import urlparse, urlsplit - net PavloSEO-seotools-0cc5acd/seohead/tools/schema_build.py :21
from urllib.parse import urlparse - net PavloSEO-seotools-0cc5acd/seohead/tools/sitemap.py :32
from urllib.parse import urljoin, urlsplit, urlunsplit - net PavloSEO-seotools-0cc5acd/seohead/tools/soft404.py :24
from urllib.parse import urlsplit, urlunsplit - net (weak) PavloSEO-seotools-0cc5acd/tests/test_fetch_error_reporting.py :15
import httpx
tool registrations 50
- seo_parse PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :48
- seo_redirects_generate PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :56
- seo_redirects_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :69
- seo_crawl_site PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :74
- seo_sitemap_crawl PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :100
- seo_images_download PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :106
- seo_images_optimize PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :114
- seo_keywords_cluster PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :126
- seo_robots_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :136
- seo_headers_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :144
- seo_asset_weight_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :150
- seo_links_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :160
- seo_hreflang_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :166
- seo_domain_profile PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :172
- seo_cdn_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :179
- seo_tech_detect PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :186
- seo_security_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :193
- seo_backlinks_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :201
- seo_schema_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :208
- seo_schema_build PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :219
- seo_duplicate_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :232
- seo_mirror_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :246
- seo_ai_bots_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :256
- seo_llms_txt_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :265
- seo_citability_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :274
- seo_social_meta_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :284
- seo_soft404_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :294
- seo_log_analyze PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :304
- seo_regions_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :316
- seo_render_check PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :333
- seo_site_audit PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :346
- seo_report_build PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :369
- seo_compare_crawls PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :379
- seo_keywords_expand PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :393
- seo_keywords_seasonality PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :405
- seo_keywords_exact PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :420
- seo_serp_fetch PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :430
- seo_google_keywords PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :443
- seo_google_serp PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :474
- seo_metrika_counters PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :493
- seo_metrika_setup PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :499
- seo_metrika_report PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :508
- seo_regions_tree PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :537
- seo_spend_report PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :544
- seo_sources_doctor PavloSEO-seotools-0cc5acd/seohead/servers/mcp_server.py :552
- sf_audit_run PavloSEO-seotools-0cc5acd/seohead/servers/sf_mcp.py :101
- sf_audit_summary PavloSEO-seotools-0cc5acd/seohead/servers/sf_mcp.py :121
- sf_audit_issues PavloSEO-seotools-0cc5acd/seohead/servers/sf_mcp.py :139
- sf_list_exports PavloSEO-seotools-0cc5acd/seohead/servers/sf_mcp.py :161
- sf_audit_tasks PavloSEO-seotools-0cc5acd/seohead/servers/sf_mcp.py :173
declared dependencies 25
- mcp@>=1.9,<2
- pandas@>=2.0,<4
- openpyxl@>=3.1,<4
- lxml@>=4.9,<7
- jsonschema@>=4.0,<5
- httpx@>=0.27,<1
- h2@>=4.1,<5
- beautifulsoup4@>=4.12,<5
- defusedxml@>=0.7,<1
- Pillow@>=10.2,<13
- pydantic@>=2.6,<3
- advertools@>=0.16,<1
- python-dateutil@>=2.8,<3
- playwright@>=1.44,<2
- python-docx@>=1.1,<2
- scikit-learn@>=1.4,<2
- numpy@>=1.26,<3
- snowballstemmer@>=2.2,<4
- build@>=1.2,<2
- pytest@>=8.0,<10
- pytest-cov@>=5.0,<8
- PyYAML@>=6,<7
- respx@>=0.21,<1
- ruff@>=0.9,<1
- twine@>=6,<8