| .github/workflows | ||
| .vscode | ||
| assets | ||
| Examples | ||
| Sources | ||
| Tests/AXorcistTests | ||
| .gitignore | ||
| .swiftformat | ||
| .swiftlint.yml | ||
| axorc_runner.sh | ||
| axorc_stderr.log | ||
| LICENSE | ||
| Makefile | ||
| Package.resolved | ||
| Package.swift | ||
| README.md | ||
| run_axorc_with_json_content.sh | ||
| run_tests.sh | ||
AXorcist: The power of Swift compels your UI to obey!
Swift wrapper for macOS Accessibility—chainable, fuzzy-matched queries
that read, click, and inspect any UI.
AXorcist harnesses the dark arts of macOS Accessibility APIs to give you supernatural control over any application's interface. Whether you're automating workflows, testing applications, or building assistive technologies, AXorcist provides the incantations you need to make UI elements bend to your will.
✨ Supernatural Powers
- 🔍 Element Summoning: Conjure UI elements using flexible locator spells
- 📋 Attribute Divination: Extract mystical properties from accessibility elements
- ⚡ Action Invocation: Cast clicks, text input, and menu manipulation spells
- 🔄 Batch Sorcery: Execute multiple enchantments efficiently in a single ritual
- 📜 Text Extraction: Harvest textual essence from any UI element
- 🗺️ Path Navigation: Navigate the ethereal element hierarchies with precision
- 🐛 Debug Scrying: Comprehensive logging to troubleshoot your incantations
- 📊 JSON Grimoire: Clean JSON input/output for seamless spell integration
📦 Summoning AXorcist
Swift Package Manager
Invoke AXorcist into your project by adding it to your Package.swift grimoire:
dependencies: [
.package(url: "https://github.com/steipete/AXorcist.git", from: "0.1.0")
]
Command Line Familiar
Conjure the axorc command-line familiar:
git clone https://github.com/steipete/AXorcist.git
cd AXorcist
make build
make install
🚀 First Incantations
Casting Swift Spells
import AXorcist
@MainActor
func example() async {
let axorcist = AXorcist()
// Configure logging for the operation (optional)
// AXorcist.GlobalAXLogger.startCollecting(enableDebugLogging: .verbose, forCommandID: "exampleFocusedElement")
// Summon the focused element
let result = await axorcist.handleGetFocusedElement(
for: "Safari",
requestedAttributes: ["AXRole", "AXTitle"]
)
if let element = result.data {
print("Behold! Element with attributes:", element.attributes)
}
// Retrieve and print logs (optional)
// let collectedLogs = await AXorcist.GlobalAXLogger.getLogsAsStrings()
// if !collectedLogs.isEmpty {
// print("\\nArcane Logs:")
// collectedLogs.forEach { print($0) }
// }
// await AXorcist.GlobalAXLogger.stopCollecting() // Clears logs and stops collection for this ID
}
Command Line Rituals
# Divine the focused element in any application
echo '{"command_id": "1", "command": "getFocusedElement"}' | axorc --stdin
# Summon a specific button with precise locator magic
echo '{
"command_id": "2",
"command": "query",
"locator": {
"criteria": {
"AXRole": "AXButton",
"AXTitle": "Submit"
}
}
}' | axorc --stdin
📖 The Spell Book
The AXorcist Entity
Your primary conduit to the accessibility realm, wielding eight powerful enchantments:
⚡ Core Enchantments
handleGetFocusedElement: Divine the currently focused UI elementhandleGetAttributes: Extract mystical properties using locator spellshandleQuery: Summon elements matching your criteriahandleDescribeElement: Reveal comprehensive element secretshandlePerformAction: Command UI elements to perform your biddinghandleExtractText: Harvest textual essence from any elementhandleBatchCommands: Execute multiple spells in a single ritualhandleCollectAll: Recursively gather all matching elements from the UI realm
🧙♂️ Spell Components
All enchantments accept these mystical parameters:
appIdentifierOrNil: Target application realm (bundle ID, name, or "focused")locator: Magical search criteria for element summoningpathHint: Array of breadcrumbs for UI navigationmaxDepth: Maximum depth to traverse the element abyssrequestedAttributes: Specific mystical properties to harvestoutputFormat: Revelation format (.smart,.verbose,.json_string)
For debug logging, AXorcist now uses a global, MainActor-isolated logger (AXorcist.GlobalAXLogger).
Call GlobalAXLogger.startCollecting(...) before an operation and GlobalAXLogger.stopCollecting() / GlobalAXLogger.getLogsAsStrings() afterwards if you need to inspect logs programmatically.
🎯 Locator Spells
Locators are your targeting spells for finding UI elements in the digital realm:
let locator = Locator(
criteria: [
"AXRole": "AXButton",
"AXTitle": "Save Document"
],
requireAction: "AXPress" // Ensure the element can be commanded
)
📜 Prophecy Format
All spells return visions in the form of HandlerResponse:
public struct HandlerResponse {
public var data: AXElement? // The summoned element's essence
public var error: String? // Curse description if spell failed
public var debug_logs: [String]? // Scrying logs and mystical insights
}
🔮 Element Essence Structure
The harvested element data contains:
public struct AXElement {
public var attributes: [String: AnyCodable] // Mystical element properties
public var path: [String] // Journey from app realm to element
}
🖥️ Command Line Grimoire
The axorc familiar accepts JSON incantations through multiple mystical channels:
📥 Invocation Methods
# Channel through the ethereal STDIN
echo '{"command": "ping", "command_id": "1"}' | axorc --stdin
# Read from a spell scroll (file)
axorc --file command.json
# Direct magical utterance
axorc '{"command": "ping", "command_id": "1"}'
🎭 Available Enchantments
ping: Test the spiritual connectiongetFocusedElement: Divine the currently focused elementgetAttributes: Extract element properties using locator magicquery: Summon elements matching your desiresdescribeElement: Reveal comprehensive element mysteriesperformAction: Command elements to do your biddingextractText: Harvest textual essence from the digital realmbatch: Execute multiple rituals in sequencecollectAll: Gather all matching elements from the UI cosmos
📋 Example Incantation
{
"command_id": "summon_back_button",
"command": "query",
"application": "Safari",
"locator": {
"criteria": {
"AXRole": "AXButton",
"AXTitle": "Back"
}
},
"attributes": ["AXRole", "AXTitle", "AXEnabled"]
}
🔐 Mystical Permissions
AXorcist requires sacred accessibility permissions to commune with the UI spirits. macOS will present you with a permission ritual upon first use, or you may grant access manually through:
System Preferences → Security & Privacy → Privacy → Accessibility
Grant AXorcist the power it needs to serve your digital dominion!
🔨 Forging Your Arsenal
# Forge the mystical artifacts
make build
# Test the enchantments (requires local machine - CI spirits cannot grant accessibility permissions)
make test
# Complete ritual: build and test
make all
# Purify the workspace
make clean
🌙 Testing in the Shadows
The test rituals require accessibility permissions to commune with the UI spirits—permissions that cannot be granted automatically on CI. While automated build specters can verify your Swift incantations compile correctly, the full test ceremonies must be performed on a local machine where you can manually grant the sacred accessibility permissions through System Preferences.
The spirits of continuous integration watch over your builds, but only mortal hands can unlock the accessibility gates.
⚔️ Minimum Requirements
- macOS 13.0 or later (The realm of Ventura and beyond)
- Swift 5.9 or later (Modern Swift sorcery)
- Xcode 15.0 or later (For apprentice developers)
🤝 Join the Coven
- Fork this mystical repository
- Create your feature branch (
git checkout -b feature/amazing-spell) - Craft your enhancements
- Add tests for new magical abilities
- Ensure all enchantments pass (
make test) - Submit a pull request to the main grimoire
📜 Sacred License
MIT License - see LICENSE scroll for the complete binding agreement.
🌟 Allied Magical Artifacts
- AccessibilitySnapshot - iOS accessibility testing spells
- Marathon - Cross-platform test execution rituals
- Hammerspoon - Lua-powered macOS automation sorcery
May your UI elements bend to your will, and may your accessibility spells never fail. 🧙♂️✨
