macOS Harness: raw Mac primitives for an LLM agent, no app-specific tools
The simplest, thinnest harness that gives an LLM complete freedom to control a Mac.
At a glance
- What is it?
- macos-harness from browser-use gives an agent six primitives (see, key, type, click, ax, script) inside one persistent Python process, with the real browser and the local filesystem in reach. It is alpha, macOS only, and the README documents no rollback.
- Who is it for?
- Adopt macos-harness if you are building a computer-use agent on macOS and want raw Accessibility, Apple Events and CDP access in one Python process instead of a library of per-app tools. Do not adopt it if you need Windows or Linux support, a stable API, or an auditable record of what the agent did, since the README describes no undo path and no logging of prompts, app names or scripts.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 43 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What macos-harness solves, and for whom
Most computer-use stacks grow a tool per application. A Spotify tool, a Slack tool, a Final Cut tool. Each one has to be written, tested and kept in step with the app. The README states the opposite position plainly: there are no Spotify tools, Slack tools or Final Cut tools, and the model gets raw primitives and writes the rest. The pitch is that when an agent hits a task no helper covers, it looks at the app through raw macOS primitives and writes the missing logic in ordinary Python mid-task, with no app-specific tool added.
That makes the audience narrow and specific. It is for Python developers building agents that need to operate a real Mac: clicking through a desktop app, driving a logged-in Chrome session, touching files, running shell commands. It is not for someone who wants a packaged automation product, and it is not for anyone who needs a supported, stable surface. The project classifies itself as Development Status 3 - Alpha and calls itself experimental in the README.
One process, six primitives, three escape hatches
The architecture diagram in the README shows one persistent Python process with three branches hanging off it. The mac branch fans out to CGWindow screenshots, CGEvent input sent to a PID, and AX plus Apple Events. The browser branch goes through Browser Harness and CDP to a real Chrome. The third branch is plain Path and subprocess, so files and shell are ordinary Python.
The six primitives are see, key, type, click, ax and script. Two design choices stand out. First, captures happen against background app windows without bringing them forward, and keyboard and coordinate input go directly to an app PID rather than to whatever is focused. Second, the harness draws an animated, click-through pointer without moving the real cursor, and the README says it never activates or raises a target app and never moves the physical pointer. That is the difference between an agent that hijacks your machine for the duration of a task and one that can work on a window you are not looking at.
The escape hatches matter as much as the primitives. When vision is not enough, mac.ax and mac.script expose raw Apple Accessibility and Apple Events. When the desktop is not enough, browser.page_info() talks to the real, logged-in browser. When neither is enough, list(Path.home().iterdir()) is just Python.
Installing macos-harness with uv and running a first capture
The README's primary install path is to hand the job to an agent. It gives a prompt to paste into Codex or Claude Code, which tells the agent to install or upgrade macOS Harness from the GitHub URL with uv using Python 3.12, register the skill printed by macos-harness skill, run macos-harness doctor, explain any missing macOS permissions and ask before requesting them, and finally verify by capturing one already-running app without bringing it to the foreground. A manual setup document, install.md, is linked for people who would rather do it themselves.
The package requires Python 3.11 or newer per pyproject.toml, though the agent prompt specifies 3.12. Its runtime dependencies are browser-harness, pillow, and pyobjc-framework-ApplicationServices on darwin. The console entry point is macos-harness, backed by macos_harness.cli:main.
Once installed, the README's own example shows the shape of a session. It is fed to the CLI on stdin as a heredoc:
macos-harness <<'PY'
frame = mac.see("Spotify")
mac.key("cmd+k", app="Spotify")
mac.type("Alessia Cara", app="Spotify")
mac.click(640, 420, app="Spotify")
item = mac.ax.at(640, 420, app="Spotify")
mac.script('tell application "Spotify" to play')
print(browser.page_info())
print(list(Path.home().iterdir()))
PYEach line is a primitive aimed at a named app: capture the window, send a keyboard shortcut, type text, click a coordinate. The ax call reads the Accessibility element at that same coordinate, which is how you check what you just clicked instead of trusting the pixel. The script call falls through to Apple Events when the Accessibility layer does not expose what you need. The last two lines print browser page info and the contents of your home directory, showing that browser and filesystem access sit in the same process as the Mac primitives.
Before any of that runs, macos-harness doctor reports the macOS permissions actually needed. The README does not enumerate which permissions those are, so treat the doctor output as the source of truth on your machine rather than a list in the docs.
There is no undo, and the docs do not pretend otherwise
The genuine limitation is not performance, it is blast radius. An agent with click, type, script and subprocess in one process can do anything you can do, and the README does not describe a rollback mechanism, a dry-run mode, or a confirmation step before destructive actions. The only guardrail mentioned is on the install path: the agent prompt tells the agent to explain missing permissions and ask before requesting them. That governs setup, not execution.
The telemetry policy is explicit about what is not recorded. It says telemetry never records prompts, app names, screenshots, UI text, scripts, paths or window titles. Useful for privacy, but it also means there is no built-in audit trail of what the agent actually did, so if you need a record of every click and script for compliance or debugging, you are building it yourself.
Two more boundaries. The README says macOS only, so Windows and Linux are out. And the project is alpha at version 0.1.2, with three releases all pushed on 2026-08-17. The API you write against today is the API of an early release.
macos-harness versus a scripted AppleScript or pyobjc setup
The obvious alternative is what people already do on macOS: write AppleScript or JXA directly, or call the pyobjc frameworks yourself. That approach is mature, documented by Apple, and needs no third-party harness. The difference in practice is who writes the glue. With raw AppleScript you decide up front which apps you support and what each script does, and the agent can only choose from what you wrote. With macos-harness the primitives are fixed and the per-task logic is generated at run time, which the README frames as the agent writing what is missing mid-task.
The trade is predictability for coverage. A hand-written AppleScript library is auditable, versioned and testable; you know exactly which operations exist. macos-harness deliberately has no per-app layer, so the operation set is unbounded and so is the surface you have to reason about. If your automation is a fixed set of well-understood tasks, scripted AppleScript is the lower-risk choice. If your agent is supposed to handle tasks you did not anticipate, the harness is aimed at exactly that gap.
A second comparison point is the browser side. Rather than driving a fresh headless Chrome, macos-harness uses Browser Harness against the real, logged-in browser over CDP. That gets you sessions, cookies and extensions that a clean profile would not have. It also means the agent operates inside your actual browsing identity, which is a capability and a risk at the same time.
Maintenance cost, licence and telemetry
The last push to the repository was on 2026-08-17, the same day as the v0.1.2 release, so the project is recent but has a short history: three releases, all on that date, and a version number still in 0.1.x. There is a CONTRIBUTING.md and a tests directory with pytest configured in pyproject.toml, and the dev group pins pytest, pyyaml and ruff, which suggests the project expects contributors to run lint and tests. There is also a SECURITY.md at the top level. None of that changes the alpha classification, and upgrade cost is the real question: with a 0.1.x API, pin your version and read the release notes before moving.
The licence is MIT, declared in pyproject.toml with a LICENSE file at the repository root and referenced from the README. MIT is permissive, so the usual obligations are attribution and inclusion of the licence text when you redistribute. One dependency detail is worth flagging for licence review: pyobjc-framework-ApplicationServices is pulled in only on darwin, and browser-harness is a hard dependency, so your dependency audit needs to cover those too. That is a description of the declared metadata, not legal advice.
Telemetry is on by default. The README says it records the CLI command category, success, duration, package version, OS and architecture, and the detected agent client. If that is not acceptable in your environment, the documented switch is:
macos-harness telemetry disableEditorial conclusion
Adopt macos-harness if you are building a computer-use agent on macOS and want raw Accessibility, Apple Events and CDP access in one Python process instead of a library of per-app tools. Do not adopt it if you need Windows or Linux support, a stable API, or an auditable record of what the agent did, since the README describes no undo path and no logging of prompts, app names or scripts. Before wiring it into anything real, run macos-harness doctor and confirm which permissions macOS actually grants, then decide whether telemetry should stay enabled or be turned off with macos-harness telemetry disable.
Frequently asked questions
How do I know if my Mac is x64 or ARM64?
The README does not cover how to check your Mac's architecture. It does say that telemetry records the OS and architecture, and that pyobjc-framework-ApplicationServices is installed only on darwin, so the package targets macOS regardless of which of the two you have.
What does macOS stand for?
The README does not explain the name. It only states that macos-harness is macOS only, and describes the project as experimental.
What coding language does macOS use?
The README does not describe the language macOS itself is written in. It does say that macos-harness is a Python package, that its primary language is Python, and that it requires Python 3.11 or newer per pyproject.toml.
Is macOS Unix or Linux?
The README does not address whether macOS is Unix or Linux. It only states that macos-harness is macOS only and that its pyobjc dependency is marked darwin-only.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/browser-use-macos-harness)