docpull 4.4.1__tar.gz → 5.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.
Files changed (168) hide show
  1. {docpull-4.4.1/src/docpull.egg-info → docpull-5.0.1}/PKG-INFO +207 -39
  2. docpull-5.0.1/README.md +454 -0
  3. {docpull-4.4.1 → docpull-5.0.1}/pyproject.toml +23 -1
  4. docpull-5.0.1/src/docpull/__init__.py +182 -0
  5. docpull-5.0.1/src/docpull/accounting.py +340 -0
  6. docpull-5.0.1/src/docpull/auth_cli.py +166 -0
  7. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/benchmark.py +796 -259
  8. docpull-5.0.1/src/docpull/cli.py +1449 -0
  9. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/conversion/extractor.py +61 -5
  10. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/conversion/protocols.py +1 -1
  11. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/core/fetcher.py +39 -13
  12. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/discovery/__init__.py +22 -0
  13. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/discovery/_fetch.py +12 -4
  14. docpull-5.0.1/src/docpull/discovery/contracts.py +1496 -0
  15. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/discovery/crawler.py +31 -4
  16. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/discovery/link_extractors/enhanced.py +14 -8
  17. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/discovery/link_extractors/static.py +10 -4
  18. docpull-5.0.1/src/docpull/discovery_cli.py +449 -0
  19. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/doctor.py +20 -2
  20. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/evidence_pack.py +2 -1
  21. docpull-5.0.1/src/docpull/exports.py +674 -0
  22. docpull-5.0.1/src/docpull/graph.py +1069 -0
  23. docpull-5.0.1/src/docpull/local_workflows.py +734 -0
  24. docpull-5.0.1/src/docpull/mcp/server.py +2685 -0
  25. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/models/__init__.py +8 -0
  26. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/models/config.py +290 -5
  27. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/models/events.py +1 -0
  28. docpull-5.0.1/src/docpull/monitor.py +458 -0
  29. docpull-5.0.1/src/docpull/pack_reader.py +732 -0
  30. docpull-5.0.1/src/docpull/pack_tools.py +1822 -0
  31. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/parallel_workflows.py +212 -18
  32. docpull-5.0.1/src/docpull/parity.py +953 -0
  33. docpull-5.0.1/src/docpull/parity_cli.py +276 -0
  34. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/pipeline/steps/__init__.py +2 -0
  35. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/pipeline/steps/convert.py +2 -2
  36. docpull-5.0.1/src/docpull/pipeline/steps/render.py +82 -0
  37. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/pipeline/steps/save.py +31 -30
  38. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/pipeline/steps/save_ndjson.py +2 -1
  39. docpull-5.0.1/src/docpull/policy.py +395 -0
  40. docpull-5.0.1/src/docpull/policy_cli.py +86 -0
  41. docpull-5.0.1/src/docpull/provider_adapters.py +1409 -0
  42. docpull-5.0.1/src/docpull/provider_capabilities.py +190 -0
  43. docpull-5.0.1/src/docpull/provider_cli.py +1363 -0
  44. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/provider_keys.py +81 -21
  45. docpull-5.0.1/src/docpull/provider_probes.py +615 -0
  46. docpull-5.0.1/src/docpull/rendering.py +944 -0
  47. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/security/download_policy.py +2 -2
  48. docpull-5.0.1/src/docpull/server.py +207 -0
  49. docpull-5.0.1/src/docpull/skill_export.py +265 -0
  50. {docpull-4.4.1 → docpull-5.0.1/src/docpull.egg-info}/PKG-INFO +207 -39
  51. {docpull-4.4.1 → docpull-5.0.1}/src/docpull.egg-info/SOURCES.txt +41 -1
  52. {docpull-4.4.1 → docpull-5.0.1}/src/docpull.egg-info/requires.txt +15 -0
  53. docpull-5.0.1/tests/test_accounting.py +29 -0
  54. docpull-5.0.1/tests/test_auth_cli.py +177 -0
  55. {docpull-4.4.1 → docpull-5.0.1}/tests/test_benchmark.py +279 -0
  56. docpull-5.0.1/tests/test_ci_policy.py +192 -0
  57. docpull-5.0.1/tests/test_cli.py +802 -0
  58. {docpull-4.4.1 → docpull-5.0.1}/tests/test_discovery.py +30 -0
  59. docpull-5.0.1/tests/test_discovery_contracts.py +647 -0
  60. docpull-5.0.1/tests/test_doctor.py +214 -0
  61. docpull-5.0.1/tests/test_exports.py +271 -0
  62. docpull-5.0.1/tests/test_graph.py +127 -0
  63. {docpull-4.4.1 → docpull-5.0.1}/tests/test_link_extractors.py +56 -6
  64. docpull-5.0.1/tests/test_local_workflows.py +196 -0
  65. docpull-5.0.1/tests/test_mcp_server.py +533 -0
  66. docpull-5.0.1/tests/test_metadata_extractor.py +149 -0
  67. docpull-5.0.1/tests/test_monitor.py +120 -0
  68. docpull-5.0.1/tests/test_pack_server.py +191 -0
  69. docpull-5.0.1/tests/test_pack_tools.py +612 -0
  70. {docpull-4.4.1 → docpull-5.0.1}/tests/test_parallel_workflows.py +58 -0
  71. docpull-5.0.1/tests/test_parity_workflows.py +175 -0
  72. {docpull-4.4.1 → docpull-5.0.1}/tests/test_pipeline.py +150 -0
  73. docpull-5.0.1/tests/test_policy.py +109 -0
  74. docpull-5.0.1/tests/test_policy_cli.py +59 -0
  75. docpull-5.0.1/tests/test_provider_adapters.py +140 -0
  76. docpull-5.0.1/tests/test_provider_cli.py +457 -0
  77. docpull-5.0.1/tests/test_provider_keys.py +169 -0
  78. docpull-5.0.1/tests/test_provider_probes.py +206 -0
  79. docpull-5.0.1/tests/test_rate_limiter.py +46 -0
  80. {docpull-4.4.1 → docpull-5.0.1}/tests/test_real_site_regressions.py +65 -0
  81. docpull-5.0.1/tests/test_rendering.py +506 -0
  82. docpull-5.0.1/tests/test_surface_contract.py +194 -0
  83. docpull-5.0.1/tests/test_trafilatura_extractor.py +94 -0
  84. docpull-4.4.1/README.md +0 -298
  85. docpull-4.4.1/src/docpull/__init__.py +0 -74
  86. docpull-4.4.1/src/docpull/cli.py +0 -715
  87. docpull-4.4.1/src/docpull/mcp/server.py +0 -921
  88. docpull-4.4.1/src/docpull/pack_tools.py +0 -517
  89. docpull-4.4.1/src/docpull/provider_cli.py +0 -426
  90. docpull-4.4.1/tests/test_ci_policy.py +0 -58
  91. docpull-4.4.1/tests/test_cli.py +0 -172
  92. docpull-4.4.1/tests/test_mcp_server.py +0 -64
  93. docpull-4.4.1/tests/test_pack_tools.py +0 -283
  94. docpull-4.4.1/tests/test_provider_cli.py +0 -85
  95. {docpull-4.4.1 → docpull-5.0.1}/LICENSE +0 -0
  96. {docpull-4.4.1 → docpull-5.0.1}/setup.cfg +0 -0
  97. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/__main__.py +0 -0
  98. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/cache/__init__.py +0 -0
  99. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/cache/frontier.py +0 -0
  100. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/cache/manager.py +0 -0
  101. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/cache/streaming_dedup.py +0 -0
  102. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/conversion/__init__.py +0 -0
  103. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/conversion/chunking.py +0 -0
  104. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/conversion/filings.py +0 -0
  105. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/conversion/markdown.py +0 -0
  106. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/conversion/special_cases.py +0 -0
  107. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/conversion/trafilatura_extractor.py +0 -0
  108. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/core/__init__.py +0 -0
  109. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/discovery/composite.py +0 -0
  110. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/discovery/filters.py +0 -0
  111. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/discovery/link_extractors/__init__.py +0 -0
  112. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/discovery/link_extractors/protocols.py +0 -0
  113. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/discovery/protocols.py +0 -0
  114. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/discovery/sitemap.py +0 -0
  115. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/fixtures/__init__.py +0 -0
  116. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/fixtures/parallel-search-extract.json +0 -0
  117. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/http/__init__.py +0 -0
  118. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/http/client.py +0 -0
  119. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/http/protocols.py +0 -0
  120. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/http/rate_limiter.py +0 -0
  121. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/judge.py +0 -0
  122. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/mcp/__init__.py +0 -0
  123. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/mcp/sources.py +0 -0
  124. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/mcp/tools.py +0 -0
  125. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/metadata_extractor.py +0 -0
  126. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/models/document.py +0 -0
  127. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/models/profiles.py +0 -0
  128. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/models/run.py +0 -0
  129. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/passk.py +0 -0
  130. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/pipeline/__init__.py +0 -0
  131. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/pipeline/base.py +0 -0
  132. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/pipeline/manifest.py +0 -0
  133. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/pipeline/steps/chunk.py +0 -0
  134. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/pipeline/steps/dedup.py +0 -0
  135. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/pipeline/steps/fetch.py +0 -0
  136. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/pipeline/steps/metadata.py +0 -0
  137. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/pipeline/steps/save_json.py +0 -0
  138. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/pipeline/steps/save_okf.py +0 -0
  139. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/pipeline/steps/save_sqlite.py +0 -0
  140. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/pipeline/steps/validate.py +0 -0
  141. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/py.typed +0 -0
  142. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/scraper.py +0 -0
  143. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/security/__init__.py +0 -0
  144. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/security/robots.py +0 -0
  145. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/security/url_validator.py +0 -0
  146. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/source_scoring.py +0 -0
  147. {docpull-4.4.1 → docpull-5.0.1}/src/docpull/time_utils.py +0 -0
  148. {docpull-4.4.1 → docpull-5.0.1}/src/docpull.egg-info/dependency_links.txt +0 -0
  149. {docpull-4.4.1 → docpull-5.0.1}/src/docpull.egg-info/entry_points.txt +0 -0
  150. {docpull-4.4.1 → docpull-5.0.1}/src/docpull.egg-info/top_level.txt +0 -0
  151. {docpull-4.4.1 → docpull-5.0.1}/tests/test_cache_conditional_get.py +0 -0
  152. {docpull-4.4.1 → docpull-5.0.1}/tests/test_chunking.py +0 -0
  153. {docpull-4.4.1 → docpull-5.0.1}/tests/test_conversion.py +0 -0
  154. {docpull-4.4.1 → docpull-5.0.1}/tests/test_convert_step_new.py +0 -0
  155. {docpull-4.4.1 → docpull-5.0.1}/tests/test_document_record.py +0 -0
  156. {docpull-4.4.1 → docpull-5.0.1}/tests/test_evidence_pack.py +0 -0
  157. {docpull-4.4.1 → docpull-5.0.1}/tests/test_frontier_resume.py +0 -0
  158. {docpull-4.4.1 → docpull-5.0.1}/tests/test_integration.py +0 -0
  159. {docpull-4.4.1 → docpull-5.0.1}/tests/test_judge.py +0 -0
  160. {docpull-4.4.1 → docpull-5.0.1}/tests/test_mcp_tools.py +0 -0
  161. {docpull-4.4.1 → docpull-5.0.1}/tests/test_naming.py +0 -0
  162. {docpull-4.4.1 → docpull-5.0.1}/tests/test_outputs_e2e.py +0 -0
  163. {docpull-4.4.1 → docpull-5.0.1}/tests/test_passk.py +0 -0
  164. {docpull-4.4.1 → docpull-5.0.1}/tests/test_save_ndjson.py +0 -0
  165. {docpull-4.4.1 → docpull-5.0.1}/tests/test_save_sqlite.py +0 -0
  166. {docpull-4.4.1 → docpull-5.0.1}/tests/test_security_hardening.py +0 -0
  167. {docpull-4.4.1 → docpull-5.0.1}/tests/test_special_cases.py +0 -0
  168. {docpull-4.4.1 → docpull-5.0.1}/tests/test_time_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docpull
3
- Version: 4.4.1
3
+ Version: 5.0.1
4
4
  Summary: Convert public web pages into clean Markdown for AI agents and RAG
5
5
  Author-email: Zachary Roth <support@raintree.technology>
6
6
  Maintainer-email: Raintree Technology <support@raintree.technology>
@@ -15,7 +15,7 @@ Project-URL: MCP Plugin, https://github.com/raintree-technology/docpull/tree/mai
15
15
  Project-URL: Comparison Guide, https://github.com/raintree-technology/docpull/blob/main/docs/alternatives.md
16
16
  Project-URL: Download Stats, https://pepy.tech/project/docpull
17
17
  Project-URL: Changelog, https://github.com/raintree-technology/docpull/blob/main/docs/CHANGELOG.md
18
- Keywords: python,markdown,documentation,web-extraction,web-scraping,web-crawler,crawler,developer-tools,cli,rag,llm,mcp,ai-agents,context-engineering,claude,ai-training-data
18
+ Keywords: python,markdown,documentation,web,website,web-extraction,web-to-markdown,web-scraping,web-crawler,crawler,content-extraction,developer-tools,cli,rag,llm,mcp,ai-agents,context-engineering,source-packs,research,claude,ai-training-data
19
19
  Classifier: Development Status :: 5 - Production/Stable
20
20
  Classifier: Intended Audience :: Developers
21
21
  Classifier: Intended Audience :: Information Technology
@@ -62,13 +62,20 @@ Requires-Dist: tiktoken>=0.7.0; extra == "tokens"
62
62
  Provides-Extra: mcp
63
63
  Requires-Dist: cryptography>=48.0.1; extra == "mcp"
64
64
  Requires-Dist: mcp>=1.0.0; extra == "mcp"
65
+ Requires-Dist: pydantic-settings>=2.14.2; extra == "mcp"
65
66
  Requires-Dist: pyjwt>=2.13.0; extra == "mcp"
66
67
  Requires-Dist: python-multipart>=0.0.27; extra == "mcp"
67
68
  Requires-Dist: starlette>=1.3.1; extra == "mcp"
69
+ Provides-Extra: serve
70
+ Requires-Dist: uvicorn>=0.30.0; extra == "serve"
68
71
  Provides-Extra: parallel
69
72
  Requires-Dist: parallel-web>=1.0.1; extra == "parallel"
70
73
  Provides-Extra: observability
71
74
  Requires-Dist: raindrop-ai>=0.0.50; extra == "observability"
75
+ Provides-Extra: parquet
76
+ Requires-Dist: pyarrow>=16.0.0; extra == "parquet"
77
+ Provides-Extra: e2b
78
+ Requires-Dist: e2b>=2.0.0; extra == "e2b"
72
79
  Provides-Extra: llm
73
80
  Requires-Dist: tiktoken>=0.7.0; extra == "llm"
74
81
  Provides-Extra: all
@@ -78,11 +85,15 @@ Requires-Dist: trafilatura>=1.12.0; extra == "all"
78
85
  Requires-Dist: tiktoken>=0.7.0; extra == "all"
79
86
  Requires-Dist: cryptography>=48.0.1; extra == "all"
80
87
  Requires-Dist: mcp>=1.0.0; extra == "all"
88
+ Requires-Dist: pydantic-settings>=2.14.2; extra == "all"
81
89
  Requires-Dist: pyjwt>=2.13.0; extra == "all"
82
90
  Requires-Dist: python-multipart>=0.0.27; extra == "all"
83
91
  Requires-Dist: starlette>=1.3.1; extra == "all"
92
+ Requires-Dist: uvicorn>=0.30.0; extra == "all"
84
93
  Requires-Dist: parallel-web>=1.0.1; extra == "all"
85
94
  Requires-Dist: raindrop-ai>=0.0.50; extra == "all"
95
+ Requires-Dist: pyarrow>=16.0.0; extra == "all"
96
+ Requires-Dist: e2b>=2.0.0; extra == "all"
86
97
  Provides-Extra: dev
87
98
  Requires-Dist: pytest>=7.0.0; extra == "dev"
88
99
  Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
@@ -91,6 +102,7 @@ Requires-Dist: mypy>=1.0.0; extra == "dev"
91
102
  Requires-Dist: ruff>=0.1.0; extra == "dev"
92
103
  Requires-Dist: bandit>=1.7.0; extra == "dev"
93
104
  Requires-Dist: pip-audit>=2.0.0; extra == "dev"
105
+ Requires-Dist: msgpack>=1.2.1; extra == "dev"
94
106
  Requires-Dist: pre-commit>=3.0.0; extra == "dev"
95
107
  Requires-Dist: types-requests>=2.31.0; extra == "dev"
96
108
  Requires-Dist: types-beautifulsoup4>=4.12.0; extra == "dev"
@@ -100,7 +112,7 @@ Dynamic: license-file
100
112
 
101
113
  # docpull
102
114
 
103
- **Turn public documentation sites into local Markdown, NDJSON, and agent-ready context packs. No browser required.**
115
+ **Turn public web sources into local Markdown, NDJSON, and agent-ready context packs. Browser-free by default.**
104
116
 
105
117
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
106
118
  [![PyPI version](https://badge.fury.io/py/docpull.svg)](https://badge.fury.io/py/docpull)
@@ -108,18 +120,31 @@ Dynamic: license-file
108
120
  [![GitHub stars](https://img.shields.io/github/stars/raintree-technology/docpull?style=social)](https://github.com/raintree-technology/docpull/stargazers)
109
121
  [![License: MIT](https://img.shields.io/github/license/raintree-technology/docpull)](https://github.com/raintree-technology/docpull/blob/main/LICENSE)
110
122
 
111
- docpull is a Python CLI, SDK, and MCP server that fetches public static or
112
- server-rendered web pages and converts them into clean, auditable local
113
- artifacts for LLMs, retrieval-augmented generation (RAG), offline research, and
114
- agent workflows.
123
+ docpull is a Python CLI, SDK, and MCP server that fetches public or explicitly
124
+ authorized static/server-rendered web pages and converts them into clean,
125
+ auditable local artifacts for LLMs, retrieval-augmented generation (RAG),
126
+ offline research, and agent workflows.
115
127
 
116
- It works best on documentation sites, blogs, API references, OpenAPI specs,
117
- vendor pages, and other public pages where the useful content is available in
118
- HTML or embedded page data.
128
+ DocPull is local-first: direct fetching, sitemap/link discovery, extraction,
129
+ indexing, pack intelligence, and local `agent-browser` rendering can run with no
130
+ provider account and no required API spend. Tavily, Exa, Parallel, and cloud
131
+ renderers are optional escalation paths when local and open-source routes are
132
+ not enough.
119
133
 
120
- docpull is not a browser and does not render JavaScript. JS-only pages are
121
- skipped with a clear reason. See [Scraping Boundary](docs/scraping-boundary.md)
122
- and [Alternatives](docs/alternatives.md) for the full boundary.
134
+ DocPull exposes the same core workflows through CLI, Python SDK, and MCP, with
135
+ each surface optimized for its user. The [Surface Contract](docs/surface-contract.md)
136
+ defines how those surfaces align and where they intentionally differ.
137
+
138
+ Web-source ingestion is the core workflow. Documentation is one high-value
139
+ lane, not the product boundary. It works best on static or server-rendered
140
+ pages such as blogs, API references, OpenAPI specs, changelogs, vendor pages,
141
+ product pages, filings, docs sites, and other pages where the useful content is
142
+ available in HTML or embedded page data.
143
+
144
+ docpull is browser-free by default. JS-only pages are skipped with a clear
145
+ reason unless you explicitly opt into the local `agent-browser` renderer. See
146
+ [Scraping Boundary](docs/scraping-boundary.md) and
147
+ [Alternatives](docs/alternatives.md) for the full boundary.
123
148
 
124
149
  ## Install
125
150
 
@@ -133,21 +158,90 @@ Install optional extras as needed:
133
158
  pip install 'docpull[llm]' # tiktoken for token-accurate chunking
134
159
  pip install 'docpull[trafilatura]' # alternative extractor for noisy pages
135
160
  pip install 'docpull[mcp]' # stdio MCP server
161
+ pip install 'docpull[serve]' # local pack JSON server runner
136
162
  pip install 'docpull[parallel]' # Parallel context packs
137
163
  pip install 'docpull[observability]' # Raindrop benchmark tracing
164
+ pip install 'docpull[e2b]' # E2B cloud sandbox renderer SDK
138
165
  pip install 'docpull[all]' # all optional extras
139
166
  ```
140
167
 
168
+ Browser rendering is an explicit external extension, not part of the base
169
+ install. Install an `agent-browser` compatible CLI separately, put it on
170
+ `PATH`, or set `DOCPULL_AGENT_BROWSER_BIN=/path/to/agent-browser`. Verify the
171
+ runtime with `docpull render --check`. Render targets must use HTTPS except for
172
+ localhost/loopback HTTP during local testing, and DocPull keeps renderer action
173
+ permissions locked down to HTML retrieval only.
174
+
175
+ For stronger isolation, cloud runtimes are available explicitly:
176
+ `docpull render URL --runtime vercel` uses the Vercel Sandbox CLI and Vercel
177
+ auth, while `docpull render URL --runtime e2b` uses the E2B Python SDK and
178
+ `E2B_API_KEY`. These are never enabled by default. All runtimes execute the same
179
+ `agent-browser --json` renderer contract. Use `--cloud-max-estimated-cost` to
180
+ set a local per-render budget guard, and use `--cloud-agent-browser-install skip`
181
+ with a prebuilt sandbox/template that already includes `agent-browser`. For E2B,
182
+ pass `--template` or set `DOCPULL_E2B_TEMPLATE` to use that prebuilt environment.
183
+
184
+ ## Free-First Budgets
185
+
186
+ Use `--budget 0` when a run must not make paid-capable provider or cloud calls:
187
+
188
+ ```bash
189
+ docpull https://docs.example.com --budget 0 -o ./docs/example
190
+ docpull discover scan https://docs.example.com -o ./packs/discovery
191
+ docpull render https://example.com/app --runtime local --budget 0
192
+ docpull providers context-pack "Find official docs" --provider all --dry-run --budget 0 --json
193
+ docpull benchmark quick --zero-dollar --target-set zero-dollar --provider all
194
+ ```
195
+
196
+ Under a zero budget, local cache, direct HTTP, sitemap/static-link discovery,
197
+ local extraction, local indexing, pack analysis, monitors, and local
198
+ `agent-browser` rendering remain allowed. Live Tavily, Exa, Parallel, Vercel
199
+ Sandbox, and E2B calls are blocked before execution. Runs involving a budget or
200
+ paid-capable route write `run.accounting.json` with non-secret route, cost,
201
+ HTTP/cache, browser, and blocked-action metadata.
202
+
203
+ Use `docpull discover scan URL` to build a provider-free discovery pack from
204
+ open site hints: `llms.txt`, RSS/Atom feeds, OpenAPI specs, sitemap indexes,
205
+ and public GitHub docs trees. It writes the same `candidate_sources.ndjson`
206
+ contract as provider imports and URL/sitemap files, so the next step is still
207
+ `docpull discover select` or `docpull discover fetch`.
208
+
209
+ When a zero-dollar benchmark or local run is partial, DocPull reports the
210
+ lowest-friction escalation path before spending money: local `--render fallback`
211
+ first, BYOK providers next, and cloud rendering only when local rendering or
212
+ infrastructure is the blocker. Benchmark reports include suggested commands,
213
+ estimated paid request counts, and estimated paid cost guards before any
214
+ provider or cloud call is made.
215
+
216
+ The `zero-dollar` benchmark target set is the Phase 2 measurement matrix. It
217
+ keeps the existing docs/provider targets and adds JS-heavy docs, pricing,
218
+ filings, feeds, sitemaps, and search-to-evidence tasks. The report classifies
219
+ each target as `complete_for_0`, `complete_with_local_browser`, `partial_for_0`,
220
+ `requires_provider`, `requires_cloud_browser`, or `blocked_by_policy`.
221
+
222
+ ## Open Source And Hosted Boundary
223
+
224
+ The open-source package owns local fetching, local rendering adapters,
225
+ provider-free discovery, extraction, indexing, packs, diffs, monitors, MCP,
226
+ BYOK providers, budget policy, accounting, and benchmarks.
227
+
228
+ A hosted DocPull product, if offered, should sell managed execution: always-on
229
+ schedules, browser/proxy infrastructure, persistent auth profiles, queues,
230
+ alerts, dashboards, collaboration, retention, SSO, audit logs, SLAs, and
231
+ bundled provider billing. The hosted boundary does not change the OSS default:
232
+ no hidden paid calls, no CAPTCHA bypass, no stealth scraping, and no claim of a
233
+ proprietary web-scale index.
234
+
141
235
  ## 30-Second Usage
142
236
 
143
237
  ```bash
144
- docpull https://docs.python.org/3/library/asyncio.html --single -o ./asyncio-docs
238
+ docpull https://www.python.org/blogs/ --single -o ./python-news
145
239
  ```
146
240
 
147
241
  Example output:
148
242
 
149
243
  ```text
150
- asyncio-docs/
244
+ python-news/
151
245
  index.md
152
246
  corpus.manifest.json
153
247
  ```
@@ -156,20 +250,21 @@ Markdown includes source metadata and readable page content:
156
250
 
157
251
  ```markdown
158
252
  ---
159
- title: "asyncio - Asynchronous I/O"
160
- source: https://docs.python.org/3/library/asyncio.html
161
- source_type: "sphinx"
253
+ title: "Blogs"
254
+ source: https://www.python.org/blogs/
255
+ source_type: "html"
162
256
  ---
163
257
 
164
- # asyncio - Asynchronous I/O
258
+ # Blogs
165
259
 
166
- asyncio is a library to write concurrent code using the async/await syntax.
260
+ News from the Python Software Foundation, Python core developers, and the
261
+ wider Python community.
167
262
  ```
168
263
 
169
264
  Stream chunked NDJSON for agents and RAG:
170
265
 
171
266
  ```bash
172
- docpull https://docs.python.org/3/library/asyncio.html \
267
+ docpull https://www.python.org/blogs/ \
173
268
  --single \
174
269
  --profile llm \
175
270
  --stream | jq .
@@ -178,31 +273,70 @@ docpull https://docs.python.org/3/library/asyncio.html \
178
273
  Each line is a JSON document:
179
274
 
180
275
  ```json
181
- {"schema_version":1,"document_id":"doc_...","chunk_id":"chunk_...","url":"https://docs.python.org/3/library/asyncio.html","title":"asyncio - Asynchronous I/O","content":"asyncio is a library to write concurrent code...","source_type":"sphinx","chunk_index":0,"token_count":842}
276
+ {"schema_version":1,"document_id":"doc_...","chunk_id":"chunk_...","url":"https://www.python.org/blogs/","title":"Blogs","content":"News from the Python Software Foundation...","source_type":"html","chunk_index":0,"token_count":842}
182
277
  ```
183
278
 
184
279
  ## Common Workflows
185
280
 
186
281
  ```bash
187
- # Crawl a site and write Markdown files
188
- docpull https://docs.example.com -o ./docs-example
282
+ # Crawl a public web section and write Markdown files
283
+ docpull https://www.python.org/blogs/ -o ./python-news
189
284
 
190
- # Stream LLM-ready NDJSON chunks from a site
191
- docpull https://docs.example.com --profile llm --stream | jq .
285
+ # Stream LLM-ready NDJSON chunks from a source
286
+ docpull https://www.python.org/blogs/ --profile llm --stream | jq .
192
287
 
193
288
  # Write SQLite with an FTS5 search index
194
- docpull https://docs.example.com --format sqlite -o ./docs-db
289
+ docpull https://www.python.org/blogs/ --format sqlite -o ./python-news-db
195
290
 
196
291
  # Build an Open Knowledge Format (OKF) bundle for portable source packs
197
292
  docpull https://example.com --profile okf -o ./site-okf
293
+
294
+ # Turn a source corpus into agent-ready skills/rules
295
+ docpull https://sdk.vercel.ai \
296
+ --skill vercel-ai \
297
+ --skill-agent all \
298
+ --skill-description "Vercel AI SDK source reference"
299
+ ```
300
+
301
+ Local-first parity workflows mirror common hosted search/extract/crawl/research
302
+ API shapes while writing auditable files instead of relying on a hosted index:
303
+
304
+ ```bash
305
+ # Normalize candidate URLs without fetching content
306
+ docpull map urls ./urls.txt -o ./packs/map
307
+
308
+ # Extract known URLs into a local pack
309
+ docpull extract-pack ./urls.txt -o ./packs/extract
310
+
311
+ # Select mapped candidates and fetch them
312
+ docpull crawl-pack ./packs/map --select top:10 -o ./packs/crawl
313
+
314
+ # Answer/research from an existing local pack with lifecycle artifacts
315
+ docpull research-pack ./packs/crawl \
316
+ --objective "Summarize auth and webhook behavior" \
317
+ --schema ./output.schema.json
318
+
319
+ # Build a cited entity/list pack from existing evidence
320
+ docpull entities-pack ./packs/crawl --limit 100
198
321
  ```
199
322
 
200
323
  More examples live in [CLI Recipes](docs/examples/README.md).
201
324
 
325
+ With an explicit `--skill-agent`, docpull stores the scraped corpus under
326
+ `.docpull/skills/<name>/references` and creates agent-specific wrappers that
327
+ point at that corpus. `--skill-agent claude` writes a Claude Code skill under
328
+ `.claude/skills/<name>/`, `--skill-agent codex` writes a Codex skill under
329
+ `.agents/skills/<name>/` with `agents/openai.yaml`, and `--skill-agent cursor`
330
+ writes a Cursor project rule at `.cursor/rules/<name>.mdc`. Use
331
+ `--skill-agent all` to create all three. If you pass `--output-dir`, docpull
332
+ stages the generated corpus there; explicit `--skill-agent` targets still write
333
+ their active agent wrappers.
334
+
202
335
  Use docpull when you need to:
203
336
 
204
- - Convert public docs, blogs, API references, vendor pages, and OpenAPI specs
205
- into Markdown or chunked NDJSON for LLM and RAG pipelines.
337
+ - Convert public web sources - docs, blogs, API references, vendor pages,
338
+ product pages, changelogs, filings, and OpenAPI specs - into Markdown or
339
+ chunked NDJSON for LLM and RAG pipelines.
206
340
  - Give an agent a local tool for fetching, caching, grepping, and reading web
207
341
  sources.
208
342
  - Build repeatable context packs with stable IDs, hashes, manifests, and source
@@ -220,20 +354,21 @@ docpull is designed for agent and RAG workflows, not just downloading pages.
220
354
  | Repeatability | Stable document IDs, chunk IDs, hashes, and manifests |
221
355
  | Offline work | Cached archives and mirrored source artifacts |
222
356
  | Agent access | Local CLI, Python SDK, and stdio MCP server |
357
+ | Downstream exports | JSONL, Sheets CSV/TSV, n8n JSON, Vercel AI JSON, CrewAI JSON, warehouse NDJSON, optional Parquet, and agent skills |
223
358
  | Safer fetching | HTTPS defaults, robots.txt compliance, SSRF protections, and redirect guards |
224
359
 
225
360
  ## Supported Sources
226
361
 
227
- docpull uses async HTTP instead of browser automation and includes special
228
- handling for common documentation and API surfaces.
362
+ docpull uses async HTTP instead of browser automation by default and includes
363
+ special handling for common web, documentation, and API surfaces.
229
364
 
230
365
  | Source shape | Support |
231
366
  | --- | --- |
232
- | Static HTML / SSR docs | Extracts article or document regions |
367
+ | Static HTML / SSR pages | Extracts article, main, or document regions |
233
368
  | Next.js / Mintlify | Parses static HTML and `__NEXT_DATA__` when available |
234
369
  | OpenAPI / Swagger | Renders specs into Markdown |
235
370
  | Docusaurus / Sphinx / MkDocs | Extracts static article or document regions |
236
- | VitePress / VuePress / Astro Starlight | Extracts static docs content |
371
+ | VitePress / VuePress / Astro Starlight | Extracts static content regions |
237
372
  | GitBook / ReadMe.io | Extracts available article or content regions |
238
373
  | Redoc / Scalar | Extracts static API reference regions |
239
374
  | JS-only apps | Skipped unless useful content is present in HTML or embedded data |
@@ -270,15 +405,19 @@ Run `docpull --help` for the full option list.
270
405
 
271
406
  ## When Not to Use docpull
272
407
 
273
- docpull intentionally does not use a browser. It is not the right tool for:
408
+ docpull intentionally does not use a browser unless rendering is explicitly
409
+ enabled. It is not the right tool for:
274
410
 
275
- - JS-only pages that require client-side rendering.
411
+ - JS-only pages that require complex browser workflows beyond static rendered HTML.
276
412
  - Authenticated dashboards or private apps.
277
413
  - Pages behind CAPTCHA or bot challenges.
278
414
  - Workflows that require clicking, scrolling, or browser state.
279
415
 
280
- For those cases, use browser automation, such as Playwright, then pass the
281
- rendered HTML or exported content into your pipeline.
416
+ For those cases, use browser automation, such as Playwright, then pass rendered
417
+ HTML or exported content into your pipeline. For simple public JS-rendered
418
+ pages, `docpull render` and `--render fallback` provide an explicit local
419
+ fallback without changing the default crawler behavior. The fallback requires
420
+ the optional external `agent-browser` backend.
282
421
 
283
422
  ## How It Compares
284
423
 
@@ -287,7 +426,7 @@ rendered HTML or exported content into your pipeline.
287
426
  | `wget` / site mirroring | Downloading raw files | Not agent/RAG-oriented |
288
427
  | Browser automation | JS-heavy pages and interactions | Slower, heavier, more stateful |
289
428
  | Hosted extraction APIs | Managed extraction at scale | External dependency and cost |
290
- | docpull | Local public-doc extraction and context packs | No JavaScript rendering |
429
+ | docpull | Local public web-source extraction and context packs | No JavaScript rendering by default |
291
430
 
292
431
  ## Python SDK
293
432
 
@@ -304,7 +443,7 @@ import asyncio
304
443
  from docpull import Fetcher, DocpullConfig, EventType, ProfileName
305
444
 
306
445
  async def main():
307
- cfg = DocpullConfig(url="https://docs.example.com", profile=ProfileName.LLM)
446
+ cfg = DocpullConfig(url="https://example.com/blog", profile=ProfileName.LLM)
308
447
  async with Fetcher(cfg) as fetcher:
309
448
  async for event in fetcher.run():
310
449
  if event.type == EventType.FETCH_PROGRESS:
@@ -351,7 +490,34 @@ part of the package release contract.
351
490
  - `docpull[parallel]` can discover, extract, enrich, score, diff, and archive
352
491
  live web sources with your own Parallel API key. See
353
492
  [Parallel Integration](docs/parallel.md).
493
+ - Local pack intelligence can build citation maps, extract cited entities,
494
+ search pack records, write provider-free research briefs, build cited source
495
+ graphs, or prepare the full sidecar bundle with
496
+ `docpull pack citations`, `docpull pack entities`, `docpull pack search`,
497
+ `docpull pack brief`, `docpull graph build`, `docpull graph query`, and
498
+ `docpull pack prepare`.
499
+ - Local-first expansion commands add policy files, discovery packs, refresh
500
+ reports, audits, cited answers, exports, a localhost pack server, explicit
501
+ rendering, authenticated-source checks, and cron-friendly monitors:
502
+ `docpull policy`, `docpull discover`, `docpull refresh`,
503
+ `docpull pack audit`, `docpull answer-pack`, `docpull export`,
504
+ `docpull serve`, `docpull render`, `docpull auth check`, and
505
+ `docpull monitor`.
506
+ - `docpull export` writes local files for OpenAI vector JSONL, LangChain,
507
+ LlamaIndex, DSPy, Sheets CSV/TSV, n8n workflow JSON, Vercel AI SDK JSON,
508
+ CrewAI JSON, warehouse NDJSON, optional Parquet via `docpull[parquet]`, and
509
+ Codex/Claude/Cursor agent references.
354
510
  - Optional provider workflows can use Parallel, Tavily, and Exa when configured.
511
+ Tavily and Exa are available through `docpull providers ...` and first-class
512
+ aliases such as `docpull tavily context-pack`, `docpull exa context-pack`,
513
+ `docpull exa extract-pack`, and `docpull tavily map-pack`. Use
514
+ `docpull providers capabilities` to see the shared baseline and provider-only
515
+ extensions. For agent or CI logs, use
516
+ `docpull providers auth --json --require-ready --redact-paths` for offline
517
+ local readiness, then `docpull providers probe --json --require-verified
518
+ --redact-paths` when explicit live key validation is intended. Successful
519
+ provider context-pack runs are post-processed into the same local pack
520
+ intelligence artifacts.
355
521
  See [CLI Recipes](docs/examples/README.md#parallel-context-pack).
356
522
  - SEC filing evidence packs use rule profiles such as
357
523
  [vendor-dependency-rules.yml](docs/examples/vendor-dependency-rules.yml).
@@ -372,6 +538,7 @@ When running with `--proxy`, DNS pinning is delegated to the proxy. Pass
372
538
 
373
539
  ```bash
374
540
  docpull --doctor
541
+ docpull render --check
375
542
  docpull URL --verbose
376
543
  docpull URL --dry-run
377
544
  docpull URL --preview-urls
@@ -383,6 +550,7 @@ docpull URL --preview-urls
383
550
  - [Scraping Boundary](docs/scraping-boundary.md) - what docpull does and does not fetch.
384
551
  - [Alternatives](docs/alternatives.md) - when to use browser automation or hosted extraction.
385
552
  - [Corpus Manifest](docs/corpus-manifest.md) - stable IDs, hashes, and source maps.
553
+ - [Surface Contract](docs/surface-contract.md) - how the CLI, Python SDK/API, and MCP surfaces align.
386
554
  - [Parallel Integration](docs/parallel.md) - live-source context pack workflows.
387
555
  - [Changelog](docs/CHANGELOG.md) - release history.
388
556