ParthJadhav/SpaceO

Give AI agents their own macOS displays. Keep your screen, cursor, and focus.

Swift

11

19 commits

updated Sep 28, 2026

See the code

See what people are saying

SourceMessageScoreDate

SpaceO - Give AI agents a separate virtual monitor while you keep using your Mac (r/SideProject)

Using a computer-use agent usually means letting it take over your screen and waiting for it to finish. I tried fixing that by giving it a separate virtual monitor. It’s called SpaceO. Claude Code or Codex can open apps and work on that monitor while you keep using your Mac. You can also watch what…

1

Sep 28, 2026

README

SpaceO logo

Give AI agents their own screen on your Mac.

Let agents work in real apps while you keep using your computer.
SpaceO runs agent apps on separate, headless displays.

CI macOS 14 or later Apple Silicon MIT license Latest release

Get started · How it works · FAQ · Setup guide · Releases · Reference

SpaceO Viewer switching between working, needs-you, and release-note sessions

Recorded from the real SpaceO Viewer using synthetic preview sessions and sample screen content. View the still screenshot.

[!NOTE] Latest release · latest signed SpaceO release. Install it with one command, which verifies the signed, notarized release for you. You can also download the DMG from the Releases page.

Supported scope: native apps and Chromium browsers. Managed Electron apps such as Cursor and VS Code are refused before launch because they can take desktop focus. These editors can still connect to SpaceO as MCP clients to drive supported apps.

A screen for every agent

You keep workingYour agents keep working
Your physical display stays availableApps render on headless virtual displays
Your pointer stays where you put itAccessibility actions and targeted events operate apps
You decide when to interveneViewer shows sessions, activity, pause, and human handoff
Multiple agents can share one MacSessions own apps, windows, and display tiles

SpaceO is a native Swift app, a CLI, and an MCP server. Agents can read interface elements, click controls, enter text, inspect screenshots, and check what actually happened. Sessions can use dedicated displays or share a display in separate tiles.

What an agent can do

CapabilityMCP tools
Own a workspacespaceo_session_create, spaceo_session_destroy, spaceo_session_list, spaceo_pool_status
Launch and place appsspaceo_open_app, spaceo_open_url, spaceo_adopt_app, spaceo_place_window, spaceo_list_windows
See the interfacespaceo_read_screen, spaceo_find, spaceo_read_text, spaceo_screenshot, spaceo_wait_for
Act on itspaceo_click, spaceo_type, spaceo_press_key, spaceo_scroll, spaceo_drag, spaceo_menu, spaceo_select_text
Batch and verifyspaceo_run_steps, spaceo_verify_isolation, spaceo_events
Hand off to youspaceo_session_pause, spaceo_session_resume, per-session clipboard broker

Actions prefer Accessibility elements over coordinates, and every receipt says whether the result was confirmed, unconfirmed, or refused. The reference lists every tool and CLI command.

How it works

flowchart LR
  You["You · keyboard + mouse"] --> Physical["Your physical display"]
  Physical --> Work["Your apps and work"]
  AgentA["Agent A"] --> SessionA["Session A · virtual display"]
  AgentB["Agent B"] --> SessionB["Session B · virtual display / tile"]
  SessionA --> AppA["Browser · research"]
  SessionB --> AppB["Editor · documents"]
  Viewer["SpaceO Viewer"] -. "observe · pause · take control" .-> SessionA
  Viewer -. "observe · pause · take control" .-> SessionB
  style Physical fill:#eaf5ef,stroke:#24845b,color:#163a29
  style SessionA fill:#edf0ff,stroke:#6172cb,color:#25345f
  style SessionB fill:#edf0ff,stroke:#6172cb,color:#25345f

An inactive Mission Control Space can stop an app from drawing. A virtual display keeps its windows available to the compositor, capture, and Accessibility. SpaceO places agent windows there and sends actions to the target without deliberately activating it or moving your pointer.

Apps can still activate themselves, and macOS private APIs can change. SpaceO reports observed isolation failures and checks it cannot establish; an attempted action is not automatically reported as a confirmed result.

[!IMPORTANT] Attention isolation is not a security sandbox. Agent apps run as your macOS user, with that user’s files, network, credentials, and app sessions. Use a separate login or VM for untrusted workloads. Keep SIP enabled. See the security policy.

Get started

You need a Mac with Apple Silicon and macOS 14 or later. Run one command:

curl -fsSL https://raw.githubusercontent.com/ParthJadhav/SpaceO/main/install.sh | bash

The installer:

  1. downloads the latest signed release and checks its publisher signature, checksum, and notarization before running anything from it;
  2. installs spaceo to ~/.local/bin and SpaceO Viewer to ~/Applications, without sudo;
  3. connects SpaceO to Claude Code, Codex, Cursor, and Claude Desktop if they are installed;
  4. walks you through the Accessibility and Screen Recording permissions and runs a short self-test.

Restart your agent, then ask it something like "Open TextEdit in SpaceO, write a short note, and show me a screenshot". It creates its own session and cleans it up when it finishes.

Run the command again to upgrade. Add | bash -s -- --uninstall to remove SpaceO, or --help for options. To do each step yourself, follow INSTALL.md. Runtime support depends on your macOS build; spaceo doctor checks your Mac without changing anything. A passing self-test does not cover every input or isolation behavior. The setup guide covers permissions, compatibility, and your first session.

Connect another agent later

spaceo setup --client claude-code     # or codex, cursor, claude-desktop

For other MCP clients, use the absolute path to spaceo with the argument mcp (client configurations).

Or build from source (needs Xcode with Swift 6.2 or later; CI selects Xcode 26.3)

git clone https://github.com/ParthJadhav/SpaceO.git
cd SpaceO
make install                 # installs ~/.local/bin/spaceo
~/.local/bin/spaceo setup    # permissions, self-test, and MCP configuration

Virtual-display creation uses runtime capability checks on macOS 14 and later, with bounded lifecycle waits and creation limits. See display safety.

Or drive an app yourself from the CLI

spaceo daemon &
eval "$(spaceo session create --session try --export)"   # sets SPACEO_SESSION and SPACEO_LEASE
spaceo run TextEdit
spaceo ax                  # list indexed Accessibility elements
spaceo click --element 0
spaceo type "hello from another display"
spaceo screenshot -o /tmp/try.png
spaceo session destroy
spaceo daemon stop

Use Viewer on a physical display while the controlled application runs on a SpaceO virtual display. Hosting Viewer itself on a SpaceO virtual display is not qualified or supported: that nested arrangement showed intermittent stream staleness during qualification. No runtime fix for nested Viewer use is claimed; that arrangement remains unsupported.

Open the Viewer from a source build

SPACEO_CODESIGN_IDENTITY=- make viewer
open ".build/SpaceO Viewer.app"

This produces a local development build. Releases contain a Developer ID-signed, notarized Viewer and CLI in a signed, stapled DMG. See installation and verification.

From request to result

sequenceDiagram
  participant Agent
  participant SpaceO
  participant App as App on agent display
  participant Human as You / Viewer
  Agent->>SpaceO: Create session
  SpaceO-->>Agent: Session + controller lease
  Agent->>SpaceO: Open app, read screen
  SpaceO->>App: Place window, inspect Accessibility
  SpaceO-->>Agent: Elements and observed state
  Agent->>SpaceO: Act on an element
  SpaceO->>App: Targeted action
  SpaceO-->>Agent: Confirmed / unconfirmed / failed
  opt Human assistance needed
    Human->>SpaceO: Pause agent and take control
    Human->>SpaceO: Return control
    SpaceO-->>Agent: Handoff context
  end
  Agent->>SpaceO: Destroy session
  SpaceO-->>Agent: Cleanup result and any blockers

Architecture

flowchart TB
  MCP["MCP clients"] --> Server["SpaceOMCP · tool schemas + stdio"]
  CLI["spaceo · CLI"] --> Daemon["Shared per-user daemon"]
  Server --> Daemon
  Viewer["SpaceO Viewer · SwiftUI / AppKit"] --> Daemon
  Daemon --> Kit["SpaceOKit · sessions, leases, placement, input, capture, recovery"]
  Viewer --> Kit
  Kit --> Public["Accessibility · ScreenCaptureKit · AppKit"]
  Kit --> Private["SpaceOPrivate · runtime-resolved private APIs"]
  Public --> Apps["macOS apps on virtual displays"]
  Private --> Apps

Private API resolution stays in one target. Higher layers enforce bounded requests, ownership, capability checks, and explicit partial results. Controller leases coordinate clients running as the same user; they do not create a separate security boundary.

Read the architecture, runtime API support, and session recovery documents for the contracts and limitations.

FAQ

Why not just use another Space or a VM? Apps on an inactive Mission Control Space can stop drawing, so they can't be captured or reliably driven. A VM works but has no access to your installed apps, sign-ins, or files. SpaceO keeps apps in your login on displays you don't see.

Will it steal my focus or move my mouse? SpaceO never warps the pointer and does not deliberately activate agent apps. Apps can still activate themselves. When that happens, SpaceO reports the breach instead of hiding it (spaceo_verify_isolation).

Which apps work? Native macOS apps and Chromium browsers (Chrome, Chromium, Edge, Brave, Vivaldi, Opera, Arc) are in scope. Apps built on Electron, such as Cursor, VS Code, and Slack, are refused before launch in 1.0.0, because their renderers can take desktop focus.

Is it a sandbox? No. Agent apps run as your user, with your files, network, and credentials. Use a separate login or VM for untrusted work.

Why does it use private APIs? macOS has no public API for creating virtual displays or delivering targeted background input. SpaceO resolves these APIs at runtime, confines them to one target, and fails closed when a capability is missing. See runtime API support.

How do I remove it? Run spaceo daemon stop, then delete ~/.local/bin/spaceo and the Viewer app. Full steps are in INSTALL.md.

Develop and contribute

make build
make test             # deterministic; no app launches or synthetic input
make verify-release   # optimized build, safe tests, MCP smoke checks

Live tests create displays and drive real apps. Read LIVE_TESTS.md and use an eligible idle host. Skipped live tests are not release evidence.

See CONTRIBUTING.md for changes and review, AGENTS.md for repository conventions, and CHANGELOG.md for what is implemented.

Learn more
ReferenceCLI, MCP, Viewer controls, tiling, and capability status
TroubleshootingPermissions, sessions, input, and recovery
UpdatesVersion checks and daemon upgrades
SupportSupported platforms and known limits
SecurityPrivate vulnerability reporting and trust boundaries
Release policySigning, qualification, and publication approval

Released under the MIT license. macOS and Apple frameworks remain subject to Apple’s terms; SpaceO does not include Apple SDKs or private-framework binaries.

ai-agents
automation
computer-use
developer-tools
macos
mcp
model-context-protocol
swift
virtual-display

ParthJadhav/SpaceO

Give AI agents their own macOS displays. Keep your screen, cursor, and focus.

Swift

11

19 commits

updated Sep 28, 2026

See the code

See what people are saying

SourceMessageScoreDate

SpaceO - Give AI agents a separate virtual monitor while you keep using your Mac (r/SideProject)

Using a computer-use agent usually means letting it take over your screen and waiting for it to finish. I tried fixing that by giving it a separate virtual monitor. It’s called SpaceO. Claude Code or Codex can open apps and work on that monitor while you keep using your Mac. You can also watch what…

1

Sep 28, 2026

README

SpaceO logo

Give AI agents their own screen on your Mac.

Let agents work in real apps while you keep using your computer.
SpaceO runs agent apps on separate, headless displays.

CI macOS 14 or later Apple Silicon MIT license Latest release

Get started · How it works · FAQ · Setup guide · Releases · Reference

SpaceO Viewer switching between working, needs-you, and release-note sessions

Recorded from the real SpaceO Viewer using synthetic preview sessions and sample screen content. View the still screenshot.

[!NOTE] Latest release · latest signed SpaceO release. Install it with one command, which verifies the signed, notarized release for you. You can also download the DMG from the Releases page.

Supported scope: native apps and Chromium browsers. Managed Electron apps such as Cursor and VS Code are refused before launch because they can take desktop focus. These editors can still connect to SpaceO as MCP clients to drive supported apps.

A screen for every agent

You keep workingYour agents keep working
Your physical display stays availableApps render on headless virtual displays
Your pointer stays where you put itAccessibility actions and targeted events operate apps
You decide when to interveneViewer shows sessions, activity, pause, and human handoff
Multiple agents can share one MacSessions own apps, windows, and display tiles

SpaceO is a native Swift app, a CLI, and an MCP server. Agents can read interface elements, click controls, enter text, inspect screenshots, and check what actually happened. Sessions can use dedicated displays or share a display in separate tiles.

What an agent can do

CapabilityMCP tools
Own a workspacespaceo_session_create, spaceo_session_destroy, spaceo_session_list, spaceo_pool_status
Launch and place appsspaceo_open_app, spaceo_open_url, spaceo_adopt_app, spaceo_place_window, spaceo_list_windows
See the interfacespaceo_read_screen, spaceo_find, spaceo_read_text, spaceo_screenshot, spaceo_wait_for
Act on itspaceo_click, spaceo_type, spaceo_press_key, spaceo_scroll, spaceo_drag, spaceo_menu, spaceo_select_text
Batch and verifyspaceo_run_steps, spaceo_verify_isolation, spaceo_events
Hand off to youspaceo_session_pause, spaceo_session_resume, per-session clipboard broker

Actions prefer Accessibility elements over coordinates, and every receipt says whether the result was confirmed, unconfirmed, or refused. The reference lists every tool and CLI command.

How it works

flowchart LR
  You["You · keyboard + mouse"] --> Physical["Your physical display"]
  Physical --> Work["Your apps and work"]
  AgentA["Agent A"] --> SessionA["Session A · virtual display"]
  AgentB["Agent B"] --> SessionB["Session B · virtual display / tile"]
  SessionA --> AppA["Browser · research"]
  SessionB --> AppB["Editor · documents"]
  Viewer["SpaceO Viewer"] -. "observe · pause · take control" .-> SessionA
  Viewer -. "observe · pause · take control" .-> SessionB
  style Physical fill:#eaf5ef,stroke:#24845b,color:#163a29
  style SessionA fill:#edf0ff,stroke:#6172cb,color:#25345f
  style SessionB fill:#edf0ff,stroke:#6172cb,color:#25345f

An inactive Mission Control Space can stop an app from drawing. A virtual display keeps its windows available to the compositor, capture, and Accessibility. SpaceO places agent windows there and sends actions to the target without deliberately activating it or moving your pointer.

Apps can still activate themselves, and macOS private APIs can change. SpaceO reports observed isolation failures and checks it cannot establish; an attempted action is not automatically reported as a confirmed result.

[!IMPORTANT] Attention isolation is not a security sandbox. Agent apps run as your macOS user, with that user’s files, network, credentials, and app sessions. Use a separate login or VM for untrusted workloads. Keep SIP enabled. See the security policy.

Get started

You need a Mac with Apple Silicon and macOS 14 or later. Run one command:

curl -fsSL https://raw.githubusercontent.com/ParthJadhav/SpaceO/main/install.sh | bash

The installer:

  1. downloads the latest signed release and checks its publisher signature, checksum, and notarization before running anything from it;
  2. installs spaceo to ~/.local/bin and SpaceO Viewer to ~/Applications, without sudo;
  3. connects SpaceO to Claude Code, Codex, Cursor, and Claude Desktop if they are installed;
  4. walks you through the Accessibility and Screen Recording permissions and runs a short self-test.

Restart your agent, then ask it something like "Open TextEdit in SpaceO, write a short note, and show me a screenshot". It creates its own session and cleans it up when it finishes.

Run the command again to upgrade. Add | bash -s -- --uninstall to remove SpaceO, or --help for options. To do each step yourself, follow INSTALL.md. Runtime support depends on your macOS build; spaceo doctor checks your Mac without changing anything. A passing self-test does not cover every input or isolation behavior. The setup guide covers permissions, compatibility, and your first session.

Connect another agent later

spaceo setup --client claude-code     # or codex, cursor, claude-desktop

For other MCP clients, use the absolute path to spaceo with the argument mcp (client configurations).

Or build from source (needs Xcode with Swift 6.2 or later; CI selects Xcode 26.3)

git clone https://github.com/ParthJadhav/SpaceO.git
cd SpaceO
make install                 # installs ~/.local/bin/spaceo
~/.local/bin/spaceo setup    # permissions, self-test, and MCP configuration

Virtual-display creation uses runtime capability checks on macOS 14 and later, with bounded lifecycle waits and creation limits. See display safety.

Or drive an app yourself from the CLI

spaceo daemon &
eval "$(spaceo session create --session try --export)"   # sets SPACEO_SESSION and SPACEO_LEASE
spaceo run TextEdit
spaceo ax                  # list indexed Accessibility elements
spaceo click --element 0
spaceo type "hello from another display"
spaceo screenshot -o /tmp/try.png
spaceo session destroy
spaceo daemon stop

Use Viewer on a physical display while the controlled application runs on a SpaceO virtual display. Hosting Viewer itself on a SpaceO virtual display is not qualified or supported: that nested arrangement showed intermittent stream staleness during qualification. No runtime fix for nested Viewer use is claimed; that arrangement remains unsupported.

Open the Viewer from a source build

SPACEO_CODESIGN_IDENTITY=- make viewer
open ".build/SpaceO Viewer.app"

This produces a local development build. Releases contain a Developer ID-signed, notarized Viewer and CLI in a signed, stapled DMG. See installation and verification.

From request to result

sequenceDiagram
  participant Agent
  participant SpaceO
  participant App as App on agent display
  participant Human as You / Viewer
  Agent->>SpaceO: Create session
  SpaceO-->>Agent: Session + controller lease
  Agent->>SpaceO: Open app, read screen
  SpaceO->>App: Place window, inspect Accessibility
  SpaceO-->>Agent: Elements and observed state
  Agent->>SpaceO: Act on an element
  SpaceO->>App: Targeted action
  SpaceO-->>Agent: Confirmed / unconfirmed / failed
  opt Human assistance needed
    Human->>SpaceO: Pause agent and take control
    Human->>SpaceO: Return control
    SpaceO-->>Agent: Handoff context
  end
  Agent->>SpaceO: Destroy session
  SpaceO-->>Agent: Cleanup result and any blockers

Architecture

flowchart TB
  MCP["MCP clients"] --> Server["SpaceOMCP · tool schemas + stdio"]
  CLI["spaceo · CLI"] --> Daemon["Shared per-user daemon"]
  Server --> Daemon
  Viewer["SpaceO Viewer · SwiftUI / AppKit"] --> Daemon
  Daemon --> Kit["SpaceOKit · sessions, leases, placement, input, capture, recovery"]
  Viewer --> Kit
  Kit --> Public["Accessibility · ScreenCaptureKit · AppKit"]
  Kit --> Private["SpaceOPrivate · runtime-resolved private APIs"]
  Public --> Apps["macOS apps on virtual displays"]
  Private --> Apps

Private API resolution stays in one target. Higher layers enforce bounded requests, ownership, capability checks, and explicit partial results. Controller leases coordinate clients running as the same user; they do not create a separate security boundary.

Read the architecture, runtime API support, and session recovery documents for the contracts and limitations.

FAQ

Why not just use another Space or a VM? Apps on an inactive Mission Control Space can stop drawing, so they can't be captured or reliably driven. A VM works but has no access to your installed apps, sign-ins, or files. SpaceO keeps apps in your login on displays you don't see.

Will it steal my focus or move my mouse? SpaceO never warps the pointer and does not deliberately activate agent apps. Apps can still activate themselves. When that happens, SpaceO reports the breach instead of hiding it (spaceo_verify_isolation).

Which apps work? Native macOS apps and Chromium browsers (Chrome, Chromium, Edge, Brave, Vivaldi, Opera, Arc) are in scope. Apps built on Electron, such as Cursor, VS Code, and Slack, are refused before launch in 1.0.0, because their renderers can take desktop focus.

Is it a sandbox? No. Agent apps run as your user, with your files, network, and credentials. Use a separate login or VM for untrusted work.

Why does it use private APIs? macOS has no public API for creating virtual displays or delivering targeted background input. SpaceO resolves these APIs at runtime, confines them to one target, and fails closed when a capability is missing. See runtime API support.

How do I remove it? Run spaceo daemon stop, then delete ~/.local/bin/spaceo and the Viewer app. Full steps are in INSTALL.md.

Develop and contribute

make build
make test             # deterministic; no app launches or synthetic input
make verify-release   # optimized build, safe tests, MCP smoke checks

Live tests create displays and drive real apps. Read LIVE_TESTS.md and use an eligible idle host. Skipped live tests are not release evidence.

See CONTRIBUTING.md for changes and review, AGENTS.md for repository conventions, and CHANGELOG.md for what is implemented.

Learn more
ReferenceCLI, MCP, Viewer controls, tiling, and capability status
TroubleshootingPermissions, sessions, input, and recovery
UpdatesVersion checks and daemon upgrades
SupportSupported platforms and known limits
SecurityPrivate vulnerability reporting and trust boundaries
Release policySigning, qualification, and publication approval

Released under the MIT license. macOS and Apple frameworks remain subject to Apple’s terms; SpaceO does not include Apple SDKs or private-framework binaries.

ai-agents
automation
computer-use
developer-tools
macos
mcp
model-context-protocol
swift
virtual-display

Languages

Swift

92.5%

Shell

3.0%

JavaScript

1.8%

Python

1.4%

Objective-C

1.1%