No-host mode
Run duodoc entirely on your laptop. No account, no internet, no third-party processors. Storage is pglite — an embedded Postgres in WASM, file-backed in .duodoc/duodoc.pg/. Same schema and SQL as the hosted version; the only difference is where the bytes live.
When to use it
- Solo + agent loops.You're iterating on a doc with Claude Code in one terminal, reviewing in your browser in another. No one else is commenting.
- Sensitive content.Drafts you don't want sitting in a SaaS DB even momentarily.
- Offline / airgapped work. No outbound network calls except your own Anthropic key when you invoke Address with Claude / Visualize Markdown.
Quickstart (v1)
# 1. Clone the repo (v1 needs the Next.js source; standalone binary in progress) git clone https://github.com/aagarwal-gtr/duodoc.git cd duodoc && npm install # 2. Run the local-only server npm run nohost:serve # or, if you have @duodoc/cli installed globally: duodoc serve # 3. Open http://localhost:3000
On first run the server creates .duodoc/duodoc.pg/ and applies migrations. Subsequent launches reuse the existing DB and your docs persist across restarts.
What changes vs. hosted
- Magic-link emails are logged to the console, not sent. There's no Resend in local mode. The console line includes the link — paste it back into your browser to sign in.
- Visibility settings still workas a UI affordance but on a single-user laptop they're mostly ceremonial.
- BYOK Anthropic still BYOK. The local server relays the key to api.anthropic.com but never persists it, same as hosted.
- No CLI
duodoc pushfrom a separate project, unless you point its.duodoc/duodoc.jsonathttp://localhost:3000.
Roadmap
- Standalone binary. Bundle the Next.js standalone build into
@duodoc/clisoduodoc serveworks without a clone. - Optional LAN binding. Today the server only listens on localhost. A future flag will bind to 0.0.0.0 with an auth token so colleagues on the same network can comment.
- Project-bound DB. Today the DB lives at
.duodoc/duodoc.pgin the repo root. Should move to a project-bound location (XDG state dir + project hash) so multiple projects don't collide.