# How Cua Driver Achieves Background macOS Automation Without Stealing Cursor or Focus

> Discover how Cua Driver enables background macOS automation by preventing cursor and focus stealing using accessibility, synthetic focus, and reactive workspace notifications.

- Repository: [Cua/cua](https://github.com/trycua/cua)
- Tags: internals
- Published: 2026-04-27

---

**Cua Driver achieves background macOS automation without stealing cursor or focus by layering three independent techniques: accessibility attribute enablement, synthetic focus state injection, and a reactive guard that intercepts and reverses focus-stealing attempts via NSWorkspace notifications.**

The `trycua/cua` repository implements this capability in the Cua Driver, a Swift-based automation framework that controls macOS applications entirely in the background. Unlike traditional AppleScript or Accessibility API approaches that force the target app to the foreground, this driver preserves the user's current context by manipulating the accessibility tree and focus states directly.

## The Three-Layer Focus Suppression Architecture

The driver prevents cursor and focus stealing through a coordinated defense implemented across three distinct layers. Each layer addresses a specific mechanism by which macOS applications typically force themselves into the foreground.

The architecture consists of:

- **AX Enablement**: Setting accessibility attributes on Chromium-family apps to expose full UI trees without activation
- **Synthetic Focus**: Temporarily overriding `AXFocused` and `AXMain` attributes to simulate focus without system activation
- **Reactive Guard**: Monitoring `NSWorkspace.didActivateApplicationNotification` to immediately reverse any successful focus grabs

## Layer 1: AX Enablement for Chromium Applications

Modern macOS applications built on Chromium frameworks (Chrome, VS Code, Slack) require specific accessibility attributes to expose their full UI hierarchy when running in the background. The `AXEnablementAssertion` actor in [`libs/cua-driver/Sources/CuaDriverCore/Focus/AXEnablementAssertion.swift`](https://github.com/trycua/cua/blob/main/libs/cua-driver/Sources/CuaDriverCore/Focus/AXEnablementAssertion.swift) handles this initialization.

```swift
/// Writes AXManualAccessibility and AXEnhancedUserInterface on the application root.
public actor AXEnablementAssertion {
    private var assertedPids: Set<pid_t> = []
    private var nonAssertablePids: Set<pid_t> = []

    public func assert(pid: pid_t, root: AXUIElement) -> Bool { … }
}

```

When `assert(pid:root:)` succeeds, the target application exposes a complete accessibility tree capable of receiving actions without `NSRunningApplication.activate` being called. The implementation caches process IDs (PIDs) that fail assertion as "non-assertable" to avoid redundant failed writes on subsequent operations.

## Layer 2: Synthetic Focus State Injection

Even with accessibility enabled, macOS UI actions typically require the target window to hold system focus. The `SyntheticAppFocusEnforcer` actor in [`libs/cua-driver/Sources/CuaDriverCore/Focus/SyntheticAppFocusEnforcer.swift`](https://github.com/trycua/cua/blob/main/libs/cua-driver/Sources/CuaDriverCore/Focus/SyntheticAppFocusEnforcer.swift) bypasses this requirement by temporarily manipulating focus attributes directly.

```swift
public actor SyntheticAppFocusEnforcer {
    public func preventActivation(pid: pid_t,
                                 window: AXUIElement?,
                                 element: AXUIElement?) async -> FocusState { … }

    public func reenableActivation(_ state: FocusState) async { … }
}

```

The `preventActivation` method records the current `AXFocused` and `AXMain` boolean values, writes `true` to both attributes, and returns a `FocusState` token. This makes the target's internal AppKit state believe it already has focus, preventing the system from invoking `AXUIElementPerformAction(kAXRaiseAction)`. After the automation action completes, `reenableActivation` restores the original values.

## Layer 3: Reactive Focus-Steal Guard

Some applications (particularly Safari and WebKit-based browsers) occasionally bypass synthetic focus controls and trigger `activate` calls. The `SystemFocusStealPreventer` in [`libs/cua-driver/Sources/CuaDriverCore/Focus/SystemFocusStealPreventer.swift`](https://github.com/trycua/cua/blob/main/libs/cua-driver/Sources/CuaDriverCore/Focus/SystemFocusStealPreventer.swift) implements a reactive defense against these edge cases.

```swift
public actor SystemFocusStealPreventer {
    public func beginSuppression(targetPid: pid_t,
                                restoreTo: NSRunningApplication) async -> SuppressionHandle { … }
    public func endSuppression(_ handle: SuppressionHandle) async { … }
}

```

This actor installs an observer on `NSWorkspace.didActivateApplicationNotification`. When the notification indicates the suppressed target PID has activated, the guard immediately calls `restoreTo.activate(options: [])` to return focus to the previously frontmost application. The `SuppressionHandle` manages the lifecycle of this observation, ensuring cleanup after automation completes.

## The FocusGuard Coordinator

The `FocusGuard` actor in [`libs/cua-driver/Sources/CuaDriverCore/Focus/FocusGuard.swift`](https://github.com/trycua/cua/blob/main/libs/cua-driver/Sources/CuaDriverCore/Focus/FocusGuard.swift) serves as the public entry point, coordinating all three suppression layers into a single transactional API.

```swift
public actor FocusGuard {
    public func withFocusSuppressed<T: Sendable>(pid: pid_t,
                                                element: AXUIElement?,
                                                body: @Sendable () async throws -> T) async throws -> T { … }
}

```

The `withFocusSuppressed` method executes the following sequence:

1. Invokes `AXEnablementAssertion.assert` to prepare accessibility attributes
2. Calls `SyntheticAppFocusEnforcer.preventActivation` to inject synthetic focus
3. Optionally initiates `SystemFocusStealPreventer.beginSuppression` for reactive monitoring
4. Executes the provided `body` closure containing the actual automation action
5. Restores original focus states and ends suppression via the respective cleanup methods

## Practical Implementation Example

To perform background automation using the driver, instantiate the three components and wrap your automation logic inside `withFocusSuppressed`:

```swift
import CuaDriverCore

let pid = 12345                     // PID of the background app (e.g. Calculator)
let element: AXUIElement? = nil     // No specific AX element, just the app root

let guard = FocusGuard(
    enablement: AXEnablementAssertion(),
    enforcer: SyntheticAppFocusEnforcer(),
    systemPreventer: SystemFocusStealPreventer()
)

await guard.withFocusSuppressed(pid: pid, element: element) {
    // Inside this closure you can safely call any driver tool, e.g. click a button:
    try await ClickTool.perform(pid: pid, windowId: 0, x: 150, y: 80)
}

```

For Python-based integrations, the [`driver_client.py`](https://github.com/trycua/cua/blob/main/driver_client.py) in [`libs/cua-driver/Tests/integration/driver_client.py`](https://github.com/trycua/cua/blob/main/libs/cua-driver/Tests/integration/driver_client.py) forwards JSON-RPC calls to the Swift driver binary where the suppression logic executes:

```python
from driver_client import DriverClient, default_binary_path

with DriverClient(default_binary_path()) as client:
    # Example: press the "A" key in a background app

    client.call_tool("type_text", {"pid": 12345, "text": "A"})

```

The focus suppression logic resides entirely within the compiled Swift driver, not the client layer, ensuring consistent behavior across language bindings.

## Summary

- **Three-layer architecture**: Cua Driver combines AX enablement, synthetic focus injection, and reactive focus-steal prevention to maintain background operation.
- **Chromium compatibility**: The `AXEnablementAssertion` class enables full accessibility trees on Electron and Chromium apps without activation.
- **Focus simulation**: `SyntheticAppFocusEnforcer` manipulates `AXFocused` and `AXMain` attributes to trick AppKit into believing the target already has focus.
- **Reactive protection**: `SystemFocusStealPreventer` monitors `NSWorkspace.didActivateApplicationNotification` to reverse any unwanted activations from WebKit applications.
- **Unified API**: `FocusGuard.withFocusSuppressed` provides a transactional interface that bundles all suppression layers and automatically manages cleanup.

## Frequently Asked Questions

### Does this approach work with all macOS applications?

The driver works with standard Cocoa applications and Chromium-based apps (VS Code, Slack, Chrome) that respect accessibility attributes. However, some system applications or those implementing custom window management may resist synthetic focus injection, in which case the reactive guard in `SystemFocusStealPreventer` provides fallback protection by immediately reversing any focus theft.

### What happens if the target application tries to activate itself during automation?

If the target app attempts to steal focus via `NSRunningApplication.activate` or similar APIs, the `SystemFocusStealPreventer` intercepts the `NSWorkspace.didActivateApplicationNotification` and immediately reactivates the previously frontmost application. This creates a near-instantaneous focus restoration that prevents visible UI disruption or cursor movement.

### How does the driver handle performance when suppressing focus?

The suppression logic introduces minimal overhead. `AXEnablementAssertion` caches non-assertable PIDs to avoid redundant accessibility writes, and `SyntheticAppFocusEnforcer` performs only two AX attribute reads and writes per operation. The `SystemFocusStealPreventer` maintains a single notification observer regardless of how many operations are performed, ensuring the reactive guard scales efficiently.

### Can I use this driver to automate applications that are not currently running?

No. The Cua Driver requires the target application to be already running with a valid process ID (PID). The focus suppression techniques described here manipulate existing accessibility trees and window states; they do not handle application launch or initialization of new accessibility contexts.