ascent-research
Your agent's next step up. Every session picks up where you left off. Every turn goes higher.
One-line pitch. ascent-research is an incremental research workflow CLI for AI agents: point it at a topic / source tree / Obsidian vault, and it will keep researching across sessions — fetching, citing, diagramming, and accreting a durable wiki you can come back to tomorrow and pick up exactly where you stopped.
# (next day)
&&
Bookmark-ready: every session lives as plain files under
~/.actionbook/ascent-research/<slug>/, so Obsidian, VS Code, grep
and git all work.
Author's positioning — an external handle for agent self-evolution
A Claude Code or Codex conversation ends. The agent forgets everything. Next week you ask the same question — same search, same fetches, same half-formed understanding.
I built ascent-research because I want my AI agents to get smarter
over time, not reset every session. The on-disk session (session.md,
session.jsonl, wiki/, SCHEMA.md) is the agent's external long-term
memory — survives process death, carries across tool switches, inspectable
and editable by the human. Every loop run isn't "research this topic
from scratch"; it's "continue the research we were doing, check what's
unused from last time, append to the pages you've already written."
The agent-facing surface (actions like write_wiki_page,
append_wiki_page, digest_source) exists specifically so the agent can
accrete rather than overwrite. The infra-enforced rules
(smell test, preserve_diagram_refs, figure-rich contract) exist so this
long-term memory stays clean without human QA every turn.
Whether you use it standalone or as a skill inside a coding-agent instance, the pitch is the same: stop throwing away your agent's research work at the end of every conversation. Keep it on disk. Let the next turn stand on the last one's shoulders.
Two ways to use it
ascent-research is a CLI that calls an LLM provider (Claude via
cc-sdk, Codex via codex app-server, or fake for tests). Which
process hosts the agent decides the usage shape:
Standalone — ascent-research runs its own loop
Run the CLI directly; it spawns the provider itself and drives the research loop end-to-end, no outer agent needed. Good for batch / CI / "I just want a report."
Skill — driven from a Claude Code or Codex instance
Drop the bundled skill into your Claude Code / Codex config and the outer agent invokes the CLI per-turn as a tool. Good for interactive sessions where you want to mix research with coding / writing work in the same conversation, or want the outer agent to plan the workflow (decide what to ingest, when to query, when to synthesize).
# Then in a Claude Code session: /skill:ascent-research
# Or just describe the task — "research tokio's scheduler via source" —
# the skill triggers automatically.
Both modes share the same on-disk session format, so you can start a session in standalone mode and later resume it from inside a Claude Code / Codex instance, or vice versa.
What's new in 0.4.2
- Third LLM provider: OpenCode Go ($10/mo subscription, OpenAI-
and Anthropic-compatible HTTP endpoints to DeepSeek / Kimi / GLM /
Qwen / MiniMax). Build with
--features provider-opencode-go, setOPENCODE_API_KEY+ASR_OPENCODE_MODEL, thenascent-research loop <slug> --provider opencode-go. - Useful when Claude Code Pro / ChatGPT Plus subscriptions are out of
reach (cost or payment-region constraints). All knobs are env-driven
(
ASR_OPENCODE_PROTOCOL,ASR_OPENCODE_TEMPERATURE,ASR_OPENCODE_MAX_TOKENS,ASR_OPENCODE_TIMEOUT_MS). - Also works as
ASR_BILINGUAL_PROVIDER=opencode-goforsynthesize --bilingualChinese translation. - CLI defaults unchanged —
--providerstill defaults tofake; opt in toopencode-goexplicitly. - Thanks to @Paul-Yuchao-Dong for raising the use case and contributing the initial design (PR #19).
See CHANGELOG.md for the full design rationale incl. what was
deliberately not adopted from the PR.
What's new in 0.4.1
- x.com / twitter.com tweet capture works end-to-end through the V2
browser backend. v0.4.0's generic runcode JS returned ~160 bytes of
X's left-nav chrome only; 0.4.1 adds an
XTweetruncode flavor that waits forarticle[data-testid="tweet"](notnetworkidle), scrolls with snapshot-collect across virtualized DOM so the main tweet isn't unmounted out of the result, and reads up to 25 thread articles with image / video poster URLs inlined as markdown. - 3 new tech preset rules:
x-tweet-status,x-profile,x-search-live— explicit kinds forroutedebugging. - Bugfix in
md_parser::extract_http_links: markdown image syntaxis now correctly excluded from the cited-sources scan, so embedding pictures of cited tweets no longer tripssources_hallucinated.
Live impact (same URLs, before vs after):
| URL | 0.4.0 | 0.4.1 |
|---|---|---|
x.com/<user>/status/<id> (any) |
162 B chrome | 2-3 KB main tweet + thread + media |
See CHANGELOG.md for full notes and specs/x-com-tweet-runcode-flavor.spec.md
for the design (33 BDD scenarios, lint 100%).
What's new in 0.4.0
- V2 Actionbook MCP backend is now the default for browser-rendered
fetches (Cloud Worker at
edge.actionbook.dev/mcp+ Chrome extension over WSS). SetACTIONBOOK_BACKEND=v1-clito keep the old local-CLI path — it's a permanent fallback, not slated for removal. - Catalog seed pre-fetch: every
add/batchfirst probes the V2 catalog and seeds matching actions into the session wiki, so the agent knows what's known about a site before navigating. - Composite source fetch: one rule can fan out into N parts
(e.g. postagent metadata + browser rendered) merged under
composite-v1; short-circuits on first part failure with a labelledcomposite_failed_partevent. - 3 new autoresearch actions for the loop:
actionbook_search,actionbook_manual,actionbook_run_code. - New flags on
add/batch:--frame-id,--run-code-args,--reseed,--actionbook-backend. - Default per-source timeout raised from 30 s → 90 s (V2 server's inner run-code budget is 60 s; extra 30 s covers edge overhead).
- Fixes: smell
www.↔ apex equivalence; CJK / UTF-8 docs now pass theadd-localtext detector; user--timeout > 60sis no longer silently truncated by the V2 server's hard cap.
See CHANGELOG.md for the full list and docs/rfc/v2-session-export-to-postagent.md
for the cross-tool RFC that didn't ship in this release.
Why it's different
Five properties — each validated end-to-end across four live research sessions (tokio internals, an Obsidian agent-SE series, a mixed online-plus-local AI coding agents comparison, and self-research on this repo):
0. Autoresearch lineage — 2-file resume, extended to reports
Inherits the core loop architecture from
karpathy/autoresearch
and pi-autoresearch:
a fresh agent can resume any session from two files —
session.md (human-readable living doc) + session.jsonl
(append-only event log) — even after process death, context reset,
or a week of inactivity. Where the original autoresearch optimizes a
single scalar (training loss, bundle size, test speed) via
edit → benchmark → keep-or-revert, ascent-research generalizes
the same loop grammar to research:
plan → fetch → digest → write_section / write_wiki_page / write_diagram
producing a figure-rich report plus a durable cross-session wiki
instead of a single optimized number.
1. Incremental research — sessions resume, knowledge accretes
ascent-research resume <slug> picks up exactly where a prior turn
stopped. Wiki pages accrue via append_wiki_page — new findings
grow existing entity pages instead of overwriting them. Coverage
signals (sources_unused, diagrams_referenced, wiki_pages,
wiki_total_bytes) let each loop run know what's still open from
the previous turn, so it continues rather than restarts. One-shot
DR tools can't do this — when they finish, they're done.
2. Three-way ingest, one pipeline
add (HTTP via postagent) + add-local (file trees) + browser
fallback (via actionbook browser for JS-heavy pages) all flow
through the same smell-test → event-log → wiki → report path. A
single session can cite GitHub READMEs, arXiv papers, blog posts,
and your private Obsidian notes side-by-side in one wiki page's
sources list — the renderer doesn't care about URL scheme.
3. Figure-rich by contract
Narrative-only output is considered incomplete. The loop's system
prompt carries a non-negotiable FIGURE-RICH CONTRACT: target ≥ 1
hand-drawn SVG per numbered section, bidirectional rule that every
 markdown reference must have a matching
write_diagram action and vice versa, infra-level guarantee that
section overwrites never drop figures. Every SVG is inline
(no external assets, no screenshots) and the HTML report has a
clickable wiki TOC + EN/ZH bilingual toggle.
4. Infra-enforced correctness + machine-readable errors
Agents can't "just summarize this for me." Every fetch runs through
a smell test at the CLI layer before the LLM sees it; rejections
become typed events. Overwrites preserve figures. Wiki writes are
append-safe. Coverage computes sources_hallucinated (URLs cited
but never fetched) as a report_ready blocker. Every error returns
a machine-readable code (NO_ACTIVE_SESSION, SMELL_REJECTED,
DIAGRAM_OUT_OF_BOUNDS, WIKI_EMPTY, …) so agents route recovery
deterministically without parsing prose.
Install
# Full build (loop + Claude provider) — what live sessions need
Alternative feature sets:
# Minimal — no autonomous loop, no LLM
# Loop with fake provider only (for scripted tests)
# Loop with Codex instead of Claude
Prereqs for online ingest: Rust stable (edition 2024),
postagent for HTTP API fetches,
and (for JS-heavy pages) the Actionbook Chrome extension — see below.
Neither is required if you only use add-local.
Browser ingest backends
ascent-research picks between two actionbook backends based on
ACTIONBOOK_BACKEND (default v2-mcp):
| Env value | Path | What's needed |
|---|---|---|
v2-mcp (default) |
Cloud MCP at edge.actionbook.dev/mcp + Actionbook Chrome extension over WSS |
ACTIONBOOK_API_KEY (an ak_* token), Chrome extension installed & signed in |
v1-cli |
Local actionbook CLI subprocess (offline-capable fallback, permanently supported) |
The actionbook binary on PATH, and your Chrome profile reachable by it |
V2 setup:
- Install the Actionbook Cloud (v2) Chrome extension (v0.2.0-alpha.4
or later). Unpacked-load it from
chrome://extensions→ Load unpacked. - Sign in via the extension popup.
- Get an
ak_*token from actionbook.dev/dashboard/api-keys and export it:
⚠️ Do not commit this token to git. Prefer.envrc+ direnv or a secret manager.ascent-researchnever echoes the token in error messages or logs.
Recommended: dedicated Chrome profile. V2 drives the page through
chrome.debugger, which Chromium will refuse to attach when other
extensions inject chrome-extension:// content frames into the target
page (most password managers, AI sidebars, translation extensions, and
DevTools extensions do this). Symptom: every browser fetch fails with
DEBUGGER_ATTACH_CONFLICT.
The cleanest fix is a dedicated Chrome profile that only has the Actionbook extension installed:
# macOS — launch a specific profile directly:
(Replace Profile 2 with the directory name shown at chrome://version
in your dedicated profile.)
Other V2 env vars:
| Env | Default | Purpose |
|---|---|---|
ACTIONBOOK_BACKEND |
v2-mcp |
v1-cli to revert to subprocess; unknown values are fatal |
ACTIONBOOK_MCP_ENDPOINT |
https://edge.actionbook.dev/mcp |
Point at staging or a local worker |
ACTIONBOOK_API_KEY |
— | ak_* token (required for v2-mcp) |
ACTIONBOOK_BIN |
actionbook |
V1 path only; ignored under v2-mcp |
ACTIONBOOK_BROWSER_SESSION |
— | V1: shared session name. V2: tab-handle prefix (lets multiple ascent instances share one Chrome without colliding) |
ACTIONBOOK_STDOUT_CAP |
16 MB | Cap on per-call response body (both backends) |
Three shapes of research
A. Survey a topic from public sources
PDF export is opt-in. The default backend is local and free: it uses an isolated headless Chromium when available, so the HTML stays on your machine and no paid API is required:
The local backend discovers Playwright Chromium first. If it is not installed,
run npx playwright install chromium or set ASR_PDF_CHROME_BIN to a known
safe browser binary. Desktop Google Chrome is not auto-launched by default; set
ASR_PDF_ALLOW_SYSTEM_CHROME=1 only if you explicitly want that fallback.
B. Deep-dive a library's source tree
C. Structure your Obsidian vault
D. Audit GitHub star-trust signals
github-audit creates a deterministic evidence artifact first; the LLM only
interprets that artifact and any follow-up public context. It reports a
human-facing trust score, machine-facing risk score/band, confidence, reasons,
and evidence, not a hard “fake/real” verdict.
Use audit.html when the user needs the trust decision surface directly:
trust score, risk score, confidence, metric dashboard, reasons, and evidence
gaps. Use the research session only for contextual follow-up around that
deterministic score.
Full command reference, error-code triage, loop contracts, and scenario
playbooks: see skills/ascent-research/SKILL.md.
Session layout
Each project is one directory under ~/.actionbook/ascent-research/<slug>/.
Everything is plain files — markdown, JSON lines, SVG, TOML — so your
editor / grep / git / Obsidian all work without a custom client.
| File | Purpose |
|---|---|
session.md |
Narrative — numbered sections, overview, aside. Report spine. |
session.jsonl |
Append-only event log. Sources, attempts, loop steps. Authoritative. |
SCHEMA.md |
User-editable session guidance. Loop re-reads each turn. |
wiki/*.md |
Persistent entity / concept / analysis pages with cross-links. |
diagrams/*.svg |
Hand-drawn figures inlined into the HTML report. |
raw/ |
Raw fetched content, one file per accepted source. |
report.html |
Rendered editorial output — wiki TOC, inline SVGs, optional bilingual toggle. |
report.pdf |
Optional local PDF export of report.html, created only by synthesize --pdf or --pdf-output. Defaults to isolated local Chromium. |
Override the root via ACTIONBOOK_RESEARCH_HOME=/some/path. Legacy
~/.actionbook/research/ is read as a fallback so sessions from
v0.2 keep working.
Agent integration
skills/ascent-research/SKILL.md is a bundled Claude Code / Codex skill
describing the full workflow with nine scenario playbooks, error-code
triage, and build-target matrix. Expose it on your global skill path:
Development
All integration tests use a FakeProvider replaying scripted JSON
turns, so the full suite never hits a real LLM and needs no network.
Project lineage
- Core 2-file resume loop inherited from karpathy/autoresearch
- Per-session wiki layer inspired by karpathy's LLM Wiki gist
- Widget / dashboard pattern borrowed from pi-autoresearch
- Previously named
research-rs(v0.1 / v0.2); renamed toascent-researchin v0.3 to foreground the incremental-research story
License
Apache-2.0.