hyperresearch 0.2.0__tar.gz → 0.3.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 (98) hide show
  1. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/.gitignore +2 -0
  2. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/CHANGELOG.md +31 -0
  3. hyperresearch-0.3.0/PKG-INFO +188 -0
  4. hyperresearch-0.3.0/README.md +148 -0
  5. hyperresearch-0.3.0/assets/banner.png +0 -0
  6. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/pyproject.toml +5 -3
  7. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/fetch.py +45 -4
  8. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/core/agent_docs.py +107 -16
  9. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/core/fetcher.py +39 -3
  10. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/core/hooks.py +16 -7
  11. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/skills/research.md +86 -6
  12. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/web/base.py +63 -0
  13. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/web/crawl4ai_provider.py +178 -39
  14. hyperresearch-0.2.0/PKG-INFO +0 -172
  15. hyperresearch-0.2.0/PLAN.md +0 -330
  16. hyperresearch-0.2.0/README.md +0 -132
  17. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/.github/workflows/ci.yml +0 -0
  18. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/.github/workflows/publish.yml +0 -0
  19. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/CONTRIBUTING.md +0 -0
  20. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/LICENSE +0 -0
  21. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/__init__.py +0 -0
  22. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/__main__.py +0 -0
  23. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/__init__.py +0 -0
  24. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/_output.py +0 -0
  25. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/assets.py +0 -0
  26. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/batch.py +0 -0
  27. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/config_cmd.py +0 -0
  28. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/dedup.py +0 -0
  29. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/export.py +0 -0
  30. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/fetch_batch.py +0 -0
  31. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/git_cmd.py +0 -0
  32. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/graph.py +0 -0
  33. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/import_cmd.py +0 -0
  34. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/index.py +0 -0
  35. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/install.py +0 -0
  36. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/link.py +0 -0
  37. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/lint.py +0 -0
  38. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/main.py +0 -0
  39. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/mcp_cmd.py +0 -0
  40. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/note.py +0 -0
  41. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/repair.py +0 -0
  42. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/research.py +0 -0
  43. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/search.py +0 -0
  44. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/serve.py +0 -0
  45. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/setup.py +0 -0
  46. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/sources.py +0 -0
  47. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/tag.py +0 -0
  48. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/template.py +0 -0
  49. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/topic.py +0 -0
  50. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/cli/watch.py +0 -0
  51. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/core/__init__.py +0 -0
  52. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/core/config.py +0 -0
  53. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/core/db.py +0 -0
  54. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/core/enrich.py +0 -0
  55. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/core/frontmatter.py +0 -0
  56. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/core/linker.py +0 -0
  57. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/core/migrations.py +0 -0
  58. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/core/note.py +0 -0
  59. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/core/patterns.py +0 -0
  60. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/core/similarity.py +0 -0
  61. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/core/sync.py +0 -0
  62. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/core/templates.py +0 -0
  63. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/core/vault.py +0 -0
  64. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/export/__init__.py +0 -0
  65. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/graph/__init__.py +0 -0
  66. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/indexgen/__init__.py +0 -0
  67. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/indexgen/generator.py +0 -0
  68. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/mcp/__init__.py +0 -0
  69. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/mcp/server.py +0 -0
  70. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/models/__init__.py +0 -0
  71. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/models/graph.py +0 -0
  72. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/models/note.py +0 -0
  73. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/models/output.py +0 -0
  74. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/models/search.py +0 -0
  75. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/py.typed +0 -0
  76. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/search/__init__.py +0 -0
  77. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/search/filters.py +0 -0
  78. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/search/fts.py +0 -0
  79. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/serve/__init__.py +0 -0
  80. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/serve/renderer.py +0 -0
  81. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/serve/server.py +0 -0
  82. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/skills/__init__.py +0 -0
  83. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/web/__init__.py +0 -0
  84. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/src/hyperresearch/web/builtin.py +0 -0
  85. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/tests/__init__.py +0 -0
  86. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/tests/conftest.py +0 -0
  87. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/tests/test_cli/__init__.py +0 -0
  88. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/tests/test_cli/test_commands.py +0 -0
  89. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/tests/test_cli/test_note_ops.py +0 -0
  90. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/tests/test_core/__init__.py +0 -0
  91. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/tests/test_core/test_frontmatter.py +0 -0
  92. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/tests/test_core/test_note.py +0 -0
  93. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/tests/test_core/test_sync.py +0 -0
  94. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/tests/test_core/test_vault.py +0 -0
  95. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/tests/test_graph/__init__.py +0 -0
  96. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/tests/test_graph/test_links.py +0 -0
  97. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/tests/test_search/__init__.py +0 -0
  98. {hyperresearch-0.2.0 → hyperresearch-0.3.0}/tests/test_search/test_fts.py +0 -0
@@ -11,3 +11,5 @@ build/
11
11
  .mypy_cache/
12
12
  .ruff_cache/
13
13
  *.egg
14
+ .env
15
+ bench/
@@ -1,5 +1,35 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.0] - 2026-04-11
4
+
5
+ ### New
6
+
7
+ - **Native PDF extraction** — PDFs detected by URL pattern, downloaded directly with httpx, text extracted with pymupdf. No browser needed. arXiv `/abs/` links auto-convert to `/pdf/`.
8
+ - **Raw file storage** — PDF bytes saved to `research/raw/<note-id>.pdf`, linked from note frontmatter via `raw_file:` field. Agent can read the raw PDF directly.
9
+ - **Junk page detection** — `WebResult.looks_like_junk()` catches Cloudflare captchas, error pages, cookie walls, binary garbage, reCAPTCHA, and empty content before saving. Returns `JUNK_CONTENT` error instead of creating useless notes.
10
+ - **Gap analysis step** — after drafting the report, agent re-reads the original query word by word, identifies gaps, and does another full round of research to fill them.
11
+ - **Adversarial audit** — two subagents (comprehensiveness auditor + logic/structure auditor) review the draft in parallel. Runs up to 2 loops. Agent uses wait time productively to improve summaries and tags.
12
+ - **Source checkpoint** — agent must review collected sources before writing any draft. Checks coverage breadth, missing angles, uncited references. Expects 50-100+ sources on complex topics.
13
+ - **Scholarly API guidance** — CLAUDE.md and `/research` skill now encourage use of arXiv, Semantic Scholar, CrossRef, and PubMed APIs for academic research.
14
+ - **Date injection** — today's date injected programmatically into CLAUDE.md at install time.
15
+ - **Multi-round research emphasis** — agent docs stress multiple rounds of search → fetch → follow links, spawning 10-20 fetcher agents per round.
16
+
17
+ ### Changed
18
+
19
+ - **Agent-driven curation replaces auto-enrich** — removed the keyword-matching `enrich_note_file()` from the fetch pipeline. Fetcher subagents now read content, write real summaries, add meaningful tags, and quality-check each source (deprecating junk/off-topic notes).
20
+ - **Fetcher subagent quality gate** — subagent now checks relevance, content quality, and duplicates. Deprecates bad notes instead of leaving them as drafts.
21
+ - **`_resolve_executable()` prioritizes venv** — checks venv `Scripts/` dir before PATH, preventing system-wide installs from overriding the project's venv.
22
+ - **PDF binary detection improved** — checks for `endstream`, `endobj`, `/FlateDecode`, `%PDF-` markers and non-printable character ratios. Catches binary garbage in both single-fetch and batch-fetch paths.
23
+ - **Junk detection thresholds raised** — empty content threshold: 100→300 chars, cookie page threshold: 500→1500 chars. Added `recaptcha`, `checking your browser`, `verify you are human` to bot detection signals.
24
+ - **SSL verification disabled for PDF downloads** — academic sites often have self-signed certs. `httpx.get(verify=False)` for PDF fetches only.
25
+ - **PDF fetch logging** — `_fetch_pdf` failures now logged via `logging.getLogger("hyperresearch.pdf")` instead of silently returning None.
26
+ - **Fetcher subagent continues on failure** — no longer stops on first fetch error, tries all URLs and reports failures individually.
27
+
28
+ ### Added dependencies
29
+
30
+ - `pymupdf>=1.24` — PDF text extraction
31
+ - `httpx>=0.27` — direct HTTP downloads for PDFs (bypasses browser)
32
+
3
33
  ## [0.2.0] - 2026-04-10
4
34
 
5
35
  ### New
@@ -68,5 +98,6 @@ Initial release. Forked from [llm-kasten](https://github.com/jordan-gibbs/llm-ka
68
98
  - Web viewer with force-directed knowledge graph
69
99
  - 70 tests
70
100
 
101
+ [0.3.0]: https://github.com/jordan-gibbs/hyperresearch/releases/tag/v0.3.0
71
102
  [0.2.0]: https://github.com/jordan-gibbs/hyperresearch/releases/tag/v0.2.0
72
103
  [0.1.0]: https://github.com/jordan-gibbs/hyperresearch/releases/tag/v0.1.0
@@ -0,0 +1,188 @@
1
+ Metadata-Version: 2.4
2
+ Name: hyperresearch
3
+ Version: 0.3.0
4
+ Summary: Agent-driven research knowledge base. Browse, collect, and synthesize web sources into a searchable wiki.
5
+ Project-URL: Homepage, https://github.com/jordan-gibbs/hyperresearch
6
+ Project-URL: Repository, https://github.com/jordan-gibbs/hyperresearch
7
+ Project-URL: Issues, https://github.com/jordan-gibbs/hyperresearch/issues
8
+ Author-email: Jordan Gibbs <jordan@jordangibbs.xyz>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: agent,cli,knowledge-base,llm,markdown,research,wiki,zettelkasten
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Text Processing :: Markup :: Markdown
20
+ Requires-Python: >=3.11
21
+ Requires-Dist: crawl4ai>=0.4
22
+ Requires-Dist: httpx>=0.27
23
+ Requires-Dist: jinja2>=3.1
24
+ Requires-Dist: platformdirs>=4.0
25
+ Requires-Dist: pydantic>=2.0
26
+ Requires-Dist: pymupdf>=1.24
27
+ Requires-Dist: pyyaml>=6.0
28
+ Requires-Dist: rich>=13.0
29
+ Requires-Dist: typer>=0.9.0
30
+ Provides-Extra: all
31
+ Requires-Dist: mcp>=1.6; extra == 'all'
32
+ Provides-Extra: dev
33
+ Requires-Dist: mypy>=1.8; extra == 'dev'
34
+ Requires-Dist: pytest-cov>=4.1; extra == 'dev'
35
+ Requires-Dist: pytest>=7.4; extra == 'dev'
36
+ Requires-Dist: ruff>=0.3; extra == 'dev'
37
+ Provides-Extra: mcp
38
+ Requires-Dist: mcp>=1.6; extra == 'mcp'
39
+ Description-Content-Type: text/markdown
40
+
41
+ <p align="center">
42
+ <img src="assets/banner.png" alt="HYPERRESEARCH" width="700">
43
+ </p>
44
+
45
+ <h3 align="center">Ultra deep, persistent web research for AI coding agents</h3>
46
+
47
+ <p align="center">
48
+ <a href="https://pypi.org/project/hyperresearch/"><img src="https://img.shields.io/pypi/v/hyperresearch" alt="PyPI version"></a>
49
+ <a href="https://pypi.org/project/hyperresearch/"><img src="https://img.shields.io/pypi/pyversions/hyperresearch" alt="Python 3.11+"></a>
50
+ <a href="LICENSE"><img src="https://img.shields.io/github/license/jordan-gibbs/hyperresearch" alt="License: MIT"></a>
51
+ <a href="https://github.com/jordan-gibbs/hyperresearch"><img src="https://img.shields.io/github/stars/jordan-gibbs/hyperresearch?style=social" alt="GitHub stars"></a>
52
+ </p>
53
+
54
+ ---
55
+
56
+ Your AI agent searches the web, finds great sources, synthesizes an answer — then the session ends and everything is gone. Next time, it starts from zero.
57
+
58
+ **Hyperresearch makes research persist.** Every source your agent finds is fetched with a real headless browser, saved as searchable markdown, and indexed into a knowledge base that compounds across sessions. Hyperresearch can follow maps of links to digest paths of information that current agent web searching isn't capable of.
59
+
60
+ ```bash
61
+ pip install hyperresearch
62
+ hyperresearch install
63
+ ```
64
+
65
+ ## What people use it for
66
+
67
+ - **In-depth topic research** — "Research the latest advances in state space models" → agent fetches 20+ papers, docs, and blog posts, follows citations to primary sources, builds a linked knowledge graph
68
+ - **News tracking over time** — run research sessions weekly on a topic, each session builds on what's already collected, nothing gets re-fetched
69
+ - **State-of-the-art surveys** — "What's the current SOTA for speech recognition?" → agent goes down rabbit holes, collects benchmarks, papers, and implementations
70
+ - **Competitive analysis** — scrape company pages, LinkedIn profiles, product docs, news articles into a persistent, searchable corpus
71
+ - **Due diligence** — aggregate everything about a person, company, or technology from across the web with authenticated crawling (LinkedIn, Twitter, paywalled sites)
72
+
73
+ ## How it works
74
+
75
+ 1. **You ask your agent to research something**
76
+ 2. **Agent searches the web** — multiple queries, different angles
77
+ 3. **Fetches every source** with a real headless browser (crawl4ai) — JS rendering, bot detection bypass, login-gated content
78
+ 4. **Saves each page** as a searchable markdown note with tags, summary, and source tracking
79
+ 5. **Follows links** to primary sources — the paper, not the blog post about the paper
80
+ 6. **Auto-links related notes** with `[[wiki-links]]` across the knowledge graph
81
+ 7. **Synthesizes findings** into a summary note linking all sources
82
+ 8. **Next session** — agent checks the KB before searching the web. Knowledge compounds.
83
+
84
+ ```
85
+ your-repo/
86
+ .hyperresearch/ # Config + SQLite FTS5 index (rebuildable)
87
+ research/
88
+ notes/ # Markdown notes — the source of truth
89
+ index/ # Auto-generated wiki pages
90
+ CLAUDE.md # Agent docs (auto-injected)
91
+ ```
92
+
93
+ ## Works with every major agent
94
+
95
+ `hyperresearch install` hooks into your agent in one step:
96
+
97
+ | Platform | Hook | Trigger |
98
+ |----------|------|---------|
99
+ | **Claude Code** | `.claude/settings.json` + `/research` skill | Before WebSearch, WebFetch |
100
+ | **Codex** | `.codex/hooks.json` | Before Bash |
101
+ | **Cursor** | `.cursor/rules/hyperresearch.mdc` | Always-apply rule |
102
+ | **Gemini CLI** | `.gemini/settings.json` | Before tool calls |
103
+
104
+ ```bash
105
+ hyperresearch install --platform all # Hook every platform at once
106
+ ```
107
+
108
+ ## Key features
109
+
110
+ - **Real headless browser** — crawl4ai runs local Chromium. Handles JavaScript, bypasses bot detection, renders SPAs. Not a simple HTTP fetch.
111
+ - **Native PDF extraction** — fetches PDFs directly, extracts full text with pymupdf, saves raw files to `research/raw/`. Academic papers, whitepapers, reports — all first-class citizens.
112
+ - **Authenticated crawling** — log into LinkedIn, Twitter, paywalled news. Your sessions persist across fetches.
113
+ - **Agent-driven curation** — fetcher subagents read each source, write real summaries, add meaningful tags, and flag junk. No keyword-matching shortcuts.
114
+ - **Junk detection** — Cloudflare captchas, error pages, cookie walls, binary garbage, login redirects all caught and rejected before saving.
115
+ - **Multi-round deep research** — the agent does multiple rounds of search → fetch → follow links, with a source checkpoint that forces breadth before synthesis.
116
+ - **Gap analysis + adversarial audit** — after drafting, the agent re-reads the original query to find gaps, then spawns two auditor subagents (comprehensiveness + logic) to tear the draft apart. Runs twice.
117
+ - **Cheap parallel fetching** — ships a Haiku-powered subagent that fetches, summarizes, and quality-checks URLs in parallel for pennies. Spawn 10-20 per round.
118
+ - **Scholarly API guidance** — agent docs encourage use of arXiv, Semantic Scholar, CrossRef, and PubMed APIs for academic topics.
119
+ - **`/research` skill** — scripted deep research workflow. Clarifies ambiguous requests, searches broadly, fetches aggressively, follows rabbit holes, audits, synthesizes.
120
+ - **Smart SPA wait** — polls DOM stability instead of fixed delays. Fast pages finish instantly, SPAs get up to 10 seconds.
121
+ - **FTS5 search** — instant full-text search across thousands of notes with BM25 ranking
122
+ - **Knowledge graph** — `[[wiki-links]]`, backlinks, hub detection, auto-linking
123
+ - **MCP server** — 13 tools (read + write) for Claude Desktop, Cursor, or any MCP client
124
+ - **Note lifecycle** — draft → review → evergreen → stale → deprecated → archive
125
+
126
+ ## Commands
127
+
128
+ ```bash
129
+ # Research
130
+ hyperresearch fetch <url> --tag t -j # Fetch a URL into the KB
131
+ hyperresearch fetch-batch <urls...> -j # Fetch many URLs at once
132
+ hyperresearch research "topic" --max 5 -j # Full pipeline: search → fetch → link → synthesize
133
+
134
+ # Search
135
+ hyperresearch search "query" -j # Full-text search
136
+ hyperresearch search "query" --max-tokens 8000 # Stay within context budget
137
+ hyperresearch note show <id> -j # Read a note
138
+
139
+ # Knowledge graph
140
+ hyperresearch link --auto -j # Auto-link related notes
141
+ hyperresearch graph hubs -j # Most-connected notes
142
+ hyperresearch graph backlinks <id> -j # What links to this note
143
+
144
+ # Manage
145
+ hyperresearch sources list -j # Every URL ever fetched
146
+ hyperresearch lint -j # Health check
147
+ hyperresearch repair -j # Fix links, rebuild indexes
148
+ ```
149
+
150
+ Every command returns `{"ok": true, "data": {...}}` with `-j`.
151
+
152
+ ## Authenticated crawling
153
+
154
+ Fetch from LinkedIn, Twitter, paywalled sites — anything you can log into:
155
+
156
+ ```bash
157
+ hyperresearch setup # Browser opens. Log into your sites. Done.
158
+ ```
159
+
160
+ ```toml
161
+ # .hyperresearch/config.toml
162
+ [web]
163
+ provider = "crawl4ai"
164
+ profile = "research"
165
+ ```
166
+
167
+ LinkedIn, Twitter, Facebook, Instagram, and TikTok automatically use a visible browser to avoid session kills.
168
+
169
+ ## Philosophy
170
+
171
+ - **No LLM calls.** Hyperresearch stores, indexes, and searches. Your agent is the LLM.
172
+ - **Markdown is truth.** Notes are plain files. SQLite is a rebuildable cache.
173
+ - **Over-collect, then prune.** Fetch aggressively. Deprecate what you don't need.
174
+ - **Check before you fetch.** Hooks kill redundant searches across sessions.
175
+ - **Raw content is king.** Save the original with formatting, not a rewritten summary.
176
+
177
+ ## Requirements
178
+
179
+ - Python 3.11+
180
+ - Windows, macOS, Linux
181
+
182
+ ## License
183
+
184
+ [MIT](LICENSE)
185
+
186
+ ## Star History
187
+
188
+ [![Star History Chart](https://api.star-history.com/svg?repos=jordan-gibbs/hyperresearch&type=Date)](https://star-history.com/#jordan-gibbs/hyperresearch&Date)
@@ -0,0 +1,148 @@
1
+ <p align="center">
2
+ <img src="assets/banner.png" alt="HYPERRESEARCH" width="700">
3
+ </p>
4
+
5
+ <h3 align="center">Ultra deep, persistent web research for AI coding agents</h3>
6
+
7
+ <p align="center">
8
+ <a href="https://pypi.org/project/hyperresearch/"><img src="https://img.shields.io/pypi/v/hyperresearch" alt="PyPI version"></a>
9
+ <a href="https://pypi.org/project/hyperresearch/"><img src="https://img.shields.io/pypi/pyversions/hyperresearch" alt="Python 3.11+"></a>
10
+ <a href="LICENSE"><img src="https://img.shields.io/github/license/jordan-gibbs/hyperresearch" alt="License: MIT"></a>
11
+ <a href="https://github.com/jordan-gibbs/hyperresearch"><img src="https://img.shields.io/github/stars/jordan-gibbs/hyperresearch?style=social" alt="GitHub stars"></a>
12
+ </p>
13
+
14
+ ---
15
+
16
+ Your AI agent searches the web, finds great sources, synthesizes an answer — then the session ends and everything is gone. Next time, it starts from zero.
17
+
18
+ **Hyperresearch makes research persist.** Every source your agent finds is fetched with a real headless browser, saved as searchable markdown, and indexed into a knowledge base that compounds across sessions. Hyperresearch can follow maps of links to digest paths of information that current agent web searching isn't capable of.
19
+
20
+ ```bash
21
+ pip install hyperresearch
22
+ hyperresearch install
23
+ ```
24
+
25
+ ## What people use it for
26
+
27
+ - **In-depth topic research** — "Research the latest advances in state space models" → agent fetches 20+ papers, docs, and blog posts, follows citations to primary sources, builds a linked knowledge graph
28
+ - **News tracking over time** — run research sessions weekly on a topic, each session builds on what's already collected, nothing gets re-fetched
29
+ - **State-of-the-art surveys** — "What's the current SOTA for speech recognition?" → agent goes down rabbit holes, collects benchmarks, papers, and implementations
30
+ - **Competitive analysis** — scrape company pages, LinkedIn profiles, product docs, news articles into a persistent, searchable corpus
31
+ - **Due diligence** — aggregate everything about a person, company, or technology from across the web with authenticated crawling (LinkedIn, Twitter, paywalled sites)
32
+
33
+ ## How it works
34
+
35
+ 1. **You ask your agent to research something**
36
+ 2. **Agent searches the web** — multiple queries, different angles
37
+ 3. **Fetches every source** with a real headless browser (crawl4ai) — JS rendering, bot detection bypass, login-gated content
38
+ 4. **Saves each page** as a searchable markdown note with tags, summary, and source tracking
39
+ 5. **Follows links** to primary sources — the paper, not the blog post about the paper
40
+ 6. **Auto-links related notes** with `[[wiki-links]]` across the knowledge graph
41
+ 7. **Synthesizes findings** into a summary note linking all sources
42
+ 8. **Next session** — agent checks the KB before searching the web. Knowledge compounds.
43
+
44
+ ```
45
+ your-repo/
46
+ .hyperresearch/ # Config + SQLite FTS5 index (rebuildable)
47
+ research/
48
+ notes/ # Markdown notes — the source of truth
49
+ index/ # Auto-generated wiki pages
50
+ CLAUDE.md # Agent docs (auto-injected)
51
+ ```
52
+
53
+ ## Works with every major agent
54
+
55
+ `hyperresearch install` hooks into your agent in one step:
56
+
57
+ | Platform | Hook | Trigger |
58
+ |----------|------|---------|
59
+ | **Claude Code** | `.claude/settings.json` + `/research` skill | Before WebSearch, WebFetch |
60
+ | **Codex** | `.codex/hooks.json` | Before Bash |
61
+ | **Cursor** | `.cursor/rules/hyperresearch.mdc` | Always-apply rule |
62
+ | **Gemini CLI** | `.gemini/settings.json` | Before tool calls |
63
+
64
+ ```bash
65
+ hyperresearch install --platform all # Hook every platform at once
66
+ ```
67
+
68
+ ## Key features
69
+
70
+ - **Real headless browser** — crawl4ai runs local Chromium. Handles JavaScript, bypasses bot detection, renders SPAs. Not a simple HTTP fetch.
71
+ - **Native PDF extraction** — fetches PDFs directly, extracts full text with pymupdf, saves raw files to `research/raw/`. Academic papers, whitepapers, reports — all first-class citizens.
72
+ - **Authenticated crawling** — log into LinkedIn, Twitter, paywalled news. Your sessions persist across fetches.
73
+ - **Agent-driven curation** — fetcher subagents read each source, write real summaries, add meaningful tags, and flag junk. No keyword-matching shortcuts.
74
+ - **Junk detection** — Cloudflare captchas, error pages, cookie walls, binary garbage, login redirects all caught and rejected before saving.
75
+ - **Multi-round deep research** — the agent does multiple rounds of search → fetch → follow links, with a source checkpoint that forces breadth before synthesis.
76
+ - **Gap analysis + adversarial audit** — after drafting, the agent re-reads the original query to find gaps, then spawns two auditor subagents (comprehensiveness + logic) to tear the draft apart. Runs twice.
77
+ - **Cheap parallel fetching** — ships a Haiku-powered subagent that fetches, summarizes, and quality-checks URLs in parallel for pennies. Spawn 10-20 per round.
78
+ - **Scholarly API guidance** — agent docs encourage use of arXiv, Semantic Scholar, CrossRef, and PubMed APIs for academic topics.
79
+ - **`/research` skill** — scripted deep research workflow. Clarifies ambiguous requests, searches broadly, fetches aggressively, follows rabbit holes, audits, synthesizes.
80
+ - **Smart SPA wait** — polls DOM stability instead of fixed delays. Fast pages finish instantly, SPAs get up to 10 seconds.
81
+ - **FTS5 search** — instant full-text search across thousands of notes with BM25 ranking
82
+ - **Knowledge graph** — `[[wiki-links]]`, backlinks, hub detection, auto-linking
83
+ - **MCP server** — 13 tools (read + write) for Claude Desktop, Cursor, or any MCP client
84
+ - **Note lifecycle** — draft → review → evergreen → stale → deprecated → archive
85
+
86
+ ## Commands
87
+
88
+ ```bash
89
+ # Research
90
+ hyperresearch fetch <url> --tag t -j # Fetch a URL into the KB
91
+ hyperresearch fetch-batch <urls...> -j # Fetch many URLs at once
92
+ hyperresearch research "topic" --max 5 -j # Full pipeline: search → fetch → link → synthesize
93
+
94
+ # Search
95
+ hyperresearch search "query" -j # Full-text search
96
+ hyperresearch search "query" --max-tokens 8000 # Stay within context budget
97
+ hyperresearch note show <id> -j # Read a note
98
+
99
+ # Knowledge graph
100
+ hyperresearch link --auto -j # Auto-link related notes
101
+ hyperresearch graph hubs -j # Most-connected notes
102
+ hyperresearch graph backlinks <id> -j # What links to this note
103
+
104
+ # Manage
105
+ hyperresearch sources list -j # Every URL ever fetched
106
+ hyperresearch lint -j # Health check
107
+ hyperresearch repair -j # Fix links, rebuild indexes
108
+ ```
109
+
110
+ Every command returns `{"ok": true, "data": {...}}` with `-j`.
111
+
112
+ ## Authenticated crawling
113
+
114
+ Fetch from LinkedIn, Twitter, paywalled sites — anything you can log into:
115
+
116
+ ```bash
117
+ hyperresearch setup # Browser opens. Log into your sites. Done.
118
+ ```
119
+
120
+ ```toml
121
+ # .hyperresearch/config.toml
122
+ [web]
123
+ provider = "crawl4ai"
124
+ profile = "research"
125
+ ```
126
+
127
+ LinkedIn, Twitter, Facebook, Instagram, and TikTok automatically use a visible browser to avoid session kills.
128
+
129
+ ## Philosophy
130
+
131
+ - **No LLM calls.** Hyperresearch stores, indexes, and searches. Your agent is the LLM.
132
+ - **Markdown is truth.** Notes are plain files. SQLite is a rebuildable cache.
133
+ - **Over-collect, then prune.** Fetch aggressively. Deprecate what you don't need.
134
+ - **Check before you fetch.** Hooks kill redundant searches across sessions.
135
+ - **Raw content is king.** Save the original with formatting, not a rewritten summary.
136
+
137
+ ## Requirements
138
+
139
+ - Python 3.11+
140
+ - Windows, macOS, Linux
141
+
142
+ ## License
143
+
144
+ [MIT](LICENSE)
145
+
146
+ ## Star History
147
+
148
+ [![Star History Chart](https://api.star-history.com/svg?repos=jordan-gibbs/hyperresearch&type=Date)](https://star-history.com/#jordan-gibbs/hyperresearch&Date)
Binary file
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "hyperresearch"
7
- version = "0.2.0"
7
+ version = "0.3.0"
8
8
  description = "Agent-driven research knowledge base. Browse, collect, and synthesize web sources into a searchable wiki."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -28,12 +28,14 @@ dependencies = [
28
28
  "pydantic>=2.0",
29
29
  "jinja2>=3.1",
30
30
  "platformdirs>=4.0",
31
+ "Crawl4AI>=0.4",
32
+ "pymupdf>=1.24",
33
+ "httpx>=0.27",
31
34
  ]
32
35
 
33
36
  [project.optional-dependencies]
34
- crawl4ai = ["Crawl4AI>=0.4"]
35
37
  mcp = ["mcp>=1.6"]
36
- all = ["hyperresearch[crawl4ai,mcp]"]
38
+ all = ["hyperresearch[mcp]"]
37
39
  dev = [
38
40
  "pytest>=7.4",
39
41
  "pytest-cov>=4.1",
@@ -116,6 +116,16 @@ def fetch(
116
116
  console.print(f"[red]Auth required:[/] {msg}")
117
117
  raise typer.Exit(1)
118
118
 
119
+ # Detect junk pages — captcha, error pages, binary garbage, empty content
120
+ junk_reason = result.looks_like_junk()
121
+ if junk_reason:
122
+ msg = f"Skipped junk content from {url}: {junk_reason}"
123
+ if json_output:
124
+ output(error(msg, "JUNK_CONTENT"), json_mode=True)
125
+ else:
126
+ console.print(f"[yellow]Skipped:[/] {msg}")
127
+ raise typer.Exit(1)
128
+
119
129
  # Write note
120
130
  note_title = title or result.title or urlparse(url).path.split("/")[-1] or "Untitled"
121
131
  domain = result.domain
@@ -140,10 +150,40 @@ def fetch(
140
150
  extra_frontmatter=extra_meta,
141
151
  )
142
152
 
143
- # Auto-enrich: add suggested tags and summary before sync
144
- from hyperresearch.core.enrich import enrich_note_file
145
-
146
- enrich_note_file(note_path, conn, tags)
153
+ # Save raw file (PDF, etc.) if present
154
+ raw_file_path = None
155
+ if result.raw_bytes and result.raw_content_type:
156
+ ext_map = {
157
+ "application/pdf": ".pdf",
158
+ "image/png": ".png",
159
+ "image/jpeg": ".jpg",
160
+ "image/gif": ".gif",
161
+ "image/webp": ".webp",
162
+ }
163
+ ext = ext_map.get(result.raw_content_type, "")
164
+ if ext:
165
+ raw_dir = vault.root / "research" / "raw"
166
+ raw_dir.mkdir(parents=True, exist_ok=True)
167
+ raw_filename = note_path.stem + ext
168
+ raw_file = raw_dir / raw_filename
169
+ raw_file.write_bytes(result.raw_bytes)
170
+ raw_file_path = f"raw/{raw_filename}"
171
+
172
+ # Note: tagging and summarization is the agent's job, not an automatic process.
173
+ # The agent reads the fetched content and writes meaningful summaries and tags.
174
+
175
+ # Add raw_file reference to frontmatter AFTER enrich (enrich rewrites frontmatter)
176
+ if raw_file_path:
177
+ note_text = note_path.read_text(encoding="utf-8")
178
+ if note_text.startswith("---") and "raw_file:" not in note_text:
179
+ end_idx = note_text.find("---", 3)
180
+ if end_idx != -1:
181
+ note_text = (
182
+ note_text[:end_idx]
183
+ + f"raw_file: {raw_file_path}\n"
184
+ + note_text[end_idx:]
185
+ )
186
+ note_path.write_text(note_text, encoding="utf-8")
147
187
 
148
188
  # Sync first so the note exists in the notes table (needed for FK on sources/assets)
149
189
  note_id = note_path.stem
@@ -175,6 +215,7 @@ def fetch(
175
215
  "path": str(note_path.relative_to(vault.root)),
176
216
  "word_count": len(result.content.split()),
177
217
  "assets": saved_assets,
218
+ "raw_file": raw_file_path,
178
219
  }
179
220
 
180
221
  if json_output: