glidercli 0.3.5 → 0.3.6
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 +66 -141
- package/bin/glider.js +120 -21
- package/config/browser.json.example +5 -0
- package/docs/BROWSERS.md +185 -0
- package/docs/setup.json +40 -0
- package/lib/bexplore.js +21 -4
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -15,173 +15,110 @@
|
|
|
15
15
|
|
|
16
16
|
<br/>
|
|
17
17
|
|
|
18
|
-
## ToC
|
|
19
|
-
|
|
20
|
-
<ol>
|
|
21
|
-
<a href="#about">About</a><br/>
|
|
22
|
-
<a href="#install">Install</a><br/>
|
|
23
|
-
<a href="#usage">Usage</a><br/>
|
|
24
|
-
<a href="#the-loop">The loop</a><br/>
|
|
25
|
-
<a href="#task-files">Task files</a><br/>
|
|
26
|
-
<a href="#commands">Commands</a><br/>
|
|
27
|
-
<a href="#roadmap">Roadmap</a><br/>
|
|
28
|
-
<a href="#tools-used">Tools</a><br/>
|
|
29
|
-
<a href="#contact">Contact</a>
|
|
30
|
-
</ol>
|
|
31
|
-
|
|
32
|
-
<br/>
|
|
33
|
-
|
|
34
18
|
## About
|
|
35
19
|
|
|
36
|
-
|
|
20
|
+
| | |
|
|
21
|
+
|---|---|
|
|
22
|
+
| **What** | Control a Chromium-based browser from the terminal via CDP; run YAML tasks; loop until done (Ralph Wiggum pattern). |
|
|
23
|
+
| **CDP** | Chrome DevTools Protocol via relay + browser extension |
|
|
24
|
+
| **Tasks** | Declarative steps: `goto`, `click`, `explore`, `eval`, `screenshot` |
|
|
25
|
+
| **Loops** | Run until completion marker or max iterations / timeout |
|
|
26
|
+
| **Safety** | Max iterations, timeout, backoff |
|
|
37
27
|
|
|
38
|
-
|
|
39
|
-
- **YAML tasks** - Define automation steps declaratively
|
|
40
|
-
- **Autonomous loops** - Run until completion marker found
|
|
41
|
-
- **Safety guards** - Max iterations, timeout, exponential backoff
|
|
28
|
+
---
|
|
42
29
|
|
|
43
30
|
## Install
|
|
44
31
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
npm i -g glidercli
|
|
48
|
-
|
|
32
|
+
| Step | Action |
|
|
33
|
+
|------|--------|
|
|
34
|
+
| **1. CLI** | `npm i -g glidercli` |
|
|
35
|
+
| **2. Extension** | [Install Glider from Chrome Web Store](https://chromewebstore.google.com/detail/glider/njbidokkffhgpofcejgcfcgcinmeoalj) (required; bridges relay ↔ tab). |
|
|
36
|
+
| **3. Daemon** | `glider install` then `glider connect` |
|
|
37
|
+
| **4. (Optional) Browser** | Default: Chrome. For Arc/Edge/Brave: [BROWSERS.md](docs/BROWSERS.md) or `export GLIDER_BROWSER=Arc` |
|
|
49
38
|
|
|
50
|
-
**Then:**
|
|
51
|
-
```bash
|
|
52
|
-
glider install # start daemon (runs forever, auto-restarts)
|
|
53
|
-
glider connect # connect to Chrome
|
|
54
|
-
```
|
|
55
39
|
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
glider update # pulls latest from npm
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### Requirements
|
|
40
|
+
## Requirements
|
|
62
41
|
|
|
63
|
-
|
|
42
|
+
| Requirement | Minimum |
|
|
43
|
+
|-------------|---------|
|
|
44
|
+
| Node | 18+ |
|
|
45
|
+
| Browser | Chromium-based (Chrome, Arc, Edge, Brave, Opera, Vivaldi, DuckDuckGo). No Firefox/Safari → [BROWSERS.md](docs/BROWSERS.md) |
|
|
64
46
|
|
|
65
|
-
|
|
47
|
+
---
|
|
66
48
|
|
|
67
49
|
## Usage
|
|
68
50
|
|
|
69
51
|
```bash
|
|
70
|
-
glider connect
|
|
71
|
-
glider status
|
|
72
|
-
glider goto "https://
|
|
73
|
-
glider eval "document.title"
|
|
74
|
-
glider run task.yaml
|
|
75
|
-
glider loop task.yaml -n 50
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### Daemon
|
|
79
|
-
|
|
80
|
-
The daemon keeps the relay server running 24/7. Auto-restarts on crash.
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
glider install # install daemon (runs at login)
|
|
84
|
-
glider uninstall # remove daemon
|
|
52
|
+
glider connect
|
|
53
|
+
glider status
|
|
54
|
+
glider goto "https://reddit.com"
|
|
55
|
+
glider eval "document.title"
|
|
56
|
+
glider run task.yaml
|
|
57
|
+
glider loop task.yaml -n 50
|
|
85
58
|
```
|
|
86
59
|
|
|
87
|
-
Logs
|
|
60
|
+
| Daemon | Logs |
|
|
61
|
+
|--------|------|
|
|
62
|
+
| `glider install` / `glider uninstall` | `~/.glider/daemon.log` |
|
|
88
63
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
The `loop` (or `ralph`) command runs your task repeatedly until:
|
|
92
|
-
- Completion marker found (`LOOP_COMPLETE` or `DONE`)
|
|
93
|
-
- Max iterations reached
|
|
94
|
-
- Timeout hit
|
|
95
|
-
|
|
96
|
-
```bash
|
|
97
|
-
glider loop scrape-feed.yaml -n 100 -t 3600
|
|
98
|
-
glider ralph task.yaml # same thing
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
Safety: max iterations, timeout, exponential backoff on errors, state persistence.
|
|
64
|
+
---
|
|
102
65
|
|
|
103
66
|
## Task files
|
|
104
67
|
|
|
105
68
|
```yaml
|
|
106
|
-
name: "
|
|
69
|
+
name: "Reddit"
|
|
107
70
|
steps:
|
|
108
|
-
- goto: "https://
|
|
109
|
-
- wait:
|
|
110
|
-
- eval: "document.
|
|
111
|
-
- screenshot: "/tmp/
|
|
71
|
+
- goto: "https://reddit.com"
|
|
72
|
+
- wait: 2
|
|
73
|
+
- eval: "document.title"
|
|
74
|
+
- screenshot: "/tmp/out.png"
|
|
112
75
|
```
|
|
113
76
|
|
|
77
|
+
---
|
|
78
|
+
|
|
114
79
|
## Commands
|
|
115
80
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
| `glider install` | Install daemon (runs at login) |
|
|
81
|
+
| Command | Description |
|
|
82
|
+
|---------|-------------|
|
|
83
|
+
| `glider install` | Install daemon (relay at login) |
|
|
120
84
|
| `glider uninstall` | Remove daemon |
|
|
121
|
-
| `glider update` | Update to latest version |
|
|
122
85
|
| `glider connect` | Connect to browser |
|
|
123
|
-
| `glider status` | Server/extension/
|
|
124
|
-
| `glider
|
|
125
|
-
|
|
126
|
-
### Navigation
|
|
127
|
-
| Command | What |
|
|
128
|
-
|---------|------|
|
|
86
|
+
| `glider status` | Server / extension / tabs |
|
|
87
|
+
| `glider browser` | Show browser config (name, path) |
|
|
129
88
|
| `glider goto <url>` | Navigate |
|
|
130
|
-
| `glider eval <js>` |
|
|
89
|
+
| `glider eval <js>` | Run JS in page |
|
|
131
90
|
| `glider click <sel>` | Click element |
|
|
132
91
|
| `glider type <sel> <text>` | Type into input |
|
|
133
|
-
| `glider screenshot` | Capture page |
|
|
134
|
-
| `glider html <sel>` | Get element HTML |
|
|
135
|
-
| `glider title` | Get page title |
|
|
136
|
-
| `glider text` | Get page text |
|
|
137
|
-
|
|
138
|
-
### Multi-tab
|
|
139
|
-
| Command | What |
|
|
140
|
-
|---------|------|
|
|
141
|
-
| `glider fetch <url>` | Fetch URL with browser session (authenticated) |
|
|
142
|
-
| `glider spawn <urls...>` | Open multiple tabs |
|
|
143
|
-
| `glider extract [opts]` | Extract content from all connected tabs |
|
|
144
|
-
| `glider explore <url>` | Crawl site, capture links/network |
|
|
145
|
-
|
|
146
|
-
### Automation
|
|
147
|
-
| Command | What |
|
|
148
|
-
|---------|------|
|
|
92
|
+
| `glider screenshot [path]` | Capture page |
|
|
149
93
|
| `glider run <file>` | Run YAML task |
|
|
150
|
-
| `glider loop <file
|
|
151
|
-
|
|
94
|
+
| `glider loop <file> [-n N]` | Loop until done or limit |
|
|
95
|
+
|
|
96
|
+
Full list: `glider --help`.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Docs
|
|
101
|
+
|
|
102
|
+
| Doc | Contents |
|
|
103
|
+
|-----|----------|
|
|
104
|
+
| This README | Install, usage, commands |
|
|
105
|
+
| [docs/BROWSERS.md](docs/BROWSERS.md) | Which browsers work; browser name/path (env or `~/.glider/config/browser.json`) |
|
|
106
|
+
| [config/browser.json.example](config/browser.json.example) | Example browser config |
|
|
107
|
+
|
|
108
|
+
---
|
|
152
109
|
|
|
153
110
|
## Roadmap
|
|
154
111
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
- [x] macOS notifications
|
|
160
|
-
- [x] Multi-tab orchestration (spawn, extract)
|
|
161
|
-
- [x] Authenticated fetch via browser session
|
|
162
|
-
- [x] Site exploration/crawling
|
|
163
|
-
- [x] Chrome Web Store extension publish
|
|
164
|
-
- [ ] Linux support
|
|
165
|
-
- [ ] Windows support
|
|
166
|
-
- [ ] Headless mode
|
|
167
|
-
- [ ] Task chaining (output of one -> input of next)
|
|
168
|
-
- [ ] Built-in scraping templates
|
|
169
|
-
- [ ] Session recording/playback
|
|
170
|
-
- [ ] AI-assisted task generation
|
|
171
|
-
- [ ] Web dashboard for monitoring loops
|
|
172
|
-
|
|
173
|
-
## Tools
|
|
174
|
-
|
|
175
|
-
[![Claude Code][claudecode-badge]][claudecode-url]
|
|
176
|
-
[![Claude][claude-badge]][claude-url]
|
|
177
|
-
[![Node.js][nodejs-badge]][nodejs-url]
|
|
178
|
-
[![Chrome DevTools Protocol][cdp-badge]][cdp-url]
|
|
112
|
+
| Status | Area |
|
|
113
|
+
|--------|------|
|
|
114
|
+
| Done | CDP relay + extension, YAML tasks, loop, daemon, multi-tab |
|
|
115
|
+
| Todo | Linux / Windows, headless, task chaining, scraping templates |
|
|
179
116
|
|
|
180
|
-
|
|
117
|
+
---
|
|
181
118
|
|
|
119
|
+
## Contact
|
|
182
120
|
|
|
183
|
-
<a href="https://vd7.io"><img src="https://
|
|
184
|
-
<a href="https://x.com/vdutts7"><img src="https://img.shields.io/badge/vdutts7-000000?style=for-the-badge&logo=X&logoColor=white" alt="Twitter" /></a>
|
|
121
|
+
<a href="https://vd7.io"><img src="https://res.cloudinary.com/ddyc1es5v/image/upload/v1773910810/readme-badges/readme-badge-vd7.png" alt="vd7.io" height="40" /></a> <a href="https://x.com/vdutts7"><img src="https://res.cloudinary.com/ddyc1es5v/image/upload/v1773910817/readme-badges/readme-badge-x.png" alt="/vdutts7" height="40" /></a>
|
|
185
122
|
|
|
186
123
|
|
|
187
124
|
<!-- BADGES -->
|
|
@@ -189,15 +126,3 @@ steps:
|
|
|
189
126
|
[github-url]: https://github.com/vdutts7/glidercli
|
|
190
127
|
[npm]: https://img.shields.io/badge/npm%20i%20--g%20glidercli-CB3837?style=for-the-badge&logo=npm
|
|
191
128
|
[npm-url]: https://www.npmjs.com/package/glidercli
|
|
192
|
-
[claudecode-badge]: https://img.shields.io/badge/Claude_Code-D97757?style=for-the-badge&logo=anthropic&logoColor=white
|
|
193
|
-
[claudecode-url]: https://claude.ai/code
|
|
194
|
-
[claude-badge]: https://img.shields.io/badge/Claude-D97757?style=for-the-badge&logo=anthropic&logoColor=white
|
|
195
|
-
[claude-url]: https://claude.ai
|
|
196
|
-
[nodejs-badge]: https://img.shields.io/badge/Node.js-339933?style=for-the-badge&logo=nodedotjs&logoColor=white
|
|
197
|
-
[nodejs-url]: https://nodejs.org
|
|
198
|
-
[cdp-badge]: https://img.shields.io/badge/Chrome_DevTools_Protocol-4285F4?style=for-the-badge&logo=googlechrome&logoColor=white
|
|
199
|
-
[cdp-url]: https://chromedevtools.github.io/devtools-protocol/
|
|
200
|
-
[email]: https://img.shields.io/badge/Email-000000?style=for-the-badge&logo=Gmail&logoColor=white
|
|
201
|
-
[email-url]: mailto:me@vd7.io
|
|
202
|
-
[twitter]: https://img.shields.io/badge/Twitter-000000?style=for-the-badge&logo=Twitter&logoColor=white
|
|
203
|
-
[twitter-url]: https://x.com/vdutts7
|
package/bin/glider.js
CHANGED
|
@@ -50,11 +50,10 @@ if (fs.existsSync(REGISTRY_FILE)) {
|
|
|
50
50
|
// Direct CDP module
|
|
51
51
|
const { DirectCDP, checkChrome } = require(path.join(LIB_DIR, 'cdp-direct.js'));
|
|
52
52
|
|
|
53
|
-
// Domain extensions - load from ~/.glider/config/domains.json
|
|
53
|
+
// Domain extensions - load from ~/.glider/config/domains.json
|
|
54
54
|
const DOMAIN_CONFIG_PATHS = [
|
|
55
55
|
path.join(os.homedir(), '.glider', 'config', 'domains.json'),
|
|
56
56
|
path.join(os.homedir(), '.glider', 'domains.json'),
|
|
57
|
-
path.join(os.homedir(), '.cursor', 'glider', 'domains.json'), // legacy
|
|
58
57
|
];
|
|
59
58
|
let DOMAINS = {};
|
|
60
59
|
for (const cfgPath of DOMAIN_CONFIG_PATHS) {
|
|
@@ -66,6 +65,56 @@ for (const cfgPath of DOMAIN_CONFIG_PATHS) {
|
|
|
66
65
|
}
|
|
67
66
|
}
|
|
68
67
|
|
|
68
|
+
// Browser config - which browser to launch/use (must be Chromium-based, see docs/BROWSERS.md)
|
|
69
|
+
const BROWSER_CONFIG_PATHS = [
|
|
70
|
+
path.join(os.homedir(), '.glider', 'config', 'browser.json'),
|
|
71
|
+
path.join(os.homedir(), '.glider', 'browser.json'),
|
|
72
|
+
];
|
|
73
|
+
let BROWSER_CONFIG = {};
|
|
74
|
+
for (const cfgPath of BROWSER_CONFIG_PATHS) {
|
|
75
|
+
if (fs.existsSync(cfgPath)) {
|
|
76
|
+
try {
|
|
77
|
+
BROWSER_CONFIG = JSON.parse(fs.readFileSync(cfgPath, 'utf8'));
|
|
78
|
+
break;
|
|
79
|
+
} catch (e) { /* ignore parse errors */ }
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Browsers registry - key → { name, path, processName }. Used when browser.json has "use": "<key>"
|
|
84
|
+
const BROWSERS_REGISTRY_PATHS = [
|
|
85
|
+
process.env.GLIDER_BROWSERS_REGISTRY,
|
|
86
|
+
path.join(os.homedir(), '.cursor', 'registry', 'browsers.json'),
|
|
87
|
+
path.join(os.homedir(), '.glider', 'config', 'browsers-registry.json'),
|
|
88
|
+
].filter(Boolean);
|
|
89
|
+
let BROWSERS_REGISTRY = {};
|
|
90
|
+
for (const regPath of BROWSERS_REGISTRY_PATHS) {
|
|
91
|
+
if (regPath && fs.existsSync(regPath)) {
|
|
92
|
+
try {
|
|
93
|
+
const data = JSON.parse(fs.readFileSync(regPath, 'utf8'));
|
|
94
|
+
BROWSERS_REGISTRY = data.registry || data;
|
|
95
|
+
break;
|
|
96
|
+
} catch (e) { /* ignore */ }
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function getBrowserConfig() {
|
|
101
|
+
let name = process.env.GLIDER_BROWSER || BROWSER_CONFIG.name;
|
|
102
|
+
let pathOrNull = process.env.GLIDER_BROWSER_PATH || BROWSER_CONFIG.path || null;
|
|
103
|
+
let processName = process.env.GLIDER_BROWSER_PROCESS || BROWSER_CONFIG.processName;
|
|
104
|
+
|
|
105
|
+
// Key-based lookup: browser.json has { "use": "arc" } → resolve from registry
|
|
106
|
+
if (!name && BROWSER_CONFIG.use && BROWSERS_REGISTRY[BROWSER_CONFIG.use]) {
|
|
107
|
+
const entry = BROWSERS_REGISTRY[BROWSER_CONFIG.use];
|
|
108
|
+
name = entry.name;
|
|
109
|
+
pathOrNull = entry.path != null ? entry.path : null;
|
|
110
|
+
processName = entry.processName || entry.name;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
name = name || 'Google Chrome';
|
|
114
|
+
processName = processName || name;
|
|
115
|
+
return { name, path: pathOrNull, processName };
|
|
116
|
+
}
|
|
117
|
+
|
|
69
118
|
// Colors - matching the deep blue gradient logo
|
|
70
119
|
const RED = '\x1b[31m';
|
|
71
120
|
const GREEN = '\x1b[32m';
|
|
@@ -242,7 +291,7 @@ async function ensureConnected() {
|
|
|
242
291
|
|
|
243
292
|
if (!await checkExtension()) {
|
|
244
293
|
log.fail('Extension not connected - make sure Glider extension is installed');
|
|
245
|
-
log.info('Install from
|
|
294
|
+
log.info('Install extension from Chrome Web Store: https://chromewebstore.google.com/detail/glider/njbidokkffhgpofcejgcfcgcinmeoalj');
|
|
246
295
|
return false;
|
|
247
296
|
}
|
|
248
297
|
|
|
@@ -621,7 +670,7 @@ async function cmdUninstallDaemon() {
|
|
|
621
670
|
}
|
|
622
671
|
|
|
623
672
|
async function cmdConnect() {
|
|
624
|
-
// Bulletproof connect: relay +
|
|
673
|
+
// Bulletproof connect: relay + browser + trigger attach via HTTP
|
|
625
674
|
log.info('Connecting...');
|
|
626
675
|
|
|
627
676
|
// 1. Ensure relay is running
|
|
@@ -630,12 +679,17 @@ async function cmdConnect() {
|
|
|
630
679
|
await new Promise(r => setTimeout(r, 1000));
|
|
631
680
|
}
|
|
632
681
|
|
|
633
|
-
// 2. Ensure
|
|
682
|
+
// 2. Ensure browser is running (see getBrowserConfig + docs/BROWSERS.md)
|
|
683
|
+
const browser = getBrowserConfig();
|
|
634
684
|
try {
|
|
635
|
-
execSync(
|
|
685
|
+
execSync(`pgrep -x "${browser.processName}"`, { stdio: 'ignore' });
|
|
636
686
|
} catch {
|
|
637
|
-
log.info(
|
|
638
|
-
|
|
687
|
+
log.info(`Starting ${browser.name}...`);
|
|
688
|
+
if (browser.path) {
|
|
689
|
+
execSync(`open "${browser.path}"`, { stdio: 'ignore' });
|
|
690
|
+
} else {
|
|
691
|
+
execSync(`open -a "${browser.name}"`);
|
|
692
|
+
}
|
|
639
693
|
await new Promise(r => setTimeout(r, 3000));
|
|
640
694
|
}
|
|
641
695
|
|
|
@@ -647,7 +701,7 @@ async function cmdConnect() {
|
|
|
647
701
|
|
|
648
702
|
if (!await checkExtension()) {
|
|
649
703
|
log.fail('Extension not connected to relay');
|
|
650
|
-
log.info(
|
|
704
|
+
log.info(`Make sure Glider extension is installed in ${browser.name} (Chromium-based only; see glider docs/BROWSERS.md)`);
|
|
651
705
|
process.exit(1);
|
|
652
706
|
}
|
|
653
707
|
log.ok('Extension connected');
|
|
@@ -665,18 +719,18 @@ async function cmdConnect() {
|
|
|
665
719
|
return;
|
|
666
720
|
}
|
|
667
721
|
|
|
668
|
-
// 5. Ensure we have a real tab (not chrome://)
|
|
722
|
+
// 5. Ensure we have a real tab (not chrome:// or arc://)
|
|
669
723
|
try {
|
|
670
|
-
const tabUrl = execSync(`osascript -e 'tell application "
|
|
671
|
-
if (tabUrl.startsWith('chrome://') || tabUrl.startsWith('chrome-extension://')) {
|
|
724
|
+
const tabUrl = execSync(`osascript -e 'tell application "${browser.name}" to return URL of active tab of front window'`).toString().trim();
|
|
725
|
+
if (tabUrl.startsWith('chrome://') || tabUrl.startsWith('chrome-extension://') || tabUrl.startsWith('arc://')) {
|
|
672
726
|
log.info('Creating new tab...');
|
|
673
|
-
execSync(`osascript -e 'tell application "
|
|
727
|
+
execSync(`osascript -e 'tell application "${browser.name}" to make new tab at front window with properties {URL:"https://google.com"}'`);
|
|
674
728
|
await new Promise(r => setTimeout(r, 2000));
|
|
675
729
|
}
|
|
676
730
|
} catch {
|
|
677
731
|
// No window, create one
|
|
678
732
|
log.info('Creating new window...');
|
|
679
|
-
execSync(`osascript -e 'tell application "
|
|
733
|
+
execSync(`osascript -e 'tell application "${browser.name}" to make new window with properties {URL:"https://google.com"}'`);
|
|
680
734
|
await new Promise(r => setTimeout(r, 2000));
|
|
681
735
|
}
|
|
682
736
|
|
|
@@ -700,7 +754,7 @@ async function cmdConnect() {
|
|
|
700
754
|
|
|
701
755
|
// 7. Fallback: create fresh tab and retry
|
|
702
756
|
log.info('Creating fresh tab...');
|
|
703
|
-
execSync(`osascript -e 'tell application "
|
|
757
|
+
execSync(`osascript -e 'tell application "${browser.name}" to make new tab at front window with properties {URL:"https://google.com"}'`);
|
|
704
758
|
await new Promise(r => setTimeout(r, 2000));
|
|
705
759
|
|
|
706
760
|
try {
|
|
@@ -717,13 +771,13 @@ async function cmdConnect() {
|
|
|
717
771
|
}
|
|
718
772
|
} catch {}
|
|
719
773
|
|
|
720
|
-
// 8. Need manual click -
|
|
721
|
-
log.warn(
|
|
722
|
-
console.log(` ${B5}(on any real webpage, not chrome:// pages)${NC}`);
|
|
723
|
-
execSync(`osascript -e 'tell application "
|
|
774
|
+
// 8. Need manual click - activate browser and show instructions
|
|
775
|
+
log.warn(`Click the Glider extension icon in ${browser.name}`);
|
|
776
|
+
console.log(` ${B5}(on any real webpage, not chrome:// or arc:// pages)${NC}`);
|
|
777
|
+
execSync(`osascript -e 'tell application "${browser.name}" to activate'`);
|
|
724
778
|
|
|
725
779
|
// Send macOS notification so user sees it even if not looking at terminal
|
|
726
|
-
notify('Glider',
|
|
780
|
+
notify('Glider', `Click the extension icon in ${browser.name} to connect`, true);
|
|
727
781
|
|
|
728
782
|
// Wait for user to click
|
|
729
783
|
log.info('Waiting for connection...');
|
|
@@ -745,6 +799,40 @@ async function cmdConnect() {
|
|
|
745
799
|
log.info('Make sure you clicked the extension icon on a real webpage');
|
|
746
800
|
}
|
|
747
801
|
|
|
802
|
+
function cmdBrowser() {
|
|
803
|
+
const b = getBrowserConfig();
|
|
804
|
+
console.log('Browser config (used by glider connect):');
|
|
805
|
+
console.log(` name: ${b.name}`);
|
|
806
|
+
console.log(` path: ${b.path || '(default launch via name)'}`);
|
|
807
|
+
console.log(` processName: ${b.processName}`);
|
|
808
|
+
if (BROWSER_CONFIG.use) {
|
|
809
|
+
console.log(` use: ${BROWSER_CONFIG.use} ${DIM}(from registry)${NC}`);
|
|
810
|
+
}
|
|
811
|
+
console.log('');
|
|
812
|
+
console.log('Source: GLIDER_BROWSER* env → ~/.glider/config/browser.json { "use": "<key>" } or { name, path } → default "Google Chrome"');
|
|
813
|
+
console.log('Registry: GLIDER_BROWSERS_REGISTRY or ~/.cursor/registry/browsers.json. Keys: ' + Object.keys(BROWSERS_REGISTRY).join(', ') || '(none loaded)');
|
|
814
|
+
console.log('See docs/BROWSERS.md for compatibility and examples.');
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
function cmdUse(key) {
|
|
818
|
+
if (!key) {
|
|
819
|
+
console.log('Usage: glider use <key>');
|
|
820
|
+
console.log('Keys in registry: ' + (Object.keys(BROWSERS_REGISTRY).length ? Object.keys(BROWSERS_REGISTRY).join(', ') : '(no registry loaded)'));
|
|
821
|
+
if (BROWSER_CONFIG.use) console.log('Current: ' + BROWSER_CONFIG.use);
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
if (!BROWSERS_REGISTRY[key]) {
|
|
825
|
+
console.error('Unknown key: ' + key + '. Available: ' + Object.keys(BROWSERS_REGISTRY).join(', '));
|
|
826
|
+
process.exit(1);
|
|
827
|
+
}
|
|
828
|
+
const configDir = path.join(os.homedir(), '.glider', 'config');
|
|
829
|
+
const browserPath = path.join(configDir, 'browser.json');
|
|
830
|
+
if (!fs.existsSync(configDir)) fs.mkdirSync(configDir, { recursive: true });
|
|
831
|
+
fs.writeFileSync(browserPath, JSON.stringify({ use: key }, null, 2) + '\n');
|
|
832
|
+
console.log('Set browser to: ' + key + ' → ' + BROWSERS_REGISTRY[key].name);
|
|
833
|
+
console.log('Run: glider connect');
|
|
834
|
+
}
|
|
835
|
+
|
|
748
836
|
async function cmdTest() {
|
|
749
837
|
showBanner();
|
|
750
838
|
log.box('DIAGNOSTICS');
|
|
@@ -1342,11 +1430,13 @@ async function cmdExplore(url, opts = []) {
|
|
|
1342
1430
|
let depth = 2;
|
|
1343
1431
|
let outputDir = '/tmp/glider-explore';
|
|
1344
1432
|
let harFile = null;
|
|
1433
|
+
let sessionId = null;
|
|
1345
1434
|
|
|
1346
1435
|
for (let i = 0; i < opts.length; i++) {
|
|
1347
1436
|
if (opts[i] === '--depth' || opts[i] === '-d') depth = parseInt(opts[++i], 10);
|
|
1348
1437
|
else if (opts[i] === '--output' || opts[i] === '-o') outputDir = opts[++i];
|
|
1349
1438
|
else if (opts[i] === '--har') harFile = opts[++i];
|
|
1439
|
+
else if (opts[i] === '--session-id') sessionId = opts[++i];
|
|
1350
1440
|
}
|
|
1351
1441
|
|
|
1352
1442
|
log.info(`Exploring: ${url} (depth: ${depth})`);
|
|
@@ -1357,6 +1447,7 @@ async function cmdExplore(url, opts = []) {
|
|
|
1357
1447
|
const { spawn } = require('child_process');
|
|
1358
1448
|
const spawnArgs = [bexplorePath, url, '--depth', String(depth), '--output', outputDir];
|
|
1359
1449
|
if (harFile) spawnArgs.push('--har', harFile);
|
|
1450
|
+
if (sessionId) spawnArgs.push('--session-id', sessionId);
|
|
1360
1451
|
|
|
1361
1452
|
const child = spawn('node', spawnArgs, {
|
|
1362
1453
|
stdio: 'inherit'
|
|
@@ -1659,6 +1750,8 @@ ${B5}SETUP${NC}
|
|
|
1659
1750
|
|
|
1660
1751
|
${B5}STATUS${NC}
|
|
1661
1752
|
${BW}status${NC} Check server, extension, tabs
|
|
1753
|
+
${BW}browser${NC} Show browser config ${DIM}(name, path, processName, or use key)${NC}
|
|
1754
|
+
${BW}use${NC} <key> Set browser by registry key ${DIM}(e.g. arc, brave, chrome)${NC}
|
|
1662
1755
|
${BW}test${NC} Run diagnostics
|
|
1663
1756
|
|
|
1664
1757
|
${B5}NAVIGATION${NC}
|
|
@@ -1755,7 +1848,7 @@ ${YELLOW}DOMAIN EXTENSIONS:${NC}
|
|
|
1755
1848
|
Add custom domain commands via ~/.glider/config/domains.json:
|
|
1756
1849
|
{
|
|
1757
1850
|
"mysite": { "url": "https://mysite.com/dashboard" },
|
|
1758
|
-
"mytool": { "script": "
|
|
1851
|
+
"mytool": { "script": "~/scripts/mytool.sh" }
|
|
1759
1852
|
}
|
|
1760
1853
|
Then: glider mysite -> navigates to that URL
|
|
1761
1854
|
glider mytool -> runs that script
|
|
@@ -1887,6 +1980,12 @@ async function main() {
|
|
|
1887
1980
|
case 'connect':
|
|
1888
1981
|
await cmdConnect();
|
|
1889
1982
|
break;
|
|
1983
|
+
case 'browser':
|
|
1984
|
+
cmdBrowser();
|
|
1985
|
+
break;
|
|
1986
|
+
case 'use':
|
|
1987
|
+
cmdUse(args[1]);
|
|
1988
|
+
break;
|
|
1890
1989
|
case 'test':
|
|
1891
1990
|
await cmdTest();
|
|
1892
1991
|
break;
|
package/docs/BROWSERS.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# Glider browser support and configuration
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
|---|---|
|
|
5
|
+
| **Install / usage** | [README](../README.md) |
|
|
6
|
+
| **How it works** | Chrome extension → WebSocket relay → CDP. Browser must support that extension (Chromium-based). |
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Browser support
|
|
11
|
+
|
|
12
|
+
Icons: `https://raw.githubusercontent.com/vdutts7/squircle/main/webp/{slug}.webp` ([squircle](https://github.com/vdutts7/squircle)).
|
|
13
|
+
|
|
14
|
+
**Extension:** Install [Glider](https://chromewebstore.google.com/detail/glider/njbidokkffhgpofcejgcfcgcinmeoalj) from the Chrome Web Store — same for every browser in this table.
|
|
15
|
+
|
|
16
|
+
| | Browser | Config |
|
|
17
|
+
|:---:|--------|--------|
|
|
18
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/chrome.webp" width="16" alt=""> | Google Chrome | Default for `glider connect`. |
|
|
19
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/arc.webp" width="16" alt=""> | Arc | `GLIDER_BROWSER=Arc` or [browser.json](../config/browser.json.example). |
|
|
20
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/microsoft/microsoft-edge.webp" width="16" alt=""> | Microsoft Edge | — |
|
|
21
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/brave.webp" width="16" alt=""> | Brave | — |
|
|
22
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/opera-gx.webp" width="16" alt=""> | Opera | — |
|
|
23
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/vivaldi.webp" width="16" alt=""> | Vivaldi | — |
|
|
24
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/duckduckgo.webp" width="16" alt=""> | DuckDuckGo Desktop | — |
|
|
25
|
+
| <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. |
|
|
26
|
+
|
|
27
|
+
See **[Future](#future)** for browsers not supported today.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Future
|
|
32
|
+
|
|
33
|
+
Not supported today: Glider needs a **Chromium-based** browser that can install the extension from the **Chrome Web Store**. No timeline implied; listed for clarity.
|
|
34
|
+
|
|
35
|
+
Same icon base as above: `https://raw.githubusercontent.com/vdutts7/squircle/main/webp/{slug}.webp`.
|
|
36
|
+
|
|
37
|
+
| | Browser | Notes |
|
|
38
|
+
|:---:|--------|--------|
|
|
39
|
+
| <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. |
|
|
40
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/librewolf.webp" width="16" alt=""> | LibreWolf | Gecko — same constraints as Firefox. |
|
|
41
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/waterfox.webp" width="16" alt=""> | Waterfox | Gecko — same constraints as Firefox. |
|
|
42
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/zen.webp" width="16" alt=""> | Zen | Gecko — same constraints as Firefox. |
|
|
43
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/floorp.webp" width="16" alt=""> | Floorp | Gecko — same constraints as Firefox. |
|
|
44
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/tor-browser.webp" width="16" alt=""> | Tor Browser | Gecko — same constraints as Firefox. |
|
|
45
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/mullvad-browser.webp" width="16" alt=""> | Mullvad Browser | Gecko — same constraints as Firefox. |
|
|
46
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/icecat.webp" width="16" alt=""> | IceCat | Gecko — same constraints as Firefox. |
|
|
47
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/firefox-focus.webp" width="16" alt=""> | Firefox Focus | Gecko — same constraints as Firefox. |
|
|
48
|
+
| <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. |
|
|
49
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/safari.webp" width="16" alt=""> | Safari | WebKit (Apple desktop). Not Chromium. |
|
|
50
|
+
| <img src="https://raw.githubusercontent.com/vdutts7/squircle/main/webp/orion.webp" width="16" alt=""> | Orion | WebKit-based desktop browser. Not Chromium. |
|
|
51
|
+
| <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. |
|
|
52
|
+
| <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. |
|
|
53
|
+
| <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. |
|
|
54
|
+
| <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. |
|
|
55
|
+
| <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. |
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Configuring the browser
|
|
60
|
+
|
|
61
|
+
**Priority (highest first):** env vars → config file → default `Google Chrome`.
|
|
62
|
+
|
|
63
|
+
### Environment variables
|
|
64
|
+
|
|
65
|
+
| Variable | Purpose | Example |
|
|
66
|
+
|----------|---------|---------|
|
|
67
|
+
| `GLIDER_BROWSER` | App name (`open -a`, AppleScript) | `Arc`, `Google Chrome`, `Microsoft Edge` |
|
|
68
|
+
| `GLIDER_BROWSER_PATH` | (Optional) Path to app bundle | `/Applications/My Apps/Chrome.app` |
|
|
69
|
+
| `GLIDER_BROWSER_PROCESS` | (Optional) Process name for `pgrep` | Defaults to same as `GLIDER_BROWSER` |
|
|
70
|
+
|
|
71
|
+
**Examples:**
|
|
72
|
+
|
|
73
|
+
| Use case | Command |
|
|
74
|
+
|----------|---------|
|
|
75
|
+
| Arc | `export GLIDER_BROWSER=Arc` then `glider connect` |
|
|
76
|
+
| Custom Chrome path | `export GLIDER_BROWSER="Google Chrome"` and `export GLIDER_BROWSER_PATH="/Applications/My Apps/Google Chrome.app"` |
|
|
77
|
+
|
|
78
|
+
### Config file: `$HOME/.glider/config/browser.json`
|
|
79
|
+
|
|
80
|
+
Same keys as env, or use a **registry key**. Env overrides file.
|
|
81
|
+
|
|
82
|
+
**Option A — Registry key (recommended):**
|
|
83
|
+
|
|
84
|
+
Set browser by key from the browsers registry. Run `glider use <key>` to write this.
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"use": "arc"
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Registry is loaded from (first found): `GLIDER_BROWSERS_REGISTRY` env, `$HOME/.cursor/registry/browsers.json`, `$HOME/.glider/config/browsers-registry.json`. Keys are predefined (e.g. `arc`, `brave`, `chrome`, `edge`, `opera`, `vivaldi`, `duckduckgo`, `chromium`). Edit the registry to add or change paths.
|
|
93
|
+
|
|
94
|
+
**Option B — Explicit name/path:**
|
|
95
|
+
|
|
96
|
+
| Field | Required | Description |
|
|
97
|
+
|-------|:--------:|-------------|
|
|
98
|
+
| `name` | Yes* | App name for `open -a` / AppleScript. Must match system (e.g. `Arc`, `Google Chrome`). |
|
|
99
|
+
| `path` | No | If set, use `open "<path>"` instead of `open -a "<name>"`. For non-default install location. |
|
|
100
|
+
| `processName` | No | For `pgrep -x`. Defaults to `name`. |
|
|
101
|
+
|
|
102
|
+
\* Omit `name` when using `use` (registry key).
|
|
103
|
+
|
|
104
|
+
**Example:**
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"name": "Arc",
|
|
109
|
+
"path": "/Applications/Arc.app",
|
|
110
|
+
"processName": "Arc"
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**By browser:**
|
|
115
|
+
|
|
116
|
+
| Browser | `name` | `path` (optional) | `processName` (optional) |
|
|
117
|
+
|---------|--------|-------------------|---------------------------|
|
|
118
|
+
| Arc | `Arc` | `/Applications/Arc.app` | `Arc` |
|
|
119
|
+
| Edge | `Microsoft Edge` | — | `Microsoft Edge` |
|
|
120
|
+
| Chrome (custom) | `Google Chrome` | `/Users/me/Applications/Google Chrome.app` | `Google Chrome` |
|
|
121
|
+
| DuckDuckGo | `DuckDuckGo` | — | `DuckDuckGo` |
|
|
122
|
+
|
|
123
|
+
Check app name in Finder/Spotlight; process name: `ps aux | grep -i <name>`.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Browser registry (keymap)
|
|
128
|
+
|
|
129
|
+
A single registry file can define all Chromium browsers; Glider picks one by key.
|
|
130
|
+
|
|
131
|
+
**Registry location (first found):**
|
|
132
|
+
|
|
133
|
+
- `GLIDER_BROWSERS_REGISTRY` (env, path to JSON file)
|
|
134
|
+
- `$HOME/.cursor/registry/browsers.json`
|
|
135
|
+
- `$HOME/.glider/config/browsers-registry.json`
|
|
136
|
+
|
|
137
|
+
**Registry format:**
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"version": "1.0",
|
|
142
|
+
"registry": {
|
|
143
|
+
"arc": { "name": "Arc", "path": "/Applications/Arc.app", "processName": "Arc" },
|
|
144
|
+
"brave": { "name": "Brave Browser", "path": "/Applications/Brave Browser.app", "processName": "Brave Browser" },
|
|
145
|
+
"chrome": { "name": "Google Chrome", "path": "/Applications/Google Chrome.app", "processName": "Google Chrome" },
|
|
146
|
+
"edge": { "name": "Microsoft Edge", "path": "/Applications/Microsoft Edge.app", "processName": "Microsoft Edge" }
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Commands:**
|
|
152
|
+
|
|
153
|
+
| Command | Effect |
|
|
154
|
+
|---------|--------|
|
|
155
|
+
| `glider use arc` | Set `$HOME/.glider/config/browser.json` to `{ "use": "arc" }` (resolved from registry). |
|
|
156
|
+
| `glider use brave` | Switch to Brave. |
|
|
157
|
+
| `glider use` | Show current key and list of registry keys. |
|
|
158
|
+
| `glider browser` | Show resolved name, path, processName (and `use` key if set). |
|
|
159
|
+
|
|
160
|
+
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.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Platform
|
|
165
|
+
|
|
166
|
+
| Platform | Behavior |
|
|
167
|
+
|----------|----------|
|
|
168
|
+
| macOS | `open -a "<name>"` or `open "<path>"`; AppleScript for tab/window. `name` = exact app name. |
|
|
169
|
+
| Linux / Windows | Not fully implemented. Future: `path` may be executable. |
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Summary
|
|
174
|
+
|
|
175
|
+
| Topic | Detail |
|
|
176
|
+
|-------|--------|
|
|
177
|
+
| Supported | Chromium-based + Chrome Web Store extension (see table above). |
|
|
178
|
+
| Not supported | See [Future](#future). |
|
|
179
|
+
| Configure | `$HOME/.glider/config/browser.json` (use key or name/path) and/or `GLIDER_BROWSER*`. Registry: `$HOME/.cursor/registry/browsers.json` or `GLIDER_BROWSERS_REGISTRY`. |
|
|
180
|
+
| Switch | `glider use <key>` (e.g. `glider use arc`, `glider use brave`). |
|
|
181
|
+
| Path | Optional; use when app is not in default location. |
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
[← README](../README.md)
|
package/docs/setup.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"project": "glidercli",
|
|
4
|
+
"updated": "2026-01-31"
|
|
5
|
+
},
|
|
6
|
+
"architecture": {
|
|
7
|
+
"flow": "glidercli -> bserve (ws:19988) -> chrome-extension -> chrome.debugger -> tab",
|
|
8
|
+
"relay_port": 19988,
|
|
9
|
+
"relay_host": "127.0.0.1"
|
|
10
|
+
},
|
|
11
|
+
"requirements": {
|
|
12
|
+
"node": ">=18",
|
|
13
|
+
"browser": "Chromium-based (Chrome, Arc, Edge, Brave, etc.); see docs/BROWSERS.md",
|
|
14
|
+
"os": "macOS (tested), Linux (untested), Windows (untested)"
|
|
15
|
+
},
|
|
16
|
+
"install": {
|
|
17
|
+
"cli": "npm install -g glidercli",
|
|
18
|
+
"extension": {
|
|
19
|
+
"cws": "https://chromewebstore.google.com/detail/glider/njbidokkffhgpofcejgcfcgcinmeoalj",
|
|
20
|
+
"source": "https://github.com/vdutts7/glider"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"endpoints": {
|
|
24
|
+
"http": {
|
|
25
|
+
"/status": "GET - extension/targets/clients status",
|
|
26
|
+
"/targets": "GET - connected tabs",
|
|
27
|
+
"/cdp": "POST - forward CDP command"
|
|
28
|
+
},
|
|
29
|
+
"websocket": {
|
|
30
|
+
"/extension": "chrome extension connects here",
|
|
31
|
+
"/cdp": "cli/clients connect here"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"config_paths": {
|
|
35
|
+
"domains": "~/.glider/config/domains.json",
|
|
36
|
+
"browser": "~/.glider/config/browser.json",
|
|
37
|
+
"daemon_log": "~/.glider/daemon.log"
|
|
38
|
+
},
|
|
39
|
+
"discovery": "glider --help"
|
|
40
|
+
}
|
package/lib/bexplore.js
CHANGED
|
@@ -27,6 +27,8 @@ class SiteExplorer {
|
|
|
27
27
|
this.depth = options.depth || 3;
|
|
28
28
|
this.outputDir = options.outputDir || '/tmp/explore';
|
|
29
29
|
this.harFile = options.harFile;
|
|
30
|
+
this.wantedSessionId = options.sessionId || null;
|
|
31
|
+
this.sessionResolved = null;
|
|
30
32
|
|
|
31
33
|
// Captured data
|
|
32
34
|
this.requests = [];
|
|
@@ -77,8 +79,15 @@ class SiteExplorer {
|
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
if (msg.method === 'Target.attachedToTarget') {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
const sid = msg.params.sessionId;
|
|
83
|
+
if (this.wantedSessionId) {
|
|
84
|
+
if (sid === this.wantedSessionId) {
|
|
85
|
+
this.sessionId = sid;
|
|
86
|
+
if (this.sessionResolved) this.sessionResolved();
|
|
87
|
+
}
|
|
88
|
+
} else if (!this.sessionId) {
|
|
89
|
+
this.sessionId = sid;
|
|
90
|
+
if (this.sessionResolved) this.sessionResolved();
|
|
82
91
|
}
|
|
83
92
|
}
|
|
84
93
|
|
|
@@ -179,7 +188,13 @@ class SiteExplorer {
|
|
|
179
188
|
|
|
180
189
|
async init() {
|
|
181
190
|
await this.send('Target.setAutoAttach', { autoAttach: true, waitForDebuggerOnStart: false, flatten: true });
|
|
182
|
-
await new Promise(
|
|
191
|
+
await new Promise((resolve, reject) => {
|
|
192
|
+
this.sessionResolved = resolve;
|
|
193
|
+
setTimeout(() => {
|
|
194
|
+
if (!this.sessionId) reject(new Error('Timeout waiting for tab attachment'));
|
|
195
|
+
else resolve();
|
|
196
|
+
}, 10000);
|
|
197
|
+
});
|
|
183
198
|
if (!this.sessionId) throw new Error('No browser tab connected');
|
|
184
199
|
|
|
185
200
|
// Enable ALL the things
|
|
@@ -756,14 +771,16 @@ Examples:
|
|
|
756
771
|
let depth = 3;
|
|
757
772
|
let outputDir = '/tmp/explore';
|
|
758
773
|
let harFile = null;
|
|
774
|
+
let sessionId = null;
|
|
759
775
|
|
|
760
776
|
for (let i = 0; i < args.length; i++) {
|
|
761
777
|
if (args[i] === '--depth') depth = parseInt(args[++i]);
|
|
762
778
|
else if (args[i] === '--output') outputDir = args[++i];
|
|
763
779
|
else if (args[i] === '--har') harFile = args[++i];
|
|
780
|
+
else if (args[i] === '--session-id') sessionId = args[++i];
|
|
764
781
|
}
|
|
765
782
|
|
|
766
|
-
const explorer = new SiteExplorer({ depth, outputDir, harFile });
|
|
783
|
+
const explorer = new SiteExplorer({ depth, outputDir, harFile, sessionId });
|
|
767
784
|
|
|
768
785
|
try {
|
|
769
786
|
await explorer.connect();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "glidercli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
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": {
|
|
@@ -37,6 +37,8 @@
|
|
|
37
37
|
"files": [
|
|
38
38
|
"bin/",
|
|
39
39
|
"lib/",
|
|
40
|
+
"docs/",
|
|
41
|
+
"config/",
|
|
40
42
|
"index.js",
|
|
41
43
|
"README.md"
|
|
42
44
|
]
|