@monoes/monomindcli 1.10.31 → 1.10.33
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/.claude/commands/browse.md +6 -17
- package/.claude/helpers/handlers/budget-status-handler.cjs +14 -0
- package/.claude/helpers/handlers/compact-handler.cjs +33 -0
- package/.claude/helpers/handlers/loops-status-handler.cjs +45 -0
- package/.claude/helpers/handlers/session-restore-handler.cjs +21 -15
- package/.claude/helpers/handlers/stats-handler.cjs +14 -0
- package/.claude/helpers/hook-handler.cjs +10 -70
- package/.claude/helpers/statusline.cjs +16 -5
- package/.claude/skills/agent-browser-testing/SKILL.md +149 -151
- package/.claude/skills/monomind/browse-agentcore.md +20 -21
- package/.claude/skills/monomind/browse-electron.md +45 -46
- package/.claude/skills/monomind/browse-qa.md +29 -30
- package/.claude/skills/monomind/browse-references/authentication.md +39 -40
- package/.claude/skills/monomind/browse-references/trust-boundaries.md +1 -2
- package/.claude/skills/monomind/browse-references/video-recording.md +23 -24
- package/.claude/skills/monomind/browse-slack.md +52 -53
- package/.claude/skills/monomind/browse-vercel.md +26 -27
- package/.claude/skills/monomind/browse.md +273 -273
- package/dist/src/ui/.monomind/sessions/current.json +1 -1
- package/dist/src/ui/dashboard-v2.html +770 -15
- package/dist/src/ui/server.mjs +34 -0
- package/package.json +1 -1
|
@@ -14,10 +14,9 @@ triggers:
|
|
|
14
14
|
tools:
|
|
15
15
|
- Bash
|
|
16
16
|
requires:
|
|
17
|
-
-
|
|
17
|
+
- monomind >= 1.0.0
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
<!-- Pattern adapted from agent-browser — rebranded for monomind -->
|
|
21
20
|
|
|
22
21
|
# Slack Browser Automation (monomind:browse-slack)
|
|
23
22
|
|
|
@@ -29,13 +28,13 @@ See `monomind:browse` for the full browser automation reference. For API-based S
|
|
|
29
28
|
|
|
30
29
|
```bash
|
|
31
30
|
# Connect to existing Slack browser session
|
|
32
|
-
|
|
31
|
+
npx monomind browse open --port 0
|
|
33
32
|
|
|
34
33
|
# Or open Slack fresh
|
|
35
|
-
|
|
34
|
+
npx monomind browse open https://app.slack.com
|
|
36
35
|
|
|
37
36
|
# Take a snapshot to see what's available
|
|
38
|
-
|
|
37
|
+
npx monomind browse snapshot -i
|
|
39
38
|
```
|
|
40
39
|
|
|
41
40
|
## Core Loop
|
|
@@ -49,66 +48,66 @@ Connect/Open → Snapshot -i → Navigate → Extract/Interact → Screenshot
|
|
|
49
48
|
### Check Unread Messages
|
|
50
49
|
|
|
51
50
|
```bash
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
npx monomind browse open --port 0
|
|
52
|
+
npx monomind browse snapshot -i
|
|
54
53
|
|
|
55
54
|
# Navigate to Activity tab (all unreads in one view)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
npx monomind browse click @e14 # Activity tab
|
|
56
|
+
npx monomind browse wait 1000
|
|
57
|
+
npx monomind browse screenshot activity-unreads.png
|
|
59
58
|
|
|
60
59
|
# Or expand "More unreads" in sidebar
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
60
|
+
npx monomind browse click @e21 # More unreads button
|
|
61
|
+
npx monomind browse wait 500
|
|
62
|
+
npx monomind browse snapshot -i
|
|
63
|
+
npx monomind browse screenshot unreads.png
|
|
65
64
|
```
|
|
66
65
|
|
|
67
66
|
### Navigate to a Channel
|
|
68
67
|
|
|
69
68
|
```bash
|
|
70
|
-
|
|
69
|
+
npx monomind browse snapshot -i
|
|
71
70
|
# Find channel name in sidebar (treeitem elements)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
npx monomind browse click @e94 # example channel ref
|
|
72
|
+
npx monomind browse wait --load networkidle
|
|
73
|
+
npx monomind browse screenshot channel.png
|
|
75
74
|
```
|
|
76
75
|
|
|
77
76
|
### Search Slack
|
|
78
77
|
|
|
79
78
|
```bash
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
79
|
+
npx monomind browse snapshot -i
|
|
80
|
+
npx monomind browse click @e5 # Search button
|
|
81
|
+
npx monomind browse fill @e_search "keyword"
|
|
82
|
+
npx monomind browse press Enter
|
|
83
|
+
npx monomind browse wait --load networkidle
|
|
84
|
+
npx monomind browse screenshot search-results.png
|
|
86
85
|
```
|
|
87
86
|
|
|
88
87
|
### Extract Channel Info
|
|
89
88
|
|
|
90
89
|
```bash
|
|
91
|
-
|
|
90
|
+
npx monomind browse snapshot --json > slack-snapshot.json
|
|
92
91
|
# Parse for treeitem elements (channel names) and listitem elements (messages)
|
|
93
92
|
```
|
|
94
93
|
|
|
95
94
|
### Send a Message
|
|
96
95
|
|
|
97
96
|
```bash
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
97
|
+
npx monomind browse click @e_channel # open channel
|
|
98
|
+
npx monomind browse wait --load networkidle
|
|
99
|
+
npx monomind browse snapshot -i
|
|
100
|
+
npx monomind browse fill @e_composer "Hello from monomind!"
|
|
101
|
+
npx monomind browse press Enter
|
|
102
|
+
npx monomind browse wait 1000
|
|
103
|
+
npx monomind browse screenshot sent.png
|
|
105
104
|
```
|
|
106
105
|
|
|
107
106
|
### Scroll Through Messages
|
|
108
107
|
|
|
109
108
|
```bash
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
npx monomind browse scroll down 500 --selector ".p-message_list"
|
|
110
|
+
npx monomind browse snapshot -i
|
|
112
111
|
```
|
|
113
112
|
|
|
114
113
|
## Sidebar Layout
|
|
@@ -128,14 +127,14 @@ Key tabs to look for: `@e12` Home, `@e13` DMs, `@e14` Activity, `@e5` Search, `@
|
|
|
128
127
|
|
|
129
128
|
```bash
|
|
130
129
|
# Text content of a message or element
|
|
131
|
-
|
|
130
|
+
npx monomind browse get text @e_message
|
|
132
131
|
|
|
133
132
|
# Full structured snapshot for parsing
|
|
134
|
-
|
|
133
|
+
npx monomind browse snapshot --json > output.json
|
|
135
134
|
# Look for: treeitem (channels), listitem/document (messages), button (users), link (timestamps)
|
|
136
135
|
|
|
137
136
|
# Count unread items after expanding unreads
|
|
138
|
-
|
|
137
|
+
npx monomind browse snapshot -i | grep -c "treeitem"
|
|
139
138
|
```
|
|
140
139
|
|
|
141
140
|
## Best Practices
|
|
@@ -156,34 +155,34 @@ agent-browser snapshot -i | grep -c "treeitem"
|
|
|
156
155
|
## Debugging
|
|
157
156
|
|
|
158
157
|
```bash
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
158
|
+
npx monomind browse console # browser console messages
|
|
159
|
+
npx monomind browse errors # uncaught JS exceptions
|
|
160
|
+
npx monomind browse get url # current URL
|
|
161
|
+
npx monomind browse screenshot page-state.png
|
|
163
162
|
```
|
|
164
163
|
|
|
165
164
|
## Full Unread Check Script
|
|
166
165
|
|
|
167
166
|
```bash
|
|
168
167
|
#!/bin/bash
|
|
169
|
-
|
|
170
|
-
|
|
168
|
+
npx monomind browse open --port 0
|
|
169
|
+
npx monomind browse snapshot -i
|
|
171
170
|
|
|
172
171
|
# Activity tab
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
172
|
+
npx monomind browse click @e14
|
|
173
|
+
npx monomind browse wait 1000
|
|
174
|
+
npx monomind browse screenshot activity.png
|
|
176
175
|
|
|
177
176
|
# DMs tab
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
177
|
+
npx monomind browse click @e13
|
|
178
|
+
npx monomind browse wait 1000
|
|
179
|
+
npx monomind browse screenshot dms.png
|
|
181
180
|
|
|
182
181
|
# More unreads
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
182
|
+
npx monomind browse click @e21
|
|
183
|
+
npx monomind browse wait 500
|
|
184
|
+
npx monomind browse snapshot -i
|
|
185
|
+
npx monomind browse screenshot unreads.png
|
|
187
186
|
|
|
188
187
|
echo "See activity.png, dms.png, unreads.png"
|
|
189
188
|
```
|
|
@@ -12,15 +12,14 @@ triggers:
|
|
|
12
12
|
tools:
|
|
13
13
|
- Bash
|
|
14
14
|
requires:
|
|
15
|
-
-
|
|
15
|
+
- monomind >= 1.0.0
|
|
16
16
|
- "@vercel/sandbox"
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
-
<!-- Pattern adapted from agent-browser — rebranded for monomind -->
|
|
20
19
|
|
|
21
20
|
# Vercel Sandbox Browser Automation (monomind:browse-vercel)
|
|
22
21
|
|
|
23
|
-
Run
|
|
22
|
+
Run monomind browse + headless Chrome inside ephemeral Vercel Sandbox microVMs. A Linux VM spins up on demand, executes browser commands, and shuts down. Works with Next.js, SvelteKit, Nuxt, Remix, Astro, and any Vercel-deployed framework.
|
|
24
23
|
|
|
25
24
|
See `monomind:browse` for the full browser automation reference.
|
|
26
25
|
|
|
@@ -78,8 +77,8 @@ async function withBrowser<T>(
|
|
|
78
77
|
"-c",
|
|
79
78
|
`sudo dnf clean all 2>&1 && sudo dnf install -y --skip-broken ${CHROMIUM_SYSTEM_DEPS.join(" ")} 2>&1 && sudo ldconfig 2>&1`,
|
|
80
79
|
]);
|
|
81
|
-
await sandbox.runCommand(
|
|
82
|
-
await sandbox.runCommand(
|
|
80
|
+
await sandbox.runCommand(# monomind browse is built-in);
|
|
81
|
+
await sandbox.runCommand(# no install needed);
|
|
83
82
|
}
|
|
84
83
|
|
|
85
84
|
try {
|
|
@@ -95,21 +94,21 @@ async function withBrowser<T>(
|
|
|
95
94
|
```typescript
|
|
96
95
|
export async function screenshotUrl(url: string) {
|
|
97
96
|
return withBrowser(async (sandbox) => {
|
|
98
|
-
await sandbox.runCommand("
|
|
97
|
+
await sandbox.runCommand("npx monomind browse", ["open", url]);
|
|
99
98
|
|
|
100
|
-
const titleResult = await sandbox.runCommand("
|
|
99
|
+
const titleResult = await sandbox.runCommand("npx monomind browse", [
|
|
101
100
|
"get", "title", "--json",
|
|
102
101
|
]);
|
|
103
102
|
const title = JSON.parse(await titleResult.stdout())?.data?.title || url;
|
|
104
103
|
|
|
105
|
-
const ssResult = await sandbox.runCommand("
|
|
104
|
+
const ssResult = await sandbox.runCommand("npx monomind browse", [
|
|
106
105
|
"screenshot", "--json",
|
|
107
106
|
]);
|
|
108
107
|
const ssPath = JSON.parse(await ssResult.stdout())?.data?.path;
|
|
109
108
|
const b64Result = await sandbox.runCommand("base64", ["-w", "0", ssPath]);
|
|
110
109
|
const screenshot = (await b64Result.stdout()).trim();
|
|
111
110
|
|
|
112
|
-
await sandbox.runCommand("
|
|
111
|
+
await sandbox.runCommand("npx monomind browse", ["close"]);
|
|
113
112
|
return { title, screenshot };
|
|
114
113
|
});
|
|
115
114
|
}
|
|
@@ -120,19 +119,19 @@ export async function screenshotUrl(url: string) {
|
|
|
120
119
|
```typescript
|
|
121
120
|
export async function snapshotUrl(url: string) {
|
|
122
121
|
return withBrowser(async (sandbox) => {
|
|
123
|
-
await sandbox.runCommand("
|
|
122
|
+
await sandbox.runCommand("npx monomind browse", ["open", url]);
|
|
124
123
|
|
|
125
|
-
const titleResult = await sandbox.runCommand("
|
|
124
|
+
const titleResult = await sandbox.runCommand("npx monomind browse", [
|
|
126
125
|
"get", "title", "--json",
|
|
127
126
|
]);
|
|
128
127
|
const title = JSON.parse(await titleResult.stdout())?.data?.title || url;
|
|
129
128
|
|
|
130
|
-
const snapResult = await sandbox.runCommand("
|
|
129
|
+
const snapResult = await sandbox.runCommand("npx monomind browse", [
|
|
131
130
|
"snapshot", "-i", "-c",
|
|
132
131
|
]);
|
|
133
132
|
const snapshot = await snapResult.stdout();
|
|
134
133
|
|
|
135
|
-
await sandbox.runCommand("
|
|
134
|
+
await sandbox.runCommand("npx monomind browse", ["close"]);
|
|
136
135
|
return { title, snapshot };
|
|
137
136
|
});
|
|
138
137
|
}
|
|
@@ -143,25 +142,25 @@ export async function snapshotUrl(url: string) {
|
|
|
143
142
|
```typescript
|
|
144
143
|
export async function fillAndSubmitForm(url: string, data: Record<string, string>) {
|
|
145
144
|
return withBrowser(async (sandbox) => {
|
|
146
|
-
await sandbox.runCommand("
|
|
145
|
+
await sandbox.runCommand("npx monomind browse", ["open", url]);
|
|
147
146
|
|
|
148
|
-
const snapResult = await sandbox.runCommand("
|
|
147
|
+
const snapResult = await sandbox.runCommand("npx monomind browse", ["snapshot", "-i"]);
|
|
149
148
|
const snapshot = await snapResult.stdout();
|
|
150
149
|
// Parse snapshot to identify refs...
|
|
151
150
|
|
|
152
151
|
for (const [ref, value] of Object.entries(data)) {
|
|
153
|
-
await sandbox.runCommand("
|
|
152
|
+
await sandbox.runCommand("npx monomind browse", ["fill", ref, value]);
|
|
154
153
|
}
|
|
155
154
|
|
|
156
|
-
await sandbox.runCommand("
|
|
157
|
-
await sandbox.runCommand("
|
|
155
|
+
await sandbox.runCommand("npx monomind browse", ["click", "@e5"]);
|
|
156
|
+
await sandbox.runCommand("npx monomind browse", ["wait", "--load", "networkidle"]);
|
|
158
157
|
|
|
159
|
-
const ssResult = await sandbox.runCommand("
|
|
158
|
+
const ssResult = await sandbox.runCommand("npx monomind browse", ["screenshot", "--json"]);
|
|
160
159
|
const ssPath = JSON.parse(await ssResult.stdout())?.data?.path;
|
|
161
160
|
const b64Result = await sandbox.runCommand("base64", ["-w", "0", ssPath]);
|
|
162
161
|
const screenshot = (await b64Result.stdout()).trim();
|
|
163
162
|
|
|
164
|
-
await sandbox.runCommand("
|
|
163
|
+
await sandbox.runCommand("npx monomind browse", ["close"]);
|
|
165
164
|
return { screenshot };
|
|
166
165
|
});
|
|
167
166
|
}
|
|
@@ -169,9 +168,9 @@ export async function fillAndSubmitForm(url: string, data: Record<string, string
|
|
|
169
168
|
|
|
170
169
|
## Sandbox Snapshots (Sub-Second Startup)
|
|
171
170
|
|
|
172
|
-
A sandbox snapshot pre-installs system deps +
|
|
171
|
+
A sandbox snapshot pre-installs system deps + monomind + Chromium so each run boots in under 1 second instead of ~30s.
|
|
173
172
|
|
|
174
|
-
> Note: "sandbox snapshot" is a Vercel infrastructure concept (like a Docker image). It is NOT the same as `
|
|
173
|
+
> Note: "sandbox snapshot" is a Vercel infrastructure concept (like a Docker image). It is NOT the same as `monomind browse snapshot` (accessibility tree dump).
|
|
175
174
|
|
|
176
175
|
### Create a snapshot (run once)
|
|
177
176
|
|
|
@@ -185,8 +184,8 @@ async function createSnapshot(): Promise<string> {
|
|
|
185
184
|
"-c",
|
|
186
185
|
`sudo dnf clean all 2>&1 && sudo dnf install -y --skip-broken ${CHROMIUM_SYSTEM_DEPS.join(" ")} 2>&1 && sudo ldconfig 2>&1`,
|
|
187
186
|
]);
|
|
188
|
-
await sandbox.runCommand(
|
|
189
|
-
await sandbox.runCommand(
|
|
187
|
+
await sandbox.runCommand(# monomind browse is built-in);
|
|
188
|
+
await sandbox.runCommand(# no install needed);
|
|
190
189
|
|
|
191
190
|
const snapshot = await sandbox.snapshot();
|
|
192
191
|
return snapshot.snapshotId;
|
|
@@ -205,9 +204,9 @@ AGENT_BROWSER_SNAPSHOT_ID=snap_xxxxxxxxxxxx
|
|
|
205
204
|
// app/api/cron/route.ts (Next.js example)
|
|
206
205
|
export async function GET() {
|
|
207
206
|
const result = await withBrowser(async (sandbox) => {
|
|
208
|
-
await sandbox.runCommand("
|
|
209
|
-
const snap = await sandbox.runCommand("
|
|
210
|
-
await sandbox.runCommand("
|
|
207
|
+
await sandbox.runCommand("npx monomind browse", ["open", "https://example.com/pricing"]);
|
|
208
|
+
const snap = await sandbox.runCommand("npx monomind browse", ["snapshot", "-i", "-c"]);
|
|
209
|
+
await sandbox.runCommand("npx monomind browse", ["close"]);
|
|
211
210
|
return await snap.stdout();
|
|
212
211
|
});
|
|
213
212
|
|