hyperresearch

jordan-gibbsMIT活跃维护

把 Claude Code 或 Codex 变成深度研究智能体,自动采集、检索并综合网页资料,沉淀成可持续积累、可搜索的持久化 Wiki。

Convert Claude Code or Codex into the most intelligent Deep Research Agent. Collect, search, and synthesize web research into a persistent, searchable wiki that builds on itself. Hosted API + MCP: hyperresearch.ai

v0.13.0发布于 2026-10-27 21:19 UTC4,506star +70 / 7 天463fork同步于 2026-11-10 17:39 UTC

怎么上手

由 README 提炼,执行前请确认
cd your-project
pip install hyperresearch
hyperresearch install
硬件要求按 README 说明

README 未说明硬件要求;运行依赖 Python 3.11–3.14,研究过程需文件写入与网络访问

下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

把 Claude Code 或 Codex 变成深度研究代理,产出带引用审计、可复用来源库的研究报告

把 Claude Code 或 Codex 变成深度研究智能体,自动采集、检索并综合网页资料,沉淀成可持续积累、可搜索的持久化 Wiki。

核心能力

  • 16 步分层流水线,从拆解问题到成稿逐阶段执行
  • 每条引用发布前由怀疑式核查器验证是否支撑原句
  • 多源学术检索按 DOI 与标题去重,覆盖论文、临床试验与 SEC 文件
  • 所有来源存入可检索的 markdown+SQLite 库供后续会话复用
  • 崩溃的运行凭 manifest 从断点步骤恢复

容易踩的坑

Codex 支持尚未进入 PyPI 正式版,需用 pip install git+https://github.com/jordan-gibbs/hyperresearch 从 GitHub 安装;Codex 默认禁止写文件和联网,须用 --sandbox workspace-write -c sandbox_workspace_write.network_access=true 启动;Codex 无浏览器通道,遇登录墙或反爬的来源会留在升级队列中

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v0.13.0
  1. v0.13.0最新正式版2026-10-27 · 2026-10-27 21:19 UTC
    • Step prompts agree with each other (#102). Settles the contract conflicts listed in the issue: the no-re-synthesis invariant names the ship gate's compression pass as its one exception; width-sweep fetchers take no new topic searches but still chase the primary sources their batch cites; step 7 has a documented path for fewer than the target tensions when step 4 justified zero loci; a failed critic is re-spawned once and otherwise leaves an empty critic_failed findings file, since the ship gate checks all four exist; the step 11 outline leaves out Opinionated Synthesis for short reports; the step 1 example no longer shows a wrapper requirement in the decomposition; the readability recommender writes a JSON object, matching its schema; the polish auditor receives wrapper_contract_path so it knows whether to keep YAML frontmatter; step 16 hands off to the ship gate instead of declaring the run done; the one-chapter case in step 1.5 is described as an escape hatch; and the cite-check Goal states that non-numeric citations are sampled.
    • The pipeline runs on the OpenAI Codex CLI. hyperresearch install . --target codex installs the entry skill at .agents/skills/hyperresearch/, invoked as $hyperresearch <query>, along with the 18 step procedures as plain files under .hyperresearch/codex/steps/, the subagent roster as custom agents in .codex/agents/*.toml, a Stop hook in .codex/hooks.json, and an AGENTS.md block. The step procedures are plain files because Codex caps the skill listing and has no skill-to-skill invocation. --target all installs both platforms. --global --target codex writes the skill to ~/.agents/skills/ and the agents to ~/.codex/agents/. --target claude is the default and installs the same layout as before. Differences on Codex: there is no browser lane, so blocked fetches stay queued and are listed for the user; the Read+Edit tool locks are instructions rather than enforcement; and the Stop hook (hyperresearch run stop-gate) blocks the session from ending mid-pipeline. The Stop hook exists because an earlier Codex attempt answered inline and never touched the vault. Codex's sandbox defaults to read-only with no network, so a session needs --sandbox workspace-write -c sandbox_workspace_write.network_access=true. hyperresearch documents these flags and never writes to Codex's config.
    • The repo is a Codex plugin marketplace too. .codex-plugin/plugin.json and .agents/plugins/marketplace.json publish the same deep-research bootstrap skill as the Claude Code plugin: codex plugin marketplace add jordan-gibbs/hyperresearch, then codex plugin add hyperresearch@hyperresearch. The skill no longer assumes Claude Code. On Codex it runs install --target codex and then reads the entry skill directly, because Codex discovers skills when a session starts. It gains license and compatibility frontmatter and an agents/openai.yaml. Codex namespaces plugin skills, so from the plugin it is $hyperresearch:deep-research; installed standalone with npx skills add jordan-gibbs/hyperresearch -a codex (to .agents/skills/deep-research/) it is $deep-research. The openai.yaml starter prompt names the skill in words rather than by a $ mention that would only match one of those. The README now leads with Claude Code and Codex install paths side by side.
    • run resume follows the tier step 1 declared. A run is initialized with the installed gear's step list, and step 1 can reclassify it (usually to light) in prompt-decomposition.json. The ship gate already honoured that tier; resume_position did not, so a light-tier run that finished step 2 was told to resume at step 3, a step its tier skips. run resume, run status and the Codex Stop gate now use the declared tier's steps. Found during the first live Codex run.
    • The SSRF gate resolves the name httpx connects to (#161). check_url looked up the hostname as urlparse returns it, and getaddrinfo encodes
  2. v0.12.02026-09-24 · 2026-09-24 14:37 UTC
    查看更新说明

    Scholarly search filters, a Serply web provider, and the repo as a Claude Code plugin (/plugin marketplace add jordan-gibbs/hyperresearch).

    Behaviour change: crawl4ai's headless browser now verifies TLS certificates. A bad certificate raises CertVerificationError; [fetch] browser_verify_tls = false opts out.

    Migration: the v13 migration makes is_retracted nullable (unknown vs. checked) and runs on first open.

    Security: IPv4-mapped IPv6 classified by its IPv4; run tags and note ids confined to the vault; OA URLs through the SSRF gate.

    Also: Python 3.14, a PDF lane for the builtin provider, fence-length-aware code stripping, and an OpenAlex outage no longer erases a known retraction. Full list in CHANGELOG.md.

  3. v0.11.12026-09-11 · 2026-09-11 21:15 UTC
    查看更新说明

    Seven fixes from the backlog sweep

    • Markdown links no longer mint stub notes (#93, reported by @ThiagoMafra-Integrare). [[Label]](https://…) — everywhere on GitHub READMEs, awesome-lists and Wikipedia-shaped pages — parsed as a wikilink, and repair --stub (default on, and mandated after every session) turned each one into a real note that then topped _most-linked and inflated PageRank. WIKI_LINK_RE now refuses a ]] immediately followed by (; the hygiene filter also rejects unsubstituted {…} placeholders and unbalanced brackets. Resolver-minted stubs are excluded from both rankers and have their stale centrality zeroed, so vaults polluted before this fix recover on the next graph rank. The stub marker is centralized so the minting sites and the filter cannot drift.
    • claims ingest finds the claims (#69, reported by @fduple). The default scan read only the legacy research/temp/, while every producer and consumer had moved to research/runs/<tag>/temp/ — so the claims table was empty in every real run and claims matrix / targets were dead on arrival. The default now scans both; --tag narrows to the run. A zero-file default scan prints a hint instead of a bare zero.
    • A Semantic Scholar rate limit is reported as a rate limit (#70, reported by @fduple). A 429 was folded into "No metadata found" — an affirmatively wrong diagnosis. 429s now retry three times with backoff (honouring Retry-After), and an exhausted budget surfaces as rate_limited in sources score output rather than missing. Nothing is cached for a throttle, so the next run retries. Optional S2_API_KEY support, scoped to semanticscholar.org hosts only — the fetch helper is shared with Unpaywall and Europe PMC, and an unscoped header would have shipped the key to them.
    • run resume names a skill that exists, chapters reach the manifest, step 8 keeps its preflight gaps (#100, from @darlingm's contract audit in #88). resume printed hyperresearch-2 for a skill named hyperresearch-2-width-sweep, and CLAUDE.md advertises resume as the recovery path — the slug now comes from the installer's own step table. set_chapter() had zero callers; it is gone, and the chapter-plan event the partition skill already emits now registers the chapter, so a resumed dissertation reports what is actually pending. Step 8's subagent wrote to the same file the preflight had just written; it gets its own output and a merge step, and gap records carry the id the dispatch already referenced.
    • Every pipeline constant is authored once (#101, from @darlingm's contract audit in #88). citation_density_min sat unread on the profile while two gates hardcoded their own number; the draft orchestrator hardcoded word targets the synthesizer templated, so on premier the two halves of a run were 60% apart; step 4 templated loci_analysts and then said "both" and wrote loci-a.json / loci-b.json. A new test asserts every Profile field is read somewhere outside profiles.py — and it found eight more dead fields (comparisons_tensions, source_tensions, tension_survey, tension_full_reads, corpus_critic_fetchers, citation_totals, utility_scoring, vault_check_interval_s), all now wired into the prose that had been hardcoding them. char_targets_no_word_boundary is authored per gear at the 3:1 ratio the profile already used, which moved full's argumentative range from 20000–25000 to 15000–30000 — the old span was 1.25× against a 2× word span.
    • Citation density is per 1000 effective words, not per 1000 characters (#76). The floor meant something roughly 3× stricter for CJK than for English. The denominator reuses #64's boundary detection: whitespace tokens where they exist, characters ÷ chars_per_word_no_word_boundary (3.0) where they don't. The floor is re-derived as citation_density_min = 9.0 per 1000 words, which is what 1.5 per 1000 characters worked out to for English prose — English verdict
  4. v0.11.02026-09-11 · 2026-09-11 18:17 UTC
    查看更新说明

    SSRF gate + size caps for fetches (builtin, crawl4ai entry points, PDF and image downloads)

    • The builtin provider, the crawl4ai entry points, and PDF and image downloads now go through an SSRF gate (web/safe_http.py): http/https only; hostnames resolving to private, loopback, link-local, multicast, reserved, CGNAT (RFC 6598), or unspecified addresses are refused (cloud metadata, RFC1918, [::1], 100.64.0.0/10, …). Not covered: the fixed-host API calls in core/embed.py and core/scholar.py, which take no attacker-influenced URLs. On the safe_get paths (builtin provider, PDF and image downloads) redirects are followed manually and every hop is revalidated. The browser lanes (crawl4ai fetch(), fetch_many(), and the visible-window path) are gated at entry AND re-checked on the URL the browser actually landed on — the browser follows redirects internally, so the entry check alone cannot vouch for the destination. A post-hoc recheck cannot stop the request that already fired (blind SSRF survives it), but it keeps private-network content out of the vault; the same-host case skips the extra DNS lookup. Refused URLs in a batch are logged and skipped, not fatal. The hostname check is best-effort against DNS rebinding (httpx re-resolves at connect time); the residual window is documented in the module docstring.
    • [fetch] allow_private_hosts — escape hatch for self-hosted mirrors and intranet sources: hostnames (exact, case-insensitive) or CIDRs that may be fetched despite resolving to private space. Empty by default; consulted by check_url everywhere, including redirect hops and the final-URL recheck. A malformed CIDR entry errors loudly instead of being silently ignored.
    • Response-size caps, streamed and enforced mid-body so a lying or chunked server cannot exhaust memory. Configurable via new [fetch] settings max_html_bytes (10 MiB), max_pdf_bytes (25 MiB), max_image_bytes (2 MiB). A gate refusal on an image download is printed, not silently swallowed.
    • No unverified-TLS retry. A certificate failure on a PDF fetch is a refusal that names the existing pdf_verify_tls = false opt-out — never an automatic verify-off retry, which a MITM could force with a bad cert. The refusal is its own exception type (CertVerificationError), and a cert-refused PDF is never handed to the browser fallback lane: that lane runs with TLS errors ignored, so "falling back" there would be the automatic unverified retry by another name. In a batch it is a loud skip instead.

    Scholarly discovery: eight sources through one client layer

    Academic discovery used to be four URL templates rendered into the agent's instructions by core/agent_docs.py, which the model was trusted to assemble and call by hand. No retry, no rate limiting, no dedup, no offline tests — and one of those templates shipped [email protected], a shared placeholder on every install, which is exactly the anti-pattern the open-access resolver refuses to commit for Unpaywall. It is now a real package.

    • hpr scholar search and hpr scholar sources. One query hits every configured provider, merges records that are the same work, and returns one list. sources lists what is wired, what each covers, and why anything is unavailable — so a user is never guessing which source to reach for.
    • Dedup is by DOI first, then normalized title within ±1 year. The year tolerance is deliberate: providers disagree systematically about online-first versus print year for the same article. Two different DOIs never merge regardless of title, which is what stops four 2025 reprints of a famous paper from collapsing into one record. A work confirmed by several providers carries them in also_in, with the highest citation count and the longest abstract.
    • --limit is per provider, not a cap on the merged list. A post-merge cap would show only the first provider's records at small limits and make every other source look emp
  5. v0.10.12026-09-11 · 2026-09-11 16:03 UTC
    查看更新说明

    A maintenance release. Everything here is a contributed fix, and two of them unblock users who could not ship a run at all.

    • The length-in-range verify gate no longer measures CJK reports with a Latin-script ruler (#71, fixed by @tetra4rnav in #64). verify_run counted whitespace-separated tokens, which in Japanese or Chinese counts almost nothing — a correctly-sized report measured roughly 20x short and run finish hard-blocked it, with no honest way past the gate. Length is now measured in characters when whitespace doesn't segment the text, against a new char_targets_no_word_boundary profile field. Detection is by average token length rather than Unicode range, which matters: Hangul is space-delimited, and a range-based check would have broken Korean while fixing Japanese. This shipped to main three days after the 0.10.0 tag and has been sitting unreleased since.

    • hpr serve no longer hangs on an idle browser connection (#87, reported by @muppavv, fixed by @maximilliangrand in #96). The viewer ran a single-threaded HTTPServer whose handler set no read timeout, so one socket that connected and sent nothing starved every other client — and Chrome opens exactly such a preconnect socket, which meant the first page load with --open could poison the server. The symptom was indistinguishable from a hang: no error, no CPU. Now ThreadingHTTPServer with a handler read timeout. The shared SQLite connection that made threading unsafe was correctly retired at the same time, rather than papered over with a lock.

    • An invalid --status is rejected instead of silently corrupting a note (@MarceloSenai in #89). NoteMeta had no validate_assignment, so note update --status evergreeen wrote the typo straight to frontmatter. The note then failed validation on the next sync, dropped out of the index, and note list kept serving the stale row — every later edit to that note going unindexed too. The valid set is read from the NoteStatus enum rather than a hand-maintained list, so it can't drift.

    • "Purchase this article" is recognised as a paywall (@MarceloSenai in #91). The phrase list had "buy this article" and "purchase pdf" but not this one, so those interstitials passed as full text and open-access recovery never ran — the note kept an abstract while the report cited it as though the paper had been read. The gate's own comment used this exact phrase as its worked example.

    • The registered PreToolUse hook command quotes the script path (@dajiaohuang in #98). install wrote node <path> into .claude/settings.json unquoted, and a hook command runs through a shell — so a project directory containing a space split the path there and node was handed a truncated script, making the hook exit 1 on every Glob, Grep, WebSearch and WebFetch call. Paths with spaces are ordinary (a Windows user directory, anything under My Documents). Installs written before this change keep the old entry, because the installer treats any existing hyperresearch hook as already installed; removing that entry and re-running install picks up the fix.

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    Hyperresearch turns Claude Code into a deep research agent, and it's #1 on the DRACO deep research benchmark, ahead of Claude Research, ChatGPT, Gemini and Perplexity. It runs in OpenAI Codex too. A tier-adaptive 16-step pipeline takes one prompt and produces an adversarially-audited report with full source provenance. Every source it reads lands in a persistent, searchable vault, so each session starts smarter than the last.

    Don't want to run it locally? Hyperresearch is the hosted version: the same pipeline, with no Claude Code or Codex install needed.

    [!NOTE] New: hyperresearch runs on OpenAI Codex. One command installs the full pipeline for Codex: entry skill, step procedures, the subagent roster as Codex custom agents, and a Stop hook that keeps Codex from skipping steps. Same vault, same ship gate as on Claude Code.

    pip install hyperresearch && hyperresearch install . --target codex
    codex --sandbox workspace-write -c sandbox_workspace_write.network_access=true   # then: $hyperresearch <question>
    

    Codex support ships in the next PyPI release; until then install from GitHub with pip install git+https://github.com/jordan-gibbs/hyperresearch. Details and what differs on Codex: Codex.

    See a sample report

    Read a full report before you install anything. These are unedited Deep runs from the hosted version, and you don't need to log in:

    These are the same kind of Deep runs that put Hyperresearch at #1 on DRACO. Method and per-task scores are on the benchmark page.

    Why it wins

    • 250+ sources in a single run. The premier scale profile targets 100–130 in the width sweep alone; citation chasing and gap-fill fetches more than double what actually lands in the corpus.
    • Every citation is verified before the report ships. A skeptical cite-checker audits whether each cited source actually supports its sentence. Hallucinated quotes and unacknowledged retractions are hard blocks at the gate.
    • Syndication doesn't count as consensus. An independence audit clusters derivative copies, so five reprints of one press release argue with the weight of one source.
    • Adversarial by construction. Four critics attack every draft in parallel, and a tool-locked patcher can only apply surgical edits. It physically cannot rewrite the report.
    • Eight scholarly sources, one query. hpr scholar search hits OpenAlex, Crossref, CORE, DOAB, ClinicalTrials.gov, SEC EDGAR and FRED through one client layer and returns a single list deduplicated by DOI and title. Books, trials and filings come back alongside papers, each tagged so the pipeline knows which is which. The humanities and social sciences are covered on purpose, not as an afterthought.
    • Paywalled papers get read, not skimmed. A closed paper normally enters a vault as a 1,500-character abstract that the report then cites as though it had been read. Hyperresearch asks Unpaywall, Europe PMC and CORE for a legal open-access copy and stores the full text instead, even when the publisher blocks the fetch outright. Every substitution is disclosed in the note, the frontmatter, and the CLI output.
    • Nothing is thrown away. Every source lands in a searchable markdown-plus-SQLite vault that your next session reuses before it fetches anything new.
    • Crashed runs resume. Each run keeps a manifest; run resume picks up at the exact step where it died.
    • Scales from 30 minutes to a dissertation. Bounded queries auto-route to a 5-step fast path. Opt-in dissertation runs (experimental) write 25K–80K words across chapters, from 300–450 sources.

    Browse the vault by DOI, venue, citation count, retraction status, or retrieved manuscript version with scholarly metadata filters.

    Install

    Works in Claude Code and OpenAI Codex: same pipeline, same vault.

    cd your-project
    pip install hyperresearch
    
    hyperresearch install                    # Claude Code, then: /hyperresearch <anything>
    hyperresearch install . --target codex   # OpenAI Codex, then: $hyperresearch <anything>
    

    --target all installs both side by side. Codex sessions need write access and network, see below.

    Prefer a plugin or a single skill? Each route below installs one bootstrap skill, deep-research, that sets the pipeline up in the current project on first use. It still needs pip install hyperresearch.

    Claude CodeOpenAI Codex
    Plugin/plugin marketplace add jordan-gibbs/hyperresearch/plugin install hyperresearch@hyperresearchcodex plugin marketplace add jordan-gibbs/hyperresearchcodex plugin add hyperresearch@hyperresearch
    Skill (skills.sh)npx skills add jordan-gibbs/hyperresearch -a claude-codenpx skills add jordan-gibbs/hyperresearch -a codex
    Invoke/hyperresearch:deep-research <question> (plugin)/deep-research <question> (skill)$hyperresearch:deep-research <question> (plugin)$deep-research <question> (skill)

    Or just ask for deep research in plain words; the skill triggers on its description.

    Python 3.11–3.14.

    Power users: hyperresearch install --global makes /hyperresearch reachable from every Claude Code session anywhere, at the cost of ~15 lines in every session's system reminder. Per-project install (above) keeps unrelated CC sessions clean.

    The bootstrap skill

    The repo is a Claude Code plugin marketplace, a Codex plugin marketplace, and a skills.sh source, and all three ship the same skill, deep-research. It checks for the hyperresearch CLI, runs hyperresearch install for the agent it is running in (--target codex under Codex), and hands off to the pipeline. The pipeline itself still comes from the Python package.

    If Claude Code does not pick up the newly installed skills and subagents, restart it in the same directory and run /hyperresearch <question>. Codex discovers skills at session start, so on first use the bootstrap reads the freshly installed entry skill directly; later sessions can start with $hyperresearch <question>.

    Codex

    The same pipeline runs on the OpenAI Codex CLI.

    cd your-project
    pip install hyperresearch && hyperresearch install . --target codex
    

    This installs the entry skill at .agents/skills/hyperresearch/, the step procedures under .hyperresearch/codex/steps/, the subagents as custom agents in .codex/agents/, a Stop hook in .codex/hooks.json, and a short block in AGENTS.md. --target all installs the Claude Code and Codex versions side by side. --global --target codex puts the entry skill in ~/.agents/skills/ and the agents in ~/.codex/agents/.

    Research needs to write files and reach the network, and Codex allows neither by default. Start the session with both enabled, then invoke the skill:

    codex --sandbox workspace-write -c sandbox_workspace_write.network_access=true
    # then, in the session:
    $hyperresearch <anything>
    
    # non-interactive:
    codex exec --sandbox workspace-write -c sandbox_workspace_write.network_access=true \
      --dangerously-bypass-hook-trust "\$hyperresearch <anything>"
    

    You pass these as flags; hyperresearch never edits your Codex config. codex exec cannot ask you to trust the project's hooks, so without --dangerously-bypass-hook-trust the Stop hook below does not run. Only pass it for hooks you have read (.codex/hooks.json).

    Subagents inherit the session's model. To pin a model per role, add a codex_models override to a profile in .hyperresearch/config.toml and re-run hyperresearch install . --target codex:

    [profile.full]
    codex_models = { fetcher = "gpt-5.4-mini", critics = "gpt-5.5" }
    

    What is different on Codex:

    • No browser lane. Codex has no Claude-in-Chrome equivalent, so fetches blocked by a login wall or bot wall stay in the escalation queue, and the final message lists them for you.
    • Tool locks are instructions, not enforcement. Codex custom agents have no per-agent tool allowlist. The patcher and polish auditor are told to make surgical edits only, but nothing stops them from doing more.
    • A Stop hook guards the pipeline. hyperresearch run stop-gate blocks the session from ending while the newest run is mid-pipeline, so Codex cannot quietly answer inline and stop. Codex runs a project's hooks only after you trust them.

    The 16-step research pipeline

    The entry skill is a thin router. It pins down the canonical research query, then invokes one step skill per phase via Claude Code's Skill tool (on Codex, it reads one step file per phase from .hyperresearch/codex/steps/). Each step's procedure loads into context only when that step actually runs. That's what stops a long pipeline from quietly dropping steps as its context rots.

    #StepWhat it doesTiers
    1DecomposeCanonical query → atomic items + coverage matrix + tier classificationall
    1.5Chapter partitionGroup atomic items into 4–10 chapters; steps 2–10 then loop per chapterdissertation
    2Width sweepMulti-perspective search plan + parallel fetcher wavesall
    3Contradiction graphPair contradictions across the corpus into ranked clustersfull
    4Loci analysisTwo parallel loci-analysts → scored loci with source budgetsfull
    5Depth investigationK parallel depth-investigators → interim notes with committed positionsfull
    6Cross-locus reconcileReconcile committed positions → comparisons.mdfull
    7Source tensionsExtract expert disagreements → source-tensions.jsonfull
    8Corpus critic"What source would overturn this?" + targeted gap-fill fetchfull
    9Evidence digestTop claims + verbatim quotes → evidence-digest.mdfull
    10Triple draftPer-angle source curation + 3 parallel draft sub-orchestrators (light: single draft)all
    11SynthesizePlan + outline + spawn synthesizer subagent → final_report.mdfull
    12Critics4 adversarial critics in parallel → findings JSONsfull
    13Gap-fetchTargeted fetch wave for critic-identified vault gapsfull
    14PatcherSurgical Edit hunks applied to draft (tool-locked Read+Edit)full
    14.5Cite-checkVerify citation-sentence bindings; skeptical LLM spot-check; second surgical patch passfull
    15PolishHygiene + filler pass (tool-locked Read+Edit subagent)all
    16Readability auditRecommender writes JSON suggestions; orchestrator selectively appliesall

    Tiers and gears: the two scale levers

    Tiers route per query. Step 1 auto-classifies light vs full. dissertation is opt-in only; ask for it in your prompt. It is experimental: its length, read-budget and citation targets are configured but not yet wired in (#103).

    TierWhat runsTypical time
    lightbounded factual queries, surveys, comparisons: 1 → 2 → 10 → 15 → 16~30–40 min
    full (default)deep argumentative analysis with adversarial review: all 16 steps + cite-check~1.5–2.5 h at full gear
    dissertation (experimental)chaptered mega-runs: 300–450 sources across 4–10 chapters, 25K–80K words~4–8 hours

    Gears set the scale of the standard pipeline: the source targets, depth budgets, and word targets rendered into the step skills.

    hyperresearch profile list           # all profiles + descriptions + current gear
    hyperresearch profile use premier    # 100–130 sources, doubled depth budget (~3–5 h)
    hyperresearch profile use full       # back to the 55–80-source baseline
    

    The gear persists per project and survives reinstalls. Custom gears: define [profile.<name>] in .hyperresearch/config.toml (any knob: source targets, loci caps, draft counts, word targets, per-agent models) and profile use <name>.

    Run levers: what voice the report is written in

    Tiers and gears set how much work happens. Levers set what kind of report comes out, and step 1 picks them from your prompt's verb shape. An explicit directive in your prompt always wins.

    LeverValuesWhat changes
    registerteach / survey / analyze / advocate"Teach me X" gets a pedagogical explainer; "what's the landscape" gets a map of the field with no verdict; analyze (the default) gets the evaluative argument; advocate defends one named thesis
    domain_notesfreeformSourcing strategy, evidence norms, recency window for the field in question
    inference_depthsurface / standard / deepThe rabbithole dial. Step 4 can upgrade it after seeing what the corpus actually holds

    The levers render into role-scoped shim files that spawn templates paste verbatim into subagent prompts, so the critics move with the register instead of undoing it. In survey register the dialectic critic flags unfair representation rather than missing commitment, and the polish auditor stops striking hedges. In advocate all of them tighten instead.

    The cite-checker and the ship gate receive no shim at all. Verification never softens by mode.

    hyperresearch levers set <tag> inference_depth=deep --rerender   # go deeper mid-run
    hyperresearch run status -j                                      # see what step 1 chose
    

    The two load-bearing principles

    1. Patch, never regenerate. After step 11 produces the synthesized report (or step 10 for light tier), the only modifications are surgical Edit hunks. The patcher and polish auditor are tool-locked to [Read, Edit] at the Claude Code allowlist level so they physically cannot Write a new draft (on Codex this lock is an instruction, not enforcement). Per-hunk caps make "just rewrite it" mechanically impossible. Critic findings that don't fit a small hunk escalate as structural issues.

    2. Canonical research query is gospel. The verbatim user prompt is persisted to research/runs/<vault_tag>/query.md once and re-read by every subsequent step and every spawned subagent. Wrapper requirements (save paths, citation format, terminal sections) are a separate contract.

    Subagent roster

    Models are profile config, not hardcode. The table shows the shipped defaults, and you can override any of them in .hyperresearch/config.toml: [profile.full] with models = { fetcher = "haiku" } swaps every fetcher to Haiku on the next install or profile use.

    AgentDefault modelRole
    hyperresearch-fetcherSonnetURL fetching via crawl4ai; runs 8–12 in parallel per wave
    hyperresearch-source-analystSonnetEnd-to-end digest of any single long source >5000 words
    hyperresearch-loci-analystSonnetReads the width corpus, returns 1–8 depth loci with rationale
    hyperresearch-depth-investigatorSonnetInvestigates one locus, writes one interim note with a committed position
    hyperresearch-corpus-criticSonnet"What source would overturn the current direction?" pre-draft gap analysis
    hyperresearch-draft-orchestratorOpusOne per draft angle; reads its curated source list and writes one draft
    hyperresearch-synthesizerOpusReads all 3 drafts, writes the final report (two-pass write, Read+Write locked)
    hyperresearch-dialectic-criticOpusCounter-evidence the draft missed
    hyperresearch-depth-criticOpusShallow spots interim notes could fill
    hyperresearch-width-criticOpusTopical corners the corpus supports but the draft ignores
    hyperresearch-instruction-criticOpusStructural mismatches against the prompt's atomic items
    hyperresearch-patcherOpusTool-locked [Read, Edit]. Applies critic findings as surgical Edit hunks
    hyperresearch-cite-checkerSonnetSkeptically verifies sampled citation-sentence bindings before ship
    hyperresearch-polish-auditorOpusTool-locked [Read, Edit]. Cuts filler, strips hygiene leaks
    hyperresearch-readability-recommenderOpusWrites JSON suggestions for paragraph rhythm and list/table conversion
    hyperresearch-browser-fetcherSonnetDrains the escalation queue by driving your real Chrome (Claude-in-Chrome)

    The vault: persistent, searchable, compounding

    Most deep research harnesses are one-shot: report out, everything else discarded. Hyperresearch keeps what it reads. Every fetched source lands in a SQLite-indexed vault that future sessions search before they fetch.

    hyperresearch search "ion-trap gate fidelity" -j           # Full-text search
    hyperresearch search "quantum" --include-body -j           # Full-body search
    hyperresearch note show <id1> <id2> <id3> -j               # Batch-read notes
    hyperresearch graph hubs -j                                # Most-connected notes
    hyperresearch graph backlinks <id> -j                      # Reverse links
    hyperresearch lint -j                                      # Health check (broken links, missing tags)
    

    Markdown is truth, SQLite is cache. Notes live as plain markdown with YAML frontmatter in research/notes/. The SQLite index is fully rebuildable: delete it and hyperresearch sync reconstructs it from the markdown. Open the vault in any editor, version it in git. You don't need the tool installed to read your own research.

    PDFs fetch directly. hyperresearch fetch auto-detects PDF URLs (arXiv, NBER, SSRN, direct .pdf links) and extracts full text via pymupdf. Raw PDFs land in research/raw/<note-id>.pdf and the note's raw_file: frontmatter links back.

    Provenance breadcrumbs. Every fetched source carries a --suggested-by link back to whatever surfaced it. The chain forms a rooted tree from seed fetches; the provenance lint rule catches disconnected components.

    Semantic search, if you want it. hyperresearch embed sync populates embeddings (provider-pluggable: voyage, openai, or the default none, which needs zero API keys) and search --semantic blends vector similarity with full-text ranking.

    Curation: notes have a lifecycle

    Every session ends with a curation pass, and notes move through draft → review → evergreen, or stale → deprecated → archive as material ages out. That's what keeps a vault from turning into a landfill of half-read pages.

    hyperresearch note update <id> --summary "..." --add-tag <t> -j   # promote a draft
    hyperresearch dedup -j                                            # near-duplicate pairs by content similarity
    hyperresearch topic tree -j                                       # the topic hierarchy
    hyperresearch index build -j                                      # regenerate index pages
    hyperresearch batch set-status stale --tag <t> -j                 # bulk lifecycle moves
    hyperresearch link --note <id> --dry-run -j                       # wiki-links the linker would add
    

    You are not locked in

    The vault is markdown in a directory. Everything below is a convenience on top of that, not a dependency.

    hyperresearch export json -o out.json # every note as structured JSON
    hyperresearch export vault <dir>      # a filtered subset to another directory
    hyperresearch import <dir>            # pull an existing markdown collection in
    hyperresearch git changed -j          # notes with uncommitted changes
    hyperresearch git log -j              # notes touched by recent commits
    hyperresearch watch                   # auto-sync while you edit in your own editor
    

    Use the vault outside Claude Code

    An MCP server. pip install hyperresearch[mcp], then hyperresearch mcp speaks stdio, so Claude Desktop, Cursor, or anything else that speaks MCP can work the same vault. Thirteen tools: search_notes, read_note, read_many, list_notes, get_backlinks, get_hubs, vault_status, lint_vault, check_source, list_sources, fetch_url, create_note, update_note.

    A local web UI. hyperresearch serve --open starts a stdlib HTTP server on port 8080 with note browsing, tag pages, search, and an interactive link graph. No build step and no JavaScript dependencies.


    Source ranking: quality is persistent, not vibes

    Every source accumulates a composite quality_score built from source-type tier, fetch-time utility, citation authority (from OpenAlex / Semantic Scholar, including retraction flags), and vault PageRank centrality:

    hyperresearch sources score -j             # Enrich DOI-bearing notes: citations, venue, retractions
    hyperresearch graph rank -j                # PageRank over the link + provenance graph
    hyperresearch search "q" --ranked -j       # Quality-weighted full-text search
    hyperresearch sources independence -j      # Cluster syndicated/derivative copies: 5 copies of one press release = 1 vote
    hyperresearch claims search "q" -j         # Query extracted claims across all sources
    

    Retracted sources are floored to near-zero quality, and a ship-time retraction sweep re-checks every cited DOI fresh, so a retraction published yesterday is caught today. Even on vault sources reused from old runs.


    Runs: resumable, budgeted, verified

    Every run owns an isolated workspace (research/runs/<vault_tag>/) and a manifest. Concurrent runs never collide, and a crashed run resumes exactly where it stopped:

    hyperresearch run status -j          # Step-by-step status, spend, escalation queue depth
    hyperresearch run resume -j          # Exact next step + Skill invocation to continue
    hyperresearch run report -j          # Per-step wall-time / spend / source-yield telemetry
    hyperresearch run verify <tag> -j    # Ship gate: headings, length, citation density, cite-check resolution
    

    run init --budget 50 caps estimated API-equivalent spend; crossing the cap blocks the run rather than letting it quietly balloon. And before any report ships, the verification battery runs: quote-integrity (every quoted span must exist verbatim in a vault note), retracted-citations (citing a retracted source unacknowledged blocks the ship), numeric-consistency (numbers untraceable to evidence get flagged), plus the cite-check step's per-citation binding audit.


    What's structurally enforced

    • Verbatim prompt as gospel. scaffold-prompt lint blocks if the scaffold doesn't open with the user's exact prompt
    • Locus coverage. Every step 4 locus must have a step 5 interim note; missing interims flag as errors
    • Patch-only modification. Steps 14, 15, 16 are tool-locked to [Read, Edit]. They cannot regenerate the draft
    • Critical findings never silently skip. patch-surgery lint surfaces any critical finding the patcher couldn't apply
    • Quoted text must exist. quote-integrity lint blocks any quoted span that doesn't appear verbatim in a vault note; hallucinated quotes cannot ship
    • Retractions block the ship. Citing a retracted source without acknowledging the retraction is a hard error at the final gate
    • Schema integrity. tier, content_type, and type are SQLite CHECK-constrained vocabularies; corrupted frontmatter cannot poison the index
    • Hygiene leaks caught on the way out. Scaffold sections, YAML frontmatter, and prompt echoes are stripped by step 15 before ship
    • Fetched text is data, never instructions. Web-fetched bodies are served inside an <untrusted-source> fence on both note show and search, so a page telling the agent to ignore its instructions is read as content

    The web is hostile input

    A research agent reads hundreds of pages it did not choose, and any one of them can contain text addressed to the agent rather than to you.

    Every body fetched from the web is served wrapped in <untrusted-source url="..."> delimiters with an inline treat-as-data preamble, on both paths that serve bodies (note show in single, batch, and JSON forms, and search with bodies included). Notes your own pipeline subagents wrote pass through unwrapped. Forged fence tags inside a fetched body are neutralized and left visible for forensics, the url attribute is HTML-escaped with control characters stripped, and in search the wrapping happens after token-budget truncation so the closing fence can never be severed. The fetcher, depth-investigator, draft-orchestrator, and source-analyst prompts all carry a policy block telling them not to launder a fenced page's directives into trusted output.

    Resolved URLs from third-party APIs get the same treatment. An open-access location arrives inside someone else's JSON, so it's checked for scheme, embedded credentials, and publicly-routable resolution before anything fetches it.


    Web providers

    The [web] provider setting in .hyperresearch/config.toml picks how pages are fetched and, for the providers that support it, how the web is searched. All are optional extras except the default.

    • builtin (default) — plain HTTP fetch with no search. Zero extra dependencies; the starting point everything else improves on.
    • crawl4ai — headless browser fetch with stealth, PDF extraction and the browser-escalation lane. The one the pipeline is tuned for. pip install "hyperresearch[crawl4ai]".
    • exa — neural web search and page extraction. Needs an API key. pip install "hyperresearch[exa]".
    • tavily — search and extraction built for agents. Needs an API key. pip install "hyperresearch[tavily]".
    • parallel — Parallel's Search MCP endpoint, which needs no account or key. Search only — bulk fetch waves degrade to per-URL, so it is a good search provider rather than a replacement for the crawl4ai fetch path. Every request from one process carries a random session ID that Parallel uses for correlation and rate limiting on its side. pip install "hyperresearch[parallel]".
    • serply — Serply's Google search API, with page fetch through the same key (API docs). Search results are fetched to full page text, falling back to the snippet when a page cannot be fetched. Needs an API key; no extra install.
    # .hyperresearch/config.toml
    [web]
    provider = "crawl4ai"
    

    Every fetch lane verifies TLS certificates by default: builtin, the PDF downloads, and crawl4ai's headless browser. A bad certificate fails the fetch with CertVerificationError; nothing retries it unverified. For a cert-broken site you trust, set the opt-out for the lane that refused it under [fetch]: browser_verify_tls = false for crawl4ai's headless browser, pdf_verify_tls = false for PDFs. The builtin provider has no opt-out. The visible-window browser used with a login profile (--visible, and the LinkedIn / Twitter-style domains) still accepts bad certificates, because some of the walled sites it exists for serve broken chains.


    Authenticated crawling + the browser lane

    Fetch from LinkedIn, Twitter, paywalled sites or anything you can log into:

    hyperresearch setup       # Browser opens. Log into your sites. Done.
    

    LinkedIn, Twitter, Facebook, Instagram, and TikTok automatically use a visible browser to avoid session kills.

    Blocked fetches escalate instead of dying. When headless crawling hits a login wall or bot wall mid-run, the URL queues as an escalation (hyperresearch escalation list -j). If you have the Claude-in-Chrome extension, the browser-fetcher agent drains the queue by driving your real, logged-in Chrome. Hard boundary: CAPTCHAs, 2FA, and logins are never solved automatically. They're consolidated into one message and handed to you.


    Scholarly discovery: eight sources, one query, one deduplicated list

    For any topic with a research literature, search the scholarly sources BEFORE web search. They return citation-ranked canonical works; web search returns derivative commentary. That advice used to be delivered as a list of URL templates the agent was trusted to assemble by hand — no retry, no rate limiting, no dedup, no tests. It is now a real client layer:

    hpr scholar search "Byzantine iconoclasm" -j                # every available source, merged
    hpr scholar search "GLP-1 cardiovascular outcomes" --scope papers -j
    hpr scholar search "credit default swaps" -s edgar -s fred -j
    hpr scholar sources                                          # what is wired, what each covers
    

    One call queries every configured source, merges records that are the same work (by DOI first, then by normalized title and year), and returns one list. A work found by two providers carries both in also_in, with the higher citation count and the longer abstract. Every provider shares one cache, one per-host courtesy rate limiter, and one result shape.

    The literature sources:

    • OpenAlex — ~250M works across every discipline, including books, book chapters and theses. The right default outside STEM, where the incumbent tools are weakest.
    • Crossref — the DOI registry itself. Authoritative metadata for ~160M registered works, including registrations too new for anything else to have indexed.
    • CORE — the largest open-access full-text aggregator. Hosts the text rather than linking to it, so it is also a full-text resolver (below). Needs a key: CORE_API_KEY.
    • DOAB — peer-reviewed open-access scholarly books and chapters. The only source here that finds the book rather than a review of it, which matters because in the humanities the book, not the article, is the unit of publication.
    • RePEc — listed so the gap is visible rather than silent. Their API has no search function; hpr scholar sources says so and points at OpenAlex and Crossref for the DOI-bearing series.

    The specialist sources — citable records that are not papers, tagged by work_type so the pipeline never mistakes one for literature:

    • ClinicalTrials.gov — registered studies including the ones that never produced a paper. No key.
    • SEC EDGAR — full-text search over filings. The SEC rejects any request without a contact address in the User-Agent, so set HYPERRESEARCH_CONTACT_EMAIL.
    • FRED — Federal Reserve economic series. Needs a key: FRED_API_KEY, which is never written to the cache.

    Setting HYPERRESEARCH_CONTACT_EMAIL also puts you in the OpenAlex and Crossref "polite pools", which are rate-limited far more generously than anonymous traffic. No placeholder is ever sent on your behalf.

    After the scholarly sweep, run web searches for context, news, non-academic angles, and at least one adversarial search ("criticism of X", "limitations of X").


    Open-access full text: read this before you cite

    A paywalled paper otherwise enters the vault as an abstract, and the pipeline then reasons over ~1,500 characters while citing the work as though the paper had been read. To close that, when a fetch lands a thin page carrying a DOI, hyperresearch asks Unpaywall, Europe PMC and CORE, in that order, for a legal open-access copy and stores that text in the note body instead. Unpaywall needs a contact address and Europe PMC covers biomedicine only; CORE is the broad net that catches everything else, and it hosts the text directly rather than pointing at a repository that may 403.

    The note's source: still points at the URL you asked for. The body may have come from somewhere else. That substitution is disclosed in four places, and you should know all of them:

    1. A banner at the top of the note body, naming the URL the text actually came from and which version it is.
    2. oa_url / oa_source / oa_version / oa_license / oa_recovery_kind in the note's frontmatter.
    3. An oa block in hpr note show <id> --json, carrying body_is_not_from_source: true.
    4. A line in the output of hpr fetch and hpr fetch-batch.

    Rescued notes: nothing in them came from the source

    The same lookup runs when a source can't be read at all — a 403, a login wall, a bot wall. Those are where a paywalled paper is most completely lost, and, since a DOI identifies the work rather than the host, where a legal copy is most likely to exist elsewhere.

    A note built that way is a stronger claim than a substitution, and it is marked differently: oa_recovery_kind: rescued, nothing_from_source: true in note show, and a banner that says the source URL was never read. Take it literally. The title, the authors, and every word of the body are the open-access copy's — nothing was read from the URL in source:. If you would rather have no note than a note assembled entirely from a substitute, set oa_rescue_blocked = false.

    Two limits worth knowing. Rescue needs a DOI, and a source that returned nothing offers no page to read one out of, so it only fires when the DOI is in the URL itself (a doi.org link) or in a wall page's citation_doi meta tag. A bare publisher URL with no DOI in it fails exactly as it did before. And a rescued source is not queued for the browser-escalation lane, because the paper is already in hand — if you want the publisher's own page specifically, fetch it through that lane yourself.

    Versions are not interchangeable. Unpaywall will happily hand back an accepted manuscript or a submitted preprint when no published copy is open. hyperresearch prefers the version of record and records what it got in oa_version, but if that says acceptedVersion or submittedVersion, check any direct quotation against the published paper before it reaches a report. The body banner says so too.

    Configure it under [scholar] in .hyperresearch/config.toml:

    [scholar]
    oa_recovery = true              # set false to disable entirely
    contact_email = ""              # REQUIRED by Unpaywall's terms — empty means Unpaywall is skipped
    oa_min_full_text_chars = 6000   # bodies shorter than this trigger a lookup
    oa_prefer_published = true      # version of record over preprints
    oa_max_attempts = 3             # candidate copies to try before giving up
    oa_rescue_blocked = true        # also run when the source can't be read at all
    

    Out of the box contact_email is empty, so only Europe PMC runs and recovery is limited to papers in its open-access subset. Set it to a real address to enable Unpaywall — their terms require one, and shipping a shared placeholder would get that placeholder rate-limited for every hyperresearch user at once.

    Publishers block their own open-access PDFs often enough that one attempt isn't enough, so hyperresearch walks a candidate list: every PDF Unpaywall knows about, then the landing pages, then Europe PMC's structured full text (parsed from JATS, which beats pymupdf on a two-column PDF — real section boundaries, no header bleed, no column interleaving). Europe PMC is only queried once Unpaywall's copies are exhausted.

    Recovery never fails a fetch and never lowers quality. A candidate has to clear two bars to be accepted: more text than you already had, and enough text to clear oa_min_full_text_chars. That second bar is what stops a repository record page — title, authors, a 200-word summary — from passing for full text just by being marginally longer than the publisher's abstract. If no candidate clears both, you keep the abstract and no oa block appears. Rescue only ever turns a failed fetch into a note, never the reverse: when a blocked source has no open-access copy, the command fails exactly as it always did.


    What it doesn't do

    • It doesn't replace your judgment on which sources matter. The agent picks, you steer.
    • It can't fetch what's behind a paywall you haven't logged into. Open-access recovery finds a legal free copy when one exists — even when the publisher blocks the fetch outright — but when none exists you get the abstract, or nothing, and the note says so.
    • On Claude Code it runs on Anthropic models via the subagent roster (per-agent assignments come from the profile's model map). On Codex, subagents use the session's model unless a Codex override is configured. Usage scales with tier, gear, and corpus size. The Codex port is new and has not been benchmarked yet; the Claude Code pipeline is the one that has been benchmarked.
    • The lint gate catches structural failures (missing scaffold, broken provenance, unresolved CRITICALs). It cannot guarantee factual accuracy, that's still your call.

    Requirements


    License

    MIT


    Star History