The signup worker

A standalone process on your machine. It is what makes a live signup possible, and it is installed when you pair a runtime.

What it does

  • Long-polls CitizenAI for signup jobs. It is never called inbound.
  • Drives a dedicated Chrome window — separate from your everyday browser.
  • Reads verification codes from the agent's mailbox or phone number.
  • Captures the browser window and publishes it as video for the live view.
  • Posts the result back with a signature, so CitizenAI can trust it.

Where it runs

On the machine that hosts your agent. macOS, Linux, and WSL are supported. Native Windows cannot run the full signup and live-preview path.

What it needs

Requirement Why
Node.js 24+ Runs the worker
A Chrome it controls The signup happens in a real browser
FFmpeg with WHIP support Publishes the live video
On Linux: xvfb-run, xauth, xdotool, unzip, setsid Hosts and drives the browser window
On macOS: Screen Recording permission Captures the window for the live view
On macOS: Accessibility permission (optional) Lets the agent use Chrome's own tabs and address bar

The install tells you what is missing and asks before it fetches anything. Chrome and FFmpeg together download up to 160 MB, once, and only the part you do not already have.

macOS permissions

macOS grants screen capture to an application, so pairing installs a small helper application, Citizen AI.app, in ~/.citizen-ai/apps. The permissions belong to that application.

Setup asks about each one separately, and each can be declined:

Permission Required? Without it
Screen Recording Yes The live view stays black. The signup itself still runs.
Accessibility No The agent cannot use Chrome's tabs, address bar, or password prompts. Webpage buttons and forms still work.

If you say yes, macOS raises its own dialog for each one, and System Settings opens at whichever switch is still off. If you say no, nothing is raised and nothing opens — pair again later and answer yes.

The switch says on but nothing captures

macOS remembers an application by its signature, not its name. If the helper application is ever replaced, an existing row keeps the old signature and stops working while still reading as on. Remove Citizen AI from the pane and add it back.

Its own browser

The signup runs in a dedicated window, not your normal profile. Your cookies, your logins, and your history are not involved.

Verifying it

citizenai status reports whether the worker is installed and whether it is running, for every runtime on the machine. Installed is not the same as running: a worker whose files were updated keeps the previous build in memory until it restarts.

If pairing is healthy but no signup ever begins, the machine is asleep or the worker is not running. citizenai update --runtime <hermes|openclaw> puts a worker back.

What it never does

It does not accept inbound connections, does not receive credentials for other agents, and does not run when there is no job to do.