hop2 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README-MCP.md +70 -36
- package/README.md +23 -8
- package/hay/CHANGELOG.md +31 -1
- package/hay/README.md +53 -8
- package/hay/apps/cli/package.json +1 -1
- package/hay/apps/cli/src/index.ts +1097 -135
- package/hay/apps/server/package.json +1 -1
- package/hay/apps/server/src/rooms.ts +68 -14
- package/hay/apps/server/test/rooms.test.ts +75 -0
- package/hay/apps/web/package.json +1 -1
- package/hay/apps/web/src/App.tsx +512 -111
- package/hay/apps/web/src/components/MobileKeyboard.tsx +32 -11
- package/hay/apps/web/src/styles.css +254 -68
- package/hay/package-lock.json +0 -1
- package/hay/packages/shared/package.json +1 -1
- package/hay/packages/shared/src/protocol.ts +8 -2
- package/hay/packages/shared/test/protocol.test.ts +32 -0
- package/hay-web/assets/index-BzJB9r_I.js +64 -0
- package/hay-web/assets/{index-D9aOC5Zt.js.map → index-BzJB9r_I.js.map} +1 -1
- package/hay-web/assets/index-DG8Ntznc.css +32 -0
- package/hay-web/index.html +2 -2
- package/hop +977 -140
- package/lib/naming-themes.js +28 -14
- package/mcp/hop-mcp.js +380 -90
- package/package.json +1 -1
- package/scripts/hay-host.js +8 -1
- package/sessions.html +152 -21
- package/setup-mcp.js +37 -19
- package/hay-web/assets/index-BmWjq_Nh.css +0 -32
- package/hay-web/assets/index-D9aOC5Zt.js +0 -63
package/README-MCP.md
CHANGED
|
@@ -6,7 +6,7 @@ restarts.
|
|
|
6
6
|
|
|
7
7
|
## Quick Start
|
|
8
8
|
|
|
9
|
-
1. Ensure the Hop daemon is running locally.
|
|
9
|
+
1. Ensure the Hop daemon is running locally by running `hop` (interactive) or `hop start` (daemon only).
|
|
10
10
|
|
|
11
11
|
2. Auto-configure supported MCP clients:
|
|
12
12
|
|
|
@@ -49,7 +49,7 @@ The server auto-connects to the local Hop daemon via `~/.hop2/.tunnel-state`.
|
|
|
49
49
|
|
|
50
50
|
Recommended flow for driving one Claude/Codex/Gemini terminal safely:
|
|
51
51
|
|
|
52
|
-
1. Launch a dedicated terminal:
|
|
52
|
+
1. Launch a dedicated terminal (the returned `id` is the `terminal_id` used by every other tool):
|
|
53
53
|
|
|
54
54
|
```
|
|
55
55
|
hop_create_terminal(name="subagent", cwd="/path/to/repo")
|
|
@@ -58,33 +58,56 @@ hop_create_terminal(name="subagent", cwd="/path/to/repo")
|
|
|
58
58
|
2. Start the agent CLI:
|
|
59
59
|
|
|
60
60
|
```
|
|
61
|
-
hop_write_terminal(data="claude\n")
|
|
61
|
+
hop_write_terminal(terminal_id=<id>, data="claude\n")
|
|
62
62
|
# or
|
|
63
|
-
hop_write_terminal(data="codex\n")
|
|
63
|
+
hop_write_terminal(terminal_id=<id>, data="codex\n")
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
3. Wait for a prompt before sending work:
|
|
67
67
|
|
|
68
68
|
```
|
|
69
|
-
hop_wait_terminal(until_prompt=true, start_from="latest")
|
|
69
|
+
hop_wait_terminal(terminal_id=<id>, until_prompt=true, start_from="latest")
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
4. Run a multi-turn loop:
|
|
73
|
-
- Preferred: `hopx_agent_turn(data="<task>", mode="auto")`
|
|
74
|
-
- Good lower-level helper: `hopx_send_and_wait(data="<task>", press_enter=true, capture="readable_raw")`
|
|
73
|
+
- Preferred: `hopx_agent_turn(terminal_id=<id>, data="<task>", mode="auto")`
|
|
74
|
+
- Good lower-level helper: `hopx_send_and_wait(terminal_id=<id>, data="<task>", press_enter=true, capture="readable_raw")`
|
|
75
75
|
- Manual split only when needed:
|
|
76
|
-
- send with `hop_write_terminal(data="<task>\n")`
|
|
77
|
-
- wait with `hop_wait_terminal(capture="readable_raw")`
|
|
78
|
-
- continue via cursor deltas from `hop_read_terminal(start_from="cursor", cursor=...)`
|
|
76
|
+
- send with `hop_write_terminal(terminal_id=<id>, data="<task>\n")`
|
|
77
|
+
- wait with `hop_wait_terminal(terminal_id=<id>, capture="readable_raw")`
|
|
78
|
+
- continue via cursor deltas from `hop_read_terminal(terminal_id=<id>, start_from="cursor", cursor=...)`
|
|
79
79
|
|
|
80
80
|
5. Stop or clean up:
|
|
81
|
-
- interrupt with `hop_send_key(key="ctrl_c")`
|
|
82
|
-
- close with `hop_close_terminal(killSession=false)`
|
|
81
|
+
- interrupt with `hop_send_key(terminal_id=<id>, key="ctrl_c")`
|
|
82
|
+
- close with `hop_close_terminal(terminal_id=<id>, killSession=false)`
|
|
83
83
|
|
|
84
84
|
Safety notes:
|
|
85
85
|
- Keep one subagent per terminal (no multiplexing multiple agent CLIs in one PTY).
|
|
86
86
|
- For existing user sessions, verify `agentPermitted` (or set with `hop_set_agent_permission`) before writing input.
|
|
87
87
|
|
|
88
|
+
## Shell Commands: `hopx_exec`
|
|
89
|
+
|
|
90
|
+
For plain shell work (not interactive TUIs), `hopx_exec` behaves like a Bash
|
|
91
|
+
tool on a persistent terminal: it sends the command, waits for the next shell
|
|
92
|
+
prompt, and returns clean plain-text output.
|
|
93
|
+
|
|
94
|
+
Worked example:
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
hop_create_terminal(name="builder", cwd="/path/to/repo") # returns id
|
|
98
|
+
hopx_exec(terminal_id=<id>, command="npm test")
|
|
99
|
+
# -> { "ok": true, "exit_code": 0, "stdout": "...", "next_cursor": ... }
|
|
100
|
+
hopx_exec(terminal_id=<id>, command="ls /nope")
|
|
101
|
+
# -> { "ok": true, "exit_code": 1, "stdout": "ls: /nope: No such file or directory", ... }
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Semantics:
|
|
105
|
+
- `ok` means the shell prompt returned within `timeout_ms` — NOT that the command succeeded.
|
|
106
|
+
- `exit_code` is the command's real exit status, captured by appending a POSIX sentinel (`<cmd>; printf '\n__HOPX_RC_<nonce>=%d\n' "$?"`). It is `null` when the sentinel was never observed (timeout, or a shell without POSIX `$?` semantics) — in that case behavior degrades gracefully to prompt-based capture.
|
|
107
|
+
- The sentinel line, the echoed command, the trailing prompt, and ANSI codes are stripped from `stdout`.
|
|
108
|
+
- On timeout, `timed_out: true` is set and `ok` is `false`.
|
|
109
|
+
- For SSH sessions or unusual prompts, pass `prompt_regex`; for commands with non-standard output endings, pass `idle_ms` as a fallback condition.
|
|
110
|
+
|
|
88
111
|
## Remote Hop
|
|
89
112
|
|
|
90
113
|
To connect to a remote hop instance, set env vars or use `connect_server`:
|
|
@@ -108,29 +131,32 @@ connect_server(base_url="https://hop2.example.com", token="<token>", verify=true
|
|
|
108
131
|
## Tools
|
|
109
132
|
|
|
110
133
|
Core tools (`hop_`): stable atomic operations.
|
|
111
|
-
- `connect_server`
|
|
112
|
-
- `hop_server_info`
|
|
113
|
-
- `hop_list_sessions`
|
|
114
|
-
- `hop_list_terminals`
|
|
115
|
-
- `hop_create_terminal`
|
|
116
|
-
- `hop_attach_terminal`
|
|
117
|
-
- `hop_write_terminal`
|
|
118
|
-
- `hop_send_key`
|
|
119
|
-
- `hop_wait_terminal`
|
|
120
|
-
- `hop_wait_start`
|
|
121
|
-
- `hop_wait_poll`
|
|
122
|
-
- `hop_resize_terminal`
|
|
123
|
-
- `hop_read_terminal`
|
|
124
|
-
- `hop_close_terminal`
|
|
125
|
-
- `hop_set_agent_permission`
|
|
126
|
-
- `hop_list_workspaces`
|
|
127
|
-
- `
|
|
128
|
-
- `
|
|
129
|
-
- `
|
|
134
|
+
- `connect_server` — connect to a Hop API base_url (optional token); use for remote hop instances
|
|
135
|
+
- `hop_server_info` — hop-mcp runtime diagnostics (version, script path, read-mode capabilities)
|
|
136
|
+
- `hop_list_sessions` — list Hop sessions and metadata
|
|
137
|
+
- `hop_list_terminals` — list terminal API sessions (created via `hop_create_terminal` / `hop_attach_terminal`)
|
|
138
|
+
- `hop_create_terminal` — create a terminal session and optionally run a startup command; returns the `id` used as `terminal_id` everywhere else
|
|
139
|
+
- `hop_attach_terminal` — attach to an existing terminal session by name or internalName
|
|
140
|
+
- `hop_write_terminal` — write raw input to a terminal session
|
|
141
|
+
- `hop_send_key` — send a named keypress (enter, esc, tab, shift_tab, arrows, f1-f12, ctrl+[a-z], ...)
|
|
142
|
+
- `hop_wait_terminal` — wait for output conditions (regex, prompt, idle, agent_done); `async=true` returns a `wait_id`
|
|
143
|
+
- `hop_wait_start` — deprecated legacy alias for `hop_wait_terminal(async=true)`
|
|
144
|
+
- `hop_wait_poll` — poll or await completion of a background wait job
|
|
145
|
+
- `hop_resize_terminal` — resize the terminal PTY
|
|
146
|
+
- `hop_read_terminal` — read terminal output events (default `mode="readable_raw"`); returns a cursor for incremental reads
|
|
147
|
+
- `hop_close_terminal` — detach the terminal API session; optionally kill the underlying hop session
|
|
148
|
+
- `hop_set_agent_permission` — allow or block agent access for a session
|
|
149
|
+
- `hop_list_workspaces` — list available workspaces
|
|
150
|
+
- `hop_create_workspace` — create an empty workspace by name
|
|
151
|
+
- `hop_show_workspace` — show saved definitions in a workspace
|
|
152
|
+
- `hop_save_workspace` — save a workspace snapshot from live sessions
|
|
153
|
+
- `hop_delete_workspace` — delete a workspace by name
|
|
154
|
+
- `hop_load_workspace` — load a workspace and optionally start sessions
|
|
130
155
|
|
|
131
156
|
Helper tools (`hopx_`): convenience wrappers built on top of core tools.
|
|
132
|
-
- `hopx_send_and_wait`
|
|
133
|
-
- `
|
|
157
|
+
- `hopx_send_and_wait` — single-call send + wait wrapper
|
|
158
|
+
- `hopx_exec` — Bash-tool-style shell execution: command in, clean stdout + `exit_code` out (see section above)
|
|
159
|
+
- `hopx_agent_turn` — single-turn send + wait + mode-aware output, default `mode="auto"`
|
|
134
160
|
|
|
135
161
|
## Resources
|
|
136
162
|
|
|
@@ -151,6 +177,11 @@ Helper tools (`hopx_`): convenience wrappers built on top of core tools.
|
|
|
151
177
|
|
|
152
178
|
### `hop_read_terminal`
|
|
153
179
|
|
|
180
|
+
- Defaults are token-thrifty:
|
|
181
|
+
- `mode` defaults to `"readable_raw"` (pass `"raw"` or `"ui"` explicitly when needed)
|
|
182
|
+
- `maxEvents` defaults to `200` and `maxBytes` to `65536`; pass `0` explicitly for unlimited (the buffer keeps the last 2000 events)
|
|
183
|
+
- when these caps truncate a read, the payload includes `truncated: true` plus a `hint`; continue with `start_from="cursor"`, `cursor=<next_cursor>`
|
|
184
|
+
- `start_from` defaults to `cursor` when `cursor` is provided, otherwise `beginning`
|
|
154
185
|
- `hop_read_terminal` supports `mode: "ui"` for structured terminal snapshots:
|
|
155
186
|
- `ui.lines`: visible screen lines
|
|
156
187
|
- `ui.cursor`: cursor position
|
|
@@ -194,9 +225,9 @@ Helper tools (`hopx_`): convenience wrappers built on top of core tools.
|
|
|
194
225
|
|
|
195
226
|
### Async wait helpers
|
|
196
227
|
|
|
197
|
-
- `
|
|
198
|
-
- start with `hop_wait_start(...)` and poll with `hop_wait_poll(wait_id=..., wait=true)`
|
|
228
|
+
- For long-running conditions, start a background wait with `hop_wait_terminal(terminal_id=<id>, async=true, ...)` (returns `wait_id` immediately) and poll with `hop_wait_poll(wait_id=..., wait=true)`
|
|
199
229
|
- use `consume=true` on poll to remove completed jobs
|
|
230
|
+
- `hop_wait_start` is a deprecated legacy alias for `hop_wait_terminal(async=true)`; prefer the latter
|
|
200
231
|
|
|
201
232
|
### `hopx_send_and_wait`
|
|
202
233
|
|
|
@@ -225,8 +256,11 @@ Helper tools (`hopx_`): convenience wrappers built on top of core tools.
|
|
|
225
256
|
|
|
226
257
|
### Error model
|
|
227
258
|
|
|
228
|
-
- Tool calls that fail at the Hop API layer
|
|
259
|
+
- Tool calls that fail at the Hop API layer return MCP tool errors (`isError: true`) with normalized fields:
|
|
229
260
|
- `ok`
|
|
230
261
|
- `status`
|
|
231
262
|
- `endpoint`
|
|
232
263
|
- `error`
|
|
264
|
+
- `hint` (when a remedy is known)
|
|
265
|
+
- Connection-level failures (daemon not running, unreachable host, timeouts) also come back as normalized tool errors with `status: null` and a `hint` explaining how to start the daemon (`hop` or `hop start`) or reconnect via `connect_server(base_url=...)` — not as raw JSON-RPC protocol errors.
|
|
266
|
+
- A `403` "Agent access not permitted" error includes a hint to enable access with `hop_set_agent_permission(name=..., allowed=true)` or `hop session permit <name>`.
|
package/README.md
CHANGED
|
@@ -140,21 +140,21 @@ Use one dedicated terminal per subagent.
|
|
|
140
140
|
2. Start the agent CLI with `hop_write_terminal`.
|
|
141
141
|
3. Wait for readiness with `hop_wait_terminal(until_prompt=true)`.
|
|
142
142
|
4. Prefer `hopx_agent_turn(mode="auto")` or `hopx_send_and_wait(...)` for one turn at a time.
|
|
143
|
-
5. For long waits, use `hopx_agent_turn(async=true, ...)` or the lower-level `
|
|
143
|
+
5. For long waits, use `hopx_agent_turn(async=true, ...)` or the lower-level `hop_wait_terminal(async=true, ...)` + `hop_wait_poll(...)` (`hop_wait_start` remains only as a legacy alias).
|
|
144
144
|
6. Interrupt with `hop_send_key(key="ctrl_c")` and close with `hop_close_terminal`.
|
|
145
145
|
|
|
146
146
|
Safety tips:
|
|
147
147
|
|
|
148
148
|
- Keep one subagent per terminal.
|
|
149
149
|
- Do not queue a second instruction before reading the first response.
|
|
150
|
-
- For attached user sessions, confirm `agentPermitted` before sending input.
|
|
150
|
+
- For attached user sessions, confirm `agentPermitted` before sending input (grant it with `hop session permit <name>`).
|
|
151
151
|
|
|
152
152
|
### Share a Local Web App
|
|
153
153
|
|
|
154
154
|
Expose a local HTTP or WebSocket service through your Hop tunnel:
|
|
155
155
|
|
|
156
156
|
```bash
|
|
157
|
-
hop session add myapp --port 3000
|
|
157
|
+
hop session add myapp --port 3000 --workspace dev
|
|
158
158
|
```
|
|
159
159
|
|
|
160
160
|
Result:
|
|
@@ -172,6 +172,7 @@ hop attach <session>
|
|
|
172
172
|
```
|
|
173
173
|
|
|
174
174
|
This is useful when you want a browser, an MCP client, and a local shell to converge on the same named session.
|
|
175
|
+
Local terminal sessions are persistent by default: they keep running in the Hay host if the local CLI detaches or the Hop daemon restarts. The local CLI status line shows `persists`; use `Ctrl+Q` inside the local Hop view to kill the session.
|
|
175
176
|
|
|
176
177
|
### Use Hop on Mobile
|
|
177
178
|
|
|
@@ -263,12 +264,21 @@ Hop uses the external Hay host runtime for PTY hosting and session recovery.
|
|
|
263
264
|
|
|
264
265
|
| Command | Description |
|
|
265
266
|
|---------|-------------|
|
|
266
|
-
| `hop` | Start hop daemon/tunnel if needed, then launch a local terminal |
|
|
267
|
+
| `hop` | Start hop daemon/tunnel if needed, then launch a local terminal. Unnamed launches do not reuse a session that already has a local CLI attached. |
|
|
268
|
+
| `hop start` | Start the hop daemon and print QR codes |
|
|
269
|
+
| `hop attach [session]` | Attach to an existing terminal session |
|
|
267
270
|
| `hop attach all` | Attach sequentially to all terminal sessions |
|
|
268
271
|
| `hop local [session]` | Start a daemonless local terminal (`[session]` attaches if it exists) |
|
|
272
|
+
| `hop stop` | Stop the hop daemon (terminal sessions keep running) |
|
|
273
|
+
| `hop stop --all` | Stop the daemon, the hay-host, and all terminal sessions |
|
|
274
|
+
| `hop status` | Show daemon, tunnel, and session status |
|
|
275
|
+
| `hop doctor` | Run environment/health checks |
|
|
276
|
+
| `hop logs [-f]` | Show daemon logs (`-f` to follow) |
|
|
277
|
+
| `hop health [--restart]` | Check tunnel health (`--restart` forces a tunnel restart) |
|
|
269
278
|
| `hop url` | Print current tunnel URL |
|
|
270
279
|
| `hop qr` | Show QR code for current tunnel URL |
|
|
271
280
|
| `hop qr auth` | Show QR code for authenticator app setup |
|
|
281
|
+
| `hop config theme [name]` | Show or set the session naming theme |
|
|
272
282
|
| `hop domain <hostname>` | Set custom domain (named tunnel) |
|
|
273
283
|
| `hop domain-clear` | Remove custom domain, use random URLs |
|
|
274
284
|
| `hop password set` | Set/change password |
|
|
@@ -278,19 +288,24 @@ Hop uses the external Hay host runtime for PTY hosting and session recovery.
|
|
|
278
288
|
| `hop user remove <name>` | Remove user |
|
|
279
289
|
| `hop user export <name>` | Export user credentials |
|
|
280
290
|
| `hop session list` | List live terminal sessions |
|
|
281
|
-
| `hop session list --all` | Include saved definitions from all workspaces alongside live sessions |
|
|
291
|
+
| `hop session list --all` | Include saved definitions from all workspaces alongside live sessions (`-a` is shorthand) |
|
|
282
292
|
| `hop session add <name> [--cwd P] --workspace W` | Save a terminal session definition to a named workspace |
|
|
283
293
|
| `hop session add <name> --port N --workspace W` | Save a port session definition to a named workspace |
|
|
294
|
+
| `hop session permit <name>` | Allow agent access to a session |
|
|
295
|
+
| `hop session block <name>` | Block agent access to a session |
|
|
296
|
+
| `hop workspace list` | List workspaces |
|
|
284
297
|
| `hop workspace create <name>` | Create an empty workspace |
|
|
285
298
|
| `hop workspace show <name>` | Show saved definitions in a workspace |
|
|
286
299
|
| `hop workspace save <name>` | Save selected live terminal sessions into a workspace |
|
|
287
300
|
| `hop workspace load <name>` | Start sessions defined in a workspace |
|
|
288
|
-
| `hop workspace delete <name
|
|
301
|
+
| `hop workspace delete <name> [--yes]` | Delete a workspace (asks before deleting a non-empty one) |
|
|
289
302
|
| `hop session rename <old> <new>` | Rename a session |
|
|
290
303
|
| `hop session remove <name>` | Remove a session |
|
|
291
304
|
| `hop client <credentials>` | Run hop with exported credentials |
|
|
292
|
-
| `hop wipe [--all]` | Remove workspace-defined sessions (`--all` also kills live sessions) |
|
|
293
|
-
| `
|
|
305
|
+
| `hop wipe [--all] [--yes]` | Remove workspace-defined sessions (`--all` also kills live sessions after a confirmation; `--yes` skips it) |
|
|
306
|
+
| `hop wipe --agent` | Close all agent-created terminal API sessions |
|
|
307
|
+
|
|
308
|
+
Local CLI mouse capture is off by default so terminal-native selection and context menus keep working. Use Option+M / Alt+M inside the local Hop view to toggle Hop mouse selection when needed. Use Option+B / Alt+B to toggle the status bar. CLI defaults live under `hay-cli` in `~/.hop.json`.
|
|
294
309
|
|
|
295
310
|
### Development
|
|
296
311
|
|
package/hay/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,40 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## [
|
|
3
|
+
## [0.9.0] - 2026-06-12
|
|
4
|
+
|
|
5
|
+
### New Features
|
|
6
|
+
|
|
7
|
+
#### CLI Client
|
|
8
|
+
- **Scrollback search (Opt+F)**: incremental search over the buffer; all matches are highlighted (current match bright), `Enter`/`↓` jump to the next match and `↑` to the previous one.
|
|
9
|
+
- **Presence names + take/release control (Opt+C)**: peer names (with typing markers) in the status bar and exclusive-control parity with the web client.
|
|
10
|
+
- **Persistent reconnect indicator**: a banner with the failure reason, countdown to the next retry, and attempt count stays visible while disconnected (CLI and web); the CLI now exits with a clear error if the first ~5 connection attempts never succeed.
|
|
11
|
+
- **Kill confirmation**: `Ctrl+Q` must be pressed twice within 2s to kill the session; the end-of-session message names who killed it and includes the exit code/signal when relevant.
|
|
12
|
+
- **Scroll indicator**: when the viewport is detached from live output the status bar shows `scroll <pos>/<total> · Opt+0 live`; exiting search keeps your scrollback position and hints the way back.
|
|
13
|
+
- **Send-literal escape hatch (Opt+\\)**: forwards the next key verbatim so reserved keys (`Ctrl+Q`/`Ctrl+G`) can reach remote programs.
|
|
14
|
+
- **Hints toggle moved to Opt+T** (was `Ctrl+T`), matching the other Opt toggles; `Ctrl+T` now passes through to the remote terminal (readline transpose-chars, fzf, etc.).
|
|
15
|
+
- **Adaptive bar themes**: status/hint bars auto-detect light vs dark terminal backgrounds (OSC 11 query, `$COLORFGBG` fallback) with truecolor palettes; pin with `--theme light|dark|auto` or `{"hay-cli": {"theme": "dark"}}` in `.hop.json`.
|
|
16
|
+
- **Status bar redesign**: semantic state dot at the right edge (green connected / amber reconnecting / red disconnected / purple locked), session name as an accent chip at the left edge, dim cwd, `·` separators, `manual` shown only when autofit is off.
|
|
17
|
+
- **Bigger reattach scrollback**: the server now retains ~2MB of raw output per room for reattach snapshots (was 200KB, which TUI-heavy streams exhausted in a screenful); override with `HAY_SNAPSHOT_BUFFER_BYTES`. Client scrollback raised to 5000 lines (CLI and web).
|
|
18
|
+
- **Hint bar redesign**: keycap-style hints (`⌃G detach · ⌥F find …` on macOS) with keys at full strength and labels dim; notices render as toasts (`✓` confirmations, `!` warnings, accent edge for info); the hint line surface is one step fainter than the status line.
|
|
19
|
+
- **Clearer session feedback**: "Created new session" vs "Attached to (N participants)" notice on connect, named control-handoff notices ("alice took control…"), friendlier control-locked rejection with the controller's name, and a reattach hint on detach.
|
|
20
|
+
- **CLI argument validation**: unknown flags and extra positional arguments are rejected with an error instead of silently becoming the room name.
|
|
21
|
+
|
|
22
|
+
#### Server
|
|
23
|
+
- Optional `created` flag on `hello` and `by` attribution on `session_ended` (both backwards compatible).
|
|
24
|
+
- Invalid client messages are rejected with the message type and offending field (e.g. `Invalid resize message: rows …`) instead of a bare "Invalid message".
|
|
25
|
+
|
|
26
|
+
### Performance
|
|
27
|
+
|
|
28
|
+
- CLI rendering uses dirty-line diffing with a ~60fps frame throttle, repainting only rows that changed.
|
|
4
29
|
|
|
5
30
|
### Bug Fixes
|
|
6
31
|
|
|
7
32
|
- Fixed the mobile terminal layout so the virtual keyboard anchors to the viewport bottom and no longer leaves a large gap above the screen edge.
|
|
33
|
+
- `Ctrl+Q` while disconnected no longer falsely prints "Session terminated."; it now explains the server is unreachable and that the session may still be running.
|
|
34
|
+
- Tiny terminal windows no longer send `resize` messages below the protocol minimum (2x2), which the server used to reject.
|
|
35
|
+
- Reserved `Ctrl` keys pressed in the brief post-connect grace window are swallowed instead of being forwarded to the remote shell.
|
|
36
|
+
- Mouse-copy notice hedges to "Sent N line(s) to clipboard (OSC 52)" since terminal support for OSC 52 varies.
|
|
37
|
+
- README/`--help` keyboard documentation corrected (all viewport shortcuts require Opt/Alt) and completed (Opt+0, Opt+F, Opt+C, Opt+H/J/K/L, Shift fast-pan, Opt+\\).
|
|
8
38
|
|
|
9
39
|
## [0.8.0] - 2025-01-25
|
|
10
40
|
|
package/hay/README.md
CHANGED
|
@@ -68,17 +68,55 @@ After building:
|
|
|
68
68
|
node apps/cli/dist/index.js -r my-room -n alice
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
+
### Theming
|
|
72
|
+
|
|
73
|
+
The status and hint bars adapt to your terminal. By default (`auto`) the CLI
|
|
74
|
+
queries the terminal's background color (OSC 11, with `$COLORFGBG` as an
|
|
75
|
+
immediate fallback) and picks a light or dark palette to match. Colors use
|
|
76
|
+
truecolor when `$COLORTERM` advertises support, with 256-color fallbacks.
|
|
77
|
+
|
|
78
|
+
Pin a palette per run with `--theme light|dark|auto`, or persist it in
|
|
79
|
+
`.hop.json` (local or `~/.hop.json`):
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{ "hay-cli": { "theme": "dark" } }
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The dot at the right edge of the status bar is semantic: green = connected,
|
|
86
|
+
amber = connecting/reconnecting, red = disconnected, purple = control locked.
|
|
87
|
+
|
|
71
88
|
### Keyboard Shortcuts
|
|
72
89
|
|
|
90
|
+
`Opt` means the Option key on macOS and `Alt` elsewhere. Run `hay --help` for
|
|
91
|
+
the authoritative, up-to-date list.
|
|
92
|
+
|
|
73
93
|
| Key | Action |
|
|
74
94
|
|-----|--------|
|
|
75
|
-
|
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
79
|
-
| `
|
|
80
|
-
| `
|
|
81
|
-
| `
|
|
95
|
+
| `Opt+←` `Opt+→` `Opt+↑` `Opt+↓` | Pan viewport (add `Shift` for faster panning) |
|
|
96
|
+
| `Opt+H` `Opt+J` `Opt+K` `Opt+L` | Pan viewport, vim-style (`Shift` = faster) |
|
|
97
|
+
| `Opt+0` | Return to live output (center on cursor) |
|
|
98
|
+
| `Opt+A` | Toggle autofit of the remote size to the local window |
|
|
99
|
+
| `Opt+B` | Toggle status bar |
|
|
100
|
+
| `Opt+M` | Toggle mouse capture (off by default, so terminal context menus keep working) |
|
|
101
|
+
| `Opt+F` | Search scrollback (`Enter`/`↓` next, `↑` previous, `Esc` close) |
|
|
102
|
+
| `Opt+C` | Take/release exclusive control |
|
|
103
|
+
| `Opt+T` | Toggle hints bar |
|
|
104
|
+
| `Opt+\` | Send the next key literally to the remote terminal (lets reserved keys like `Ctrl+Q`/`Ctrl+G` reach remote programs) |
|
|
105
|
+
| `Ctrl+G` | Detach from session; the session keeps running |
|
|
106
|
+
| `Ctrl+Q` `Ctrl+Q` | Kill session for all participants (press twice within 2s to confirm) |
|
|
107
|
+
|
|
108
|
+
`Opt`/`Alt` letter shortcuts arrive as ESC-prefixed keys: on non-macOS
|
|
109
|
+
terminals (and macOS terminals without "Option as Meta") enable the
|
|
110
|
+
option/alt-as-meta or ESC-prefix setting in your terminal emulator for them to
|
|
111
|
+
work.
|
|
112
|
+
|
|
113
|
+
Local sessions are persistent by default: they keep running in the Hay host if
|
|
114
|
+
the local CLI detaches or the Hop daemon restarts. Use `Ctrl+Q` (pressed twice)
|
|
115
|
+
to end the session itself; reattach to a running session with `hay -r <room>`.
|
|
116
|
+
|
|
117
|
+
Mouse-selection copy uses OSC 52, so it lands in your local clipboard only if
|
|
118
|
+
your terminal emulator supports and allows OSC 52 clipboard writes (iTerm2,
|
|
119
|
+
kitty, WezTerm, recent tmux with `set-clipboard on`, etc.).
|
|
82
120
|
|
|
83
121
|
When the viewport is at the bottom, the CLI follows new output automatically.
|
|
84
122
|
If you pan upward to inspect scrollback, incoming output no longer forces the
|
|
@@ -100,6 +138,9 @@ Example `.hop.json`:
|
|
|
100
138
|
{
|
|
101
139
|
"hay-cli": {
|
|
102
140
|
"showHints": true,
|
|
141
|
+
"showStatusBar": true,
|
|
142
|
+
"mouseCapture": false,
|
|
143
|
+
"syncSize": true,
|
|
103
144
|
"scrollOff": 3
|
|
104
145
|
}
|
|
105
146
|
}
|
|
@@ -110,6 +151,9 @@ Configuration options:
|
|
|
110
151
|
| Option | Default | Description |
|
|
111
152
|
|--------|---------|-------------|
|
|
112
153
|
| `showHints` | `true` | Show keyboard shortcut hints at the bottom |
|
|
154
|
+
| `showStatusBar` | `true` | Show the session/status bar |
|
|
155
|
+
| `mouseCapture` | `false` | Capture mouse events for Hop selection and local wheel scrolling |
|
|
156
|
+
| `syncSize` | `true` | Auto-fit the remote terminal size to the local viewport |
|
|
113
157
|
| `scrollOff` | `3` | Lines of context to keep above/below the cursor |
|
|
114
158
|
|
|
115
159
|
## Web Client
|
|
@@ -188,12 +232,13 @@ Client to server:
|
|
|
188
232
|
Server to client:
|
|
189
233
|
|
|
190
234
|
```ts
|
|
191
|
-
{ type: "hello", clientId, roomId, color, collabMode, controllerId }
|
|
235
|
+
{ type: "hello", clientId, roomId, color, collabMode, controllerId, created? }
|
|
192
236
|
{ type: "output", data: string }
|
|
193
237
|
{ type: "snapshot", data: string }
|
|
194
238
|
{ type: "presence", clients: [...] }
|
|
195
239
|
{ type: "collab", enabled, controllerId }
|
|
196
240
|
{ type: "input_rejected", reason: string }
|
|
241
|
+
{ type: "session_ended", exitCode, signal, message, by? }
|
|
197
242
|
```
|
|
198
243
|
|
|
199
244
|
## Environment Variables
|