Orca IDE server setup
Orca IDE server setup
Written 2026-10-25Tested against Orca 1.4.238.
(orcad
The two things that make this non-obvious
0.1. The CLI defaults to the wrong profile.
There are two profiles0) on thisDebian box:13. Updated 2026-10-28.
~/.orca | , not the |
~/.config/orca | . orca-ide ORCA_USER_DATA_PATH |
orca-ide status reports "not running" while theempty server is running, because it
looks in ~/.config/orca. Everyand commandyou belowget thereforeorcad_instance_lock_held pinserrors.
orca-ide serve gets paused when run in a terminal. It starts bash -ilc to read your environment, and that shell grabs the exportso ORCA_USER_DATA_PATH=/home/USERNAME/.orcathe whole Addjob thatends line toup .~/Stoppedbashrc kill -CONT ifdoesn't youhelp. wantAlways run it permanent.
with setsid (see step 2).
orca-ide, not orca. /usr/bin/orca is the GNOME screen Pair IDE.a ~/.local/bin/orcanew shadowsphone it(service today,already butrunning)
Stop the orderingservice, isrun fragile.a Alwayspairing useserver, scan orca-ide(→the QR, /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 andthen start atthe boot.service again.
1. Look before touching
export ORCA_USER_DATA_PATH=/home/USERNAME/.orca
orca-ide status # expect:1. appRunning: true, pid <orcad pid>
ps aux | grep -i orca | grep -v grep
ss -tlnp | grep -E '6768|44267'Stop
systemctl --user list-unitsstop 'orca-serve-*.service'
# 2. Pair
setsid nohup orca-ide serve --all | grepmobile-pairing -i-pairing-address 100.64.0.4 \
</dev/null >/tmp/orca-serve.log 2>&1 &
sleep 15; cat /tmp/orca-serve.log
Scan the QR with the Orca app, or open the orca://pair?code=... link on the phone. Once the phone shows it's connected:
# 3. Start
pkill -f 'cli/index.js serve'
systemctl --user start orca-serve-3eba5288.service
systemctl --user is-active orca-serve-3eba5288.service # should print: active
The phone stays paired after the switch back. If cat shows no QR yet, wait a few seconds and run it again.
1. One-time: set the profile path
Put this at the top of ~/.bashrc, above the case $- in ... return block. If it sits below that block, non-interactive SSH sessions (the Orca desktop app) never see it:
export ORCA_USER_DATA_PATH="${ORCA_USER_DATA_PATH:-$HOME/.orca}"
Check it from another machine:
ssh conor@cbfarm 'echo $ORCA_USER_DATA_PATH' # should print /home/conor/.orca
2. Pair a device
WhatThe wasservice runningruns at the time of writing:with orcad (pid 54008) serving
, 127.0.0.1:6768--no-pairingitsso Electronto web-UIpair childyou onstop 0.0.0.0:44267,it and tworun terminala daemonspairing inserver orca-daemon-*.scope.by 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.hand.
systemctl --user stop 'app-orca-serve-*.scope'
systemctl --user stop 'orca-daemon-*.scope'
pgrep -f 'orcad\.js --json' | head -1 | xargs -r kill # the headless runtime wrapperservice'
pkill -f 'orca-idecli/index.js --serve' || true # webany UI,leftover ifmanual stillserver
alive# Phone 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 thisbeforeinstalling(use theserviceTailscale—IPafterwards it would kill your new server too (the service unit isorca-serve-*.service, butorca-daemon-*.scopeis shared).
3. Pair your devices (do this before installing)
Why a foreground run instead ofso 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 offerphone can onlyreach beit)
mintedsetsid bynohup 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 --pairing-address 100.64.0.4 \
</dev/null >/tmp/orca-serve.log 2>&1 &
sleep 15; cat /tmp/orca-serve.log # printsscan athe QRQR, or open the orca:/ mobile/pair?code=... link
WhenFor donea pairing,desktop or CLI client, leave out .Ctrl-C--mobile-pairing
- Each offer pairs one device and expires quickly. For the
offernextcarriesdevice,thisrunprofile'spkillE2EE-fhost'cli/index.jspublic key (~/.orca/orca-e2ee-keypair.jsonserve'),andclientsstartpinitthatagain. - Pairings
sopersist across restarts andrebootsreboots.
3. requireHand re-pairing.back to the service
pkill -f 'cli/index.js serve'
orca-ide serve service install # writes the unit, enables it, starts it
CheckThis whocreates ~/.config/systemd/user/orca-serve-<hash>.service, which runs orca-ide serve --supervise --no-pairing with ORCA_USER_DATA_PATH set. Linger is pairedalready on (loginctl show-user conor --property=Linger), so it starts at anyboot timewithout (read-only,anyone logging in.
4. Check it
orca-ide serve service status
ss -tlnp | grep 6768 # orcad listening on 0.0.0.0:6768
pgrep -af orcad-server.js # exactly one, running from ~/.orca
ls ~/.config/orca 2>/dev/null || echo "good, no tokensstray printed):profile"
List paired devices:
python3 -c "
import jsonjson; for d in json.load(open('/home/USERNAME/.orca/orca-devices.json')):
[print(d['scope'].ljust(8), d['name'].ljust(45), d['deviceId']) for d in json.load(open('$HOME/.orca/orca-devices.json'))]"
Troubleshooting
4.
| Symptom | Fix |
|---|---|
[1]+ Stopped orca-ide serve ... |
It was run in a terminal. Kill it with kill -9 -- -<pid> and use the setsid command from step 2 |
orcad_instance_lock_held |
Another server owns the profile. Stop the service or |
Error mentions ~/.config/orca |
ORCA_USER_DATA_PATH isn't set in that shell. Run rm -rf ~/.config/orca and fix step 1 |
| Desktop over SSH shows an empty workspace | Same cause: the export is below the interactive check in ~/.bashrc |
| Service starts then immediately stops | The supervisor gave up. Check orca-ide serve service serve service install again |
start request repeated too quickly |
systemctl --user reset-failed 'orca-serve-*.service' |
| Pairing link rejected | The
|
5.Quick Verifyreference
orca-ide serve service status | install | uninstall
systemctl --user statusstop|start '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
| |
|
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 resumeclears a paused restore.
Reboot gotchas:
Give-up brake is on diskat~/.orca/serve-supervisor-brake.json, keyed by build. Once the supervisor gives up, a reboot willnotretry — the unit exits 0 immediately. Fix the cause, re-runorca-ide serve service install(that clears the brake), ororca-ide serve --supervise --forceonce outside the service.serve service statusreportsgaveUp.systemd's own limit(5starts /900s):systemctl --user reset-failedbefore it will try again.The unit has noAfter=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:
Details worth knowing:
Each device gets itsowndeviceIdand token, tracked in~/.orca/orca-devices.json. No device cap is enforced in this build.runtimescope = the desktop/CLI client;mobilescope = phone. A mobile device records theparentDeviceIdof the runtime device that invited it.Offsets of the scale: offers are single-device. Pair each device from its own foregroundorca-ide serverun (or--mobile-pairingfor a phone), or mint more offers from a desktop app that is already paired.Manage/revoke from the desktop app's device list. Hand-editingorca-devices.jsononly takes effect with the server stopped, and is easy to get wrong — prefer the app.
Troubleshooting
| | |
| | |
| ||
| | |
| ||
| ||
| |
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-ideafter statusa # runtime reachability for this profilereboot