Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions crates/bsk-cli/skill/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,27 @@ Drive the user's **real Chromium browser** (with their logins and cookies) throu
2. browser-skill **extension** loaded in Chromium and connected (popup shows green)
3. Any `bsk` command auto-starts background services as needed; use `bsk doctor` if anything fails

### 0-browser recovery protocol (mandatory)

When you observe `browsers connected: 0` (from `bsk status`) or a `NoBrowserConnected` failure (from `bsk session start` / `bsk doctor`), **do not ask the user to check anything yet**. The default behaviour — every time — is to recover on the agent's own, in this exact order:

1. **Self-detect.** Run `pgrep -lf 'Google Chrome|Chromium|brave-browser|microsoft-edge'` (or the platform equivalent). If any of those processes are running, the browser is up but its extension is not connected — go straight to step 3.
2. **Self-launch (if nothing was running).** You almost certainly have a shell that can spawn GUI apps. Launch the user's default supported browser yourself:
- macOS: `open -a "Google Chrome"` (or `Chromium` / `"Microsoft Edge"` / `"Brave Browser"`)
- Linux: `google-chrome &` (or `chromium` / `microsoft-edge` / `brave-browser &`)
- Windows: `start chrome` (or `start chromium` / `start msedge` / `start brave`)
3. **Wait + verify.** Sleep a few seconds (`bsk wait-ms 3s` or `sleep 3`), then re-run `bsk status` (or `bsk browsers`). If `browsers connected` is still 0, retry once (an extension service worker may need a moment to wake).
4. **Now retry the original task** (`bsk session start`, etc.) — do not pre-emptively message the user.

Only fall back to involving the user if you hit one of these blockers and **only at the matching step**:

- **Step 1 detected a browser, but step 3 still shows 0 after retry** → the extension is likely not installed or the popup is not green. Ask the user to confirm the browser-skill extension is loaded in that browser and the popup is green, then retry step 3.
- **Step 2 cannot launch** (sandboxed shell, no GUI spawn) → detect which browsers are present, report state, ask the user to open a supported browser themselves, then retry from step 3 after they confirm.
- **Step 1 cannot detect processes at all** (no `pgrep` / no OS access) → ask the user to confirm a supported Chromium browser is started with the extension connected, then retry.
- **No supported Chromium browser is installed on this host** → tell the user to install one (Chrome, Chromium, Edge, or Brave) and the browser-skill extension; retry after they confirm.

The `hint:` line that `bsk status` and `bsk doctor` print in this state is the same tree condensed into one line — follow it.

## Mandatory workflow

Every automation task **must** follow this lifecycle. Do **not** rely on idle timeouts (default session idle is 5 minutes).
Expand Down Expand Up @@ -260,6 +281,17 @@ Human errors print `error:` + `hint:` on stderr; `--json` includes `code`, `mess
| Any failure you cannot fix in one retry | `bsk doctor` |
| Multiple browsers / wrong target | `bsk browsers` then `bsk session start --browser <id>` |

### NoBrowserConnected (exit 1)

No browser with the browser-skill extension installed and connected was found.
BrowserSkill never launches a browser — the agent or user must. Get one connected:

| Capability | Action |
|------------|--------|
| Can detect + launch (default) | Launch the browser yourself (relaunch if a stale one is open but not green); confirm connected via `bsk status`; retry. |
| Can detect, no launch | Report detected state; ask user to open the browser and confirm extension installed and connected; retry after confirm. |
| No OS access / human | Ask user to confirm a supported browser is started and the extension is installed and connected; retry. |

Always **`bsk session stop <id>`** in a `finally`-style path so the Agent Window closes and borrowed tabs return.

## Red lines
Expand Down
28 changes: 23 additions & 5 deletions crates/bsk-cli/src/cli/doctor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,27 @@ fn display_protocol(value: &str) -> &str {
if value.is_empty() { "unknown" } else { value }
}

/// Repair hint emitted by [`check_extension_connected`] when zero
/// browsers are online. Mirrors the ACTION/FALLBACK decision tree of
/// `ErrorCode::NoBrowserConnected` in `cli::render_error` (issue #40)
/// so an LLM driving `bsk doctor` is steered to launch a browser
/// itself (the default), fall back to asking the user only when it
/// genuinely cannot spawn GUI apps, and reach for the Web Store URL
/// only as a last-resort "no Chromium installed on this host" path.
/// Kept as a single line because [`render_human`] concatenates it
/// after `— hint: ` without wrapping.
const NO_BROWSER_HINT: &str = "BrowserSkill does not launch browsers itself. \
Launch a supported Chromium browser (Chrome / Chromium / Edge / Brave) so the extension can connect — \
quit and relaunch any stale one whose extension popup is not green. \
macOS: `open -a \"Google Chrome\"` (or Chromium / \"Microsoft Edge\" / \"Brave Browser\"); \
Linux: `google-chrome &` (or chromium / microsoft-edge / brave-browser &); \
Windows: `start chrome` (or start chromium / start msedge / start brave). \
Then `bsk status` / `bsk browsers` and retry. \
FALLBACK — only if you genuinely CANNOT launch applications (sandboxed, no GUI spawn, or no shell/OS access): \
- Can detect processes but cannot launch: detect which browsers are running and report state; ask user to open a supported browser and confirm extension is connected (popup green); retry after they confirm. \
- Cannot detect processes at all: ask user to confirm a supported Chromium browser is started and the extension is connected (popup green); retry. \
If no supported Chromium browser is installed on this host at all, install one and the browser-skill extension from {URL}.";

fn check_extension_connected(status: Option<&StatusResult>) -> CheckResult {
let name = "extension connected";
let Some(status) = status else {
Expand All @@ -417,11 +438,8 @@ fn check_extension_connected(status: Option<&StatusResult>) -> CheckResult {
if browsers > 0 {
CheckResult::ok(name, format!("{} browser(s) connected", browsers))
} else {
CheckResult::fail(
name,
"0 browsers connected",
format!("install the extension from {EXTENSION_STORE_URL} and load it in Chromium"),
)
let hint = NO_BROWSER_HINT.replace("{URL}", EXTENSION_STORE_URL);
CheckResult::fail(name, "0 browsers connected", hint)
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/bsk-cli/src/cli/render_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ pub fn info_for(code: ErrorCode) -> RenderInfo {
ErrorCode::NoBrowserConnected => RenderInfo {
summary: "no browser is connected to the daemon",
hint: Some(
"open the browser-skill extension in your browser and wait for the popup to show \"connected\"",
"a supported Chromium browser (Chrome, Chromium, Edge, or Brave) with the browser-skill extension installed and connected (popup shows green) is required before a session can start. BrowserSkill does not launch browsers itself — so the agent (or user) must connect one.\n\nACTION — do this first. If you run in a normal shell (the usual case for an AI agent, and you can spawn GUI apps), launch the browser yourself:\n1. If a supported browser is already running but its popup is NOT green, quit it and relaunch so the extension makes a fresh connection.\n2. If no supported browser is running, launch one:\n - macOS: open -a \"Google Chrome\" (or Chromium / \"Microsoft Edge\" / \"Brave Browser\")\n - Linux: google-chrome & (or chromium / microsoft-edge / brave-browser &)\n - Windows: start chrome (or start chromium / start msedge / start brave)\n3. Wait a few seconds for the extension to connect; verify with `bsk status` or `bsk browsers`.\n4. Retry `bsk session start`.\n\nFALLBACK — only if you genuinely CANNOT launch applications in your environment (sandboxed shell with no GUI spawn, or no shell/OS access at all):\n- Can detect processes but cannot launch: detect which supported browsers are running and report the state; ask the user to open the missing browser and confirm the browser-skill extension is installed and connected (popup green); retry after they confirm.\n- Cannot detect processes at all: ask the user to confirm a supported Chromium browser is started and the browser-skill extension is installed and connected (popup green); retry.\n\nIf you are a human user: open a supported Chromium browser, ensure the browser-skill extension is installed and its popup shows connected (green), then run `bsk session start` again.",
),
exit_code: 1,
},
Expand Down
36 changes: 36 additions & 0 deletions crates/bsk-cli/src/cli/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,32 @@ use crate::cli::browser_wait::{
use crate::cli::ensure_daemon::ensure_daemon;
use crate::cli::error::CliError;

/// Chrome Web Store listing for the browser-skill extension. Mirrors the
/// same constant in `cli::doctor` — they must stay in sync so a single
/// `bsk status` / `bsk doctor` run steers an LLM to the same place.
const EXTENSION_STORE_URL: &str =
"https://chromewebstore.google.com/detail/hhcmgoofomhgciiibhipgmgkgnoenaoi";

/// Repair hint appended after the `browsers connected` row when zero
/// browsers are online. Mirrors the ACTION/FALLBACK decision tree of
/// `ErrorCode::NoBrowserConnected` in `cli::render_error` and the
/// `extension connected` check in `cli::doctor` (issue #40) so an LLM
/// driving `bsk status` is steered to launch a browser itself, fall
/// back to asking the user only when it genuinely cannot spawn GUI
/// apps, and reach for the Web Store URL only as a last-resort
/// "no Chromium installed on this host" path.
const NO_BROWSER_HINT: &str = "BrowserSkill does not launch browsers itself. \
Launch a supported Chromium browser (Chrome / Chromium / Edge / Brave) so the extension can connect — \
quit and relaunch any stale one whose extension popup is not green. \
macOS: `open -a \"Google Chrome\"` (or Chromium / \"Microsoft Edge\" / \"Brave Browser\"); \
Linux: `google-chrome &` (or chromium / microsoft-edge / brave-browser &); \
Windows: `start chrome` (or start chromium / start msedge / start brave). \
Then `bsk status` / `bsk browsers` and retry. \
FALLBACK — only if you genuinely CANNOT launch applications (sandboxed, no GUI spawn, or no shell/OS access): \
- Can detect processes but cannot launch: detect which browsers are running and report state; ask user to open a supported browser and confirm extension is connected (popup green); retry after they confirm. \
- Cannot detect processes at all: ask user to confirm a supported Chromium browser is started and the extension is connected (popup green); retry. \
If no supported Chromium browser is installed on this host at all, install one and the browser-skill extension from {URL}.";

/// Output format selector.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Output {
Expand Down Expand Up @@ -99,6 +125,16 @@ fn render_human(s: &StatusResult) {
for (key, value) in &rows {
println!("{key:<label_width$} {value}");
}
if s.browsers.is_empty() {
// Mirrors the FAIL hint in `cli::doctor` so the first thing
// an LLM reaches for after a failed session start (`bsk
// status` → 0 browsers) sees the same ACTION / FALLBACK tree.
// Written to stderr so `--json` consumers and stdout-parsing
// agents ignore it.
eprintln!();
let hint = NO_BROWSER_HINT.replace("{URL}", EXTENSION_STORE_URL);
eprintln!("hint: {hint}");
}
}

fn render_json(s: &StatusResult) -> anyhow::Result<()> {
Expand Down
32 changes: 32 additions & 0 deletions skill/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,27 @@ Drive the user's **real Chromium browser** (with their logins and cookies) throu
2. browser-skill **extension** loaded in Chromium and connected (popup shows green)
3. Any `bsk` command auto-starts background services as needed; use `bsk doctor` if anything fails

### 0-browser recovery protocol (mandatory)

When you observe `browsers connected: 0` (from `bsk status`) or a `NoBrowserConnected` failure (from `bsk session start` / `bsk doctor`), **do not ask the user to check anything yet**. The default behaviour — every time — is to recover on the agent's own, in this exact order:

1. **Self-detect.** Run `pgrep -lf 'Google Chrome|Chromium|brave-browser|microsoft-edge'` (or the platform equivalent). If any of those processes are running, the browser is up but its extension is not connected — go straight to step 3.
2. **Self-launch (if nothing was running).** You almost certainly have a shell that can spawn GUI apps. Launch the user's default supported browser yourself:
- macOS: `open -a "Google Chrome"` (or `Chromium` / `"Microsoft Edge"` / `"Brave Browser"`)
- Linux: `google-chrome &` (or `chromium` / `microsoft-edge` / `brave-browser &`)
- Windows: `start chrome` (or `start chromium` / `start msedge` / `start brave`)
3. **Wait + verify.** Sleep a few seconds (`bsk wait-ms 3s` or `sleep 3`), then re-run `bsk status` (or `bsk browsers`). If `browsers connected` is still 0, retry once (an extension service worker may need a moment to wake).
4. **Now retry the original task** (`bsk session start`, etc.) — do not pre-emptively message the user.

Only fall back to involving the user if you hit one of these blockers and **only at the matching step**:

- **Step 1 detected a browser, but step 3 still shows 0 after retry** → the extension is likely not installed or the popup is not green. Ask the user to confirm the browser-skill extension is loaded in that browser and the popup is green, then retry step 3.
- **Step 2 cannot launch** (sandboxed shell, no GUI spawn) → detect which browsers are present, report state, ask the user to open a supported browser themselves, then retry from step 3 after they confirm.
- **Step 1 cannot detect processes at all** (no `pgrep` / no OS access) → ask the user to confirm a supported Chromium browser is started with the extension connected, then retry.
- **No supported Chromium browser is installed on this host** → tell the user to install one (Chrome, Chromium, Edge, or Brave) and the browser-skill extension; retry after they confirm.

The `hint:` line that `bsk status` and `bsk doctor` print in this state is the same tree condensed into one line — follow it.

## Mandatory workflow

Every automation task **must** follow this lifecycle. Do **not** rely on idle timeouts (default session idle is 5 minutes).
Expand Down Expand Up @@ -260,6 +281,17 @@ Human errors print `error:` + `hint:` on stderr; `--json` includes `code`, `mess
| Any failure you cannot fix in one retry | `bsk doctor` |
| Multiple browsers / wrong target | `bsk browsers` then `bsk session start --browser <id>` |

### NoBrowserConnected (exit 1)

No browser with the browser-skill extension installed and connected was found.
BrowserSkill never launches a browser — the agent or user must. Get one connected:

| Capability | Action |
|------------|--------|
| Can detect + launch (default) | Launch the browser yourself (relaunch if a stale one is open but not green); confirm connected via `bsk status`; retry. |
| Can detect, no launch | Report detected state; ask user to open the browser and confirm extension installed and connected; retry after confirm. |
| No OS access / human | Ask user to confirm a supported browser is started and the extension is installed and connected; retry. |

Always **`bsk session stop <id>`** in a `finally`-style path so the Agent Window closes and borrowed tabs return.

## Red lines
Expand Down