browsirai 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -1
- package/dist/bin.js +44 -43
- package/dist/bin.js.map +1 -1
- package/dist/cli/commands/act.js +1226 -0
- package/dist/cli/commands/act.js.map +1 -0
- package/dist/cli/commands/nav.js +739 -0
- package/dist/cli/commands/nav.js.map +1 -0
- package/dist/cli/commands/net.js +556 -0
- package/dist/cli/commands/net.js.map +1 -0
- package/dist/cli/commands/obs.js +1049 -0
- package/dist/cli/commands/obs.js.map +1 -0
- package/dist/cli/run.js +727 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli.js +44 -43
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
**Your browser. Your sessions. Your agent.**
|
|
7
7
|
|
|
8
|
-
An MCP server that connects AI coding agents to your real Chrome via CDP.
|
|
8
|
+
An MCP server + CLI that connects AI coding agents to your real Chrome via CDP. Use as an MCP server for LLM-driven automation, or as a standalone CLI for direct browser control from the terminal.
|
|
9
9
|
|
|
10
10
|
## Why browsirai?
|
|
11
11
|
|
|
@@ -170,6 +170,65 @@ mcpServers:
|
|
|
170
170
|
```
|
|
171
171
|
</details>
|
|
172
172
|
|
|
173
|
+
## CLI Mode
|
|
174
|
+
|
|
175
|
+
browsirai also works as a standalone CLI — no LLM required. Same commands, same Chrome connection.
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
browsirai open example.com
|
|
179
|
+
browsirai snapshot -i
|
|
180
|
+
browsirai click @e5
|
|
181
|
+
browsirai fill @e2 "hello world"
|
|
182
|
+
browsirai press Enter
|
|
183
|
+
browsirai eval "document.title"
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Commands (30)
|
|
187
|
+
|
|
188
|
+
| Category | Commands |
|
|
189
|
+
|----------|----------|
|
|
190
|
+
| **Navigation** | `open` (goto, navigate), `back`, `scroll`, `wait`, `tab` (tabs), `close`, `resize` |
|
|
191
|
+
| **Observation** | `snapshot`, `screenshot`, `html`, `eval`, `find`, `source`, `console`, `network` |
|
|
192
|
+
| **Actions** | `click`, `fill`, `type`, `press` (key), `hover`, `drag`, `select`, `upload`, `dialog` |
|
|
193
|
+
| **Network** | `route`, `abort`, `unroute`, `save`, `load`, `diff` |
|
|
194
|
+
|
|
195
|
+
### Short Flags
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
browsirai snapshot -i # interactive elements only
|
|
199
|
+
browsirai snapshot -c # compact output
|
|
200
|
+
browsirai snapshot -d 3 # depth limit
|
|
201
|
+
browsirai snapshot -s "main" # scope to selector
|
|
202
|
+
browsirai screenshot -o ss.png # save to file
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Positional Arguments
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
browsirai click @e5 # ref (not --ref=@e5)
|
|
209
|
+
browsirai click "#submit" # CSS selector
|
|
210
|
+
browsirai fill @e2 "text" # ref + value
|
|
211
|
+
browsirai drag @e1 @e2 # source + target
|
|
212
|
+
browsirai select @e3 "option1" # ref + value(s)
|
|
213
|
+
browsirai scroll down # direction
|
|
214
|
+
browsirai resize 1280 720 # width height
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Workflow Example
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
browsirai open github.com/login
|
|
221
|
+
browsirai snapshot -i
|
|
222
|
+
# @e12 textbox "Username"
|
|
223
|
+
# @e15 textbox "Password"
|
|
224
|
+
# @e18 button "Sign in"
|
|
225
|
+
browsirai fill @e12 "user@example.com"
|
|
226
|
+
browsirai fill @e15 "password"
|
|
227
|
+
browsirai click @e18
|
|
228
|
+
browsirai wait --url="github.com/dashboard"
|
|
229
|
+
browsirai snapshot -i
|
|
230
|
+
```
|
|
231
|
+
|
|
173
232
|
## Features
|
|
174
233
|
|
|
175
234
|
| Feature | Description |
|
package/dist/bin.js
CHANGED
|
@@ -4602,6 +4602,8 @@ __export(doctor_exports, {
|
|
|
4602
4602
|
});
|
|
4603
4603
|
import { execSync as execSync3 } from "child_process";
|
|
4604
4604
|
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
|
|
4605
|
+
import { homedir as homedir4 } from "os";
|
|
4606
|
+
import { join as join4 } from "path";
|
|
4605
4607
|
function findChromePath() {
|
|
4606
4608
|
const whichCommands = process.platform === "win32" ? ["where chrome", "where chromium", "where msedge"] : ["which google-chrome", "which chromium", "which chromium-browser", "which chrome"];
|
|
4607
4609
|
for (const cmd of whichCommands) {
|
|
@@ -4638,41 +4640,52 @@ function checkNodeVersion() {
|
|
|
4638
4640
|
message: ok ? `v${versionStr} (>= 18 required)` : `v${versionStr} \u2014 Node.js >= 18 is required`
|
|
4639
4641
|
};
|
|
4640
4642
|
}
|
|
4641
|
-
function
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
label: "Platform config",
|
|
4649
|
-
message: `Config file not found: ${configPath} (platform: ${detection.platform})`
|
|
4650
|
-
};
|
|
4651
|
-
}
|
|
4643
|
+
function resolvePath(p) {
|
|
4644
|
+
if (p.startsWith("~/")) return join4(homedir4(), p.slice(2));
|
|
4645
|
+
return p;
|
|
4646
|
+
}
|
|
4647
|
+
function checkConfigFile(filePath, configKey, platform) {
|
|
4648
|
+
const resolved = resolvePath(filePath);
|
|
4649
|
+
if (!existsSync4(resolved)) return null;
|
|
4652
4650
|
try {
|
|
4653
|
-
const content = readFileSync4(
|
|
4651
|
+
const content = readFileSync4(resolved, "utf-8");
|
|
4654
4652
|
const parsed = JSON.parse(content);
|
|
4655
|
-
const servers = parsed[
|
|
4653
|
+
const servers = parsed[configKey];
|
|
4656
4654
|
if (servers && typeof servers === "object" && "browsirai" in servers) {
|
|
4657
4655
|
return {
|
|
4658
4656
|
ok: true,
|
|
4659
4657
|
label: "Platform config",
|
|
4660
|
-
message: `browsirai found in ${
|
|
4658
|
+
message: `browsirai found in ${resolved} (platform: ${platform})`
|
|
4661
4659
|
};
|
|
4662
4660
|
}
|
|
4663
|
-
return
|
|
4664
|
-
ok: false,
|
|
4665
|
-
label: "Platform config",
|
|
4666
|
-
message: `browsirai not found in ${configPath} under "${config.configKey}"`
|
|
4667
|
-
};
|
|
4661
|
+
return null;
|
|
4668
4662
|
} catch {
|
|
4669
|
-
return
|
|
4670
|
-
ok: false,
|
|
4671
|
-
label: "Platform config",
|
|
4672
|
-
message: `Failed to parse config file: ${configPath}`
|
|
4673
|
-
};
|
|
4663
|
+
return null;
|
|
4674
4664
|
}
|
|
4675
4665
|
}
|
|
4666
|
+
function checkPlatformConfig() {
|
|
4667
|
+
const detection = detectPlatform();
|
|
4668
|
+
const config = getInstallConfig(detection.platform);
|
|
4669
|
+
const detected = checkConfigFile(config.configPath, config.configKey, detection.platform);
|
|
4670
|
+
if (detected) return detected;
|
|
4671
|
+
const knownPaths = [
|
|
4672
|
+
{ path: "~/.mcp.json", key: "mcpServers", platform: "claude-code (global)" },
|
|
4673
|
+
{ path: ".mcp.json", key: "mcpServers", platform: "claude-code" },
|
|
4674
|
+
{ path: ".cursor/mcp.json", key: "mcpServers", platform: "cursor" },
|
|
4675
|
+
{ path: "~/.gemini/settings.json", key: "mcpServers", platform: "gemini-cli" },
|
|
4676
|
+
{ path: ".vscode/mcp.json", key: "servers", platform: "vscode-copilot" },
|
|
4677
|
+
{ path: "~/.codeium/windsurf/mcp_config.json", key: "mcpServers", platform: "windsurf" }
|
|
4678
|
+
];
|
|
4679
|
+
for (const entry of knownPaths) {
|
|
4680
|
+
const result = checkConfigFile(entry.path, entry.key, entry.platform);
|
|
4681
|
+
if (result) return result;
|
|
4682
|
+
}
|
|
4683
|
+
return {
|
|
4684
|
+
ok: false,
|
|
4685
|
+
label: "Platform config",
|
|
4686
|
+
message: `browsirai not found in any known config file (detected: ${detection.platform})`
|
|
4687
|
+
};
|
|
4688
|
+
}
|
|
4676
4689
|
async function runDoctor() {
|
|
4677
4690
|
const checks = [];
|
|
4678
4691
|
const method = getInstallMethod();
|
|
@@ -4750,13 +4763,13 @@ __export(install_exports, {
|
|
|
4750
4763
|
import { intro, select, confirm, spinner, outro, isCancel, cancel, log } from "@clack/prompts";
|
|
4751
4764
|
import { existsSync as existsSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4 } from "fs";
|
|
4752
4765
|
import { resolve, dirname as dirname2 } from "path";
|
|
4753
|
-
import { homedir as
|
|
4766
|
+
import { homedir as homedir5 } from "os";
|
|
4754
4767
|
function resolveConfigPath(configPath, scope) {
|
|
4755
4768
|
if (configPath.startsWith("~")) {
|
|
4756
|
-
return resolve(
|
|
4769
|
+
return resolve(homedir5(), configPath.slice(2));
|
|
4757
4770
|
}
|
|
4758
4771
|
if (scope === "global") {
|
|
4759
|
-
return resolve(
|
|
4772
|
+
return resolve(homedir5(), configPath);
|
|
4760
4773
|
}
|
|
4761
4774
|
return resolve(process.cwd(), configPath);
|
|
4762
4775
|
}
|
|
@@ -4768,7 +4781,7 @@ async function runInstall() {
|
|
|
4768
4781
|
const config2 = getInstallConfig(opt.value);
|
|
4769
4782
|
const paths = [
|
|
4770
4783
|
resolve(process.cwd(), config2.configPath),
|
|
4771
|
-
config2.configPath.startsWith("~") ? resolve(
|
|
4784
|
+
config2.configPath.startsWith("~") ? resolve(homedir5(), config2.configPath.slice(2)) : resolve(homedir5(), config2.configPath)
|
|
4772
4785
|
];
|
|
4773
4786
|
for (const filePath2 of paths) {
|
|
4774
4787
|
if (existsSync5(filePath2)) {
|
|
@@ -4901,21 +4914,9 @@ async function runCli(args) {
|
|
|
4901
4914
|
break;
|
|
4902
4915
|
}
|
|
4903
4916
|
default: {
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
`browsirai v${VERSION}`,
|
|
4908
|
-
"",
|
|
4909
|
-
"Usage: browsirai [command]",
|
|
4910
|
-
"",
|
|
4911
|
-
"Commands:",
|
|
4912
|
-
" (none) Start the MCP server (default)",
|
|
4913
|
-
" doctor Run diagnostics",
|
|
4914
|
-
" install Install browser integration",
|
|
4915
|
-
" --version Print version",
|
|
4916
|
-
""
|
|
4917
|
-
].join("\n")
|
|
4918
|
-
);
|
|
4917
|
+
const cliUrl = new URL("./cli/run.js", import.meta.url);
|
|
4918
|
+
const { runCLI } = await import(cliUrl.href);
|
|
4919
|
+
await runCLI(args);
|
|
4919
4920
|
break;
|
|
4920
4921
|
}
|
|
4921
4922
|
}
|