anvilsign in

collin/browser-terminal-extension

RenderedSource

1# CLAUDE.md
2
3A tmux sidebar for Chrome and Firefox. Two halves that ship separately:
4
5- `extension/` is the browser extension (named **terminal**). Plain files, no
6 bundler: the browser loads the `.js`/`.css`/`.html` on disk as they are.
7- `daemon/` is `termbridge`, a Rust CLI that serves a WebSocket on
8 `127.0.0.1:7681`, spawns a pty, and runs tmux inside it. tmux, not the daemon,
9 is the persistence layer.
10
11See `README.md` for protocol, pairing, TLS, and the systemd socket activation
12story. This file is the build and edit loop.
13
14## Build
15
16```sh
17./build.sh # extension -> dist/chrome and dist/firefox
18./run.sh # daemon: cargo build --release, then `termbridge serve`
19```
20
21**`build.sh` copies files into `dist/`.** The browser loads `dist/chrome` (or
22`dist/firefox`), never `extension/`. So an edit under `extension/` has no effect
23until `./build.sh` runs and the sidebar (or the extension) is reloaded. This is
24the most common reason a change "didn't work".
25
26`build.sh` copies an explicit list of files. A new file under `extension/` or
27`extension/lib/` will not reach `dist/` until it is added to that list.
28`extension/mock.html` is deliberately excluded: it renders the sidebar header in
29a plain tab for layout work, outside the extension.
30
31## Checks
32
33```sh
34npm test # node --test over extension/lib/*.test.js
35npm run check # tsc over both jsconfig projects, noEmit
36cd daemon && cargo test
37```
38
39`npm run check` is type checking only, never a build step. The extension files
40are classic scripts sharing one global scope (`sidebar.js` reaches `Themes`,
41`Sanitize`, `tbPickElement` with no imports), so nothing under `extension/` may
42introduce `import`/`export` syntax. There are two tsconfig projects because
43there are two global scopes: `jsconfig.json` (sidebar document) and
44`jsconfig.sw.json` (service worker), both extending `jsconfig.base.json`.
45
46Daemon tests use `/bin/sh` rather than tmux where they can, and skip themselves
47when tmux is missing; the tmux ones use a private socket so they never touch
48your real sessions.
49
50## Daemon edit loop
51
52If the daemon is installed as a user service (`termbridge install`), a rebuilt
53binary is picked up on the next activation, but only once the running one exits:
54
55```sh
56cd daemon && cargo build --release
57termbridge reload
58```
59
60Re-run `termbridge install` instead when the change affects what the unit
61encodes (port, idle timeout, pinned session, binary path).
62
63## Conventions
64
65- Both manifests (`manifest.chrome.json`, `manifest.firefox.json`) are hand
66 maintained. A permission or file change usually has to land in both.
67- `extension/lib/theme.js` is the single source of truth for both palettes: the
68 `ui` block becomes CSS custom properties, the `xterm` block goes to
69 `term.options.theme`. Do not hardcode colors in `sidebar.css`; use the
70 variables.
71- `sidebar.css` carries long comments explaining *why* a rule exists (the tab
72 silhouette, the separators, the seam the active tab covers). Keep that style
73 when editing it, and read the surrounding comment before changing a value.
74- `extension/vendor/` is vendored xterm.js. Do not edit it.