Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
b69acb7
feat(website): reposition homepage around the phone
nedtwigg Aug 18, 2026
56b8bb7
feat(website): add browser-surface section, widen section one
nedtwigg Aug 18, 2026
1bbff37
docs(vscode-ext): make the README the canonical product guide
nedtwigg Aug 18, 2026
b25489e
feat(website): render the product guide at /docs
nedtwigg Aug 18, 2026
8eb8103
feat(website): add /docs/dor and /docs/agent-skill
nedtwigg Aug 18, 2026
bdeb4d7
feat: homepage transcript, root README, and public-doc lint
nedtwigg Aug 18, 2026
39dc715
fix(docs): serve guide media from dormouse.sh, not GitHub
nedtwigg Aug 18, 2026
4626d44
refactor(docs): make the guide's Markdown the source of truth for media
nedtwigg Aug 18, 2026
9c19d37
refactor(website): simplify the docs pipeline after review
nedtwigg Aug 18, 2026
82f7eb1
fix(website): render the guide's site links relative, not absolute
nedtwigg Aug 19, 2026
bcbac66
feat(website): drop /docs, keep the two generated references
nedtwigg Aug 19, 2026
46d69a4
Merge remote-tracking branch 'origin/main' into launch-marketing
nedtwigg Sep 2, 2026
ab9b00d
fix(docs): move guide media out of the webview's output directory
nedtwigg Sep 2, 2026
d289bef
feat(website): publish the self-host runbook at /docs/self-host
nedtwigg Sep 2, 2026
b49edb6
feat(website): let the docs pages follow the reader's theme
nedtwigg Sep 2, 2026
006d97d
refactor(website): give the docs pipeline's inventories one owner each
nedtwigg Sep 2, 2026
6b0da7a
fix(website): restore h1 rendering, and stop the theme prompt mismatc…
nedtwigg Sep 2, 2026
8650d40
test(website): key the img attribute test off the allowlist itself
nedtwigg Sep 2, 2026
d075f52
refactor(website): let the docs rail own which pages are in it
nedtwigg Sep 3, 2026
2509763
feat(website): give every page in the rail a table of contents
nedtwigg Sep 3, 2026
e06d3c8
feat(website): put the docs behind one left navigation rail
nedtwigg Sep 3, 2026
f4db321
refactor(website): read the rail's page list instead of scraping it
nedtwigg Sep 3, 2026
a7453e1
fix(website): repair the outline and the rail's dead anchors
nedtwigg Sep 3, 2026
3203831
fix(website): give the filtered changelog route its own head tags
nedtwigg Sep 3, 2026
93993fd
fix(website): make the re-export rule catch its own regression
nedtwigg Sep 3, 2026
d19d243
fix(website): stop the filtered changelog claiming a second canonical
nedtwigg Sep 3, 2026
a64a828
docs(website): state the rule that makes the canonical drop safe
nedtwigg Sep 3, 2026
f1d6b19
docs(website): record the measured clearance behind the scroll offset
nedtwigg Sep 3, 2026
2f34877
docs(website): correct the clearance figure per breakpoint
nedtwigg Sep 3, 2026
2986898
fix(website): honor _redirects on the dev server
nedtwigg Sep 3, 2026
9fdb79f
feat(website): put the mobile theme picker in the docs bar
nedtwigg Sep 3, 2026
d0cd62e
fix(website): take the docs link colour from the theme, not its kind
nedtwigg Sep 3, 2026
b399a71
fix(website): wrap long paths in prose instead of widening the page
nedtwigg Sep 3, 2026
b9d4828
fix(website): stop breaking inside runs of separators
nedtwigg Sep 3, 2026
f59f6cc
Merge origin/main into launch-marketing
nedtwigg Sep 3, 2026
7bac256
fix(specs): stop backticking a path the generator creates
nedtwigg Sep 3, 2026
cc54aec
fix(website): measure the colour that is actually returned
nedtwigg Sep 3, 2026
acc05d2
docs(website): widen the rendering guarantee to prose, and pin the copy
nedtwigg Sep 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ jobs:
run: pnpm --filter dormouse build

- name: Package extension
run: pnpm --dir vscode-ext exec vsce package --no-dependencies
run: pnpm --dir vscode-ext exec vsce package --no-dependencies --baseImagesUrl https://dormouse.sh/guide

- name: Generate artifact manifest
shell: bash
Expand Down
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ lib/.vite/

# VSCode extension
vscode-ext/dist/
vscode-ext/dor-cli/
# The webview bundle's Vite output. Emptied on every build, so guide media
# lives in vscode-ext/images/ instead (docs/specs/website-docs.md).
vscode-ext/media/
vscode-ext/dor-cli/
vscode-ext/node_modules/
vscode-ext/*.vsix

Expand All @@ -40,6 +42,8 @@ standalone/node_modules/
website/dist/
website/node_modules/
website/src/data/changelog.json
website/src/data/docs.*.json
website/public/guide/

# OS
.DS_Store
Expand Down
4 changes: 3 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ One implementation map per spec: an exhaustive `Files` / `Code Map` section or s
- **`docs/specs/auto-update.md`** — Standalone auto-update: check → approved download → install-on-quit, the Baseboard notice, Windows sidecar teardown, per-platform quit behavior.
- **`docs/specs/mobile-terminal-ui.md`** — The mobile composition (`MobileTerminalUi` / `MobileWall`): stable viewport + keyboard reserve, touch modes, the radial gesture menu; shipped in the Pocket playground and the Pocket app.
- **`docs/specs/tutorial.md`** — Website playground tutorial: device-specific routes, the `tut` runner and progress state, desktop and Pocket profiles, the lib hooks for tutorial observability.
- **`docs/specs/website-docs.md`** — Public documentation on the marketing site: the generated references, the Markdown rendering contract they share, the left rail across the docs section, `vscode-ext/README.md` as the canonical guide published off-site, and the lint that pins their links.
- **`docs/specs/webgl-text.md`** — SDF text rendering for the 3D/WebXR effort: the diffplug/xterm.js fork pipeline and its version lockstep, the SDF glyph architecture, the canopy Storybook lab.
- **`docs/specs/remote-security-model.md`** — Remote-control trust model: one Noise channel per ceremony, passkeys proving presence inside it, per-Host Client statics, the Host (not the Server) authorizing the pair. Read first for anything remote.
- **`docs/specs/remote-api.md`** — What an authorized Client speaks: the shipped terminal-only **protocol-v1** and the staged remainder.
Expand Down Expand Up @@ -83,10 +84,11 @@ Specs are written ahead of the code: a new component's spec starts as a full des

`scripts/spec-lint.mjs` (`pnpm lint:specs`, the first step of the root `pnpm test`) enforces the mechanically checkable conventions above — its header comment lists the checks — and ratchets size: every spec and this file carry a word budget in `scripts/spec-word-budgets.json`, its size rounded up to the nearest 50. Rationale files carry none; evidence may grow without limit. Over budget: cut to fit, or re-baseline with `node scripts/spec-lint.mjs --ratchet <spec>` in the same PR. `SELF_HOST.md` rides the same checks. Advisory prose reviews follow `docs/prose-audit.md` (`pnpm audit:prose`).

Four sibling lints run in `pnpm test`, each enforcing one invariant a spec states in prose; each names the line it enforces and fails if that line is gone:
Five sibling lints run in `pnpm test`, each enforcing one invariant a spec states in prose; each names the line it enforces and fails if that line is gone:

| Lint | Enforces |
|---|---|
| `scripts/public-docs-lint.mjs` (`pnpm lint:public-docs`) | The public-doc contracts in `docs/specs/website-docs.md`, every inventory derived from the file that owns it. |
| `scripts/xterm-lint.mjs` (`pnpm lint:xterm`) | The `@xterm/*` version lockstep in `docs/specs/webgl-text.md`. |
| `scripts/loopback-lint.mjs` (`pnpm lint:loopback`) | `SECURITY.md` -> "Loopback Listeners": a loopback bind is not an access control — a new listener references a guard module or is allowlisted with a reason. |
| `scripts/deploy-lint.mjs` (`pnpm lint:deploy`) | `SECURITY.md` -> "Credentials at rest" and "Network posture (self-hosted)": the installer controls binding all three of `deploy/local/install-{macos,windows,linux}`. |
Expand Down
31 changes: 22 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,29 @@

[![maintained with tend](https://img.shields.io/badge/maintained_with-tend-bba580?logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwxNikgc2NhbGUoMC4wMTI1LC0wLjAxMjUpIiBmaWxsPSIjZmZmIiBzdHJva2U9Im5vbmUiPjxwYXRoIGQ9Ik02ODAgMTEyOCBjNjIgLTk2IDY5IC0xNzggMjAgLTI0MSAtMTcgLTIyIC0yMCAtNDAgLTIwIC0xMzQgbDEgLTEwOCAyMSAyOCBjMTEgMTYgMzAgNDcgNDIgNzAgMTIgMjIgMzIgNDkgNDYgNTkgMzcgMjcgMTE0IDM4IDE4NCAyNyA5MyAtMTUgOTQgLTE4IDQ0IC03OSAtNzIgLTg4IC0xMDkgLTExMyAtMTc2IC0xMTcgLTMxIC0yIC02NCAxIC03MiA2IC0yMyAxNSAyMSA1NiAxMDcgOTggNDAgMjAgNzEgMzggNjkgNDAgLTYgNyAtODggLTE3IC0xMjYgLTM3IC00OSAtMjUgLTEwMCAtNzggLTEyMSAtMTI1IC0xNSAtMzMgLTE5IC02NiAtMTkgLTE4OCAwIC0xNTcgOCAtMTk1IDUwIC0yMzIgMTcgLTE2IDM2IC0yMCA4NSAtMTkgNjIgMSA2MyAxIDczIC0zMiA5IC0zMiA5IC0zMyAtMjIgLTQwIC01MCAtMTIgLTEzMiAtNyAtMTY0IDEwIC00MCAyMSAtNzkgNjkgLTkyIDExNCAtNSAyMCAtMTAgMTAyIC0xMCAxODIgMCA4MCAtNSAxNjIgLTExIDE4NCAtMjIgNzkgLTEzNSAxNjYgLTIzNCAxODEgLTM3IDYgLTM1IDMgMzAgLTI4IDc4IC0zOSAxNDQgLTkxIDEzMiAtMTA0IC01IC00IC0zNyAtOCAtNzEgLTggLTc3IDAgLTExNyAyNCAtMTgyIDEwOSAtNTIgNjggLTUxIDcwIDQyIDg1IDcxIDExIDE0MyAwIDE4MyAtMjkgMTYgLTExIDQwIC00MyA1NCAtNzMgMTMgLTI5IDMyIC01OSA0MSAtNjYgMTQgLTEyIDE2IC03IDE2IDU4IDAgNTkgNCA3NyAyMyAxMDIgMTkgMjYgMjMgNDYgMjUgMTMwIDMgNjcgMCA5OSAtNyA5OSAtNyAwIC0xMSAtMjMgLTEyIC01NyAwIC0zMiAtNiAtNzYgLTEyIC05NyBsLTEyIC00MCAtMjcgMzIgYy0zNCA0MSAtNDMgOTYgLTI0IDE1MSAxNCA0MSA3NSAxNDEgODYgMTQxIDMgMCAyMSAtMjQgNDAgLTUyeiIvPjwvZz48L3N2Zz4K)](https://github.com/max-sixty/tend)

A multitasking terminal for VS Code and the desktop — a real tiling layout, tmux keybindings, full mouse support, browser panes your agents can drive, and alerts that tell you when something needs you.

## Try it

- **[Playground](https://dormouse.sh/playground)** - try in your browser, no install
- **[VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=diffplug.dormouse)** / **[Open VSX](https://open-vsx.org/extension/diffplug/dormouse)** - works in VS Code and its forks
- **[Standalone app](https://dormouse.sh/#download)** - Mac, Windows, Linux

## Documentation

- [CLI reference](https://dormouse.sh/docs/dor) — every `dor` command
- [Agent skill](https://dormouse.sh/docs/agent-skill) — the operating guide Dormouse bundles for coding agents
- [Self-host](https://dormouse.sh/docs/self-host) — run the coordinating server on your own tailnet

## Features

- **Automatic completion detection.** Detect when an agent needs your attention. When a pane goes quiet for two seconds, it's marked done. Works with builds, AI agents, scripts, anything.
- **Alerts when something needs you.** Terminal notification protocols (`BEL`, `OSC 9/9;4/99/777`) and unattended command exits alert with no setup; opt in per command name to also be alerted when a watched command goes quiet.
- **tmux-compatible keybindings.** Same prefix, same splits, same pane navigation. Muscle memory transfers.
- **Full mouse support.** Click to split, drag to resize, scroll to navigate. Or stay on the keyboard.
- **Copy-paste that works.** Click and drag selects text the way you'd expect, even in mouse-aware TUIs that normally swallow it as escape codes.
- **Sleep/wake panes.** Minimize a terminal to a compact status indicator. It keeps running and you can still see whether its task finished.
- **Minimize to doors.** Minimize a terminal to a compact status indicator. It keeps running and keeps reporting whether its task needs attention.
- **Browser panes.** Put a browser in the tiling layout next to the terminal serving it, drivable by you or your agents.
- **Dual distribution.** Standalone desktop app (Mac/Windows/Linux) or VS Code extension.
- **Pocket (coming soon).** Tether your sessions to your phone over WebRTC — walk away, keep working.

## Development

Expand All @@ -28,25 +36,30 @@ The terminal is currently hosted by `node-pty`, but we plan on switching to a Ru

```sh
pnpm install
pnpm dev:website # vite hotreload at http://localhost:5173/playground
pnpm dev:website # vite hotreload at http://localhost:5173
pnpm dev:standalone # tauri hotreload
pnpm dev:server # selfhost relay server for remote control

pnpm dogfood:vscode # builds the VSCode extension and installs it into your local VSCode
pnpm dogfood:standalone # installs your local build overtop of your existing system installation
pnpm dogfood:standalone --no-install # builds and runs the standalone app from the build dir, without installing

pnpm storybook # http://localhost:6006
pnpm test # runs all tests
pnpm test # runs all tests (spec lint first)
pnpm lint:specs # docs/specs conventions only
```

### Folder structure

| Path | Description |
|------|-------------|
| `lib/` | Shared terminal library |
| `website/` | dormouse.sh (including playground) |
| `standalone/` | Tauri desktop app |
| `vscode-ext/` | VSCode extension |
| `lib/` | Shared React terminal library, plus the remote/Pocket modules |
| `website/` | dormouse.sh — marketing, playground, and the generated docs pages |
| `standalone/` | Tauri desktop app and its Node PTY sidecar |
| `vscode-ext/` | VS Code extension (the README there is the canonical product guide) |
| `server/` | Selfhost coordinating server for remote control |
| `dor/` | The `dor` CLI staged onto every Dormouse terminal's `PATH` |
| `docs/specs/` | Internal specs — the reference for how everything actually behaves |

### Agent strategy

Expand Down
16 changes: 13 additions & 3 deletions docs/specs/theme.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,19 @@ playground navbar — carries none**.
init **and repeats after commit** (hydration again). Pocket passes
`restorePocketTheme` as its `restore` argument so the browser-chrome sync rides
the same lifecycle.
- The two `/playground/pocket` marketing mounts keep the free-floating `compact`
picker (rationale). **Both variants show the active theme's `ThemeSwatch`** —
beside its label on the dialog trigger, beside the word "Theme" in `compact`.
- The two `/playground/pocket` marketing mounts and the docs pages keep the
free-floating `compact` picker (rationale); the docs pages give it two
placements, floating at `lg` and inline in the mobile bar. **Both variants
show the active theme's `ThemeSwatch`** — beside its label on the dialog
trigger, beside the word "Theme" in `compact`.
- **`compact` takes its menu offset from style, never a Tailwind class**
(`menuSide`): the website renders against the lib's *prebuilt* stylesheet, so
a utility the lib never emitted is absent there and the menu drops to its
static position.
- **`onPick` reports the choice, not the change.** `restoreActiveTheme` persists
the id it resolved, so `dormouse:active-theme` exists whether or not anyone
chose, and `subscribeToActiveTheme` is silent on a re-pick. Only the picker
can answer "has this person chosen yet".
- **The host's fallback theme is module state, not a prop.**
`setDefaultThemeId()` holds it and `restoreActiveTheme()` takes no argument, so
every path re-resolving the active theme gets the same answer (rationale).
Expand Down
Loading