@browserbasehq/cli 0.3.1 → 0.4.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/LICENSE +21 -0
- package/README.md +170 -9
- package/dist/commands/browse.js +39 -13
- package/dist/commands/contexts.js +15 -10
- package/dist/commands/extensions.js +7 -7
- package/dist/commands/fetch.js +7 -3
- package/dist/commands/functions.js +22 -10
- package/dist/commands/projects.js +7 -7
- package/dist/commands/search.js +7 -3
- package/dist/commands/sessions.js +36 -21
- package/dist/commands/skills.js +25 -12
- package/dist/lib/command.js +25 -0
- package/package.json +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Browserbase, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,20 +1,181 @@
|
|
|
1
1
|
# Browserbase CLI
|
|
2
2
|
|
|
3
|
-
Browserbase
|
|
3
|
+
The official CLI for [Browserbase](https://browserbase.com). Manage sessions, deploy serverless functions, browse the web, and interact with the full Browserbase platform from your terminal.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
npm install -g @browserbasehq/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Requires Node.js 18+.
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Set your API key
|
|
17
|
+
export BROWSERBASE_API_KEY=bb_live_...
|
|
18
|
+
|
|
19
|
+
# Fetch a webpage
|
|
20
|
+
bb fetch https://example.com
|
|
21
|
+
|
|
22
|
+
# Search the web
|
|
23
|
+
bb search "browserbase documentation"
|
|
24
|
+
|
|
25
|
+
# Browse interactively
|
|
26
|
+
bb browse https://example.com
|
|
27
|
+
|
|
28
|
+
# List your sessions
|
|
29
|
+
bb sessions list
|
|
11
30
|
```
|
|
12
31
|
|
|
13
|
-
##
|
|
32
|
+
## Commands
|
|
33
|
+
|
|
34
|
+
### `bb fetch <url>`
|
|
35
|
+
|
|
36
|
+
Retrieve webpage content without a full browser session.
|
|
14
37
|
|
|
15
38
|
```bash
|
|
16
|
-
|
|
39
|
+
bb fetch https://example.com
|
|
40
|
+
bb fetch https://example.com --output page.json
|
|
41
|
+
bb fetch https://example.com --proxies --allow-redirects
|
|
17
42
|
```
|
|
18
43
|
|
|
19
|
-
|
|
20
|
-
|
|
44
|
+
| Flag | Description |
|
|
45
|
+
|------|-------------|
|
|
46
|
+
| `--output <path>` | Write response to file |
|
|
47
|
+
| `--proxies` | Enable Browserbase proxy support |
|
|
48
|
+
| `--allow-redirects` | Follow HTTP redirects |
|
|
49
|
+
| `--allow-insecure-ssl` | Bypass TLS certificate verification |
|
|
50
|
+
|
|
51
|
+
### `bb search <query>`
|
|
52
|
+
|
|
53
|
+
Search the web using the Browserbase Search API.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
bb search "web automation tools"
|
|
57
|
+
bb search "browserbase" --num-results 5
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
| Flag | Description |
|
|
61
|
+
|------|-------------|
|
|
62
|
+
| `--num-results <n>` | Number of results (1-25, default 10) |
|
|
63
|
+
| `--output <path>` | Write results to file |
|
|
64
|
+
|
|
65
|
+
### `bb browse [args...]`
|
|
66
|
+
|
|
67
|
+
Launch a browser session. Forwards to the `@browserbasehq/browse-cli` package (auto-installs on first use).
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
bb browse https://example.com
|
|
71
|
+
bb browse --yes # skip install prompt
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### `bb sessions`
|
|
75
|
+
|
|
76
|
+
Manage remote browser sessions.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
bb sessions list # List all sessions
|
|
80
|
+
bb sessions list --q "status=RUNNING" # Filter by metadata
|
|
81
|
+
bb sessions get <session-id> # Get session details
|
|
82
|
+
bb sessions create --body '{"projectId":"..."}'
|
|
83
|
+
bb sessions update <id> --status REQUEST_RELEASE
|
|
84
|
+
bb sessions debug <id> # Get debugger connection URLs
|
|
85
|
+
bb sessions logs <id> # View session logs
|
|
86
|
+
bb sessions recording <id> # Get rrweb recording events
|
|
87
|
+
bb sessions downloads get <id> # Download session artifacts (ZIP)
|
|
88
|
+
bb sessions uploads create <id> <file> # Upload a file to a session
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### `bb functions`
|
|
92
|
+
|
|
93
|
+
Write and deploy serverless browser automation to the cloud.
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Scaffold a new project
|
|
97
|
+
bb functions init my-function
|
|
98
|
+
|
|
99
|
+
# Run locally
|
|
100
|
+
bb functions dev handler.ts --port 3000
|
|
101
|
+
|
|
102
|
+
# Deploy to Browserbase
|
|
103
|
+
bb functions publish handler.ts
|
|
104
|
+
bb functions publish handler.ts --dry-run # preview without deploying
|
|
105
|
+
|
|
106
|
+
# Invoke a deployed function
|
|
107
|
+
bb functions invoke <function-id> --params '{"url":"https://example.com"}'
|
|
108
|
+
bb functions invoke --check-status <invocation-id>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
| Subcommand | Description |
|
|
112
|
+
|------------|-------------|
|
|
113
|
+
| `init [name]` | Scaffold a Functions project (`--package-manager npm\|pnpm`) |
|
|
114
|
+
| `dev <entry>` | Start local dev server (`--port`, `--host`, `--verbose`) |
|
|
115
|
+
| `publish <entry>` | Deploy function (`--dry-run`) |
|
|
116
|
+
| `invoke [id]` | Invoke a function (`--params`, `--no-wait`, `--check-status`) |
|
|
117
|
+
|
|
118
|
+
### `bb projects`
|
|
119
|
+
|
|
120
|
+
Manage Browserbase projects.
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
bb projects list
|
|
124
|
+
bb projects get <project-id>
|
|
125
|
+
bb projects usage <project-id>
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### `bb contexts`
|
|
129
|
+
|
|
130
|
+
Persist browser state (cookies, localStorage) across sessions.
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
bb contexts create --body '{"projectId":"..."}'
|
|
134
|
+
bb contexts get <context-id>
|
|
135
|
+
bb contexts update <context-id> # Refresh upload URL
|
|
136
|
+
bb contexts delete <context-id>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### `bb extensions`
|
|
140
|
+
|
|
141
|
+
Manage Chrome extensions for remote sessions.
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
bb extensions upload extension.zip
|
|
145
|
+
bb extensions get <extension-id>
|
|
146
|
+
bb extensions delete <extension-id>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### `bb skills`
|
|
150
|
+
|
|
151
|
+
Install Browserbase agent skills for Claude Code.
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
bb skills # Interactive install
|
|
155
|
+
bb skills install # Non-interactive install
|
|
156
|
+
bb skills --yes # Auto-accept prompts
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Configuration
|
|
160
|
+
|
|
161
|
+
| Environment Variable | Description |
|
|
162
|
+
|---------------------|-------------|
|
|
163
|
+
| `BROWSERBASE_API_KEY` | Your Browserbase API key (required) |
|
|
164
|
+
| `BROWSERBASE_PROJECT_ID` | Default project ID for Functions |
|
|
165
|
+
| `BROWSERBASE_BASE_URL` | Custom API base URL |
|
|
166
|
+
|
|
167
|
+
All environment variables can be overridden per-command with `--api-key`, `--project-id`, or `--base-url` flags.
|
|
168
|
+
|
|
169
|
+
## Development
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
bun install
|
|
173
|
+
bun run cli -- --help # Run locally
|
|
174
|
+
bun run check # Type-check
|
|
175
|
+
bun run build # Build to dist/
|
|
176
|
+
bun run test # Build + run tests
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## License
|
|
180
|
+
|
|
181
|
+
This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.
|
package/dist/commands/browse.js
CHANGED
|
@@ -19,6 +19,19 @@ async function installBrowseCli() {
|
|
|
19
19
|
process.exitCode = exitCode;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
+
function extractYesFlag(args) {
|
|
23
|
+
const remaining = [];
|
|
24
|
+
let yes = false;
|
|
25
|
+
for (const arg of args) {
|
|
26
|
+
if (arg === "--yes" || arg === "-y") {
|
|
27
|
+
yes = true;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
remaining.push(arg);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return { yes, remaining };
|
|
34
|
+
}
|
|
22
35
|
export function attachBrowseCommand(program) {
|
|
23
36
|
program
|
|
24
37
|
.command("browse")
|
|
@@ -28,7 +41,15 @@ export function attachBrowseCommand(program) {
|
|
|
28
41
|
.allowExcessArguments(true)
|
|
29
42
|
.passThroughOptions()
|
|
30
43
|
.helpOption(false)
|
|
44
|
+
.addHelpText("after", [
|
|
45
|
+
"",
|
|
46
|
+
"Examples:",
|
|
47
|
+
" bb browse --url https://example.com",
|
|
48
|
+
' bb browse --url https://example.com --text "Click Login"',
|
|
49
|
+
" bb browse --yes (auto-install if not present)",
|
|
50
|
+
].join("\n"))
|
|
31
51
|
.action(async (args) => {
|
|
52
|
+
const { yes, remaining: forwardArgs } = extractYesFlag(args ?? []);
|
|
32
53
|
let browsePath = await findExecutable("browse");
|
|
33
54
|
if (!browsePath) {
|
|
34
55
|
console.log([
|
|
@@ -39,18 +60,23 @@ export function attachBrowseCommand(program) {
|
|
|
39
60
|
" npm install -g @browserbasehq/browse-cli",
|
|
40
61
|
"",
|
|
41
62
|
].join("\n"));
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
63
|
+
if (!yes) {
|
|
64
|
+
if (!process.stdin.isTTY) {
|
|
65
|
+
fail("Cannot prompt for install in non-interactive mode. Use --yes to auto-install.");
|
|
66
|
+
}
|
|
67
|
+
const rl = readline.createInterface({
|
|
68
|
+
input: process.stdin,
|
|
69
|
+
output: process.stdout,
|
|
70
|
+
});
|
|
71
|
+
try {
|
|
72
|
+
const answer = await rl.question("Install now? [Y/n] ");
|
|
73
|
+
if (answer.trim().toLowerCase() === "n") {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
rl.close();
|
|
50
79
|
}
|
|
51
|
-
}
|
|
52
|
-
finally {
|
|
53
|
-
rl.close();
|
|
54
80
|
}
|
|
55
81
|
await installBrowseCli();
|
|
56
82
|
browsePath = await findExecutable("browse");
|
|
@@ -61,8 +87,8 @@ export function attachBrowseCommand(program) {
|
|
|
61
87
|
].join("\n"));
|
|
62
88
|
}
|
|
63
89
|
}
|
|
64
|
-
const
|
|
65
|
-
const exitCode = await spawnPassthrough(browsePath,
|
|
90
|
+
const finalArgs = forwardArgs.length > 0 ? forwardArgs : ["--help"];
|
|
91
|
+
const exitCode = await spawnPassthrough(browsePath, finalArgs);
|
|
66
92
|
if (exitCode !== 0) {
|
|
67
93
|
process.exitCode = exitCode;
|
|
68
94
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { addCommonApiOptions, createBrowserbaseClient, outputJson,
|
|
1
|
+
import { addCommonApiOptions, addExamples, createBrowserbaseClient, outputJson, resolveBody, requestBrowserbase, requestBrowserbaseJson, } from "../lib/command.js";
|
|
2
2
|
export function attachContextsCommand(program) {
|
|
3
3
|
const contexts = program
|
|
4
4
|
.command("contexts")
|
|
@@ -7,30 +7,35 @@ export function attachContextsCommand(program) {
|
|
|
7
7
|
contexts.action(() => {
|
|
8
8
|
contexts.outputHelp();
|
|
9
9
|
});
|
|
10
|
-
addCommonApiOptions(contexts
|
|
10
|
+
addExamples(addCommonApiOptions(contexts
|
|
11
11
|
.command("create")
|
|
12
12
|
.description("Create a context.")
|
|
13
|
-
.option("--body <body>", "Optional JSON request body.")
|
|
13
|
+
.option("--body <body>", "Optional JSON request body.")
|
|
14
|
+
.option("--stdin", "Read JSON request body from stdin.")), [
|
|
15
|
+
"bb contexts create",
|
|
16
|
+
`bb contexts create --body '{"projectId":"proj_abc"}'`,
|
|
17
|
+
`echo '{"projectId":"proj_abc"}' | bb contexts create --stdin`,
|
|
18
|
+
]).action(async (options) => {
|
|
14
19
|
const client = createBrowserbaseClient(options);
|
|
15
|
-
const body =
|
|
20
|
+
const body = await resolveBody(options);
|
|
16
21
|
outputJson(await client.contexts.create(body));
|
|
17
22
|
});
|
|
18
|
-
addCommonApiOptions(contexts
|
|
23
|
+
addExamples(addCommonApiOptions(contexts
|
|
19
24
|
.command("get <id>")
|
|
20
|
-
.description("Get a context by ID.")).action(async (id, options) => {
|
|
25
|
+
.description("Get a context by ID.")), ["bb contexts get <context-id>"]).action(async (id, options) => {
|
|
21
26
|
const client = createBrowserbaseClient(options);
|
|
22
27
|
outputJson(await client.contexts.retrieve(id));
|
|
23
28
|
});
|
|
24
|
-
addCommonApiOptions(contexts
|
|
29
|
+
addExamples(addCommonApiOptions(contexts
|
|
25
30
|
.command("update <id>")
|
|
26
|
-
.description("Refresh the upload URL for a context.")).action(async (id, options) => {
|
|
31
|
+
.description("Refresh the upload URL for a context.")), ["bb contexts update <context-id>"]).action(async (id, options) => {
|
|
27
32
|
outputJson(await requestBrowserbaseJson(options, `/v1/contexts/${id}`, {
|
|
28
33
|
method: "PUT",
|
|
29
34
|
}));
|
|
30
35
|
});
|
|
31
|
-
addCommonApiOptions(contexts
|
|
36
|
+
addExamples(addCommonApiOptions(contexts
|
|
32
37
|
.command("delete <id>")
|
|
33
|
-
.description("Delete a context.")).action(async (id, options) => {
|
|
38
|
+
.description("Delete a context.")), ["bb contexts delete <context-id>"]).action(async (id, options) => {
|
|
34
39
|
await requestBrowserbase(options, `/v1/contexts/${id}`, {
|
|
35
40
|
method: "DELETE",
|
|
36
41
|
headers: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { addCommonApiOptions, createBrowserbaseClient, outputJson, requestBrowserbase, resolveUploadableFile, } from "../lib/command.js";
|
|
1
|
+
import { addCommonApiOptions, addExamples, createBrowserbaseClient, outputJson, requestBrowserbase, resolveUploadableFile, } from "../lib/command.js";
|
|
2
2
|
export function attachExtensionsCommand(program) {
|
|
3
3
|
const extensions = program
|
|
4
4
|
.command("extensions")
|
|
@@ -7,23 +7,23 @@ export function attachExtensionsCommand(program) {
|
|
|
7
7
|
extensions.action(() => {
|
|
8
8
|
extensions.outputHelp();
|
|
9
9
|
});
|
|
10
|
-
addCommonApiOptions(extensions
|
|
10
|
+
addExamples(addCommonApiOptions(extensions
|
|
11
11
|
.command("upload <file>")
|
|
12
|
-
.description("Upload an extension ZIP file.")).action(async (file, options) => {
|
|
12
|
+
.description("Upload an extension ZIP file.")), ["bb extensions upload ./extension.zip"]).action(async (file, options) => {
|
|
13
13
|
const client = createBrowserbaseClient(options);
|
|
14
14
|
outputJson(await client.extensions.create({
|
|
15
15
|
file: await resolveUploadableFile(file, "extension"),
|
|
16
16
|
}));
|
|
17
17
|
});
|
|
18
|
-
addCommonApiOptions(extensions
|
|
18
|
+
addExamples(addCommonApiOptions(extensions
|
|
19
19
|
.command("get <id>")
|
|
20
|
-
.description("Get an extension by ID.")).action(async (id, options) => {
|
|
20
|
+
.description("Get an extension by ID.")), ["bb extensions get <extension-id>"]).action(async (id, options) => {
|
|
21
21
|
const client = createBrowserbaseClient(options);
|
|
22
22
|
outputJson(await client.extensions.retrieve(id));
|
|
23
23
|
});
|
|
24
|
-
addCommonApiOptions(extensions
|
|
24
|
+
addExamples(addCommonApiOptions(extensions
|
|
25
25
|
.command("delete <id>")
|
|
26
|
-
.description("Delete an extension.")).action(async (id, options) => {
|
|
26
|
+
.description("Delete an extension.")), ["bb extensions delete <extension-id>"]).action(async (id, options) => {
|
|
27
27
|
await requestBrowserbase(options, `/v1/extensions/${id}`, {
|
|
28
28
|
method: "DELETE",
|
|
29
29
|
headers: {
|
package/dist/commands/fetch.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
import { addCommonApiOptions, createBrowserbaseClient, outputJson, writeOutputFile, } from "../lib/command.js";
|
|
1
|
+
import { addCommonApiOptions, addExamples, createBrowserbaseClient, outputJson, writeOutputFile, } from "../lib/command.js";
|
|
2
2
|
export function attachFetchCommand(program) {
|
|
3
|
-
addCommonApiOptions(program
|
|
3
|
+
addExamples(addCommonApiOptions(program
|
|
4
4
|
.command("fetch <url>")
|
|
5
5
|
.description("Retrieve webpage content without a full browser session using the lightweight Browserbase Fetch API.")
|
|
6
6
|
.option("--allow-insecure-ssl", "Bypass TLS certificate verification.")
|
|
7
7
|
.option("--allow-redirects", "Follow HTTP redirects.")
|
|
8
8
|
.option("--proxies", "Enable Browserbase proxy support.")
|
|
9
|
-
.option("--output <output>", "Write the fetched content to a file."))
|
|
9
|
+
.option("--output <output>", "Write the fetched content to a file.")), [
|
|
10
|
+
"bb fetch https://www.google.com",
|
|
11
|
+
"bb fetch https://example.com --allow-insecure-ssl --output page.html",
|
|
12
|
+
"bb fetch https://example.com --allow-redirects --proxies",
|
|
13
|
+
]).action(async (url, options) => {
|
|
10
14
|
const client = createBrowserbaseClient(options);
|
|
11
15
|
const result = await client.fetchAPI.create({
|
|
12
16
|
url,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Option } from "commander";
|
|
2
|
-
import { addFunctionsApiOptions } from "../lib/command.js";
|
|
2
|
+
import { addExamples, addFunctionsApiOptions } from "../lib/command.js";
|
|
3
3
|
import { initFunctionsProject } from "../lib/functions/init.js";
|
|
4
4
|
import { invokeFunction } from "../lib/functions/invoke.js";
|
|
5
5
|
import { startFunctionsDevServer } from "../lib/functions/dev.js";
|
|
@@ -13,23 +13,28 @@ export function attachFunctionsCommand(program) {
|
|
|
13
13
|
functions.action(() => {
|
|
14
14
|
functions.outputHelp();
|
|
15
15
|
});
|
|
16
|
-
functions
|
|
16
|
+
addExamples(functions
|
|
17
17
|
.command("init [projectName]")
|
|
18
18
|
.description("Initialize a new Browserbase Functions project.")
|
|
19
19
|
.addOption(new Option("--package-manager <packageManager>", "Package manager to use.")
|
|
20
20
|
.choices([...packageManagers])
|
|
21
|
-
.default("pnpm"))
|
|
22
|
-
|
|
21
|
+
.default("pnpm")), [
|
|
22
|
+
"bb functions init my-function",
|
|
23
|
+
"bb functions init my-function --package-manager npm",
|
|
24
|
+
]).action(async (projectName, options) => {
|
|
23
25
|
await initFunctionsProject({
|
|
24
26
|
projectName: projectName ?? "my-browserbase-function",
|
|
25
27
|
packageManager: options.packageManager ?? "pnpm",
|
|
26
28
|
});
|
|
27
29
|
});
|
|
28
|
-
addFunctionsApiOptions(functions
|
|
30
|
+
addExamples(addFunctionsApiOptions(functions
|
|
29
31
|
.command("dev <entrypoint>")
|
|
30
32
|
.description("Run the local Browserbase Functions development server.")
|
|
31
33
|
.option("--port <port>", "Port to listen on.", "14113")
|
|
32
|
-
.option("--host <host>", "Host to bind to.", "127.0.0.1"), { includeProjectId: true, includeVerbose: true })
|
|
34
|
+
.option("--host <host>", "Host to bind to.", "127.0.0.1"), { includeProjectId: true, includeVerbose: true }), [
|
|
35
|
+
"bb functions dev index.ts",
|
|
36
|
+
"bb functions dev index.ts --port 3000 --verbose",
|
|
37
|
+
]).action(async (entrypoint, options) => {
|
|
33
38
|
await startFunctionsDevServer({
|
|
34
39
|
entrypoint,
|
|
35
40
|
port: Number(options.port ?? "14113"),
|
|
@@ -40,10 +45,13 @@ export function attachFunctionsCommand(program) {
|
|
|
40
45
|
verbose: options.verbose ?? false,
|
|
41
46
|
});
|
|
42
47
|
});
|
|
43
|
-
addFunctionsApiOptions(functions
|
|
48
|
+
addExamples(addFunctionsApiOptions(functions
|
|
44
49
|
.command("publish <entrypoint>")
|
|
45
50
|
.description("Package and upload a Browserbase Function build.")
|
|
46
|
-
.option("--dry-run", "Show what would be published without uploading."), { includeProjectId: true })
|
|
51
|
+
.option("--dry-run", "Show what would be published without uploading."), { includeProjectId: true }), [
|
|
52
|
+
"bb functions publish index.ts --dry-run",
|
|
53
|
+
"bb functions publish index.ts",
|
|
54
|
+
]).action(async (entrypoint, options) => {
|
|
47
55
|
await publishFunction({
|
|
48
56
|
entrypoint,
|
|
49
57
|
apiKey: options.apiKey,
|
|
@@ -52,12 +60,16 @@ export function attachFunctionsCommand(program) {
|
|
|
52
60
|
dryRun: options.dryRun ?? false,
|
|
53
61
|
});
|
|
54
62
|
});
|
|
55
|
-
addFunctionsApiOptions(functions
|
|
63
|
+
addExamples(addFunctionsApiOptions(functions
|
|
56
64
|
.command("invoke [functionId]")
|
|
57
65
|
.description("Invoke a deployed Browserbase Function or check invocation status.")
|
|
58
66
|
.option("--params <params>", "JSON params to pass to the function.")
|
|
59
67
|
.option("--no-wait", "Return immediately after creating the invocation.")
|
|
60
|
-
.option("--check-status <checkStatus>", "Invocation ID to inspect without creating a new invocation."))
|
|
68
|
+
.option("--check-status <checkStatus>", "Invocation ID to inspect without creating a new invocation.")), [
|
|
69
|
+
`bb functions invoke <function-id> --params '{"url":"https://example.com"}'`,
|
|
70
|
+
"bb functions invoke <function-id> --no-wait",
|
|
71
|
+
"bb functions invoke --check-status <invocation-id>",
|
|
72
|
+
]).action(async (functionId, options) => {
|
|
61
73
|
await invokeFunction({
|
|
62
74
|
functionId,
|
|
63
75
|
params: options.params,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { addCommonApiOptions, createBrowserbaseClient, outputJson } from "../lib/command.js";
|
|
1
|
+
import { addCommonApiOptions, addExamples, createBrowserbaseClient, outputJson } from "../lib/command.js";
|
|
2
2
|
export function attachProjectsCommand(program) {
|
|
3
3
|
const projects = program
|
|
4
4
|
.command("projects")
|
|
@@ -7,21 +7,21 @@ export function attachProjectsCommand(program) {
|
|
|
7
7
|
projects.action(() => {
|
|
8
8
|
projects.outputHelp();
|
|
9
9
|
});
|
|
10
|
-
addCommonApiOptions(projects
|
|
10
|
+
addExamples(addCommonApiOptions(projects
|
|
11
11
|
.command("list")
|
|
12
|
-
.description("List projects visible to the current API key.")).action(async (options) => {
|
|
12
|
+
.description("List projects visible to the current API key.")), ["bb projects list"]).action(async (options) => {
|
|
13
13
|
const client = createBrowserbaseClient(options);
|
|
14
14
|
outputJson(await client.projects.list());
|
|
15
15
|
});
|
|
16
|
-
addCommonApiOptions(projects
|
|
16
|
+
addExamples(addCommonApiOptions(projects
|
|
17
17
|
.command("get <id>")
|
|
18
|
-
.description("Get a project by ID.")).action(async (id, options) => {
|
|
18
|
+
.description("Get a project by ID.")), ["bb projects get <project-id>"]).action(async (id, options) => {
|
|
19
19
|
const client = createBrowserbaseClient(options);
|
|
20
20
|
outputJson(await client.projects.retrieve(id));
|
|
21
21
|
});
|
|
22
|
-
addCommonApiOptions(projects
|
|
22
|
+
addExamples(addCommonApiOptions(projects
|
|
23
23
|
.command("usage <id>")
|
|
24
|
-
.description("Get project usage.")).action(async (id, options) => {
|
|
24
|
+
.description("Get project usage.")), ["bb projects usage <project-id>"]).action(async (id, options) => {
|
|
25
25
|
const client = createBrowserbaseClient(options);
|
|
26
26
|
outputJson(await client.projects.usage(id));
|
|
27
27
|
});
|
package/dist/commands/search.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { addCommonApiOptions, outputJson, requestBrowserbaseJson, writeOutputFile, } from "../lib/command.js";
|
|
1
|
+
import { addCommonApiOptions, addExamples, outputJson, requestBrowserbaseJson, writeOutputFile, } from "../lib/command.js";
|
|
2
2
|
export function attachSearchCommand(program) {
|
|
3
|
-
addCommonApiOptions(program
|
|
3
|
+
addExamples(addCommonApiOptions(program
|
|
4
4
|
.command("search <query>")
|
|
5
5
|
.description("Search the web using the Browserbase Search API.")
|
|
6
6
|
.option("--num-results <count>", "Number of results to return (1-25, default 10).")
|
|
7
|
-
.option("--output <output>", "Write the search results as JSON to a file."))
|
|
7
|
+
.option("--output <output>", "Write the search results as JSON to a file.")), [
|
|
8
|
+
`bb search "best restaurants in SF"`,
|
|
9
|
+
`bb search "web scraping tools" --num-results 5`,
|
|
10
|
+
`bb search "browserbase docs" --output results.json`,
|
|
11
|
+
]).action(async (query, options) => {
|
|
8
12
|
const numResults = options.numResults ? parseInt(options.numResults, 10) : undefined;
|
|
9
13
|
const result = await requestBrowserbaseJson(options, "/v1/search", {
|
|
10
14
|
method: "POST",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Option } from "commander";
|
|
2
|
-
import { addCommonApiOptions, createBrowserbaseClient, fail, outputJson,
|
|
2
|
+
import { addCommonApiOptions, addExamples, createBrowserbaseClient, fail, outputJson, resolveBody, resolveUploadableFile, writeBinaryOutput, } from "../lib/command.js";
|
|
3
3
|
export function attachSessionsCommand(program) {
|
|
4
4
|
const sessions = program
|
|
5
5
|
.command("sessions")
|
|
@@ -8,57 +8,69 @@ export function attachSessionsCommand(program) {
|
|
|
8
8
|
sessions.action(() => {
|
|
9
9
|
sessions.outputHelp();
|
|
10
10
|
});
|
|
11
|
-
addCommonApiOptions(sessions
|
|
11
|
+
addExamples(addCommonApiOptions(sessions
|
|
12
12
|
.command("list")
|
|
13
13
|
.description("List sessions.")
|
|
14
|
-
.option("--q <q>", `Session metadata query (e.g. "user_metadata['env']:'staging'").`))
|
|
14
|
+
.option("--q <q>", `Session metadata query (e.g. "user_metadata['env']:'staging'").`)), [
|
|
15
|
+
"bb sessions list",
|
|
16
|
+
`bb sessions list --q "user_metadata['env']:'staging'"`,
|
|
17
|
+
]).action(async (options) => {
|
|
15
18
|
const client = createBrowserbaseClient(options);
|
|
16
19
|
outputJson(await client.sessions.list(options.q ? { q: options.q } : {}));
|
|
17
20
|
});
|
|
18
|
-
addCommonApiOptions(sessions
|
|
21
|
+
addExamples(addCommonApiOptions(sessions
|
|
19
22
|
.command("get <id>")
|
|
20
|
-
.description("Get a session by ID.")).action(async (id, options) => {
|
|
23
|
+
.description("Get a session by ID.")), ["bb sessions get <session-id>"]).action(async (id, options) => {
|
|
21
24
|
const client = createBrowserbaseClient(options);
|
|
22
25
|
outputJson(await client.sessions.retrieve(id));
|
|
23
26
|
});
|
|
24
|
-
addCommonApiOptions(sessions
|
|
27
|
+
addExamples(addCommonApiOptions(sessions
|
|
25
28
|
.command("create")
|
|
26
29
|
.description("Create a session.")
|
|
27
|
-
.option("--body <body>", "Optional JSON request body.")
|
|
30
|
+
.option("--body <body>", "Optional JSON request body.")
|
|
31
|
+
.option("--stdin", "Read JSON request body from stdin.")), [
|
|
32
|
+
"bb sessions create",
|
|
33
|
+
`bb sessions create --body '{"proxies":true}'`,
|
|
34
|
+
`echo '{"proxies":true}' | bb sessions create --stdin`,
|
|
35
|
+
]).action(async (options) => {
|
|
28
36
|
const client = createBrowserbaseClient(options);
|
|
29
|
-
const body =
|
|
37
|
+
const body = await resolveBody(options);
|
|
30
38
|
outputJson(await client.sessions.create(body));
|
|
31
39
|
});
|
|
32
|
-
addCommonApiOptions(sessions
|
|
40
|
+
addExamples(addCommonApiOptions(sessions
|
|
33
41
|
.command("update <id>")
|
|
34
42
|
.description("Update a session.")
|
|
35
43
|
.addOption(new Option("--status <status>", "Session status update.")
|
|
36
44
|
.choices(["REQUEST_RELEASE"])
|
|
37
45
|
.default("REQUEST_RELEASE"))
|
|
38
|
-
.option("--body <body>", "Optional JSON request body. Merged with --status when provided.")
|
|
46
|
+
.option("--body <body>", "Optional JSON request body. Merged with --status when provided.")
|
|
47
|
+
.option("--stdin", "Read JSON request body from stdin.")), [
|
|
48
|
+
"bb sessions update <session-id> --status REQUEST_RELEASE",
|
|
49
|
+
`bb sessions update <session-id> --body '{"status":"REQUEST_RELEASE"}'`,
|
|
50
|
+
]).action(async (id, options) => {
|
|
39
51
|
const client = createBrowserbaseClient(options);
|
|
40
52
|
const sessionId = id || fail("Session ID is required.");
|
|
41
53
|
const body = {
|
|
42
|
-
...
|
|
54
|
+
...(await resolveBody(options)),
|
|
43
55
|
status: options.status ?? "REQUEST_RELEASE",
|
|
44
56
|
};
|
|
45
57
|
outputJson(await client.sessions.update(sessionId, body));
|
|
46
58
|
});
|
|
47
|
-
addCommonApiOptions(sessions
|
|
59
|
+
addExamples(addCommonApiOptions(sessions
|
|
48
60
|
.command("debug <id>")
|
|
49
|
-
.description("Get live debugger URLs for a session.")).action(async (id, options) => {
|
|
61
|
+
.description("Get live debugger URLs for a session.")), ["bb sessions debug <session-id>"]).action(async (id, options) => {
|
|
50
62
|
const client = createBrowserbaseClient(options);
|
|
51
63
|
outputJson(await client.sessions.debug(id));
|
|
52
64
|
});
|
|
53
|
-
addCommonApiOptions(sessions
|
|
65
|
+
addExamples(addCommonApiOptions(sessions
|
|
54
66
|
.command("logs <id>")
|
|
55
|
-
.description("Get session logs.")).action(async (id, options) => {
|
|
67
|
+
.description("Get session logs.")), ["bb sessions logs <session-id>"]).action(async (id, options) => {
|
|
56
68
|
const client = createBrowserbaseClient(options);
|
|
57
69
|
outputJson(await client.sessions.logs.list(id));
|
|
58
70
|
});
|
|
59
|
-
addCommonApiOptions(sessions
|
|
71
|
+
addExamples(addCommonApiOptions(sessions
|
|
60
72
|
.command("recording <id>")
|
|
61
|
-
.description("Get rrweb session recording events.")).action(async (id, options) => {
|
|
73
|
+
.description("Get rrweb session recording events.")), ["bb sessions recording <session-id>"]).action(async (id, options) => {
|
|
62
74
|
const client = createBrowserbaseClient(options);
|
|
63
75
|
outputJson(await client.sessions.recording.retrieve(id));
|
|
64
76
|
});
|
|
@@ -69,10 +81,13 @@ export function attachSessionsCommand(program) {
|
|
|
69
81
|
downloads.action(() => {
|
|
70
82
|
downloads.outputHelp();
|
|
71
83
|
});
|
|
72
|
-
addCommonApiOptions(downloads
|
|
84
|
+
addExamples(addCommonApiOptions(downloads
|
|
73
85
|
.command("get <id>")
|
|
74
86
|
.description("Download session files as a ZIP archive.")
|
|
75
|
-
.option("--output <output>", "Path to write the ZIP file."))
|
|
87
|
+
.option("--output <output>", "Path to write the ZIP file.")), [
|
|
88
|
+
"bb sessions downloads get <session-id>",
|
|
89
|
+
"bb sessions downloads get <session-id> --output ./downloads.zip",
|
|
90
|
+
]).action(async (id, options) => {
|
|
76
91
|
const client = createBrowserbaseClient(options);
|
|
77
92
|
const response = await client.sessions.downloads.list(id);
|
|
78
93
|
const defaultPath = `${id}-downloads.zip`;
|
|
@@ -88,9 +103,9 @@ export function attachSessionsCommand(program) {
|
|
|
88
103
|
uploads.action(() => {
|
|
89
104
|
uploads.outputHelp();
|
|
90
105
|
});
|
|
91
|
-
addCommonApiOptions(uploads
|
|
106
|
+
addExamples(addCommonApiOptions(uploads
|
|
92
107
|
.command("create <id> <file>")
|
|
93
|
-
.description("Upload a file to a session.")).action(async (id, file, options) => {
|
|
108
|
+
.description("Upload a file to a session.")), ["bb sessions uploads create <session-id> ./file.pdf"]).action(async (id, file, options) => {
|
|
94
109
|
const client = createBrowserbaseClient(options);
|
|
95
110
|
outputJson(await client.sessions.uploads.create(id, {
|
|
96
111
|
file: await resolveUploadableFile(file, "session upload"),
|
package/dist/commands/skills.js
CHANGED
|
@@ -25,7 +25,15 @@ export function attachSkillsCommand(program) {
|
|
|
25
25
|
const skills = program
|
|
26
26
|
.command("skills")
|
|
27
27
|
.description("Install Browserbase agent skills for Claude Code.")
|
|
28
|
-
.
|
|
28
|
+
.option("-y, --yes", "Auto-accept installation prompts.")
|
|
29
|
+
.addHelpText("after", [
|
|
30
|
+
"",
|
|
31
|
+
"Examples:",
|
|
32
|
+
" bb skills (interactive install prompt)",
|
|
33
|
+
" bb skills --yes (auto-install without prompting)",
|
|
34
|
+
" bb skills install (non-interactive install)",
|
|
35
|
+
].join("\n"))
|
|
36
|
+
.action(async (options) => {
|
|
29
37
|
console.log([
|
|
30
38
|
"",
|
|
31
39
|
"Browserbase Skills for Claude Code",
|
|
@@ -38,18 +46,23 @@ export function attachSkillsCommand(program) {
|
|
|
38
46
|
" Run: npx skills add browserbase/skills --yes --global",
|
|
39
47
|
"",
|
|
40
48
|
].join("\n"));
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
if (!options.yes) {
|
|
50
|
+
if (!process.stdin.isTTY) {
|
|
51
|
+
fail("Cannot prompt for install in non-interactive mode. Use --yes to auto-install.");
|
|
52
|
+
}
|
|
53
|
+
const rl = readline.createInterface({
|
|
54
|
+
input: process.stdin,
|
|
55
|
+
output: process.stdout,
|
|
56
|
+
});
|
|
57
|
+
try {
|
|
58
|
+
const answer = await rl.question("Install skills? [Y/n] ");
|
|
59
|
+
if (answer.trim().toLowerCase() === "n") {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
rl.close();
|
|
49
65
|
}
|
|
50
|
-
}
|
|
51
|
-
finally {
|
|
52
|
-
rl.close();
|
|
53
66
|
}
|
|
54
67
|
await installSkills();
|
|
55
68
|
});
|
package/dist/lib/command.js
CHANGED
|
@@ -2,6 +2,7 @@ import Browserbase from "@browserbasehq/sdk";
|
|
|
2
2
|
import { createReadStream, constants } from "node:fs";
|
|
3
3
|
import { access, mkdir, writeFile } from "node:fs/promises";
|
|
4
4
|
import { dirname, resolve } from "node:path";
|
|
5
|
+
import { Readable } from "node:stream";
|
|
5
6
|
const defaultBrowserbaseApiUrl = "https://api.browserbase.com";
|
|
6
7
|
export class CommandFailure extends Error {
|
|
7
8
|
exitCode;
|
|
@@ -151,3 +152,27 @@ export async function writeBinaryOutput(pathname, contents) {
|
|
|
151
152
|
await mkdir(dirname(absolutePath), { recursive: true });
|
|
152
153
|
await writeFile(absolutePath, contents);
|
|
153
154
|
}
|
|
155
|
+
export function addExamples(command, examples) {
|
|
156
|
+
const text = "\nExamples:\n" + examples.map((e) => ` ${e}`).join("\n");
|
|
157
|
+
return command.addHelpText("after", text);
|
|
158
|
+
}
|
|
159
|
+
export async function readStdin() {
|
|
160
|
+
if (process.stdin.isTTY) {
|
|
161
|
+
fail("--stdin requires piped input. Example: echo '{\"key\":\"value\"}' | bb <command> --stdin");
|
|
162
|
+
}
|
|
163
|
+
const chunks = [];
|
|
164
|
+
for await (const chunk of Readable.toWeb(process.stdin)) {
|
|
165
|
+
chunks.push(Buffer.from(chunk));
|
|
166
|
+
}
|
|
167
|
+
return Buffer.concat(chunks).toString("utf8").trim();
|
|
168
|
+
}
|
|
169
|
+
export async function resolveBody(options) {
|
|
170
|
+
if (options.body && options.stdin) {
|
|
171
|
+
fail("Cannot use both --body and --stdin. Provide one or the other.");
|
|
172
|
+
}
|
|
173
|
+
if (options.stdin) {
|
|
174
|
+
const input = await readStdin();
|
|
175
|
+
return parseOptionalJsonObjectArg(input, "stdin");
|
|
176
|
+
}
|
|
177
|
+
return parseOptionalJsonObjectArg(options.body, "body");
|
|
178
|
+
}
|