browse-agent-cli 0.0.5 → 0.0.7
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/dist/clear.js +1 -1
- package/dist/cli.js +71 -56
- package/dist/config.js +13 -15
- package/dist/script.js +1 -1
- package/dist/service.js +17 -2
- package/dist/tabs.js +25 -6
- package/package.json +1 -1
- package/skills/SKILL.md +9 -5
- package/skills/references/cli.md +3 -4
package/dist/clear.js
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,68 +1,83 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { f as resolveOptions, n as DEFAULT_PROFILE_PATHS, r as DEFAULT_SERVICE_PORT, s as findBrowser, u as loadServiceSession } from "./config.js";
|
|
3
3
|
import { t as clear } from "./clear.js";
|
|
4
|
-
import {
|
|
5
|
-
import { cpSync, existsSync, mkdirSync, readdirSync, rmSync, statSync
|
|
4
|
+
import { spawn } from "node:child_process";
|
|
5
|
+
import { cpSync, existsSync, mkdirSync, readdirSync, rmSync, statSync } from "node:fs";
|
|
6
6
|
import { dirname, join, resolve } from "node:path";
|
|
7
7
|
import { createInterface } from "node:readline/promises";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
9
|
//#region src/scripts/setup.ts
|
|
10
|
+
const BROWSE_AGENT_WEBSTORE_URL = "https://chromewebstore.google.com/detail/browse-agent/amfbnjpgfgappenkkklkogngmoeofeae?authuser=0&hl=zh-CN";
|
|
11
|
+
const BROWSE_AGENT_EXTENSION_ID = "amfbnjpgfgappenkkklkogngmoeofeae";
|
|
12
|
+
const INSTALL_WAIT_TIMEOUT_MS = 300 * 1e3;
|
|
13
|
+
const INSTALL_POLL_INTERVAL_MS = 1500;
|
|
14
|
+
function openUrlInSelectedBrowser(url) {
|
|
15
|
+
const opts = resolveOptions();
|
|
16
|
+
const proc = spawn(findBrowser(opts.browser), ["--new-window", url], {
|
|
17
|
+
stdio: "ignore",
|
|
18
|
+
detached: true
|
|
19
|
+
});
|
|
20
|
+
proc.on("error", (err) => {
|
|
21
|
+
throw new Error(`${opts.browser} launch failed: ${err.message}`);
|
|
22
|
+
});
|
|
23
|
+
proc.unref();
|
|
24
|
+
}
|
|
25
|
+
function listProfileDirs(userDataDir) {
|
|
26
|
+
const candidates = ["Default"];
|
|
27
|
+
try {
|
|
28
|
+
for (const name of readdirSync(userDataDir)) if (name.startsWith("Profile ")) candidates.push(name);
|
|
29
|
+
} catch {}
|
|
30
|
+
return [...new Set(candidates)].map((name) => join(userDataDir, name));
|
|
31
|
+
}
|
|
32
|
+
function isExtensionInstalledInBrowser(browser) {
|
|
33
|
+
const userDataDir = DEFAULT_PROFILE_PATHS[browser]?.[process.platform];
|
|
34
|
+
if (!userDataDir || !existsSync(userDataDir)) return false;
|
|
35
|
+
for (const profileDir of listProfileDirs(userDataDir)) {
|
|
36
|
+
const extDir = join(profileDir, "Extensions", BROWSE_AGENT_EXTENSION_ID);
|
|
37
|
+
if (!existsSync(extDir)) continue;
|
|
38
|
+
try {
|
|
39
|
+
if (readdirSync(extDir).length > 0) return true;
|
|
40
|
+
} catch {}
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
function sleep$1(ms) {
|
|
45
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
46
|
+
}
|
|
47
|
+
async function waitForExtensionInstall(browser, timeoutMs) {
|
|
48
|
+
const deadline = Date.now() + timeoutMs;
|
|
49
|
+
while (Date.now() < deadline) {
|
|
50
|
+
if (isExtensionInstalledInBrowser(browser)) return true;
|
|
51
|
+
await sleep$1(INSTALL_POLL_INTERVAL_MS);
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
10
55
|
async function setup() {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const extensionInstalled = existsSync(join(extensionDir, "manifest.json"));
|
|
15
|
-
if (extensionInstalled) {
|
|
16
|
-
console.log("browse-agent is already set up.");
|
|
17
|
-
console.log(` Extension path: ${extensionDir}`);
|
|
18
|
-
console.log(" Extension: installed\n");
|
|
56
|
+
const browser = resolveOptions().browser;
|
|
57
|
+
if (isExtensionInstalledInBrowser(browser)) {
|
|
58
|
+
console.log(`Browse Agent extension is already installed in ${browser}.`);
|
|
19
59
|
return;
|
|
20
60
|
}
|
|
21
|
-
console.log(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
console.log("\
|
|
25
|
-
console.log("
|
|
26
|
-
console.log(
|
|
27
|
-
console.log("
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const asset = JSON.parse(releaseJson).assets?.find((item) => item.name.endsWith(".zip"));
|
|
32
|
-
if (!asset) {
|
|
33
|
-
console.error("Error: No extension zip found in latest release.");
|
|
34
|
-
console.error("Visit https://github.com/imlinhanchao/browse-agent/releases to check.");
|
|
35
|
-
process.exit(1);
|
|
36
|
-
}
|
|
37
|
-
console.log(` Downloading ${asset.name} (${(asset.size / 1024).toFixed(1)} KB)...`);
|
|
38
|
-
execSync(`curl -sL -o "${zipPath}" "${asset.browser_download_url}"`);
|
|
39
|
-
console.log("\n[2/2] Extracting extension...");
|
|
40
|
-
if (existsSync(extensionDir)) execSync(`rm -rf "${extensionDir}"`);
|
|
41
|
-
mkdirSync(extensionDir, { recursive: true });
|
|
42
|
-
execSync(`unzip -o "${zipPath}" -d "${extensionDir}"`, { stdio: "pipe" });
|
|
43
|
-
unlinkSync(zipPath);
|
|
44
|
-
const files = readdirSync(extensionDir);
|
|
45
|
-
if (!files.includes("manifest.json")) {
|
|
46
|
-
const subdirs = files.filter((file) => {
|
|
47
|
-
try {
|
|
48
|
-
return readdirSync(join(extensionDir, file)).includes("manifest.json");
|
|
49
|
-
} catch {
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
if (subdirs.length > 0) {
|
|
54
|
-
const subdir = join(extensionDir, subdirs[0]);
|
|
55
|
-
execSync(`mv "${subdir}"/* "${extensionDir}"/`);
|
|
56
|
-
execSync(`rmdir "${subdir}"`);
|
|
57
|
-
} else {
|
|
58
|
-
console.error("Error: Extension extraction failed - manifest.json not found.");
|
|
59
|
-
process.exit(1);
|
|
60
|
-
}
|
|
61
|
+
console.log(`Opening Chrome Web Store install page in ${browser}...`);
|
|
62
|
+
try {
|
|
63
|
+
openUrlInSelectedBrowser(BROWSE_AGENT_WEBSTORE_URL);
|
|
64
|
+
console.log("Please click \"Add to Chrome\" to install Browse Agent.");
|
|
65
|
+
console.log("Browser extensions cannot be silently installed from CLI without enterprise policy.");
|
|
66
|
+
console.log(`If it did not open automatically, visit:\n${BROWSE_AGENT_WEBSTORE_URL}\n`);
|
|
67
|
+
console.log("Waiting for extension installation...");
|
|
68
|
+
if (await waitForExtensionInstall(browser, INSTALL_WAIT_TIMEOUT_MS)) {
|
|
69
|
+
console.log(`Browse Agent extension installation detected in ${browser}.`);
|
|
70
|
+
return;
|
|
61
71
|
}
|
|
72
|
+
console.error(`Timed out after ${Math.round(INSTALL_WAIT_TIMEOUT_MS / 1e3)}s waiting for extension install in ${browser}.`);
|
|
73
|
+
console.error("Please finish installation in browser, then run \"browse-agent setup\" again.");
|
|
74
|
+
process.exit(1);
|
|
75
|
+
} catch (err) {
|
|
76
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
77
|
+
console.error(`Failed to open browser automatically: ${msg}`);
|
|
78
|
+
console.error(`Please open manually:\n${BROWSE_AGENT_WEBSTORE_URL}\n`);
|
|
79
|
+
process.exit(1);
|
|
62
80
|
}
|
|
63
|
-
console.log("\nSetup complete!");
|
|
64
|
-
console.log(` Extension path: ${extensionDir}`);
|
|
65
|
-
console.log(" Extension: installed\n");
|
|
66
81
|
}
|
|
67
82
|
//#endregion
|
|
68
83
|
//#region src/cli.ts
|
|
@@ -160,7 +175,7 @@ Examples:
|
|
|
160
175
|
`.trim());
|
|
161
176
|
}
|
|
162
177
|
function resolveSkillSourceDir() {
|
|
163
|
-
return join(dirname(fileURLToPath(import.meta.url)), "..", "
|
|
178
|
+
return join(dirname(fileURLToPath(import.meta.url)), "..", "skills");
|
|
164
179
|
}
|
|
165
180
|
function isNonEmptyDirectory(path) {
|
|
166
181
|
if (!existsSync(path)) return false;
|
|
@@ -316,7 +331,7 @@ try {
|
|
|
316
331
|
}
|
|
317
332
|
if (!service.newlyStarted) {
|
|
318
333
|
const status = await requestService(servicePort, "/status", "GET");
|
|
319
|
-
if (status.running === true) {
|
|
334
|
+
if (status.running === true && status.connected === true) {
|
|
320
335
|
console.log(JSON.stringify({
|
|
321
336
|
servicePort,
|
|
322
337
|
skipped: "service-and-browser-already-running",
|
package/dist/config.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { execSync } from "node:child_process";
|
|
2
|
-
import {
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
5
|
//#region src/scripts/config.ts
|
|
6
6
|
const CLI_RUNTIME_DIR = dirname(fileURLToPath(import.meta.url));
|
|
7
7
|
const HOME = process.env.HOME || process.env.USERPROFILE || "";
|
|
8
|
+
const DEFAULT_BASE_DIR = HOME ? join(HOME, ".browse-agent") : join(process.cwd(), ".browse-agent");
|
|
9
|
+
function unique(paths) {
|
|
10
|
+
return [...new Set(paths.filter(Boolean))];
|
|
11
|
+
}
|
|
8
12
|
const BROWSER_PATHS = {
|
|
9
13
|
chrome: {
|
|
10
14
|
darwin: ["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"],
|
|
@@ -63,8 +67,13 @@ const BROWSER_PATHS = {
|
|
|
63
67
|
netbsd: []
|
|
64
68
|
}
|
|
65
69
|
};
|
|
66
|
-
const BASE_DIR =
|
|
70
|
+
const BASE_DIR = process.env.BROWSE_AGENT_HOME || DEFAULT_BASE_DIR;
|
|
67
71
|
const DEFAULT_SERVICE_PORT = Number(process.env.BROWSE_AGENT_SERVICE_PORT || 9316);
|
|
72
|
+
unique([
|
|
73
|
+
join(CLI_RUNTIME_DIR, ".browse-agent"),
|
|
74
|
+
join(dirname(CLI_RUNTIME_DIR), ".browse-agent"),
|
|
75
|
+
join(process.cwd(), ".browse-agent")
|
|
76
|
+
]).filter((dir) => dir !== BASE_DIR);
|
|
68
77
|
async function importSdk() {
|
|
69
78
|
try {
|
|
70
79
|
return await import("browse-agent-sdk");
|
|
@@ -187,17 +196,6 @@ function getProfileDir(browser, useUserProfile) {
|
|
|
187
196
|
mkdirSync(dir, { recursive: true });
|
|
188
197
|
return dir;
|
|
189
198
|
}
|
|
190
|
-
function patchExtension(port, secret) {
|
|
191
|
-
const extensionSrc = join(BASE_DIR, "extension");
|
|
192
|
-
const extensionWork = join(BASE_DIR, "_ext_work");
|
|
193
|
-
if (!existsSync(join(extensionSrc, "manifest.json"))) throw new Error(`Extension is not installed at ${extensionSrc}. Run "browse-agent setup" first.`);
|
|
194
|
-
if (existsSync(extensionWork)) rmSync(extensionWork, { recursive: true });
|
|
195
|
-
cpSync(extensionSrc, extensionWork, { recursive: true });
|
|
196
|
-
const swPath = join(extensionWork, "service-worker.js");
|
|
197
|
-
const originalSW = readFileSync(swPath, "utf8");
|
|
198
|
-
writeFileSync(swPath, [`chrome.storage.local.set({ wsUrl: 'ws://127.0.0.1:${port}', secret: '${secret}' });`, originalSW].join("\n"));
|
|
199
|
-
return extensionWork;
|
|
200
|
-
}
|
|
201
199
|
function cleanExtensionWork() {
|
|
202
200
|
const extensionWork = join(BASE_DIR, "_ext_work");
|
|
203
201
|
if (existsSync(extensionWork)) rmSync(extensionWork, { recursive: true });
|
|
@@ -206,13 +204,13 @@ function resolveOptions(options = {}) {
|
|
|
206
204
|
return {
|
|
207
205
|
browser: options.browser ?? process.env.BROWSER ?? "chrome",
|
|
208
206
|
headless: options.headless ?? process.env.HEADLESS === "true",
|
|
209
|
-
useUserProfile: options.useUserProfile ?? process.env.USE_USER_PROFILE
|
|
207
|
+
useUserProfile: options.useUserProfile ?? process.env.USE_USER_PROFILE !== "false",
|
|
210
208
|
port: options.port ?? Number(process.env.BROWSE_AGENT_PORT || 9315),
|
|
211
209
|
timeout: options.timeout ?? Number(process.env.CONNECTION_TIMEOUT || 3e4),
|
|
212
210
|
secret: options.secret ?? process.env.SHARED_SECRET ?? ""
|
|
213
211
|
};
|
|
214
212
|
}
|
|
215
213
|
//#endregion
|
|
216
|
-
export {
|
|
214
|
+
export { clearServiceSession as a, getProfileDir as c, loadSession as d, resolveOptions as f, cleanExtensionWork as i, importSdk as l, saveSession as m, DEFAULT_PROFILE_PATHS as n, clearSession as o, saveServiceSession as p, DEFAULT_SERVICE_PORT as r, findBrowser as s, BASE_DIR as t, loadServiceSession as u };
|
|
217
215
|
|
|
218
216
|
//# sourceMappingURL=config.js.map
|
package/dist/script.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { d as loadSession, f as resolveOptions, i as cleanExtensionWork, l as importSdk } from "./config.js";
|
|
2
2
|
import { t as clear } from "./clear.js";
|
|
3
3
|
import { a as injectCSS, c as getDOM, d as closeBrowser, f as launchBrowser, i as screenshot, l as getContent, n as closeTab, o as injectScript, r as listTabs, s as evaluate, t as activateTab, u as navigate } from "./tabs.js";
|
|
4
4
|
//#region src/scripts/connect.ts
|
package/dist/service.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as clearServiceSession, f as resolveOptions, p as saveServiceSession, r as DEFAULT_SERVICE_PORT } from "./config.js";
|
|
2
2
|
import { a as injectCSS, c as getDOM, d as closeBrowser, f as launchBrowser, i as screenshot, l as getContent, n as closeTab, o as injectScript, r as listTabs, s as evaluate, t as activateTab, u as navigate } from "./tabs.js";
|
|
3
3
|
import { createServer } from "node:http";
|
|
4
4
|
//#region src/service.ts
|
|
@@ -13,6 +13,15 @@ function toCommandRequest(value) {
|
|
|
13
13
|
}
|
|
14
14
|
let currentSession = null;
|
|
15
15
|
let currentAgent = null;
|
|
16
|
+
function isProcessAlive(pid) {
|
|
17
|
+
if (!pid) return false;
|
|
18
|
+
try {
|
|
19
|
+
process.kill(pid, 0);
|
|
20
|
+
return true;
|
|
21
|
+
} catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
16
25
|
function getServicePort() {
|
|
17
26
|
const index = process.argv.findIndex((arg) => arg === "--service-port");
|
|
18
27
|
if (index !== -1 && process.argv[index + 1]) {
|
|
@@ -39,11 +48,17 @@ function sessionInfo(session) {
|
|
|
39
48
|
const { _agent, _proc, ...info } = session;
|
|
40
49
|
return {
|
|
41
50
|
running: true,
|
|
51
|
+
connected: Boolean(_agent?.isConnected),
|
|
42
52
|
...info
|
|
43
53
|
};
|
|
44
54
|
}
|
|
45
55
|
async function handleLaunch(body) {
|
|
46
|
-
if (currentSession && currentAgent)
|
|
56
|
+
if (currentSession && currentAgent) {
|
|
57
|
+
const connected = Boolean(currentAgent?.isConnected);
|
|
58
|
+
const browserAlive = isProcessAlive(currentSession.pid);
|
|
59
|
+
if (connected && browserAlive) return sessionInfo(currentSession);
|
|
60
|
+
await stopBrowserSession();
|
|
61
|
+
}
|
|
47
62
|
const options = {
|
|
48
63
|
browser: body.browser,
|
|
49
64
|
headless: body.headless,
|
package/dist/tabs.js
CHANGED
|
@@ -1,11 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { spawn } from "node:child_process";
|
|
1
|
+
import { c as getProfileDir, d as loadSession, f as resolveOptions, i as cleanExtensionWork, l as importSdk, m as saveSession, o as clearSession, s as findBrowser } from "./config.js";
|
|
2
|
+
import { execSync, spawn } from "node:child_process";
|
|
3
3
|
//#region src/scripts/launch-browser.ts
|
|
4
|
+
const BROWSE_AGENT_WEBSTORE_URL = "https://chromewebstore.google.com/detail/browse-agent/amfbnjpgfgappenkkklkogngmoeofeae?authuser=0&hl=zh-CN";
|
|
4
5
|
async function launchBrowser(options = {}) {
|
|
5
6
|
const { BrowserAgent } = await importSdk();
|
|
6
7
|
const opts = resolveOptions(options);
|
|
7
|
-
const extensionWork = patchExtension(opts.port, opts.secret);
|
|
8
8
|
const profileDir = getProfileDir(opts.browser, opts.useUserProfile ?? true);
|
|
9
|
+
try {
|
|
10
|
+
if (process.platform === "win32") execSync("taskkill /F /IM chrome.exe /IM msedge.exe /IM brave.exe 2>nul", { stdio: "ignore" });
|
|
11
|
+
else if (opts.useUserProfile) for (const processName of {
|
|
12
|
+
chrome: ["Google Chrome"],
|
|
13
|
+
chromium: ["Chromium"],
|
|
14
|
+
edge: ["Microsoft Edge"],
|
|
15
|
+
brave: ["Brave Browser"]
|
|
16
|
+
}[opts.browser] || []) execSync(`pkill -x "${processName}" 2>/dev/null || true`, {
|
|
17
|
+
stdio: "pipe",
|
|
18
|
+
shell: "/bin/sh"
|
|
19
|
+
});
|
|
20
|
+
else execSync(`pkill -f "user-data-dir=${profileDir}" 2>/dev/null || true`, {
|
|
21
|
+
stdio: "pipe",
|
|
22
|
+
shell: "/bin/sh"
|
|
23
|
+
});
|
|
24
|
+
} catch {}
|
|
9
25
|
const agent = new BrowserAgent({
|
|
10
26
|
secret: opts.secret,
|
|
11
27
|
port: opts.port
|
|
@@ -13,9 +29,11 @@ async function launchBrowser(options = {}) {
|
|
|
13
29
|
await agent.start();
|
|
14
30
|
console.error(`[browse-agent] Server started on port ${opts.port}`);
|
|
15
31
|
const launchArgs = [
|
|
16
|
-
`--
|
|
32
|
+
`--user-data-dir=${profileDir}`,
|
|
17
33
|
"--no-first-run",
|
|
18
|
-
"--no-default-browser-check"
|
|
34
|
+
"--no-default-browser-check",
|
|
35
|
+
"--new-window",
|
|
36
|
+
BROWSE_AGENT_WEBSTORE_URL
|
|
19
37
|
];
|
|
20
38
|
if (opts.headless) launchArgs.push("--headless=new");
|
|
21
39
|
const proc = spawn(findBrowser(opts.browser), launchArgs, {
|
|
@@ -33,13 +51,14 @@ async function launchBrowser(options = {}) {
|
|
|
33
51
|
secret: opts.secret,
|
|
34
52
|
browser: opts.browser,
|
|
35
53
|
profileDir,
|
|
36
|
-
extensionWork,
|
|
54
|
+
extensionWork: "chrome-webstore:amfbnjpgfgappenkkklkogngmoeofeae",
|
|
37
55
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
38
56
|
_agent: agent,
|
|
39
57
|
_proc: proc
|
|
40
58
|
};
|
|
41
59
|
saveSession(session);
|
|
42
60
|
console.error(`[browse-agent] Browser launched (PID: ${proc.pid})`);
|
|
61
|
+
console.error("[browse-agent] Opened Chrome Web Store page. Please click \"Add to Chrome\" if not installed.");
|
|
43
62
|
return session;
|
|
44
63
|
}
|
|
45
64
|
//#endregion
|
package/package.json
CHANGED
package/skills/SKILL.md
CHANGED
|
@@ -19,7 +19,13 @@ Control a real Chrome browser to visit web pages, extract content, take screensh
|
|
|
19
19
|
browse-agent setup
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
`setup` now opens the Chrome Web Store page in the selected browser and waits for installation detection.
|
|
23
|
+
|
|
24
|
+
Important for AI agents:
|
|
25
|
+
- Always remind the user to run `browse-agent setup` before first use.
|
|
26
|
+
- Explicitly remind the user to click **Add to Chrome** on the Web Store page (installation cannot be silent in normal user environments).
|
|
27
|
+
- `setup` exits immediately if it detects the extension is already installed.
|
|
28
|
+
- Do NOT use `--headless` unless the user explicitly asks for headless/silent/background mode. Default launch should always open a visible browser window.
|
|
23
29
|
|
|
24
30
|
## Usage Procedure — Step-by-Step (Recommended)
|
|
25
31
|
|
|
@@ -79,8 +85,7 @@ Each step is independent. If the page content isn't what you expected, you can n
|
|
|
79
85
|
|
|
80
86
|
| Option | Applies to | Description |
|
|
81
87
|
|---|---|---|
|
|
82
|
-
| `--
|
|
83
|
-
| `--browser <name>` | launch | `chrome` \| `chromium` \| `edge` \| `brave` (default: chrome) |
|
|
88
|
+
| `--browser <name>` | setup, launch | `chrome` \| `chromium` \| `edge` \| `brave` (default: chrome) |
|
|
84
89
|
| `--headless` | launch | Run without visible window |
|
|
85
90
|
| `--port <number>` | launch, connect, feature cmds | WebSocket port (default: 9315) |
|
|
86
91
|
| `--tabId <id>` | all feature cmds | Target a specific tab (ID from `navigate` or `tabs list`) |
|
|
@@ -115,8 +120,7 @@ For full API and script examples, see [API Reference](./references/api.md) and [
|
|
|
115
120
|
## Cleanup
|
|
116
121
|
|
|
117
122
|
```bash
|
|
118
|
-
browse-agent clear # remove local
|
|
119
|
-
browse-agent clear --global # remove global installation
|
|
123
|
+
browse-agent clear # remove local runtime data
|
|
120
124
|
```
|
|
121
125
|
|
|
122
126
|
## References
|
package/skills/references/cli.md
CHANGED
|
@@ -11,11 +11,11 @@ browse-agent <command> [options]
|
|
|
11
11
|
```bash
|
|
12
12
|
# Setup (install SDK + extension)
|
|
13
13
|
browse-agent setup
|
|
14
|
-
browse-agent setup --global
|
|
15
14
|
|
|
16
15
|
# Launch browser
|
|
17
16
|
browse-agent launch
|
|
18
17
|
browse-agent launch --browser edge --headless
|
|
18
|
+
browse-agent launch --server-only
|
|
19
19
|
|
|
20
20
|
# Check connection
|
|
21
21
|
browse-agent connect
|
|
@@ -25,7 +25,6 @@ browse-agent close
|
|
|
25
25
|
|
|
26
26
|
# Remove installation
|
|
27
27
|
browse-agent clear
|
|
28
|
-
browse-agent clear --global
|
|
29
28
|
```
|
|
30
29
|
|
|
31
30
|
## Feature Commands
|
|
@@ -64,9 +63,9 @@ browse-agent tabs close 123
|
|
|
64
63
|
|
|
65
64
|
| Option | Applies to | Description |
|
|
66
65
|
|---|---|---|
|
|
67
|
-
| `--
|
|
68
|
-
| `--browser <name>` | launch | Browser: `chrome` \| `chromium` \| `edge` \| `brave` |
|
|
66
|
+
| `--browser <name>` | launch, setup | Browser: `chrome` \| `chromium` \| `edge` \| `brave` |
|
|
69
67
|
| `--headless` | launch | Run in headless mode |
|
|
68
|
+
| `--server-only` | launch | Start service only, skip browser launch |
|
|
70
69
|
| `--port <number>` | launch, connect, feature cmds | WebSocket port (default: 9315) |
|
|
71
70
|
| `--tabId <id>` | all feature cmds | Target a specific tab (ID from `navigate` or `tabs list`) |
|
|
72
71
|
| `--format <type>` | get-content, screenshot | Content format (`text`/`html`) or screenshot format (`png`/`jpeg`) |
|