A Go CLI tool that drives a persistent headless Chrome instance using the rod browser automation library. Each command connects to the same long-running Chrome process, making it easy to script multi-step browser interactions from shell scripts or interactive use.
rodney start → launches Chrome (headless, persists after CLI exits)
saves WebSocket debug URL to ~/.rodney/state.json
rodney connect H:P → connects to an existing Chrome on a remote debug port
saves WebSocket debug URL to ~/.rodney/state.json
rodney open URL → connects to running Chrome via WebSocket
navigates the active tab, disconnects
rodney js EXPR → connects, evaluates JS, prints result, disconnects
rodney stop → connects and shuts down Chrome, cleans up state
Each CLI invocation is a short-lived process. Chrome runs independently and tabs persist between commands.
go build -o rodney .
Requires:
ROD_CHROME_BIN=/path/to/chrome)rodney start # Launch headless Chrome
rodney start --show # Launch with visible browser window
rodney start --insecure # Launch with TLS errors ignored (-k shorthand)
rodney connect host:9222 # Connect to existing Chrome on remote debug port
rodney status # Show browser info and active page
rodney stop # Shut down Chrome
rodney open https://example.com # Navigate to URL
rodney open example.com # http:// prefix added automatically
rodney back # Go back
rodney forward # Go forward
rodney reload # Reload page
rodney reload --hard # Reload bypassing cache
rodney clear-cache # Clear the browser cache
rodney url # Print current URL
rodney title # Print page title
rodney text "h1" # Print text content of element
rodney html "div.content" # Print outer HTML of element
rodney html # Print full page HTML
rodney attr "a#link" href # Print attribute value
rodney pdf output.pdf # Save page as PDF
rodney js document.title # Evaluate expression
rodney js "1 + 2" # Math
rodney js 'document.querySelector("h1").textContent' # DOM queries
rodney js '[1,2,3].map(x => x * 2)' # Returns pretty-printed JSON
rodney js 'document.querySelectorAll("a").length' # Count elements
The expression is automatically wrapped in () => { return (expr); }.
rodney click "button#submit" # Click element
rodney input "#search" "query" # Type into input field
rodney clear "#search" # Clear input field
rodney file "#upload" photo.png # Set file on a file input
rodney file "#upload" - # Set file from stdin
rodney download "a.pdf-link" # Download href/src target to file
rodney download "a.pdf-link" - # Download to stdout
rodney select "#dropdown" "value" # Select dropdown by value
rodney submit "form#login" # Submit a form
rodney hover ".menu-item" # Hover over element
rodney focus "#email" # Focus element
rodney wait ".loaded" # Wait for element to appear and be visible
rodney waitload # Wait for page load event
rodney waitstable # Wait for DOM to stop changing
rodney waitidle # Wait for network to be idle
rodney sleep 2.5 # Sleep for N seconds
rodney screenshot # Save as screenshot.png
rodney screenshot page.png # Save to specific file
rodney screenshot -w 1280 -h 720 out.png # Set viewport width/height
rodney screenshot-el ".chart" chart.png # Screenshot specific element
rodney pages # List all tabs (* marks active)
rodney newpage https://... # Open URL in new tab
rodney page 1 # Switch to tab by index
rodney closepage 1 # Close tab by index
rodney closepage # Close active tab
rodney exists ".loading" # Exit 0 if exists, exit 1 if not
rodney count "li.item" # Print number of matching elements
rodney visible "#modal" # Exit 0 if visible, exit 1 if not
rodney assert 'document.title' 'Home' # Exit 0 if equal, exit 1 if not
rodney assert 'document.querySelector("h1") !== null' # Exit 0 if truthy
rodney ax-tree # Dump full accessibility tree
rodney ax-tree --depth 3 # Limit tree depth
rodney ax-tree --json # Output as JSON
rodney ax-find --role button # Find all buttons
rodney ax-find --name "Submit" # Find by accessible name
rodney ax-find --role link --name "Home" # Combine filters
rodney ax-find --role button --json # Output as JSON
rodney ax-node "#submit-btn" # Inspect element's a11y properties
rodney ax-node "h1" --json # Output as JSON
These commands use Chrome's Accessibility CDP domain to expose what assistive technologies see. ax-tree uses getFullAXTree, ax-find uses queryAXTree, and ax-node uses getPartialAXTree.
# CI check: verify all buttons have accessible names
rodney ax-find --role button --json | python3 -c "
import json, sys
buttons = json.load(sys.stdin)
unnamed = [b for b in buttons if not b.get('name', {}).get('value')]
if unnamed:
print(f'FAIL: {len(unnamed)} button(s) missing accessible name')
sys.exit(1)
print(f'PASS: all {len(buttons)} buttons have accessible names')
"
By default, Rodney stores state globally in ~/.rodney/. You can instead create a session scoped to the current directory with --local:
rodney start --local # State stored in ./.rodney/state.json
# Chrome data in ./.rodney/chrome-data/
rodney open https://example.com # Auto-detects local session
rodney stop # Cleans up local session
This is useful when you want isolated browser sessions per project — each directory gets its own Chrome instance, cookies, and state.
Auto-detection: When neither --local nor --global is specified, Rodney checks for ./.rodney/state.json in the current directory. If found, it uses the local session; otherwise it falls back to the global ~/.rodney/ session.
# Force global even when a local session exists
rodney --global open https://example.com
# Force local (errors if no local session)
rodney --local status
The --local and --global flags can appear anywhere in the command:
rodney --local start
rodney start --local # Same effect
rodney open --global https://example.com
Add .rodney/ to your .gitignore to keep session state out of version control.
# Wait for page to load and extract data
rodney start
rodney open https://example.com
rodney waitstable
title=$(rodney title)
echo "Page: $title"
# Conditional logic based on element presence
if rodney exists ".error-message"; then
rodney text ".error-message"
fi
# Loop through pages
for url in page1 page2 page3; do
rodney open "https://example.com/$url"
rodney waitstable
rodney screenshot "${url}.png"
done
rodney stop
Rodney uses distinct exit codes to separate check failures from errors:
| Exit code | Meaning |
|---|---|
0 | Success |
1 | Check failed — the command ran successfully but the condition/assertion was not met |
2 | Error — something went wrong (bad arguments, no browser session, timeout, etc.) |
This makes it easy to distinguish between "the assertion is false" and "the command couldn't run" in scripts and CI pipelines.
Several commands return exit code 1 when a condition is not met, making them useful as assertions in shell scripts and CI pipelines. All of these print their result to stdout and exit cleanly — no error message is written to stderr.
exists — check if an element exists in the DOMrodney exists "h1"
# Prints "true", exits 0
rodney exists ".nonexistent"
# Prints "false", exits 1
visible — check if an element is visiblerodney visible "#modal"
# Prints "true" and exits 0 if the element exists and is visible
rodney visible "#hidden-div"
# Prints "false" and exits 1 if the element is hidden or doesn't exist
ax-find — check for accessibility nodesrodney ax-find --role button --name "Submit"
# Prints the matching node(s), exits 0
rodney ax-find --role banner --name "Nonexistent"
# Prints "No matching nodes" to stderr, exits 1
assert — assert a JavaScript expressionWith one argument, checks that the expression is truthy. With two arguments, checks that the expression's value equals the expected string. Use --message / -m to set a custom failure message.
# Truthy mode — check that expression evaluates to a truthy value
rodney assert 'document.querySelector(".logged-in") !== null'
# Prints "pass", exits 0
rodney assert 'document.querySelector(".nonexistent")'
# Prints "fail: got null", exits 1
# Equality mode — check that expression result matches expected value
rodney assert 'document.title' 'Dashboard'
# Prints "pass" if title is "Dashboard", exits 0
rodney assert 'document.querySelectorAll(".item").length' '3'
# Prints "pass" if there are exactly 3 items, exits 0
rodney assert 'document.title' 'Wrong Title'
# Prints 'fail: got "Dashboard", expected "Wrong Title"', exits 1
The expression is evaluated the same way as rodney js — the result is converted to its string representation before comparison. This means rodney assert 'document.title' 'Dashboard' compares the unquoted string, and rodney assert '1 + 2' '3' compares the number as a string.
Use --message (or -m) to add a human-readable description to the failure output:
rodney assert 'document.querySelector(".logged-in")' -m "User should be logged in"
# On failure: "fail: User should be logged in (got null)"
rodney assert 'document.title' 'Dashboard' --message "Wrong page loaded"
# On failure: 'fail: Wrong page loaded (got "Home", expected "Dashboard")'
You can chain these together in a single script to run multiple assertions. Because check failures use exit code 1 while real errors use exit code 2, you can use set -e to abort on errors while handling check failures explicitly:
#!/bin/bash
set -euo pipefail
FAIL=0
check() {
if ! "$@"; then
echo "FAIL: $*"
FAIL=1
fi
}
rodney start
rodney open "https://example.com"
rodney waitstable
# Assert elements exist
check rodney exists "h1"
check rodney exists "nav"
check rodney exists "footer"
# Assert key elements are visible
check rodney visible "h1"
check rodney visible "#main-content"
# Assert JS expressions
check rodney assert 'document.title' 'Example Domain'
check rodney assert 'document.querySelectorAll("p").length' '2'
check rodney assert 'document.querySelector("h1") !== null'
# Assert accessibility requirements
check rodney ax-find --role navigation
check rodney ax-find --role heading --name "Example Domain"
rodney stop
if [ "$FAIL" -ne 0 ]; then
echo "Some checks failed"
exit 1
fi
echo "All checks passed"
This pattern is useful in CI — run Rodney as a post-deploy check, an accessibility audit, or a smoke test against a staging environment. Because exit code 2 signals an actual error (e.g. Chrome didn't start), set -e will abort the script immediately if something is broken rather than reporting a misleading test failure.
| Environment Variable | Default | Description |
|---|---|---|
RODNEY_HOME | ~/.rodney | Data directory for state and Chrome profile |
ROD_CHROME_BIN | /usr/bin/google-chrome | Path to Chrome/Chromium binary |
ROD_TIMEOUT | 30 | Default timeout in seconds for element queries |
HTTPS_PROXY / HTTP_PROXY | (none) | Authenticated proxy auto-detected on start |
Global state is stored in ~/.rodney/state.json with Chrome user data in ~/.rodney/chrome-data/. When using --local, state is stored in ./.rodney/state.json and ./.rodney/chrome-data/ in the current directory instead. Set RODNEY_HOME to override the default global directory.
In environments with authenticated HTTP proxies (e.g., HTTPS_PROXY=http://user:pass@host:port), rodney start automatically:
Proxy-Authorization headers into CONNECT requestsThis is necessary because Chrome cannot natively authenticate to proxies during HTTPS tunnel (CONNECT) establishment. The local proxy runs as a background process and is automatically cleaned up by rodney stop.
See claude-code-chrome-proxy.md for detailed technical notes.
The tool uses the rod Go library which communicates with Chrome via the DevTools Protocol (CDP) over WebSocket. Key implementation details:
start uses rod's launcher package to start Chrome with Leakless(false) so Chrome survives after the CLI exitsBrowser connection to the same Chrome instance, executes the operation, and disconnectsEvalproto package (getFullAXTree, queryAXTree, getPartialAXTree)| Command | Arguments | Description |
|---|---|---|
start | [--show] [--insecure|-k] | Launch Chrome (headless by default, --show for visible) |
connect | <host:port> | Connect to existing Chrome on remote debug port |
stop | Shut down Chrome | |
status | Show browser status | |
open | <url> | Navigate to URL |
back | Go back in history | |
forward | Go forward in history | |
reload | [--hard] | Reload page (--hard bypasses cache) |
clear-cache | Clear the browser cache | |
url | Print current URL | |
title | Print page title | |
html | [selector] | Print HTML (page or element) |
text | <selector> | Print element text content |
attr | <selector> <name> | Print attribute value |
pdf | [file] | Save page as PDF |
js | <expression> | Evaluate JavaScript |
click | <selector> | Click element |
input | <selector> <text> | Type into input |
clear | <selector> | Clear input |
file | <selector> <path|-> | Set file on a file input (- for stdin) |
download | <selector> [file|-] | Download href/src target (- for stdout) |
select | <selector> <value> | Select dropdown value |
submit | <selector> | Submit form |
hover | <selector> | Hover over element |
focus | <selector> | Focus element |
wait | <selector> | Wait for element to appear |
waitload | Wait for page load | |
waitstable | Wait for DOM stability | |
waitidle | Wait for network idle | |
sleep | <seconds> | Sleep N seconds |
screenshot | [-w N] [-h N] [file] | Page screenshot (optional viewport size) |
screenshot-el | <selector> [file] | Element screenshot |
pages | List tabs | |
page | <index> | Switch tab |
newpage | [url] | Open new tab |
closepage | [index] | Close tab |
exists | <selector> | Check element exists (exit 1 if not) |
count | <selector> | Count matching elements |
visible | <selector> | Check element visible (exit 1 if not) |
assert | <expr> [expected] [-m msg] | Assert JS expression is truthy or equals expected (exit 1 if not) |
ax-tree | [--depth N] [--json] | Dump accessibility tree |
ax-find | [--name N] [--role R] [--json] | Find accessible nodes |
ax-node | <selector> [--json] | Show element accessibility info |
| Flag | Description |
|---|---|
--local | Use directory-scoped session (./.rodney/) |
--global | Use global session (~/.rodney/) |
--version | Print version and exit |
--help, -h, help | Show help message |
Go
88.9%
Shell
5.1%
Python
3.1%
HTML
2.9%
A Go CLI tool that drives a persistent headless Chrome instance using the rod browser automation library. Each command connects to the same long-running Chrome process, making it easy to script multi-step browser interactions from shell scripts or interactive use.
rodney start → launches Chrome (headless, persists after CLI exits)
saves WebSocket debug URL to ~/.rodney/state.json
rodney connect H:P → connects to an existing Chrome on a remote debug port
saves WebSocket debug URL to ~/.rodney/state.json
rodney open URL → connects to running Chrome via WebSocket
navigates the active tab, disconnects
rodney js EXPR → connects, evaluates JS, prints result, disconnects
rodney stop → connects and shuts down Chrome, cleans up state
Each CLI invocation is a short-lived process. Chrome runs independently and tabs persist between commands.
go build -o rodney .
Requires:
ROD_CHROME_BIN=/path/to/chrome)rodney start # Launch headless Chrome
rodney start --show # Launch with visible browser window
rodney start --insecure # Launch with TLS errors ignored (-k shorthand)
rodney connect host:9222 # Connect to existing Chrome on remote debug port
rodney status # Show browser info and active page
rodney stop # Shut down Chrome
rodney open https://example.com # Navigate to URL
rodney open example.com # http:// prefix added automatically
rodney back # Go back
rodney forward # Go forward
rodney reload # Reload page
rodney reload --hard # Reload bypassing cache
rodney clear-cache # Clear the browser cache
rodney url # Print current URL
rodney title # Print page title
rodney text "h1" # Print text content of element
rodney html "div.content" # Print outer HTML of element
rodney html # Print full page HTML
rodney attr "a#link" href # Print attribute value
rodney pdf output.pdf # Save page as PDF
rodney js document.title # Evaluate expression
rodney js "1 + 2" # Math
rodney js 'document.querySelector("h1").textContent' # DOM queries
rodney js '[1,2,3].map(x => x * 2)' # Returns pretty-printed JSON
rodney js 'document.querySelectorAll("a").length' # Count elements
The expression is automatically wrapped in () => { return (expr); }.
rodney click "button#submit" # Click element
rodney input "#search" "query" # Type into input field
rodney clear "#search" # Clear input field
rodney file "#upload" photo.png # Set file on a file input
rodney file "#upload" - # Set file from stdin
rodney download "a.pdf-link" # Download href/src target to file
rodney download "a.pdf-link" - # Download to stdout
rodney select "#dropdown" "value" # Select dropdown by value
rodney submit "form#login" # Submit a form
rodney hover ".menu-item" # Hover over element
rodney focus "#email" # Focus element
rodney wait ".loaded" # Wait for element to appear and be visible
rodney waitload # Wait for page load event
rodney waitstable # Wait for DOM to stop changing
rodney waitidle # Wait for network to be idle
rodney sleep 2.5 # Sleep for N seconds
rodney screenshot # Save as screenshot.png
rodney screenshot page.png # Save to specific file
rodney screenshot -w 1280 -h 720 out.png # Set viewport width/height
rodney screenshot-el ".chart" chart.png # Screenshot specific element
rodney pages # List all tabs (* marks active)
rodney newpage https://... # Open URL in new tab
rodney page 1 # Switch to tab by index
rodney closepage 1 # Close tab by index
rodney closepage # Close active tab
rodney exists ".loading" # Exit 0 if exists, exit 1 if not
rodney count "li.item" # Print number of matching elements
rodney visible "#modal" # Exit 0 if visible, exit 1 if not
rodney assert 'document.title' 'Home' # Exit 0 if equal, exit 1 if not
rodney assert 'document.querySelector("h1") !== null' # Exit 0 if truthy
rodney ax-tree # Dump full accessibility tree
rodney ax-tree --depth 3 # Limit tree depth
rodney ax-tree --json # Output as JSON
rodney ax-find --role button # Find all buttons
rodney ax-find --name "Submit" # Find by accessible name
rodney ax-find --role link --name "Home" # Combine filters
rodney ax-find --role button --json # Output as JSON
rodney ax-node "#submit-btn" # Inspect element's a11y properties
rodney ax-node "h1" --json # Output as JSON
These commands use Chrome's Accessibility CDP domain to expose what assistive technologies see. ax-tree uses getFullAXTree, ax-find uses queryAXTree, and ax-node uses getPartialAXTree.
# CI check: verify all buttons have accessible names
rodney ax-find --role button --json | python3 -c "
import json, sys
buttons = json.load(sys.stdin)
unnamed = [b for b in buttons if not b.get('name', {}).get('value')]
if unnamed:
print(f'FAIL: {len(unnamed)} button(s) missing accessible name')
sys.exit(1)
print(f'PASS: all {len(buttons)} buttons have accessible names')
"
By default, Rodney stores state globally in ~/.rodney/. You can instead create a session scoped to the current directory with --local:
rodney start --local # State stored in ./.rodney/state.json
# Chrome data in ./.rodney/chrome-data/
rodney open https://example.com # Auto-detects local session
rodney stop # Cleans up local session
This is useful when you want isolated browser sessions per project — each directory gets its own Chrome instance, cookies, and state.
Auto-detection: When neither --local nor --global is specified, Rodney checks for ./.rodney/state.json in the current directory. If found, it uses the local session; otherwise it falls back to the global ~/.rodney/ session.
# Force global even when a local session exists
rodney --global open https://example.com
# Force local (errors if no local session)
rodney --local status
The --local and --global flags can appear anywhere in the command:
rodney --local start
rodney start --local # Same effect
rodney open --global https://example.com
Add .rodney/ to your .gitignore to keep session state out of version control.
# Wait for page to load and extract data
rodney start
rodney open https://example.com
rodney waitstable
title=$(rodney title)
echo "Page: $title"
# Conditional logic based on element presence
if rodney exists ".error-message"; then
rodney text ".error-message"
fi
# Loop through pages
for url in page1 page2 page3; do
rodney open "https://example.com/$url"
rodney waitstable
rodney screenshot "${url}.png"
done
rodney stop
Rodney uses distinct exit codes to separate check failures from errors:
| Exit code | Meaning |
|---|---|
0 | Success |
1 | Check failed — the command ran successfully but the condition/assertion was not met |
2 | Error — something went wrong (bad arguments, no browser session, timeout, etc.) |
This makes it easy to distinguish between "the assertion is false" and "the command couldn't run" in scripts and CI pipelines.
Several commands return exit code 1 when a condition is not met, making them useful as assertions in shell scripts and CI pipelines. All of these print their result to stdout and exit cleanly — no error message is written to stderr.
exists — check if an element exists in the DOMrodney exists "h1"
# Prints "true", exits 0
rodney exists ".nonexistent"
# Prints "false", exits 1
visible — check if an element is visiblerodney visible "#modal"
# Prints "true" and exits 0 if the element exists and is visible
rodney visible "#hidden-div"
# Prints "false" and exits 1 if the element is hidden or doesn't exist
ax-find — check for accessibility nodesrodney ax-find --role button --name "Submit"
# Prints the matching node(s), exits 0
rodney ax-find --role banner --name "Nonexistent"
# Prints "No matching nodes" to stderr, exits 1
assert — assert a JavaScript expressionWith one argument, checks that the expression is truthy. With two arguments, checks that the expression's value equals the expected string. Use --message / -m to set a custom failure message.
# Truthy mode — check that expression evaluates to a truthy value
rodney assert 'document.querySelector(".logged-in") !== null'
# Prints "pass", exits 0
rodney assert 'document.querySelector(".nonexistent")'
# Prints "fail: got null", exits 1
# Equality mode — check that expression result matches expected value
rodney assert 'document.title' 'Dashboard'
# Prints "pass" if title is "Dashboard", exits 0
rodney assert 'document.querySelectorAll(".item").length' '3'
# Prints "pass" if there are exactly 3 items, exits 0
rodney assert 'document.title' 'Wrong Title'
# Prints 'fail: got "Dashboard", expected "Wrong Title"', exits 1
The expression is evaluated the same way as rodney js — the result is converted to its string representation before comparison. This means rodney assert 'document.title' 'Dashboard' compares the unquoted string, and rodney assert '1 + 2' '3' compares the number as a string.
Use --message (or -m) to add a human-readable description to the failure output:
rodney assert 'document.querySelector(".logged-in")' -m "User should be logged in"
# On failure: "fail: User should be logged in (got null)"
rodney assert 'document.title' 'Dashboard' --message "Wrong page loaded"
# On failure: 'fail: Wrong page loaded (got "Home", expected "Dashboard")'
You can chain these together in a single script to run multiple assertions. Because check failures use exit code 1 while real errors use exit code 2, you can use set -e to abort on errors while handling check failures explicitly:
#!/bin/bash
set -euo pipefail
FAIL=0
check() {
if ! "$@"; then
echo "FAIL: $*"
FAIL=1
fi
}
rodney start
rodney open "https://example.com"
rodney waitstable
# Assert elements exist
check rodney exists "h1"
check rodney exists "nav"
check rodney exists "footer"
# Assert key elements are visible
check rodney visible "h1"
check rodney visible "#main-content"
# Assert JS expressions
check rodney assert 'document.title' 'Example Domain'
check rodney assert 'document.querySelectorAll("p").length' '2'
check rodney assert 'document.querySelector("h1") !== null'
# Assert accessibility requirements
check rodney ax-find --role navigation
check rodney ax-find --role heading --name "Example Domain"
rodney stop
if [ "$FAIL" -ne 0 ]; then
echo "Some checks failed"
exit 1
fi
echo "All checks passed"
This pattern is useful in CI — run Rodney as a post-deploy check, an accessibility audit, or a smoke test against a staging environment. Because exit code 2 signals an actual error (e.g. Chrome didn't start), set -e will abort the script immediately if something is broken rather than reporting a misleading test failure.
| Environment Variable | Default | Description |
|---|---|---|
RODNEY_HOME | ~/.rodney | Data directory for state and Chrome profile |
ROD_CHROME_BIN | /usr/bin/google-chrome | Path to Chrome/Chromium binary |
ROD_TIMEOUT | 30 | Default timeout in seconds for element queries |
HTTPS_PROXY / HTTP_PROXY | (none) | Authenticated proxy auto-detected on start |
Global state is stored in ~/.rodney/state.json with Chrome user data in ~/.rodney/chrome-data/. When using --local, state is stored in ./.rodney/state.json and ./.rodney/chrome-data/ in the current directory instead. Set RODNEY_HOME to override the default global directory.
In environments with authenticated HTTP proxies (e.g., HTTPS_PROXY=http://user:pass@host:port), rodney start automatically:
Proxy-Authorization headers into CONNECT requestsThis is necessary because Chrome cannot natively authenticate to proxies during HTTPS tunnel (CONNECT) establishment. The local proxy runs as a background process and is automatically cleaned up by rodney stop.
See claude-code-chrome-proxy.md for detailed technical notes.
The tool uses the rod Go library which communicates with Chrome via the DevTools Protocol (CDP) over WebSocket. Key implementation details:
start uses rod's launcher package to start Chrome with Leakless(false) so Chrome survives after the CLI exitsBrowser connection to the same Chrome instance, executes the operation, and disconnectsEvalproto package (getFullAXTree, queryAXTree, getPartialAXTree)| Command | Arguments | Description |
|---|---|---|
start | [--show] [--insecure|-k] | Launch Chrome (headless by default, --show for visible) |
connect | <host:port> | Connect to existing Chrome on remote debug port |
stop | Shut down Chrome | |
status | Show browser status | |
open | <url> | Navigate to URL |
back | Go back in history | |
forward | Go forward in history | |
reload | [--hard] | Reload page (--hard bypasses cache) |
clear-cache | Clear the browser cache | |
url | Print current URL | |
title | Print page title | |
html | [selector] | Print HTML (page or element) |
text | <selector> | Print element text content |
attr | <selector> <name> | Print attribute value |
pdf | [file] | Save page as PDF |
js | <expression> | Evaluate JavaScript |
click | <selector> | Click element |
input | <selector> <text> | Type into input |
clear | <selector> | Clear input |
file | <selector> <path|-> | Set file on a file input (- for stdin) |
download | <selector> [file|-] | Download href/src target (- for stdout) |
select | <selector> <value> | Select dropdown value |
submit | <selector> | Submit form |
hover | <selector> | Hover over element |
focus | <selector> | Focus element |
wait | <selector> | Wait for element to appear |
waitload | Wait for page load | |
waitstable | Wait for DOM stability | |
waitidle | Wait for network idle | |
sleep | <seconds> | Sleep N seconds |
screenshot | [-w N] [-h N] [file] | Page screenshot (optional viewport size) |
screenshot-el | <selector> [file] | Element screenshot |
pages | List tabs | |
page | <index> | Switch tab |
newpage | [url] | Open new tab |
closepage | [index] | Close tab |
exists | <selector> | Check element exists (exit 1 if not) |
count | <selector> | Count matching elements |
visible | <selector> | Check element visible (exit 1 if not) |
assert | <expr> [expected] [-m msg] | Assert JS expression is truthy or equals expected (exit 1 if not) |
ax-tree | [--depth N] [--json] | Dump accessibility tree |
ax-find | [--name N] [--role R] [--json] | Find accessible nodes |
ax-node | <selector> [--json] | Show element accessibility info |
| Flag | Description |
|---|---|
--local | Use directory-scoped session (./.rodney/) |
--global | Use global session (~/.rodney/) |
--version | Print version and exit |
--help, -h, help | Show help message |
Go
88.9%
Shell
5.1%
Python
3.1%
HTML
2.9%