@lattices/cli 0.3.0 → 0.4.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/README.md +85 -9
- package/app/Info.plist +30 -0
- package/app/Lattices.app/Contents/Info.plist +8 -2
- package/app/Lattices.app/Contents/MacOS/Lattices +0 -0
- package/app/Lattices.app/Contents/Resources/AppIcon.icns +0 -0
- package/app/Lattices.app/Contents/Resources/tap.wav +0 -0
- package/app/Lattices.app/Contents/_CodeSignature/CodeResources +139 -0
- package/app/Lattices.entitlements +15 -0
- package/app/Package.swift +8 -1
- package/app/Resources/tap.wav +0 -0
- package/app/Sources/AdvisorLearningStore.swift +90 -0
- package/app/Sources/AgentSession.swift +377 -0
- package/app/Sources/AppDelegate.swift +45 -12
- package/app/Sources/AppShellView.swift +81 -8
- package/app/Sources/AudioProvider.swift +386 -0
- package/app/Sources/CheatSheetHUD.swift +261 -19
- package/app/Sources/DaemonProtocol.swift +13 -0
- package/app/Sources/DaemonServer.swift +8 -0
- package/app/Sources/DesktopModel.swift +189 -6
- package/app/Sources/DesktopModelTypes.swift +2 -0
- package/app/Sources/DiagnosticLog.swift +104 -2
- package/app/Sources/EventBus.swift +1 -0
- package/app/Sources/HUDBottomBar.swift +279 -0
- package/app/Sources/HUDController.swift +1158 -0
- package/app/Sources/HUDLeftBar.swift +849 -0
- package/app/Sources/HUDMinimap.swift +179 -0
- package/app/Sources/HUDRightBar.swift +774 -0
- package/app/Sources/HUDState.swift +367 -0
- package/app/Sources/HUDTopBar.swift +243 -0
- package/app/Sources/HandsOffSession.swift +802 -0
- package/app/Sources/HomeDashboardView.swift +125 -0
- package/app/Sources/HotkeyManager.swift +2 -0
- package/app/Sources/HotkeyStore.swift +49 -9
- package/app/Sources/IntentEngine.swift +962 -0
- package/app/Sources/Intents/CreateLayerIntent.swift +54 -0
- package/app/Sources/Intents/DistributeIntent.swift +56 -0
- package/app/Sources/Intents/FocusIntent.swift +69 -0
- package/app/Sources/Intents/HelpIntent.swift +41 -0
- package/app/Sources/Intents/KillIntent.swift +47 -0
- package/app/Sources/Intents/LatticeIntent.swift +78 -0
- package/app/Sources/Intents/LaunchIntent.swift +67 -0
- package/app/Sources/Intents/ListSessionsIntent.swift +32 -0
- package/app/Sources/Intents/ListWindowsIntent.swift +30 -0
- package/app/Sources/Intents/ScanIntent.swift +52 -0
- package/app/Sources/Intents/SearchIntent.swift +190 -0
- package/app/Sources/Intents/SwitchLayerIntent.swift +50 -0
- package/app/Sources/Intents/TileIntent.swift +61 -0
- package/app/Sources/LatticesApi.swift +1275 -30
- package/app/Sources/LauncherHUD.swift +348 -0
- package/app/Sources/MainView.swift +147 -44
- package/app/Sources/MouseFinder.swift +222 -0
- package/app/Sources/OcrModel.swift +34 -1
- package/app/Sources/OmniSearchState.swift +99 -102
- package/app/Sources/OnboardingView.swift +457 -0
- package/app/Sources/PermissionChecker.swift +2 -12
- package/app/Sources/PiChatDock.swift +454 -0
- package/app/Sources/PiChatSession.swift +815 -0
- package/app/Sources/PiWorkspaceView.swift +364 -0
- package/app/Sources/PlacementSpec.swift +195 -0
- package/app/Sources/Preferences.swift +59 -0
- package/app/Sources/ProjectScanner.swift +58 -45
- package/app/Sources/ScreenMapState.swift +701 -55
- package/app/Sources/ScreenMapView.swift +843 -103
- package/app/Sources/ScreenMapWindowController.swift +22 -0
- package/app/Sources/SessionLayerStore.swift +285 -0
- package/app/Sources/SessionManager.swift +4 -1
- package/app/Sources/SettingsView.swift +186 -3
- package/app/Sources/Theme.swift +9 -8
- package/app/Sources/TmuxModel.swift +7 -0
- package/app/Sources/TmuxQuery.swift +27 -3
- package/app/Sources/VoiceChatView.swift +192 -0
- package/app/Sources/VoiceCommandWindow.swift +1594 -0
- package/app/Sources/VoiceIntentResolver.swift +671 -0
- package/app/Sources/VoxClient.swift +454 -0
- package/app/Sources/WindowTiler.swift +348 -87
- package/app/Sources/WorkspaceManager.swift +127 -18
- package/app/Tests/StageDragTests.swift +333 -0
- package/app/Tests/StageJoinTests.swift +313 -0
- package/app/Tests/StageManagerTests.swift +280 -0
- package/app/Tests/StageTileTests.swift +353 -0
- package/assets/AppIcon.icns +0 -0
- package/bin/client.ts +16 -0
- package/bin/{daemon-client.js → daemon-client.ts} +49 -30
- package/bin/handsoff-infer.ts +280 -0
- package/bin/handsoff-worker.ts +740 -0
- package/bin/lattices-app.ts +338 -0
- package/bin/lattices-dev +208 -0
- package/bin/{lattices.js → lattices.ts} +777 -140
- 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 +142 -0
- package/docs/api.md +153 -34
- package/docs/app.md +29 -1
- package/docs/config.md +5 -1
- package/docs/handsoff-test-scenarios.md +84 -0
- package/docs/layers.md +20 -20
- package/docs/ocr.md +14 -5
- package/docs/overview.md +5 -1
- package/docs/presentation-execution-review.md +491 -0
- package/docs/prompts/hands-off-system.md +374 -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/tiling-reference.md +167 -0
- package/docs/twins.md +138 -0
- package/docs/voice-command-protocol.md +278 -0
- package/docs/voice.md +219 -0
- package/package.json +29 -11
- package/bin/client.js +0 -4
- package/bin/lattices-app.js +0 -221
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Agent Guide: Generating Layers
|
|
2
|
+
|
|
3
|
+
How to create and manage Lattices workspace layers programmatically. This guide is for AI agents (Claude Code, etc.) that want to generate layers from high-level user descriptions.
|
|
4
|
+
|
|
5
|
+
## Quick Reference
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# See what's on screen
|
|
9
|
+
lattices windows --json
|
|
10
|
+
|
|
11
|
+
# Create a layer with tiling
|
|
12
|
+
lattices layer create "Design" --json '[
|
|
13
|
+
{"app": "Figma", "tile": "left"},
|
|
14
|
+
{"app": "Google Chrome", "title": "Tailwind", "tile": "right"}
|
|
15
|
+
]'
|
|
16
|
+
|
|
17
|
+
# Snapshot current windows as a layer
|
|
18
|
+
lattices layer snap "my-context"
|
|
19
|
+
|
|
20
|
+
# List / switch / delete session layers
|
|
21
|
+
lattices layer session
|
|
22
|
+
lattices layer session "Design"
|
|
23
|
+
lattices layer delete "Design"
|
|
24
|
+
lattices layer clear
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## How It Works
|
|
28
|
+
|
|
29
|
+
There are two kinds of layers:
|
|
30
|
+
|
|
31
|
+
| Type | Storage | Requires restart? | How to create |
|
|
32
|
+
|------|---------|-------------------|---------------|
|
|
33
|
+
| **Config layers** | `~/.lattices/workspace.json` | Yes (or refresh) | Edit JSON file |
|
|
34
|
+
| **Session layers** | In-memory (daemon) | No | CLI or daemon API |
|
|
35
|
+
|
|
36
|
+
**Session layers are what you want.** They're created via TypeScript CLI commands, take effect immediately, and don't require restarting anything.
|
|
37
|
+
|
|
38
|
+
## Step-by-Step: Generating a Layer
|
|
39
|
+
|
|
40
|
+
### 1. Discover what's available
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
lattices windows --json
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Returns an array of window objects:
|
|
47
|
+
```json
|
|
48
|
+
[
|
|
49
|
+
{
|
|
50
|
+
"wid": 1234,
|
|
51
|
+
"app": "iTerm2",
|
|
52
|
+
"title": "lattices — zsh",
|
|
53
|
+
"latticesSession": "lattices-abc123",
|
|
54
|
+
"frame": { "x": 0, "y": 25, "w": 960, "h": 1050 },
|
|
55
|
+
"spaceIds": [1]
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"wid": 5678,
|
|
59
|
+
"app": "Google Chrome",
|
|
60
|
+
"title": "GitHub - arach/lattices",
|
|
61
|
+
"frame": { "x": 960, "y": 25, "w": 960, "h": 1050 },
|
|
62
|
+
"spaceIds": [1]
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Key fields for matching:
|
|
68
|
+
- `wid` — unique window ID (most precise)
|
|
69
|
+
- `app` — application name
|
|
70
|
+
- `title` — window title (use for disambiguation when multiple windows of same app)
|
|
71
|
+
- `latticesSession` — tmux session name (for terminal windows)
|
|
72
|
+
|
|
73
|
+
### 2. Decide on a layout
|
|
74
|
+
|
|
75
|
+
Pick tile positions based on how many windows and what makes sense:
|
|
76
|
+
|
|
77
|
+
| Windows | Good layout | Tile values |
|
|
78
|
+
|---------|-------------|-------------|
|
|
79
|
+
| 2 | Side by side | `left`, `right` |
|
|
80
|
+
| 2 | Stacked | `top`, `bottom` |
|
|
81
|
+
| 3 | Main + sidebar | `left` (60%), `top-right`, `bottom-right` |
|
|
82
|
+
| 3 | Columns | `left-third`, `center-third`, `right-third` |
|
|
83
|
+
| 4 | Quadrants | `top-left`, `top-right`, `bottom-left`, `bottom-right` |
|
|
84
|
+
| 1 | Focused | `maximize` or `center` |
|
|
85
|
+
|
|
86
|
+
Full position reference:
|
|
87
|
+
- **Halves**: `left`, `right`, `top`, `bottom`
|
|
88
|
+
- **Quarters**: `top-left`, `top-right`, `bottom-left`, `bottom-right`
|
|
89
|
+
- **Thirds**: `left-third`, `center-third`, `right-third`
|
|
90
|
+
- **Sixths**: `top-left-third`, `top-center-third`, `top-right-third`, `bottom-left-third`, `bottom-center-third`, `bottom-right-third`
|
|
91
|
+
- **Fourths**: `first-fourth`, `second-fourth`, `third-fourth`, `last-fourth`
|
|
92
|
+
- **Special**: `maximize`, `center`
|
|
93
|
+
- **Custom grid**: `grid:CxR:C,R` (e.g. `grid:5x3:2,1`)
|
|
94
|
+
|
|
95
|
+
### 3. Create the layer
|
|
96
|
+
|
|
97
|
+
**Option A: By window ID (most reliable)**
|
|
98
|
+
```bash
|
|
99
|
+
lattices layer create "Coding" --json '[
|
|
100
|
+
{"wid": 1234, "tile": "left"},
|
|
101
|
+
{"wid": 5678, "tile": "right"}
|
|
102
|
+
]'
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Option B: By app name (survives window recreation)**
|
|
106
|
+
```bash
|
|
107
|
+
lattices layer create "Research" --json '[
|
|
108
|
+
{"app": "Google Chrome", "title": "docs", "tile": "left"},
|
|
109
|
+
{"app": "Notes", "tile": "right"}
|
|
110
|
+
]'
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Option C: Simple wid list (no tiling)**
|
|
114
|
+
```bash
|
|
115
|
+
lattices layer create "Focus" wid:1234 wid:5678
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Option D: Snapshot everything visible**
|
|
119
|
+
```bash
|
|
120
|
+
lattices layer snap "Current Context"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### 4. Switch between layers
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
lattices layer session # list all session layers
|
|
127
|
+
lattices layer session "Coding" # switch to "Coding"
|
|
128
|
+
lattices layer session 0 # switch by index
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Daemon API (Advanced)
|
|
132
|
+
|
|
133
|
+
For finer control, use raw daemon calls:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Create layer with window IDs
|
|
137
|
+
lattices call session.layers.create '{"name":"Coding","windowIds":[1234,5678]}'
|
|
138
|
+
|
|
139
|
+
# Create layer with app references
|
|
140
|
+
lattices call session.layers.create '{"name":"Design","windows":[{"app":"Figma"},{"app":"Google Chrome","contentHint":"Tailwind"}]}'
|
|
141
|
+
|
|
142
|
+
# Tile a specific window
|
|
143
|
+
lattices call window.place '{"wid":1234,"placement":"left"}'
|
|
144
|
+
|
|
145
|
+
# Switch layer
|
|
146
|
+
lattices call session.layers.switch '{"name":"Coding"}'
|
|
147
|
+
|
|
148
|
+
# List session layers
|
|
149
|
+
lattices call session.layers.list
|
|
150
|
+
|
|
151
|
+
# Delete
|
|
152
|
+
lattices call session.layers.delete '{"name":"old-layer"}'
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Composing Layers from Intent
|
|
156
|
+
|
|
157
|
+
When a user says something high-level, here's how to think about it:
|
|
158
|
+
|
|
159
|
+
### "Make me a coding layer"
|
|
160
|
+
1. Find terminal windows (iTerm2, Terminal, Warp, etc.)
|
|
161
|
+
2. Find browser windows with dev-related titles (GitHub, docs, localhost)
|
|
162
|
+
3. Main editor/terminal on `left`, reference material on `right`
|
|
163
|
+
|
|
164
|
+
### "Set up a design layer"
|
|
165
|
+
1. Find design tools (Figma, Sketch, Adobe XD)
|
|
166
|
+
2. Find browser windows with design references
|
|
167
|
+
3. Design tool `left` (or `maximize`), references `right`
|
|
168
|
+
|
|
169
|
+
### "Create a writing layer"
|
|
170
|
+
1. Find text editors, notes apps (Notes, Obsidian, iA Writer, VS Code with .md)
|
|
171
|
+
2. Find research/reference windows
|
|
172
|
+
3. Writing app `left` or `center`, references `right`
|
|
173
|
+
|
|
174
|
+
### "Give me a communication layer"
|
|
175
|
+
1. Find messaging apps (Slack, Discord, Messages)
|
|
176
|
+
2. Find email (Mail, Gmail in browser)
|
|
177
|
+
3. Arrange by priority — primary tool `left`, secondary `right`
|
|
178
|
+
|
|
179
|
+
### "Split my work into layers by project"
|
|
180
|
+
1. Group windows by project (match on title keywords, session names, or app)
|
|
181
|
+
2. Create one layer per project group
|
|
182
|
+
3. Use the 3-window layout pattern: main `left`, support `top-right`, `bottom-right`
|
|
183
|
+
|
|
184
|
+
## App Grouping Heuristics
|
|
185
|
+
|
|
186
|
+
When deciding which windows go together:
|
|
187
|
+
|
|
188
|
+
| Category | Common apps | Goes well with |
|
|
189
|
+
|----------|-------------|----------------|
|
|
190
|
+
| **Code** | iTerm2, Terminal, VS Code, Xcode | Chrome (docs/GitHub), Simulator |
|
|
191
|
+
| **Design** | Figma, Sketch, Pixelmator | Chrome (design systems), Preview |
|
|
192
|
+
| **Writing** | Notes, Obsidian, iA Writer | Chrome (research), Preview |
|
|
193
|
+
| **Communication** | Slack, Discord, Messages, Mail | Calendar, Notes |
|
|
194
|
+
| **Media** | Spotify, Music, Podcasts | (background, no tile needed) |
|
|
195
|
+
| **Reference** | Chrome, Safari, Preview, Finder | (depends on content) |
|
|
196
|
+
|
|
197
|
+
Browser windows are chameleons — use `title` matching to assign them to the right layer based on their content.
|
|
198
|
+
|
|
199
|
+
## Tips
|
|
200
|
+
|
|
201
|
+
- Prefer `wid` when the windows are already open — it's unambiguous.
|
|
202
|
+
- Use `app` + `title` when you want the layer to survive window restarts.
|
|
203
|
+
- Don't put more than 4-5 windows in a single layer — it gets cramped.
|
|
204
|
+
- Background apps (music, etc.) usually don't need to be in any layer.
|
|
205
|
+
- The `snap` command is great for "save what I have now" scenarios.
|
|
206
|
+
- Session layers are ephemeral — they live until the daemon restarts. For permanent layers, edit `~/.lattices/workspace.json`.
|
|
207
|
+
- You can create multiple layers in sequence, then switch between them with `lattices layer session <name>`.
|
package/docs/agents.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Agent Guide
|
|
3
|
+
description: Canonical contracts for agents using docs URLs, CLI, voice, and the daemon API
|
|
4
|
+
order: 6
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Lattices exposes the same execution model through four surfaces:
|
|
8
|
+
|
|
9
|
+
- **Docs URLs** for discovery and citation
|
|
10
|
+
- **CLI** for shell-based agents
|
|
11
|
+
- **Daemon API** for typed programmatic control
|
|
12
|
+
- **Voice / hands-off / HUD** as clients of the same execution layer
|
|
13
|
+
|
|
14
|
+
The rule is simple: agents should learn the **canonical action model**
|
|
15
|
+
first, then choose the transport that fits the environment.
|
|
16
|
+
|
|
17
|
+
## Canonical mutations
|
|
18
|
+
|
|
19
|
+
These are the preferred action identifiers:
|
|
20
|
+
|
|
21
|
+
| Action | Purpose | Preferred surface |
|
|
22
|
+
|--------|---------|-------------------|
|
|
23
|
+
| `window.place` | Place a window or session using a typed placement spec | Daemon API |
|
|
24
|
+
| `layer.activate` | Bring up a workspace layer with explicit activation mode | Daemon API |
|
|
25
|
+
| `space.optimize` | Rebalance a set of windows using an explicit scope and strategy | Daemon API |
|
|
26
|
+
|
|
27
|
+
Compatibility wrappers still exist:
|
|
28
|
+
|
|
29
|
+
| Legacy method | Canonical equivalent |
|
|
30
|
+
|---------------|----------------------|
|
|
31
|
+
| `window.tile` | `window.place` |
|
|
32
|
+
| `layer.switch` | `layer.activate` with `mode=launch` |
|
|
33
|
+
| `layout.distribute` | `space.optimize` with `scope=visible`, `strategy=balanced` |
|
|
34
|
+
|
|
35
|
+
## Discoverability
|
|
36
|
+
|
|
37
|
+
Agents should use these paths in order:
|
|
38
|
+
|
|
39
|
+
1. **API schema**: `lattices call api.schema`
|
|
40
|
+
2. **Daemon reference**: [/docs/api](/docs/api)
|
|
41
|
+
3. **Agent guide**: [/docs/agents](/docs/agents)
|
|
42
|
+
4. **Voice model**: [/docs/voice](/docs/voice)
|
|
43
|
+
5. **Concepts / config**: [/docs/concepts](/docs/concepts), [/docs/config](/docs/config)
|
|
44
|
+
|
|
45
|
+
Useful CLI discovery commands:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
lattices help
|
|
49
|
+
lattices call api.schema
|
|
50
|
+
lattices voice intents
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Placement contract
|
|
54
|
+
|
|
55
|
+
At the boundary, placements may be strings for convenience.
|
|
56
|
+
Inside the daemon, the canonical contract is typed.
|
|
57
|
+
|
|
58
|
+
String shorthand:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{ "placement": "top-right" }
|
|
62
|
+
{ "placement": "grid:3x2:2,0" }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Typed placement objects:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{ "placement": { "kind": "tile", "value": "top-third" } }
|
|
69
|
+
{ "placement": { "kind": "grid", "columns": 3, "rows": 2, "column": 2, "row": 0 } }
|
|
70
|
+
{ "placement": { "kind": "fractions", "x": 0.5, "y": 0, "w": 0.5, "h": 1 } }
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
This lets voice stay natural while the executor stays explicit.
|
|
74
|
+
|
|
75
|
+
## Choosing a surface
|
|
76
|
+
|
|
77
|
+
Use the **daemon API** when you need:
|
|
78
|
+
|
|
79
|
+
- typed receipts and traces
|
|
80
|
+
- explicit targeting by `wid`, `session`, or `app`
|
|
81
|
+
- composition across layers, windows, and optimization
|
|
82
|
+
|
|
83
|
+
Use the **CLI** when you need:
|
|
84
|
+
|
|
85
|
+
- one-shot shell execution
|
|
86
|
+
- quick discovery from inside an agent terminal
|
|
87
|
+
- compatibility with environments that already have `lattices`
|
|
88
|
+
|
|
89
|
+
Use **docs URLs** when an agent needs:
|
|
90
|
+
|
|
91
|
+
- a citeable contract
|
|
92
|
+
- a stable page to open in a browser or pass to another agent
|
|
93
|
+
- quick onboarding without reading source
|
|
94
|
+
|
|
95
|
+
## Examples
|
|
96
|
+
|
|
97
|
+
Node.js:
|
|
98
|
+
|
|
99
|
+
```js
|
|
100
|
+
import { daemonCall } from '@lattices/cli'
|
|
101
|
+
|
|
102
|
+
await daemonCall('session.launch', { path: '/Users/you/dev/frontend' })
|
|
103
|
+
await daemonCall('window.place', {
|
|
104
|
+
session: 'frontend-a1b2c3',
|
|
105
|
+
placement: { kind: 'tile', value: 'left' }
|
|
106
|
+
})
|
|
107
|
+
await daemonCall('layer.activate', { name: 'review', mode: 'launch' })
|
|
108
|
+
await daemonCall('space.optimize', { scope: 'visible', strategy: 'balanced' })
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
CLI:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
lattices call api.schema
|
|
115
|
+
lattices call window.place '{"session":"frontend-a1b2c3","placement":"left"}'
|
|
116
|
+
lattices call layer.activate '{"name":"review","mode":"launch"}'
|
|
117
|
+
lattices call space.optimize '{"scope":"visible","strategy":"balanced"}'
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Receipts and traceability
|
|
121
|
+
|
|
122
|
+
Mutating daemon calls should return structured receipts when possible.
|
|
123
|
+
The important fields for agents are:
|
|
124
|
+
|
|
125
|
+
- resolved target
|
|
126
|
+
- resolved placement / scope / mode
|
|
127
|
+
- affected window IDs
|
|
128
|
+
- trace entries explaining why the daemon chose that path
|
|
129
|
+
|
|
130
|
+
This is what keeps voice, hands-off, and scripted execution scrutable.
|
|
131
|
+
|
|
132
|
+
## Voice and hands-off
|
|
133
|
+
|
|
134
|
+
Voice is not a separate execution system. It should compile into the
|
|
135
|
+
same canonical actions:
|
|
136
|
+
|
|
137
|
+
- "put Terminal in the upper third" → `window.place`
|
|
138
|
+
- "bring up review" → `layer.activate`
|
|
139
|
+
- "make this nice" → `space.optimize`
|
|
140
|
+
|
|
141
|
+
That keeps the interaction layer flexible while the executor stays
|
|
142
|
+
predictable.
|
package/docs/api.md
CHANGED
|
@@ -112,7 +112,10 @@ 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)
|
|
@@ -190,6 +193,12 @@ Useful for agent self-discovery.
|
|
|
190
193
|
|
|
191
194
|
**Params**: none
|
|
192
195
|
|
|
196
|
+
CLI shortcut:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
lattices call api.schema
|
|
200
|
+
```
|
|
201
|
+
|
|
193
202
|
#### `diagnostics.list`
|
|
194
203
|
|
|
195
204
|
Return recent diagnostic log entries from the daemon.
|
|
@@ -210,13 +219,15 @@ Return recent diagnostic log entries from the daemon.
|
|
|
210
219
|
| `windows.get` | read | Single window by ID |
|
|
211
220
|
| `windows.search` | read | Search windows by query |
|
|
212
221
|
| `spaces.list` | read | macOS display spaces |
|
|
213
|
-
| `window.
|
|
222
|
+
| `window.place` | write | Place a window or session using a typed placement spec |
|
|
223
|
+
| `window.tile` | write | Compatibility wrapper for session tiling |
|
|
214
224
|
| `window.focus` | write | Focus a window / switch Spaces |
|
|
215
225
|
| `window.move` | write | Move a window to another Space |
|
|
216
226
|
| `window.assignLayer` | write | Tag a window to a layer |
|
|
217
227
|
| `window.removeLayer` | write | Remove a window's layer tag |
|
|
218
228
|
| `window.layerMap` | read | All window→layer assignments |
|
|
219
|
-
| `
|
|
229
|
+
| `space.optimize` | write | Optimize a set of windows using an explicit scope and strategy |
|
|
230
|
+
| `layout.distribute` | write | Compatibility wrapper for visible-window balancing |
|
|
220
231
|
|
|
221
232
|
#### `windows.list`
|
|
222
233
|
|
|
@@ -263,17 +274,50 @@ Get a single window by its CGWindowID.
|
|
|
263
274
|
|
|
264
275
|
#### `windows.search`
|
|
265
276
|
|
|
266
|
-
Search windows by text query,
|
|
277
|
+
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.
|
|
267
278
|
|
|
268
279
|
**Params**:
|
|
269
280
|
|
|
270
281
|
| Field | Type | Required | Description |
|
|
271
282
|
|---------|--------|----------|--------------------------------|
|
|
272
|
-
| `query` | string | yes | Search query (matches title, app, OCR text) |
|
|
283
|
+
| `query` | string | yes | Search query (matches title, app, session, OCR text) |
|
|
273
284
|
| `ocr` | boolean| no | Include OCR text in search (default true) |
|
|
274
|
-
| `limit` | number | no | Max results (default
|
|
285
|
+
| `limit` | number | no | Max results (default 50) |
|
|
286
|
+
|
|
287
|
+
**Returns**: array of window objects with additional search fields:
|
|
288
|
+
|
|
289
|
+
```json
|
|
290
|
+
[
|
|
291
|
+
{
|
|
292
|
+
"wid": 265,
|
|
293
|
+
"app": "iTerm2",
|
|
294
|
+
"title": "✳ Claude Code",
|
|
295
|
+
"matchSource": "ocr",
|
|
296
|
+
"ocrSnippet": "…~/dev/vox StatusBarIconFolder…",
|
|
297
|
+
"frame": { "x": 688, "y": 3, "w": 1720, "h": 720 },
|
|
298
|
+
"isOnScreen": true
|
|
299
|
+
}
|
|
300
|
+
]
|
|
301
|
+
```
|
|
275
302
|
|
|
276
|
-
|
|
303
|
+
`matchSource` values: `"title"`, `"app"`, `"session"`, `"ocr"`.
|
|
304
|
+
|
|
305
|
+
**CLI usage**:
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
# Basic search (uses windows.search)
|
|
309
|
+
lattices search vox
|
|
310
|
+
|
|
311
|
+
# Deep search — adds terminal tab/process inspection for ranking
|
|
312
|
+
lattices search vox --deep
|
|
313
|
+
|
|
314
|
+
# Pipeable output
|
|
315
|
+
lattices search vox --wid
|
|
316
|
+
lattices search vox --json
|
|
317
|
+
|
|
318
|
+
# Search + focus + tile in one step
|
|
319
|
+
lattices place vox right
|
|
320
|
+
```
|
|
277
321
|
|
|
278
322
|
#### `spaces.list`
|
|
279
323
|
|
|
@@ -297,20 +341,53 @@ List macOS display spaces (virtual desktops).
|
|
|
297
341
|
]
|
|
298
342
|
```
|
|
299
343
|
|
|
300
|
-
#### `window.
|
|
344
|
+
#### `window.place`
|
|
301
345
|
|
|
302
|
-
|
|
346
|
+
Canonical window placement mutation. Use this when an agent needs a
|
|
347
|
+
single, typed placement contract across voice, CLI, and daemon clients.
|
|
303
348
|
|
|
304
349
|
**Params**:
|
|
305
350
|
|
|
306
|
-
| Field
|
|
307
|
-
|
|
308
|
-
| `
|
|
309
|
-
| `
|
|
351
|
+
| Field | Type | Required | Description |
|
|
352
|
+
|-------------|-----------------|----------|------------------------------------------|
|
|
353
|
+
| `wid` | number | no | Target window ID |
|
|
354
|
+
| `session` | string | no | Target lattices session |
|
|
355
|
+
| `app` | string | no | Target app name |
|
|
356
|
+
| `title` | string | no | Optional title substring for app matching |
|
|
357
|
+
| `display` | number | no | Target display index |
|
|
358
|
+
| `placement` | string \| object | yes | Placement shorthand or typed object |
|
|
359
|
+
|
|
360
|
+
Target resolution priority is `wid` → `session` → `app/title` → frontmost window.
|
|
310
361
|
|
|
311
|
-
**
|
|
362
|
+
**Placement strings**: `left`, `right`, `top`, `bottom`, `top-left`, `top-right`,
|
|
312
363
|
`bottom-left`, `bottom-right`, `left-third`, `center-third`, `right-third`,
|
|
313
|
-
`
|
|
364
|
+
`top-third`, `middle-third`, `bottom-third`, `left-quarter`, `right-quarter`,
|
|
365
|
+
`top-quarter`, `bottom-quarter`, `maximize`, `center`, or `grid:CxR:C,R`.
|
|
366
|
+
|
|
367
|
+
**Typed placement examples**:
|
|
368
|
+
|
|
369
|
+
```json
|
|
370
|
+
{ "kind": "tile", "value": "top-right" }
|
|
371
|
+
{ "kind": "grid", "columns": 3, "rows": 2, "column": 2, "row": 0 }
|
|
372
|
+
{ "kind": "fractions", "x": 0.5, "y": 0, "w": 0.5, "h": 1 }
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
**Returns**: execution receipt including resolved target, placement, and trace.
|
|
376
|
+
|
|
377
|
+
#### `window.tile`
|
|
378
|
+
|
|
379
|
+
Compatibility wrapper for `window.place` when the target is a lattices
|
|
380
|
+
session window.
|
|
381
|
+
|
|
382
|
+
**Params**:
|
|
383
|
+
|
|
384
|
+
| Field | Type | Required | Description |
|
|
385
|
+
|------------|--------|----------|-----------------------------------------|
|
|
386
|
+
| `session` | string | yes | Session name |
|
|
387
|
+
| `position` | string | yes | Placement shorthand or grid syntax |
|
|
388
|
+
|
|
389
|
+
This method exists for compatibility. New integrations should prefer
|
|
390
|
+
`window.place`.
|
|
314
391
|
|
|
315
392
|
#### `window.focus`
|
|
316
393
|
|
|
@@ -375,9 +452,31 @@ Return all current window→layer assignments.
|
|
|
375
452
|
|
|
376
453
|
Keys are CGWindowIDs (as strings), values are layer IDs.
|
|
377
454
|
|
|
455
|
+
#### `space.optimize`
|
|
456
|
+
|
|
457
|
+
Canonical space-balancing mutation. Use this when the goal is to make
|
|
458
|
+
the current workspace coherent rather than placing one specific window.
|
|
459
|
+
|
|
460
|
+
**Params**:
|
|
461
|
+
|
|
462
|
+
| Field | Type | Required | Description |
|
|
463
|
+
|-------------|----------|----------|-----------------------------------------------------|
|
|
464
|
+
| `scope` | string | no | `visible`, `active-app`, `app`, or `selection` |
|
|
465
|
+
| `strategy` | string | no | `balanced` or `mosaic` |
|
|
466
|
+
| `app` | string | no | App name for `app` scope |
|
|
467
|
+
| `title` | string | no | Optional title substring for app matching |
|
|
468
|
+
| `windowIds` | number[] | no | Explicit window IDs for `selection` scope |
|
|
469
|
+
|
|
470
|
+
If `windowIds` is provided, scope is inferred as `selection`.
|
|
471
|
+
If `app` is provided and `scope` is omitted, scope is inferred as `app`.
|
|
472
|
+
|
|
473
|
+
**Returns**: execution receipt including resolved scope, strategy,
|
|
474
|
+
affected window IDs, and trace.
|
|
475
|
+
|
|
378
476
|
#### `layout.distribute`
|
|
379
477
|
|
|
380
|
-
|
|
478
|
+
Compatibility wrapper for `space.optimize` with `scope=visible` and
|
|
479
|
+
`strategy=balanced`.
|
|
381
480
|
|
|
382
481
|
**Params**: none
|
|
383
482
|
|
|
@@ -512,7 +611,8 @@ Restart a specific pane's process within a session.
|
|
|
512
611
|
| `projects.list` | read | Discovered projects |
|
|
513
612
|
| `projects.scan` | write | Re-scan project directory |
|
|
514
613
|
| `layers.list` | read | Workspace layers and active index |
|
|
515
|
-
| `layer.
|
|
614
|
+
| `layer.activate` | write | Activate a workspace layer using an explicit mode |
|
|
615
|
+
| `layer.switch` | write | Compatibility wrapper for launch-style layer activation |
|
|
516
616
|
| `group.launch` | write | Launch a tab group |
|
|
517
617
|
| `group.kill` | write | Kill a tab group |
|
|
518
618
|
|
|
@@ -569,20 +669,33 @@ List configured workspace layers and the active index.
|
|
|
569
669
|
|
|
570
670
|
Returns empty `layers` array if no workspace config is loaded.
|
|
571
671
|
|
|
572
|
-
#### `layer.
|
|
672
|
+
#### `layer.activate`
|
|
573
673
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
a `layer.switched` event.
|
|
674
|
+
Canonical layer mutation. Use this when an agent wants an explicit
|
|
675
|
+
activation mode instead of implicit "switch" behavior.
|
|
577
676
|
|
|
578
677
|
**Params**:
|
|
579
678
|
|
|
580
|
-
| Field | Type | Required | Description
|
|
581
|
-
|
|
582
|
-
| `index` | number | no | Layer index (0-based)
|
|
583
|
-
| `name` | string | no | Layer ID or label
|
|
679
|
+
| Field | Type | Required | Description |
|
|
680
|
+
|---------|--------|----------|---------------------------------------------|
|
|
681
|
+
| `index` | number | no | Layer index (0-based) |
|
|
682
|
+
| `name` | string | no | Layer ID or label |
|
|
683
|
+
| `mode` | string | no | `launch`, `focus`, or `retile` |
|
|
684
|
+
|
|
685
|
+
Provide either `index` or `name`.
|
|
584
686
|
|
|
585
|
-
|
|
687
|
+
**Modes**:
|
|
688
|
+
|
|
689
|
+
- `launch` — bring up the layer, launching missing projects and retiling
|
|
690
|
+
- `focus` — raise the layer's windows in place
|
|
691
|
+
- `retile` — re-apply the layer layout without launch semantics
|
|
692
|
+
|
|
693
|
+
**Returns**: execution receipt including resolved layer, mode, and trace.
|
|
694
|
+
|
|
695
|
+
#### `layer.switch`
|
|
696
|
+
|
|
697
|
+
Compatibility wrapper for `layer.activate` with `mode=launch`.
|
|
698
|
+
It keeps the old semantics and still posts a `layer.switched` event.
|
|
586
699
|
|
|
587
700
|
#### `group.launch`
|
|
588
701
|
|
|
@@ -839,13 +952,19 @@ project knows how to control the workspace:
|
|
|
839
952
|
This project uses lattices for workspace management. The daemon API
|
|
840
953
|
is available at ws://127.0.0.1:9399.
|
|
841
954
|
|
|
842
|
-
###
|
|
843
|
-
-
|
|
844
|
-
|
|
955
|
+
### Search (find windows)
|
|
956
|
+
- Search by content: `daemonCall('windows.search', { query: 'myproject' })`
|
|
957
|
+
Returns windows with `matchSource` ("title", "app", "session", "ocr") and `ocrSnippet`
|
|
958
|
+
- Search terminals: `daemonCall('terminals.search', {})` — tabs, cwds, processes
|
|
959
|
+
- CLI: `lattices search myproject` or `lattices search myproject --deep`
|
|
960
|
+
|
|
961
|
+
### Actions
|
|
962
|
+
- Focus a window: `daemonCall('window.focus', { wid: 1234 })`
|
|
963
|
+
- Place a window: `daemonCall('window.place', { session: 'name', placement: 'left' })`
|
|
845
964
|
- Launch a project: `daemonCall('session.launch', { path: '/absolute/path' })`
|
|
846
|
-
-
|
|
847
|
-
-
|
|
848
|
-
-
|
|
965
|
+
- Activate a layer: `daemonCall('layer.activate', { name: 'web', mode: 'launch' })`
|
|
966
|
+
- Optimize the workspace: `daemonCall('space.optimize', { scope: 'visible', strategy: 'balanced' })`
|
|
967
|
+
- CLI: `lattices place myproject left` (search + focus + tile in one step)
|
|
849
968
|
|
|
850
969
|
### Import
|
|
851
970
|
\```js
|
|
@@ -872,8 +991,8 @@ const sessions = await daemonCall('tmux.sessions')
|
|
|
872
991
|
const fe = sessions.find(s => s.name.startsWith('frontend'))
|
|
873
992
|
const api = sessions.find(s => s.name.startsWith('api'))
|
|
874
993
|
|
|
875
|
-
await daemonCall('window.
|
|
876
|
-
await daemonCall('window.
|
|
994
|
+
await daemonCall('window.place', { session: fe.name, placement: 'left' })
|
|
995
|
+
await daemonCall('window.place', { session: api.name, placement: 'right' })
|
|
877
996
|
```
|
|
878
997
|
|
|
879
998
|
### Reactive event pattern
|
package/docs/app.md
CHANGED
|
@@ -143,10 +143,21 @@ highlight around it for ~1 second so you can spot it immediately.
|
|
|
143
143
|
Grant Screen Recording and Accessibility permissions in System
|
|
144
144
|
Settings > Privacy & Security for all three paths to work.
|
|
145
145
|
|
|
146
|
+
## Voice commands
|
|
147
|
+
|
|
148
|
+
> See [Voice Commands](/docs/voice) for the full guide.
|
|
149
|
+
|
|
150
|
+
Press **Hyper+3** to open the voice command window. Hold **Option** to
|
|
151
|
+
speak, release to stop. Lattices transcribes via Vox, matches to an
|
|
152
|
+
intent, and executes. Built-in commands: find, show, open, tile, kill, scan.
|
|
153
|
+
|
|
154
|
+
A Claude Haiku advisor runs in parallel, offering follow-up suggestions
|
|
155
|
+
in the AI corner. Configure the model and budget in Settings > AI.
|
|
156
|
+
|
|
146
157
|
## Settings
|
|
147
158
|
|
|
148
159
|
Open via the command palette or the gear icon in the main view.
|
|
149
|
-
The settings window has
|
|
160
|
+
The settings window has four tabs:
|
|
150
161
|
|
|
151
162
|
### General
|
|
152
163
|
|
|
@@ -162,6 +173,17 @@ The settings window has three tabs:
|
|
|
162
173
|
(helpful while getting used to tmux)
|
|
163
174
|
- **Auto** — detaches sessions automatically (fewer prompts)
|
|
164
175
|
|
|
176
|
+
### AI
|
|
177
|
+
|
|
178
|
+
| Setting | Default | Description |
|
|
179
|
+
|----------------------|----------------|------------------------------------------|
|
|
180
|
+
| Claude CLI path | Auto-detected | Path to `claude` binary |
|
|
181
|
+
| Advisor model | Haiku | `haiku` (fast) or `sonnet` (smarter) |
|
|
182
|
+
| Budget per session | $0.50 | Max spend per Claude CLI invocation |
|
|
183
|
+
|
|
184
|
+
Shows live session stats: context usage %, session cost, and learned
|
|
185
|
+
pattern count.
|
|
186
|
+
|
|
165
187
|
### Shortcuts
|
|
166
188
|
|
|
167
189
|
Shows keyboard shortcut reference:
|
|
@@ -169,6 +191,12 @@ Shows keyboard shortcut reference:
|
|
|
169
191
|
| Shortcut | Action |
|
|
170
192
|
|-------------------|----------------------|
|
|
171
193
|
| Cmd+Shift+M | Open command palette |
|
|
194
|
+
| Hyper+1 | Screen map |
|
|
195
|
+
| Hyper+2 | Window bezel |
|
|
196
|
+
| Hyper+3 | Voice commands |
|
|
197
|
+
| Hyper+4 | Desktop inventory |
|
|
198
|
+
| Hyper+5 | Omni search |
|
|
199
|
+
| Hyper+6 | Cheat sheet |
|
|
172
200
|
| Cmd+Option+1/2/3 | Switch workspace layer |
|
|
173
201
|
| Ctrl+B D | Detach from session |
|
|
174
202
|
| Ctrl+B X | Kill current pane |
|