glidercli 0.3.9 → 0.3.13
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 +113 -189
- package/bin/glider.js +34 -11
- package/config/domains.template.json +15 -0
- package/docs/setup.json +6 -1
- package/lib/domain-resolve.js +75 -0
- package/lib/paths.js +76 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -8,195 +8,116 @@
|
|
|
8
8
|
<h1 align="center">glider CLI</h1>
|
|
9
9
|
<p align="center"><i><b>Browser automation CLI with autonomous loop execution</b></i></p>
|
|
10
10
|
|
|
11
|
-
<a href="https://github.com/vdutts7/glidercli"><img src="./assets/badges/github.badge.svg" alt="GitHub" height="34" /></a>
|
|
11
|
+
<a href="https://github.com/vdutts7/glidercli"><img src="./assets/badges/github.badge.svg" alt="GitHub" height="34" /></a>
|
|
12
|
+
<a href="https://www.npmjs.com/package/glidercli"><img src="./assets/badges/npm.badge.svg" alt="glidercli on npm" height="34" /></a>
|
|
12
13
|
|
|
13
14
|
</div>
|
|
14
15
|
|
|
15
16
|
<br/>
|
|
16
17
|
|
|
17
|
-
## About
|
|
18
|
-
|
|
19
|
-
| | |
|
|
20
|
-
|---|---|
|
|
21
|
-
| **What** | Control a **Chromium-based** browser from the terminal via CDP, run YAML tasks, and loop until done (Ralph Wiggum pattern) |
|
|
22
|
-
| **CDP** | Chrome DevTools Protocol via relay + browser extension |
|
|
23
|
-
| **Tasks** | Declarative steps: `goto`, `click`, `explore`, `eval`, `screenshot` |
|
|
24
|
-
| **Loops** | Run until completion marker or max iterations / timeout |
|
|
25
|
-
| **Safety** | Max iterations, timeout, backoff |
|
|
26
|
-
|
|
27
18
|
---
|
|
28
19
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
|
32
|
-
|
|
33
|
-
|
|
|
34
|
-
| **2. Extension** | [Install Glider from Chrome Web Store](https://chromewebstore.google.com/detail/glider/njbidokkffhgpofcejgcfcgcinmeoalj) in the same browser/profile you will automate (required, bridges relay ↔ tab) |
|
|
35
|
-
| **3. Daemon** | `glider install` then `glider connect` |
|
|
36
|
-
| **4. Browser (required setup)** | Configure supported browser/profile + extension in the **Browsers** section below. |
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
## Requirements
|
|
20
|
+
| | headless CDP | extension relay (glider) |
|
|
21
|
+
|---|--------------|---------------------------|
|
|
22
|
+
| logged-in tab / SSO | ❌ cold profile | ✅ attach to open tab |
|
|
23
|
+
| corp / MFA sessions | ❌ re-auth wall | ✅ reuse browser cookies |
|
|
24
|
+
| loop until done | manual glue | ✅ `glider loop` + markers |
|
|
40
25
|
|
|
41
|
-
|
|
42
|
-
|-------------|---------|
|
|
43
|
-
| Node | 18+ |
|
|
44
|
-
| Browser | Chromium-based (Chrome, Arc, Edge, Brave, Opera, Vivaldi) with the Glider extension installed/enabled in that browser profile. No Firefox/Safari/DuckDuckGo |
|
|
26
|
+
`glidercli` → relay at `ws://127.0.0.1:19988` → [`Glider extension`](https://chromewebstore.google.com/detail/glider/njbidokkffhgpofcejgcfcgcinmeoalj) → CDP on your tab.
|
|
45
27
|
|
|
46
28
|
---
|
|
47
29
|
|
|
48
|
-
##
|
|
49
|
-
|
|
50
|
-
| | |
|
|
51
|
-
|---|---|
|
|
52
|
-
| **How it works** | Chrome extension → WebSocket relay → CDP. Browser must support that extension (Chromium-based). |
|
|
30
|
+
## Issue
|
|
53
31
|
|
|
54
|
-
|
|
32
|
+
| failure mode | symptom |
|
|
33
|
+
|--------------|---------|
|
|
34
|
+
| ❌ cold profile launch | SSO/MFA breaks on internal sites; no logged-in tab to drive |
|
|
35
|
+
| ❌ raw CDP without bridge | extension must relay debugger traffic from real Chromium profile |
|
|
36
|
+
| ❌ cookie-only terminal fetch | cross-origin API hosts often 401 without in-tab bearer |
|
|
37
|
+
| ❌ one-shot scripts only | no first-class loop with iteration cap, timeout, completion marker |
|
|
55
38
|
|
|
56
|
-
|
|
39
|
+
---
|
|
57
40
|
|
|
58
|
-
|
|
59
|
-
|:---:|--------|--------|
|
|
60
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/chrome.webp" width="16" alt=""> | Google Chrome | Default for `glider connect`|
|
|
61
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/chrome-canary.webp" width="16" alt=""> | Chrome Canary | n/a |
|
|
62
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/arc.webp" width="16" alt=""> | Arc | [browser.json](config/browser.json.example) (`{ "use": "arc" }`) |
|
|
63
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/microsoft/microsoft-edge.webp" width="16" alt=""> | Microsoft Edge | n/a |
|
|
64
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/brave.webp" width="16" alt=""> | Brave | n/a |
|
|
65
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/operagx.webp" width="16" alt=""> | Opera | n/a |
|
|
66
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/vivaldi.webp" width="16" alt=""> | Vivaldi | n/a |
|
|
67
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/chromium.webp" width="16" alt=""> | Other Chromium | Must support installing extensions from the Chrome Web Store. |
|
|
68
|
-
|
|
69
|
-
### Future
|
|
70
|
-
|
|
71
|
-
- not supported today
|
|
72
|
-
- Glider needs a **Chromium-based** browser that can install the extension from the **Chrome Web Store**
|
|
73
|
-
- no timeline implied- listed for clarity
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
| | Browser | Notes |
|
|
77
|
-
|:---:|--------|--------|
|
|
78
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/firefox.webp" width="16" alt=""> | Firefox | **Gecko** (Firefox engine). Not Chromium, Glider uses a Chrome Web Store extension + CDP |
|
|
79
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/firefox-focus.webp" width="16" alt=""> | Firefox Focus | Gecko- same constraints as Firefox |
|
|
80
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/firefox.webp" width="16" alt=""> | Firefox Klar | Gecko (Focus branding in some regions)- same constraints as Firefox |
|
|
81
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/librewolf.webp" width="16" alt=""> | LibreWolf | Gecko- same constraints as Firefox |
|
|
82
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/waterfox.webp" width="16" alt=""> | Waterfox | Gecko- same constraints as Firefox |
|
|
83
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/zen.webp" width="16" alt=""> | Zen | Gecko- same constraints as Firefox |
|
|
84
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/floorp.webp" width="16" alt=""> | Floorp | Gecko- same constraints as Firefox |
|
|
85
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/tor-browser.webp" width="16" alt=""> | Tor Browser | Gecko- same constraints as Firefox |
|
|
86
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/mullvad-browser.webp" width="16" alt=""> | Mullvad Browser | Gecko- same constraints as Firefox |
|
|
87
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/icecat.webp" width="16" alt=""> | IceCat | Gecko- same constraints as Firefox |
|
|
88
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/safari.webp" width="16" alt=""> | Safari | WebKit (Apple desktop). Not Chromium |
|
|
89
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/safari-technology-preview.webp" width="16" alt=""> | Safari Technology Preview | WebKit preview channel (Apple desktop). Not Chromium |
|
|
90
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/orion.webp" width="16" alt=""> | Orion | WebKit-based desktop browser. Not Chromium |
|
|
91
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/dia-browser.webp" width="16" alt=""> | Dia | AI-first browser, not in Glider’s supported Chromium + CWS model today |
|
|
92
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/chatgpt-atlas.webp" width="16" alt=""> | ChatGPT Atlas | AI-first browser, not in Glider’s supported Chromium + CWS model today |
|
|
93
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/perplexity-comet.webp" width="16" alt=""> | Perplexity Comet | AI-first browser, not in Glider’s supported Chromium + CWS model today |
|
|
94
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/whale-browser.webp" width="16" alt=""> | Whale Browser | Chromium-based, support not implemented in Glider today |
|
|
95
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/yandex-browser.webp" width="16" alt=""> | Yandex Browser | Chromium-based, support not implemented in Glider today |
|
|
96
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/bromite.webp" width="16" alt=""> | Bromite | Chromium-derived, no practical Chrome Web Store path for Glider |
|
|
97
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/chromium.webp" width="16" alt=""> | Chromite | Chromium-derived, no practical Chrome Web Store path for Glider |
|
|
98
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/grapheneos.webp" width="16" alt=""> | Vanadium | Chromium-derived (GrapheneOS), no practical Chrome Web Store path for Glider |
|
|
99
|
-
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/duckduckgo.webp" width="16" alt=""> | DuckDuckGo | No practical Chrome Web Store extension install path for Glider |
|
|
100
|
-
|
|
101
|
-
### Configuring the browser
|
|
102
|
-
|
|
103
|
-
**Priority (highest first):** config file -> default `Google Chrome`
|
|
104
|
-
|
|
105
|
-
#### Config file: `$HOME/.glider/config/browser.json`
|
|
106
|
-
|
|
107
|
-
Use a **registry key** or explicit name/path in the file
|
|
108
|
-
|
|
109
|
-
**Option A- Registry key (recommended):**
|
|
110
|
-
|
|
111
|
-
Set browser by key from the browsers registry. Run `glider use <key>` to write this.
|
|
41
|
+
## Setup
|
|
112
42
|
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
43
|
+
```bash
|
|
44
|
+
npm i -g glidercli
|
|
45
|
+
glider install
|
|
46
|
+
glider connect
|
|
117
47
|
```
|
|
118
48
|
|
|
119
|
-
|
|
49
|
+
| Step | Action |
|
|
50
|
+
|------|--------|
|
|
51
|
+
| CLI | `npm i -g glidercli` |
|
|
52
|
+
| Extension | [`Glider` on Chrome Web Store](https://chromewebstore.google.com/detail/glider/njbidokkffhgpofcejgcfcgcinmeoalj) in the profile you automate |
|
|
53
|
+
| Daemon | `glider install` |
|
|
54
|
+
| Session | `glider connect` (once per browser launch) |
|
|
120
55
|
|
|
121
|
-
|
|
56
|
+
Node 18+. Chromium-based browser with the extension enabled (see Browsers).
|
|
122
57
|
|
|
123
|
-
|
|
124
|
-
|-------|:--------:|-------------|
|
|
125
|
-
| `name` | Yes* | App name for `open -a` / AppleScript. Must match system (e.g. `Arc`, `Google Chrome`). |
|
|
126
|
-
| `path` | No | If set, use `open "<path>"` instead of `open -a "<name>"`. For non-default install location. |
|
|
127
|
-
| `processName` | No | For `pgrep -x`. Defaults to `name`. |
|
|
58
|
+
---
|
|
128
59
|
|
|
129
|
-
|
|
60
|
+
## Browsers
|
|
130
61
|
|
|
131
|
-
|
|
62
|
+
Extension + relay model uses Chromium + Glider extension from Chrome Web Store in the same profile as `glider connect`.
|
|
132
63
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
64
|
+
| | Browser | Config |
|
|
65
|
+
|---|--------|--------|
|
|
66
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/chrome.webp" width="16" alt=""> | Google Chrome | default for `glider connect` |
|
|
67
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/arc.webp" width="16" alt=""> | Arc | [`config/browser.json.example`](config/browser.json.example) |
|
|
68
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/microsoft/microsoft-edge.webp" width="16" alt=""> | Microsoft Edge | registry key `edge` |
|
|
69
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/brave.webp" width="16" alt=""> | Brave | registry key `brave` |
|
|
70
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/vivaldi.webp" width="16" alt=""> | Vivaldi | registry key `vivaldi` |
|
|
140
71
|
|
|
141
|
-
|
|
72
|
+
Not supported today: Firefox/Safari/WebKit/Gecko, DuckDuckGo, browsers without Chrome Web Store extension path.
|
|
142
73
|
|
|
143
|
-
|
|
144
|
-
|---------|--------|-------------------|---------------------------|
|
|
145
|
-
| Arc | `Arc` | `/Applications/Arc.app` | `Arc` |
|
|
146
|
-
| Edge | `Microsoft Edge` | n/a | `Microsoft Edge` |
|
|
147
|
-
| Chrome (custom) | `Google Chrome` | `/Users/me/Applications/Google Chrome.app` | `Google Chrome` |
|
|
74
|
+
### Browser config
|
|
148
75
|
|
|
149
|
-
|
|
76
|
+
Priority: `~/.glider/config/browser.json` → default Google Chrome.
|
|
150
77
|
|
|
151
|
-
|
|
78
|
+
Registry key (recommended):
|
|
152
79
|
|
|
153
|
-
|
|
80
|
+
```json
|
|
81
|
+
{ "use": "arc" }
|
|
82
|
+
```
|
|
154
83
|
|
|
155
|
-
|
|
84
|
+
Registry file: `~/.glider/config/browsers-registry.json`
|
|
156
85
|
|
|
157
|
-
|
|
86
|
+
```bash
|
|
87
|
+
glider use arc
|
|
88
|
+
glider browser
|
|
89
|
+
```
|
|
158
90
|
|
|
159
|
-
|
|
91
|
+
Explicit name/path:
|
|
160
92
|
|
|
161
93
|
```json
|
|
162
94
|
{
|
|
163
|
-
"
|
|
164
|
-
"
|
|
165
|
-
|
|
166
|
-
"brave": { "name": "Brave Browser", "path": "/Applications/Brave Browser.app", "processName": "Brave Browser" },
|
|
167
|
-
"chrome": { "name": "Google Chrome", "path": "/Applications/Google Chrome.app", "processName": "Google Chrome" },
|
|
168
|
-
"edge": { "name": "Microsoft Edge", "path": "/Applications/Microsoft Edge.app", "processName": "Microsoft Edge" }
|
|
169
|
-
}
|
|
95
|
+
"name": "Arc",
|
|
96
|
+
"path": "/Applications/Arc.app",
|
|
97
|
+
"processName": "Arc"
|
|
170
98
|
}
|
|
171
99
|
```
|
|
172
100
|
|
|
173
|
-
**Commands:**
|
|
174
|
-
|
|
175
101
|
| Command | Effect |
|
|
176
102
|
|---------|--------|
|
|
177
|
-
| `glider use arc` |
|
|
178
|
-
| `glider use
|
|
179
|
-
| `glider
|
|
180
|
-
| `glider browser` | Show resolved name, path, processName (and `use` key if set). |
|
|
181
|
-
|
|
182
|
-
Add or edit entries in the registry to match your machine (e.g. custom install paths). Keys are stable, point Glider at one by name.
|
|
103
|
+
| `glider use arc` | write `{ "use": "arc" }` to `browser.json` |
|
|
104
|
+
| `glider use` | list registry keys |
|
|
105
|
+
| `glider browser` | show resolved name, path, process |
|
|
183
106
|
|
|
184
|
-
|
|
107
|
+
macOS: `open -a` / AppleScript. Linux/Windows: partial, on roadmap.
|
|
185
108
|
|
|
186
|
-
|
|
187
|
-
|----------|----------|
|
|
188
|
-
| macOS | `open -a "<name>"` or `open "<path>"`, AppleScript for tab/window. `name` = exact app name |
|
|
189
|
-
| Linux / Windows | Not fully implemented. Future: `path` may be executable. |
|
|
109
|
+
---
|
|
190
110
|
|
|
191
|
-
|
|
111
|
+
## Task files
|
|
192
112
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
113
|
+
```yaml
|
|
114
|
+
name: hn-front
|
|
115
|
+
steps:
|
|
116
|
+
goto: "https://news.ycombinator.com"
|
|
117
|
+
wait: 2
|
|
118
|
+
eval: "document.title"
|
|
119
|
+
screenshot: "/tmp/hn.png"
|
|
120
|
+
```
|
|
200
121
|
|
|
201
122
|
---
|
|
202
123
|
|
|
@@ -205,28 +126,41 @@ Add or edit entries in the registry to match your machine (e.g. custom install p
|
|
|
205
126
|
```bash
|
|
206
127
|
glider connect
|
|
207
128
|
glider status
|
|
208
|
-
glider goto "https://
|
|
129
|
+
glider goto "https://news.ycombinator.com"
|
|
209
130
|
glider eval "document.title"
|
|
210
|
-
glider run
|
|
211
|
-
glider loop
|
|
131
|
+
glider run `hn-scrape.yaml`
|
|
132
|
+
glider loop `hn-scrape.yaml` -n 50 -m hn_scrape_done
|
|
212
133
|
```
|
|
213
134
|
|
|
214
|
-
|
|
135
|
+
```bash
|
|
136
|
+
# per-host capture hints (optional)
|
|
137
|
+
glider resolve https://news.ycombinator.com --json
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
| Output | Path |
|
|
215
141
|
|--------|------|
|
|
216
|
-
|
|
|
142
|
+
| daemon log | `~/.glider/daemon.log` |
|
|
143
|
+
| domain index | `~/.glider/config/domains.json` |
|
|
144
|
+
| per-host intel | `~/.glider/warch/HOST/glider.json` |
|
|
145
|
+
| explore cache | `~/.glider/bexplore/HOST/` |
|
|
146
|
+
|
|
147
|
+
| Env | Default | Role |
|
|
148
|
+
|-----|---------|------|
|
|
149
|
+
| `GLIDER_HOME` | `~/.glider` | config, cache, warch tree |
|
|
150
|
+
| `AGREGISTRY` | unset | optional registry root → warch at `$AGREGISTRY/warch/HOST/` |
|
|
151
|
+
|
|
152
|
+
Copy `config/domains.template.json` into `~/.glider/config/domains.json` to seed the host index.
|
|
217
153
|
|
|
218
154
|
---
|
|
219
155
|
|
|
220
|
-
##
|
|
156
|
+
## Gotchas
|
|
221
157
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
-
|
|
226
|
-
-
|
|
227
|
-
-
|
|
228
|
-
- screenshot: "/tmp/out.png"
|
|
229
|
-
```
|
|
158
|
+
| problem | fix | stability | why |
|
|
159
|
+
|---------|-----|-----------|-----|
|
|
160
|
+
| extension not connected | click Glider icon in toolbar → `glider connect` | per Chrome launch | relay waits on extension WS |
|
|
161
|
+
| wrong tab targeted | `glider targets` → `glider use-session session-6` | session-stable | multi-tab needs explicit session |
|
|
162
|
+
| explore HAR empty bodies | replay in-tab with auth hook on XHR/fetch | site-specific | some SPAs never expose bearer in storage |
|
|
163
|
+
| `resolve` misses host | add `~/.glider/warch/HOST/glider.json` or set `AGREGISTRY` | file-stable | optional per-host capture hints |
|
|
230
164
|
|
|
231
165
|
---
|
|
232
166
|
|
|
@@ -234,42 +168,32 @@ steps:
|
|
|
234
168
|
|
|
235
169
|
| Command | Description |
|
|
236
170
|
|---------|-------------|
|
|
237
|
-
| `glider install` |
|
|
238
|
-
| `glider
|
|
239
|
-
| `glider
|
|
240
|
-
| `glider
|
|
241
|
-
| `glider
|
|
242
|
-
| `glider
|
|
243
|
-
| `glider
|
|
244
|
-
| `glider
|
|
245
|
-
| `glider type <sel> <text>` | Type into input |
|
|
246
|
-
| `glider screenshot [path]` | Capture page |
|
|
247
|
-
| `glider run <file>` | Run YAML task |
|
|
248
|
-
| `glider loop <file> [-n N]` | Loop until done or limit |
|
|
249
|
-
|
|
250
|
-
Full list: `glider --help`
|
|
251
|
-
|
|
252
|
-
---
|
|
171
|
+
| `glider install` / `uninstall` | daemon at login |
|
|
172
|
+
| `glider connect` | attach relay to browser |
|
|
173
|
+
| `glider status` | server, extension, tabs |
|
|
174
|
+
| `glider goto` / `eval` / `click` / `type` | page ops |
|
|
175
|
+
| `glider screenshot` | PNG capture |
|
|
176
|
+
| `glider explore` | crawl + HAR |
|
|
177
|
+
| `glider resolve` | host → local warch intel (`--json`) |
|
|
178
|
+
| `glider run` / `loop` | YAML task / Ralph loop |
|
|
253
179
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
| Doc | Contents |
|
|
257
|
-
|-----|----------|
|
|
258
|
-
| This README | Install, usage, commands, full browser support/config |
|
|
259
|
-
| [config/browser.json.example](config/browser.json.example) | Example browser config |
|
|
180
|
+
Full surface: `glider --help`
|
|
260
181
|
|
|
261
182
|
---
|
|
262
183
|
|
|
263
184
|
## Roadmap
|
|
264
185
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
186
|
+
| status | item |
|
|
187
|
+
|--------|------|
|
|
188
|
+
| done | CDP relay, YAML tasks, loop, daemon, multi-tab, `resolve` |
|
|
189
|
+
| planned | Linux and Windows browser launch |
|
|
190
|
+
| | headless cloud mode |
|
|
191
|
+
| | task chaining |
|
|
270
192
|
|
|
271
193
|
---
|
|
272
194
|
|
|
273
195
|
## Contact
|
|
274
196
|
|
|
275
|
-
|
|
197
|
+
[](https://vd7.io)
|
|
198
|
+
|
|
199
|
+
[](https://x.com/vdutts7)
|
package/bin/glider.js
CHANGED
|
@@ -57,6 +57,7 @@ if (fs.existsSync(REGISTRY_FILE)) {
|
|
|
57
57
|
|
|
58
58
|
// Direct CDP module
|
|
59
59
|
const { DirectCDP, checkChrome } = require(path.join(LIB_DIR, 'cdp-direct.js'));
|
|
60
|
+
const { resolveDomain } = require(path.join(LIB_DIR, 'domain-resolve.js'));
|
|
60
61
|
|
|
61
62
|
// Domain extensions - load from ~/.glider/config/domains.json
|
|
62
63
|
const DOMAIN_CONFIG_PATHS = [
|
|
@@ -1069,7 +1070,7 @@ async function cmdWindow(args) {
|
|
|
1069
1070
|
}
|
|
1070
1071
|
|
|
1071
1072
|
async function cmdDomains() {
|
|
1072
|
-
const domainKeys = Object.keys(DOMAINS);
|
|
1073
|
+
const domainKeys = Object.keys(DOMAINS).filter((k) => k !== 'meta');
|
|
1073
1074
|
if (domainKeys.length === 0) {
|
|
1074
1075
|
log.warn('No domains configured');
|
|
1075
1076
|
log.info('Add domains to ~/.glider/config/domains.json');
|
|
@@ -1078,12 +1079,28 @@ async function cmdDomains() {
|
|
|
1078
1079
|
console.log(`${GREEN}${domainKeys.length}${NC} domain(s) configured:\n`);
|
|
1079
1080
|
for (const key of domainKeys) {
|
|
1080
1081
|
const d = DOMAINS[key];
|
|
1081
|
-
const
|
|
1082
|
-
const
|
|
1082
|
+
const shortcut = d.shortcut || {};
|
|
1083
|
+
const type = shortcut.type || (d.script ? 'script' : d.url ? 'url' : 'none');
|
|
1084
|
+
const target = shortcut.target || d.script || d.url || '';
|
|
1083
1085
|
console.log(` ${CYAN}${key}${NC} ${DIM}(${type})${NC}`);
|
|
1086
|
+
if (d.host) console.log(` ${DIM}host: ${d.host}${NC}`);
|
|
1087
|
+
if (d.warch) console.log(` ${DIM}warch: ${d.warch}${NC}`);
|
|
1084
1088
|
if (d.description) console.log(` ${d.description}`);
|
|
1085
|
-
console.log(` ${DIM}${target}${NC}`);
|
|
1089
|
+
if (target) console.log(` ${DIM}${target}${NC}`);
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
async function cmdResolve(input, opts = []) {
|
|
1094
|
+
if (!input) {
|
|
1095
|
+
log.fail('Usage: glider resolve <url|host> [--json]');
|
|
1096
|
+
process.exit(1);
|
|
1097
|
+
}
|
|
1098
|
+
const result = resolveDomain(input);
|
|
1099
|
+
if (opts.includes('--json') || jsonOutput) {
|
|
1100
|
+
console.log(JSON.stringify({ ok: true, ...result }));
|
|
1101
|
+
return;
|
|
1086
1102
|
}
|
|
1103
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1087
1104
|
}
|
|
1088
1105
|
|
|
1089
1106
|
async function cmdOpen(url) {
|
|
@@ -1955,6 +1972,8 @@ ${B5}STATUS${NC}
|
|
|
1955
1972
|
${BW}browser${NC} Show browser config ${DIM}(name, path, processName, or use key)${NC}
|
|
1956
1973
|
${BW}use${NC} <key> Set browser by registry key ${DIM}(e.g. arc, brave, chrome)${NC}
|
|
1957
1974
|
${BW}test${NC} Run diagnostics
|
|
1975
|
+
${BW}domains${NC} List ~/.glider domain shortcuts + warch paths
|
|
1976
|
+
${BW}resolve${NC} <url> Domain intel under ~/.glider/warch ${DIM}(--json)${NC}
|
|
1958
1977
|
|
|
1959
1978
|
${B5}NAVIGATION${NC}
|
|
1960
1979
|
${BW}goto${NC} <url> Navigate to URL
|
|
@@ -2144,7 +2163,7 @@ async function main() {
|
|
|
2144
2163
|
}
|
|
2145
2164
|
|
|
2146
2165
|
// Ensure server is running for most commands
|
|
2147
|
-
if (!['start', 'stop', 'help', '--help', '-h', 'update', 'version', '-v', '--version'].includes(cmd)) {
|
|
2166
|
+
if (!['start', 'stop', 'help', '--help', '-h', 'update', 'version', '-v', '--version', 'domains', 'resolve'].includes(cmd)) {
|
|
2148
2167
|
if (!await checkServer()) {
|
|
2149
2168
|
log.info('Server not running, starting...');
|
|
2150
2169
|
await cmdStart();
|
|
@@ -2214,6 +2233,9 @@ async function main() {
|
|
|
2214
2233
|
case 'domains':
|
|
2215
2234
|
await cmdDomains();
|
|
2216
2235
|
break;
|
|
2236
|
+
case 'resolve':
|
|
2237
|
+
await cmdResolve(args[1], args.slice(2));
|
|
2238
|
+
break;
|
|
2217
2239
|
case 'goto':
|
|
2218
2240
|
case 'navigate':
|
|
2219
2241
|
await cmdGoto(args[1]);
|
|
@@ -2297,9 +2319,11 @@ async function main() {
|
|
|
2297
2319
|
// Check if it's a domain command from config
|
|
2298
2320
|
if (DOMAINS[cmd]) {
|
|
2299
2321
|
const domain = DOMAINS[cmd];
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2322
|
+
const shortcut = domain.shortcut || {};
|
|
2323
|
+
const scriptPathRaw = shortcut.type === 'script' ? shortcut.target : domain.script;
|
|
2324
|
+
const urlRaw = shortcut.type === 'url' ? shortcut.target : domain.url;
|
|
2325
|
+
if (scriptPathRaw) {
|
|
2326
|
+
const scriptPath = scriptPathRaw.replace(/^~/, os.homedir()).replace(/\$HOME/g, os.homedir());
|
|
2303
2327
|
if (fs.existsSync(scriptPath)) {
|
|
2304
2328
|
const { execSync } = require('child_process');
|
|
2305
2329
|
try {
|
|
@@ -2311,9 +2335,8 @@ async function main() {
|
|
|
2311
2335
|
log.fail(`Domain script not found: ${scriptPath}`);
|
|
2312
2336
|
process.exit(1);
|
|
2313
2337
|
}
|
|
2314
|
-
} else if (
|
|
2315
|
-
|
|
2316
|
-
await cmdGoto(domain.url);
|
|
2338
|
+
} else if (urlRaw) {
|
|
2339
|
+
await cmdGoto(urlRaw);
|
|
2317
2340
|
}
|
|
2318
2341
|
break;
|
|
2319
2342
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"schema_version": "2.0",
|
|
4
|
+
"description": "Domain index: host → warch dir under registry base",
|
|
5
|
+
"registry_base": "AGREGISTRY env if set, else GLIDER_HOME (~/.glider)",
|
|
6
|
+
"warch_layout": "<registry_base>/warch/<host>/"
|
|
7
|
+
},
|
|
8
|
+
"example_com": {
|
|
9
|
+
"host": "example.com",
|
|
10
|
+
"warch": "warch/example.com",
|
|
11
|
+
"shortcut": { "type": "none", "target": null },
|
|
12
|
+
"description": "Replace with your domain",
|
|
13
|
+
"notes": "glider.json + gotchas.json under warch/<host>/"
|
|
14
|
+
}
|
|
15
|
+
}
|
package/docs/setup.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"meta": {
|
|
3
3
|
"project": "glidercli",
|
|
4
|
-
"updated": "2026-
|
|
4
|
+
"updated": "2026-07-06"
|
|
5
5
|
},
|
|
6
6
|
"architecture": {
|
|
7
7
|
"flow": "glidercli -> bserve (ws:19988) -> chrome-extension -> chrome.debugger -> tab",
|
|
@@ -32,7 +32,12 @@
|
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
34
|
"config_paths": {
|
|
35
|
+
"glider_home": "~/.glider (override: GLIDER_HOME)",
|
|
35
36
|
"domains": "~/.glider/config/domains.json",
|
|
37
|
+
"domains_template": "config/domains.template.json (shipped in package)",
|
|
38
|
+
"warch_root": "<registry_base>/warch/<host>/ (glider.json, gotchas.json, bexplore/)",
|
|
39
|
+
"registry_base": "AGREGISTRY if set, else GLIDER_HOME (~/.glider)",
|
|
40
|
+
"resolve": "glider resolve <url> --json",
|
|
36
41
|
"browser": "~/.glider/config/browser.json",
|
|
37
42
|
"daemon_log": "~/.glider/daemon.log"
|
|
38
43
|
},
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { URL } = require('url');
|
|
6
|
+
const {
|
|
7
|
+
configPath,
|
|
8
|
+
gliderHome,
|
|
9
|
+
registryBase,
|
|
10
|
+
registryMode,
|
|
11
|
+
warchDirForHost,
|
|
12
|
+
warchRoot,
|
|
13
|
+
} = require('./paths.js');
|
|
14
|
+
|
|
15
|
+
function loadDomainsIndex() {
|
|
16
|
+
for (const cfgPath of configPath('domains.json')) {
|
|
17
|
+
if (!fs.existsSync(cfgPath)) continue;
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(fs.readFileSync(cfgPath, 'utf8'));
|
|
20
|
+
} catch (_) { /* ignore */ }
|
|
21
|
+
}
|
|
22
|
+
return {};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function hostFromUrl(input) {
|
|
26
|
+
if (!input) return null;
|
|
27
|
+
try {
|
|
28
|
+
const u = input.includes('://') ? input : `https://${input}`;
|
|
29
|
+
return new URL(u).hostname || null;
|
|
30
|
+
} catch (_) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function resolveDomain(input) {
|
|
36
|
+
const host = hostFromUrl(input);
|
|
37
|
+
const domains = loadDomainsIndex();
|
|
38
|
+
const warchPath = host ? warchDirForHost(host, domains) : null;
|
|
39
|
+
const gliderJsonPath = warchPath && path.join(warchPath, 'glider.json');
|
|
40
|
+
const gotchasPath = warchPath && path.join(warchPath, 'gotchas.json');
|
|
41
|
+
const gliderJsonExists = !!(gliderJsonPath && fs.existsSync(gliderJsonPath));
|
|
42
|
+
const gotchasExists = !!(gotchasPath && fs.existsSync(gotchasPath));
|
|
43
|
+
let gliderJson = null;
|
|
44
|
+
if (gliderJsonExists) {
|
|
45
|
+
try {
|
|
46
|
+
gliderJson = JSON.parse(fs.readFileSync(gliderJsonPath, 'utf8'));
|
|
47
|
+
} catch (_) { /* ignore */ }
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
host,
|
|
51
|
+
registry_mode: registryMode(),
|
|
52
|
+
glider_home: gliderHome(),
|
|
53
|
+
registry_base: registryBase(),
|
|
54
|
+
warch_root: warchRoot(),
|
|
55
|
+
warch_path: warchPath,
|
|
56
|
+
glider_json_exists: gliderJsonExists,
|
|
57
|
+
gotchas_exists: gotchasExists,
|
|
58
|
+
domains_index_hit: host ? Object.keys(domains).find((k) => {
|
|
59
|
+
if (k === 'meta') return false;
|
|
60
|
+
const v = domains[k];
|
|
61
|
+
return v && typeof v === 'object' && (v.host === host || k === host);
|
|
62
|
+
}) ?? null : null,
|
|
63
|
+
capture_mode: gliderJson?.capture_mode ?? null,
|
|
64
|
+
wait_ms: gliderJson?.wait_ms ?? null,
|
|
65
|
+
auth_mode: gliderJson?.auth_mode ?? null,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = {
|
|
70
|
+
resolveDomain,
|
|
71
|
+
hostFromUrl,
|
|
72
|
+
warchRoot,
|
|
73
|
+
loadDomainsIndex,
|
|
74
|
+
gliderHome,
|
|
75
|
+
};
|
package/lib/paths.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const os = require('os');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
/** Browser runtime data — always ~/.glider unless GLIDER_HOME set. */
|
|
7
|
+
function gliderHome() {
|
|
8
|
+
return process.env.GLIDER_HOME || path.join(os.homedir(), '.glider');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Installed package root (glidercli npm tree). */
|
|
12
|
+
function packageRoot() {
|
|
13
|
+
return path.join(__dirname, '..');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Registry base for warch: AGREGISTRY or GLIDER_HOME. */
|
|
17
|
+
function registryBase() {
|
|
18
|
+
const ag = process.env.AGREGISTRY;
|
|
19
|
+
if (ag) return expandUser(ag);
|
|
20
|
+
return gliderHome();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function registryMode() {
|
|
24
|
+
return process.env.AGREGISTRY ? 'agents' : 'standalone';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function configPath(name) {
|
|
28
|
+
const home = gliderHome();
|
|
29
|
+
return [
|
|
30
|
+
path.join(home, 'config', name),
|
|
31
|
+
path.join(home, name),
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Domain intel: $AGREGISTRY/warch or ~/.glider/warch when AGREGISTRY unset. */
|
|
36
|
+
function warchRoot() {
|
|
37
|
+
return path.join(registryBase(), 'warch');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function domainsTemplatePath() {
|
|
41
|
+
return path.join(packageRoot(), 'config', 'domains.template.json');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function expandUser(p) {
|
|
45
|
+
if (!p || typeof p !== 'string') return p;
|
|
46
|
+
return p.replace(/^~(?=$|[/\\])/, os.homedir());
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** warch dir: domains.json entry (relative to registryBase) or warch/<host>. */
|
|
50
|
+
function warchDirForHost(host, domainsIndex) {
|
|
51
|
+
if (!host) return null;
|
|
52
|
+
const domains = domainsIndex || {};
|
|
53
|
+
const base = registryBase();
|
|
54
|
+
for (const [key, val] of Object.entries(domains)) {
|
|
55
|
+
if (key === 'meta' || !val || typeof val !== 'object') continue;
|
|
56
|
+
if (val.host !== host && key !== host) continue;
|
|
57
|
+
if (val.warch) {
|
|
58
|
+
const raw = expandUser(String(val.warch));
|
|
59
|
+
return path.isAbsolute(raw) ? raw : path.join(base, raw);
|
|
60
|
+
}
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
return path.join(warchRoot(), host);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = {
|
|
67
|
+
gliderHome,
|
|
68
|
+
packageRoot,
|
|
69
|
+
registryBase,
|
|
70
|
+
registryMode,
|
|
71
|
+
configPath,
|
|
72
|
+
warchRoot,
|
|
73
|
+
domainsTemplatePath,
|
|
74
|
+
expandUser,
|
|
75
|
+
warchDirForHost,
|
|
76
|
+
};
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "glidercli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.13",
|
|
4
4
|
"description": "Browser automation CLI. Control Chrome from terminal via CDP, run YAML task files, autonomous loops until completion.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"glider": "bin/glider.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"test": "node bin/glider.js --help"
|
|
10
|
+
"test": "node bin/glider.js --help && bash scripts/ship-gate.sh"
|
|
11
11
|
},
|
|
12
12
|
"keywords": [
|
|
13
13
|
"browser",
|