collin/browser-terminal-extension
70c842632d07d4d70bab99227471661396da8d00 / CLAUDE.md
RenderedSource
| 1 | # CLAUDE.md |
| 2 | |
| 3 | A 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 | |
| 11 | See `README.md` for protocol, pairing, TLS, and the systemd socket activation |
| 12 | story. 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 |
| 23 | until `./build.sh` runs and the sidebar (or the extension) is reloaded. This is |
| 24 | the 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 |
| 29 | a plain tab for layout work, outside the extension. |
| 30 | |
| 31 | `.githooks/post-commit` runs `build.sh` after any commit that touched |
| 32 | `extension/`, so a committed change is at least *in* `dist/`. Enable it once per |
| 33 | clone (hooks live outside the repo, so this is what points git at the tracked |
| 34 | copy): |
| 35 | |
| 36 | ```sh |
| 37 | git config core.hooksPath .githooks |
| 38 | ``` |
| 39 | |
| 40 | It does not reload the sidebar, and it does nothing for an uncommitted edit — |
| 41 | `./build.sh` by hand is still the loop while you are working. |
| 42 | |
| 43 | ## Checks |
| 44 | |
| 45 | ```sh |
| 46 | npm test # node --test over extension/lib/*.test.js |
| 47 | npm run check # tsc over both jsconfig projects, noEmit |
| 48 | cd daemon && cargo test |
| 49 | ``` |
| 50 | |
| 51 | `npm run check` is type checking only, never a build step. The extension files |
| 52 | are classic scripts sharing one global scope (`sidebar.js` reaches `Themes`, |
| 53 | `Sanitize`, `tbPickElement` with no imports), so nothing under `extension/` may |
| 54 | introduce `import`/`export` syntax. There are two tsconfig projects because |
| 55 | there are two global scopes: `jsconfig.json` (sidebar document) and |
| 56 | `jsconfig.sw.json` (service worker), both extending `jsconfig.base.json`. |
| 57 | |
| 58 | Daemon tests use `/bin/sh` rather than tmux where they can, and skip themselves |
| 59 | when tmux is missing; the tmux ones use a private socket so they never touch |
| 60 | your real sessions. |
| 61 | |
| 62 | ## Daemon edit loop |
| 63 | |
| 64 | If the daemon is installed as a user service (`termbridge install`), a rebuilt |
| 65 | binary is picked up on the next activation, but only once the running one exits: |
| 66 | |
| 67 | ```sh |
| 68 | cd daemon && cargo build --release |
| 69 | termbridge reload |
| 70 | ``` |
| 71 | |
| 72 | Re-run `termbridge install` instead when the change affects what the unit |
| 73 | encodes (port, idle timeout, pinned session, binary path). |
| 74 | |
| 75 | ## Conventions |
| 76 | |
| 77 | - Both manifests (`manifest.chrome.json`, `manifest.firefox.json`) are hand |
| 78 | maintained. A permission or file change usually has to land in both. |
| 79 | - `extension/lib/theme.js` is the single source of truth for both palettes: the |
| 80 | `ui` block becomes CSS custom properties, the `xterm` block goes to |
| 81 | `term.options.theme`. Do not hardcode colors in `sidebar.css`; use the |
| 82 | variables. |
| 83 | - `sidebar.css` carries long comments explaining *why* a rule exists (the tab |
| 84 | silhouette, the separators, the seam the active tab covers). Keep that style |
| 85 | when editing it, and read the surrounding comment before changing a value. |
| 86 | - `extension/vendor/` is vendored xterm.js. Do not edit it. |