Skip to main content

Orca IDE server setup

Written 2026-10-25 against Orca 1.4.238.


The two things that make this non-obvious

1. The CLI defaults to the wrong profile. There are two profiles on this box:

Path What it is
~/.orca the live one — paired devices, agent-session journal, terminal history, chat scratch (~18 MB)
~/.config/orca Electron's default profile; created 25/10 07:15, contains only a 155 MB orcad-artifacts download

orca-ide status reports "not running" while the server is running, because it looks in ~/.config/orca. Every command below therefore pins the profile:

export ORCA_USER_DATA_PATH=/home/USERNAME/.orca

Add that line to ~/.bashrc if you want it permanent.

2. /usr/bin/orca is the GNOME screen reader, not Orca IDE. ~/.local/bin/orca shadows it today, but the ordering is fragile. Always use orca-ide (→ /home/USERNAME/.local/bin/orca-ide → /opt/Orca/resources/bin/orca-ide).

Good news: loginctl show-user USERNAME already reports Linger=yes, so user services survive logout and start at boot.


1. Look before touching

export ORCA_USER_DATA_PATH=/home/USERNAME/.orca

orca-ide status                  # expect: appRunning: true, pid <orcad pid>
ps aux | grep -i orca | grep -v grep
ss -tlnp | grep -E '6768|44267'
systemctl --user list-units --all | grep -i orca

What was running at the time of writing: orcad (pid 54008) serving 127.0.0.1:6768, its Electron web-UI child on 0.0.0.0:44267, and two terminal daemons in orca-daemon-*.scope. Critically, the runtime lived in session-9.scope — an SSH login already in state closing, whose RemoteHost was 100.64.0.1. That is why it was doomed: not supervised, not enabled, and killed when systemd reaps the session.


2. Stop the old stack

orca serve refuses to start (exit code 3) while another Orca serves the same profile, so this comes first.

systemctl --user stop 'app-orca-*.scope'
systemctl --user stop 'orca-daemon-*.scope'
pgrep -f 'orcad\.js --json' | head -1 | xargs -r kill   # the headless runtime wrapper

pkill -f 'orca-ide --serve' || true               # web UI, if still alive

Verify both ports are free:

ss -tlnp | grep -E '6768|44267' || echo "ports free"

Notes:

  • Any terminals/agents inside those daemons stop here. Do this before starting work.
  • Only run this before installing the service — afterwards it would kill your new server too (the service unit is orca-serve-*.service, but orca-daemon-*.scope is shared).

3. Pair your devices (do this before installing)

Why a foreground run instead of the service: the installer hardcodes --no-pairing, because a pairing offer is a live credential and a service's output lands in the journal. One offer can only be minted by a foreground server (or by a desktop app already attached to this runtime).

One offer enrols one device. Offers are short-lived (relay invites expire in at most 10 minutes) — treat them as single-use.

# still no service running, still ORCA_USER_DATA_PATH set
orca-ide serve

It prints the bound endpoint, the advertised endpoint, and a pairing link (orca://pair?code=...) plus a browser URL. Pair the device now, then, for each additional device:

Ctrl-C, then: orca-ide serve      # fresh offer for the next device

For a phone, use a mobile-scoped offer instead:

orca-ide serve --mobile-pairing   # prints a QR / mobile link

When done pairing, Ctrl-C. Pairing persists: the offer carries this profile's E2EE host public key (~/.orca/orca-e2ee-keypair.json), and clients pin that key, so restarts and reboots do not require re-pairing.

Check who is paired at any time (read-only, no tokens printed):

python3 -c "
import json
for d in json.load(open('/home/USERNAME/.orca/orca-devices.json')):
    print(d['scope'].ljust(8), d['name'].ljust(45), d['deviceId'])
"

4. Install the service

orca-ide serve service install --dry-run    # prints the unit, writes nothing
orca-ide serve service install

The install writes this unit, then runs daemon-reload, enable and restart — i.e. the server starts immediately.

~/.config/systemd/USERNAME/orca-serve-3eba5288.service (the 3eba5288 suffix is derived from ORCA_USER_DATA_PATH; the default profile would give plain orca-serve.service)

[Unit]
Description=Orca server (orca serve --supervise)
StartLimitIntervalSec=900
StartLimitBurst=5

[Service]
Type=simple
ExecStart=/home/USERNAME/.local/bin/orca-ide serve --supervise --no-pairing
Environment=ORCA_USER_DATA_PATH=/home/USERNAME/.orca
Restart=on-failure
RestartSec=10
TimeoutStopSec=90
KillMode=process

[Install]
WantedBy=default.target

Why the flags matter:

  • --supervise — restarts with backoff, waits (instead of dying) while the app updates or another Orca serves the profile, and gives up cleanly after 6 failures in 15 minutes.
  • --no-pairing — no live offer in the journal. Pairing is a manual step (§3).
  • KillMode=process — stopping the service stops the server but leaves the terminal daemon and your terminals alive.

5. Verify

orca-ide serve service status
systemctl --user status 'orca-serve-*.service' --no-pager
journalctl --user -u 'orca-serve-*.service' -n 50 --no-pager
ss -tlnp | grep 6768
orca-ide status

Expect: unit enabled + active (running), runtimeState: ready, runtimeReachable: true. There will be no pairing link in the log — by design.


6. Reboot survival

Requirement Status
loginctl enable-linger USERNAME already yes (persists across boots)
unit enabled in default.target done by the installer
loginctl show-user USERNAME --property=Linger --value
systemctl --user is-enabled 'orca-serve-*.service'

With lingering on, the user manager starts at boot without anyone logging in, so the server comes up on its own. Verify for real with a reboot, then re-run the checks in §5.

What survives vs. what doesn't:

  • Survives: the server, pairings, terminal journal, orchestration DB.
  • Does not survive: live processes inside terminals. Orca restores sessions from its journal, but large restores are throttled — agents may come back asleep and resume when you open them. orca-ide serve restore resume clears a paused restore.

Reboot gotchas:

  • Give-up brake is on disk at ~/.orca/serve-supervisor-brake.json, keyed by build. Once the supervisor gives up, a reboot will not retry — the unit exits 0 immediately. Fix the cause, re-run orca-ide serve service install (that clears the brake), or orca-ide serve --supervise --force once outside the service. serve service status reports gaveUp.
  • systemd's own limit (5 starts / 900s): systemctl --user reset-failed before it will try again.
  • The unit has no After=network-online.target. Fine today (binds loopback, no pairing offer). Add ordering if you ever depend on Tailscale being up at boot.

Multiple devices

Yes — multiple devices can be paired, and this profile already has five:

Scope Name
runtime CLI 21/10/2026
runtime CLI 22/10/2026
runtime CLI 25/10/2026
mobile Mobile 21/10/2026 via machine-name
mobile Mobile 21/10/2026 via machine-name

Details worth knowing:

  • Each device gets its own deviceId and token, tracked in ~/.orca/orca-devices.json. No device cap is enforced in this build.
  • runtime scope = the desktop/CLI client; mobile scope = phone. A mobile device records the parentDeviceId of the runtime device that invited it.
  • Offsets of the scale: offers are single-device. Pair each device from its own foreground orca-ide serve run (or --mobile-pairing for a phone), or mint more offers from a desktop app that is already paired.
  • Manage/revoke from the desktop app's device list. Hand-editing orca-devices.json only takes effect with the server stopped, and is easy to get wrong — prefer the app.

Troubleshooting

Symptom Cause Fix
serve exits 3 another Orca serves this profile stop it (§2), check ss -tlnp | grep 6768
orca-ide status says not running but the service is up wrong profile export ORCA_USER_DATA_PATH=/home/USERNAME/.orca
service active, then immediately inactive supervisor gave up orca-ide serve service status; re-run serve service install
start request repeated too quickly systemd start limit systemctl --user reset-failed 'orca-serve-*.service'
pairing link rejected / expired offer is short-lived and single-use re-run orca-ide serve, mint a fresh one
port 6768 already in use stale server or another profile ss -tlnp | grep 6768, stop the owner
desktop app shows an empty workspace it opened on ~/.config/orca launch with ORCA_USER_DATA_PATH=/home/USERNAME/.orca orca-ide

Rollback

orca-ide serve service uninstall      # stops it, removes the unit; daemon + terminals stay

Then, if you want the old headless runtime back, start orcad manually (it is not supervised and will not survive a reboot).


Quick reference

export ORCA_USER_DATA_PATH=/home/USERNAME/.orca

orca-ide serve                        # foreground server, prints pairing link
orca-ide serve --mobile-pairing       # phone QR / link
orca-ide serve service install        # install + enable + start the unit
orca-ide serve service status         # is it installed / live / gave up?
orca-ide serve service uninstall      # stop + remove
orca-ide serve restore resume         # un-pause throttled session restores
orca-ide status                       # runtime reachability for this profile