@vashp2029/glovebox 0.0.0-stage → 0.3.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/CHANGELOG.md +66 -0
- package/LICENSE +21 -0
- package/README.md +238 -2
- package/SECURITY.md +81 -0
- package/bin/glovebox.mjs +319 -0
- package/docs/agents.md +124 -0
- package/docs/api.md +146 -0
- package/docs/backend-protocol.md +118 -0
- package/docs/cli.md +150 -0
- package/docs/design.md +212 -0
- package/docs/recipes.md +162 -0
- package/docs/roadmap.md +167 -0
- package/docs/testing.md +79 -0
- package/native/macos/GloveboxHelper.swift +1654 -0
- package/package.json +28 -4
- package/skills/glovebox/SKILL.md +49 -0
- package/src/api.mjs +552 -0
- package/src/axformat.mjs +158 -0
- package/src/backends/index.mjs +27 -0
- package/src/backends/macos.mjs +106 -0
- package/src/config.mjs +92 -0
- package/src/daemon.mjs +127 -0
- package/src/geometry.mjs +38 -0
- package/src/kernel.mjs +217 -0
- package/src/keys.mjs +96 -0
- package/src/macos-helper.mjs +164 -0
- package/src/mcp.mjs +126 -0
- package/src/session.mjs +110 -0
- package/src/smoke.mjs +160 -0
- package/src/transform.mjs +131 -0
package/docs/roadmap.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Roadmap
|
|
2
|
+
|
|
3
|
+
What works today is macOS (14+, tested on 27). Everything below is planned,
|
|
4
|
+
not shipped. Nothing here has been tested unless it says so.
|
|
5
|
+
|
|
6
|
+
## Found by the benchmark and the field run
|
|
7
|
+
|
|
8
|
+
The diff fixes and the bugs found by the 2026-10-28 baseline
|
|
9
|
+
([bench/results](../bench/results/summary.md)) and the 2026-10-29 Citrix field
|
|
10
|
+
run ([summary](../bench/results/field/2026-10-29-citrix/summary.md)) are
|
|
11
|
+
fixed; see the [changelog](../CHANGELOG.md). One is not yet confirmed:
|
|
12
|
+
|
|
13
|
+
1. **Horizontal background scroll in Citrix.** Scroll events now set the
|
|
14
|
+
point and fixed-point deltas for the horizontal axis, but this has not been
|
|
15
|
+
tried in Citrix Viewer. (gb-1iz.12)
|
|
16
|
+
|
|
17
|
+
## Credibility and distribution
|
|
18
|
+
|
|
19
|
+
Ordered by expected impact. These come before new platforms.
|
|
20
|
+
|
|
21
|
+
1. **Benchmark harness (`bench/`).** Done 2026-10-28: harness, raw results,
|
|
22
|
+
and chart are in [bench/](../bench/README.md). The original scope follows.
|
|
23
|
+
About five fixed tasks: Calculator
|
|
24
|
+
arithmetic, editing a TextEdit document, a Finder rename, toggling a
|
|
25
|
+
setting in a non-blocked app, and filling a form in a native app. Add two
|
|
26
|
+
more: a Citrix-or-canvas task (pixel fallback, one-node tree) and a replay
|
|
27
|
+
task (run the same task again from a saved script), so the differentiators
|
|
28
|
+
below are measured against this baseline. Compare glovebox, Anthropic
|
|
29
|
+
computer use (screenshot-first), and one per-action AX MCP server
|
|
30
|
+
(open-computer-use or agent-desktop). Measure model round trips,
|
|
31
|
+
input tokens including image tokens, output tokens, wall-clock time, and
|
|
32
|
+
success over N runs per task, plus the token cost of a diff versus a full
|
|
33
|
+
tree. For the token work below, also count full re-prints caused by a
|
|
34
|
+
baseline mismatch, "no change" reads followed by another read, screenshots
|
|
35
|
+
per text task, and per-result text characters and image pixels (logged by
|
|
36
|
+
the kernel). Results must split input tokens into uncached, cache write,
|
|
37
|
+
and cache read, because with prompt caching round trips dominate cost.
|
|
38
|
+
Done when the raw results and the harness are in the repo and one chart is
|
|
39
|
+
in the README.
|
|
40
|
+
2. **A prebuilt helper.** Ship a Developer ID signed, notarized helper in each
|
|
41
|
+
release. Done when `npx -y @vashp2029/glovebox setup` works on a Mac without
|
|
42
|
+
the Xcode command line tools and grants survive an upgrade.
|
|
43
|
+
3. **Demo media, then launch.** Record a GIF and a short video. Launch (Show HN, X, Codex computer-use
|
|
44
|
+
threads) only after one or two of these exist. Done when the GIF is at the
|
|
45
|
+
top of the README.
|
|
46
|
+
4. **Exercise every documented client.** Run the Codex, Grok CLI, OpenCode,
|
|
47
|
+
Gemini CLI, and Cursor configs end to end, with a short clip for each.
|
|
48
|
+
Done when `docs/agents.md` and the README's "Works with" line list each
|
|
49
|
+
client as verified or say what failed.
|
|
50
|
+
5. **CI on real GUI runs.** Unit tests run on every push and PR. Smoke tests
|
|
51
|
+
still need a Mac with permissions granted, so they run by hand.
|
|
52
|
+
6. **Listings.** The official MCP registry, the Claude Code plugin
|
|
53
|
+
marketplace, and skills.sh (for `skills/glovebox/SKILL.md`). Done when each
|
|
54
|
+
listing is live and links back to the repo.
|
|
55
|
+
7. **Packaging and docs fixes found in review.** Done; see the changelog.
|
|
56
|
+
|
|
57
|
+
After these, Windows is the highest-priority platform: cross-platform support
|
|
58
|
+
is what lcu, agent-desktop, open-computer-use, and cua have over glovebox, and
|
|
59
|
+
Windows-MCP has about 10.5k stars.
|
|
60
|
+
|
|
61
|
+
## Token efficiency
|
|
62
|
+
|
|
63
|
+
Ranked by round trips saved. Each call re-reads the cached context and adds
|
|
64
|
+
reasoning and output tokens, so a round trip costs more than trimming one
|
|
65
|
+
read. Savings are estimates from reading the code, to be confirmed by the
|
|
66
|
+
benchmark. Effort: S is small, M is medium.
|
|
67
|
+
|
|
68
|
+
1. **Silent structured lookups.** Add `app.find({role, label, id})`,
|
|
69
|
+
`app.text(i)`, and `app.nodes()`, which return data without printing, plus
|
|
70
|
+
one instruction line in the tool description and `skills/glovebox/SKILL.md`.
|
|
71
|
+
`app.text` also gives the full value of a field, which a read truncates at
|
|
72
|
+
160 characters. Saves 1-2 round trips on text and web tasks. S.
|
|
73
|
+
2. **A read that waits for change.** Done: `app.waitForChange()` and
|
|
74
|
+
`app.settle()`.
|
|
75
|
+
3. **Checks inside the script.** An `expect` helper lets one call chain
|
|
76
|
+
several steps, stop at the first failed check, and print state on failure
|
|
77
|
+
or error. Per-action tools cannot do this. Saves 0.5-1 round trip per task
|
|
78
|
+
and per error. S.
|
|
79
|
+
4. **Outline for large trees.** Above about 250 nodes, show an outline
|
|
80
|
+
instead of the full tree, and prune offscreen nodes with a summary line.
|
|
81
|
+
Helps Electron and web apps and saves 5-8k tokens per full read. Adds no
|
|
82
|
+
round trip, because the script can call `find` in the same call. M.
|
|
83
|
+
5. **Field labels and window notices.** Resolve `AXTitleUIElement` and
|
|
84
|
+
`AXLabelUIElements` into field labels, and add a one-line notice when a
|
|
85
|
+
window, sheet, or alert opens. Helps forms and save sheets by avoiding
|
|
86
|
+
screenshots, and makes scripts that skip the read safe. S.
|
|
87
|
+
6. **Line-format cleanup.** Quiet `AXShowMenu` (it is not in `QUIET_ACTIONS`),
|
|
88
|
+
drop auto-generated `_NS:` ids, show `help=` only when there is no label,
|
|
89
|
+
collapse scroll bars into `scrolled N%`, and drop single-child unlabeled
|
|
90
|
+
groups. A guess of 20-40% off a full tree, to be verified. S.
|
|
91
|
+
7. **Diffs that survive context clearing.** A `read #N` header on each read,
|
|
92
|
+
and role plus label in short removed lists, so a diff still makes sense
|
|
93
|
+
after the earlier tree has left the context. S.
|
|
94
|
+
8. **Cheaper images.** `getScreenshot({region})` crops, and a hint when the
|
|
95
|
+
tree has two or fewer nodes. JPEG and grayscale save no tokens, because
|
|
96
|
+
images are charged by pixel size. Lowering the default scale would change
|
|
97
|
+
the click coordinate space, so it is not planned. S-M.
|
|
98
|
+
|
|
99
|
+
Not doing (backfires):
|
|
100
|
+
|
|
101
|
+
- An automatic read after every action: it adds tokens to calls that did not
|
|
102
|
+
need a read.
|
|
103
|
+
- Aggressive pruning: the agent loses elements it needs and spends a round
|
|
104
|
+
trip finding them.
|
|
105
|
+
- Diffs that show only changed attributes: they are harder to read and the
|
|
106
|
+
line no longer identifies the element.
|
|
107
|
+
- A smaller default screenshot scale: it changes the click coordinate space.
|
|
108
|
+
- An outline-first read for small trees: it adds a round trip below about
|
|
109
|
+
2-3k tokens.
|
|
110
|
+
|
|
111
|
+
## Differentiators
|
|
112
|
+
|
|
113
|
+
Two features no other tool checked has, as far as their READMEs show (eight
|
|
114
|
+
competitors checked on 2026-10-27).
|
|
115
|
+
|
|
116
|
+
1. **Local OCR text.** `app.getText()` runs Vision `VNRecognizeTextRequest`
|
|
117
|
+
in the helper and returns diffable `"text" @x,y` lines in click
|
|
118
|
+
space. It targets Citrix, canvases, and remote desktops, where the tree is
|
|
119
|
+
one node. None of the eight competitors checked documents this. The OCR
|
|
120
|
+
runs locally, but the recognized text still goes to the model.
|
|
121
|
+
2. **Durable scripts and replay.** Selectors (token item 1) and `waitFor`
|
|
122
|
+
(token item 2) feed functions saved to `~/.glovebox/lib/*.mjs`, which load
|
|
123
|
+
automatically. `glovebox run file.mjs` replays a script with zero model
|
|
124
|
+
calls. For comparison, ghost-os recipes appear to need a small model, and
|
|
125
|
+
Peekaboo and open-computer-use replay JSON step lists with no branching.
|
|
126
|
+
|
|
127
|
+
## Windows backend
|
|
128
|
+
|
|
129
|
+
Plan: a PowerShell helper (no install beyond Windows itself) that speaks the
|
|
130
|
+
backend protocol over a named pipe.
|
|
131
|
+
|
|
132
|
+
- Tree and actions: UI Automation through `System.Windows.Automation`
|
|
133
|
+
(`InvokePattern` for presses, `ValuePattern` for `setValue`,
|
|
134
|
+
`TextPattern`/`SelectionItemPattern` where present). Stable indices from
|
|
135
|
+
`RuntimeId`.
|
|
136
|
+
- Input: `SendInput` via a small `Add-Type` C# shim; `PostMessage` for
|
|
137
|
+
background keys where the target accepts it.
|
|
138
|
+
- Screenshots: `PrintWindow` with `PW_RENDERFULLCONTENT`, resized to the
|
|
139
|
+
requested size.
|
|
140
|
+
- Approval dialog: a WinForms message box from the helper.
|
|
141
|
+
|
|
142
|
+
## Linux backend
|
|
143
|
+
|
|
144
|
+
Plan: a Python helper.
|
|
145
|
+
|
|
146
|
+
- Tree and actions: AT-SPI over D-Bus (`pyatspi` or `gi.repository.Atspi`).
|
|
147
|
+
- Input: XTest on X11. Wayland compositors restrict synthetic input and
|
|
148
|
+
screen capture; support will be per compositor (portal-based capture,
|
|
149
|
+
`ydotool` or the RemoteDesktop portal for input), and some will not work.
|
|
150
|
+
- Screenshots: X11 `XGetImage` on the window; the ScreenCast portal on Wayland.
|
|
151
|
+
- Approval dialog: `zenity` or `kdialog`, else allowlist mode only.
|
|
152
|
+
|
|
153
|
+
## macOS improvements
|
|
154
|
+
|
|
155
|
+
- Chromium/Electron keyboard input on macOS 15+ may need an
|
|
156
|
+
`SLSEventAuthenticationMessage` attached to each key event; not done yet.
|
|
157
|
+
- Menu shortcuts (⌘S and friends) in background apps: press the menu item
|
|
158
|
+
through accessibility instead of sending the key.
|
|
159
|
+
- Detect apps that ignore background input and fall back automatically,
|
|
160
|
+
instead of relying on `foregroundApps` in the config.
|
|
161
|
+
- Test matrix beyond AppKit: Safari/WebKit, Electron apps, SwiftUI-only apps,
|
|
162
|
+
Citrix Viewer.
|
|
163
|
+
- MCP elicitation as an alternative to the native approval dialog when the
|
|
164
|
+
client supports it.
|
|
165
|
+
- `app.menu(["File", "Export…"])` through the menu bar tree.
|
|
166
|
+
- Optional settle detection (wait until the tree stops changing) instead of
|
|
167
|
+
a fixed delay after actions.
|
package/docs/testing.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Testing
|
|
2
|
+
|
|
3
|
+
glovebox has two kinds of tests. Unit tests cover the pure parts and run
|
|
4
|
+
anywhere. The smoke test drives real apps through the real MCP server and
|
|
5
|
+
helper, so it runs only on macOS with the helper built and permissions granted.
|
|
6
|
+
Nothing in the smoke test is mocked.
|
|
7
|
+
|
|
8
|
+
## What has been run for real on macOS 27 (Apple silicon)
|
|
9
|
+
|
|
10
|
+
- `glovebox smoke` over MCP: one batched call types `6*7=` and reads `42`;
|
|
11
|
+
the binding persists to the next call; index clicks compute `7+1=8` and
|
|
12
|
+
the read comes back as a diff; a pixel click lands on the `9` key; the
|
|
13
|
+
screenshot is 460x816, the same space as clicks; `js_reset` drops bindings.
|
|
14
|
+
- Claude Code (headless) attached through `glovebox mcp`: two calls, the
|
|
15
|
+
second reusing the first call's binding.
|
|
16
|
+
- `glovebox smoke --full` with Firefox frontmost the whole time: background
|
|
17
|
+
keys in Calculator; in TextEdit, a pixel click placed the caret, a drag
|
|
18
|
+
selected a line, a scroll moved the view; the frontmost app never changed.
|
|
19
|
+
- The approval dialog, a blocked app (Terminal) being refused, and Escape to
|
|
20
|
+
stop a script.
|
|
21
|
+
|
|
22
|
+
The Grok, OpenCode, and Codex configs in `agents.md` follow each client's
|
|
23
|
+
documented MCP format but have not been exercised end to end yet.
|
|
24
|
+
|
|
25
|
+
## Unit tests
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm test # node --test test/ (Node 22+: node --test test/unit.test.mjs)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`test/unit.test.mjs` needs only Node. It checks:
|
|
32
|
+
|
|
33
|
+
- cell rewriting: top-level bindings persist across cells and can be
|
|
34
|
+
redeclared; destructuring and imports become bindings; a rejected top-level
|
|
35
|
+
`await` rejects instead of hanging; syntax errors report a line.
|
|
36
|
+
- key parsing: xdotool chords, modifier aliases, and unknown modifiers.
|
|
37
|
+
- tree text: compact lines, and diffs keyed by element index (`~`, `+`,
|
|
38
|
+
removed).
|
|
39
|
+
- image space: window pixels round-trip to screen points, and large windows
|
|
40
|
+
are scaled to the pixel budget.
|
|
41
|
+
|
|
42
|
+
## Smoke test
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
glovebox smoke
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Starts `glovebox mcp` as a client would and works on Calculator. It prints one
|
|
49
|
+
`PASS` or `FAIL` line per check and exits 0 only if all pass. Calculator's
|
|
50
|
+
state changes during the run. The first time, macOS may ask to approve
|
|
51
|
+
Calculator for "glovebox smoke"; run `glovebox allow Calculator TextEdit`
|
|
52
|
+
first to skip the dialogs. Checks:
|
|
53
|
+
|
|
54
|
+
1. MCP handshake: the server is named `glovebox` and lists two tools.
|
|
55
|
+
2. A batched call types `6*7=` and the read shows `42`.
|
|
56
|
+
3. The binding persists to the next call; clicking by element index computes
|
|
57
|
+
`7+1=8`; the read is a diff ("changes since last read").
|
|
58
|
+
4. A pixel click at an element's `center()` presses the `9` key.
|
|
59
|
+
5. A screenshot is one image whose size equals `calc.view`, the pixel space
|
|
60
|
+
clicks use.
|
|
61
|
+
6. `js_reset` drops the binding: `typeof calc` is `undefined`.
|
|
62
|
+
7. The frontmost app was the same before and after (checked with
|
|
63
|
+
`osascript`; skipped if it cannot run).
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
glovebox smoke --full
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Runs the checks above, then writes two temporary text files, opens them in
|
|
70
|
+
TextEdit without activating it (`open -g`), and checks raw mouse input in the
|
|
71
|
+
background:
|
|
72
|
+
|
|
73
|
+
1. A pixel click places the caret: typing `Y` lands at the start of the text.
|
|
74
|
+
2. A drag selects text: typing `Q` replaces the selection.
|
|
75
|
+
3. A scroll moves the view: a scroll bar's value changes on a 300-line file.
|
|
76
|
+
|
|
77
|
+
The frontmost-app check then covers these steps too. The two documents stay
|
|
78
|
+
open in TextEdit; close them without saving (the temp directory is printed).
|
|
79
|
+
For a meaningful result, keep some other app frontmost while it runs.
|