[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-92328":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":20,"topics":23,"createdAt":10,"pushedAt":10,"updatedAt":24,"readmeContent":25,"aiSummary":26,"trendingCount":16,"starSnapshotCount":16,"syncStatus":27,"lastSyncTime":28,"discoverSource":29},92328,"rabbithole","shlokkhemani\u002Frabbithole","shlokkhemani","An infinite canvas for learning — select text, ask, and answers branch out as documents. MCP server for Claude Code, Codex, and any agent.","https:\u002F\u002Frabbithole.ing",null,"JavaScript",222,25,66,1,0,122,54.24,"MIT License",false,"main",true,[],"2026-07-22 04:02:05","# Rabbithole\n\n**An infinite canvas for learning.** Open a document, select any text, ask a\nquestion — and the answer opens as a fully-rendered child document. Recurse as\ndeep as you like. Every hole is saved and revisitable.\n\nRabbithole has two ways in: a local MCP server for terminal agents, and a\nstatic browser app for humans who want to bring their own model key. In the MCP\npath, your agent (Claude Code, Codex, or any MCP client) does the answering and\nRabbithole gives it a canvas in your browser. Everything in that path runs\nlocally: no account, no API keys, nothing leaves your machine.\n\n🌐 **[rabbithole.ing](https:\u002F\u002Frabbithole.ing)**\n\n## Use it on the web\n\nOpen **[rabbithole.ing\u002Fapp](https:\u002F\u002Frabbithole.ing\u002Fapp)** for the browser app:\nbring your own key, choose OpenRouter (recommended), Anthropic, OpenAI, or a\nlocal OpenAI-compatible endpoint, and start from pasted markdown, PDFs, URLs,\nor `.rabbithole` files. Provider keys stay in your browser and are sent only to\nthe provider origin you configure. Holes persist in IndexedDB, so the app keeps\nworking offline-ish after it loads, and `.rabbithole` export\u002Fimport keeps your\nwork portable.\n\nSelf-hosting is static: `web\u002Fdist` can be served by any host. The optional\n`workers\u002Ffetch-proxy` Cloudflare Worker enables URL ingestion for sources that\nblock browser CORS.\n\n## Quick start\n\nRequires Node 18+ and a browser. Pick your agent:\n\n**Claude Code**\n\n```bash\nclaude mcp add rabbithole -- npx -y github:shlokkhemani\u002Frabbithole\n```\n\nClaude Code's default stdio MCP timeout is already long enough for Rabbithole's\nblocking wait. If you manage `.mcp.json` manually, this optional per-server\nfield is also fine:\n\n```json\n{\n  \"mcpServers\": {\n    \"rabbithole\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"github:shlokkhemani\u002Frabbithole\"],\n      \"timeout\": 3600000\n    }\n  }\n}\n```\n\n**Codex**\n\n```bash\ncodex mcp add rabbithole -- npx -y github:shlokkhemani\u002Frabbithole\n```\n\nThen add the timeout field in `~\u002F.codex\u002Fconfig.toml`:\n\n```toml\n[mcp_servers.rabbithole]\ncommand = \"npx\"\nargs = [\"-y\", \"github:shlokkhemani\u002Frabbithole\"]\ntool_timeout_sec = 600\n```\n\n`codex mcp add` cannot set `tool_timeout_sec`; edit the config file directly.\n\n**Any other MCP client** — add this to its MCP config:\n\n```json\n{\n  \"mcpServers\": {\n    \"rabbithole\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"github:shlokkhemani\u002Frabbithole\"]\n    }\n  }\n}\n```\n\nThen start a new agent session and say:\n\n> open this document in rabbithole\n\nA browser tab opens. Select any text on the page, ask a question (or tap a\nlens — Explain · ELI5 · Example · Go Deeper), and the answer streams in as a\nnew document. Keep going.\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Prefer running from a local clone?\u003C\u002Fstrong> (faster startup, easier hacking)\u003C\u002Fsummary>\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fshlokkhemani\u002Frabbithole.git\ncd rabbithole && npm install\nclaude mcp add rabbithole -- node \"$(pwd)\u002Fbin\u002Fmcp-server.js\"\n```\n\n\u003C\u002Fdetails>\n\n## 🤖 If you are an AI agent setting this up\n\nFollow these steps exactly:\n\n1. **Check Node**: `node --version` must be ≥ 18.\n2. **Register the server** with the one-liner above that matches the agent\n   you are running inside (`claude mcp add …` for Claude Code, `codex mcp add …`\n   for Codex, or write the JSON block into the client's MCP config file).\n   The `npx -y github:shlokkhemani\u002Frabbithole` form needs no clone and no\n   install step — npx fetches this repo and runs `bin\u002Fmcp-server.js` over stdio.\n   For Codex, also add `tool_timeout_sec = 600` under\n   `[mcp_servers.rabbithole]` in `~\u002F.codex\u002Fconfig.toml`; `codex mcp add` cannot\n   set that field.\n3. **Verify**: after the client reconnects, four tools should be available —\n   `open_rabbithole`, `answer_branch`, `ingest_pdf`, `list_rabbitholes`. (In Claude Code,\n   `claude mcp list` should show `rabbithole` as connected. The server itself\n   also responds to a standard MCP `initialize` with server name `rabbithole`.)\n4. **Tell your human what to do next**: they should start a session and say\n   *\"open &lt;some document&gt; in rabbithole\"* — you then call `open_rabbithole`\n   with `{ title, content }` (or `{ title, file_path }`; add `base_url` when\n   the markdown came from a URL or repo; add `assets` for local images referenced\n   as `asset:name.png`), which blocks until they select text and ask. Answer\n   with `answer_branch` (stream chunks with `partial: true`, finish with a\n   titled final call) and keep looping until `status='session_closed'`. If a\n   long wait returns `status='keep_listening'`, immediately call\n   `open_rabbithole` with the returned `{ hole_id }` and do not re-send content.\n\nNotes for you: the tool call blocks by design (long-poll) — that is normal, not\na hang. First `npx` run takes ~15–30s while it fetches the repo; later runs are\ncached. If the browser must not auto-open (headless), set\n`RABBITHOLE_NO_BROWSER=1` in the server's env.\n\n## Tools\n\n| Tool | What it does |\n|------|--------------|\n| `open_rabbithole` | Open a doc (`{ title, content }` \u002F `{ title, file_path }`, optional `base_url`, optional `assets`, optional `ingest_id`) or resume one (`{ hole_id }`). Opens the canvas in the browser and blocks until the human asks something. |\n| `answer_branch` | Answer a pending branch request → a child document. Stream with `partial: true` chunks, then finish with a normal call carrying the node title; use `base_url` for fetched markdown and `assets` for local images referenced as `asset:name.png`. |\n| `ingest_pdf` | Extract a local PDF into page PNGs (`page-001.png`...), opportunistic embedded rasters (`embed-p001-01.png`...), metadata, and per-page text. Author the markdown yourself, reference returned asset names with `asset:`, then pass `ingest_id` to `open_rabbithole`; or pass `hole_id` to ingest directly into an existing hole. |\n| `list_rabbitholes` | List saved holes to resume by id. |\n\nThe loop: `open_rabbithole` → `branch_request` → `answer_branch` → `branch_request` → … → `session_closed`.\nLong waits may return `keep_listening`; immediately call `open_rabbithole`\nagain with the returned `hole_id`. If the host reports a tool timeout, do the\nsame — questions are saved.\n\nFor research PDFs, use page renders as the dependable figure source and embedded\nrasters when they are cleaner. For arXiv links, prefer fetching the HTML version\nand opening that content with `base_url` instead of ingesting the PDF.\n\n## What's inside\n\n- **Reader mode (default):** fullscreen reading, branches sidebar, breadcrumbs;\n  selections become inline marks (pending → ready); hover a ready mark for a\n  peek preview; child docs carry a FROM strip that jumps back to the exact origin.\n- **Streamed answers:** words appear live with a breathing caret — in the\n  reader, the thread, and the canvas card.\n- **Rich Markdown:** answers can use math, highlighted language code fences,\n  `show` diagrams, URL-based resolution for relative links\u002Fimages, and local\n  image assets via `asset:name.png`; source stays as Markdown for copy\u002Fexport,\n  while frozen snapshots inline assets into the HTML.\n- **Lenses:** one-tap presets on the ask popup — Explain · ELI5 · Example ·\n  Go Deeper (keys 1–4).\n- **Follow-up chat:** a composer under each document asks about the doc as a\n  whole; answers render inline and are branchable like any other text.\n- **Canvas mode:** infinite pan\u002Fzoom, draggable\u002Fresizable cards, edges that\n  attach to the exact selected text in the parent, collapse, auto-layout.\n- **Navigation:** `j`\u002F`k` walk marks, `↵` opens, `⌫` jumps back up, `⌘K` searches\n  the whole hole.\n- **Share\u002Fexport:** copy any trail or document as Markdown, download a frozen\n  single-file snapshot, or ask the agent for a synthesis of the whole journey.\n- **Durable asks:** questions asked while the agent is away are saved and\n  re-queued on resume — the agent answers them first thing.\n- **Persistence:** holes auto-save as JSON under `~\u002F.rabbithole\u002F`; resuming\n  restores the doc, scroll position, mode, and canvas framing.\n\nThe MCP host stores each hole as a JSON file directly under `~\u002F.rabbithole\u002F`\n(`RABBITHOLE_DIR` overrides the base directory) and assets under the matching\nasset directory. The web `.rabbithole` file is the same persisted hole JSON\nwrapped as `{ format: \"rabbithole\", format_version: 1, hole, assets }`, with\nassets base64-encoded into the single JSON file for portability.\n\n## Configuration\n\n| Env var | Effect |\n|---------|--------|\n| `RABBITHOLE_DIR` | Override the storage directory (default `~\u002F.rabbithole\u002F`). |\n| `RABBITHOLE_NO_BROWSER=1` | Don't auto-open the browser (headless\u002Ftesting). |\n| `RABBITHOLE_MAX_BLOCK_MS` | Max time for one blocking MCP wait before returning `keep_listening` (default `240000`). |\n\n## Repo layout\n\n- `bin\u002Fmcp-server.js` — entry point (stdio MCP server)\n- `src\u002F` — server, canvas UI (self-contained HTML), storage\n- `website\u002F` — [rabbithole.ing](https:\u002F\u002Frabbithole.ing), a Next.js single-page site\n\n## Development\n\nThe browser runtime source lives in `src\u002Fui\u002F` and is bundled into committed\nartifacts under `dist\u002F`. When editing the UI, run:\n\n```bash\nnpm run build\nnpm run check:dist\n```\n\nCommit both the source changes and `dist\u002F`. There is no `prepare` build step;\nGitHub `npx` installs use the committed artifacts.\n\n## License\n\nMIT\n","Rabbithole 是一个面向深度学习与知识探索的无限画布工具，支持在任意文档中选中文本并即时提问，答案以可交互、可嵌套的子文档形式展开，形成树状知识图谱。核心特性包括本地化 MCP 服务（兼容 Claude Code、Codex 等 MCP 客户端）、浏览器端静态应用（支持 OpenRouter\u002FAnthropic\u002FOpenAI 及本地模型）、离线缓存（IndexedDB）与便携式 `.rabbithole` 文件导入导出。所有处理默认本地运行，无需账户或云端 API 密钥泄露。适用于技术文档研读、学术资料精读、代码库理解及需多层追问的知识梳理场景。",2,"2026-07-08 04:30:06","CREATED_QUERY"]