Skip to content

Quick Start

Installation

Add xa11y to your Cargo.toml:

[dependencies]
xa11y = "0.1"

Platform Setup

Grant accessibility permissions to your terminal app (or IDE) in System Settings → Privacy & Security → Accessibility.

xa11y can check this for you:

use xa11y::*;
let provider = create_provider()?;
match provider.check_permissions()? {
PermissionStatus::Granted => println!("Ready!"),
PermissionStatus::Denied { instructions } => {
eprintln!("{}", instructions);
}
}

Reading an Accessibility Tree

use xa11y::*;
fn main() -> Result<()> {
let provider = create_provider()?;
// Get the accessibility tree for an app by name
let tree = provider.get_app_tree(
&AppTarget::ByName("Safari".to_string()),
&QueryOptions::default(),
)?;
println!("Root: {:?}", tree.root().role);
println!("Children: {}", tree.children(tree.root()).len());
Ok(())
}

Querying Elements

xa11y supports CSS-like selectors to find elements in the tree.

use xa11y::*;
let provider = create_provider()?;
let tree = provider.get_app_tree(
&AppTarget::ByName("Safari".to_string()),
&QueryOptions::default(),
)?;
// Find all buttons
let buttons = tree.query("button")?;
// Find a button by name
let submit = tree.query("button[name='Submit']")?;
let first = &submit[0];
println!("Found: {}", first.name.as_deref().unwrap_or("unnamed"));
// Find text fields
let fields = tree.query("textfield")?;

Performing Actions

use xa11y::*;
let provider = create_provider()?;
let target = AppTarget::ByName("Safari".to_string());
// Use a Locator for resilient element interaction
let submit = Locator::new(&*provider, target.clone(), "button[name='Submit']");
// Press the button
submit.press()?;
// Type into a text field
let search = Locator::new(&*provider, target, "textfield[name^='Search']");
search.set_value("hello world")?;

Listing Applications

use xa11y::*;
let provider = create_provider()?;
let apps = provider.list_apps()?;
for app in &apps {
println!("{} (pid: {})", app.name, app.pid);
}

Selector Syntax Reference

PatternMeaning
buttonElements with role Button
button[name='OK']Button named exactly “OK”
textfield[name^='Search']Text field whose name starts with “Search”
textfield[name*='email']Text field whose name contains “email”
group > buttonButtons that are direct children of a group
window button[name='OK']Button named “OK” anywhere inside a window
button:nth(2)The 2nd button match

Next Steps