pbm is a deterministic macOS desktop automation CLI and MCP stdio server.
The macOS implementation is native Swift and returns the stable JSON contract:
{ "schemaVersion": "pbm.stable.v1", "ok": true, "data": {} }Failures use the same envelope with structured error codes. Commands do not call AI models, agents, model providers, natural-language planners, shell execution tools, or remote public listeners.
swift build
swift test
.build/debug/pbm --version
.build/debug/pbm doctorInstall the development binary wherever you want the public command name:
install -m 0755 .build/debug/pbm /usr/local/bin/pbmbrew tap mkusaka/tap
brew install mkusaka/tap/pbm
pbm --version
pbm doctorpbm doctor
pbm --version
pbm config init
pbm see
pbm see --bundle-id com.google.Chrome
pbm see --bundle-id com.google.Chrome --window-title Inbox --max-children 50 --timeout 5
pbm see --app-id com.google.Chrome
pbm see --scope allApps --max-elements 2000
pbm image --mode screen --path /tmp/pbm-screen.png
pbm click --target B1
pbm click --target-text "Send"
pbm window list
pbm app list
pbm clipboard get
pbm clipboard get --type public.png --output /tmp/clipboard.png
pbm snapshot list
pbm mcp- macOS install, permissions, and validation
- Homebrew install and release
- Command reference
- MCP setup and tools
- Agent skill install
- Native capability limits
Every CLI command writes one JSON envelope to stdout.
Success:
{
"schemaVersion": "pbm.stable.v1",
"ok": true,
"data": {}
}Failure:
{
"schemaVersion": "pbm.stable.v1",
"ok": false,
"error": {
"code": "target_not_found",
"message": "Target was not found.",
"details": {},
"retryHint": "optional"
}
}Exit codes:
0: success2: invalid arguments or required confirmation missing1: permission, target, platform, capability, or internal failure
The default config requires --confirm for destructive commands when safety.confirmDestructiveActions is true. This covers window close, app quit/relaunch, clipboard clear, dialog dismiss, daemon/Bridge uninstall, and disruptive Dock commands.
Tool policy applies to both CLI and MCP:
{
"policy": {
"allow": [],
"deny": ["clipboard.clear"]
}
}