hop2 0.9.0 → 0.9.1

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/AGENTS.md ADDED
@@ -0,0 +1,33 @@
1
+ # AGENTS.md (hop2)
2
+
3
+ Guidance for agents working on hop2.
4
+
5
+ ## Project shape
6
+ - `hop` is the main Node.js CLI/server entry point (bin target).
7
+ - `sessions.html` is the built-in session picker UI.
8
+ - `hay/` contains the terminal sharing stack (server/cli/web).
9
+ - `hay-web/` is the built web client output served by `hop`.
10
+
11
+ ## Local state & config
12
+ - Default config dir is `~/.hop2` (override via `HOP_HOME`).
13
+ - State files here should remain private (permissions matter).
14
+ - Be careful with migrations: preserve backward compatibility where possible.
15
+
16
+ ## Change discipline
17
+ - Keep changes focused and consistent with existing patterns.
18
+ - Avoid unrelated refactors; minimize surface area.
19
+ - Add concise comments only for non-obvious logic.
20
+ - Update docs when user-visible behavior changes.
21
+
22
+ ## Build & test
23
+ - Build web assets via `npm run build` (builds `hay` then syncs to `hay-web`).
24
+ - Basic sanity check: `npm test` (runs `node --check hop`).
25
+ - If you don’t run tests, say so and suggest likely commands.
26
+
27
+ ## UI work
28
+ - Preserve existing visual language unless a redesign is intended.
29
+ - Ensure layouts remain usable on desktop and mobile.
30
+
31
+ ## Server/CLI work
32
+ - Prefer clear errors and non-zero exit codes on failures.
33
+ - Keep security-sensitive behavior conservative and explicit.
@@ -0,0 +1,30 @@
1
+ # Multi-Agent Run Checklist
2
+
3
+ ## Goal
4
+ Ensure concurrent agent sessions stay isolated, time-bounded, and recoverable.
5
+
6
+ ## Safety Gates
7
+
8
+ - [ ] **Isolated terminals** — assign each agent its own PTY via `hop_create_terminal`; never share a session between agents.
9
+ - [ ] **Destructive-command approval** — gate every `rm -rf`, force-push, or `DROP TABLE` behind explicit user confirmation, regardless of autonomy level.
10
+ - [ ] **Per-command timeouts** — enforce `idle_ms` and `max_wait_ms` on every `hop_wait_terminal` call; escalate or kill on deadline breach.
11
+
12
+ ## Execution Loop
13
+
14
+ 1. **Create session** — one `hop_create_terminal` per agent.
15
+ 2. **Validate prompt** — call `hop_wait_terminal(until_prompt=true)` to confirm the shell is ready before sending any command.
16
+ 3. **Send command** — write via `hop_write_terminal`; never blind-write into mid-execution output.
17
+ 4. **Await result** — use `until_regex` or `until_prompt` with `max_wait_ms` to capture output and detect completion.
18
+ 5. **Assert state** — verify exit code / expected output before proceeding.
19
+ 6. **Repeat** steps 2–5 for each command in the plan.
20
+
21
+ ## Recovery
22
+
23
+ | Step | Action |
24
+ |------|--------|
25
+ | 1 | Send `ctrl_c` via `hop_send_key` |
26
+ | 2 | If unresponsive after 5 s → `hop_close_terminal(killSession=true)` |
27
+ | 3 | On orchestrator crash → kill **all** child terminals (kill switch) |
28
+ | 4 | Verify zero orphaned processes before declaring shutdown complete |
29
+
30
+ **Rule:** Never skip escalation. Always tear down — never leave orphaned sessions.
package/README-MCP.md ADDED
@@ -0,0 +1,213 @@
1
+ # Hop MCP Server
2
+
3
+ The Hop MCP server exposes hop’s terminal/session APIs over the Model Context Protocol (MCP), so agents can create terminals, stream output, and send input through Hop.
4
+
5
+ ## Quick Start
6
+
7
+ 1) Ensure Hop daemon is running locally (creates `~/.hop2/.tunnel-state`).
8
+
9
+ 2) Auto-configure supported MCP clients:
10
+
11
+ ```bash
12
+ hop-mcp-setup
13
+ ```
14
+
15
+ If you are running from source in this repo:
16
+
17
+ ```bash
18
+ npm run setup-mcp
19
+ ```
20
+
21
+ Supported auto-detected clients:
22
+ - Claude Code
23
+ - Claude Desktop
24
+ - Cursor IDE
25
+ - Gemini CLI
26
+ - Codex CLI
27
+ - VS Code / GitHub Copilot (workspace via `.vscode/mcp.json`)
28
+ - Antigravity
29
+
30
+ 3) Or configure your MCP client manually:
31
+
32
+ ```json
33
+ {
34
+ "mcpServers": {
35
+ "hop": {
36
+ "command": "hop-mcp"
37
+ }
38
+ }
39
+ }
40
+ ```
41
+
42
+ 4) Restart your MCP client.
43
+
44
+ The server auto-connects to the local Hop daemon via `~/.hop2/.tunnel-state`.
45
+
46
+ ## One Subagent Terminal (Claude/Codex)
47
+
48
+ Recommended flow for driving one agent CLI safely:
49
+
50
+ 1) Launch a dedicated terminal:
51
+
52
+ ```
53
+ hop_create_terminal(name="subagent", cwd="/path/to/repo")
54
+ ```
55
+
56
+ 2) Start the agent CLI:
57
+
58
+ ```
59
+ hop_write_terminal(data="claude\n")
60
+ # or
61
+ hop_write_terminal(data="codex\n")
62
+ ```
63
+
64
+ 3) Wait for a prompt before sending work:
65
+
66
+ ```
67
+ hop_wait_terminal(until_prompt=true, start_from="latest")
68
+ ```
69
+
70
+ 4) Run a multi-turn loop:
71
+ - preferred: `hopx_send_and_wait(data="<task>", press_enter=true, capture="readable_raw")`
72
+ - helper alternative: `hopx_agent_turn(data="<task>", mode="auto")`
73
+ - manual split (if needed):
74
+ - send one instruction with `hop_write_terminal(data="<task>\n")`
75
+ - wait for output with `hop_wait_terminal(capture="readable_raw")` (defaults to `until_agent_done`)
76
+ - continue with cursor-deltas via `hop_read_terminal(start_from="cursor", cursor=...)`
77
+ - send the next instruction only after output is captured
78
+
79
+ 5) Stop/cleanup:
80
+ - interrupt with `hop_send_key(key="ctrl_c")`
81
+ - close with `hop_close_terminal(killSession=false)`
82
+
83
+ Safety notes:
84
+ - Keep one subagent per terminal (no multiplexing multiple agent CLIs in one PTY).
85
+ - For existing user sessions, verify `agentPermitted` (or set with `hop_set_agent_permission`) before writing input.
86
+
87
+ ## Remote Hop
88
+
89
+ To connect to a remote hop instance, set env vars or use `connect_server`:
90
+
91
+ ```bash
92
+ HOP_API_URL="https://hop2.example.com" HOP_TOKEN="<token>" hop-mcp
93
+ ```
94
+
95
+ Or from tools:
96
+
97
+ ```
98
+ connect_server(base_url="https://hop2.example.com", token="<token>")
99
+ ```
100
+
101
+ Optional verification:
102
+
103
+ ```
104
+ connect_server(base_url="https://hop2.example.com", token="<token>", verify=true, verify_endpoint="/api/sessions")
105
+ ```
106
+
107
+ ## Tools
108
+
109
+ Core tools (`hop_`): stable atomic operations.
110
+ - `connect_server`
111
+ - `hop_server_info`
112
+ - `hop_list_sessions`
113
+ - `hop_list_terminals`
114
+ - `hop_create_terminal`
115
+ - `hop_attach_terminal`
116
+ - `hop_write_terminal`
117
+ - `hop_send_key`
118
+ - `hop_wait_terminal`
119
+ - `hop_wait_start`
120
+ - `hop_wait_poll`
121
+ - `hop_resize_terminal`
122
+ - `hop_read_terminal`
123
+ - `hop_close_terminal`
124
+ - `hop_set_agent_permission`
125
+ - `hop_list_workspaces`
126
+ - `hop_save_workspace`
127
+ - `hop_load_workspace`
128
+ - `hop_use_workspace`
129
+
130
+ Helper tools (`hopx_`): convenience wrappers built on top of core tools.
131
+ - `hopx_send_and_wait` (single-call send + wait wrapper)
132
+ - `hopx_agent_turn` (single-turn send + wait + mode-aware output, default `mode="auto"`)
133
+
134
+ ## Resources
135
+
136
+ - `hop://sessions`
137
+ - `hop://terminals`
138
+ - `hop://workspaces`
139
+
140
+ ## Notes
141
+
142
+ - Agent access is gated by `agentPermitted` for sessions created by users.
143
+ - `terminal_id` is an ephemeral daemon attachment handle; underlying hop `sessionName` is the stable identity.
144
+ - On daemon restart, terminal-scoped tools auto-reattach once using stored session identity and retry transparently when possible.
145
+ - `hop_read_terminal` returns a cursor for incremental polling.
146
+ - `hop_read_terminal` supports `mode: "ui"` for structured terminal snapshots:
147
+ - `ui.lines`: visible screen lines
148
+ - `ui.cursor`: cursor position
149
+ - `ui.window.strategy`: `cursor_centered` with auto fallback to `densest_nonempty` when needed
150
+ - `rawTail`: optional lossless tail of recent raw events (for transient output)
151
+ - Hop server now replays buffered terminal events on stream connect, so late attaches get immediate context instead of an empty first read.
152
+ - `hop_read_terminal` supports `mode: "readable_raw"`:
153
+ - preserves printable text in `events[].text`
154
+ - includes compact control hints in `events[].controls` (cursor, erase, alt-screen, visibility)
155
+ - `control_level` tunes control noise:
156
+ - `full`
157
+ - `structural` (cursor/edit/screen controls; omits CR/LF noise)
158
+ - `none` (default; text only)
159
+ - `noise_filter` tunes status/spinner suppression:
160
+ - `balanced` (default; suppresses CR/erase rewrite bursts, commits stable lines, strips spinner-prefix/dot animation for dedupe)
161
+ - in `balanced`, recent shell echo lines for agent-sent input (prompt + command) and prompt-padding artifacts are compacted
162
+ - `off` (raw parsed text; useful for parser debugging)
163
+ - in default `none`, empty output frames are dropped to reduce event noise
164
+ - `coalesce_ms` and `coalesce_max_chars` can merge adjacent output frames for cleaner streaming text
165
+ - defaults: `coalesce_ms=250`, `coalesce_max_chars=32768`
166
+ - parses incrementally across chunk boundaries to avoid split ANSI artifacts
167
+ - reconstructs common inline edits (backspace/cursor rewrites) so text is cleaner for agent parsing
168
+ - avoids full ANSI noise while retaining interaction structure
169
+ - `hop_send_key` sends normalized named keys (for example `enter`, `esc`, `up`, `ctrl_c`) to improve interactive TUI control without raw escape-string handling.
170
+ - `hop_wait_terminal` blocks on output conditions without client polling loops:
171
+ - `start_from` controls where matching begins:
172
+ - `latest` (default): stream tail / new output only
173
+ - `cursor`: requires `cursor` argument
174
+ - `beginning`: oldest buffered event
175
+ - if no explicit condition is provided, it defaults to `until_agent_done=true`
176
+ - `async=true` starts a background wait job and returns `wait_id` immediately
177
+ - `until_agent_done` matches when output has started, terminal becomes quiet, and interactive cursor is visible (agent-friendly completion)
178
+ - regex match via `until_regex`
179
+ - prompt match via `until_prompt` (optional custom `prompt_regex`)
180
+ - quiet-period detection via `idle_ms`
181
+ - bounded event capture in `raw` or `readable_raw`
182
+ - for `capture="readable_raw"`, supports `control_level`, `noise_filter`, `coalesce_ms`, `coalesce_max_chars`, and optional `includeMetaEvents`
183
+ - `hop_wait_start` / `hop_wait_poll` provide explicit async wait orchestration for long-running conditions:
184
+ - start with `hop_wait_start(...)` and poll with `hop_wait_poll(wait_id=..., wait=true)`
185
+ - use `consume=true` on poll to remove completed jobs
186
+ - `hopx_send_and_wait` combines input send + optional enter/key + wait, and defaults to cursor-based delta capture from just before send.
187
+ - helper defaults are token-thrifty for interactive loops: `capture_max_events=60`, `control_level=none`, `noise_filter=balanced`, `coalesce_ms=350` (unless overridden)
188
+ - for `capture="readable_raw"`, `text_only` defaults to `true`; this condenses wait payloads by returning joined `wait.text`, setting `wait.events=[]`, `wait.eventCount=0`, and preserving prior count in `wait.originalEventCount` (set `text_only=false` to keep full events)
189
+ - `hop_read_terminal` supports deterministic delta reads:
190
+ - `start_from`: `beginning` (default), `cursor`, or `latest`
191
+ - response includes `cursorStart`, `cursorEnd`, and `next_cursor`
192
+ - `hopx_agent_turn` is a helper wrapper (not a core primitive):
193
+ - default `mode="auto"` chooses `ui` when terminal is in alternate-screen, otherwise `readable_raw`
194
+ - in `mode="auto"`, if alternate-screen starts during the same turn, it auto-promotes to `ui` for that response
195
+ - wait-only continuation is supported: omit `data`/`message` and use `control="wait"` to keep waiting on a terminal without sending new input
196
+ - `async=true` starts the turn wait in the background and returns `wait_id` immediately; continue polling or controlling that turn with `hopx_agent_turn(wait_id=..., wait=true|false, control=...)`
197
+ - `control="interrupt"` / `control="terminate"` send an explicit interrupt key (default `esc`); `terminate_message` can send a final follow-up after the interrupt
198
+ - `mode="ui"` returns a UI snapshot payload after wait
199
+ - for readable modes, `text_only` defaults to `true` and condenses waits the same way as `hopx_send_and_wait` (set `text_only=false` to keep full wait events)
200
+ - `text_only` is ignored for `mode="ui"` output snapshots
201
+ - `mode="ui"` defaults `includeRawTail=false` to reduce noisy tail payloads (opt in with `includeRawTail=true`)
202
+ - `mode="ui"` defaults wait capture to `capture_max_events=0` (override when you need readable wait-event diagnostics)
203
+ - when using default `until_agent_done` semantics in `mode="ui"`, hopx applies a short UI busy-guard pass to avoid returning while status lines still indicate active work (`esc to interrupt`, `working`, `waiting for process`, etc.)
204
+ - `mode="readable_raw"` / `mode="raw"` returns the same wait payload shape as `hopx_send_and_wait`
205
+ - Tool calls that fail at the Hop API layer now return MCP errors (`isError: true`) with normalized fields:
206
+ - `ok`
207
+ - `status`
208
+ - `endpoint`
209
+ - `error`
210
+ - Hop now isolates shell history per session and writes per-session NDJSON audit logs under `~/.hop2/workspaces/<workspace>/logs/<session>/audit.ndjson` with truncation metadata for large chunks.
211
+ - Audit logging auto-switches to diff-suppressed `tui_keyframe` snapshots when alternate-screen apps (vim/htop/agent TUIs) are detected, while still capturing all input events.
212
+ - Default fallback terminal size is `140x40` when no explicit `cols`/`rows` are provided.
213
+ - `hop_create_terminal` / `hop_attach_terminal` now do a short output warmup before returning, reducing first-command races in interactive shells.
package/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  Access your Mac's terminal from your phone, tablet, or any browser — secured with password + 2FA, tunneled through Cloudflare.
6
6
 
7
+ Hop also ships with a built-in MCP server, so Claude Code, Codex, Gemini, Cursor, and other MCP clients can create terminals, stream output, and drive agent sessions through Hop.
8
+
7
9
  > **🍎 macOS/Linux** — Requires cloudflared for tunneling
8
10
 
9
11
  ```
@@ -16,6 +18,7 @@ Access your Mac's terminal from your phone, tablet, or any browser — secured w
16
18
 
17
19
  - 🔐 **Password + 2FA** — Optional password plus TOTP (required for custom domains)
18
20
  - 🌍 **Access Anywhere** — Cloudflare tunnel, no port forwarding
21
+ - 🤖 **Built-in MCP Server** — Turn Hop into an agent-facing terminal platform for Claude Code, Codex, Gemini, Cursor, and more
19
22
  - 🌐 **Custom Domains + Multi‑User** — Share subdomains with per‑user credentials
20
23
  - 📱 **Mobile Virtual Keyboard** — Custom keyboard with Esc, Ctrl, Alt, arrows, and more
21
24
  - ⌨️ **Native Keyboard Support** — Tap the blue button for dictation, spellcheck & autocomplete
@@ -33,6 +36,11 @@ Access your Mac's terminal from your phone, tablet, or any browser — secured w
33
36
  npm install -g hop2
34
37
  ```
35
38
 
39
+ This installs:
40
+ - `hop` — main CLI / daemon / browser terminal entrypoint
41
+ - `hop-mcp` — MCP server exposing Hop terminals and sessions
42
+ - `hop-mcp-setup` — MCP client auto-config helper
43
+
36
44
  Then just run:
37
45
  ```bash
38
46
  hop
@@ -69,9 +77,6 @@ source ~/.zshrc
69
77
  ```bash
70
78
  # Start hopping!
71
79
  hop
72
-
73
- # Use iTerm control mode for local session
74
- hop --iterm
75
80
  ```
76
81
 
77
82
  **First time:**
@@ -86,6 +91,27 @@ hop --iterm
86
91
  3. Pick or create a session
87
92
  4. 🐰 You're in! Use the virtual keyboard for terminal keys, or tap the blue button for native input
88
93
 
94
+ ## 🤖 Hop MCP
95
+
96
+ Hop is not just a browser terminal. It also exposes terminals and sessions over MCP so agents can safely operate through the same platform.
97
+
98
+ Use cases:
99
+ - Launch a dedicated Claude Code / Codex / Gemini terminal and drive it over multiple turns
100
+ - Create isolated agent sessions with per-session history and audit logs
101
+ - Read terminal output incrementally instead of screen-scraping a browser
102
+ - Build higher-level agent workflows on top of stable terminal/session primitives
103
+
104
+ Quick start:
105
+
106
+ ```bash
107
+ hop
108
+ hop-mcp-setup
109
+ ```
110
+
111
+ Then restart your MCP client. `hop-mcp-setup` auto-detects and configures supported clients such as Claude Code, Claude Desktop, Cursor, Gemini CLI, Codex CLI, VS Code / Copilot, and Antigravity.
112
+
113
+ For full MCP usage, tools, and subagent workflows, see [README-MCP.md](./README-MCP.md).
114
+
89
115
  ## 🪟 Sessions
90
116
 
91
117
  Create multiple independent terminal sessions from the Session Picker (`/sessions`):
@@ -98,8 +124,37 @@ You can also create **Port Sessions** that proxy to a local HTTP/WS service on y
98
124
  Use the Session Picker or:
99
125
  ```bash
100
126
  hop session add myapp --port 3000
127
+ hop session add workspace-shell --cwd ~/src/my-project
101
128
  ```
102
129
 
130
+ ## 🧾 Session History & Audit Logs
131
+
132
+ Hop always writes per-session audit logs.
133
+ Shell history isolation is role-based by default:
134
+
135
+ - Agent-created terminal sessions: isolated history file per session
136
+ - User-created terminal sessions: keep your shell default history file (opt-in isolation available)
137
+
138
+ - Isolated history file path: `~/.hop2/workspaces/<workspace>/history/<internal-session>.history`
139
+ - Audit log (NDJSON): `~/.hop2/workspaces/<workspace>/logs/<internal-session>/audit.ndjson`
140
+ - Audit events include `session_start`, `input`, `resize`, `session_end`, plus:
141
+ - `audit_mode` / `pty_state` transitions (auto-switches between `stream` and `tui_keyframe`)
142
+ - `tui_keyframe` snapshots (diff-suppressed; emitted only when content changes)
143
+ - `command_launch` metadata (captures launched command token and detected agent CLI type)
144
+ - Large input/output chunks are truncated with metadata (`bytes`, `omittedBytes`, `dataHead`, `dataTail`)
145
+
146
+ Tunable defaults:
147
+
148
+ - `HOP_SESSION_HISTORY_SIZE` (default `5000`)
149
+ - `HOP_AGENT_HISTORY_ISOLATION` (default `1`)
150
+ - `HOP_USER_HISTORY_ISOLATION` (default `0`)
151
+ - `HOP_AGENT_POST_START_HISTORY_INIT` (default `1`)
152
+ - `HOP_POST_START_HISTORY_INIT` (default `0`, forces post-start history init for all sessions)
153
+ - `HOP_SESSION_AUDIT_INLINE_MAX_BYTES` (default `4096`)
154
+ - `HOP_SESSION_TUI_KEYFRAME_INTERVAL_MS` (default `750`)
155
+ - `HOP_SESSION_TUI_KEYFRAME_TAIL_CHARS` (default `20000`)
156
+ - `HOP_SESSION_TUI_KEYFRAME_MAX_LINES` (default `80`)
157
+
103
158
  ## 🌐 Custom Domains & Multi‑User
104
159
 
105
160
  ### Admin (your machine)
@@ -145,13 +200,13 @@ On mobile devices, Hop provides a custom virtual keyboard designed for terminal
145
200
  - First-time users will see a tooltip pointing to the native keyboard button
146
201
  - Use the native keyboard for longer text input with autocomplete
147
202
 
148
- ## 🖥️ iTerm Integration
203
+ ## 🖥️ Local Attach
149
204
 
150
205
  ```bash
151
- hop --iterm
206
+ hop attach <session>
152
207
  ```
153
208
 
154
- Uses tmux control mode (`-CC`) for native scrolling, copy/paste, splits, and search. Session remains accessible via web.
209
+ Attach your local terminal client to an existing hop terminal session.
155
210
 
156
211
  ## 🔌 Port Sessions
157
212
 
@@ -168,10 +223,12 @@ Works with dev servers, Jupyter, APIs — anything on localhost. Supports WebSoc
168
223
 
169
224
  | Command | Description |
170
225
  |---------|-------------|
171
- | `hop` | Start hop (or attach to existing tunnel) |
172
- | `hop --iterm` | Use iTerm tmux control mode for local session |
226
+ | `hop` | Start hop daemon/tunnel if needed, then launch a local terminal |
227
+ | `hop attach all` | Attach sequentially to all terminal sessions |
228
+ | `hop local [session]` | Start a daemonless local terminal (`[session]` attaches if it exists) |
173
229
  | `hop url` | Print current tunnel URL |
174
- | `hop qr` | Show QR code for current URL |
230
+ | `hop qr` | Show QR code for current tunnel URL |
231
+ | `hop qr auth` | Show QR code for authenticator app setup |
175
232
  | `hop domain <hostname>` | Set custom domain (named tunnel) |
176
233
  | `hop domain-clear` | Remove custom domain, use random URLs |
177
234
  | `hop password set` | Set/change password |
@@ -180,19 +237,36 @@ Works with dev servers, Jupyter, APIs — anything on localhost. Supports WebSoc
180
237
  | `hop user add <name>` | Add user + subdomain |
181
238
  | `hop user remove <name>` | Remove user |
182
239
  | `hop user export <name>` | Export user credentials |
183
- | `hop session list` | List sessions |
184
- | `hop session add <name>` | Create a terminal session |
240
+ | `hop session list` | List sessions with `LIVE` vs `SAVED` terminal status |
241
+ | `hop session add <name> [--cwd P]` | Create a terminal session |
185
242
  | `hop session add <name> --port N` | Create a port session (proxy) |
243
+ | `hop session rename <old> <new>` | Rename a session |
186
244
  | `hop session remove <name>` | Remove a session |
187
245
  | `hop client <credentials>` | Run hop with exported credentials |
188
- | `hop wipe` | Kill all hop tmux sessions |
246
+ | `hop wipe [--all]` | Remove saved sessions (`--all` also kills live sessions) |
189
247
  | `quit` | Type at exit prompt to shutdown tunnel |
190
248
 
249
+ Additional installed binaries:
250
+ - `hop-mcp` — Start the Hop MCP server directly
251
+ - `hop-mcp-setup` — Auto-configure supported MCP clients
252
+
253
+ Startup behavior:
254
+ - Hop reconciles already-running external Hay sessions first, then applies the default workspace as additional startup state.
255
+
256
+ ## 🧪 Terminal Backend
257
+
258
+ Hop always uses the `external` terminal runtime (PTYs in a separate local hay host process).
259
+
260
+ - The host persists across hop daemon restarts.
261
+ - Host state is tracked in `~/.hop2/.hay-host-state`.
262
+ - On startup and session listing, Hop discovers live hay-host processes and adopts the one(s) that still own runtime rooms if the state file is stale.
263
+ - Local CLI transport is direct to hay-host; daemon restarts do not terminate local terminal sessions.
264
+ - Bare `hop` prompts on cwd match (`Attach existing` vs `Create new`, default `Create new`); non-interactive runs always create new.
265
+ - `HOP_TERMINAL_BACKEND` is accepted for compatibility but ignored.
266
+
191
267
  ## 📦 Dependencies
192
268
 
193
269
  Installed automatically via Homebrew:
194
- - `tmux` — Terminal multiplexer
195
- - `ttyd` — Web terminal
196
270
  - `cloudflared` — Cloudflare tunnel
197
271
 
198
272
  Node.js packages:
@@ -206,6 +280,7 @@ Node.js packages:
206
280
  - **Password + TOTP** — Password optional, but required for custom domains
207
281
  - **Rate Limiting** — Exponential backoff on failed attempts
208
282
  - **Secure Cookies** — `httpOnly`, `secure`, `sameSite=lax`
283
+ - **Session persistence** — Login cookies are signed with a stable session secret by default, so browser sessions can survive `hop stop/start` without reauth.
209
284
  - **Random URL** — Unguessable tunnel URL for quick tunnels
210
285
  - **Fixed URL** — Custom domains keep a stable URL
211
286
  - **Local Binding** — Server only listens on 127.0.0.1
@@ -214,6 +289,7 @@ Node.js packages:
214
289
  **Passwords:** Recommended for any public URL; required for custom domains.
215
290
 
216
291
  **Secrets:** Stored in `~/.hop2/` (treat like `~/.ssh/`)
292
+ Set `HOP_PERSIST_SESSION_SECRET=0` to force a fresh login cookie secret every daemon restart.
217
293
 
218
294
  ## 🛠 Development (Hay)
219
295
 
@@ -226,10 +302,31 @@ npm run build
226
302
  This builds hay (web + cli) and syncs `hay/apps/web/dist` into `hay-web/` for Hop to serve.
227
303
  If `./hay` exists and the dist folder is missing, `hop` will auto-build hay on startup.
228
304
 
305
+ ## 🤖 Hop MCP (One Subagent Terminal)
306
+
307
+ Use one dedicated terminal when driving a subagent CLI through Hop MCP.
308
+
309
+ 1. Create a terminal with `hop_create_terminal` (set `name` and `cwd`).
310
+ 2. Start the agent CLI with `hop_write_terminal` (`claude` or `codex`).
311
+ 3. Wait for readiness with `hop_wait_terminal(until_prompt=true)`.
312
+ 4. Send one instruction at a time via `hopx_send_and_wait` (or `hop_write_terminal` + `hop_wait_terminal`).
313
+ 5. Optional helper path: use `hopx_agent_turn(mode="auto")` for a single send+wait turn with mode-aware output (`ui` for TUI screens, `readable_raw` otherwise); it auto-promotes to `ui` if alternate-screen starts mid-turn and uses lean capture defaults (`capture_max_events=60` for readable modes, `0` for `ui` unless overridden, plus `text_only=true` by default for readable waits).
314
+ 6. For long waits, prefer `hopx_agent_turn(async=true, ...)` and continue with `hopx_agent_turn(wait_id=..., wait=true, control="wait")`; fall back to `hop_wait_start(...)` / `hop_wait_poll(...)` when you want the lower-level primitives directly.
315
+ 7. After each turn, collect output with `hop_wait_terminal` or incremental `hop_read_terminal` cursor reads.
316
+ 8. Interrupt with `hop_send_key(key="ctrl_c")` and close using `hop_close_terminal`.
317
+
318
+ Safety tips:
319
+ - Keep one subagent per terminal.
320
+ - Do not queue a second instruction before reading the first response.
321
+ - For attached user sessions, confirm `agentPermitted` before sending input.
322
+
229
323
  ## 🐛 Troubleshooting
230
324
 
231
- **QR code not working?**
232
- Delete `.auth_secret` and restart hop to generate a new code.
325
+ **Authenticator QR code needed again?**
326
+ Run `hop qr auth` to re-show the current TOTP setup QR for Duo/Authy/1Password.
327
+
328
+ **Need to reset TOTP entirely?**
329
+ Delete `.auth_secret` and restart hop to generate a new authenticator secret and QR code.
233
330
 
234
331
  **Client reset (user mode)?**
235
332
  Delete `~/.hop2/clients/<tunnel-id>/` and run `hop client` again.
@@ -237,9 +334,12 @@ Delete `~/.hop2/clients/<tunnel-id>/` and run `hop client` again.
237
334
  **Tunnel not starting?**
238
335
  Make sure `cloudflared` is installed: `brew install cloudflared`
239
336
 
337
+ **Tunnel returns 502 or died after network changes?**
338
+ Run `hop health --restart`. Hop now waits for the public URL to become healthy again instead of only sending a fire-and-forget restart request.
339
+
240
340
  **Stuck processes?**
241
341
  ```bash
242
- pkill ttyd; pkill cloudflared; tmux kill-server
342
+ pkill cloudflared
243
343
  ```
244
344
 
245
345
  ## 📝 License
package/hay/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [Unreleased]
4
+
5
+ ### Bug Fixes
6
+
7
+ - 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.
8
+
3
9
  ## [0.8.0] - 2025-01-25
4
10
 
5
11
  ### Major Changes