`bsk session start --no-focus` opens the Agent Window in the background
without stealing focus. The flag threads focused=false through
CLI -> daemon IPC -> tool.session_start -> chrome.windows.create; an
omitted `focused` keeps the extension default (true) so older clients
are unaffected.
Reworked onto current main so it composes with #52 window sizing:
AgentWindowApi.create / SessionManager.start (extension), start_session
(CLI) and the daemon's session start now take options objects/structs
({ size, focused }) instead of colliding positional params.
Co-authored-by: alectimison-maker <alec.timison@gmail.com>
The daemon's periodic update check now installs a newer release instead
of only refreshing the hint cache: it reuses the update.rs install path
(download, sha256 verify, extract, replace), skips the round while any
agent session is live, and otherwise restarts itself into the new binary
(spawns a detached replacement that waits for the old pid, then exits).
On by default; BSK_AUTO_UPDATE=off keeps the old cache/hint-only
behaviour. Windows can only stage the replacement, so it just logs that
a restart is needed. The CLI hint wording reflects the switch.
* fix(update): run periodic update check in daemon so hints actually fire
The CLI spawned a detached thread to refresh ~/.bsk/update-check.json,
but the process exits as soon as the command finishes, killing the
thread before the fetch could complete — so the cache was never
written and the new-version hint never showed.
Move the periodic check into the daemon: a tokio task ticks every
30 minutes (down from 24h), refreshes the cache when missing/stale,
and logs failures at warn/info into the daemon log. The CLI path is
now read-only: it prints the hint only from a fresh cache and never
spawns threads or touches the network.
* fix(update): decouple daemon refresh window so checks truly run every 30min
The refresh decision reused the 30min tick interval as its freshness
window, and with is_fresh()'s inclusive bound a cache written just
after tick N still counted as fresh at tick N+1 — so in steady state
the daemon only refetched every other tick (~60min).
Judge staleness against DAEMON_REFRESH_WINDOW (25min = 5/6 of the
tick) instead: every 30min tick now finds the cache stale and really
refreshes, while a daemon restarted with a younger-than-25min cache
still skips its first tick. CLI hint freshness semantics
(UPDATE_CHECK_INTERVAL = 30min) are unchanged.
* feat(emulate): add mobile device emulation via CDP Emulation domain
Add `bsk emulate` so agents can debug mobile page behaviour by
emulating a device environment on a session tab:
- Viewport metrics (Emulation.setDeviceMetricsOverride), User-Agent
(Emulation.setUserAgentOverride, optional accept-language and UA
client-hints metadata), and touch (Emulation.setTouchEmulationEnabled
with maxTouchPoints).
- Seven CLI-side device presets (iphone-14, iphone-14-pro-max,
iphone-se, pixel-7, galaxy-s23, ipad-mini, galaxy-tab-s8) via
--device; manual flags (--width/--height/--dpr/--mobile/--ua/
--accept-language/--touch/--max-touch-points) work standalone or
override individual preset fields.
- `bsk emulate --off` clears every override (clearDeviceMetricsOverride
+ touch disabled + empty UA override) and restores the real
environment.
- Overrides are per-tab (CDP per-target) and not inherited by new tabs;
the result JSON carries a note reminding agents to re-apply.
Wire: new tool.emulate method end-to-end (bsk-protocol types + JSON
schemas + Method::ToolEmulate classified BrowserMutation, daemon
forwarding, CLI subcommand, extension tool handler + ChromiumCdp
Emulation wrappers, dispatcher registration), docs in both SKILL.md
copies, and unit tests on every layer.
* refine(emulate): merge per-tab state and align preset override semantics
- extension: remember the applied emulation state per tab and merge each new request onto it field by field before applying, so a later --width/--height no longer resets an earlier preset's dpr/mobile; --off clears the stored state along with the CDP overrides
- extension: cdp_failed errors now note that already-applied overrides were not rolled back and can be reset with --off
- cli: validate width/height pairing and metric requirements on the merged preset+flags result, so --device iphone-14 --width 500 keeps the preset height
- cli: add --no-mobile/--no-touch (conflicting with --mobile/--touch) to turn preset mobile/touch fields back off
- docs: describe the merge behaviour, --no-mobile/--no-touch and --off state clearing in both SKILL.md copies
- `bsk session start --width <px> --height <px>` opens the Agent Window
with the given outer size (chrome.windows.create)
- new `bsk window resize --session <id> --width <px> --height <px>`
resizes the Agent Window at runtime (chrome.windows.update)
- both validated on CLI, daemon and extension sides (100..=7680 CSS px)
- protocol: new tool.window_resize method (BrowserMutation) and
optional width/height on tool.session_start params; schemas regenerated
`bsk install-skill --all` installed the bundled skill into every supported harness directory (detected or not), creating junk paths like ~/.claude/skills on machines without those harnesses. --all now targets detected harnesses only and errors with guidance when none are found; --harness remains the explicit override. The --yes non-interactive branch shares the same detected-only logic.
* feat(request-help): add BSK_REQUEST_HELP=off to disable blocking help requests
* style(extension): format HelpOutcome union per biome
* docs(skill): condense BSK_REQUEST_HELP section
Add a popup launcher + action-recording panel that builds a copyable
`bsk record start` prompt, add `--browser` targeting, and default `--url`
to https://example.com/ when omitted. Drop the popup browser-alias field.
After a long idle the service worker is only revived on its next
keepalive-alarm tick (up to 30s away), so the previous 5s wait made
the first command after idle fail with `no_browser_connected` even
though the extension was about to reconnect.
- Raise the daemon's `EXTENSION_CONNECT_WAIT` (used by `session.start`)
to 35s so it comfortably covers one alarm period plus handshake slack.
- Bump the CLI `session start` IPC timeout to that window plus slack so
it never gives up before the daemon answers, and print a one-line
"waiting for browser extension to connect…" hint when it actually
waits.
- Keep `bsk status` / `browsers` on their own short 5s wait so quick
informational commands are not slowed down.
Co-authored-by: Cursor <cursoragent@cursor.com>
Capture user actions in the Agent Window and export a record-only
trace (pages[] + navigate/click/fill/select/press steps with target
descriptors). Adds the record overlay UI aligned with the control
overlay, and wires record start/stop/await through CLI, daemon,
protocol, and extension.
Add `bsk network` as a sibling of the `console` command from #7,
reading the buffered network responses / failures for a tab. Fills the
remaining half of the request in #2 (console landed in #7; network did
not).
Mirrors the console command's conventions exactly:
bsk network --session <id> [--tab-id N] [--since C]
[--limit N] [--max-text-chars N]
The extension enables `Network` on attach (best-effort) and buffers
`responseReceived` / `loadingFailed` events per tab with a monotonic
sequence, correlating them to `requestWillBeSent` for method/URL. Reads
are cursor-paginated (`since` -> `next_since`) and bounded (`limit`,
`max_text_chars`) for agent-context safety, same as console. Entries
carry the real HTTP status code (response) or the CDP failure reason
(failure) — things `performance.getEntriesByType('resource')` can't
give.
Classified read-only (pass-through under the pending-interrupt gate);
defaults to the Agent Window's active tab.
Wires bsk-protocol (Method + params/result/entry structs + schema),
bsk-cli (network subcommand + daemon dispatch allow-list) and the
extension (handler + dispatcher route), with unit / parse / IPC tests
paralleling the console command.
Refs #2.