@arach/lattices 0.2.1 → 0.6.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/LICENSE +21 -0
- package/README.md +144 -69
- package/apps/mac/Info.plist +43 -0
- package/apps/mac/Lattices.app/Contents/Info.plist +43 -0
- package/apps/mac/Lattices.app/Contents/MacOS/Lattices +0 -0
- package/apps/mac/Lattices.app/Contents/Resources/AppIcon.icns +0 -0
- package/apps/mac/Lattices.app/Contents/Resources/docs/assistant-knowledge.md +130 -0
- package/apps/mac/Lattices.app/Contents/Resources/tap.wav +0 -0
- package/apps/mac/Lattices.app/Contents/_CodeSignature/CodeResources +150 -0
- package/apps/mac/Lattices.entitlements +21 -0
- package/apps/mac/Resources/Pets/assistant-spark/pet.json +62 -0
- package/apps/mac/Resources/Pets/assistant-spark/spritesheet.webp +0 -0
- package/apps/mac/Resources/Pets/scout-ranger/pet.json +6 -0
- package/apps/mac/Resources/Pets/scout-ranger/spritesheet.webp +0 -0
- package/apps/mac/Resources/tap.wav +0 -0
- package/assets/AppIcon.icns +0 -0
- package/bin/assistant-intelligence.ts +912 -0
- package/bin/cli/capture.ts +252 -0
- package/bin/cli/daemon.ts +22 -0
- package/bin/cli/helpers.ts +105 -0
- package/bin/cli/layer.ts +178 -0
- package/bin/cli/runs.ts +43 -0
- package/bin/cli/search.ts +141 -0
- package/bin/cli/session.ts +32 -0
- package/bin/client.ts +17 -0
- package/bin/cua.ts +26 -0
- package/bin/{daemon-client.js → daemon-client.ts} +49 -30
- package/bin/handsoff-infer.ts +96 -0
- package/bin/handsoff-worker.ts +531 -0
- package/bin/infer.ts +424 -0
- package/bin/keychain.ts +75 -0
- package/bin/lattices-app.ts +655 -0
- package/bin/lattices-build +125 -0
- package/bin/lattices-build-env.ts +77 -0
- package/bin/lattices-dev +362 -0
- package/bin/lattices.ts +3260 -0
- package/bin/project-twin.ts +645 -0
- package/docs/agent-execution-plan.md +562 -0
- package/docs/agent-layer-guide.md +207 -0
- package/docs/agents.md +233 -0
- package/docs/ai-chat-ux-review.md +416 -0
- package/docs/api.md +1041 -47
- package/docs/app.md +96 -13
- package/docs/assistant-knowledge.md +130 -0
- package/docs/companion-deck.md +209 -0
- package/docs/component-extraction-roadmap.md +392 -0
- package/docs/concepts.md +13 -12
- package/docs/config.md +83 -10
- package/docs/gesture-customization-proposal.md +520 -0
- package/docs/handsoff-test-scenarios.md +84 -0
- package/docs/hyperspace-grid-snappiness.md +210 -0
- package/docs/layers.md +176 -28
- package/docs/mouse-gestures.md +244 -0
- package/docs/ocr.md +21 -9
- package/docs/overview.md +42 -23
- package/docs/presentation-execution-review.md +491 -0
- package/docs/prompts/hands-off-system.md +382 -0
- package/docs/prompts/hands-off-turn.md +30 -0
- package/docs/prompts/voice-advisor.md +31 -0
- package/docs/prompts/voice-fallback.md +23 -0
- package/docs/proposals/LAT-001-gesture-visual-customization.md +522 -0
- package/docs/proposals/LAT-002-shared-overlay-canvas.md +353 -0
- package/docs/proposals/LAT-003-menu-bar-controller-architecture.md +291 -0
- package/docs/proposals/LAT-004-interactive-overlay-actors.md +534 -0
- package/docs/proposals/LAT-005-action-runtime-product-spine.md +914 -0
- package/docs/proposals/LAT-006-followup-gaps.md +103 -0
- package/docs/proposals/LAT-006-runs-and-capture-in-lattices.md +566 -0
- package/docs/proposals/LAT-007-unified-app-shell.md +128 -0
- package/docs/quickstart.md +8 -12
- package/docs/reference/dewey.config.ts +74 -0
- package/docs/reference/install-agent.md +79 -0
- package/docs/release.md +172 -0
- package/docs/repo-structure.md +100 -0
- package/docs/terminal-kit.md +87 -0
- package/docs/tiling-reference.md +224 -0
- package/docs/twins.md +138 -0
- package/docs/voice-command-protocol.md +278 -0
- package/docs/voice-error-model.md +73 -0
- package/docs/voice.md +221 -0
- package/package.json +69 -16
- package/packages/npm/sdk/cua.d.mts +1 -0
- package/packages/npm/sdk/cua.d.ts +188 -0
- package/packages/npm/sdk/cua.mjs +376 -0
- package/app/Lattices.app/Contents/Info.plist +0 -24
- package/app/Package.swift +0 -13
- package/app/Sources/ActionRow.swift +0 -61
- package/app/Sources/App.swift +0 -10
- package/app/Sources/AppDelegate.swift +0 -234
- package/app/Sources/AppShellView.swift +0 -62
- package/app/Sources/AppTypeClassifier.swift +0 -70
- package/app/Sources/AppWindowShell.swift +0 -63
- package/app/Sources/CheatSheetHUD.swift +0 -332
- package/app/Sources/CommandModeState.swift +0 -1362
- package/app/Sources/CommandModeView.swift +0 -1405
- package/app/Sources/CommandModeWindow.swift +0 -192
- package/app/Sources/CommandPaletteView.swift +0 -307
- package/app/Sources/CommandPaletteWindow.swift +0 -134
- package/app/Sources/DaemonProtocol.swift +0 -101
- package/app/Sources/DaemonServer.swift +0 -414
- package/app/Sources/DesktopModel.swift +0 -121
- package/app/Sources/DesktopModelTypes.swift +0 -71
- package/app/Sources/DiagnosticLog.swift +0 -271
- package/app/Sources/EventBus.swift +0 -30
- package/app/Sources/HotkeyManager.swift +0 -250
- package/app/Sources/HotkeyStore.swift +0 -338
- package/app/Sources/InventoryManager.swift +0 -35
- package/app/Sources/InventoryPath.swift +0 -43
- package/app/Sources/KeyRecorderView.swift +0 -210
- package/app/Sources/LatticesApi.swift +0 -1125
- package/app/Sources/MainView.swift +0 -467
- package/app/Sources/MainWindow.swift +0 -83
- package/app/Sources/OcrModel.swift +0 -309
- package/app/Sources/OcrStore.swift +0 -295
- package/app/Sources/OmniSearchState.swift +0 -283
- package/app/Sources/OmniSearchView.swift +0 -288
- package/app/Sources/OmniSearchWindow.swift +0 -105
- package/app/Sources/OrphanRow.swift +0 -129
- package/app/Sources/PaletteCommand.swift +0 -419
- package/app/Sources/PermissionChecker.swift +0 -125
- package/app/Sources/Preferences.swift +0 -92
- package/app/Sources/ProcessModel.swift +0 -199
- package/app/Sources/ProcessQuery.swift +0 -151
- package/app/Sources/Project.swift +0 -28
- package/app/Sources/ProjectRow.swift +0 -368
- package/app/Sources/ProjectScanner.swift +0 -121
- package/app/Sources/ScreenMapState.swift +0 -2387
- package/app/Sources/ScreenMapView.swift +0 -2820
- package/app/Sources/ScreenMapWindowController.swift +0 -89
- package/app/Sources/SessionManager.swift +0 -72
- package/app/Sources/SettingsView.swift +0 -1053
- package/app/Sources/SettingsWindow.swift +0 -20
- package/app/Sources/TabGroupRow.swift +0 -178
- package/app/Sources/Terminal.swift +0 -259
- package/app/Sources/TerminalQuery.swift +0 -156
- package/app/Sources/TerminalSynthesizer.swift +0 -200
- package/app/Sources/Theme.swift +0 -163
- package/app/Sources/TilePickerView.swift +0 -209
- package/app/Sources/TmuxModel.swift +0 -53
- package/app/Sources/TmuxQuery.swift +0 -81
- package/app/Sources/WindowTiler.swift +0 -1755
- package/app/Sources/WorkspaceManager.swift +0 -434
- package/bin/lattices-app.js +0 -221
- package/bin/lattices.js +0 -1418
package/docs/api.md
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
|
-
title:
|
|
2
|
+
title: Agent API
|
|
3
3
|
description: WebSocket API reference for programmatic control of lattices
|
|
4
4
|
order: 5
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
The lattices menu bar app runs a WebSocket
|
|
8
|
-
|
|
7
|
+
The lattices menu bar app runs a WebSocket server on `ws://127.0.0.1:9399`.
|
|
8
|
+
35+ RPC methods and 5 real-time events.
|
|
9
9
|
|
|
10
10
|
## Quick start
|
|
11
11
|
|
|
12
|
-
1. Launch the
|
|
12
|
+
1. Launch the server (it starts with the menu bar app):
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
15
|
lattices app
|
|
@@ -24,7 +24,7 @@ lattices daemon status
|
|
|
24
24
|
3. Call a method from Node.js:
|
|
25
25
|
|
|
26
26
|
```js
|
|
27
|
-
import { daemonCall } from '@
|
|
27
|
+
import { daemonCall } from '@lattices/cli'
|
|
28
28
|
|
|
29
29
|
const windows = await daemonCall('windows.list')
|
|
30
30
|
console.log(windows) // [{ wid, app, title, frame, ... }, ...]
|
|
@@ -83,14 +83,14 @@ lattices uses a JSON-RPC-style protocol over WebSocket on port **9399**.
|
|
|
83
83
|
|
|
84
84
|
### Connection lifecycle
|
|
85
85
|
|
|
86
|
-
- The
|
|
86
|
+
- The server starts when the menu bar app launches and stops when it quits.
|
|
87
87
|
- Connections are plain WebSocket. No handshake, no auth, no heartbeat.
|
|
88
88
|
- The Node.js `daemonCall()` client opens a fresh connection per call and
|
|
89
89
|
closes it when the response arrives. For event subscriptions, hold the
|
|
90
90
|
connection open (see [Reactive event pattern](#agent-integration)).
|
|
91
|
-
- If the
|
|
92
|
-
connections are dropped. Clients should reconnect and treat
|
|
93
|
-
|
|
91
|
+
- If the server restarts (e.g. after `lattices app restart`), existing
|
|
92
|
+
connections are dropped. Clients should reconnect and treat it as
|
|
93
|
+
stateless. There is no session resumption.
|
|
94
94
|
|
|
95
95
|
## Node.js client
|
|
96
96
|
|
|
@@ -103,7 +103,7 @@ matching internally.
|
|
|
103
103
|
Send an RPC call and await the response.
|
|
104
104
|
|
|
105
105
|
```js
|
|
106
|
-
import { daemonCall } from '@
|
|
106
|
+
import { daemonCall } from '@lattices/cli'
|
|
107
107
|
|
|
108
108
|
// Read-only
|
|
109
109
|
const status = await daemonCall('daemon.status')
|
|
@@ -112,21 +112,24 @@ const win = await daemonCall('windows.get', { wid: 1234 })
|
|
|
112
112
|
|
|
113
113
|
// Mutations
|
|
114
114
|
await daemonCall('session.launch', { path: '/Users/you/dev/myapp' })
|
|
115
|
-
await daemonCall('window.
|
|
115
|
+
await daemonCall('window.place', {
|
|
116
|
+
session: 'myapp-a1b2c3',
|
|
117
|
+
placement: { kind: 'tile', value: 'left' }
|
|
118
|
+
})
|
|
116
119
|
|
|
117
120
|
// Custom timeout (default: 3000ms)
|
|
118
121
|
await daemonCall('projects.scan', null, 10000)
|
|
119
122
|
```
|
|
120
123
|
|
|
121
124
|
**Returns** the `result` field from the response.
|
|
122
|
-
**Throws** if the
|
|
125
|
+
**Throws** if the server returns an error, the connection fails, or the timeout is reached.
|
|
123
126
|
|
|
124
127
|
### `isDaemonRunning()`
|
|
125
128
|
|
|
126
|
-
Check if the
|
|
129
|
+
Check if the server is reachable.
|
|
127
130
|
|
|
128
131
|
```js
|
|
129
|
-
import { isDaemonRunning } from '@
|
|
132
|
+
import { isDaemonRunning } from '@lattices/cli'
|
|
130
133
|
|
|
131
134
|
if (await isDaemonRunning()) {
|
|
132
135
|
console.log('daemon is up')
|
|
@@ -135,12 +138,50 @@ if (await isDaemonRunning()) {
|
|
|
135
138
|
|
|
136
139
|
Returns `true` if `daemon.status` responds within 1 second.
|
|
137
140
|
|
|
141
|
+
## TypeScript SDK facade
|
|
142
|
+
|
|
143
|
+
The CLI is a human/debug surface. Product code and agents should prefer the
|
|
144
|
+
typed SDK facade, which validates params with Zod and calls the same daemon
|
|
145
|
+
methods directly.
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
import { cua } from '@lattices/sdk'
|
|
149
|
+
|
|
150
|
+
await cua.magicCursor({
|
|
151
|
+
app: 'Scout',
|
|
152
|
+
xRatio: 0.52,
|
|
153
|
+
yRatio: 0.91,
|
|
154
|
+
text: 'What are the most important docs in this project, and what would an agent say after reading them?',
|
|
155
|
+
treatment: 'execute',
|
|
156
|
+
trail: 'comet',
|
|
157
|
+
motion: 'rush',
|
|
158
|
+
trajectory: 'overshoot',
|
|
159
|
+
glow: 'halo',
|
|
160
|
+
idle: 'wiggle',
|
|
161
|
+
edge: 'ripple',
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
await cua.click({
|
|
165
|
+
app: 'Scout',
|
|
166
|
+
xRatio: 0.74,
|
|
167
|
+
yRatio: 0.95,
|
|
168
|
+
transport: 'ax',
|
|
169
|
+
axLabel: 'Send',
|
|
170
|
+
noFocus: true,
|
|
171
|
+
treatment: 'execute',
|
|
172
|
+
})
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
`@lattices/cli/cua` exposes the same CUA module for CLI-adjacent scripts, but
|
|
176
|
+
new app and agent code should use `@lattices/sdk` or `@lattices/sdk/cua` so the
|
|
177
|
+
import names the product surface instead of the CLI package.
|
|
178
|
+
|
|
138
179
|
### Error handling
|
|
139
180
|
|
|
140
181
|
`daemonCall` throws on errors — always wrap calls in try/catch:
|
|
141
182
|
|
|
142
183
|
```js
|
|
143
|
-
import { daemonCall } from '@
|
|
184
|
+
import { daemonCall } from '@lattices/cli'
|
|
144
185
|
|
|
145
186
|
try {
|
|
146
187
|
await daemonCall('session.launch', { path: '/nonexistent' })
|
|
@@ -157,12 +198,707 @@ try {
|
|
|
157
198
|
|
|
158
199
|
---
|
|
159
200
|
|
|
201
|
+
## Runs And Capture
|
|
202
|
+
|
|
203
|
+
Runs are local executions that produce trace events and artifacts. Capture
|
|
204
|
+
methods write into the Lattices run store under
|
|
205
|
+
`~/Library/Application Support/Lattices/Runs/`.
|
|
206
|
+
|
|
207
|
+
| Method | Type | Description |
|
|
208
|
+
|--------|------|-------------|
|
|
209
|
+
| `runs.create` | write | Create a run record and artifact directory |
|
|
210
|
+
| `runs.list` | read | List recent runs |
|
|
211
|
+
| `runs.get` | read | Inspect one run, including artifacts and trace events |
|
|
212
|
+
| `runs.artifacts` | read | List artifacts for one run |
|
|
213
|
+
| `capture.screenshotWindow` | write | Capture a window screenshot as a run artifact |
|
|
214
|
+
| `computer.prepare` | write | Resolve and optionally capture a terminal target without mutating it |
|
|
215
|
+
| `computer.focusWindow` | write | Resolve, capture, focus, and verify a target window |
|
|
216
|
+
| `computer.showCursor` | write | Show a visible cursor appearance and record it as a run |
|
|
217
|
+
| `computer.launchApp` | write | Launch or focus a normal macOS app and record the run |
|
|
218
|
+
| `computer.typeWindowText` | write | Type or paste into a normal app window, optionally after a click |
|
|
219
|
+
| `computer.click` | write | Stage or execute a window-relative click target; prefers no-focus `AXPress` in auto/ax transport |
|
|
220
|
+
| `computer.demoScout` | write | Scout warm-up run for memo/demo recording |
|
|
221
|
+
| `computer.typeText` | write | Insert text into a safe terminal using the least intrusive transport |
|
|
222
|
+
| `computer.demoTerminal` | write | Compatibility wrapper for a bounded terminal text action |
|
|
223
|
+
|
|
224
|
+
#### `capture.screenshotWindow`
|
|
225
|
+
|
|
226
|
+
Capture a window as a PNG artifact. If no target is provided, Lattices captures
|
|
227
|
+
the frontmost non-Lattices window.
|
|
228
|
+
|
|
229
|
+
**Params**:
|
|
230
|
+
|
|
231
|
+
| Field | Type | Required | Description |
|
|
232
|
+
|-------|------|----------|-------------|
|
|
233
|
+
| `wid` | uint32 | no | Target CGWindowID |
|
|
234
|
+
| `session` | string | no | Target lattices session |
|
|
235
|
+
| `app` | string | no | Target app name |
|
|
236
|
+
| `title` | string | no | Optional title filter for `app`, or run title |
|
|
237
|
+
| `runId` | string | no | Existing run to append to |
|
|
238
|
+
| `source` | string | no | Calling surface label |
|
|
239
|
+
| `filename` | string | no | Optional artifact filename |
|
|
240
|
+
|
|
241
|
+
```js
|
|
242
|
+
await daemonCall('capture.screenshotWindow', { source: 'agent' })
|
|
243
|
+
|
|
244
|
+
await daemonCall('capture.screenshotWindow', {
|
|
245
|
+
session: 'frontend-a1b2c3',
|
|
246
|
+
filename: 'before-layout.png'
|
|
247
|
+
})
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
CLI:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
lattices capture window
|
|
254
|
+
lattices runs
|
|
255
|
+
lattices runs run_20260617-120000_a1b2c3
|
|
256
|
+
lattices terminals
|
|
257
|
+
lattices terminals --refresh
|
|
258
|
+
lattices computer prepare --text "# hello" --treatment stage
|
|
259
|
+
lattices computer focus-window --wid 7258 --treatment present
|
|
260
|
+
lattices computer cursor --style marker --shape chevron --angle-deg -8 --label typing
|
|
261
|
+
lattices computer launch-app Scout
|
|
262
|
+
lattices computer scout --treatment present
|
|
263
|
+
lattices computer scout "Draft memo text" --execute
|
|
264
|
+
lattices computer type-window --app Scout --text "Draft memo text" --x-ratio .5 --y-ratio .86 --execute
|
|
265
|
+
lattices computer click --app Scout --x-ratio .5 --y-ratio .86 --execute
|
|
266
|
+
lattices cua click --app Scout --x-ratio .74 --y-ratio .95 --transport ax --ax-label Send --execute
|
|
267
|
+
lattices computer type-text --text "# hello from lattices"
|
|
268
|
+
lattices computer demo-terminal --dry-run
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
#### Computer Action Treatments
|
|
274
|
+
|
|
275
|
+
Computer-use endpoints accept a `treatment` field that controls how intrusive
|
|
276
|
+
the action may be:
|
|
277
|
+
|
|
278
|
+
| Treatment | Behavior |
|
|
279
|
+
|-----------|----------|
|
|
280
|
+
| `observe` | Resolve target and record a run, without focus or input |
|
|
281
|
+
| `stage` | Resolve target and stage intent/artifacts, without focus or input |
|
|
282
|
+
| `present` | Focus or present the target, without input |
|
|
283
|
+
| `execute` | Perform the action after safety checks |
|
|
284
|
+
|
|
285
|
+
The legacy `dryRun: true` flag maps to `stage`.
|
|
286
|
+
|
|
287
|
+
#### `computer.prepare`
|
|
288
|
+
|
|
289
|
+
Resolve and score terminal candidates for a future computer-use action. This is
|
|
290
|
+
the least intrusive endpoint: by default it observes the target and captures an
|
|
291
|
+
artifact, but it does not focus or type.
|
|
292
|
+
|
|
293
|
+
**Params**:
|
|
294
|
+
|
|
295
|
+
| Field | Type | Required | Description |
|
|
296
|
+
|-------|------|----------|-------------|
|
|
297
|
+
| `wid` | uint32 | no | Specific terminal window id |
|
|
298
|
+
| `tty` | string | no | Specific terminal TTY |
|
|
299
|
+
| `app` | string | no | Preferred terminal app, such as `iTerm2` |
|
|
300
|
+
| `text` | string | no | Text to stage in the run trace |
|
|
301
|
+
| `treatment` | string | no | `observe`, `stage`, `present`, or `execute` |
|
|
302
|
+
| `capture` | bool | no | Capture target screenshot artifact. Defaults to `true` |
|
|
303
|
+
| `source` | string | no | Calling surface label |
|
|
304
|
+
|
|
305
|
+
```js
|
|
306
|
+
await daemonCall('computer.prepare', {
|
|
307
|
+
text: '# review before typing',
|
|
308
|
+
treatment: 'stage'
|
|
309
|
+
})
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
#### `computer.focusWindow`
|
|
313
|
+
|
|
314
|
+
Resolve a target window, optionally capture it, focus it, and verify the focused
|
|
315
|
+
window id. Use `treatment: 'observe'` or `stage` to plan without presenting.
|
|
316
|
+
|
|
317
|
+
**Params**:
|
|
318
|
+
|
|
319
|
+
| Field | Type | Required | Description |
|
|
320
|
+
|-------|------|----------|-------------|
|
|
321
|
+
| `wid` | uint32 | no | Target window id |
|
|
322
|
+
| `session` | string | no | Target lattices session |
|
|
323
|
+
| `app` | string | no | Target app name |
|
|
324
|
+
| `title` | string | no | Optional title substring for `app` |
|
|
325
|
+
| `treatment` | string | no | `observe`, `stage`, `present`, or `execute` |
|
|
326
|
+
| `dryRun` | bool | no | Stage without focusing |
|
|
327
|
+
| `capture` | bool | no | Capture before/after artifacts. Defaults to `true` |
|
|
328
|
+
| `source` | string | no | Calling surface label |
|
|
329
|
+
|
|
330
|
+
```js
|
|
331
|
+
await daemonCall('computer.focusWindow', {
|
|
332
|
+
app: 'iTerm2',
|
|
333
|
+
treatment: 'present'
|
|
334
|
+
})
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
#### `computer.showCursor`
|
|
338
|
+
|
|
339
|
+
Resolve the current cursor location and show a visible cursor appearance. This
|
|
340
|
+
is the cursor equivalent of a typing action: it records a run, cursor target,
|
|
341
|
+
appearance parameters, and trace events. Use `observe` or `stage` to plan
|
|
342
|
+
without showing anything.
|
|
343
|
+
|
|
344
|
+
**Params**:
|
|
345
|
+
|
|
346
|
+
| Field | Type | Required | Description |
|
|
347
|
+
|-------|------|----------|-------------|
|
|
348
|
+
| `x` | double | no | Screen x coordinate. Defaults to current cursor |
|
|
349
|
+
| `y` | double | no | Screen y coordinate. Defaults to current cursor |
|
|
350
|
+
| `treatment` | string | no | `observe`, `stage`, `present`, or `execute` |
|
|
351
|
+
| `style` | string | no | `spotlight`, `pulse`, or `marker` |
|
|
352
|
+
| `appearance` | string | no | Alias for `style` |
|
|
353
|
+
| `shape` | string | no | Marker shape: `chevron`, `facet`, `shard`, `wedge`, `prism`, or `notch` |
|
|
354
|
+
| `angleDeg` | double | no | Marker rotation in degrees. Positive rotates visually clockwise; default is `-8` for marker |
|
|
355
|
+
| `size` | string | no | Marker size: `small`, `regular`, or `large`. Defaults to Settings |
|
|
356
|
+
| `color` | string | no | `blue`, `green`, `amber`, `pink`, `red`, or `white` |
|
|
357
|
+
| `durationMs` | int | no | Appearance duration in milliseconds |
|
|
358
|
+
| `label` | string | no | Optional marker label |
|
|
359
|
+
| `dryRun` | bool | no | Stage without showing |
|
|
360
|
+
| `source` | string | no | Calling surface label |
|
|
361
|
+
|
|
362
|
+
```js
|
|
363
|
+
await daemonCall('computer.showCursor', {
|
|
364
|
+
style: 'marker',
|
|
365
|
+
shape: 'chevron',
|
|
366
|
+
angleDeg: -8,
|
|
367
|
+
size: 'regular',
|
|
368
|
+
color: 'white',
|
|
369
|
+
treatment: 'present'
|
|
370
|
+
})
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
#### `computer.launchApp`
|
|
374
|
+
|
|
375
|
+
Launch or focus a normal macOS app and record the result as a run. Use
|
|
376
|
+
`dryRun: true` or `treatment: 'stage'` to plan without launching.
|
|
377
|
+
|
|
378
|
+
**Params**:
|
|
379
|
+
|
|
380
|
+
| Field | Type | Required | Description |
|
|
381
|
+
|-------|------|----------|-------------|
|
|
382
|
+
| `app` | string | yes | App name, such as `Scout`, `Slack`, or `Notes` |
|
|
383
|
+
| `bundleId` | string | no | Bundle identifier fallback for precise launch |
|
|
384
|
+
| `path` | string | no | Explicit `.app` bundle path |
|
|
385
|
+
| `title` | string | no | Optional title substring for app window selection |
|
|
386
|
+
| `treatment` | string | no | `observe`, `stage`, `present`, or `execute` |
|
|
387
|
+
| `dryRun` | bool | no | Stage without launching |
|
|
388
|
+
| `capture` | bool | no | Capture the launched app window. Defaults to `true` outside dry-run |
|
|
389
|
+
| `source` | string | no | Calling surface label |
|
|
390
|
+
|
|
391
|
+
```js
|
|
392
|
+
await daemonCall('computer.launchApp', {
|
|
393
|
+
app: 'Scout',
|
|
394
|
+
treatment: 'present'
|
|
395
|
+
})
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
#### `computer.typeWindowText`
|
|
399
|
+
|
|
400
|
+
Focus a normal app window and insert text. If click coordinates are provided,
|
|
401
|
+
Lattices clicks that target before typing. Coordinates can be absolute screen
|
|
402
|
+
points (`x`, `y`) or ratios inside the target window (`xRatio`, `yRatio`).
|
|
403
|
+
For window ratios, `0,0` is the top-left of the window and `1,1` is the
|
|
404
|
+
bottom-right.
|
|
405
|
+
|
|
406
|
+
**Params**:
|
|
407
|
+
|
|
408
|
+
| Field | Type | Required | Description |
|
|
409
|
+
|-------|------|----------|-------------|
|
|
410
|
+
| `wid` | uint32 | no | Target window id |
|
|
411
|
+
| `app` | string | no | Target app name |
|
|
412
|
+
| `title` | string | no | Optional title substring for app target |
|
|
413
|
+
| `text` | string | yes | Text to insert |
|
|
414
|
+
| `enter` | bool | no | Press Enter after typing. Defaults to `false` |
|
|
415
|
+
| `send` | bool | no | Alias for `enter` in chat-style demos |
|
|
416
|
+
| `x`, `y` | double | no | Absolute click point before typing |
|
|
417
|
+
| `xRatio`, `yRatio` | double | no | Window-relative click point before typing |
|
|
418
|
+
| `treatment` | string | no | `observe`, `stage`, `present`, or `execute` |
|
|
419
|
+
| `dryRun` | bool | no | Stage without typing |
|
|
420
|
+
| `capture` | bool | no | Capture before/after artifacts. Defaults to `true` |
|
|
421
|
+
| `source` | string | no | Calling surface label |
|
|
422
|
+
|
|
423
|
+
```js
|
|
424
|
+
await daemonCall('computer.typeWindowText', {
|
|
425
|
+
app: 'Scout',
|
|
426
|
+
text: 'Draft memo text',
|
|
427
|
+
xRatio: 0.5,
|
|
428
|
+
yRatio: 0.86,
|
|
429
|
+
treatment: 'execute'
|
|
430
|
+
})
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
#### `computer.click`
|
|
434
|
+
|
|
435
|
+
Stage or execute a click target. `stage` records the target without clicking.
|
|
436
|
+
In `execute`, `transport: "auto"` prefers `AXPress` on the resolved accessibility
|
|
437
|
+
button/control before falling back to a pointer click. Use `transport: "ax"` or
|
|
438
|
+
`noFocus: true` when the action must not focus the app or move the hardware
|
|
439
|
+
pointer. When a window target is provided, ratios are relative to that window.
|
|
440
|
+
|
|
441
|
+
**Params**:
|
|
442
|
+
|
|
443
|
+
| Field | Type | Required | Description |
|
|
444
|
+
|-------|------|----------|-------------|
|
|
445
|
+
| `wid` | uint32 | no | Target window id |
|
|
446
|
+
| `app` | string | no | Target app name |
|
|
447
|
+
| `title` | string | no | Optional title substring for app target |
|
|
448
|
+
| `x`, `y` | double | no | Absolute click point |
|
|
449
|
+
| `xRatio`, `yRatio` | double | no | Window-relative click point |
|
|
450
|
+
| `button` | string | no | `left` or `right`; defaults to `left` |
|
|
451
|
+
| `transport` | string | no | `auto`, `ax`, or `pointer`; defaults to `auto` |
|
|
452
|
+
| `axLabel` | string | no | Optional AX text/title hint, such as `Send` |
|
|
453
|
+
| `noFocus` | bool | no | Require no-focus AX execution; disable pointer fallback |
|
|
454
|
+
| `treatment` | string | no | `stage`, `present`, or `execute` |
|
|
455
|
+
| `dryRun` | bool | no | Stage without clicking |
|
|
456
|
+
| `capture` | bool | no | Capture before/after artifacts when targeting a window |
|
|
457
|
+
| `source` | string | no | Calling surface label |
|
|
458
|
+
|
|
459
|
+
```js
|
|
460
|
+
await daemonCall('computer.click', {
|
|
461
|
+
app: 'Scout',
|
|
462
|
+
xRatio: 0.5,
|
|
463
|
+
yRatio: 0.86,
|
|
464
|
+
treatment: 'execute'
|
|
465
|
+
})
|
|
466
|
+
|
|
467
|
+
await daemonCall('computer.click', {
|
|
468
|
+
app: 'Scout',
|
|
469
|
+
xRatio: 0.74,
|
|
470
|
+
yRatio: 0.95,
|
|
471
|
+
transport: 'ax',
|
|
472
|
+
axLabel: 'Send',
|
|
473
|
+
noFocus: true,
|
|
474
|
+
treatment: 'execute'
|
|
475
|
+
})
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
#### `computer.demoScout`
|
|
479
|
+
|
|
480
|
+
Warm up a Scout memo/demo recording run. In `present` mode it launches or
|
|
481
|
+
focuses Scout and records a run without typing. In `execute` mode it can click
|
|
482
|
+
the likely composer area, type a draft, and optionally press Enter when
|
|
483
|
+
`enter` or `send` is true. Dry-run/stage mode does not capture by default, so it
|
|
484
|
+
works before Screen Recording permission is granted.
|
|
485
|
+
|
|
486
|
+
**Params**:
|
|
487
|
+
|
|
488
|
+
| Field | Type | Required | Description |
|
|
489
|
+
|-------|------|----------|-------------|
|
|
490
|
+
| `app` | string | no | Scout app name override. Defaults to `Scout` |
|
|
491
|
+
| `title` | string | no | Optional title substring for the Scout window |
|
|
492
|
+
| `text` | string | no | Draft text to type in `execute` mode |
|
|
493
|
+
| `enter` | bool | no | Press Enter after typing. Defaults to `false` |
|
|
494
|
+
| `send` | bool | no | Alias for `enter` |
|
|
495
|
+
| `click` | bool | no | Click the likely composer area before typing |
|
|
496
|
+
| `xRatio`, `yRatio` | double | no | Composer click point; defaults to `0.5`, `0.86` |
|
|
497
|
+
| `treatment` | string | no | `observe`, `stage`, `present`, or `execute` |
|
|
498
|
+
| `dryRun` | bool | no | Stage without launching or typing |
|
|
499
|
+
| `capture` | bool | no | Capture before/after artifacts. Defaults to `true` outside dry-run |
|
|
500
|
+
| `source` | string | no | Calling surface label |
|
|
501
|
+
|
|
502
|
+
```js
|
|
503
|
+
await daemonCall('computer.demoScout', { dryRun: true })
|
|
504
|
+
|
|
505
|
+
await daemonCall('computer.demoScout', {
|
|
506
|
+
treatment: 'present',
|
|
507
|
+
capture: false
|
|
508
|
+
})
|
|
509
|
+
|
|
510
|
+
await daemonCall('computer.demoScout', {
|
|
511
|
+
text: 'Draft memo text',
|
|
512
|
+
treatment: 'execute',
|
|
513
|
+
send: false
|
|
514
|
+
})
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
#### `computer.typeText`
|
|
518
|
+
|
|
519
|
+
Resolve a terminal target and insert text after safety checks. Lattices prefers
|
|
520
|
+
the least intrusive available transport: tmux pane input when a tmux pane is
|
|
521
|
+
known, then target-pid key events/pasteboard insertion when window focus is
|
|
522
|
+
required. Enter is never pressed unless `enter: true` is provided.
|
|
523
|
+
|
|
524
|
+
**Params**:
|
|
525
|
+
|
|
526
|
+
| Field | Type | Required | Description |
|
|
527
|
+
|-------|------|----------|-------------|
|
|
528
|
+
| `wid` | uint32 | no | Specific terminal window id |
|
|
529
|
+
| `tty` | string | no | Specific terminal TTY |
|
|
530
|
+
| `app` | string | no | Preferred terminal app, such as `iTerm2` |
|
|
531
|
+
| `text` | string | yes | Text to insert |
|
|
532
|
+
| `enter` | bool | no | Press Enter after typing. Defaults to `false` |
|
|
533
|
+
| `treatment` | string | no | `observe`, `stage`, `present`, or `execute` |
|
|
534
|
+
| `transport` | string | no | `auto`, `tmux`, or `pasteboard`. Defaults to `auto` |
|
|
535
|
+
| `dryRun` | bool | no | Stage without typing |
|
|
536
|
+
| `capture` | bool | no | Capture before/after artifacts. Defaults to `true` |
|
|
537
|
+
| `source` | string | no | Calling surface label |
|
|
538
|
+
|
|
539
|
+
```js
|
|
540
|
+
await daemonCall('computer.typeText', {
|
|
541
|
+
text: '# hello from lattices',
|
|
542
|
+
transport: 'auto',
|
|
543
|
+
enter: false
|
|
544
|
+
})
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
#### `computer.demoTerminal`
|
|
548
|
+
|
|
549
|
+
Compatibility endpoint for the original terminal demo. It follows the same
|
|
550
|
+
treatment, safety, capture, and transport rules as `computer.typeText`, but
|
|
551
|
+
provides a default text payload when `text` is omitted.
|
|
552
|
+
|
|
553
|
+
Run a bounded computer-use sequence against a terminal window:
|
|
554
|
+
|
|
555
|
+
1. synthesize and score terminal candidates
|
|
556
|
+
2. choose a safe shell-like terminal unless `wid` or `tty` is supplied
|
|
557
|
+
3. capture a `before` screenshot artifact
|
|
558
|
+
4. focus the terminal window
|
|
559
|
+
5. insert text without pressing Enter by default
|
|
560
|
+
6. capture an `after` screenshot artifact
|
|
561
|
+
|
|
562
|
+
**Params**:
|
|
563
|
+
|
|
564
|
+
| Field | Type | Required | Description |
|
|
565
|
+
|-------|------|----------|-------------|
|
|
566
|
+
| `wid` | uint32 | no | Specific terminal window id |
|
|
567
|
+
| `tty` | string | no | Specific terminal TTY |
|
|
568
|
+
| `app` | string | no | Preferred terminal app, such as `iTerm2` |
|
|
569
|
+
| `text` | string | no | Text to insert |
|
|
570
|
+
| `enter` | bool | no | Press Enter after typing. Defaults to `false` |
|
|
571
|
+
| `treatment` | string | no | `observe`, `stage`, `present`, or `execute` |
|
|
572
|
+
| `transport` | string | no | `auto`, `tmux`, or `pasteboard`. Defaults to `auto` |
|
|
573
|
+
| `dryRun` | bool | no | Plan and capture without typing |
|
|
574
|
+
| `capture` | bool | no | Capture before/after artifacts. Defaults to `true` |
|
|
575
|
+
| `source` | string | no | Calling surface label |
|
|
576
|
+
|
|
577
|
+
```js
|
|
578
|
+
await daemonCall('computer.demoTerminal', { dryRun: true })
|
|
579
|
+
|
|
580
|
+
await daemonCall('computer.demoTerminal', {
|
|
581
|
+
app: 'iTerm2',
|
|
582
|
+
text: '# hello from lattices',
|
|
583
|
+
enter: false
|
|
584
|
+
})
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
---
|
|
588
|
+
|
|
589
|
+
## Overlay UI
|
|
590
|
+
|
|
591
|
+
The macOS app exposes a shared desktop overlay canvas for lightweight
|
|
592
|
+
agent-visible UI. Use `overlay.publish` for transient passive visuals,
|
|
593
|
+
and `overlay.actor.*` for persistent, movable actor surfaces.
|
|
594
|
+
|
|
595
|
+
Persistent actors are useful for representing agents or processes on the
|
|
596
|
+
desktop. Each actor has a stable `id`, can be moved independently through the
|
|
597
|
+
API, dragged by the user, hidden/restored with **Hyper+B**, and closed with
|
|
598
|
+
right-click. Click event callbacks and action surfaces are planned follow-on
|
|
599
|
+
capabilities.
|
|
600
|
+
|
|
601
|
+
| Method | Type | Description |
|
|
602
|
+
|--------|------|-------------|
|
|
603
|
+
| `overlay.publish` | write | Publish a transient toast, label, highlight, or pet layer |
|
|
604
|
+
| `overlay.clear` | write | Clear one overlay layer by id, or clear an owner namespace |
|
|
605
|
+
| `overlay.actor.publish` | write | Create or update a persistent generative overlay actor |
|
|
606
|
+
| `overlay.actor.moveTo` | write | Move an actor with app-owned easing |
|
|
607
|
+
| `overlay.actor.hud` | write | Attach, update, or clear a hover web HUD for an actor |
|
|
608
|
+
| `overlay.actor.visibility` | write | Show, hide, toggle, or inspect the sticky actor layer |
|
|
609
|
+
|
|
610
|
+
#### `overlay.publish`
|
|
611
|
+
|
|
612
|
+
Publish a transient layer on the screen overlay canvas.
|
|
613
|
+
|
|
614
|
+
**Params**:
|
|
615
|
+
|
|
616
|
+
| Field | Type | Required | Description |
|
|
617
|
+
|-------|------|----------|-------------|
|
|
618
|
+
| `kind` | string | yes | `toast`, `label`, `highlight`, or `pet` |
|
|
619
|
+
| `id` | string | no | Stable layer id; generated if omitted |
|
|
620
|
+
| `text` | string | no | Toast/label text or pet message fallback |
|
|
621
|
+
| `detail` | string | no | Secondary toast/label text |
|
|
622
|
+
| `message` | string | no | Pet message |
|
|
623
|
+
| `petId` | string | no | Bundled pet id from `apps/mac/Resources/Pets` |
|
|
624
|
+
| `state` | string | no | Pet animation state |
|
|
625
|
+
| `placement` | string | no | `top`, `bottom`, `center`, `cursor`, or `point` |
|
|
626
|
+
| `x`, `y` | double | no | Screen-local point for `point` placement |
|
|
627
|
+
| `w`, `h` | double | no | Highlight size |
|
|
628
|
+
| `ttlMs` | int | no | Time to live in milliseconds |
|
|
629
|
+
| `dismissible` | bool | no | Whether click-away dismissal removes the layer; defaults `true` |
|
|
630
|
+
|
|
631
|
+
Example:
|
|
632
|
+
|
|
633
|
+
```js
|
|
634
|
+
await daemonCall('overlay.publish', {
|
|
635
|
+
kind: 'highlight',
|
|
636
|
+
x: 160,
|
|
637
|
+
y: 120,
|
|
638
|
+
w: 480,
|
|
639
|
+
h: 260,
|
|
640
|
+
text: 'Needs review',
|
|
641
|
+
style: 'warning',
|
|
642
|
+
ttlMs: 3000
|
|
643
|
+
})
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
#### `overlay.actor.publish`
|
|
647
|
+
|
|
648
|
+
Create or update a generative overlay actor. Actors default to persistent:
|
|
649
|
+
omit `ttlMs` or pass `0`, and `dismissible` defaults to `false`.
|
|
650
|
+
|
|
651
|
+
**Params**:
|
|
652
|
+
|
|
653
|
+
| Field | Type | Required | Description |
|
|
654
|
+
|-------|------|----------|-------------|
|
|
655
|
+
| `id` | string | no | Stable actor id; generated if omitted |
|
|
656
|
+
| `renderer` | string | no | `sprite` is currently supported |
|
|
657
|
+
| `asset` | string | no | Bundled sprite asset id, such as `scout-ranger` |
|
|
658
|
+
| `state` | string | no | Actor state or animation name |
|
|
659
|
+
| `name` | string | no | Actor display name |
|
|
660
|
+
| `message` | string | no | Attached message text |
|
|
661
|
+
| `targetApp` | string | no | App name to activate when the actor is clicked |
|
|
662
|
+
| `targetBundleId` | string | no | Bundle identifier to activate when the actor is clicked |
|
|
663
|
+
| `targetAppPath` | string | no | `.app` bundle path to open when the actor is clicked |
|
|
664
|
+
| `scale` | double | no | Actor scale multiplier |
|
|
665
|
+
| `labelHidden` | bool | no | Hide the actor label/message |
|
|
666
|
+
| `closeOnActivate` | bool | no | Remove the actor after activating its target app |
|
|
667
|
+
| `hudUrl` | string | no | URL to render in a transparent hover HUD web view |
|
|
668
|
+
| `hudHTML` | string | no | Inline HTML to render in a transparent hover HUD web view |
|
|
669
|
+
| `hudWidth` | double | no | Hover HUD width |
|
|
670
|
+
| `hudHeight` | double | no | Hover HUD height |
|
|
671
|
+
| `hudReadAccess` | string | no | Local folder a file-backed HUD may read |
|
|
672
|
+
| `placement` | string | no | `top`, `bottom`, `center`, `cursor`, or `point` |
|
|
673
|
+
| `x`, `y` | double | no | Screen-local point for `point` placement |
|
|
674
|
+
| `ttlMs` | int | no | Time to live; `0` means persistent |
|
|
675
|
+
| `dismissible` | bool | no | Whether click-away dismissal removes the actor |
|
|
676
|
+
|
|
677
|
+
Bundled sprite assets:
|
|
678
|
+
|
|
679
|
+
| Asset | Notes |
|
|
680
|
+
|-------|-------|
|
|
681
|
+
| `assistant-spark` | Animated states include `idle`, `run_right`, `run_left`, `waving`, `jumping`, `failed`, `waiting`, `running`, and `review` |
|
|
682
|
+
| `scout-ranger` | Bundled sprite asset with default frame fallback |
|
|
683
|
+
|
|
684
|
+
Example:
|
|
685
|
+
|
|
686
|
+
```js
|
|
687
|
+
await daemonCall('overlay.actor.publish', {
|
|
688
|
+
id: 'agent-scout',
|
|
689
|
+
renderer: 'sprite',
|
|
690
|
+
asset: 'scout-ranger',
|
|
691
|
+
state: 'waiting',
|
|
692
|
+
name: 'Scout',
|
|
693
|
+
message: 'Waiting for feedback',
|
|
694
|
+
placement: 'point',
|
|
695
|
+
x: 640,
|
|
696
|
+
y: 320,
|
|
697
|
+
ttlMs: 0
|
|
698
|
+
})
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
#### `overlay.actor.moveTo`
|
|
702
|
+
|
|
703
|
+
Move an actor with app-owned animation. The app interpolates position and
|
|
704
|
+
switches directional sprite states while moving.
|
|
705
|
+
|
|
706
|
+
**Params**:
|
|
707
|
+
|
|
708
|
+
| Field | Type | Required | Description |
|
|
709
|
+
|-------|------|----------|-------------|
|
|
710
|
+
| `id` | string | yes | Actor id |
|
|
711
|
+
| `x`, `y` | double | yes | Target screen-local point |
|
|
712
|
+
| `durationMs` | int | no | Animation duration |
|
|
713
|
+
| `easing` | string | no | `linear`, `easeInOut`, or `spring` |
|
|
714
|
+
|
|
715
|
+
Example:
|
|
716
|
+
|
|
717
|
+
```js
|
|
718
|
+
await daemonCall('overlay.actor.moveTo', {
|
|
719
|
+
id: 'agent-scout',
|
|
720
|
+
x: 820,
|
|
721
|
+
y: 280,
|
|
722
|
+
durationMs: 800,
|
|
723
|
+
easing: 'spring'
|
|
724
|
+
})
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
#### `overlay.actor.hud`
|
|
728
|
+
|
|
729
|
+
Attach a transparent, blurred hover HUD to an actor. The HUD is backed by a
|
|
730
|
+
native `WKWebView`, so apps can point it at a local static HTML dashboard or,
|
|
731
|
+
in development, a local URL.
|
|
732
|
+
|
|
733
|
+
**Params**:
|
|
734
|
+
|
|
735
|
+
| Field | Type | Required | Description |
|
|
736
|
+
|-------|------|----------|-------------|
|
|
737
|
+
| `id` | string | yes | Actor id |
|
|
738
|
+
| `hudUrl` | string | no | URL or file path to render |
|
|
739
|
+
| `hudHTML` | string | no | Inline HTML to render instead of a URL |
|
|
740
|
+
| `hudTitle` | string | no | HUD title metadata |
|
|
741
|
+
| `hudWidth` | double | no | HUD width |
|
|
742
|
+
| `hudHeight` | double | no | HUD height |
|
|
743
|
+
| `hudReadAccess` | string | no | Local folder a file-backed HUD may read |
|
|
744
|
+
| `clear` | bool | no | Remove the actor HUD |
|
|
745
|
+
|
|
746
|
+
Example:
|
|
747
|
+
|
|
748
|
+
```js
|
|
749
|
+
await daemonCall('overlay.actor.hud', {
|
|
750
|
+
id: 'switch-talkie',
|
|
751
|
+
hudUrl: '/Users/you/dev/talkie/.lattices/hud/index.html',
|
|
752
|
+
hudReadAccess: '/Users/you/Library/Application Support/Talkie/HUD',
|
|
753
|
+
hudWidth: 380,
|
|
754
|
+
hudHeight: 260
|
|
755
|
+
})
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
#### `overlay.actor.visibility`
|
|
759
|
+
|
|
760
|
+
Show, hide, toggle, or inspect the persistent actor layer without destroying
|
|
761
|
+
the actors. This is the daemon equivalent of the app's **Hyper+B** shortcut.
|
|
762
|
+
|
|
763
|
+
**Params**:
|
|
764
|
+
|
|
765
|
+
| Field | Type | Required | Description |
|
|
766
|
+
|-------|------|----------|-------------|
|
|
767
|
+
| `action` | string | no | `show`, `hide`, `toggle`, or `status` |
|
|
768
|
+
| `visible` | bool | no | Set layer visibility directly |
|
|
769
|
+
| `hidden` | bool | no | Set layer hidden state directly |
|
|
770
|
+
| `feedback` | bool | no | Show a short desktop feedback toast |
|
|
771
|
+
|
|
772
|
+
Example:
|
|
773
|
+
|
|
774
|
+
```js
|
|
775
|
+
await daemonCall('overlay.actor.visibility', { action: 'toggle' })
|
|
776
|
+
```
|
|
777
|
+
|
|
778
|
+
### Static HUD Manifests
|
|
779
|
+
|
|
780
|
+
Apps and projects can expose a local hover dashboard without running a web
|
|
781
|
+
server by publishing a static bundle at:
|
|
782
|
+
|
|
783
|
+
```txt
|
|
784
|
+
.lattices/hud/
|
|
785
|
+
manifest.json
|
|
786
|
+
index.html
|
|
787
|
+
assets/
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
Minimal manifest:
|
|
791
|
+
|
|
792
|
+
```json
|
|
793
|
+
{
|
|
794
|
+
"version": 1,
|
|
795
|
+
"id": "talkie",
|
|
796
|
+
"name": "Talkie",
|
|
797
|
+
"bundleId": "com.usabletalkie.Talkie",
|
|
798
|
+
"icon": "./assets/icon.png",
|
|
799
|
+
"entry": "./index.html",
|
|
800
|
+
"readAccess": "~/Library/Application Support/Talkie/HUD",
|
|
801
|
+
"surface": { "width": 380, "height": 260 },
|
|
802
|
+
"actor": {
|
|
803
|
+
"labelHidden": true,
|
|
804
|
+
"click": "activateApp"
|
|
805
|
+
},
|
|
806
|
+
"sources": [
|
|
807
|
+
{
|
|
808
|
+
"path": "~/Library/Application Support/Talkie/HUD/activity.jsonl",
|
|
809
|
+
"format": "jsonl",
|
|
810
|
+
"schema": "talkie.activity.v1",
|
|
811
|
+
"presentation": "timeline"
|
|
812
|
+
}
|
|
813
|
+
]
|
|
814
|
+
}
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
The CLI resolves this manifest into `overlay.actor.publish` with a file-backed
|
|
818
|
+
HUD URL. The macOS app loads `entry` through `WKWebView.loadFileURL`, allowing
|
|
819
|
+
read access to the HUD folder by default, or to the manifest's `readAccess`
|
|
820
|
+
folder when one is declared.
|
|
821
|
+
|
|
822
|
+
`sources` is descriptive metadata for app-owned state, logs, or event streams.
|
|
823
|
+
Lattices does not append to those logs. The app writes them in its normal
|
|
824
|
+
runtime location, and the custom HUD renderer decides how to present them.
|
|
825
|
+
|
|
826
|
+
Useful commands:
|
|
827
|
+
|
|
828
|
+
```bash
|
|
829
|
+
lattices hud register .lattices/hud/manifest.json --publish
|
|
830
|
+
lattices hud publish talkie
|
|
831
|
+
lattices hud sync
|
|
832
|
+
lattices hud discover ~/dev --register
|
|
833
|
+
```
|
|
834
|
+
|
|
835
|
+
For packaged apps, keep the renderer files in the app bundle and point mutable
|
|
836
|
+
sources at an app-owned folder such as `~/Library/Application Support/...`.
|
|
837
|
+
|
|
838
|
+
---
|
|
839
|
+
|
|
160
840
|
## System
|
|
161
841
|
|
|
162
842
|
| Method | Type | Description |
|
|
163
843
|
|--------|------|-------------|
|
|
844
|
+
| `deck.manifest` | read | Shared companion deck manifest |
|
|
845
|
+
| `deck.snapshot` | read | Current companion deck runtime snapshot |
|
|
846
|
+
| `deck.perform` | write | Perform a companion deck action |
|
|
164
847
|
| `daemon.status` | read | Health check and stats |
|
|
165
848
|
| `api.schema` | read | Full API schema for self-discovery |
|
|
849
|
+
| `diagnostics.list` | read | Recent diagnostic entries |
|
|
850
|
+
|
|
851
|
+
#### `deck.manifest`
|
|
852
|
+
|
|
853
|
+
Return the shared `DeckKit` manifest exposed by the macOS app. This is
|
|
854
|
+
the contract a future Lattices companion can consume to discover pages,
|
|
855
|
+
capabilities, and security mode.
|
|
856
|
+
|
|
857
|
+
**Params**: none
|
|
858
|
+
|
|
859
|
+
#### `deck.snapshot`
|
|
860
|
+
|
|
861
|
+
Return the current `DeckKit` runtime snapshot for the macOS host.
|
|
862
|
+
|
|
863
|
+
**Params**: none
|
|
864
|
+
|
|
865
|
+
**Returns**: a `DeckRuntimeSnapshot` object containing:
|
|
866
|
+
|
|
867
|
+
- `voice`
|
|
868
|
+
- `desktop`
|
|
869
|
+
- `switcher`
|
|
870
|
+
- `history`
|
|
871
|
+
- `questions`
|
|
872
|
+
|
|
873
|
+
#### `deck.perform`
|
|
874
|
+
|
|
875
|
+
Perform a `DeckKit` action against the running macOS host and return a
|
|
876
|
+
`DeckActionResult`.
|
|
877
|
+
|
|
878
|
+
**Params**:
|
|
879
|
+
|
|
880
|
+
| Field | Type | Required | Description |
|
|
881
|
+
|-------|------|----------|-------------|
|
|
882
|
+
| `pageID` | string | no | Deck page ID |
|
|
883
|
+
| `actionID` | string | yes | Deck action identifier |
|
|
884
|
+
| `payload` | object | no | Deck action payload |
|
|
885
|
+
|
|
886
|
+
Example:
|
|
887
|
+
|
|
888
|
+
```json
|
|
889
|
+
{
|
|
890
|
+
"id": "1",
|
|
891
|
+
"method": "deck.perform",
|
|
892
|
+
"params": {
|
|
893
|
+
"pageID": "layout",
|
|
894
|
+
"actionID": "layout.optimize",
|
|
895
|
+
"payload": {
|
|
896
|
+
"strategy": "balanced",
|
|
897
|
+
"region": "right"
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
```
|
|
166
902
|
|
|
167
903
|
#### `daemon.status`
|
|
168
904
|
|
|
@@ -189,6 +925,84 @@ Useful for agent self-discovery.
|
|
|
189
925
|
|
|
190
926
|
**Params**: none
|
|
191
927
|
|
|
928
|
+
CLI shortcut:
|
|
929
|
+
|
|
930
|
+
```bash
|
|
931
|
+
lattices call api.schema
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
#### `diagnostics.list`
|
|
935
|
+
|
|
936
|
+
Return recent diagnostic log entries from the daemon.
|
|
937
|
+
|
|
938
|
+
**Params**:
|
|
939
|
+
|
|
940
|
+
| Field | Type | Required | Description |
|
|
941
|
+
|---------|--------|----------|--------------------------------|
|
|
942
|
+
| `limit` | number | no | Max entries to return (default 50) |
|
|
943
|
+
|
|
944
|
+
---
|
|
945
|
+
|
|
946
|
+
## Mouse & Input
|
|
947
|
+
|
|
948
|
+
| Method | Type | Description |
|
|
949
|
+
|--------|------|-------------|
|
|
950
|
+
| `mouse.find` | read | Show a sonar pulse at the current cursor |
|
|
951
|
+
| `mouse.summon` | write | Move the cursor to a point or screen center |
|
|
952
|
+
| `mouse.shortcuts.get` | read | Return the live mouse shortcut config |
|
|
953
|
+
| `mouse.shortcuts.reload` | write | Reload `~/.lattices/mouse-shortcuts.json` without restarting |
|
|
954
|
+
| `mouse.shortcuts.set` | write | Replace the full mouse shortcut config and activate it |
|
|
955
|
+
| `mouse.shortcuts.upsert` | write | Create or replace one mouse shortcut rule and activate it |
|
|
956
|
+
| `mouse.shortcuts.remove` | write | Remove one mouse shortcut rule and activate the new config |
|
|
957
|
+
| `mouse.shortcuts.restoreDefaults` | write | Restore default mouse shortcuts |
|
|
958
|
+
|
|
959
|
+
Mouse shortcut rules are data. Prefer `shortcut.send` for hotkeys an agent can
|
|
960
|
+
define or change directly; do not add a named action unless the behavior cannot
|
|
961
|
+
be expressed as data.
|
|
962
|
+
|
|
963
|
+
Create or replace a gesture that sends Hyper+D:
|
|
964
|
+
|
|
965
|
+
```js
|
|
966
|
+
await daemonCall('mouse.shortcuts.upsert', {
|
|
967
|
+
rule: {
|
|
968
|
+
id: 'middle-up-voice',
|
|
969
|
+
enabled: true,
|
|
970
|
+
device: 'any',
|
|
971
|
+
trigger: { button: 'middle', kind: 'drag', direction: 'up' },
|
|
972
|
+
action: {
|
|
973
|
+
type: 'shortcut.send',
|
|
974
|
+
shortcut: {
|
|
975
|
+
key: 'd',
|
|
976
|
+
keyCode: 2,
|
|
977
|
+
modifiers: ['control', 'option', 'shift', 'command']
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
})
|
|
982
|
+
```
|
|
983
|
+
|
|
984
|
+
If an agent edits `~/.lattices/mouse-shortcuts.json` itself, refresh the running
|
|
985
|
+
app explicitly:
|
|
986
|
+
|
|
987
|
+
```js
|
|
988
|
+
await daemonCall('mouse.shortcuts.reload')
|
|
989
|
+
```
|
|
990
|
+
|
|
991
|
+
All write methods persist the config, checkpoint the previous version in
|
|
992
|
+
`~/.lattices/mouse-shortcuts.history/`, and update the active event-tap snapshot
|
|
993
|
+
immediately. No app restart is required.
|
|
994
|
+
|
|
995
|
+
Supported action types:
|
|
996
|
+
|
|
997
|
+
| Type | Purpose |
|
|
998
|
+
|------|---------|
|
|
999
|
+
| `shortcut.send` | Send a data-defined key or keyCode with modifiers |
|
|
1000
|
+
| `app.activate` | Activate an app by name |
|
|
1001
|
+
| `space.previous` | Switch to the previous macOS Space |
|
|
1002
|
+
| `space.next` | Switch to the next macOS Space |
|
|
1003
|
+
| `screenmap.toggle` | Open the Screen Map overview |
|
|
1004
|
+
| `dictation.start` | Legacy alias that presses the configured Voice Command hotkey |
|
|
1005
|
+
|
|
192
1006
|
---
|
|
193
1007
|
|
|
194
1008
|
## Windows & Spaces
|
|
@@ -197,11 +1011,17 @@ Useful for agent self-discovery.
|
|
|
197
1011
|
|--------|------|-------------|
|
|
198
1012
|
| `windows.list` | read | All visible windows |
|
|
199
1013
|
| `windows.get` | read | Single window by ID |
|
|
1014
|
+
| `windows.search` | read | Search windows by query |
|
|
200
1015
|
| `spaces.list` | read | macOS display spaces |
|
|
201
|
-
| `window.
|
|
1016
|
+
| `window.place` | write | Place a window or session using a typed placement spec |
|
|
1017
|
+
| `window.tile` | write | Compatibility wrapper for session tiling |
|
|
202
1018
|
| `window.focus` | write | Focus a window / switch Spaces |
|
|
203
1019
|
| `window.move` | write | Move a window to another Space |
|
|
204
|
-
| `
|
|
1020
|
+
| `window.assignLayer` | write | Tag a window to a layer |
|
|
1021
|
+
| `window.removeLayer` | write | Remove a window's layer tag |
|
|
1022
|
+
| `window.layerMap` | read | All window→layer assignments |
|
|
1023
|
+
| `space.optimize` | write | Optimize a set of windows using an explicit scope and strategy |
|
|
1024
|
+
| `layout.distribute` | write | Compatibility wrapper for visible-window balancing |
|
|
205
1025
|
|
|
206
1026
|
#### `windows.list`
|
|
207
1027
|
|
|
@@ -221,7 +1041,8 @@ List all visible windows tracked by the desktop model.
|
|
|
221
1041
|
"frame": { "x": 0, "y": 25, "w": 960, "h": 1050 },
|
|
222
1042
|
"spaceIds": [1],
|
|
223
1043
|
"isOnScreen": true,
|
|
224
|
-
"latticesSession": "myapp-a1b2c3"
|
|
1044
|
+
"latticesSession": "myapp-a1b2c3",
|
|
1045
|
+
"layerTag": "web"
|
|
225
1046
|
}
|
|
226
1047
|
]
|
|
227
1048
|
```
|
|
@@ -229,6 +1050,9 @@ List all visible windows tracked by the desktop model.
|
|
|
229
1050
|
The `latticesSession` field is present only on windows that belong to
|
|
230
1051
|
a lattices session (matched via the `[lattices:name]` title tag).
|
|
231
1052
|
|
|
1053
|
+
The `layerTag` field is present when a window has been manually assigned
|
|
1054
|
+
to a layer via `window.assignLayer`.
|
|
1055
|
+
|
|
232
1056
|
#### `windows.get`
|
|
233
1057
|
|
|
234
1058
|
Get a single window by its CGWindowID.
|
|
@@ -242,6 +1066,56 @@ Get a single window by its CGWindowID.
|
|
|
242
1066
|
**Returns**: a single window object (same shape as `windows.list` items).
|
|
243
1067
|
**Errors**: `Not found` if the window ID doesn't exist.
|
|
244
1068
|
|
|
1069
|
+
#### `windows.search`
|
|
1070
|
+
|
|
1071
|
+
Search windows by text query across title, app name, session tags, and OCR content. Returns results with `matchSource` indicating how the match was found, and `ocrSnippet` for OCR matches.
|
|
1072
|
+
|
|
1073
|
+
**Params**:
|
|
1074
|
+
|
|
1075
|
+
| Field | Type | Required | Description |
|
|
1076
|
+
|---------|--------|----------|--------------------------------|
|
|
1077
|
+
| `query` | string | yes | Search query (matches title, app, session, OCR text) |
|
|
1078
|
+
| `ocr` | boolean| no | Include OCR text in search (default true) |
|
|
1079
|
+
| `limit` | number | no | Max results (default 50) |
|
|
1080
|
+
|
|
1081
|
+
**Returns**: array of window objects with additional search fields:
|
|
1082
|
+
|
|
1083
|
+
```json
|
|
1084
|
+
[
|
|
1085
|
+
{
|
|
1086
|
+
"wid": 265,
|
|
1087
|
+
"app": "iTerm2",
|
|
1088
|
+
"title": "✳ Claude Code",
|
|
1089
|
+
"matchSource": "ocr",
|
|
1090
|
+
"ocrSnippet": "…~/dev/vox StatusBarIconFolder…",
|
|
1091
|
+
"frame": { "x": 688, "y": 3, "w": 1720, "h": 720 },
|
|
1092
|
+
"isOnScreen": true
|
|
1093
|
+
}
|
|
1094
|
+
]
|
|
1095
|
+
```
|
|
1096
|
+
|
|
1097
|
+
`matchSource` values: `"title"`, `"app"`, `"session"`, `"ocr"`.
|
|
1098
|
+
|
|
1099
|
+
**CLI usage**:
|
|
1100
|
+
|
|
1101
|
+
```bash
|
|
1102
|
+
# Basic search (uses windows.search)
|
|
1103
|
+
lattices search vox
|
|
1104
|
+
|
|
1105
|
+
# Deep search — adds terminal tab/process inspection for ranking
|
|
1106
|
+
lattices search vox --deep
|
|
1107
|
+
|
|
1108
|
+
# Same as --deep (all search sources)
|
|
1109
|
+
lattices search vox --all
|
|
1110
|
+
|
|
1111
|
+
# Pipeable output
|
|
1112
|
+
lattices search vox --wid
|
|
1113
|
+
lattices search vox --json
|
|
1114
|
+
|
|
1115
|
+
# Search + focus + tile in one step
|
|
1116
|
+
lattices place vox right
|
|
1117
|
+
```
|
|
1118
|
+
|
|
245
1119
|
#### `spaces.list`
|
|
246
1120
|
|
|
247
1121
|
List macOS display spaces (virtual desktops).
|
|
@@ -264,20 +1138,55 @@ List macOS display spaces (virtual desktops).
|
|
|
264
1138
|
]
|
|
265
1139
|
```
|
|
266
1140
|
|
|
267
|
-
#### `window.
|
|
1141
|
+
#### `window.place`
|
|
268
1142
|
|
|
269
|
-
|
|
1143
|
+
Canonical window placement mutation. Use this when an agent needs a
|
|
1144
|
+
single, typed placement contract across voice, CLI, and daemon clients.
|
|
270
1145
|
|
|
271
1146
|
**Params**:
|
|
272
1147
|
|
|
273
|
-
| Field
|
|
274
|
-
|
|
275
|
-
| `
|
|
276
|
-
| `
|
|
1148
|
+
| Field | Type | Required | Description |
|
|
1149
|
+
|-------------|-----------------|----------|------------------------------------------|
|
|
1150
|
+
| `wid` | number | no | Target window ID |
|
|
1151
|
+
| `session` | string | no | Target lattices session |
|
|
1152
|
+
| `app` | string | no | Target app name |
|
|
1153
|
+
| `title` | string | no | Optional title substring for app matching |
|
|
1154
|
+
| `display` | number | no | Target display index |
|
|
1155
|
+
| `placement` | string \| object | yes | Placement shorthand or typed object |
|
|
1156
|
+
|
|
1157
|
+
Target resolution priority is `wid` → `session` → `app/title` → frontmost window.
|
|
277
1158
|
|
|
278
|
-
**
|
|
1159
|
+
**Placement strings**: `left`, `right`, `top`, `bottom`, `top-left`, `top-right`,
|
|
279
1160
|
`bottom-left`, `bottom-right`, `left-third`, `center-third`, `right-third`,
|
|
280
|
-
`
|
|
1161
|
+
`top-third`, `middle-third`, `bottom-third`, `left-quarter`, `right-quarter`,
|
|
1162
|
+
`top-quarter`, `bottom-quarter`, `maximize`, `center`, `grid:CxR:C,R`, or
|
|
1163
|
+
compact `CxR:C,R`. The canonical `grid:` form is 0-indexed; the compact form is
|
|
1164
|
+
1-indexed for command entry.
|
|
1165
|
+
|
|
1166
|
+
**Typed placement examples**:
|
|
1167
|
+
|
|
1168
|
+
```json
|
|
1169
|
+
{ "kind": "tile", "value": "top-right" }
|
|
1170
|
+
{ "kind": "grid", "columns": 3, "rows": 2, "column": 2, "row": 0 }
|
|
1171
|
+
{ "kind": "fractions", "x": 0.5, "y": 0, "w": 0.5, "h": 1 }
|
|
1172
|
+
```
|
|
1173
|
+
|
|
1174
|
+
**Returns**: execution receipt including resolved target, placement, and trace.
|
|
1175
|
+
|
|
1176
|
+
#### `window.tile`
|
|
1177
|
+
|
|
1178
|
+
Compatibility wrapper for `window.place` when the target is a lattices
|
|
1179
|
+
session window.
|
|
1180
|
+
|
|
1181
|
+
**Params**:
|
|
1182
|
+
|
|
1183
|
+
| Field | Type | Required | Description |
|
|
1184
|
+
|------------|--------|----------|-----------------------------------------|
|
|
1185
|
+
| `session` | string | yes | Session name |
|
|
1186
|
+
| `position` | string | yes | Placement shorthand or grid syntax |
|
|
1187
|
+
|
|
1188
|
+
This method exists for compatibility. New integrations should prefer
|
|
1189
|
+
`window.place`.
|
|
281
1190
|
|
|
282
1191
|
#### `window.focus`
|
|
283
1192
|
|
|
@@ -303,9 +1212,70 @@ Move a session's window to a different macOS Space.
|
|
|
303
1212
|
| `session` | string | yes | Session name |
|
|
304
1213
|
| `spaceId` | number | yes | Target Space ID (from `spaces.list`) |
|
|
305
1214
|
|
|
1215
|
+
#### `window.assignLayer`
|
|
1216
|
+
|
|
1217
|
+
Manually tag a window to a layer. Tagged windows are raised and tiled
|
|
1218
|
+
when that layer activates, even if they aren't declared in `workspace.json`.
|
|
1219
|
+
|
|
1220
|
+
**Params**:
|
|
1221
|
+
|
|
1222
|
+
| Field | Type | Required | Description |
|
|
1223
|
+
|---------|--------|----------|--------------------------------|
|
|
1224
|
+
| `wid` | number | yes | CGWindowID |
|
|
1225
|
+
| `layer` | string | yes | Layer ID to assign |
|
|
1226
|
+
|
|
1227
|
+
#### `window.removeLayer`
|
|
1228
|
+
|
|
1229
|
+
Remove a window's layer tag.
|
|
1230
|
+
|
|
1231
|
+
**Params**:
|
|
1232
|
+
|
|
1233
|
+
| Field | Type | Required | Description |
|
|
1234
|
+
|-------|--------|----------|----------------|
|
|
1235
|
+
| `wid` | number | yes | CGWindowID |
|
|
1236
|
+
|
|
1237
|
+
#### `window.layerMap`
|
|
1238
|
+
|
|
1239
|
+
Return all current window→layer assignments.
|
|
1240
|
+
|
|
1241
|
+
**Params**: none
|
|
1242
|
+
|
|
1243
|
+
**Returns**:
|
|
1244
|
+
|
|
1245
|
+
```json
|
|
1246
|
+
{
|
|
1247
|
+
"1234": "web",
|
|
1248
|
+
"5678": "mobile"
|
|
1249
|
+
}
|
|
1250
|
+
```
|
|
1251
|
+
|
|
1252
|
+
Keys are CGWindowIDs (as strings), values are layer IDs.
|
|
1253
|
+
|
|
1254
|
+
#### `space.optimize`
|
|
1255
|
+
|
|
1256
|
+
Canonical space-balancing mutation. Use this when the goal is to make
|
|
1257
|
+
the current workspace coherent rather than placing one specific window.
|
|
1258
|
+
|
|
1259
|
+
**Params**:
|
|
1260
|
+
|
|
1261
|
+
| Field | Type | Required | Description |
|
|
1262
|
+
|-------------|----------|----------|-----------------------------------------------------|
|
|
1263
|
+
| `scope` | string | no | `visible`, `active-app`, `app`, or `selection` |
|
|
1264
|
+
| `strategy` | string | no | `balanced` or `mosaic` |
|
|
1265
|
+
| `app` | string | no | App name for `app` scope |
|
|
1266
|
+
| `title` | string | no | Optional title substring for app matching |
|
|
1267
|
+
| `windowIds` | number[] | no | Explicit window IDs for `selection` scope |
|
|
1268
|
+
|
|
1269
|
+
If `windowIds` is provided, scope is inferred as `selection`.
|
|
1270
|
+
If `app` is provided and `scope` is omitted, scope is inferred as `app`.
|
|
1271
|
+
|
|
1272
|
+
**Returns**: execution receipt including resolved scope, strategy,
|
|
1273
|
+
affected window IDs, and trace.
|
|
1274
|
+
|
|
306
1275
|
#### `layout.distribute`
|
|
307
1276
|
|
|
308
|
-
|
|
1277
|
+
Compatibility wrapper for `space.optimize` with `scope=visible` and
|
|
1278
|
+
`strategy=balanced`.
|
|
309
1279
|
|
|
310
1280
|
**Params**: none
|
|
311
1281
|
|
|
@@ -440,7 +1410,8 @@ Restart a specific pane's process within a session.
|
|
|
440
1410
|
| `projects.list` | read | Discovered projects |
|
|
441
1411
|
| `projects.scan` | write | Re-scan project directory |
|
|
442
1412
|
| `layers.list` | read | Workspace layers and active index |
|
|
443
|
-
| `layer.
|
|
1413
|
+
| `layer.activate` | write | Activate a workspace layer using an explicit mode |
|
|
1414
|
+
| `layer.switch` | write | Compatibility wrapper for launch-style layer activation |
|
|
444
1415
|
| `group.launch` | write | Launch a tab group |
|
|
445
1416
|
| `group.kill` | write | Kill a tab group |
|
|
446
1417
|
|
|
@@ -497,17 +1468,33 @@ List configured workspace layers and the active index.
|
|
|
497
1468
|
|
|
498
1469
|
Returns empty `layers` array if no workspace config is loaded.
|
|
499
1470
|
|
|
500
|
-
#### `layer.
|
|
1471
|
+
#### `layer.activate`
|
|
501
1472
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
a `layer.switched` event.
|
|
1473
|
+
Canonical layer mutation. Use this when an agent wants an explicit
|
|
1474
|
+
activation mode instead of implicit "switch" behavior.
|
|
505
1475
|
|
|
506
1476
|
**Params**:
|
|
507
1477
|
|
|
508
|
-
| Field | Type | Required | Description
|
|
509
|
-
|
|
510
|
-
| `index` | number |
|
|
1478
|
+
| Field | Type | Required | Description |
|
|
1479
|
+
|---------|--------|----------|---------------------------------------------|
|
|
1480
|
+
| `index` | number | no | Layer index (0-based) |
|
|
1481
|
+
| `name` | string | no | Layer ID or label |
|
|
1482
|
+
| `mode` | string | no | `launch`, `focus`, or `retile` |
|
|
1483
|
+
|
|
1484
|
+
Provide either `index` or `name`.
|
|
1485
|
+
|
|
1486
|
+
**Modes**:
|
|
1487
|
+
|
|
1488
|
+
- `launch` — bring up the layer, launching missing projects and retiling
|
|
1489
|
+
- `focus` — raise the layer's windows in place
|
|
1490
|
+
- `retile` — re-apply the layer layout without launch semantics
|
|
1491
|
+
|
|
1492
|
+
**Returns**: execution receipt including resolved layer, mode, and trace.
|
|
1493
|
+
|
|
1494
|
+
#### `layer.switch`
|
|
1495
|
+
|
|
1496
|
+
Compatibility wrapper for `layer.activate` with `mode=launch`.
|
|
1497
|
+
It keeps the old semantics and still posts a `layer.switched` event.
|
|
511
1498
|
|
|
512
1499
|
#### `group.launch`
|
|
513
1500
|
|
|
@@ -589,7 +1576,7 @@ List all discovered terminal instances with their processes, tabs, and tmux asso
|
|
|
589
1576
|
|
|
590
1577
|
| Field | Type | Required | Description |
|
|
591
1578
|
|-----------|---------|----------|--------------------------------------|
|
|
592
|
-
| `refresh` | boolean | no |
|
|
1579
|
+
| `refresh` | boolean | no | Explicitly refresh terminal-tab metadata through terminal app scripting |
|
|
593
1580
|
|
|
594
1581
|
**Returns**: array of terminal instance objects:
|
|
595
1582
|
|
|
@@ -734,7 +1721,7 @@ They have no `id` field — listen for messages with an `event` field.
|
|
|
734
1721
|
#### `layer.switched`
|
|
735
1722
|
|
|
736
1723
|
```json
|
|
737
|
-
{ "event": "layer.switched", "data": { "index": 1 } }
|
|
1724
|
+
{ "event": "layer.switched", "data": { "index": 1, "name": "mobile" } }
|
|
738
1725
|
```
|
|
739
1726
|
|
|
740
1727
|
#### `ocr.scanComplete`
|
|
@@ -764,16 +1751,23 @@ project knows how to control the workspace:
|
|
|
764
1751
|
This project uses lattices for workspace management. The daemon API
|
|
765
1752
|
is available at ws://127.0.0.1:9399.
|
|
766
1753
|
|
|
767
|
-
###
|
|
768
|
-
-
|
|
769
|
-
|
|
1754
|
+
### Search (find windows)
|
|
1755
|
+
- Search by content: `daemonCall('windows.search', { query: 'myproject' })`
|
|
1756
|
+
Returns windows with `matchSource` ("title", "app", "session", "ocr") and `ocrSnippet`
|
|
1757
|
+
- Search terminals: `daemonCall('terminals.search', {})` — tabs, cwds, processes
|
|
1758
|
+
- CLI: `lattices search myproject`, `lattices search myproject --deep`, or `lattices search myproject --all` (same as `--deep`)
|
|
1759
|
+
|
|
1760
|
+
### Actions
|
|
1761
|
+
- Focus a window: `daemonCall('window.focus', { wid: 1234 })`
|
|
1762
|
+
- Place a window: `daemonCall('window.place', { session: 'name', placement: 'left' })`
|
|
770
1763
|
- Launch a project: `daemonCall('session.launch', { path: '/absolute/path' })`
|
|
771
|
-
-
|
|
772
|
-
-
|
|
1764
|
+
- Activate a layer: `daemonCall('layer.activate', { name: 'web', mode: 'launch' })`
|
|
1765
|
+
- Optimize the workspace: `daemonCall('space.optimize', { scope: 'visible', strategy: 'balanced' })`
|
|
1766
|
+
- CLI: `lattices place myproject left` (search + focus + tile in one step)
|
|
773
1767
|
|
|
774
1768
|
### Import
|
|
775
1769
|
\```js
|
|
776
|
-
import { daemonCall } from '@
|
|
1770
|
+
import { daemonCall } from '@lattices/cli'
|
|
777
1771
|
\```
|
|
778
1772
|
```
|
|
779
1773
|
|
|
@@ -782,7 +1776,7 @@ import { daemonCall } from '@arach/lattices/daemon-client'
|
|
|
782
1776
|
An orchestrator agent can set up the full workspace for sub-agents:
|
|
783
1777
|
|
|
784
1778
|
```js
|
|
785
|
-
import { daemonCall } from '@
|
|
1779
|
+
import { daemonCall } from '@lattices/cli'
|
|
786
1780
|
|
|
787
1781
|
// Discover what's available
|
|
788
1782
|
const projects = await daemonCall('projects.list')
|
|
@@ -796,8 +1790,8 @@ const sessions = await daemonCall('tmux.sessions')
|
|
|
796
1790
|
const fe = sessions.find(s => s.name.startsWith('frontend'))
|
|
797
1791
|
const api = sessions.find(s => s.name.startsWith('api'))
|
|
798
1792
|
|
|
799
|
-
await daemonCall('window.
|
|
800
|
-
await daemonCall('window.
|
|
1793
|
+
await daemonCall('window.place', { session: fe.name, placement: 'left' })
|
|
1794
|
+
await daemonCall('window.place', { session: api.name, placement: 'right' })
|
|
801
1795
|
```
|
|
802
1796
|
|
|
803
1797
|
### Reactive event pattern
|
|
@@ -836,7 +1830,7 @@ ws.on('open', () => {
|
|
|
836
1830
|
Always verify the daemon is running before making calls:
|
|
837
1831
|
|
|
838
1832
|
```js
|
|
839
|
-
import { isDaemonRunning, daemonCall } from '@
|
|
1833
|
+
import { isDaemonRunning, daemonCall } from '@lattices/cli'
|
|
840
1834
|
|
|
841
1835
|
if (!(await isDaemonRunning())) {
|
|
842
1836
|
console.error('lattices daemon is not running — start it with: lattices app')
|