Automation guide

Automation integration

Keep Aion from auto-closing an app while your local script, tool, or automation workflow is still using it.

Local onlyFor scripts and local agentsConfirm before cleanup

Who this is for

Tell Aion when another app is still busy

Use this page when a local tool launches or controls an app and needs Aion to wait until the work is really finished.

For local automation builders

Use this when a local script or agent is actively driving a browser, editor, terminal, or uploader and Aion should keep that app open until the task is done.

Start with the socket →

For ordinary Aion users

You do not need this page for normal setup. Use the user guide unless you are connecting your own local automation tool to Aion.

Read the user guide →

Transport

How to connect

Local protection socket

Aion exposes a same-user Unix domain socket. Your tool can use it to tell Aion which app is still busy.

~/Library/Application Support/Aion/ipc/ai-protection.sock

Optional URL commands

Aion 2.11 can also accept aion:// commands for scene changes, protection toggles, lists, status reads, and window actions. This is off by default and must be enabled in Settings → Advanced.

aion://scene/activate?name=Coding

Agent skill package

Use the packaged SKILL.md so compatible agents can discover the Aion CLI and request protection during long local tasks.

aion install-skill Open SKILL.md

Protocol flow

What a working session looks like

  1. Connect to the socket as the same macOS user that is running Aion.
  2. Send `session.hello` with `protocolVersion: 1`, your `holderId`, a readable `clientName`, and your `pid`.
  3. Wait for `session.ready` before sending lease messages.
  4. Send lease messages using the existing `AIAppLeaseEnvelope` payload shape.
  5. After the lease expires and grace time passes, Aion can send one `lease.can_close.request` before closing the app.
  6. Reply with `lease.can_close.reply` to allow the close or extend the lease.

Actions

Messages you can send

  • session.hello
  • lease.begin
  • lease.renew
  • lease.end
  • lease.list
  • lease.can_close.reply
Aion may send back

lease.can_close.request

Handshake and transport errors

Messages used during the handshake

  • session.hello
  • session.ready
  • session.error
invalid_handshakeunsupported_protocol_versionholder_id_mismatchunauthenticated

App identity

How `appKey` works today

  • For most apps, `appKey` is the bundle identifier, such as `com.google.Chrome`.
  • Profile-aware or variant-aware apps may use suffixed keys such as `com.google.Chrome#profile-work`.
  • Unknown app keys are rejected with `unknown_app`.

Limits

Current timing bounds

  • Minimum lease: 60 seconds
  • Maximum lease: 1800 seconds
  • Grace period after active lease: 60 seconds
  • Close-check timeout: 3 seconds
  • Close-check cooldown: 15 seconds

Examples

Minimal payloads

Handshake

{
  "action": "session.hello",
  "protocolVersion": 1,
  "holderId": "agent.local.test",
  "clientName": "Test Agent",
  "pid": 42
}

Begin a lease

{
  "action": "lease.begin",
  "requestId": "req_123",
  "holderId": "agent.local.test",
  "appKey": "com.google.Chrome",
  "leaseSeconds": 600
}

Reply to close-check

{
  "action": "lease.can_close.reply",
  "requestId": "close_777",
  "holderId": "agent.local.test",
  "appKey": "com.google.Chrome",
  "result": "extend_lease",
  "leaseSeconds": 300
}

Lease responses

Current response codes

acceptedinvalid_payloadunknown_actionunknown_appnot_entitledholder_mismatchrequest_expiredlease_conflict

What you can rely on

What you can rely on

Documented protocol

  • The socket path and same-user local transport model.
  • The handshake messages: `session.hello`, `session.ready`, and `session.error`.
  • The supported lease actions and current response codes listed on this page.
  • The fact that Aion may push one `lease.can_close.request` before auto-quit proceeds after expiry and grace.

Internal details are not API

  • Internal store layout, actor boundaries, and UI wiring.
  • Undocumented transports or debug-only entry points.
  • Internal state changes that are not documented here.

Recipes

Common automation setups

Start with the socket and lease flow on this page. Use a recipe only when a specific runtime needs extra setup.

Local automation runtime integration

For local runtimes that actively drive an app: when to begin a lease, renew it, and release it.

Read the runtime guide

New in 2.11

Optional URL commands for trusted local tools

The socket is for keeping busy apps protected. The optional aion:// commands are for broader control: scene changes, protection toggles, list updates, status reads, and window actions. Keep this disabled unless you trust the local tool using it.

1
Enable in Advanced Settings

Open Aion → Settings → Advanced → External Agent Control / 外部控制 and turn on the toggle. The switch is off by default.

2
Send URL commands from any local app or script

Use open "aion://..." in a shell, or call NSWorkspace.shared.open(url) from Swift/Objective-C. Commands take effect immediately on the main thread.

open "aion://scene/activate?name=Coding"
3
Refresh status when you need a snapshot

~/.aion_status.json is refreshed by the status command and relevant status requests. Lease commands return through the Unix socket and do not depend on this file.

~/.aion_status.json

URL Command Reference

All available aion:// commands

Scene Management

aion://scene/activate?name=Coding Activate a scene by name
aion://scene/activate?id=<uuid> Activate a scene by UUID
aion://scene/deactivate Return to Standard Mode
aion://scene/toggle Toggle active scene on/off

Protection Toggles

aion://protect/video?on=true Toggle Full-Screen Video Lock
aion://protect/smart-guards?on=false Toggle Smart Guards auto-quit protection
aion://protect/focus-sync?on=true Toggle macOS Focus Mode sync
aion://protect/instant?on=true Toggle Instant Task protection (Use & Go)
aion://protect/clean-now Trigger an immediate idle app cleanup pass

Blacklist Management

aion://blacklist/add?bundleId=com.apple.Safari Add app to blacklist (fast-quit target)
aion://blacklist/remove?bundleId=com.apple.Safari Remove app from blacklist
aion://blacklist/toggle?bundleId=<id> Toggle blacklist membership

Whitelist Management

aion://whitelist/add?bundleId=com.apple.dt.Xcode Add app to whitelist (always keep running)
aion://whitelist/remove?bundleId=com.apple.dt.Xcode Remove app from whitelist
aion://whitelist/toggle?bundleId=<id> Toggle whitelist membership

UI Windows

aion://ui/popover Open/close the menu bar HUD popover
aion://ui/settings?tab=blacklist Open Settings to a specific tab
aion://ui/history Open Activity History window

Status Query

aion://status Write current state to ~/.aion_status.json

Status JSON

~/.aion_status.json fields

  • activeScene — Name of the currently active scene (or "Standard Mode")
  • scenes — Array of all scenes with id and display name
  • protections.autoQuit — Whether Auto-Quit is enabled
  • protections.fullScreenVideoLock — Whether Full-Screen Video Lock is enabled
  • protections.smartGuards — Whether Smart Guards protection is enabled
  • protections.focusIntegration — Whether macOS Focus sync is enabled
  • protections.instantTask — Whether Instant Task protection is enabled
  • blacklist — Array of blacklisted bundle IDs
  • whitelist — Array of whitelisted (kept-running) bundle IDs
  • aiLeases — Active AI protection leases (keyed by app bundle ID)
  • demoModeActive — Whether Demo Mode is currently active
  • version — Current Aion app version

Example

Sample status file

{
  "activeScene": "Coding",
  "aiLeases": {
    "com.google.Chrome": {
      "holderId": "aion.cli",
      "leaseUntil": "<ISO-8601 timestamp>",
      "status": "active"
    }
  },
  "blacklist": ["com.apple.Safari"],
  "demoModeActive": false,
  "protections": {
    "autoQuit": true,
    "focusIntegration": true,
    "fullScreenVideoLock": true,
    "instantTask": true,
    "smartGuards": true
  },
  "scenes": [
    { "id": "...", "name": "Coding" },
    { "id": "...", "name": "Meeting" }
  ],
  "version": "<current-version>",
  "whitelist": ["com.apple.finder", "com.apple.dt.Xcode"]
}

CLI Helper

aion-cli.sh — for scripts and agents

The Aion project includes Scripts/aion-cli.sh. Lease commands use Aion's local Unix socket and return directly; other supported commands use the opt-in aion:// URL scheme. The status JSON file is refreshed only by the status command and relevant status requests.

The holder-less begin/end examples work across separate invocations because the CLI uses the stable default holder aion.cli. Pass an explicit holder when separate agents need isolated lease ownership.

Protect an app from auto-quit (AI lease)

./Scripts/aion lease begin com.google.Chrome 600

Release a lease when done

./Scripts/aion lease end com.google.Chrome

List active protection leases

./Scripts/aion lease list

Activate a scene

./Scripts/aion scene activate "Coding"

Turn on Video Lock

./Scripts/aion protect video on

Add app to blacklist

./Scripts/aion blacklist add com.apple.Safari

Read current status JSON

./Scripts/aion status

FAQ

Before you connect

Who needs this page?

Only local scripts, agents, or automation tools that actively use an app need this integration. Normal Aion setup belongs in the user guide.

Does the socket send data to the cloud?

No. The documented transport is a same-user Unix domain socket on the Mac running Aion.

Are aion:// commands enabled by default?

No. External Agent Control is off by default and must be enabled in Settings → Advanced before a trusted local tool can use it.

Do lease messages depend on the status JSON file?

No. Lease commands return through the Unix socket. The status command refreshes ~/.aion_status.json when a snapshot is needed.

Need a human fallback?

If you are connecting a local automation tool and this guide does not cover your case, email the use case and the message flow you need. For normal setup questions, the user guide is still the faster path.