@arach/lattices 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -28
- package/app/Sources/ActionRow.swift +61 -0
- package/app/Sources/App.swift +1 -40
- package/app/Sources/AppDelegate.swift +154 -24
- package/app/Sources/CheatSheetHUD.swift +1 -0
- package/app/Sources/CommandModeState.swift +40 -19
- package/app/Sources/CommandModeView.swift +27 -2
- package/app/Sources/DaemonServer.swift +8 -0
- package/app/Sources/DiagnosticLog.swift +19 -1
- package/app/Sources/EventBus.swift +1 -0
- package/app/Sources/HotkeyManager.swift +1 -0
- package/app/Sources/HotkeyStore.swift +9 -1
- package/app/Sources/LatticesApi.swift +210 -0
- package/app/Sources/MainView.swift +46 -86
- package/app/Sources/MainWindow.swift +13 -0
- package/app/Sources/OcrModel.swift +309 -0
- package/app/Sources/OcrStore.swift +295 -0
- package/app/Sources/OmniSearchState.swift +283 -0
- package/app/Sources/OmniSearchView.swift +288 -0
- package/app/Sources/OmniSearchWindow.swift +105 -0
- package/app/Sources/PaletteCommand.swift +11 -1
- package/app/Sources/PermissionChecker.swift +12 -2
- package/app/Sources/Preferences.swift +44 -0
- package/app/Sources/ScreenMapState.swift +7 -17
- package/app/Sources/ScreenMapView.swift +3 -0
- package/app/Sources/SettingsView.swift +534 -122
- package/app/Sources/Theme.swift +39 -0
- package/app/Sources/WindowTiler.swift +59 -56
- package/bin/lattices-app.js +23 -7
- package/bin/lattices.js +123 -0
- package/docs/api.md +390 -249
- package/docs/app.md +75 -28
- package/docs/concepts.md +45 -136
- package/docs/config.md +8 -7
- package/docs/layers.md +16 -18
- package/docs/ocr.md +185 -0
- package/docs/overview.md +39 -34
- package/docs/quickstart.md +34 -35
- package/package.json +6 -2
package/docs/ocr.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Screen OCR & Search
|
|
3
|
+
description: Vision-powered screen reading with full-text search for agents
|
|
4
|
+
order: 3.5
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
The menu bar app reads text from visible windows using Apple's Vision
|
|
8
|
+
framework and stores results in a local SQLite database with FTS5
|
|
9
|
+
full-text search. Agents can use this to "see" what's on screen.
|
|
10
|
+
|
|
11
|
+
## Enabling OCR
|
|
12
|
+
|
|
13
|
+
Open **Settings** (via command palette or gear icon) and toggle
|
|
14
|
+
**Search & OCR** on. OCR is disabled by default.
|
|
15
|
+
|
|
16
|
+
### Accuracy modes
|
|
17
|
+
|
|
18
|
+
| Mode | Description |
|
|
19
|
+
|------|-------------|
|
|
20
|
+
| **Accurate** (default) | Higher quality recognition, slower processing |
|
|
21
|
+
| **Fast** | Lower latency, reduced accuracy |
|
|
22
|
+
|
|
23
|
+
Both modes use `VNRecognizeTextRequest` with language correction enabled.
|
|
24
|
+
|
|
25
|
+
## How scanning works
|
|
26
|
+
|
|
27
|
+
The app runs two scan schedules:
|
|
28
|
+
|
|
29
|
+
| Schedule | Interval | Window limit | Purpose |
|
|
30
|
+
|----------|----------|-------------|---------|
|
|
31
|
+
| **Quick scan** | 60 seconds | Top 5 windows | Keep recent content fresh |
|
|
32
|
+
| **Deep scan** | 2 hours | Up to 15 windows | Catch less-active windows |
|
|
33
|
+
|
|
34
|
+
Both intervals and limits are configurable in Settings.
|
|
35
|
+
|
|
36
|
+
### Change detection
|
|
37
|
+
|
|
38
|
+
Before running OCR on a window, the app captures the window image and
|
|
39
|
+
computes a SHA-256 hash of the pixel data. If the hash matches the
|
|
40
|
+
previous scan, the cached result is reused. No Vision processing needed.
|
|
41
|
+
|
|
42
|
+
This keeps CPU usage low when windows haven't changed. A 100ms throttle
|
|
43
|
+
between windows further limits processing bursts.
|
|
44
|
+
|
|
45
|
+
## Browsing results
|
|
46
|
+
|
|
47
|
+
The **Recent Captures** section in Settings shows OCR results grouped by
|
|
48
|
+
app. Each entry displays the window title, recognized text preview, and
|
|
49
|
+
timestamp.
|
|
50
|
+
|
|
51
|
+
## Searching
|
|
52
|
+
|
|
53
|
+
### From the command palette
|
|
54
|
+
|
|
55
|
+
The OmniSearch bar (Cmd+Shift+M) searches OCR content alongside windows,
|
|
56
|
+
projects, and sessions. Matches show as "Screen Text" results with
|
|
57
|
+
contextual snippets.
|
|
58
|
+
|
|
59
|
+
### From the CLI
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# View current OCR snapshot
|
|
63
|
+
lattices ocr
|
|
64
|
+
|
|
65
|
+
# Search OCR history
|
|
66
|
+
lattices ocr search "error OR failed"
|
|
67
|
+
|
|
68
|
+
# Trigger an immediate deep scan
|
|
69
|
+
lattices ocr scan
|
|
70
|
+
|
|
71
|
+
# View OCR history for a specific window ID
|
|
72
|
+
lattices ocr history 12345
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### From the daemon API
|
|
76
|
+
|
|
77
|
+
Agents can query OCR data through four daemon methods:
|
|
78
|
+
|
|
79
|
+
| Method | Description |
|
|
80
|
+
|--------|-------------|
|
|
81
|
+
| `ocr.snapshot` | Current OCR results for all visible windows |
|
|
82
|
+
| `ocr.search` | Full-text search across history (FTS5 syntax) |
|
|
83
|
+
| `ocr.history` | Timeline of OCR results for a specific window |
|
|
84
|
+
| `ocr.scan` | Trigger an immediate deep scan |
|
|
85
|
+
|
|
86
|
+
#### `ocr.snapshot`
|
|
87
|
+
|
|
88
|
+
Returns the latest OCR results for all on-screen windows.
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
import { daemonCall } from '@arach/lattices/daemon-client'
|
|
92
|
+
|
|
93
|
+
const snapshot = await daemonCall('ocr.snapshot')
|
|
94
|
+
// [{ wid, app, title, frame, fullText, blocks, timestamp }, ...]
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Each result includes:
|
|
98
|
+
- `wid` — window ID
|
|
99
|
+
- `app` — application name
|
|
100
|
+
- `title` — window title
|
|
101
|
+
- `frame` — `{ x, y, w, h }` screen position
|
|
102
|
+
- `fullText` — all recognized text concatenated
|
|
103
|
+
- `blocks` — individual text blocks with `{ text, confidence, x, y, w, h }`
|
|
104
|
+
- `timestamp` — Unix timestamp of the scan
|
|
105
|
+
|
|
106
|
+
#### `ocr.search`
|
|
107
|
+
|
|
108
|
+
Full-text search across OCR history using FTS5 query syntax.
|
|
109
|
+
|
|
110
|
+
```js
|
|
111
|
+
const results = await daemonCall('ocr.search', {
|
|
112
|
+
query: 'error OR failed', // FTS5 query (required)
|
|
113
|
+
app: 'Terminal', // filter by app name (optional)
|
|
114
|
+
limit: 50, // max results (optional, default 50)
|
|
115
|
+
live: false // search in-memory snapshot instead of history (optional)
|
|
116
|
+
})
|
|
117
|
+
// [{ id, wid, app, title, frame, fullText, snippet, timestamp }, ...]
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The `snippet` field contains FTS5-highlighted text with `«` and `»`
|
|
121
|
+
delimiters around matched terms.
|
|
122
|
+
|
|
123
|
+
#### `ocr.history`
|
|
124
|
+
|
|
125
|
+
Get the OCR content timeline for a specific window.
|
|
126
|
+
|
|
127
|
+
```js
|
|
128
|
+
const history = await daemonCall('ocr.history', {
|
|
129
|
+
wid: 12345, // window ID (required)
|
|
130
|
+
limit: 50 // max results (optional, default 50)
|
|
131
|
+
})
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
#### `ocr.scan`
|
|
135
|
+
|
|
136
|
+
Trigger an immediate deep scan (all visible windows up to the deep limit).
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
await daemonCall('ocr.scan')
|
|
140
|
+
// { ok: true }
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Storage
|
|
144
|
+
|
|
145
|
+
OCR data is stored in `~/.lattices/ocr.db`, a SQLite database in WAL
|
|
146
|
+
(Write-Ahead Logging) mode for safe concurrent reads.
|
|
147
|
+
|
|
148
|
+
The schema uses two tables:
|
|
149
|
+
- `ocr_entry` — stores window ID, app, title, frame, full text, and timestamp
|
|
150
|
+
- `ocr_fts` — FTS5 virtual table indexing `full_text`, `app`, and `title`
|
|
151
|
+
|
|
152
|
+
Triggers keep the FTS index in sync with inserts, updates, and deletes.
|
|
153
|
+
|
|
154
|
+
Entries older than 3 days are automatically deleted.
|
|
155
|
+
|
|
156
|
+
## Agent usage
|
|
157
|
+
|
|
158
|
+
A typical agent workflow: trigger a scan, then search for relevant content.
|
|
159
|
+
|
|
160
|
+
```js
|
|
161
|
+
import { daemonCall } from '@arach/lattices/daemon-client'
|
|
162
|
+
|
|
163
|
+
// Trigger a fresh scan
|
|
164
|
+
await daemonCall('ocr.scan')
|
|
165
|
+
|
|
166
|
+
// Search for compilation errors across all windows
|
|
167
|
+
const errors = await daemonCall('ocr.search', { query: 'error OR warning' })
|
|
168
|
+
|
|
169
|
+
for (const result of errors) {
|
|
170
|
+
console.log(`[${result.app}] ${result.title}`)
|
|
171
|
+
console.log(result.snippet)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Read everything currently visible
|
|
175
|
+
const snapshot = await daemonCall('ocr.snapshot')
|
|
176
|
+
for (const win of snapshot) {
|
|
177
|
+
console.log(`${win.app}: ${win.fullText.slice(0, 200)}`)
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Requirements
|
|
182
|
+
|
|
183
|
+
- **Screen Recording** permission — required to capture window images
|
|
184
|
+
- Grant via System Settings > Privacy & Security > Screen Recording
|
|
185
|
+
- Add the lattices menu bar app to the allowed list
|
package/docs/overview.md
CHANGED
|
@@ -4,71 +4,76 @@ description: What lattices is and who it's for
|
|
|
4
4
|
order: 0
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
with a native menu bar app to give you — and your AI coding agents —
|
|
11
|
-
full control over terminal layouts, window tiling, and project navigation.
|
|
7
|
+
lattices is a macOS developer workspace manager. A native menu bar app
|
|
8
|
+
handles window tiling, project navigation, on-screen OCR, and optionally
|
|
9
|
+
tmux-powered terminal sessions. Your AI coding agents can use it too.
|
|
12
10
|
|
|
13
11
|
## The problem
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
I kept losing track of windows. Terminal here, dev server there, browser
|
|
14
|
+
somewhere on the second monitor, three other projects buried under it all.
|
|
15
|
+
Every morning I'd rebuild the same layout. Half my context-switching was
|
|
16
|
+
just hunting for the right window.
|
|
17
|
+
|
|
18
|
+
AI agents have it worse. They're stuck inside a single shell with no way
|
|
19
|
+
to see what's on screen, arrange windows, or jump between projects.
|
|
19
20
|
|
|
20
21
|
## The solution
|
|
21
22
|
|
|
22
|
-
lattices
|
|
23
|
+
lattices fixes both sides:
|
|
23
24
|
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
sessions with
|
|
27
|
-
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
- The menu bar app tiles windows, navigates projects, and manages
|
|
26
|
+
workspace layers through a command palette. Add tmux if you want
|
|
27
|
+
persistent terminal sessions with auto-layout.
|
|
28
|
+
- The daemon API exposes 30 RPC methods over WebSocket. Agents can
|
|
29
|
+
discover projects, tile windows, switch layers, read on-screen text
|
|
30
|
+
via OCR, and launch sessions programmatically.
|
|
30
31
|
|
|
31
32
|
## What's included
|
|
32
33
|
|
|
33
34
|
| Component | Description |
|
|
34
35
|
|-----------|-------------|
|
|
35
|
-
| **CLI**
|
|
36
|
-
| **Menu bar app** | Native macOS companion
|
|
37
|
-
| **Daemon API** | WebSocket server on `ws://127.0.0.1:9399
|
|
36
|
+
| **CLI** | The `lattices` command. Tile windows, manage sessions, control the workspace from your terminal |
|
|
37
|
+
| **Menu bar app** | Native macOS companion. Command palette, window tiling, project discovery |
|
|
38
|
+
| **Daemon API** | WebSocket server on `ws://127.0.0.1:9399`. 30 methods, 5 real-time events |
|
|
39
|
+
| **OCR engine** | Reads text from visible windows using Apple Vision, indexes it with FTS5 |
|
|
38
40
|
| **Node.js client** | Zero-dependency `daemonCall()` helper for scripting |
|
|
39
41
|
|
|
40
|
-
##
|
|
42
|
+
## Example
|
|
41
43
|
|
|
42
44
|
```bash
|
|
43
|
-
# Launch a workspace (auto-detects your project)
|
|
44
45
|
cd ~/my-project && lattices
|
|
45
|
-
|
|
46
|
-
# Or give agents programmatic control
|
|
47
46
|
```
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
import { daemonCall } from 'lattices/daemon-client'
|
|
48
|
+
Agents get the same control programmatically:
|
|
51
49
|
|
|
50
|
+
```js
|
|
51
|
+
import { daemonCall } from '@arach/lattices/daemon-client'
|
|
52
52
|
await daemonCall('session.launch', { path: '/Users/you/dev/frontend' })
|
|
53
53
|
await daemonCall('window.tile', { session: 'frontend-a1b2c3', position: 'left' })
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
## Who it's for
|
|
57
57
|
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
58
|
+
- Developers who juggle multiple projects and want faster window management
|
|
59
|
+
- People building AI agents that need to control the desktop
|
|
60
|
+
- Power users who work across multiple macOS Spaces
|
|
61
|
+
- tmux users who want persistent, auto-configured terminal sessions
|
|
61
62
|
|
|
62
63
|
## Requirements
|
|
63
64
|
|
|
64
65
|
- macOS 13.0+
|
|
65
|
-
- tmux (`brew install tmux`)
|
|
66
66
|
- Node.js 18+
|
|
67
|
-
|
|
67
|
+
|
|
68
|
+
### Dev dependencies
|
|
69
|
+
|
|
70
|
+
- Swift 5.9+ — only to build the menu bar app from source
|
|
71
|
+
- tmux — needed for persistent terminal sessions (`brew install tmux`)
|
|
68
72
|
|
|
69
73
|
## Next steps
|
|
70
74
|
|
|
71
|
-
- [Quickstart](/docs/quickstart)
|
|
72
|
-
- [
|
|
73
|
-
- [
|
|
74
|
-
- [
|
|
75
|
+
- [Quickstart](/docs/quickstart): install and run your first session in 2 minutes
|
|
76
|
+
- [Configuration](/docs/config): `.lattices.json` format and CLI commands
|
|
77
|
+
- [Screen OCR](/docs/ocr): Vision-powered screen reading and full-text search
|
|
78
|
+
- [Concepts](/docs/concepts): architecture, glossary, and how it all works
|
|
79
|
+
- [Daemon API](/docs/api): RPC method reference for agents and scripts
|
package/docs/quickstart.md
CHANGED
|
@@ -4,56 +4,46 @@ description: Install lattices and launch your first workspace in 2 minutes
|
|
|
4
4
|
order: 0.5
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Four steps to a running workspace.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
## 1. Install tmux
|
|
9
|
+
## 1. Install lattices
|
|
12
10
|
|
|
13
11
|
```bash
|
|
14
|
-
|
|
12
|
+
npm install -g @arach/lattices
|
|
15
13
|
```
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
## 2. Install lattices
|
|
15
|
+
Or install from source:
|
|
20
16
|
|
|
21
17
|
```bash
|
|
22
|
-
# Clone and link
|
|
23
18
|
git clone https://github.com/arach/lattices
|
|
24
|
-
cd lattices
|
|
25
|
-
bun link
|
|
19
|
+
cd lattices && npm link
|
|
26
20
|
```
|
|
27
21
|
|
|
28
22
|
Verify: `lattices help` should print usage info.
|
|
29
23
|
|
|
30
|
-
##
|
|
24
|
+
## 2. Launch the menu bar app
|
|
31
25
|
|
|
32
26
|
```bash
|
|
33
|
-
|
|
34
|
-
lattices
|
|
27
|
+
lattices app
|
|
35
28
|
```
|
|
36
29
|
|
|
37
|
-
This
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
No config file needed — lattices auto-detects your package manager
|
|
42
|
-
and dev script.
|
|
30
|
+
This builds (or downloads) and launches the native macOS companion.
|
|
31
|
+
Open the command palette with **Cmd+Shift+M** to search and launch
|
|
32
|
+
any project, tile windows, or switch workspace layers.
|
|
43
33
|
|
|
44
|
-
##
|
|
34
|
+
## 3. Add a project config
|
|
45
35
|
|
|
46
|
-
|
|
36
|
+
Drop a `.lattices.json` in your project root:
|
|
47
37
|
|
|
48
38
|
```bash
|
|
39
|
+
cd ~/your-project
|
|
49
40
|
lattices init
|
|
50
41
|
```
|
|
51
42
|
|
|
52
|
-
This generates a
|
|
43
|
+
This generates a config like:
|
|
53
44
|
|
|
54
45
|
```json
|
|
55
46
|
{
|
|
56
|
-
"ensure": true,
|
|
57
47
|
"panes": [
|
|
58
48
|
{ "name": "claude", "cmd": "claude", "size": 60 },
|
|
59
49
|
{ "name": "server", "cmd": "bun dev" }
|
|
@@ -61,22 +51,31 @@ This generates a `.lattices.json` like:
|
|
|
61
51
|
}
|
|
62
52
|
```
|
|
63
53
|
|
|
64
|
-
|
|
54
|
+
The menu bar app discovers projects with `.lattices.json` files
|
|
55
|
+
automatically — they show up in the command palette.
|
|
56
|
+
|
|
57
|
+
## 4. (Optional) Add tmux for persistent sessions
|
|
65
58
|
|
|
66
|
-
|
|
59
|
+
If you want terminal sessions that survive disconnects and auto-restore
|
|
60
|
+
your pane layout:
|
|
67
61
|
|
|
68
62
|
```bash
|
|
69
|
-
|
|
63
|
+
brew install tmux
|
|
64
|
+
cd ~/your-project && lattices
|
|
70
65
|
```
|
|
71
66
|
|
|
72
|
-
This
|
|
73
|
-
|
|
74
|
-
|
|
67
|
+
This creates a tmux session with your configured panes side by side.
|
|
68
|
+
The session persists in the background — close your terminal, reopen it,
|
|
69
|
+
run `lattices` again, and everything is still there.
|
|
70
|
+
|
|
71
|
+
> **Without tmux**, you still get the menu bar app, command palette,
|
|
72
|
+
> window tiling, workspace layers, OCR, and the full daemon API.
|
|
75
73
|
|
|
76
74
|
## What's next
|
|
77
75
|
|
|
78
|
-
- [
|
|
79
|
-
- [
|
|
80
|
-
- [
|
|
81
|
-
- [
|
|
82
|
-
- [
|
|
76
|
+
- [Configuration](/docs/config): `.lattices.json` reference and CLI commands
|
|
77
|
+
- [Menu Bar App](/docs/app): command palette, tiling, and settings
|
|
78
|
+
- [Layers & Groups](/docs/layers): organize projects into switchable contexts
|
|
79
|
+
- [Screen OCR](/docs/ocr): let agents read what's on screen
|
|
80
|
+
- [Concepts](/docs/concepts): sessions, panes, and the architecture
|
|
81
|
+
- [Daemon API](/docs/api): programmatic control for agents and scripts
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arach/lattices",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "macOS workspace manager with window tiling, OCR, and a 30-method daemon API for AI agents",
|
|
5
5
|
"bin": {
|
|
6
6
|
"lattices": "./bin/lattices.js",
|
|
7
7
|
"lattices-app": "./bin/lattices-app.js"
|
|
@@ -20,6 +20,10 @@
|
|
|
20
20
|
"url": "https://github.com/arach/lattices"
|
|
21
21
|
},
|
|
22
22
|
"license": "MIT",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": "./bin/lattices.js",
|
|
25
|
+
"./daemon-client": "./bin/daemon-client.js"
|
|
26
|
+
},
|
|
23
27
|
"scripts": {
|
|
24
28
|
"dev": "bun --cwd docs-site dev"
|
|
25
29
|
},
|