Browser terminal
vev --web-daemon
This starts a background web server on 127.0.0.1:8778 and prints a private link. Open it in a browser to get the normal vev UI: palette, tabs, and splits.
- Each browser tab is its own client. Closing the page detaches; shells keep running.
- Reloading creates a new session. Find old ones with the session picker (
SSP) and close the ones you don't need.
- Running the command again prints the same link.
Access from another machine
vev serves plain HTTP. For HTTPS, put a reverse proxy in front of it (for example Caddy, nginx, or a NetBird app).
vev --web-daemon --web-listen 127.0.0.1:8778 \
--web-origin https://terminal.example.internal
Or in ~/.config/vev/config:
web.listen = 127.0.0.1:8778
web.origin = https://terminal.example.internal
web.listen: IP and port to listen on, such as 100.64.0.10:8778 or [::1]:8778. No hostnames.
web.origin: the URL users type in the browser, without a path. Required when not listening on loopback.
- Flags override config. Restart the gateway to apply changes; shells survive.
The proxy must:
- keep the original
Host and Origin headers,
- forward WebSocket upgrades,
- serve vev at the root path (no
/vev/ prefix).
[!WARNING]
Access to this page is access to your shell. Prefer loopback or one private IP. Avoid 0.0.0.0 unless a firewall restricts access.
Controls
| Input |
Action |
| Alt+Space or Palette button |
command palette |
| Alt+h/j/k/l |
focus pane |
| Alt+1…9 |
switch tab |
| Click |
focus pane |
| Shift + wheel |
scroll 10× faster |
| Ctrl+Shift+F6 |
move focus out of the terminal to the Palette button |
- The terminal fits the window, up to 512×256 cells.
- On touch devices, Select allows native text selection and Keys opens the keyboard.
- Your browser or window manager may catch some shortcuts first. The Palette button avoids the common Alt+Space conflict.
Not supported yet: browser scrollback, touch scrolling, copy-mode clipboard export, Kitty images, OSC 52, and full emoji fidelity.
Security
- The access token is random, kept only in memory, and gone when the gateway stops.
- The link carries it once; the page then swaps it for an HttpOnly cookie.
vev --web-renew-token revokes all links and browser sessions and prints a new link. Shells keep running.
- Host and Origin checks, a strict Content Security Policy, and input limits protect the endpoint.
- Everything is embedded in the binary. No CDN or frontend framework.
Stop the gateway
The gateway is a separate process. Stopping the session daemon does not stop it. Send it SIGTERM.
Testing a build
Use an isolated profile so tests don't touch your real sessions:
go build -o .dev/vev-web .
VEV_ENV=web-visual .dev/vev-web --web-daemon
VEV_ENV=web-visual .dev/vev-web ls
Keep the printed link out of screenshots.
scripts/web-visual-smoke.cjs and scripts/web-access-smoke.cjs run Playwright checks. Set PLAYWRIGHT_MODULE, VEV_BINARY, VEV_ENV=web-visual, and optionally CHROMIUM_PATH. Run them only against an isolated profile: they create sessions and revoke access.
source
1# Browser terminal
2
3```sh
4vev --web-daemon
5```
6
7This starts a background web server on `127.0.0.1:8778` and prints a private link. Open it in a browser to get the normal vev UI: palette, tabs, and splits.
8
9- Each browser tab is its own client. Closing the page detaches; shells keep running.
10- Reloading creates a **new** session. Find old ones with the session picker (`SSP`) and close the ones you don't need.
11- Running the command again prints the same link.
12
13## Access from another machine
14
15vev serves plain HTTP. For HTTPS, put a reverse proxy in front of it (for example Caddy, nginx, or a NetBird app).
16
17```sh
18vev --web-daemon --web-listen 127.0.0.1:8778 \
19 --web-origin https://terminal.example.internal
20```
21
22Or in `~/.config/vev/config`:
23
24```ini
25web.listen = 127.0.0.1:8778
26web.origin = https://terminal.example.internal
27```
28
29- `web.listen`: IP and port to listen on, such as `100.64.0.10:8778` or `[::1]:8778`. No hostnames.
30- `web.origin`: the URL users type in the browser, without a path. Required when not listening on loopback.
31- Flags override config. Restart the gateway to apply changes; shells survive.
32
33The proxy must:
34
35- keep the original `Host` and `Origin` headers,
36- forward WebSocket upgrades,
37- serve vev at the root path (no `/vev/` prefix).
38
39> [!WARNING]
40> Access to this page is access to your shell. Prefer loopback or one private IP. Avoid `0.0.0.0` unless a firewall restricts access.
41
42## Controls
43
44| Input | Action |
45|---|---|
46| Alt+Space or **Palette** button | command palette |
47| Alt+h/j/k/l | focus pane |
48| Alt+1…9 | switch tab |
49| Click | focus pane |
50| Shift + wheel | scroll 10× faster |
51| Ctrl+Shift+F6 | move focus out of the terminal to the Palette button |
52
53- The terminal fits the window, up to 512×256 cells.
54- On touch devices, **Select** allows native text selection and **Keys** opens the keyboard.
55- Your browser or window manager may catch some shortcuts first. The Palette button avoids the common Alt+Space conflict.
56
57Not supported yet: browser scrollback, touch scrolling, copy-mode clipboard export, Kitty images, OSC 52, and full emoji fidelity.
58
59## Security
60
61- The access token is random, kept only in memory, and gone when the gateway stops.
62- The link carries it once; the page then swaps it for an HttpOnly cookie.
63- `vev --web-renew-token` revokes all links and browser sessions and prints a new link. Shells keep running.
64- Host and Origin checks, a strict Content Security Policy, and input limits protect the endpoint.
65- Everything is embedded in the binary. No CDN or frontend framework.
66
67## Stop the gateway
68
69The gateway is a separate process. Stopping the session daemon does not stop it. Send it `SIGTERM`.
70
71## Testing a build
72
73Use an isolated profile so tests don't touch your real sessions:
74
75```sh
76go build -o .dev/vev-web .
77VEV_ENV=web-visual .dev/vev-web --web-daemon
78VEV_ENV=web-visual .dev/vev-web ls
79```
80
81Keep the printed link out of screenshots.
82
83`scripts/web-visual-smoke.cjs` and `scripts/web-access-smoke.cjs` run Playwright checks. Set `PLAYWRIGHT_MODULE`, `VEV_BINARY`, `VEV_ENV=web-visual`, and optionally `CHROMIUM_PATH`. Run them only against an isolated profile: they create sessions and revoke access.