browser-pilot-cli
Advanced tools
+47
-11
@@ -7,2 +7,3 @@ #!/usr/bin/env node | ||
| import { resolve as resolvePath } from "path"; | ||
| import { createRequire } from "module"; | ||
@@ -546,4 +547,6 @@ // src/session.ts | ||
| // src/cli.ts | ||
| var require2 = createRequire(import.meta.url); | ||
| var PKG_VERSION = require2("../package.json").version; | ||
| var program = new Command(); | ||
| program.name("bp").description("Control your browser from the command line").version("0.1.0").option("--human", "force human-readable output (default when TTY)").addHelpText("after", ` | ||
| program.name("bp").description("Control your browser from the command line").version(PKG_VERSION).option("--human", "force human-readable output (default when TTY)").addHelpText("after", ` | ||
| Workflow: | ||
@@ -664,3 +667,26 @@ bp connect # one-time setup (click Allow in Chrome) | ||
| pageup: { key: "PageUp", code: "PageUp", keyCode: 33 }, | ||
| pagedown: { key: "PageDown", code: "PageDown", keyCode: 34 } | ||
| pagedown: { key: "PageDown", code: "PageDown", keyCode: 34 }, | ||
| // Digits | ||
| "0": { key: "0", code: "Digit0", keyCode: 48 }, | ||
| "1": { key: "1", code: "Digit1", keyCode: 49 }, | ||
| "2": { key: "2", code: "Digit2", keyCode: 50 }, | ||
| "3": { key: "3", code: "Digit3", keyCode: 51 }, | ||
| "4": { key: "4", code: "Digit4", keyCode: 52 }, | ||
| "5": { key: "5", code: "Digit5", keyCode: 53 }, | ||
| "6": { key: "6", code: "Digit6", keyCode: 54 }, | ||
| "7": { key: "7", code: "Digit7", keyCode: 55 }, | ||
| "8": { key: "8", code: "Digit8", keyCode: 56 }, | ||
| "9": { key: "9", code: "Digit9", keyCode: 57 }, | ||
| // Punctuation | ||
| "-": { key: "-", code: "Minus", keyCode: 189 }, | ||
| "=": { key: "=", code: "Equal", keyCode: 187 }, | ||
| "[": { key: "[", code: "BracketLeft", keyCode: 219 }, | ||
| "]": { key: "]", code: "BracketRight", keyCode: 221 }, | ||
| "\\": { key: "\\", code: "Backslash", keyCode: 220 }, | ||
| ";": { key: ";", code: "Semicolon", keyCode: 186 }, | ||
| "'": { key: "'", code: "Quote", keyCode: 222 }, | ||
| ",": { key: ",", code: "Comma", keyCode: 188 }, | ||
| ".": { key: ".", code: "Period", keyCode: 190 }, | ||
| "/": { key: "/", code: "Slash", keyCode: 191 }, | ||
| "`": { key: "`", code: "Backquote", keyCode: 192 } | ||
| }; | ||
@@ -767,2 +793,3 @@ var MOD_DEFS = { | ||
| bp click 0 --xy 400,300 --right # right-click at coordinates`).action(action(async (ref, opts) => { | ||
| if (opts.double && opts.right) throw new Error("--double and --right are mutually exclusive"); | ||
| const limit = parseLimit(opts.limit); | ||
@@ -855,2 +882,9 @@ await withPilot(async ({ transport, sessionId, state }) => { | ||
| })); | ||
| function charToCode(char) { | ||
| const kd = KEY_DEFS[char]; | ||
| if (kd) return kd; | ||
| if (/^[a-zA-Z]$/.test(char)) return { key: char, code: `Key${char.toUpperCase()}`, keyCode: char.toUpperCase().charCodeAt(0) }; | ||
| if (char === " ") return { key: " ", code: "Space", keyCode: 32 }; | ||
| return { key: char, code: "", keyCode: char.charCodeAt(0) }; | ||
| } | ||
| async function typeViaKeyboard(t, sid, text) { | ||
@@ -863,6 +897,5 @@ for (const char of text) { | ||
| } else if (char.charCodeAt(0) >= 32 && char.charCodeAt(0) <= 126) { | ||
| const code = char === " " ? "Space" : `Key${char.toUpperCase()}`; | ||
| const keyCode = char.toUpperCase().charCodeAt(0); | ||
| await t.send("Input.dispatchKeyEvent", { type: "keyDown", key: char, code, windowsVirtualKeyCode: keyCode, text: char }, sid); | ||
| await t.send("Input.dispatchKeyEvent", { type: "keyUp", key: char, code, windowsVirtualKeyCode: keyCode }, sid); | ||
| const { key, code, keyCode } = charToCode(char); | ||
| await t.send("Input.dispatchKeyEvent", { type: "keyDown", key, code, windowsVirtualKeyCode: keyCode, text: char }, sid); | ||
| await t.send("Input.dispatchKeyEvent", { type: "keyUp", key, code, windowsVirtualKeyCode: keyCode }, sid); | ||
| } else { | ||
@@ -899,3 +932,4 @@ await t.send("Input.insertText", { text: char }, sid); | ||
| if (opts.clear) { | ||
| await dispatchKey(transport, sessionId, "Meta+a"); | ||
| const selectAllMod = process.platform === "darwin" ? "Meta" : "Control"; | ||
| await dispatchKey(transport, sessionId, `${selectAllMod}+a`); | ||
| await dispatchKey(transport, sessionId, "Delete"); | ||
@@ -905,10 +939,12 @@ } | ||
| const delay = parseInt(opts.delay, 10); | ||
| if (isNaN(delay) || delay < 0) throw new Error("--delay must be a non-negative number"); | ||
| for (const char of text) { | ||
| if (char === "\n") { | ||
| await dispatchKey(transport, sessionId, "Enter"); | ||
| } else if (char === " ") { | ||
| await dispatchKey(transport, sessionId, "Tab"); | ||
| } else if (char.charCodeAt(0) >= 32 && char.charCodeAt(0) <= 126) { | ||
| const code = char === " " ? "Space" : `Key${char.toUpperCase()}`; | ||
| const keyCode = char.toUpperCase().charCodeAt(0); | ||
| await transport.send("Input.dispatchKeyEvent", { type: "keyDown", key: char, code, windowsVirtualKeyCode: keyCode, text: char }, sessionId); | ||
| await transport.send("Input.dispatchKeyEvent", { type: "keyUp", key: char, code, windowsVirtualKeyCode: keyCode }, sessionId); | ||
| const { key, code, keyCode } = charToCode(char); | ||
| await transport.send("Input.dispatchKeyEvent", { type: "keyDown", key, code, windowsVirtualKeyCode: keyCode, text: char }, sessionId); | ||
| await transport.send("Input.dispatchKeyEvent", { type: "keyUp", key, code, windowsVirtualKeyCode: keyCode }, sessionId); | ||
| } else { | ||
@@ -915,0 +951,0 @@ await transport.send("Input.insertText", { text: char }, sessionId); |
+1
-1
| { | ||
| "name": "browser-pilot-cli", | ||
| "version": "0.1.4", | ||
| "version": "0.1.5", | ||
| "description": "CLI tool to control your browser via Chrome DevTools Protocol", | ||
@@ -5,0 +5,0 @@ "type": "module", |
+12
-1
@@ -99,4 +99,6 @@ # browser-pilot | ||
| | `bp snapshot` | snapshot | Get interactive elements | | ||
| | `bp click <ref>` | snapshot | Click element by ref number | | ||
| | `bp click <ref>` | snapshot | Click element by ref number (`--double`, `--right`) | | ||
| | `bp click 0 --xy x,y` | snapshot | Click at viewport coordinates (canvas, maps) | | ||
| | `bp type <ref> <text>` | snapshot | Type into element (`--clear`, `--submit`) | | ||
| | `bp keyboard <text>` | snapshot | Type via keyboard events (`--click`, `--clear`) | | ||
| | `bp press <key>` | snapshot | Press key (Enter, Escape, Control+a, Meta+c) | | ||
@@ -215,2 +217,11 @@ | `bp eval [js]` | value | Run JavaScript (escape hatch for anything) | | ||
| For canvas-based editors (Google Docs, Google Sheets, Figma), use `bp keyboard` which sends real keyboard events: | ||
| ```bash | ||
| bp keyboard "Hello Docs!" --click ".kix-appview-editor" # Google Docs | ||
| bp press Meta+b # toggle bold | ||
| bp keyboard "bold text" | ||
| bp click 0 --xy 400,300 # click canvas area | ||
| ``` | ||
| Shadow DOM elements are traversed automatically — no special commands needed. Elements inside open shadow roots (even deeply nested) appear in snapshots and can be clicked/typed normally. | ||
@@ -217,0 +228,0 @@ |
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
302986
0.79%2668
1.37%287
3.99%14
7.69%