@moejay/wrightty 0.0.0 → 0.1.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/dist/cli.d.ts +3 -0
- package/dist/cli.js +144 -0
- package/dist/client.d.ts +14 -0
- package/dist/client.js +83 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +8 -0
- package/dist/terminal.d.ts +48 -0
- package/dist/terminal.js +210 -0
- package/dist/types.d.ts +90 -0
- package/dist/types.js +3 -0
- package/package.json +38 -15
- package/.github/workflows/ci.yml +0 -90
- package/.github/workflows/release.yml +0 -177
- package/Cargo.lock +0 -2662
- package/Cargo.toml +0 -38
- package/PROTOCOL.md +0 -1351
- package/README.md +0 -386
- package/agents/ceo/AGENTS.md +0 -24
- package/agents/ceo/HEARTBEAT.md +0 -72
- package/agents/ceo/SOUL.md +0 -33
- package/agents/ceo/TOOLS.md +0 -3
- package/agents/founding-engineer/AGENTS.md +0 -44
- package/crates/wrightty/Cargo.toml +0 -43
- package/crates/wrightty/src/client_cmds.rs +0 -366
- package/crates/wrightty/src/discover.rs +0 -78
- package/crates/wrightty/src/main.rs +0 -100
- package/crates/wrightty/src/server.rs +0 -100
- package/crates/wrightty/src/term.rs +0 -338
- package/crates/wrightty-bridge-ghostty/Cargo.toml +0 -27
- package/crates/wrightty-bridge-ghostty/src/ghostty.rs +0 -422
- package/crates/wrightty-bridge-ghostty/src/lib.rs +0 -2
- package/crates/wrightty-bridge-ghostty/src/main.rs +0 -146
- package/crates/wrightty-bridge-ghostty/src/rpc.rs +0 -307
- package/crates/wrightty-bridge-kitty/Cargo.toml +0 -26
- package/crates/wrightty-bridge-kitty/src/kitty.rs +0 -269
- package/crates/wrightty-bridge-kitty/src/lib.rs +0 -2
- package/crates/wrightty-bridge-kitty/src/main.rs +0 -124
- package/crates/wrightty-bridge-kitty/src/rpc.rs +0 -304
- package/crates/wrightty-bridge-tmux/Cargo.toml +0 -26
- package/crates/wrightty-bridge-tmux/src/lib.rs +0 -2
- package/crates/wrightty-bridge-tmux/src/main.rs +0 -119
- package/crates/wrightty-bridge-tmux/src/rpc.rs +0 -291
- package/crates/wrightty-bridge-tmux/src/tmux.rs +0 -215
- package/crates/wrightty-bridge-wezterm/Cargo.toml +0 -26
- package/crates/wrightty-bridge-wezterm/src/lib.rs +0 -2
- package/crates/wrightty-bridge-wezterm/src/main.rs +0 -119
- package/crates/wrightty-bridge-wezterm/src/rpc.rs +0 -339
- package/crates/wrightty-bridge-wezterm/src/wezterm.rs +0 -190
- package/crates/wrightty-bridge-zellij/Cargo.toml +0 -27
- package/crates/wrightty-bridge-zellij/src/lib.rs +0 -2
- package/crates/wrightty-bridge-zellij/src/main.rs +0 -125
- package/crates/wrightty-bridge-zellij/src/rpc.rs +0 -328
- package/crates/wrightty-bridge-zellij/src/zellij.rs +0 -199
- package/crates/wrightty-client/Cargo.toml +0 -16
- package/crates/wrightty-client/src/client.rs +0 -254
- package/crates/wrightty-client/src/lib.rs +0 -2
- package/crates/wrightty-core/Cargo.toml +0 -21
- package/crates/wrightty-core/src/input.rs +0 -212
- package/crates/wrightty-core/src/lib.rs +0 -4
- package/crates/wrightty-core/src/screen.rs +0 -325
- package/crates/wrightty-core/src/session.rs +0 -249
- package/crates/wrightty-core/src/session_manager.rs +0 -77
- package/crates/wrightty-protocol/Cargo.toml +0 -13
- package/crates/wrightty-protocol/src/error.rs +0 -8
- package/crates/wrightty-protocol/src/events.rs +0 -138
- package/crates/wrightty-protocol/src/lib.rs +0 -4
- package/crates/wrightty-protocol/src/methods.rs +0 -321
- package/crates/wrightty-protocol/src/types.rs +0 -201
- package/crates/wrightty-server/Cargo.toml +0 -23
- package/crates/wrightty-server/src/lib.rs +0 -2
- package/crates/wrightty-server/src/main.rs +0 -65
- package/crates/wrightty-server/src/rpc.rs +0 -455
- package/crates/wrightty-server/src/state.rs +0 -39
- package/examples/basic_command.py +0 -53
- package/examples/interactive_tui.py +0 -86
- package/examples/record_session.py +0 -96
- package/install.sh +0 -81
- package/sdks/node/package-lock.json +0 -85
- package/sdks/node/package.json +0 -44
- package/sdks/node/src/client.ts +0 -94
- package/sdks/node/src/index.ts +0 -19
- package/sdks/node/src/terminal.ts +0 -258
- package/sdks/node/src/types.ts +0 -105
- package/sdks/node/tsconfig.json +0 -17
- package/sdks/python/README.md +0 -96
- package/sdks/python/pyproject.toml +0 -42
- package/sdks/python/wrightty/__init__.py +0 -6
- package/sdks/python/wrightty/cli.py +0 -210
- package/sdks/python/wrightty/client.py +0 -136
- package/sdks/python/wrightty/mcp_server.py +0 -434
- package/sdks/python/wrightty/terminal.py +0 -333
- package/skills/wrightty/SKILL.md +0 -261
- package/src/lib.rs +0 -1
- package/tests/integration_test.rs +0 -618
package/PROTOCOL.md
DELETED
|
@@ -1,1351 +0,0 @@
|
|
|
1
|
-
# Wrightty Protocol Specification
|
|
2
|
-
|
|
3
|
-
**Version:** 0.1.0-draft
|
|
4
|
-
**Transport:** WebSocket + JSON-RPC 2.0
|
|
5
|
-
**Default endpoint:** `ws://127.0.0.1:9420`
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## 1. Transport
|
|
10
|
-
|
|
11
|
-
All communication happens over a single WebSocket connection using [JSON-RPC 2.0](https://www.jsonrpc.org/specification).
|
|
12
|
-
|
|
13
|
-
- **Requests** flow client → server
|
|
14
|
-
- **Responses** flow server → client (matched by `id`)
|
|
15
|
-
- **Notifications/Events** flow server → client (no `id`, triggered by subscriptions)
|
|
16
|
-
- **Batching** is supported per JSON-RPC 2.0 spec
|
|
17
|
-
|
|
18
|
-
### 1.1 Connection Lifecycle
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
Client Server
|
|
22
|
-
│ │
|
|
23
|
-
├── WebSocket connect ─────────►│
|
|
24
|
-
│ │
|
|
25
|
-
├── Wrightty.getInfo ──────────►│ (optional handshake)
|
|
26
|
-
│◄── { version, capabilities } ─┤
|
|
27
|
-
│ │
|
|
28
|
-
├── Session.create ────────────►│
|
|
29
|
-
│◄── { sessionId } ─────────────┤
|
|
30
|
-
│ │
|
|
31
|
-
├── Events.subscribe ──────────►│ (start receiving events)
|
|
32
|
-
│◄── subscription confirmed ────┤
|
|
33
|
-
│ │
|
|
34
|
-
│ ... interact ... │
|
|
35
|
-
│ │
|
|
36
|
-
├── Session.destroy ───────────►│
|
|
37
|
-
│◄── ok ─────────────────────────┤
|
|
38
|
-
│ │
|
|
39
|
-
└── WebSocket close ───────────►│
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### 1.2 Discovery
|
|
43
|
-
|
|
44
|
-
When an emulator or daemon starts with wrightty support enabled, it sets:
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
WRIGHTTY_SOCKET=ws://127.0.0.1:9420
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
Clients check this env var to auto-connect. If multiple sessions exist (e.g., emulator with tabs), the client uses `Session.list` to enumerate them.
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## 2. Domains
|
|
55
|
-
|
|
56
|
-
Methods are namespaced as `Domain.methodName`.
|
|
57
|
-
|
|
58
|
-
### 2.1 Wrightty (meta)
|
|
59
|
-
|
|
60
|
-
| Method | Description |
|
|
61
|
-
|--------|-------------|
|
|
62
|
-
| `Wrightty.getInfo` | Server metadata and capability negotiation |
|
|
63
|
-
|
|
64
|
-
#### `Wrightty.getInfo`
|
|
65
|
-
|
|
66
|
-
**Params:** none
|
|
67
|
-
|
|
68
|
-
**Result:**
|
|
69
|
-
```json
|
|
70
|
-
{
|
|
71
|
-
"version": "0.1.0",
|
|
72
|
-
"implementation": "wrightty-server",
|
|
73
|
-
"capabilities": {
|
|
74
|
-
"screenshot": ["text", "ansi", "json", "svg", "png"],
|
|
75
|
-
"maxSessions": 64,
|
|
76
|
-
"supportsResize": true,
|
|
77
|
-
"supportsScrollback": true,
|
|
78
|
-
"supportsMouse": false,
|
|
79
|
-
"supportsSessionCreate": true,
|
|
80
|
-
"supportsColorPalette": true,
|
|
81
|
-
"supportsRawOutput": true,
|
|
82
|
-
"supportsShellIntegration": true,
|
|
83
|
-
"events": [
|
|
84
|
-
"Screen.updated", "Session.output", "Session.exited",
|
|
85
|
-
"Terminal.bell", "Terminal.titleChanged", "Terminal.cwdChanged",
|
|
86
|
-
"Terminal.alternateScreen", "Terminal.cursorChanged",
|
|
87
|
-
"Shell.promptStart", "Shell.commandStart", "Shell.outputStart",
|
|
88
|
-
"Shell.commandFinished", "Terminal.notification",
|
|
89
|
-
"Terminal.clipboardSet", "Terminal.modeChanged",
|
|
90
|
-
"Terminal.progressChanged"
|
|
91
|
-
]
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
The `capabilities.events` array advertises which event types this implementation can emit. Clients should check this before subscribing.
|
|
97
|
-
|
|
98
|
-
---
|
|
99
|
-
|
|
100
|
-
### 2.2 Session
|
|
101
|
-
|
|
102
|
-
Manages terminal session lifecycle. In daemon mode, each session is a PTY + shell process. In native emulator mode, sessions map to tabs/panes.
|
|
103
|
-
|
|
104
|
-
| Method | Description |
|
|
105
|
-
|--------|-------------|
|
|
106
|
-
| `Session.create` | Spawn a new terminal session |
|
|
107
|
-
| `Session.destroy` | Kill a session |
|
|
108
|
-
| `Session.list` | List active sessions |
|
|
109
|
-
| `Session.getInfo` | Get info about a specific session |
|
|
110
|
-
|
|
111
|
-
#### `Session.create`
|
|
112
|
-
|
|
113
|
-
**Params:**
|
|
114
|
-
```json
|
|
115
|
-
{
|
|
116
|
-
"shell": "/bin/bash", // optional, default: user's $SHELL or /bin/sh
|
|
117
|
-
"args": ["--norc"], // optional, shell arguments
|
|
118
|
-
"cols": 80, // optional, default: 80
|
|
119
|
-
"rows": 24, // optional, default: 24
|
|
120
|
-
"env": { // optional, additional env vars (merged with inherited env)
|
|
121
|
-
"TERM": "xterm-256color",
|
|
122
|
-
"LANG": "en_US.UTF-8"
|
|
123
|
-
},
|
|
124
|
-
"cwd": "/home/user/project" // optional, working directory
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
**Result:**
|
|
129
|
-
```json
|
|
130
|
-
{
|
|
131
|
-
"sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
|
|
132
|
-
}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
**Notes:**
|
|
136
|
-
- `TERM` defaults to `xterm-256color` if not specified
|
|
137
|
-
- In native emulator mode, `shell`/`args`/`env`/`cwd` may be ignored (session already exists)
|
|
138
|
-
- The session is ready for input immediately after this returns
|
|
139
|
-
|
|
140
|
-
#### `Session.destroy`
|
|
141
|
-
|
|
142
|
-
**Params:**
|
|
143
|
-
```json
|
|
144
|
-
{
|
|
145
|
-
"sessionId": "a1b2c3d4...",
|
|
146
|
-
"signal": "SIGTERM" // optional, default: SIGTERM then SIGKILL after 5s
|
|
147
|
-
}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
**Result:**
|
|
151
|
-
```json
|
|
152
|
-
{
|
|
153
|
-
"exitCode": 0 // null if process was killed
|
|
154
|
-
}
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
#### `Session.list`
|
|
158
|
-
|
|
159
|
-
**Params:** none
|
|
160
|
-
|
|
161
|
-
**Result:**
|
|
162
|
-
```json
|
|
163
|
-
{
|
|
164
|
-
"sessions": [
|
|
165
|
-
{
|
|
166
|
-
"sessionId": "a1b2c3d4...",
|
|
167
|
-
"title": "bash",
|
|
168
|
-
"cwd": "/home/user/project",
|
|
169
|
-
"cols": 80,
|
|
170
|
-
"rows": 24,
|
|
171
|
-
"pid": 12345,
|
|
172
|
-
"running": true,
|
|
173
|
-
"alternateScreen": false
|
|
174
|
-
}
|
|
175
|
-
]
|
|
176
|
-
}
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
#### `Session.getInfo`
|
|
180
|
-
|
|
181
|
-
**Params:**
|
|
182
|
-
```json
|
|
183
|
-
{
|
|
184
|
-
"sessionId": "a1b2c3d4..."
|
|
185
|
-
}
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
**Result:** Same shape as one entry in `Session.list.sessions`.
|
|
189
|
-
|
|
190
|
-
---
|
|
191
|
-
|
|
192
|
-
### 2.3 Input
|
|
193
|
-
|
|
194
|
-
Send keystrokes and text to a session.
|
|
195
|
-
|
|
196
|
-
| Method | Description |
|
|
197
|
-
|--------|-------------|
|
|
198
|
-
| `Input.sendKeys` | Send structured key events |
|
|
199
|
-
| `Input.sendText` | Send raw text (no key interpretation) |
|
|
200
|
-
| `Input.sendMouse` | Send mouse events (if supported) |
|
|
201
|
-
|
|
202
|
-
#### `Input.sendKeys`
|
|
203
|
-
|
|
204
|
-
**Params:**
|
|
205
|
-
```json
|
|
206
|
-
{
|
|
207
|
-
"sessionId": "a1b2c3d4...",
|
|
208
|
-
"keys": [
|
|
209
|
-
{ "key": "Char", "char": "l", "modifiers": [] },
|
|
210
|
-
{ "key": "Char", "char": "s", "modifiers": [] },
|
|
211
|
-
{ "key": "Enter" }
|
|
212
|
-
]
|
|
213
|
-
}
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
**Result:** `{}`
|
|
217
|
-
|
|
218
|
-
**Key types:**
|
|
219
|
-
|
|
220
|
-
| key | Additional fields | Example |
|
|
221
|
-
|-----|-------------------|---------|
|
|
222
|
-
| `"Char"` | `char`: single character | `{ "key": "Char", "char": "a" }` |
|
|
223
|
-
| `"Enter"` | — | `{ "key": "Enter" }` |
|
|
224
|
-
| `"Tab"` | — | `{ "key": "Tab" }` |
|
|
225
|
-
| `"Backspace"` | — | |
|
|
226
|
-
| `"Delete"` | — | |
|
|
227
|
-
| `"Escape"` | — | |
|
|
228
|
-
| `"ArrowUp"` | — | |
|
|
229
|
-
| `"ArrowDown"` | — | |
|
|
230
|
-
| `"ArrowLeft"` | — | |
|
|
231
|
-
| `"ArrowRight"` | — | |
|
|
232
|
-
| `"Home"` | — | |
|
|
233
|
-
| `"End"` | — | |
|
|
234
|
-
| `"PageUp"` | — | |
|
|
235
|
-
| `"PageDown"` | — | |
|
|
236
|
-
| `"Insert"` | — | |
|
|
237
|
-
| `"F"` | `n`: 1-24 | `{ "key": "F", "n": 5 }` |
|
|
238
|
-
|
|
239
|
-
**Modifiers** (optional array on any key):
|
|
240
|
-
```json
|
|
241
|
-
{ "key": "Char", "char": "c", "modifiers": ["Ctrl"] }
|
|
242
|
-
{ "key": "ArrowUp", "modifiers": ["Shift", "Alt"] }
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
Valid modifiers: `"Ctrl"`, `"Alt"`, `"Shift"`, `"Meta"`
|
|
246
|
-
|
|
247
|
-
**Shorthand:** For simple cases, a string shorthand is accepted in the `keys` array:
|
|
248
|
-
|
|
249
|
-
```json
|
|
250
|
-
{
|
|
251
|
-
"keys": ["h", "e", "l", "l", "o", "Enter", "Ctrl+c"]
|
|
252
|
-
}
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
Where:
|
|
256
|
-
- Single character → `Char` key
|
|
257
|
-
- Named key → looked up from the key type table
|
|
258
|
-
- `Mod+key` → modifier combination
|
|
259
|
-
|
|
260
|
-
#### `Input.sendText`
|
|
261
|
-
|
|
262
|
-
Sends raw text bytes to the PTY. No key interpretation — newlines are `\n`, not Enter key sequences. Useful for pasting.
|
|
263
|
-
|
|
264
|
-
**Params:**
|
|
265
|
-
```json
|
|
266
|
-
{
|
|
267
|
-
"sessionId": "a1b2c3d4...",
|
|
268
|
-
"text": "echo hello world\n"
|
|
269
|
-
}
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
**Result:** `{}`
|
|
273
|
-
|
|
274
|
-
#### `Input.sendMouse`
|
|
275
|
-
|
|
276
|
-
**Params:**
|
|
277
|
-
```json
|
|
278
|
-
{
|
|
279
|
-
"sessionId": "a1b2c3d4...",
|
|
280
|
-
"event": "press", // "press", "release", "move", "scroll"
|
|
281
|
-
"button": "left", // "left", "right", "middle", "none" (for move)
|
|
282
|
-
"row": 5,
|
|
283
|
-
"col": 12,
|
|
284
|
-
"modifiers": [] // optional
|
|
285
|
-
}
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
For scroll: `"button"` is `"scrollUp"` or `"scrollDown"`.
|
|
289
|
-
|
|
290
|
-
**Result:** `{}`
|
|
291
|
-
|
|
292
|
-
---
|
|
293
|
-
|
|
294
|
-
### 2.4 Screen
|
|
295
|
-
|
|
296
|
-
Read terminal screen state.
|
|
297
|
-
|
|
298
|
-
| Method | Description |
|
|
299
|
-
|--------|-------------|
|
|
300
|
-
| `Screen.getContents` | Full cell grid with attributes |
|
|
301
|
-
| `Screen.getText` | Plain text extraction |
|
|
302
|
-
| `Screen.getScrollback` | Read scrollback buffer |
|
|
303
|
-
| `Screen.screenshot` | Render to various formats |
|
|
304
|
-
| `Screen.waitForText` | Block until text appears |
|
|
305
|
-
| `Screen.waitForCursor` | Block until cursor at position |
|
|
306
|
-
|
|
307
|
-
#### `Screen.getContents`
|
|
308
|
-
|
|
309
|
-
Returns the full cell grid with styling attributes.
|
|
310
|
-
|
|
311
|
-
**Params:**
|
|
312
|
-
```json
|
|
313
|
-
{
|
|
314
|
-
"sessionId": "a1b2c3d4...",
|
|
315
|
-
"region": { // optional, default: entire visible screen
|
|
316
|
-
"top": 0,
|
|
317
|
-
"left": 0,
|
|
318
|
-
"bottom": 23, // inclusive
|
|
319
|
-
"right": 79 // inclusive
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
**Result:**
|
|
325
|
-
```json
|
|
326
|
-
{
|
|
327
|
-
"rows": 24,
|
|
328
|
-
"cols": 80,
|
|
329
|
-
"cursor": {
|
|
330
|
-
"row": 5,
|
|
331
|
-
"col": 12,
|
|
332
|
-
"visible": true,
|
|
333
|
-
"shape": "block" // "block", "underline", "bar"
|
|
334
|
-
},
|
|
335
|
-
"cells": [
|
|
336
|
-
[
|
|
337
|
-
{
|
|
338
|
-
"char": "$",
|
|
339
|
-
"width": 1, // 1 for normal, 2 for wide (CJK), 0 for continuation
|
|
340
|
-
"fg": { "r": 255, "g": 255, "b": 255 },
|
|
341
|
-
"bg": { "r": 0, "g": 0, "b": 0 },
|
|
342
|
-
"attrs": {
|
|
343
|
-
"bold": false,
|
|
344
|
-
"italic": false,
|
|
345
|
-
"underline": "none", // "none", "single", "double", "curly", "dotted", "dashed"
|
|
346
|
-
"underlineColor": null, // optional RGB, null = use fg
|
|
347
|
-
"strikethrough": false,
|
|
348
|
-
"dim": false,
|
|
349
|
-
"blink": false,
|
|
350
|
-
"reverse": false,
|
|
351
|
-
"hidden": false
|
|
352
|
-
},
|
|
353
|
-
"hyperlink": null // URL string if OSC 8 hyperlink
|
|
354
|
-
}
|
|
355
|
-
]
|
|
356
|
-
],
|
|
357
|
-
"alternateScreen": false
|
|
358
|
-
}
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
**Notes:**
|
|
362
|
-
- `cells` is a 2D array: `cells[row][col]`
|
|
363
|
-
- Wide characters: the first cell has `width: 2`, the next cell has `width: 0` (continuation/spacer)
|
|
364
|
-
- Colors are always resolved to RGB (indexed/named colors resolved against the active palette)
|
|
365
|
-
|
|
366
|
-
#### `Screen.getText`
|
|
367
|
-
|
|
368
|
-
**Params:**
|
|
369
|
-
```json
|
|
370
|
-
{
|
|
371
|
-
"sessionId": "a1b2c3d4...",
|
|
372
|
-
"region": null, // optional, same as getContents
|
|
373
|
-
"trimTrailingWhitespace": true // optional, default: true
|
|
374
|
-
}
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
**Result:**
|
|
378
|
-
```json
|
|
379
|
-
{
|
|
380
|
-
"text": "$ echo hello\nhello\n$ _"
|
|
381
|
-
}
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
Rows separated by `\n`. Trailing whitespace on each row is trimmed by default.
|
|
385
|
-
|
|
386
|
-
#### `Screen.getScrollback`
|
|
387
|
-
|
|
388
|
-
**Params:**
|
|
389
|
-
```json
|
|
390
|
-
{
|
|
391
|
-
"sessionId": "a1b2c3d4...",
|
|
392
|
-
"lines": 100, // number of scrollback lines to retrieve
|
|
393
|
-
"offset": 0 // optional, 0 = most recent scrollback line
|
|
394
|
-
}
|
|
395
|
-
```
|
|
396
|
-
|
|
397
|
-
**Result:**
|
|
398
|
-
```json
|
|
399
|
-
{
|
|
400
|
-
"lines": [
|
|
401
|
-
{ "text": "previous output line 1", "lineNumber": -100 },
|
|
402
|
-
{ "text": "previous output line 2", "lineNumber": -99 }
|
|
403
|
-
],
|
|
404
|
-
"totalScrollback": 5000
|
|
405
|
-
}
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
`lineNumber` is negative, counting up toward 0 (the first visible row).
|
|
409
|
-
|
|
410
|
-
#### `Screen.screenshot`
|
|
411
|
-
|
|
412
|
-
**Params:**
|
|
413
|
-
```json
|
|
414
|
-
{
|
|
415
|
-
"sessionId": "a1b2c3d4...",
|
|
416
|
-
"format": "png", // "text", "ansi", "json", "svg", "png"
|
|
417
|
-
"theme": null, // optional, color theme override
|
|
418
|
-
"font": { // optional, for svg/png
|
|
419
|
-
"family": "JetBrains Mono",
|
|
420
|
-
"size": 14
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
```
|
|
424
|
-
|
|
425
|
-
**Result:**
|
|
426
|
-
```json
|
|
427
|
-
{
|
|
428
|
-
"format": "png",
|
|
429
|
-
"data": "iVBORw0KGgo...", // base64 for png, raw string for text/ansi/svg/json
|
|
430
|
-
"width": 960, // pixels, only for png/svg
|
|
431
|
-
"height": 480
|
|
432
|
-
}
|
|
433
|
-
```
|
|
434
|
-
|
|
435
|
-
**Format details:**
|
|
436
|
-
- `text` — plain text, same as `Screen.getText`
|
|
437
|
-
- `ansi` — text with ANSI escape codes preserved (can be printed to another terminal)
|
|
438
|
-
- `json` — same as `Screen.getContents` response
|
|
439
|
-
- `svg` — terminal rendered as SVG with colors, font, background
|
|
440
|
-
- `png` — rasterized SVG
|
|
441
|
-
|
|
442
|
-
#### `Screen.waitForText`
|
|
443
|
-
|
|
444
|
-
Blocks until the specified text/pattern appears on screen, or timeout.
|
|
445
|
-
|
|
446
|
-
**Params:**
|
|
447
|
-
```json
|
|
448
|
-
{
|
|
449
|
-
"sessionId": "a1b2c3d4...",
|
|
450
|
-
"pattern": "\\$\\s*$", // text or regex
|
|
451
|
-
"isRegex": true, // default: false (plain text match)
|
|
452
|
-
"region": null, // optional, limit search to region
|
|
453
|
-
"timeout": 5000, // milliseconds, default: 30000
|
|
454
|
-
"interval": 100 // optional, polling interval in ms, default: 100
|
|
455
|
-
}
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
**Result:**
|
|
459
|
-
```json
|
|
460
|
-
{
|
|
461
|
-
"found": true,
|
|
462
|
-
"matches": [
|
|
463
|
-
{
|
|
464
|
-
"text": "$ ",
|
|
465
|
-
"row": 5,
|
|
466
|
-
"col": 0,
|
|
467
|
-
"length": 2
|
|
468
|
-
}
|
|
469
|
-
],
|
|
470
|
-
"elapsed": 1234 // ms waited
|
|
471
|
-
}
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
If `found` is `false`, the method returns (not an error) after timeout with an empty `matches` array.
|
|
475
|
-
|
|
476
|
-
#### `Screen.waitForCursor`
|
|
477
|
-
|
|
478
|
-
**Params:**
|
|
479
|
-
```json
|
|
480
|
-
{
|
|
481
|
-
"sessionId": "a1b2c3d4...",
|
|
482
|
-
"row": 5, // optional, null = any row
|
|
483
|
-
"col": 12, // optional, null = any col
|
|
484
|
-
"timeout": 5000
|
|
485
|
-
}
|
|
486
|
-
```
|
|
487
|
-
|
|
488
|
-
**Result:**
|
|
489
|
-
```json
|
|
490
|
-
{
|
|
491
|
-
"cursor": { "row": 5, "col": 12, "visible": true, "shape": "block" },
|
|
492
|
-
"elapsed": 500
|
|
493
|
-
}
|
|
494
|
-
```
|
|
495
|
-
|
|
496
|
-
---
|
|
497
|
-
|
|
498
|
-
### 2.5 Terminal
|
|
499
|
-
|
|
500
|
-
Control terminal properties.
|
|
501
|
-
|
|
502
|
-
| Method | Description |
|
|
503
|
-
|--------|-------------|
|
|
504
|
-
| `Terminal.resize` | Change dimensions |
|
|
505
|
-
| `Terminal.getSize` | Query dimensions |
|
|
506
|
-
| `Terminal.setColorPalette` | Override color palette |
|
|
507
|
-
| `Terminal.getColorPalette` | Read current palette |
|
|
508
|
-
| `Terminal.getModes` | Query active terminal modes |
|
|
509
|
-
|
|
510
|
-
#### `Terminal.resize`
|
|
511
|
-
|
|
512
|
-
**Params:**
|
|
513
|
-
```json
|
|
514
|
-
{
|
|
515
|
-
"sessionId": "a1b2c3d4...",
|
|
516
|
-
"cols": 120,
|
|
517
|
-
"rows": 40
|
|
518
|
-
}
|
|
519
|
-
```
|
|
520
|
-
|
|
521
|
-
**Result:** `{}`
|
|
522
|
-
|
|
523
|
-
The underlying PTY and process receive `SIGWINCH`.
|
|
524
|
-
|
|
525
|
-
#### `Terminal.getSize`
|
|
526
|
-
|
|
527
|
-
**Params:**
|
|
528
|
-
```json
|
|
529
|
-
{
|
|
530
|
-
"sessionId": "a1b2c3d4..."
|
|
531
|
-
}
|
|
532
|
-
```
|
|
533
|
-
|
|
534
|
-
**Result:**
|
|
535
|
-
```json
|
|
536
|
-
{
|
|
537
|
-
"cols": 120,
|
|
538
|
-
"rows": 40
|
|
539
|
-
}
|
|
540
|
-
```
|
|
541
|
-
|
|
542
|
-
#### `Terminal.setColorPalette`
|
|
543
|
-
|
|
544
|
-
Override the 256-color palette used for color resolution.
|
|
545
|
-
|
|
546
|
-
**Params:**
|
|
547
|
-
```json
|
|
548
|
-
{
|
|
549
|
-
"sessionId": "a1b2c3d4...",
|
|
550
|
-
"palette": {
|
|
551
|
-
"0": { "r": 0, "g": 0, "b": 0 },
|
|
552
|
-
"1": { "r": 204, "g": 0, "b": 0 },
|
|
553
|
-
"15": { "r": 255, "g": 255, "b": 255 },
|
|
554
|
-
"foreground": { "r": 200, "g": 200, "b": 200 },
|
|
555
|
-
"background": { "r": 30, "g": 30, "b": 30 },
|
|
556
|
-
"cursor": { "r": 255, "g": 255, "b": 0 }
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
```
|
|
560
|
-
|
|
561
|
-
Only specified entries are overridden; unspecified entries keep their defaults. Affects `Screen.getContents` color resolution and screenshots.
|
|
562
|
-
|
|
563
|
-
**Result:** `{}`
|
|
564
|
-
|
|
565
|
-
#### `Terminal.getModes`
|
|
566
|
-
|
|
567
|
-
Query the active terminal modes. Useful for understanding what the running application has configured.
|
|
568
|
-
|
|
569
|
-
**Params:**
|
|
570
|
-
```json
|
|
571
|
-
{
|
|
572
|
-
"sessionId": "a1b2c3d4..."
|
|
573
|
-
}
|
|
574
|
-
```
|
|
575
|
-
|
|
576
|
-
**Result:**
|
|
577
|
-
```json
|
|
578
|
-
{
|
|
579
|
-
"cursorKeyMode": "normal", // "normal" or "application" (DECCKM)
|
|
580
|
-
"keypadMode": "numeric", // "numeric" or "application" (DECKPAM/DECKPNM)
|
|
581
|
-
"alternateScreen": false, // modes 47/1047/1049
|
|
582
|
-
"bracketedPaste": true, // mode 2004
|
|
583
|
-
"mouseTracking": "none", // "none", "x10", "normal", "cellMotion", "allMotion"
|
|
584
|
-
"mouseEncoding": "sgr", // "default", "utf8", "sgr", "urxvt", "sgrPixel"
|
|
585
|
-
"focusReporting": false, // mode 1004
|
|
586
|
-
"cursorVisible": true, // DECTCEM, mode 25
|
|
587
|
-
"cursorStyle": "block", // "block", "underline", "bar" (and blinking variants)
|
|
588
|
-
"autoWrap": true, // DECAWM, mode 7
|
|
589
|
-
"reverseVideo": false, // DECSCNM, mode 5
|
|
590
|
-
"originMode": false, // DECOM, mode 6
|
|
591
|
-
"synchronizedOutput": false // mode 2026
|
|
592
|
-
}
|
|
593
|
-
```
|
|
594
|
-
|
|
595
|
-
---
|
|
596
|
-
|
|
597
|
-
### 2.6 Recording (experimental)
|
|
598
|
-
|
|
599
|
-
> **Status:** Experimental. Recording methods may change between versions. Implementations advertise recording support via `capabilities.recording` in `Wrightty.getInfo`.
|
|
600
|
-
|
|
601
|
-
Record terminal sessions, actions, and video.
|
|
602
|
-
|
|
603
|
-
| Method | Description |
|
|
604
|
-
|--------|-------------|
|
|
605
|
-
| `Recording.startSession` | Start recording raw PTY I/O (asciicast format) |
|
|
606
|
-
| `Recording.stopSession` | Stop session recording and return the data |
|
|
607
|
-
| `Recording.startActions` | Start recording wrightty API calls as a replayable script |
|
|
608
|
-
| `Recording.stopActions` | Stop action recording and return the script |
|
|
609
|
-
| `Recording.captureScreen` | Capture a single screen frame |
|
|
610
|
-
| `Recording.startVideo` | Start framebuffer video recording (native emulators only) |
|
|
611
|
-
| `Recording.stopVideo` | Stop video recording and return the file |
|
|
612
|
-
|
|
613
|
-
Recording tiers (implementations advertise which they support):
|
|
614
|
-
|
|
615
|
-
| Tier | What | How | Overhead |
|
|
616
|
-
|------|------|-----|----------|
|
|
617
|
-
| **1 — Session** | PTY byte stream + timestamps | Tap into PTY event loop | Near zero |
|
|
618
|
-
| **2 — Video** | Pixel-perfect framebuffer capture | `glReadPixels` after render, pipe to ffmpeg | Low-medium |
|
|
619
|
-
| **3 — Actions** | API call log → replayable script | Intercept JSON-RPC methods | Near zero |
|
|
620
|
-
|
|
621
|
-
#### `Recording.startSession`
|
|
622
|
-
|
|
623
|
-
Begin recording all PTY output bytes with timestamps. Compatible with [asciicast v2](https://docs.asciinema.org/manual/asciicast/v2/) format — can be played back with `asciinema play`.
|
|
624
|
-
|
|
625
|
-
**Params:**
|
|
626
|
-
```json
|
|
627
|
-
{
|
|
628
|
-
"sessionId": "a1b2c3d4...",
|
|
629
|
-
"includeInput": true // optional, also record input events (default: false)
|
|
630
|
-
}
|
|
631
|
-
```
|
|
632
|
-
|
|
633
|
-
**Result:**
|
|
634
|
-
```json
|
|
635
|
-
{
|
|
636
|
-
"recordingId": "rec_001"
|
|
637
|
-
}
|
|
638
|
-
```
|
|
639
|
-
|
|
640
|
-
#### `Recording.stopSession`
|
|
641
|
-
|
|
642
|
-
Stop a session recording and return the asciicast data.
|
|
643
|
-
|
|
644
|
-
**Params:**
|
|
645
|
-
```json
|
|
646
|
-
{
|
|
647
|
-
"recordingId": "rec_001"
|
|
648
|
-
}
|
|
649
|
-
```
|
|
650
|
-
|
|
651
|
-
**Result:**
|
|
652
|
-
```json
|
|
653
|
-
{
|
|
654
|
-
"format": "asciicast-v2",
|
|
655
|
-
"data": "{\"version\":2,\"width\":80,\"height\":24,...}\n[0.5,\"o\",\"$ \"]\n[1.2,\"o\",\"hello\\r\\n\"]\n",
|
|
656
|
-
"duration": 12.5,
|
|
657
|
-
"events": 42
|
|
658
|
-
}
|
|
659
|
-
```
|
|
660
|
-
|
|
661
|
-
The `data` field contains the full asciicast v2 file as a string. Each line after the header is `[timestamp, type, data]`:
|
|
662
|
-
- `"o"` = output (PTY → screen)
|
|
663
|
-
- `"i"` = input (user → PTY, only if `includeInput` was true)
|
|
664
|
-
|
|
665
|
-
#### `Recording.startActions`
|
|
666
|
-
|
|
667
|
-
Begin recording all wrightty API calls (sendKeys, sendText, etc.) as a replayable script. Like Playwright's codegen.
|
|
668
|
-
|
|
669
|
-
**Params:**
|
|
670
|
-
```json
|
|
671
|
-
{
|
|
672
|
-
"sessionId": "a1b2c3d4...",
|
|
673
|
-
"format": "python" // "python", "json", or "cli"
|
|
674
|
-
}
|
|
675
|
-
```
|
|
676
|
-
|
|
677
|
-
**Result:**
|
|
678
|
-
```json
|
|
679
|
-
{
|
|
680
|
-
"recordingId": "rec_002"
|
|
681
|
-
}
|
|
682
|
-
```
|
|
683
|
-
|
|
684
|
-
#### `Recording.stopActions`
|
|
685
|
-
|
|
686
|
-
Stop action recording and return the generated script.
|
|
687
|
-
|
|
688
|
-
**Params:**
|
|
689
|
-
```json
|
|
690
|
-
{
|
|
691
|
-
"recordingId": "rec_002"
|
|
692
|
-
}
|
|
693
|
-
```
|
|
694
|
-
|
|
695
|
-
**Result (format=python):**
|
|
696
|
-
```json
|
|
697
|
-
{
|
|
698
|
-
"format": "python",
|
|
699
|
-
"data": "from wrightty import Terminal\n\nterm = Terminal.connect()\nterm.send_text('ls -la\\n')\nterm.wait_for('$')\nterm.send_keys('Ctrl+c')\nterm.close()\n",
|
|
700
|
-
"actions": 3,
|
|
701
|
-
"duration": 8.2
|
|
702
|
-
}
|
|
703
|
-
```
|
|
704
|
-
|
|
705
|
-
**Result (format=json):**
|
|
706
|
-
```json
|
|
707
|
-
{
|
|
708
|
-
"format": "json",
|
|
709
|
-
"data": [
|
|
710
|
-
{ "time": 0.0, "method": "Input.sendText", "params": { "text": "ls -la\n" } },
|
|
711
|
-
{ "time": 2.1, "method": "Screen.waitForText", "params": { "pattern": "$" } },
|
|
712
|
-
{ "time": 5.5, "method": "Input.sendKeys", "params": { "keys": ["Ctrl+c"] } }
|
|
713
|
-
],
|
|
714
|
-
"actions": 3,
|
|
715
|
-
"duration": 8.2
|
|
716
|
-
}
|
|
717
|
-
```
|
|
718
|
-
|
|
719
|
-
**Result (format=cli):**
|
|
720
|
-
```json
|
|
721
|
-
{
|
|
722
|
-
"format": "cli",
|
|
723
|
-
"data": "wrightty send-text 'ls -la\\n'\nwrightty wait-for '$'\nwrightty send-keys Ctrl+c\n",
|
|
724
|
-
"actions": 3,
|
|
725
|
-
"duration": 8.2
|
|
726
|
-
}
|
|
727
|
-
```
|
|
728
|
-
|
|
729
|
-
#### `Recording.captureScreen`
|
|
730
|
-
|
|
731
|
-
Capture a single screen frame. Can be called at any time. Frames can be collected into a GIF/video later.
|
|
732
|
-
|
|
733
|
-
**Params:**
|
|
734
|
-
```json
|
|
735
|
-
{
|
|
736
|
-
"sessionId": "a1b2c3d4...",
|
|
737
|
-
"format": "svg" // "svg", "text", or "png"
|
|
738
|
-
}
|
|
739
|
-
```
|
|
740
|
-
|
|
741
|
-
**Result:**
|
|
742
|
-
```json
|
|
743
|
-
{
|
|
744
|
-
"frameId": 0,
|
|
745
|
-
"timestamp": 1679000000000,
|
|
746
|
-
"format": "svg",
|
|
747
|
-
"data": "<svg ...>"
|
|
748
|
-
}
|
|
749
|
-
```
|
|
750
|
-
|
|
751
|
-
#### `Recording.startVideo`
|
|
752
|
-
|
|
753
|
-
Start recording the terminal as a video. Captures the actual rendered framebuffer at the specified FPS. Only available on native emulators with GPU rendering (Tier 2). Requires `ffmpeg` on the system.
|
|
754
|
-
|
|
755
|
-
**Params:**
|
|
756
|
-
```json
|
|
757
|
-
{
|
|
758
|
-
"sessionId": "a1b2c3d4...",
|
|
759
|
-
"fps": 30, // frames per second (default: 30)
|
|
760
|
-
"format": "mp4" // "mp4", "webm", or "gif"
|
|
761
|
-
}
|
|
762
|
-
```
|
|
763
|
-
|
|
764
|
-
**Result:**
|
|
765
|
-
```json
|
|
766
|
-
{
|
|
767
|
-
"recordingId": "rec_003"
|
|
768
|
-
}
|
|
769
|
-
```
|
|
770
|
-
|
|
771
|
-
#### `Recording.stopVideo`
|
|
772
|
-
|
|
773
|
-
Stop video recording. The server finishes encoding and returns the video file.
|
|
774
|
-
|
|
775
|
-
**Params:**
|
|
776
|
-
```json
|
|
777
|
-
{
|
|
778
|
-
"recordingId": "rec_003"
|
|
779
|
-
}
|
|
780
|
-
```
|
|
781
|
-
|
|
782
|
-
**Result:**
|
|
783
|
-
```json
|
|
784
|
-
{
|
|
785
|
-
"format": "mp4",
|
|
786
|
-
"path": "/tmp/wrightty-rec_003.mp4",
|
|
787
|
-
"duration": 12.5,
|
|
788
|
-
"frames": 375,
|
|
789
|
-
"width": 1920,
|
|
790
|
-
"height": 1080,
|
|
791
|
-
"size": 2458624
|
|
792
|
-
}
|
|
793
|
-
```
|
|
794
|
-
|
|
795
|
-
The video is saved to a temp file. The `path` field contains the absolute path. For large videos, the file is not base64-encoded in the response — the client reads it from disk.
|
|
796
|
-
|
|
797
|
-
---
|
|
798
|
-
|
|
799
|
-
### 2.7 Events
|
|
800
|
-
|
|
801
|
-
Events use a unified subscription model. Instead of per-event subscribe/unsubscribe methods, clients use a single `Events.subscribe` method and specify which event types they want.
|
|
802
|
-
|
|
803
|
-
#### `Events.subscribe`
|
|
804
|
-
|
|
805
|
-
**Params:**
|
|
806
|
-
```json
|
|
807
|
-
{
|
|
808
|
-
"sessionId": "a1b2c3d4...",
|
|
809
|
-
"events": ["Screen.updated", "Session.exited", "Shell.commandFinished"],
|
|
810
|
-
"options": {
|
|
811
|
-
"screenDebounceMs": 16 // optional, debounce for Screen.updated, default: 16
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
```
|
|
815
|
-
|
|
816
|
-
`events` accepts `"*"` as a wildcard to subscribe to all available events:
|
|
817
|
-
```json
|
|
818
|
-
{ "sessionId": "abc123", "events": ["*"] }
|
|
819
|
-
```
|
|
820
|
-
|
|
821
|
-
**Result:**
|
|
822
|
-
```json
|
|
823
|
-
{
|
|
824
|
-
"subscriptionId": "sub_001",
|
|
825
|
-
"subscribedEvents": ["Screen.updated", "Session.exited", "Shell.commandFinished"]
|
|
826
|
-
}
|
|
827
|
-
```
|
|
828
|
-
|
|
829
|
-
`subscribedEvents` confirms which events were actually subscribed (may be a subset if some are not supported).
|
|
830
|
-
|
|
831
|
-
#### `Events.unsubscribe`
|
|
832
|
-
|
|
833
|
-
**Params:**
|
|
834
|
-
```json
|
|
835
|
-
{
|
|
836
|
-
"subscriptionId": "sub_001"
|
|
837
|
-
}
|
|
838
|
-
```
|
|
839
|
-
|
|
840
|
-
**Result:** `{}`
|
|
841
|
-
|
|
842
|
-
---
|
|
843
|
-
|
|
844
|
-
## 3. Event Catalog
|
|
845
|
-
|
|
846
|
-
All events share a common envelope:
|
|
847
|
-
|
|
848
|
-
```json
|
|
849
|
-
{
|
|
850
|
-
"jsonrpc": "2.0",
|
|
851
|
-
"method": "Events.event",
|
|
852
|
-
"params": {
|
|
853
|
-
"subscriptionId": "sub_001",
|
|
854
|
-
"event": "<EventType>",
|
|
855
|
-
"sessionId": "a1b2c3d4...",
|
|
856
|
-
"timestamp": 1679000000000,
|
|
857
|
-
"data": { ... }
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
```
|
|
861
|
-
|
|
862
|
-
Events are organized into tiers. Tier 1 events MUST be supported by all implementations. Tier 2 and 3 are optional and advertised via `capabilities.events`.
|
|
863
|
-
|
|
864
|
-
---
|
|
865
|
-
|
|
866
|
-
### Tier 1 — Core Events (required)
|
|
867
|
-
|
|
868
|
-
#### `Screen.updated`
|
|
869
|
-
|
|
870
|
-
Screen content changed. Debounced to avoid flooding (default 16ms / 60fps).
|
|
871
|
-
|
|
872
|
-
```json
|
|
873
|
-
{
|
|
874
|
-
"dirtyRegion": { // bounding box of changed area, null if unknown
|
|
875
|
-
"top": 0, "left": 0, "bottom": 5, "right": 79
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
```
|
|
879
|
-
|
|
880
|
-
The event does NOT include screen contents. Clients call `Screen.getText` or `Screen.getContents` if they need the data.
|
|
881
|
-
|
|
882
|
-
#### `Session.exited`
|
|
883
|
-
|
|
884
|
-
The shell/process in this session has exited.
|
|
885
|
-
|
|
886
|
-
```json
|
|
887
|
-
{
|
|
888
|
-
"exitCode": 0, // null if killed by signal
|
|
889
|
-
"signal": null // e.g., "SIGTERM", "SIGKILL"
|
|
890
|
-
}
|
|
891
|
-
```
|
|
892
|
-
|
|
893
|
-
#### `Session.output`
|
|
894
|
-
|
|
895
|
-
Raw PTY output bytes, base64-encoded. Useful for session recording/replay (asciicast format, etc.).
|
|
896
|
-
|
|
897
|
-
```json
|
|
898
|
-
{
|
|
899
|
-
"data": "G1szMW1oZWxsbw==" // base64-encoded bytes
|
|
900
|
-
}
|
|
901
|
-
```
|
|
902
|
-
|
|
903
|
-
#### `Terminal.bell`
|
|
904
|
-
|
|
905
|
-
BEL character (0x07) received.
|
|
906
|
-
|
|
907
|
-
```json
|
|
908
|
-
{}
|
|
909
|
-
```
|
|
910
|
-
|
|
911
|
-
#### `Terminal.titleChanged`
|
|
912
|
-
|
|
913
|
-
Window title changed via OSC 0 or OSC 2.
|
|
914
|
-
|
|
915
|
-
```json
|
|
916
|
-
{
|
|
917
|
-
"title": "vim README.md",
|
|
918
|
-
"iconName": null // OSC 1 icon name, if set separately
|
|
919
|
-
}
|
|
920
|
-
```
|
|
921
|
-
|
|
922
|
-
#### `Terminal.cwdChanged`
|
|
923
|
-
|
|
924
|
-
Working directory changed. Detected via OSC 7 (`file://host/path`), OSC 9;9, or OSC 1337;CurrentDir.
|
|
925
|
-
|
|
926
|
-
```json
|
|
927
|
-
{
|
|
928
|
-
"cwd": "/home/user/project",
|
|
929
|
-
"uri": "file://hostname/home/user/project" // original OSC 7 URI if available
|
|
930
|
-
}
|
|
931
|
-
```
|
|
932
|
-
|
|
933
|
-
#### `Terminal.alternateScreen`
|
|
934
|
-
|
|
935
|
-
Application entered or exited the alternate screen buffer (modes 47/1047/1049). Critical for detecting TUI app launch/exit.
|
|
936
|
-
|
|
937
|
-
```json
|
|
938
|
-
{
|
|
939
|
-
"active": true // true = entered, false = exited
|
|
940
|
-
}
|
|
941
|
-
```
|
|
942
|
-
|
|
943
|
-
#### `Terminal.cursorChanged`
|
|
944
|
-
|
|
945
|
-
Cursor visibility or style changed (DECTCEM mode 25, CSI N SP q).
|
|
946
|
-
|
|
947
|
-
```json
|
|
948
|
-
{
|
|
949
|
-
"visible": true,
|
|
950
|
-
"shape": "bar", // "block", "underline", "bar"
|
|
951
|
-
"blinking": true
|
|
952
|
-
}
|
|
953
|
-
```
|
|
954
|
-
|
|
955
|
-
---
|
|
956
|
-
|
|
957
|
-
### Tier 2 — Shell Integration Events (optional, requires OSC 133)
|
|
958
|
-
|
|
959
|
-
These events require the shell to emit OSC 133 sequences (bash, zsh, fish with shell integration enabled). They provide semantic understanding of what's happening in the terminal.
|
|
960
|
-
|
|
961
|
-
#### `Shell.promptStart`
|
|
962
|
-
|
|
963
|
-
Shell has begun rendering its prompt (OSC 133;A).
|
|
964
|
-
|
|
965
|
-
```json
|
|
966
|
-
{}
|
|
967
|
-
```
|
|
968
|
-
|
|
969
|
-
#### `Shell.commandStart`
|
|
970
|
-
|
|
971
|
-
User has finished the prompt; command input area begins (OSC 133;B).
|
|
972
|
-
|
|
973
|
-
```json
|
|
974
|
-
{}
|
|
975
|
-
```
|
|
976
|
-
|
|
977
|
-
#### `Shell.outputStart`
|
|
978
|
-
|
|
979
|
-
Shell is executing the command; output begins (OSC 133;C).
|
|
980
|
-
|
|
981
|
-
```json
|
|
982
|
-
{
|
|
983
|
-
"command": null // the command text, if extractable from the screen between promptStart and outputStart
|
|
984
|
-
}
|
|
985
|
-
```
|
|
986
|
-
|
|
987
|
-
#### `Shell.commandFinished`
|
|
988
|
-
|
|
989
|
-
Command has completed (OSC 133;D).
|
|
990
|
-
|
|
991
|
-
```json
|
|
992
|
-
{
|
|
993
|
-
"exitCode": 0
|
|
994
|
-
}
|
|
995
|
-
```
|
|
996
|
-
|
|
997
|
-
**Why these matter:** An AI agent can use `Shell.commandFinished` to know when a command is done instead of fragile heuristics like "wait for the prompt pattern." A test framework can assert on exit codes without parsing output.
|
|
998
|
-
|
|
999
|
-
---
|
|
1000
|
-
|
|
1001
|
-
### Tier 2 — Terminal Notifications
|
|
1002
|
-
|
|
1003
|
-
#### `Terminal.notification`
|
|
1004
|
-
|
|
1005
|
-
A desktop notification was requested by the application. Covers:
|
|
1006
|
-
- OSC 9 (iTerm2-style simple notification)
|
|
1007
|
-
- OSC 99 (kitty rich notifications with buttons, icons, urgency)
|
|
1008
|
-
- OSC 777 (rxvt-unicode notifications)
|
|
1009
|
-
|
|
1010
|
-
```json
|
|
1011
|
-
{
|
|
1012
|
-
"title": "Build complete",
|
|
1013
|
-
"body": "Project compiled successfully",
|
|
1014
|
-
"urgency": "normal", // "low", "normal", "critical"
|
|
1015
|
-
"source": "osc9" // "osc9", "osc99", "osc777"
|
|
1016
|
-
}
|
|
1017
|
-
```
|
|
1018
|
-
|
|
1019
|
-
#### `Terminal.clipboardSet`
|
|
1020
|
-
|
|
1021
|
-
Application set clipboard content via OSC 52.
|
|
1022
|
-
|
|
1023
|
-
```json
|
|
1024
|
-
{
|
|
1025
|
-
"selection": "clipboard", // "clipboard", "primary", "secondary", "select"
|
|
1026
|
-
"text": "copied text", // decoded content (NOT base64)
|
|
1027
|
-
"base64": "Y29waWVkIHRleHQ=" // raw base64 as sent by app
|
|
1028
|
-
}
|
|
1029
|
-
```
|
|
1030
|
-
|
|
1031
|
-
**Security note:** In daemon mode, wrightty intercepts OSC 52 and emits this event instead of modifying the system clipboard. The client decides whether to honor it.
|
|
1032
|
-
|
|
1033
|
-
#### `Terminal.progressChanged`
|
|
1034
|
-
|
|
1035
|
-
Taskbar/tab progress indicator changed (OSC 9;4 — ConEmu/iTerm2/Windows Terminal).
|
|
1036
|
-
|
|
1037
|
-
```json
|
|
1038
|
-
{
|
|
1039
|
-
"state": "value", // "none", "value", "error", "indeterminate", "warning"
|
|
1040
|
-
"percent": 75 // 0-100, present when state is "value"
|
|
1041
|
-
}
|
|
1042
|
-
```
|
|
1043
|
-
|
|
1044
|
-
---
|
|
1045
|
-
|
|
1046
|
-
### Tier 2 — Mode Changes
|
|
1047
|
-
|
|
1048
|
-
#### `Terminal.modeChanged`
|
|
1049
|
-
|
|
1050
|
-
A terminal mode was set or reset. Rather than individual events per mode, this provides a unified notification with the mode name.
|
|
1051
|
-
|
|
1052
|
-
```json
|
|
1053
|
-
{
|
|
1054
|
-
"mode": "bracketedPaste", // see mode names below
|
|
1055
|
-
"enabled": true
|
|
1056
|
-
}
|
|
1057
|
-
```
|
|
1058
|
-
|
|
1059
|
-
**Mode names:**
|
|
1060
|
-
| Mode name | DEC mode | Description |
|
|
1061
|
-
|-----------|----------|-------------|
|
|
1062
|
-
| `cursorKeyMode` | 1 (DECCKM) | Application vs normal cursor keys |
|
|
1063
|
-
| `alternateScreen` | 1049 | Alternate screen buffer (also fires `Terminal.alternateScreen`) |
|
|
1064
|
-
| `bracketedPaste` | 2004 | Wrap pastes in escape sequences |
|
|
1065
|
-
| `mouseTracking` | 1000-1003 | Mouse event reporting enabled |
|
|
1066
|
-
| `focusReporting` | 1004 | Focus in/out reporting |
|
|
1067
|
-
| `cursorVisible` | 25 (DECTCEM) | Cursor show/hide |
|
|
1068
|
-
| `autoWrap` | 7 (DECAWM) | Auto-wrap at margin |
|
|
1069
|
-
| `reverseVideo` | 5 (DECSCNM) | Reverse video mode |
|
|
1070
|
-
| `synchronizedOutput` | 2026 | Buffered rendering |
|
|
1071
|
-
|
|
1072
|
-
---
|
|
1073
|
-
|
|
1074
|
-
### Tier 3 — Extended Events (optional, emulator-specific)
|
|
1075
|
-
|
|
1076
|
-
#### `Terminal.focusChanged`
|
|
1077
|
-
|
|
1078
|
-
Terminal window/pane gained or lost focus (requires mode 1004 to be enabled by the app).
|
|
1079
|
-
|
|
1080
|
-
```json
|
|
1081
|
-
{
|
|
1082
|
-
"focused": true
|
|
1083
|
-
}
|
|
1084
|
-
```
|
|
1085
|
-
|
|
1086
|
-
#### `Terminal.hyperlinkHovered`
|
|
1087
|
-
|
|
1088
|
-
An OSC 8 hyperlink region is under the cursor (native emulator mode only).
|
|
1089
|
-
|
|
1090
|
-
```json
|
|
1091
|
-
{
|
|
1092
|
-
"url": "https://example.com",
|
|
1093
|
-
"id": "link-1", // hyperlink ID if specified
|
|
1094
|
-
"row": 5,
|
|
1095
|
-
"colStart": 10,
|
|
1096
|
-
"colEnd": 35
|
|
1097
|
-
}
|
|
1098
|
-
```
|
|
1099
|
-
|
|
1100
|
-
#### `Terminal.imageDisplayed`
|
|
1101
|
-
|
|
1102
|
-
An inline image was displayed via Sixel, kitty graphics protocol, or iTerm2 inline image.
|
|
1103
|
-
|
|
1104
|
-
```json
|
|
1105
|
-
{
|
|
1106
|
-
"protocol": "kitty", // "sixel", "kitty", "iterm2"
|
|
1107
|
-
"row": 5,
|
|
1108
|
-
"col": 0,
|
|
1109
|
-
"widthCells": 40,
|
|
1110
|
-
"heightCells": 20,
|
|
1111
|
-
"widthPixels": 640,
|
|
1112
|
-
"heightPixels": 480,
|
|
1113
|
-
"imageId": null // kitty image ID if applicable
|
|
1114
|
-
}
|
|
1115
|
-
```
|
|
1116
|
-
|
|
1117
|
-
#### `Terminal.colorPaletteChanged`
|
|
1118
|
-
|
|
1119
|
-
Application changed terminal colors via OSC 4, OSC 10-19, or pushed/popped the color stack.
|
|
1120
|
-
|
|
1121
|
-
```json
|
|
1122
|
-
{
|
|
1123
|
-
"changes": {
|
|
1124
|
-
"foreground": { "r": 200, "g": 200, "b": 200 },
|
|
1125
|
-
"4": { "r": 0, "g": 0, "b": 255 }
|
|
1126
|
-
},
|
|
1127
|
-
"source": "osc4" // "osc4", "osc10", "push", "pop"
|
|
1128
|
-
}
|
|
1129
|
-
```
|
|
1130
|
-
|
|
1131
|
-
#### `Terminal.remoteHostChanged`
|
|
1132
|
-
|
|
1133
|
-
Remote host info changed (OSC 1337;RemoteHost). Useful for detecting SSH sessions.
|
|
1134
|
-
|
|
1135
|
-
```json
|
|
1136
|
-
{
|
|
1137
|
-
"user": "deploy",
|
|
1138
|
-
"host": "prod-server-01"
|
|
1139
|
-
}
|
|
1140
|
-
```
|
|
1141
|
-
|
|
1142
|
-
#### `Terminal.userVariableSet`
|
|
1143
|
-
|
|
1144
|
-
iTerm2 user variable set (OSC 1337;SetUserVar).
|
|
1145
|
-
|
|
1146
|
-
```json
|
|
1147
|
-
{
|
|
1148
|
-
"key": "gitBranch",
|
|
1149
|
-
"value": "main"
|
|
1150
|
-
}
|
|
1151
|
-
```
|
|
1152
|
-
|
|
1153
|
-
#### `Terminal.fileTransfer`
|
|
1154
|
-
|
|
1155
|
-
Kitty file transfer event (OSC 5113).
|
|
1156
|
-
|
|
1157
|
-
```json
|
|
1158
|
-
{
|
|
1159
|
-
"action": "receive", // "send", "receive", "progress", "complete", "error"
|
|
1160
|
-
"filename": "data.csv",
|
|
1161
|
-
"progress": 0.75, // 0.0-1.0 for progress events
|
|
1162
|
-
"error": null
|
|
1163
|
-
}
|
|
1164
|
-
```
|
|
1165
|
-
|
|
1166
|
-
---
|
|
1167
|
-
|
|
1168
|
-
## 4. Error Codes
|
|
1169
|
-
|
|
1170
|
-
Standard JSON-RPC 2.0 errors plus protocol-specific codes.
|
|
1171
|
-
|
|
1172
|
-
| Code | Name | Description |
|
|
1173
|
-
|------|------|-------------|
|
|
1174
|
-
| -32700 | Parse error | Invalid JSON |
|
|
1175
|
-
| -32600 | Invalid request | Not a valid JSON-RPC request |
|
|
1176
|
-
| -32601 | Method not found | Unknown method |
|
|
1177
|
-
| -32602 | Invalid params | Missing or invalid parameters |
|
|
1178
|
-
| -32603 | Internal error | Server error |
|
|
1179
|
-
| 1001 | SessionNotFound | No session with the given ID |
|
|
1180
|
-
| 1002 | SessionDestroyed | Session was already destroyed |
|
|
1181
|
-
| 1003 | WaitTimeout | `waitForText`/`waitForCursor` timed out (also returns normally with `found: false`) |
|
|
1182
|
-
| 1004 | InvalidPattern | Regex pattern failed to compile |
|
|
1183
|
-
| 1005 | SpawnFailed | Failed to spawn PTY/shell process |
|
|
1184
|
-
| 1006 | NotSupported | Method or event not supported by this implementation |
|
|
1185
|
-
| 1007 | MaxSessionsReached | Cannot create more sessions |
|
|
1186
|
-
| 1008 | SubscriptionNotFound | Invalid subscription ID |
|
|
1187
|
-
|
|
1188
|
-
**Error response example:**
|
|
1189
|
-
```json
|
|
1190
|
-
{
|
|
1191
|
-
"jsonrpc": "2.0",
|
|
1192
|
-
"id": 5,
|
|
1193
|
-
"error": {
|
|
1194
|
-
"code": 1001,
|
|
1195
|
-
"message": "Session not found",
|
|
1196
|
-
"data": { "sessionId": "nonexistent-id" }
|
|
1197
|
-
}
|
|
1198
|
-
}
|
|
1199
|
-
```
|
|
1200
|
-
|
|
1201
|
-
---
|
|
1202
|
-
|
|
1203
|
-
## 5. Capability Negotiation
|
|
1204
|
-
|
|
1205
|
-
Not all implementations support every method or event. Native emulator integrations may only support a subset.
|
|
1206
|
-
|
|
1207
|
-
### 5.1 Capability Flags
|
|
1208
|
-
|
|
1209
|
-
Returned in `Wrightty.getInfo`:
|
|
1210
|
-
|
|
1211
|
-
```json
|
|
1212
|
-
{
|
|
1213
|
-
"capabilities": {
|
|
1214
|
-
"screenshot": ["text", "ansi", "json"],
|
|
1215
|
-
"maxSessions": 1,
|
|
1216
|
-
"supportsResize": true,
|
|
1217
|
-
"supportsScrollback": true,
|
|
1218
|
-
"supportsMouse": false,
|
|
1219
|
-
"supportsColorPalette": false,
|
|
1220
|
-
"supportsSessionCreate": true,
|
|
1221
|
-
"supportsRawOutput": true,
|
|
1222
|
-
"supportsShellIntegration": true,
|
|
1223
|
-
"events": [
|
|
1224
|
-
"Screen.updated", "Session.exited", "Terminal.bell",
|
|
1225
|
-
"Terminal.titleChanged", "Terminal.cwdChanged"
|
|
1226
|
-
]
|
|
1227
|
-
}
|
|
1228
|
-
}
|
|
1229
|
-
```
|
|
1230
|
-
|
|
1231
|
-
The `events` array is the authoritative list of subscribable event types. If an event type is not listed, subscribing to it will silently exclude it from the subscription (reflected in the `subscribedEvents` response).
|
|
1232
|
-
|
|
1233
|
-
### 5.2 Graceful Degradation
|
|
1234
|
-
|
|
1235
|
-
If a client calls an unsupported method, the server returns error code `1006 NotSupported`. Clients should check capabilities first and fall back accordingly.
|
|
1236
|
-
|
|
1237
|
-
---
|
|
1238
|
-
|
|
1239
|
-
## 6. Examples
|
|
1240
|
-
|
|
1241
|
-
### 6.1 Run a command and read output
|
|
1242
|
-
|
|
1243
|
-
```json
|
|
1244
|
-
// 1. Create session
|
|
1245
|
-
→ {"jsonrpc":"2.0","id":1,"method":"Session.create","params":{"cols":80,"rows":24}}
|
|
1246
|
-
← {"jsonrpc":"2.0","id":1,"result":{"sessionId":"abc123"}}
|
|
1247
|
-
|
|
1248
|
-
// 2. Wait for shell prompt
|
|
1249
|
-
→ {"jsonrpc":"2.0","id":2,"method":"Screen.waitForText","params":{"sessionId":"abc123","pattern":"\\$","isRegex":true,"timeout":5000}}
|
|
1250
|
-
← {"jsonrpc":"2.0","id":2,"result":{"found":true,"matches":[{"text":"$","row":0,"col":14,"length":1}],"elapsed":120}}
|
|
1251
|
-
|
|
1252
|
-
// 3. Type a command
|
|
1253
|
-
→ {"jsonrpc":"2.0","id":3,"method":"Input.sendKeys","params":{"sessionId":"abc123","keys":["e","c","h","o"," ","h","e","l","l","o","Enter"]}}
|
|
1254
|
-
← {"jsonrpc":"2.0","id":3,"result":{}}
|
|
1255
|
-
|
|
1256
|
-
// 4. Wait for output
|
|
1257
|
-
→ {"jsonrpc":"2.0","id":4,"method":"Screen.waitForText","params":{"sessionId":"abc123","pattern":"hello","timeout":5000}}
|
|
1258
|
-
← {"jsonrpc":"2.0","id":4,"result":{"found":true,"matches":[{"text":"hello","row":1,"col":0,"length":5}],"elapsed":50}}
|
|
1259
|
-
|
|
1260
|
-
// 5. Read the screen
|
|
1261
|
-
→ {"jsonrpc":"2.0","id":5,"method":"Screen.getText","params":{"sessionId":"abc123"}}
|
|
1262
|
-
← {"jsonrpc":"2.0","id":5,"result":{"text":"user@host:~$ echo hello\nhello\nuser@host:~$"}}
|
|
1263
|
-
|
|
1264
|
-
// 6. Take a screenshot
|
|
1265
|
-
→ {"jsonrpc":"2.0","id":6,"method":"Screen.screenshot","params":{"sessionId":"abc123","format":"png"}}
|
|
1266
|
-
← {"jsonrpc":"2.0","id":6,"result":{"format":"png","data":"iVBORw0KGgo...","width":960,"height":480}}
|
|
1267
|
-
```
|
|
1268
|
-
|
|
1269
|
-
### 6.2 Subscribe to events
|
|
1270
|
-
|
|
1271
|
-
```json
|
|
1272
|
-
// Subscribe to multiple event types at once
|
|
1273
|
-
→ {"jsonrpc":"2.0","id":10,"method":"Events.subscribe","params":{"sessionId":"abc123","events":["Screen.updated","Shell.commandFinished","Terminal.bell"]}}
|
|
1274
|
-
← {"jsonrpc":"2.0","id":10,"result":{"subscriptionId":"sub_001","subscribedEvents":["Screen.updated","Shell.commandFinished","Terminal.bell"]}}
|
|
1275
|
-
|
|
1276
|
-
// Screen update event arrives
|
|
1277
|
-
← {"jsonrpc":"2.0","method":"Events.event","params":{"subscriptionId":"sub_001","event":"Screen.updated","sessionId":"abc123","timestamp":1679000000000,"data":{"dirtyRegion":{"top":0,"left":0,"bottom":2,"right":79}}}}
|
|
1278
|
-
|
|
1279
|
-
// Command finished event (from OSC 133;D)
|
|
1280
|
-
← {"jsonrpc":"2.0","method":"Events.event","params":{"subscriptionId":"sub_001","event":"Shell.commandFinished","sessionId":"abc123","timestamp":1679000001000,"data":{"exitCode":0}}}
|
|
1281
|
-
|
|
1282
|
-
// Unsubscribe
|
|
1283
|
-
→ {"jsonrpc":"2.0","id":11,"method":"Events.unsubscribe","params":{"subscriptionId":"sub_001"}}
|
|
1284
|
-
← {"jsonrpc":"2.0","id":11,"result":{}}
|
|
1285
|
-
```
|
|
1286
|
-
|
|
1287
|
-
### 6.3 Interact with a TUI app (vim)
|
|
1288
|
-
|
|
1289
|
-
```json
|
|
1290
|
-
// Launch vim
|
|
1291
|
-
→ {"jsonrpc":"2.0","id":1,"method":"Session.create","params":{"shell":"/usr/bin/vim","args":["test.txt"],"cols":120,"rows":40}}
|
|
1292
|
-
← {"jsonrpc":"2.0","id":1,"result":{"sessionId":"vim123"}}
|
|
1293
|
-
|
|
1294
|
-
// Subscribe to know when alternate screen is entered
|
|
1295
|
-
→ {"jsonrpc":"2.0","id":2,"method":"Events.subscribe","params":{"sessionId":"vim123","events":["Terminal.alternateScreen"]}}
|
|
1296
|
-
← {"jsonrpc":"2.0","id":2,"result":{"subscriptionId":"sub_002","subscribedEvents":["Terminal.alternateScreen"]}}
|
|
1297
|
-
|
|
1298
|
-
// Alternate screen event confirms vim loaded
|
|
1299
|
-
← {"jsonrpc":"2.0","method":"Events.event","params":{"subscriptionId":"sub_002","event":"Terminal.alternateScreen","sessionId":"vim123","timestamp":1679000000100,"data":{"active":true}}}
|
|
1300
|
-
|
|
1301
|
-
// Wait for vim status line
|
|
1302
|
-
→ {"jsonrpc":"2.0","id":3,"method":"Screen.waitForText","params":{"sessionId":"vim123","pattern":"test.txt","timeout":5000}}
|
|
1303
|
-
← {"jsonrpc":"2.0","id":3,"result":{"found":true,"matches":[{"text":"test.txt","row":39,"col":1,"length":8}],"elapsed":200}}
|
|
1304
|
-
|
|
1305
|
-
// Enter insert mode and type
|
|
1306
|
-
→ {"jsonrpc":"2.0","id":4,"method":"Input.sendKeys","params":{"sessionId":"vim123","keys":["i","H","e","l","l","o"," ","w","o","r","l","d","Escape"]}}
|
|
1307
|
-
← {"jsonrpc":"2.0","id":4,"result":{}}
|
|
1308
|
-
|
|
1309
|
-
// Save and quit
|
|
1310
|
-
→ {"jsonrpc":"2.0","id":5,"method":"Input.sendKeys","params":{"sessionId":"vim123","keys":[":","w","q","Enter"]}}
|
|
1311
|
-
← {"jsonrpc":"2.0","id":5,"result":{}}
|
|
1312
|
-
|
|
1313
|
-
// Alternate screen exit event confirms vim closed
|
|
1314
|
-
← {"jsonrpc":"2.0","method":"Events.event","params":{"subscriptionId":"sub_002","event":"Terminal.alternateScreen","sessionId":"vim123","timestamp":1679000005000,"data":{"active":false}}}
|
|
1315
|
-
```
|
|
1316
|
-
|
|
1317
|
-
### 6.4 AI agent with shell integration
|
|
1318
|
-
|
|
1319
|
-
```json
|
|
1320
|
-
// Subscribe to shell integration events
|
|
1321
|
-
→ {"jsonrpc":"2.0","id":1,"method":"Events.subscribe","params":{"sessionId":"abc123","events":["Shell.commandFinished","Terminal.cwdChanged","Terminal.notification"]}}
|
|
1322
|
-
← {"jsonrpc":"2.0","id":1,"result":{"subscriptionId":"sub_003","subscribedEvents":["Shell.commandFinished","Terminal.cwdChanged"]}}
|
|
1323
|
-
|
|
1324
|
-
// Send a command
|
|
1325
|
-
→ {"jsonrpc":"2.0","id":2,"method":"Input.sendKeys","params":{"sessionId":"abc123","keys":["c","d"," ","/","t","m","p","Enter"]}}
|
|
1326
|
-
← {"jsonrpc":"2.0","id":2,"result":{}}
|
|
1327
|
-
|
|
1328
|
-
// CWD change detected via OSC 7
|
|
1329
|
-
← {"jsonrpc":"2.0","method":"Events.event","params":{"subscriptionId":"sub_003","event":"Terminal.cwdChanged","sessionId":"abc123","timestamp":1679000000500,"data":{"cwd":"/tmp","uri":"file://hostname/tmp"}}}
|
|
1330
|
-
|
|
1331
|
-
// Command finished with exit code
|
|
1332
|
-
← {"jsonrpc":"2.0","method":"Events.event","params":{"subscriptionId":"sub_003","event":"Shell.commandFinished","sessionId":"abc123","timestamp":1679000000600,"data":{"exitCode":0}}}
|
|
1333
|
-
|
|
1334
|
-
// Run a failing command
|
|
1335
|
-
→ {"jsonrpc":"2.0","id":3,"method":"Input.sendKeys","params":{"sessionId":"abc123","keys":["l","s"," ","/","n","o","p","e","Enter"]}}
|
|
1336
|
-
← {"jsonrpc":"2.0","id":3,"result":{}}
|
|
1337
|
-
|
|
1338
|
-
// Agent knows the command failed without parsing output
|
|
1339
|
-
← {"jsonrpc":"2.0","method":"Events.event","params":{"subscriptionId":"sub_003","event":"Shell.commandFinished","sessionId":"abc123","timestamp":1679000001200,"data":{"exitCode":2}}}
|
|
1340
|
-
```
|
|
1341
|
-
|
|
1342
|
-
### 6.5 Clipboard interception
|
|
1343
|
-
|
|
1344
|
-
```json
|
|
1345
|
-
// Subscribe to clipboard events
|
|
1346
|
-
→ {"jsonrpc":"2.0","id":1,"method":"Events.subscribe","params":{"sessionId":"abc123","events":["Terminal.clipboardSet"]}}
|
|
1347
|
-
← {"jsonrpc":"2.0","id":1,"result":{"subscriptionId":"sub_004","subscribedEvents":["Terminal.clipboardSet"]}}
|
|
1348
|
-
|
|
1349
|
-
// User yanks text in vim (triggers OSC 52)
|
|
1350
|
-
← {"jsonrpc":"2.0","method":"Events.event","params":{"subscriptionId":"sub_004","event":"Terminal.clipboardSet","sessionId":"abc123","timestamp":1679000002000,"data":{"selection":"clipboard","text":"yanked text here","base64":"eWFua2VkIHRleHQgaGVyZQ=="}}}
|
|
1351
|
-
```
|