hop2 0.8.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/.hop-tmux.conf +18 -0
- package/INTEGRATION.md +92 -0
- package/README.md +260 -0
- package/hay/CHANGELOG.md +46 -0
- package/hay/DEV_NOTES.md +39 -0
- package/hay/README.md +290 -0
- package/hay/apps/cli/package.json +25 -0
- package/hay/apps/cli/src/index.ts +1250 -0
- package/hay/apps/cli/tsconfig.json +8 -0
- package/hay/apps/server/package.json +37 -0
- package/hay/apps/server/src/index.ts +103 -0
- package/hay/apps/server/src/lib.ts +161 -0
- package/hay/apps/server/src/pty.ts +68 -0
- package/hay/apps/server/src/rooms.ts +421 -0
- package/hay/apps/server/src/utils.ts +20 -0
- package/hay/apps/server/test/rooms.test.ts +146 -0
- package/hay/apps/server/tsconfig.json +9 -0
- package/hay/apps/web/index.html +12 -0
- package/hay/apps/web/package.json +32 -0
- package/hay/apps/web/scripts/run-e2e.mjs +130 -0
- package/hay/apps/web/src/App.tsx +1302 -0
- package/hay/apps/web/src/components/MobileKeyboard.tsx +701 -0
- package/hay/apps/web/src/main.tsx +13 -0
- package/hay/apps/web/src/setupTests.ts +1 -0
- package/hay/apps/web/src/styles.css +1198 -0
- package/hay/apps/web/src/utils/optimisticEcho.ts +115 -0
- package/hay/apps/web/src/utils/presence.ts +24 -0
- package/hay/apps/web/src/vite-env.d.ts +10 -0
- package/hay/apps/web/test/optimisticEcho.test.ts +39 -0
- package/hay/apps/web/test/presence.test.ts +18 -0
- package/hay/apps/web/tsconfig.json +8 -0
- package/hay/apps/web/vite.config.ts +13 -0
- package/hay/apps/web/vitest.config.ts +12 -0
- package/hay/package-lock.json +5988 -0
- package/hay/package.json +18 -0
- package/hay/packages/shared/package.json +27 -0
- package/hay/packages/shared/src/colors.ts +16 -0
- package/hay/packages/shared/src/index.ts +2 -0
- package/hay/packages/shared/src/protocol.ts +90 -0
- package/hay/packages/shared/test/protocol.test.ts +33 -0
- package/hay/packages/shared/tsconfig.json +7 -0
- package/hay/tsconfig.base.json +15 -0
- package/hay-web/assets/index-CTTzApRp.css +32 -0
- package/hay-web/assets/index-FDfdolCs.js +60 -0
- package/hay-web/assets/index-FDfdolCs.js.map +1 -0
- package/hay-web/index.html +13 -0
- package/hop +3717 -0
- package/package.json +52 -0
- package/sessions.html +243 -0
- package/tunnel-shell.js +254 -0
package/.hop-tmux.conf
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
# Hop Terminal - Tmux Configuration
|
|
3
|
+
# Do not use user's config - this is hop-managed
|
|
4
|
+
|
|
5
|
+
# Enable mouse support
|
|
6
|
+
set -g mouse on
|
|
7
|
+
|
|
8
|
+
# 2-line scroll speed (compromise between smoothness and remote latency)
|
|
9
|
+
bind -T copy-mode WheelUpPane send -N 2 -X scroll-up
|
|
10
|
+
bind -T copy-mode WheelDownPane send -N 2 -X scroll-down
|
|
11
|
+
bind -T copy-mode-vi WheelUpPane send -N 2 -X scroll-up
|
|
12
|
+
bind -T copy-mode-vi WheelDownPane send -N 2 -X scroll-down
|
|
13
|
+
|
|
14
|
+
# Increase scrollback buffer
|
|
15
|
+
set -g history-limit 50000
|
|
16
|
+
|
|
17
|
+
# Better terminal colors
|
|
18
|
+
set -g default-terminal "screen-256color"
|
package/INTEGRATION.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Hop + Termshare Integration Plan
|
|
2
|
+
|
|
3
|
+
This branch integrates [termshare](https://github.com/jzthree/termshare) to replace ttyd/tmux.
|
|
4
|
+
|
|
5
|
+
## Benefits
|
|
6
|
+
|
|
7
|
+
- **No ttyd/tmux dependencies** - Pure Node.js solution
|
|
8
|
+
- **Built-in presence** - See who's connected, typing indicators
|
|
9
|
+
- **Control modes** - Collaborative or locked single-controller
|
|
10
|
+
- **No injection hacks** - Direct control over web UI
|
|
11
|
+
- **Mobile-ready** - Responsive design with iOS-style keyboard built-in
|
|
12
|
+
- **CLI client** - Connect from real terminals too
|
|
13
|
+
|
|
14
|
+
## Architecture Change
|
|
15
|
+
|
|
16
|
+
### Before (ttyd)
|
|
17
|
+
```
|
|
18
|
+
Browser → Hop Auth Proxy → ttyd (per session) → tmux → shell
|
|
19
|
+
↓
|
|
20
|
+
HTML/WebSocket injection for mobile keyboard
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### After (termshare)
|
|
24
|
+
```
|
|
25
|
+
Browser → Hop Auth Proxy → Termshare WebSocket → node-pty → shell
|
|
26
|
+
↓
|
|
27
|
+
Native termshare web UI (mobile keyboard built-in)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Implementation Steps
|
|
31
|
+
|
|
32
|
+
### 1. Add Dependencies
|
|
33
|
+
- [x] `node-pty-prebuilt-multiarch` - PTY handling
|
|
34
|
+
- [x] `ws` - WebSocket server
|
|
35
|
+
- [x] Copy termshare room/pty logic into hop (`termshare.js`)
|
|
36
|
+
|
|
37
|
+
### 2. Remove ttyd/tmux Code
|
|
38
|
+
- [x] Remove `spawn('ttyd', [...])` in `getOrCreateSession()`
|
|
39
|
+
- [ ] Remove `HOP_TMUX_CONF`, `HOP_TMUX_WRAPPER` generation (still present but unused)
|
|
40
|
+
- [ ] Remove `listTmuxSessions()`, `waitForTmuxSessionReady()` (still present but unused)
|
|
41
|
+
- [ ] Remove ttyd dependency check (still present but unused)
|
|
42
|
+
- [x] Remove keyboard HTML injection code (now using termshare's built-in)
|
|
43
|
+
- [x] Remove `getIOSKeyboardInjection()` WebSocket patching (still present but unused)
|
|
44
|
+
|
|
45
|
+
### 3. Add Termshare Integration
|
|
46
|
+
- [x] Port `Room` and `RoomManager` classes from termshare
|
|
47
|
+
- [x] Port `createPty` function
|
|
48
|
+
- [x] Create termshare WebSocket handler at `/ws` endpoint
|
|
49
|
+
- [x] Map hop sessions to termshare rooms
|
|
50
|
+
|
|
51
|
+
### 4. Update Session Management
|
|
52
|
+
```javascript
|
|
53
|
+
// Before: activeSessions[name] = { ttyd: Process, port: number }
|
|
54
|
+
// After: activeSessions[name] = { room: Room }
|
|
55
|
+
```
|
|
56
|
+
✅ Completed
|
|
57
|
+
|
|
58
|
+
### 5. Serve Termshare Web UI
|
|
59
|
+
- [x] Build termshare web client (with mobile keyboard)
|
|
60
|
+
- [x] Serve static files from hop (`termshare-web/` directory)
|
|
61
|
+
- [x] Inject room parameter for session routing
|
|
62
|
+
|
|
63
|
+
### 6. Keep Hop Features
|
|
64
|
+
- [x] Authentication (TOTP + cookies)
|
|
65
|
+
- [x] Cloudflare tunneling
|
|
66
|
+
- [x] Session URL routing (`/s/<name>/`)
|
|
67
|
+
- [x] Multi-user support
|
|
68
|
+
|
|
69
|
+
## Key Files Changed
|
|
70
|
+
|
|
71
|
+
- `hop` - Main server, updated `getOrCreateSession()` and WebSocket handler
|
|
72
|
+
- `termshare.js` - New module with Room, RoomManager, createPty
|
|
73
|
+
- `termshare-web/` - Built termshare web client with mobile keyboard
|
|
74
|
+
|
|
75
|
+
## Testing
|
|
76
|
+
|
|
77
|
+
1. Start hop: `node hop`
|
|
78
|
+
2. Open browser to tunnel URL
|
|
79
|
+
3. Verify:
|
|
80
|
+
- [ ] Login with TOTP works
|
|
81
|
+
- [ ] Terminal session works
|
|
82
|
+
- [ ] Multiple clients see same session
|
|
83
|
+
- [ ] Presence indicators show
|
|
84
|
+
- [ ] Control modes work
|
|
85
|
+
- [ ] Mobile UI works without injection
|
|
86
|
+
|
|
87
|
+
## Migration Notes
|
|
88
|
+
|
|
89
|
+
- Sessions are not persistent (by design) - shell exits when all clients disconnect
|
|
90
|
+
- tmux scrollback replaced by termshare's output buffer (200KB)
|
|
91
|
+
- iOS keyboard injection replaced by termshare's built-in mobile keyboard
|
|
92
|
+
- The old ttyd/tmux code paths are still present but no longer used; can be removed in a cleanup pass
|
package/README.md
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# 🐰 hop
|
|
2
|
+
|
|
3
|
+
**Hop into your terminal from anywhere in the world.**
|
|
4
|
+
|
|
5
|
+
Access your Mac's terminal from your phone, tablet, or any browser — secured with password + 2FA, tunneled through Cloudflare.
|
|
6
|
+
|
|
7
|
+
> **🍎 macOS/Linux** — Requires cloudflared for tunneling
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
(\(\
|
|
11
|
+
( -.-) "hop into your shell"
|
|
12
|
+
o_(")(")
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## ✨ Features
|
|
16
|
+
|
|
17
|
+
- 🔐 **Password + 2FA** — Optional password plus TOTP (required for custom domains)
|
|
18
|
+
- 🌍 **Access Anywhere** — Cloudflare tunnel, no port forwarding
|
|
19
|
+
- 🌐 **Custom Domains + Multi‑User** — Share subdomains with per‑user credentials
|
|
20
|
+
- 📱 **Mobile Virtual Keyboard** — Custom keyboard with Esc, Ctrl, Alt, arrows, and more
|
|
21
|
+
- ⌨️ **Native Keyboard Support** — Tap the blue button for dictation, spellcheck & autocomplete
|
|
22
|
+
- 🪟 **Multi-Session** — Create and switch between named sessions
|
|
23
|
+
- 🔌 **Port Sessions** — Proxy a local HTTP/WS service via hop
|
|
24
|
+
- 🔄 **Quick Session Switching** — Floating menu to switch sessions without leaving the terminal
|
|
25
|
+
- 🎨 **Modern UI** — Clean, minimal iOS-style design
|
|
26
|
+
- ⚡ **Auto-Attach** — Multiple terminals share the same tunnel
|
|
27
|
+
|
|
28
|
+
## 🚀 Quick Install
|
|
29
|
+
|
|
30
|
+
### From npm (easiest)
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install -g hop2
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Then just run:
|
|
37
|
+
```bash
|
|
38
|
+
hop
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### One-liner from source
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
git clone https://github.com/jzthree/hop.git ~/.hop && \
|
|
45
|
+
cd ~/.hop && npm install && \
|
|
46
|
+
sudo ln -sf ~/.hop/hop /usr/local/bin/hop
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Manual Install from source
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Clone the repo
|
|
53
|
+
git clone https://github.com/jzthree/hop.git ~/.hop
|
|
54
|
+
|
|
55
|
+
# Install dependencies
|
|
56
|
+
cd ~/.hop && npm install
|
|
57
|
+
|
|
58
|
+
# Add to PATH (pick one)
|
|
59
|
+
# Option A: Symlink (requires sudo)
|
|
60
|
+
sudo ln -sf ~/.hop/hop /usr/local/bin/hop
|
|
61
|
+
|
|
62
|
+
# Option B: Add to PATH
|
|
63
|
+
echo 'export PATH="$HOME/.hop:$PATH"' >> ~/.zshrc
|
|
64
|
+
source ~/.zshrc
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 🐰 Usage
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Start hopping!
|
|
71
|
+
hop
|
|
72
|
+
|
|
73
|
+
# Use iTerm control mode for local session
|
|
74
|
+
hop --iterm
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**First time:**
|
|
78
|
+
1. (Optional) Set a password: `hop password set`
|
|
79
|
+
2. Scan the QR code with your authenticator app (Google Authenticator, Authy, 1Password, etc.)
|
|
80
|
+
3. Note the URL displayed
|
|
81
|
+
4. Press Enter to start your local session
|
|
82
|
+
|
|
83
|
+
**From your phone:**
|
|
84
|
+
1. Open the URL in your browser
|
|
85
|
+
2. Enter your password (if enabled) and 6‑digit code
|
|
86
|
+
3. Pick or create a session
|
|
87
|
+
4. 🐰 You're in! Use the virtual keyboard for terminal keys, or tap the blue button for native input
|
|
88
|
+
|
|
89
|
+
## 🪟 Sessions
|
|
90
|
+
|
|
91
|
+
Create multiple independent terminal sessions from the Session Picker (`/sessions`):
|
|
92
|
+
|
|
93
|
+
- **Create**: Type a name and click Create
|
|
94
|
+
- **Join**: Click Join on any existing session
|
|
95
|
+
- **Sessions are shared**: Multiple devices can view the same session
|
|
96
|
+
|
|
97
|
+
You can also create **Port Sessions** that proxy to a local HTTP/WS service on your machine.
|
|
98
|
+
Use the Session Picker or:
|
|
99
|
+
```bash
|
|
100
|
+
hop session add myapp --port 3000
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## 🌐 Custom Domains & Multi‑User
|
|
104
|
+
|
|
105
|
+
### Admin (your machine)
|
|
106
|
+
1. Set a password (required for custom domains):
|
|
107
|
+
```bash
|
|
108
|
+
hop password set
|
|
109
|
+
```
|
|
110
|
+
2. Configure your domain:
|
|
111
|
+
```bash
|
|
112
|
+
hop domain hop.yourdomain.com
|
|
113
|
+
```
|
|
114
|
+
3. Add a user + export credentials:
|
|
115
|
+
```bash
|
|
116
|
+
hop user add alice
|
|
117
|
+
hop user export alice
|
|
118
|
+
```
|
|
119
|
+
4. Send the exported folder to the user.
|
|
120
|
+
|
|
121
|
+
### User (their machine)
|
|
122
|
+
```bash
|
|
123
|
+
npm install -g hop2
|
|
124
|
+
hop client ./credentials.json
|
|
125
|
+
```
|
|
126
|
+
First run prompts them to set a password + scan a TOTP QR code.
|
|
127
|
+
They then log in at their URL, e.g. `https://alice.hop.yourdomain.com`.
|
|
128
|
+
|
|
129
|
+
## 📱 Mobile Keyboard
|
|
130
|
+
|
|
131
|
+
On mobile devices, Hop provides a custom virtual keyboard designed for terminal use:
|
|
132
|
+
|
|
133
|
+
**Accessory Row:**
|
|
134
|
+
- `Esc` `Tab` `Ctrl` `Alt` — Essential terminal keys
|
|
135
|
+
- `← ↓ ↑ →` — Arrow keys for navigation
|
|
136
|
+
- 🔵 **Blue keyboard button** — Opens native iOS keyboard for dictation, spellcheck & autocomplete
|
|
137
|
+
|
|
138
|
+
**Floating Menu (top-right button):**
|
|
139
|
+
- **Toggle Keyboard** — Show/hide the virtual keyboard
|
|
140
|
+
- **Session List** — Quick-switch between sessions
|
|
141
|
+
- **All Sessions** — Return to session picker
|
|
142
|
+
|
|
143
|
+
**Tips:**
|
|
144
|
+
- The floating button is draggable — move it anywhere
|
|
145
|
+
- First-time users will see a tooltip pointing to the native keyboard button
|
|
146
|
+
- Use the native keyboard for longer text input with autocomplete
|
|
147
|
+
|
|
148
|
+
## 🖥️ iTerm Integration
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
hop --iterm
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Uses tmux control mode (`-CC`) for native scrolling, copy/paste, splits, and search. Session remains accessible via web.
|
|
155
|
+
|
|
156
|
+
## 🔌 Port Sessions
|
|
157
|
+
|
|
158
|
+
Expose local HTTP/WebSocket services through your tunnel:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
hop session add myapp --port 3000
|
|
162
|
+
# Access at: https://your-tunnel-url/s/myapp/
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Works with dev servers, Jupyter, APIs — anything on localhost. Supports WebSocket.
|
|
166
|
+
|
|
167
|
+
## 🔧 Commands
|
|
168
|
+
|
|
169
|
+
| Command | Description |
|
|
170
|
+
|---------|-------------|
|
|
171
|
+
| `hop` | Start hop (or attach to existing tunnel) |
|
|
172
|
+
| `hop --iterm` | Use iTerm tmux control mode for local session |
|
|
173
|
+
| `hop url` | Print current tunnel URL |
|
|
174
|
+
| `hop qr` | Show QR code for current URL |
|
|
175
|
+
| `hop domain <hostname>` | Set custom domain (named tunnel) |
|
|
176
|
+
| `hop domain-clear` | Remove custom domain, use random URLs |
|
|
177
|
+
| `hop password set` | Set/change password |
|
|
178
|
+
| `hop password clear` | Remove password protection |
|
|
179
|
+
| `hop user list` | List users |
|
|
180
|
+
| `hop user add <name>` | Add user + subdomain |
|
|
181
|
+
| `hop user remove <name>` | Remove user |
|
|
182
|
+
| `hop user export <name>` | Export user credentials |
|
|
183
|
+
| `hop session list` | List sessions |
|
|
184
|
+
| `hop session add <name>` | Create a terminal session |
|
|
185
|
+
| `hop session add <name> --port N` | Create a port session (proxy) |
|
|
186
|
+
| `hop session remove <name>` | Remove a session |
|
|
187
|
+
| `hop client <credentials>` | Run hop with exported credentials |
|
|
188
|
+
| `hop wipe` | Kill all hop tmux sessions |
|
|
189
|
+
| `quit` | Type at exit prompt to shutdown tunnel |
|
|
190
|
+
|
|
191
|
+
## 📦 Dependencies
|
|
192
|
+
|
|
193
|
+
Installed automatically via Homebrew:
|
|
194
|
+
- `tmux` — Terminal multiplexer
|
|
195
|
+
- `ttyd` — Web terminal
|
|
196
|
+
- `cloudflared` — Cloudflare tunnel
|
|
197
|
+
|
|
198
|
+
Node.js packages:
|
|
199
|
+
- `http-proxy` — Request proxying
|
|
200
|
+
- `otplib` — TOTP authentication
|
|
201
|
+
- `qrcode-terminal` — QR code display
|
|
202
|
+
- `cookie` — Session cookies
|
|
203
|
+
|
|
204
|
+
## 🛡️ Security
|
|
205
|
+
|
|
206
|
+
- **Password + TOTP** — Password optional, but required for custom domains
|
|
207
|
+
- **Rate Limiting** — Exponential backoff on failed attempts
|
|
208
|
+
- **Secure Cookies** — `httpOnly`, `secure`, `sameSite=lax`
|
|
209
|
+
- **Random URL** — Unguessable tunnel URL for quick tunnels
|
|
210
|
+
- **Fixed URL** — Custom domains keep a stable URL
|
|
211
|
+
- **Local Binding** — Server only listens on 127.0.0.1
|
|
212
|
+
- **End-to-End TLS** — Cloudflare Tunnel encryption
|
|
213
|
+
|
|
214
|
+
**Passwords:** Recommended for any public URL; required for custom domains.
|
|
215
|
+
|
|
216
|
+
**Secrets:** Stored in `~/.hop2/` (treat like `~/.ssh/`)
|
|
217
|
+
|
|
218
|
+
## 🛠 Development (Hay)
|
|
219
|
+
|
|
220
|
+
The hay source is vendored in `./hay`. Hop will serve `hay/apps/web/dist` when present.
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
npm run build
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
This builds hay (web + cli) and syncs `hay/apps/web/dist` into `hay-web/` for Hop to serve.
|
|
227
|
+
If `./hay` exists and the dist folder is missing, `hop` will auto-build hay on startup.
|
|
228
|
+
|
|
229
|
+
## 🐛 Troubleshooting
|
|
230
|
+
|
|
231
|
+
**QR code not working?**
|
|
232
|
+
Delete `.auth_secret` and restart hop to generate a new code.
|
|
233
|
+
|
|
234
|
+
**Client reset (user mode)?**
|
|
235
|
+
Delete `~/.hop2/clients/<tunnel-id>/` and run `hop client` again.
|
|
236
|
+
|
|
237
|
+
**Tunnel not starting?**
|
|
238
|
+
Make sure `cloudflared` is installed: `brew install cloudflared`
|
|
239
|
+
|
|
240
|
+
**Stuck processes?**
|
|
241
|
+
```bash
|
|
242
|
+
pkill ttyd; pkill cloudflared; tmux kill-server
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## 📝 License
|
|
246
|
+
|
|
247
|
+
MIT
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
Made with 🐰 for hopping around
|
|
252
|
+
|
|
253
|
+
```
|
|
254
|
+
____
|
|
255
|
+
/ \
|
|
256
|
+
| ^ ^ | hop hop hop
|
|
257
|
+
| .. |
|
|
258
|
+
\ -- /
|
|
259
|
+
||||
|
|
260
|
+
```
|
package/hay/CHANGELOG.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.8.0] - 2025-01-25
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- **Replaced ttyd/tmux with hay/node-pty**: Terminal sessions are now managed directly via node-pty instead of ttyd+tmux. This removes external dependencies and provides native multi-client support, presence indicators, and better web/CLI integration.
|
|
8
|
+
|
|
9
|
+
### Breaking Changes
|
|
10
|
+
|
|
11
|
+
- **RoomManager.getRoom() signature changed**: Now accepts optional third `cwd` parameter
|
|
12
|
+
```typescript
|
|
13
|
+
// Before
|
|
14
|
+
getRoom(roomId: string, initialSize: { cols: number; rows: number })
|
|
15
|
+
|
|
16
|
+
// After
|
|
17
|
+
getRoom(roomId: string, initialSize: { cols: number; rows: number }, cwd?: string)
|
|
18
|
+
```
|
|
19
|
+
The per-room `cwd` takes precedence over the RoomManager constructor's default cwd.
|
|
20
|
+
|
|
21
|
+
### New Features
|
|
22
|
+
|
|
23
|
+
#### CLI Client
|
|
24
|
+
- **Keyboard shortcuts**: Pan (arrows), center on cursor (0), auto-fit (A), mouse toggle (M), hints (Ctrl+T), detach (Ctrl+G), kill (Ctrl+Q)
|
|
25
|
+
- **Configuration file support**: Reads from `.hop.json` (under `hay-cli` key) or legacy `.hay-cli.json`
|
|
26
|
+
- **Config hierarchy**: Local config takes precedence over global (`~/.hop.json`)
|
|
27
|
+
- **scrollOff setting**: Vim-like scroll margin (default: 3 lines) keeps context visible around cursor
|
|
28
|
+
- **showHints setting**: Toggle keyboard shortcut hints bar
|
|
29
|
+
|
|
30
|
+
#### Web Client
|
|
31
|
+
- **Haptic feedback**: Tactile feedback on mobile keyboard (iOS via switch element trick, Android via Vibration API)
|
|
32
|
+
- **Improved mobile layout**: Responsive drawer and keyboard
|
|
33
|
+
|
|
34
|
+
### Bug Fixes
|
|
35
|
+
|
|
36
|
+
- Fixed sessions always starting in daemon's directory instead of caller's pwd
|
|
37
|
+
- Fixed cursor scroll behavior to match regular terminals (only scroll when cursor exits viewport)
|
|
38
|
+
- Fixed initial viewport positioning on session start
|
|
39
|
+
|
|
40
|
+
## [0.1.0] - Initial Release
|
|
41
|
+
|
|
42
|
+
- Multi-client terminal sharing
|
|
43
|
+
- Web and CLI clients
|
|
44
|
+
- Presence indicators and typing status
|
|
45
|
+
- Collaborative and locked control modes
|
|
46
|
+
- Embeddable server library
|
package/hay/DEV_NOTES.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Dev Notes
|
|
2
|
+
|
|
3
|
+
## Mobile touch scrolling + selection mode (iOS Safari)
|
|
4
|
+
|
|
5
|
+
We intentionally disable native touch handling on the xterm DOM so we can
|
|
6
|
+
implement our own smooth touch scrolling, but we also need a "selection mode"
|
|
7
|
+
that restores iOS text selection handles. The fix is split across CSS and JS.
|
|
8
|
+
|
|
9
|
+
### Default mode (scrolling)
|
|
10
|
+
* **CSS** (`hay/apps/web/src/styles.css`):
|
|
11
|
+
* `.terminal-scroll` and `.xterm*` get `touch-action: none` to prevent
|
|
12
|
+
Safari's native scrolling/selection on the terminal surface.
|
|
13
|
+
* `.xterm-rows` and span children use `pointer-events: none` so touches hit
|
|
14
|
+
our container instead of individual text nodes.
|
|
15
|
+
* **JS** (`hay/apps/web/src/App.tsx`, mobile touch effect):
|
|
16
|
+
* We attach custom `touchstart/move/end` handlers to implement momentum
|
|
17
|
+
scrolling on the terminal content.
|
|
18
|
+
|
|
19
|
+
### Selection mode (text selection)
|
|
20
|
+
* **CSS** (`hay/apps/web/src/styles.css`):
|
|
21
|
+
* `.session.selection-mode` re-enables `pointer-events` and `user-select`
|
|
22
|
+
on `.xterm-rows` so iOS can show selection handles.
|
|
23
|
+
* `touch-action: auto` is restored on xterm elements.
|
|
24
|
+
* **JS** (`hay/apps/web/src/App.tsx`):
|
|
25
|
+
* We skip the custom touch scrolling effect when `selectionMode` is true.
|
|
26
|
+
* We disable xterm's internal `viewport.handleTouchStart/Move` to stop it
|
|
27
|
+
from swallowing selection gestures.
|
|
28
|
+
* The click handler clears selection and toggles `user-select` to re-arm
|
|
29
|
+
iOS selection after a tap.
|
|
30
|
+
|
|
31
|
+
### If selection or scrolling regresses
|
|
32
|
+
1. Confirm `.session` has the `selection-mode` class when the toggle is on.
|
|
33
|
+
2. Verify the CSS block for `.session.selection-mode` is present (pointer-events
|
|
34
|
+
and user-select must be re-enabled).
|
|
35
|
+
3. In `App.tsx`, ensure the selection-mode guards still:
|
|
36
|
+
* prevent installing custom touch scrolling, and
|
|
37
|
+
* override `viewport.handleTouchStart/Move`.
|
|
38
|
+
4. If text selection works but scrolling is broken, verify `touch-action: none`
|
|
39
|
+
and `pointer-events: none` are still applied in default mode.
|