Team document hub for HTML generated by AI coding agents. Drop HTML files into any repo; htmldock auto-uploads, indexes, and serves them with team-scoped auth and public share links — all on Cloudflare's edge.
Inspired by Thariq Shihipar's The Unreasonable Effectiveness of HTML — "As agents have become more powerful, markdown has become a restricting format … HTML can convey much richer information." Thariq made the case; htmldock is the team-shaped place to put the output.
Live demo · Skill for Claude Code / Codex · CLI install · Self-host
In May 2026 Thariq Shihipar published The Unreasonable Effectiveness of HTML, arguing that as AI coding agents got more capable, HTML started beating Markdown as their output format. HTML carries the information density agents need — SVG diagrams, tables, styled callouts, interactive sliders, embedded screenshots — while Markdown reduces everything to bullet lists and ASCII boxes.
Within weeks Claude Code / Cursor / Codex / OpenHands users were turning out HTML design specs, code reviews, runbooks, dashboards, and learning notes by the bucket. And then they hit the next problem: where do these files live for a team to read?
- Markdown wikis (Notion, Confluence, GitBook) re-render HTML to their own model and strip styling.
- GitHub previews of
.htmlblobs render as source, not the page. - Pastebins / Gists are personal, not team-scoped, and don't index for search.
- S3 + static hosting has no auth, no sharing, no UI.
htmldock is the missing piece downstream of Thariq's premise: a single-purpose HTML doc hub built for the AI-agent workflow. Every HTML your agent generates lands on a team-readable URL with one CLI call, indexed for full-text search, sharable with a public token when needed — and nothing else fights for screen space.
# Set up once
htmldock login # OAuth via Lark
htmldock init # writes .htmldock.toml (team, project, etc.)
# Day-to-day: agent writes HTML, htmldock auto-publishes
claude "draft a runbook for the new auth migration" → docs/auth-migration.html
# → PostToolUse hook fires → htmldock push (silent, in background)
# → https://htmldock.example.com/d/142
# Or manually, anytime
htmldock push docs/auth-migration.html
htmldock list --tree
htmldock share 142 --ttl-days 30
htmldock delete 142- Team / project routing. Documents are grouped under team slugs and project slugs (e.g.
acme-infra / billing-api / oauth-migration.html). Git remote stays as metadata; usernames never end up in URLs. - Generate-and-upload via skill. A bundled
skills.shskill installs aPostToolUsehook into any agent runner (Claude Code, Codex, …), so HTML files written by the agent are uploaded automatically. - Three visibility levels.
team(default),public-allowed(allows generating tokenized public links),private-strict(only the author can read). - Hard delete.
htmldock delete <id>andhtmldock project delete <team>/<project>remove R2 + D1 + share tokens in one shot. No recycle bin. - Full-text search. D1's FTS5 over title + body text. Tokens, HTML tags, and entities stripped on write.
- Public share tokens. 128-bit unguessable, opt-in TTL, served from a separate content origin with
Referrer-Policy: no-referrerandX-Robots-Tag: noindex. - Origin isolation. Uploaded HTML loads from a content origin without session cookies, so untrusted user CSS/JS can't pivot to the app/API.
- Tree depth cap. Display paths limited to 3 segments (including filename), enforced server-side. Keeps the index tree always one-screen-readable.
- Cloudflare-native. Workers + D1 (SQLite) + R2 (object storage) + Pages. Free tier covers most teams; usage-based after that.
┌──────────────────┐ ┌──────────────────────┐
│ Claude Code │ PostToolUse hook │ Team member browser │
│ Cursor / Codex │ ──┐ detects *.html │ / external viewer │
└──────────────────┘ │ └────────┬─────────────┘
▼ │
┌─────────────────┐ │
│ htmldock CLI │ │
│ (Bun, single │ ─── PAT auth ──┐ │ Lark session cookie
│ binary) │ │ │ or /p/<token>
└─────────────────┘ ▼ ▼
┌───────────────────────────┐
│ Cloudflare Workers (Hono) │
│ • /api/docs, /api/teams │
│ • /api/search, /api/share │
│ • /d/<id>, /p/<token> │
└────────┬──────────┬───────┘
▼ ▼
┌──────┐ ┌─────────────┐
│ R2 │ │ D1 (SQLite)│
│ HTML │ │ + FTS5 │
└──────┘ └─────────────┘
See design.html for the full design spec (rendered in any browser).
curl -fsSL https://raw.githubusercontent.com/leeguooooo/htmldock/main/scripts/install.sh | bashInstalls the latest binary into ~/.local/bin/htmldock. Override with HTMLDOCK_REPO=<owner>/htmldock for self-hosted forks, or HTMLDOCK_VERSION=v0.5.0 to pin.
htmldock login # browser OAuth flow → PAT in ~/.config/htmldock/config.toml
htmldock team list # see teams you belong to
htmldock team create acme-infra "Acme Infra"
htmldock init # interactive: pick team, write .htmldock.toml
htmldock push docs/spec.html # uploads, prints clickable URL
htmldock push docs/spec.html --public # also generates a 30-day share link
htmldock list --tree # see the module tree for the current project
htmldock share 142 --ttl-days 7
htmldock delete 142 --yes
htmldock project delete acme-infra/old-thing --yes.htmldock.toml lives at the repo root and is the source of truth for that repo's sync behavior:
team = "acme-infra" # required
project_slug = "billing-api" # optional; defaults to repo basename
sync = true # whether the hook auto-uploads
visibility = "team" # team | public-allowed | private-strict
module_root = "docs" # only HTML under this prefix is uploaded
ignore = ["draft/**", "scratch/*.html"]
auto_module = true # let the agent choose a module prefixPlatform-agnostic. Works with Codex, Claude Code, and anything else skills.sh supports.
npx skills add leeguooooo/htmldock --skill htmldock -gWhat the skill does:
- Installs the htmldock CLI binary automatically if missing.
- Tells the agent to reuse existing module path prefixes before inventing new ones (so docs cluster by topic, not date).
- Caps tree depth at 3 (server enforces too).
- Wires a
PostToolUsehook soWrite *.htmlin any opted-in repo (sync = truein.htmldock.toml) is uploaded automatically.
Scope to one agent with -a codex or -a claude. Omit -a to register for every detected runner.
You can run htmldock on your own Cloudflare account in under 10 minutes.
git clone https://github.com/leeguooooo/htmldock
cd htmldock
bun install # only needed for type-checking + tests
bunx wrangler login
# Create resources (one-time)
bunx wrangler d1 create htmldock # paste id into wrangler.toml
bunx wrangler r2 bucket create htmldock-docs
# Apply schema
bunx wrangler d1 migrations apply htmldock --remote
# Secrets
bunx wrangler secret put HMAC_SECRET # any 32+ random bytes
bunx wrangler secret put LARK_CLIENT_ID # for OAuth login
bunx wrangler secret put LARK_CLIENT_SECRET
bunx wrangler deployAfter deploying, allowlist https://<your-host>/api/auth/lark/callback inside your Lark app. Sign in once with /api/auth/lark, then htmldock config set-token <pat> --server https://<your-host> from the CLI.
| Area | State |
|---|---|
| Backend (Workers + D1 + R2) | shipping |
| CLI (Bun single-binary) | v0.5.0 — team / delete / project delete |
| Dashboard | minimal warm-paper SSR; redesign in progress |
| Lark OAuth | working |
| Cloudflare Access SSO | deferred (team membership is enough for MVP) |
| Doc versioning / rollback | not in v1 — R2 keys overwrite |
| Comments / @ mentions | not in v1 |
Roadmap: see open issues; design rationale lives in design.html.
Bug reports, PRs, and design feedback welcome — open an issue or DM @leeguooooo. Local checks before pushing:
bun test
bunx tsc --noEmitMIT. See LICENSE.
- Thariq Shihipar, Using Claude Code: The Unreasonable Effectiveness of HTML — the design philosophy that motivated htmldock.
- Anthropic, Claude Code skills — how the bundled skill plugs in.
Built for teams that ship documentation as fast as their agents can write it.