You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(frontend): redesign Tools menu and unify user preferences (#225)
Closes#224.
Reworks the Tools side menu into clear sections (SESSION / FILES / VIEW
/ SHARE / AGENTS / SETTINGS / SYSTEM), renames CommandPalette to
ToolsPanel, and adds a non-blocking SettingsPanel that keeps the
terminal and TouchBar visible so theme/font/custom-keys changes are
observable in real time.
Backs the UI with a unified `usePreferencesStore` synced through new
`GET`/`PUT /api/preferences` endpoints (file: `~/.termbeam/prefs.json`,
0o600), with a one-time migration from the old localStorage keys. Adds
TouchBar collapse, user-defined custom keys (capped at 7), optional
haptics, and a startup workspace boot that auto-launches configured
sessions on first connect.
The PR is structured as 9 reviewable commits — each compiles and tests
green on its own. Reviewing commit-by-commit is recommended.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy file name to clipboardExpand all lines: .github/copilot-instructions.md
+7-1Lines changed: 7 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -83,7 +83,13 @@ TermBeam is a Node.js CLI tool that exposes a local PTY (pseudo-terminal) over H
83
83
-`version.js` — detects version from package.json
84
84
-`update-check.js` — npm update checking
85
85
86
-
**Frontend:** React SPA in `src/frontend/` built with Vite + TypeScript. Builds to `public/` (gitignored build artifact). Uses xterm.js, Zustand for state, and Radix UI for accessible components. Components organized into: CommandPalette, FolderBrowser, LoginPage, Modals, Overlays, SearchBar, SessionsHub, SidePanel, TabBar, TerminalApp, TerminalPane, TouchBar, and common reusable components (TopBar, ThemePicker, UpdateBanner).
86
+
**Frontend:** React SPA in `src/frontend/` built with Vite + TypeScript. Builds to `public/` (gitignored build artifact). Uses xterm.js, Zustand for state, and Radix UI for accessible components. Components organized into: ToolsPanel (right slide-in, formerly CommandPalette), Settings (preferences drawer/sheet), FolderBrowser, LoginPage, Modals, Overlays, SearchBar, SessionsHub, SidePanel (left slide-in), TabBar, TerminalApp, TerminalPane, TouchBar, and common reusable components (TopBar, ThemePicker, UpdateBanner).
87
+
88
+
**UI surfaces (terminology — use these names consistently):**
89
+
90
+
-**SidePanel** (`src/frontend/src/components/SidePanel/`) — left slide-in containing the sessions picker. Triggered by the ☰ menu button.
91
+
-**ToolsPanel** (`src/frontend/src/components/ToolsPanel/`, formerly `CommandPalette`) — right slide-in titled "Tools". Triggered by the ▦ button or `Cmd/Ctrl+K`. Sections: SESSION · FILES · VIEW · SHARE · AGENTS · SETTINGS · SYSTEM. The SETTINGS section contains a single "Settings…" row that opens the SettingsPanel.
92
+
-**SettingsPanel** (`src/frontend/src/components/Settings/`) — non-blocking preferences surface. **Top sheet** on mobile (slides down from top so terminal + TouchBar stay visible below — toggles like "Start collapsed" and "Haptic feedback" can be observed live). **Right-side drawer (420 px)** on desktop with no backdrop dim. Reached from the ToolsPanel "Settings…" row or `Cmd/Ctrl+,`. Holds Appearance, Startup, TouchBar, Terminal, and Startup Workspace sections. Backed by `usePreferencesStore`, which syncs to the server via `GET`/`PUT /api/preferences`.
87
93
88
94
**WebSocket protocol:** JSON messages over `/ws`. Client sends `attach`, `input`, `resize`; server sends `output`, `attached`, `exit`, `error`. Auth is validated at WebSocket upgrade or first message.
-**Terminal search** with regex, match count, and prev/next navigation
75
-
-**Command palette** (Ctrl+K / Cmd+K) for quick access to all actions
75
+
-**Tools panel** (Ctrl+K / Cmd+K) — slide-out sheet for quick access to all actions, organized into **Session · Files · View · Share · Agents · Settings · System**. Settings (theme, font size, defaults, haptics) are inline panels reachable from the panel; on mobile the panel slides up from the bottom, on desktop it docks to the right.
76
+
-**Customizable Touch Bar** — 8-column, multi-row (up to 3) key grid with drag-to-reorder, collapsible drawer, and a dedicated key editor (label, send payload, action, modifier).
77
+
-**Workspaces** — save named bundles of sessions (each with its own name, cwd, shell, color and initial command). Mark one as `default` and the **server** auto-spawns it on startup, so connecting any client lands on a ready terminal. Preferences (theme, fonts, defaults, custom keys, workspaces) are persisted server-side in `~/.termbeam/prefs.json` and sync across devices.
76
78
-**File upload** — send files from your phone to the session's working directory
77
79
-**File browser & download** — browse files in a session's working directory from the side panel and download them to your device
78
80
-**Markdown viewer** — preview `.md` files rendered with GitHub Flavored Markdown directly in the browser
Copy file name to clipboardExpand all lines: packages/site/src/content/docs/api.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -139,7 +139,7 @@ Create a new session.
139
139
}
140
140
```
141
141
142
-
All fields are optional. If `initialCommand` is provided, it will be sent to the shell after startup. If `color` is omitted, a color is assigned automatically from a built-in palette. The optional `cols` and `rows` fields set the initial terminal size (defaults to 120×30 if omitted).
142
+
All fields are optional. If `initialCommand` is provided, it will be sent to the shell after startup (capped at 8192 characters — longer values are rejected with `400 initialCommand too long`). If `color` is omitted, a color is assigned automatically from a built-in palette. The optional `cols` and `rows` fields set the initial terminal size (defaults to 120×30 if omitted).
143
143
144
144
The `shell` field is validated against the list of detected shells (see `GET /api/shells`). The `cwd` field must be an absolute path to an existing directory.
Copy file name to clipboardExpand all lines: packages/site/src/content/docs/architecture.md
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -169,7 +169,8 @@ The terminal page includes several client-side features:
169
169
-**Command completion notifications** — uses the browser Notification API to alert when a command finishes in a background tab. Toggled via a bell icon; preference stored in `localStorage` (`termbeam-notifications`).
170
170
-**Push notifications** — native push notifications via the Web Push API, delivered even when the browser tab is closed. The service worker (`sw.ts`) handles push events and uses the Badge API to show unread counts. Push subscription lifecycle (subscribe, unsubscribe, VAPID key mismatch detection) is managed by `services/pushSubscription.ts`.
171
171
-**Git changes view** — `GitChanges/`, `DiffViewer/`, and `BlameGutter/` components in the CodeViewer directory provide a full git integration UI: staged/unstaged diffs with syntax highlighting, per-line blame annotations, and commit history browsing.
172
-
-**Command palette** — <kbd>Ctrl+K</kbd> / <kbd>Cmd+K</kbd> (or the floating ⚙️ button) opens a slide-out tool panel with categorized actions (Session, Search, View, Share, Notifications, System).
172
+
-**Tools panel** — <kbd>Ctrl+K</kbd> / <kbd>Cmd+K</kbd> (or the floating ▦ button) opens a slide-out sheet with categorized actions (Session, Files, View, Share, Agents, Settings, System). Settings, the workspace launcher and the touch-bar key editor are inline panels reachable from this entry point.
173
+
-**Workspace autoboot (server-side)** — at startup `src/server/index.js` reads `~/.termbeam/prefs.json` and, if a workspace is flagged `default: true` (or there is exactly one named workspace, or the legacy `startupWorkspace.enabled` is true), spawns each session itself. Each session's saved `shell` is validated against the host's detected shells and falls back to the runtime default if missing (covers the host-migration case where saved shells no longer exist). If every workspace session fails to spawn, the server falls back to a single default session so the user always lands on something. This replaced the previous client-side autoboot so deleting a session in the UI stays deleted until the next service restart. When no workspace is configured the server falls back to a single default session in `config.cwd`.
Copy file name to clipboardExpand all lines: packages/site/src/content/docs/configuration.md
+50-10Lines changed: 50 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -50,18 +50,57 @@ TermBeam auto-detects your current shell by inspecting the parent process tree.
50
50
The environment variables `PTY_PASSWORD` and `PTY_CWD` are also supported as fallbacks for `TERMBEAM_PASSWORD` and `TERMBEAM_CWD` respectively.
51
51
:::
52
52
53
-
## Client-Side Settings (localStorage)
53
+
## Settings (UI)
54
+
55
+
TermBeam exposes settings through the **Tools panel**, opened from the floating ▦ button or `Ctrl/Cmd+K`. From there pick **Settings…** (or use the `Cmd/Ctrl+,` shortcut). On mobile the panel slides up from the bottom; on desktop it docks to the right (~420 px wide). It is non-blocking so theme, font size, collapsed-touchbar and haptics changes can be observed live against the terminal underneath.
56
+
57
+
For the full UI walkthrough — Tools panel sections, Settings panels, Touch Bar key editor, Workspaces — see **[Customization](../customization/)**.
58
+
59
+
### Where preferences are stored
60
+
61
+
Preferences are persisted **server-side** in `~/.termbeam/prefs.json` (mode `0o600`) via the authenticated `GET /api/preferences` and `PUT /api/preferences` endpoints. The browser keeps a `localStorage` cache (`termbeam-prefs`) for instant first paint and offline UX, but the server file is the source of truth — opening TermBeam from a phone, tablet and laptop against the same instance gets the same settings.
|`termbeam-tab-order`| Saved tab order (JSON array of session IDs). |
99
+
|`termbeam-hub-filter`| Last-used filter on the SessionsHub page.|
100
+
|`termbeam-push-subscribed`| Whether the browser is subscribed to push notifications.|
101
+
|`termbeam-review-comments:*`| Per-PR review-comment state (Copilot integration).|
63
102
64
-
These settings are per-browser and persist across sessions. They can be cleared by the user via the browser's developer tools or the Refresh button in the toolbar.
103
+
These can be cleared at any time via the browser's developer tools.
-`--tunnel` — Creates a fresh tunnel each time, deleted on shutdown. Good for one-off use.
168
208
-`--persisted-tunnel` — Saves the tunnel ID to `~/.termbeam/tunnel.json` and reuses it across restarts (30-day expiry). The URL stays the same so you can bookmark it on your phone. To get a fresh URL, just switch back to `--tunnel`.
0 commit comments