| name | ko-browser |
| description | Browser automation CLI for AI agents, written in Go. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to "open a website", "fill out a form", "click a button", "take a screenshot", "scrape data from a page", "test this web app", "login to a site", "automate browser actions", or any task requiring programmatic web interaction. |
| allowed-tools | Bash(kbr:*) |
Browser Automation with ko-browser
The CLI uses Chrome/Chromium via CDP directly. Install it with Homebrew on macOS, download a release binary on Windows or Linux, or use go install if you want to build from source. Run kbr install to verify Chrome is available, or kbr install --with-deps to auto-install it. Existing Chrome, Brave, and Chromium installations are detected automatically.
Installation
brew tap libi/tap
brew install ko-browser
go install github.com/libi/ko-browser/cmd/kbr@latest
CGO_ENABLED=1 go install -tags=ocr github.com/libi/ko-browser/cmd/kbr@latest
kbr install
kbr install --with-deps
Platform-specific release installs:
# Windows: download the latest release package, unzip, and run kbr.exe
Invoke-WebRequest -Uri https://github.com/libi/ko-browser/releases/latest/download/ko-browser-windows-amd64.zip -OutFile ko-browser-windows-amd64.zip
Expand-Archive .\ko-browser-windows-amd64.zip -DestinationPath .\ko-browser
.\ko-browser\kbr.exe --help
curl -LO https://github.com/libi/ko-browser/releases/latest/download/ko-browser-linux-amd64.tar.gz
tar xzf ko-browser-linux-amd64.tar.gz
chmod +x kbr
sudo mv kbr /usr/local/bin/kbr
OCR is optional for go install. The plain go install command has no CGO dependency.
Release binaries and Homebrew installs include OCR support. To use OCR, make sure Tesseract is installed first: brew install tesseract on macOS, apt install libtesseract-dev on Linux.
Manual browser installation by OS:
brew install --cask google-chrome
sudo apt-get install -y chromium-browser
apk add chromium
choco install googlechrome
Or download from: https://www.google.com/chrome/
Core Workflow
Every browser automation follows this pattern:
- Navigate:
kbr open <url>
- Snapshot:
kbr snapshot -i (get element IDs like 1, 2, 3)
- Interact: Use numeric IDs to click, fill, select
- Re-snapshot: After navigation or DOM changes, get fresh IDs
kbr open https://example.com/form
kbr snapshot -i
kbr fill 1 "user@example.com"
kbr fill 2 "password123"
kbr click 3
kbr wait load
kbr snapshot -i
Command Chaining
Commands can be chained with && in a single shell invocation. The browser persists between commands via a background daemon, so chaining is safe and more efficient than separate calls.
kbr open https://example.com && kbr wait load && kbr snapshot -i
kbr fill 1 "user@example.com" && kbr fill 2 "password123" && kbr click 3
kbr open https://example.com && kbr wait load && kbr screenshot page.png
When to chain: Use && when you don't need to read the output of an intermediate command before proceeding (e.g., open + wait + screenshot). Run commands separately when you need to parse the output first (e.g., snapshot to discover IDs, then interact using those IDs).
Handling Authentication
When automating a site that requires login, choose the approach that fits:
Option 1: Persistent profile (simplest for recurring tasks)
kbr --profile ~/.myapp open https://app.example.com/login
kbr --profile ~/.myapp open https://app.example.com/dashboard
Option 2: State file (manual save/load)
kbr state export ./auth.json
kbr state import ./auth.json
kbr open https://app.example.com/dashboard
Option 3: Auth vault (credentials stored, login by name)
kbr auth save mysite --url https://app.example.com/login --username user --password pass
kbr auth login mysite
auth login navigates to the URL and waits for login form selectors to appear before filling/clicking.
Option 4: Session name (isolate parallel tasks)
kbr --session myapp open https://app.example.com/login
kbr close
kbr --session agent1 open https://site-a.com
kbr --session agent2 open https://site-b.com
Essential Commands
kbr open <url>
kbr stop
kbr restart
kbr status
kbr back
kbr forward
kbr reload
kbr snapshot -i
kbr snapshot -c
kbr snapshot --selector "#content"
kbr snapshot --depth 3
kbr snapshot --ocr
kbr snapshot --cursor
kbr click 1
kbr click --new-tab 1
kbr dblclick 1
kbr fill 2 "text"
kbr type 2 "text"
kbr select 1 "option"
kbr check 1
kbr uncheck 1
kbr press Enter
kbr keyboard type "text"
kbr keyboard inserttext "text"
kbr scroll down 500
kbr scrollintoview 5
kbr hover 1
kbr focus 1
kbr drag 1 5
kbr mouse move 100 200
kbr mouse click 100 200
kbr mouse click --button right 100 200
kbr mouse down 100 200
kbr mouse up 100 200
kbr mouse wheel 100 200 300
kbr get text 1
kbr get html 1
kbr get value 1
kbr get attr 1 href
kbr get url
kbr get title
kbr get count "li.item"
kbr get box 1
kbr get styles 1
kbr get cdp-url
kbr is visible 1
kbr is enabled 1
kbr is checked 1
kbr wait time 2s
kbr wait load
kbr wait selector "#modal"
kbr wait hidden ".spinner"
kbr wait url "*login*"
kbr wait text "Welcome"
kbr wait func "window.ready"
kbr wait download ./downloads
kbr upload 3 ./file.pdf
kbr download 5 ./output
kbr network start-logging
kbr network requests
kbr network route "*.ads.*" --action block
kbr network route "*.js" --action continue
kbr network unroute "*.ads.*"
kbr network clear
kbr set viewport 1920 1080
kbr set viewport 1920 1080 2
kbr set device "iPhone 12"
kbr set geo 37.7749 -122.4194
kbr set offline true
kbr set headers X-Token=abc
kbr set credentials admin pass
kbr set media prefers-color-scheme=dark
kbr set colorscheme dark
kbr screenshot page.png
kbr screenshot -f full.png
kbr screenshot -a annotated.png
kbr screenshot --element 5 el.png
kbr screenshot -q 80 page.jpeg
kbr pdf output.pdf
kbr pdf -l landscape.pdf
kbr clipboard read
kbr clipboard write "Hello"
kbr clipboard copy
kbr clipboard paste
kbr console start
kbr console messages
kbr console messages --level error
kbr console clear
kbr errors list
kbr errors clear
kbr eval "document.title"
kbr eval "document.querySelectorAll('a').length"
kbr diff snapshot
kbr diff snapshot -b before.txt
kbr diff screenshot -b before.png
kbr diff url <url1> <url2>
kbr tab list
kbr tab new https://other.com
kbr tab switch 1
kbr tab close 1
kbr session
kbr session list
kbr status
kbr stop
kbr restart
kbr cookies get
kbr cookies set token abc --domain example.com --secure --http-only
kbr cookies delete token
kbr cookies clear
kbr storage list
kbr storage get theme
kbr storage set theme dark
kbr storage delete theme
kbr storage clear
kbr storage get key --type session
kbr state export auth.json
kbr state import auth.json
kbr auth save mysite --url <url> --username <user> --password <pass>
kbr auth login mysite
kbr auth list
kbr auth show mysite
kbr auth delete mysite
kbr highlight 1
kbr inspect
kbr trace start
kbr trace stop trace.json
kbr profiler start
kbr profiler stop profile.json
kbr record start
kbr record stop
kbr confirm
kbr deny
kbr find role button --name "Submit"
kbr find text "Sign In"
kbr find label "Email"
kbr find placeholder "Search"
kbr find alt "logo"
kbr find title "info"
kbr find testid "submit-btn"
kbr find first "div.item"
kbr find last "div.item"
kbr find nth 2 "div.item"
ID Lifecycle (Important)
IDs (1, 2, 3, ...) are invalidated when the page changes. Always re-snapshot after:
- Clicking links or buttons that navigate
- Form submissions
- Dynamic content loading (dropdowns, modals)
kbr click 5
kbr snapshot -i
kbr click 1
IDs are strictly sequential integers starting from 1, assigned via depth-first traversal of the accessibility tree. They are temporary — never cache IDs across snapshots.
Snapshot Format
The snapshot is a text representation of the browser's Accessibility Tree. Each line represents one element:
<indent><id>: <role> "<name>" [value="<value>"] [<state1> <state2> ...]
Example:
Page: "Login - GitHub"
1: link "GitHub"
2: heading "Sign in to GitHub"
3: textbox "Username or email" required
4: textbox "Password" required
5: link "Forgot password?"
6: button "Sign in"
7: link "Create an account"
Format details:
Page: "title" — root node, not interactive, no ID assigned
- 2-space indentation indicates tree depth
- Names are truncated at 80 characters with
...
- Values shown only when different from name (e.g.,
value="admin")
- Common states:
focused, disabled, checked, expanded, collapsed, selected, required, readonly, multiline
Why numeric IDs: Token-efficient for LLMs. 5: button "Submit" uses fewer tokens than @e5 button "Submit" or [5] button "Submit". LLMs reference elements with just a number: kbr click 5.
Common Patterns
Form Submission
kbr open https://example.com/signup
kbr snapshot -i
kbr fill 1 "Jane Doe"
kbr fill 2 "jane@example.com"
kbr select 3 "California"
kbr check 4
kbr click 5
kbr wait load
Authentication with Auth Vault
kbr auth save github --url https://github.com/login --username user --password pass
kbr auth login github
kbr auth list
kbr auth show github
kbr auth delete github
Authentication with State Persistence
kbr open https://app.example.com/login
kbr snapshot -i
kbr fill 1 "$USERNAME"
kbr fill 2 "$PASSWORD"
kbr click 3
kbr wait url "*dashboard*"
kbr state export auth.json
kbr state import auth.json
kbr open https://app.example.com/dashboard
Data Extraction
kbr open https://example.com/products
kbr snapshot -i
kbr get text 5
kbr get title
kbr get url
kbr snapshot -i --json
kbr get text 1 --json
Parallel Sessions
kbr --session site1 open https://site-a.com
kbr --session site2 open https://site-b.com
kbr --session site1 snapshot -i
kbr --session site2 snapshot -i
kbr session list
Viewport & Responsive Testing
kbr set viewport 1920 1080
kbr screenshot desktop.png
kbr set viewport 375 812
kbr screenshot mobile.png
kbr set viewport 1920 1080 2
kbr screenshot retina.png
kbr set device "iPhone 12"
kbr screenshot device.png
Visual Browser (Debugging)
kbr --headed open https://example.com
kbr highlight 1
kbr inspect
kbr record start
kbr profiler start
kbr profiler stop trace.json
Local Files
kbr --allow-file-access open file:///path/to/page.html
kbr snapshot -i
kbr screenshot output.png
Color Scheme (Dark Mode)
kbr set colorscheme dark
kbr screenshot dark.png
kbr set media prefers-color-scheme=dark
Annotated Screenshots (Vision Mode)
Use --annotate (-a) to take a screenshot with numbered labels overlaid on interactive elements. This helps when:
- The page has unlabeled icon buttons or visual-only elements
- You need to verify visual layout or styling
- Canvas or chart elements are present (invisible to text snapshots)
kbr screenshot -a annotated.png
Diffing (Verifying Changes)
Use diff snapshot after performing an action to verify it had the intended effect:
kbr snapshot -i
kbr click 2
kbr diff snapshot
For visual regression or monitoring:
kbr screenshot baseline.png
kbr diff screenshot -b baseline.png
kbr diff url https://staging.example.com https://prod.example.com
diff snapshot output uses + for additions and - for removals, similar to git diff. diff screenshot produces a diff image with changed pixels highlighted.
Timeouts and Slow Pages
The default timeout is 30 seconds (configurable with --timeout). For slow pages, use explicit waits:
kbr wait load
kbr wait selector "#content"
kbr wait url "*dashboard*"
kbr wait func "document.readyState === 'complete'"
kbr wait time 5s
When dealing with slow sites, use kbr wait load after kbr open to ensure the page is fully loaded before taking a snapshot.
Session Management and Cleanup
When running multiple agents concurrently, use named sessions to avoid conflicts:
kbr --session agent1 open site-a.com
kbr --session agent2 open site-b.com
kbr session list
kbr status
kbr status --json
Always close your session when done to avoid leaked daemon processes:
kbr stop
kbr --session agent1 stop
Daemon architecture notes:
- The daemon runs as a fully detached background process (new session, stdio redirected to /dev/null). It survives after the parent CLI or agent process exits.
kbr stop has the highest priority — it responds immediately even if the daemon is busy with a long-running operation (e.g., waiting for a slow page to load).
kbr status works independently of the daemon. It reads the daemon's pidfile and checks process liveness, so it returns useful info even when the daemon is unresponsive or crashed.
Security
Content Boundaries
Enable --content-boundaries to wrap page-sourced output in markers that help LLMs distinguish tool output from untrusted page content:
kbr --content-boundaries snapshot
Configuration File
Create ko-browser.json in the project root for persistent settings:
{
"headed": true,
"proxy": "http://localhost:8080",
"profile": "./browser-data"
}
Priority (lowest to highest): config file < env vars < CLI flags. Use --config <path> for a custom config location.