Skip to main content

Orca IDE server setup

Orca IDE server setup

Written 2026-10-25Tested against Orca 1.4.238.

243
(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.

Gotchas

  • The
  • live , .
    PathWhat itprofile is
    ~/.orcanot the livedefault one — paired devices, agent-session journal, terminal history, chat scratch (~18 MB)
    ~/.config/orca Electron'sEvery defaultorca-ide profile;command createdmust 25/10have 07:15,ORCA_USER_DATA_PATH containsset. onlyOtherwise it quietly starts a 155second, MB orcad-artifacts download

    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 profile:

    terminal,
    exportso ORCA_USER_DATA_PATH=/home/USERNAME/.orcathe 
    whole

    Addjob thatends line toup ~/Stopped.bashrc kill -CONT ifdoesn't youhelp. wantAlways run it permanent.

    detached

    with setsid (see step 2).

  • 2.Use orca-ide, not orca. /usr/bin/orca is the GNOME screen reader,reader.
  • not Orca

    Pair IDE.a ~/.local/bin/orcanew shadowsphone it(service today,already butrunning)

    Stop the orderingservice, isrun fragile.a Alwayspairing useserver, orca-idescan (→the /home/USERNAME/.local/bin/orca-ideQR, → /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-pairing, itsso 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 this before installing(use the serviceTailscale —IP 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 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.

    Pairing
      persists:
    • Each offer pairs one device and expires quickly. For the offernext carriesdevice, thisrun profile'spkill E2EE-f host'cli/index.js public key (~/.orca/orca-e2ee-keypair.jsonserve'), and clientsstart pinit thatagain.
    • key,
    • Pairings sopersist across restarts and rebootsreboots.
    • do
    not

    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.Install

    (§3).
  • KillMode=process
  • — stopping the service stops the server but leaves the terminal daemon and your terminals alive.
    SymptomFix
    [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_heldAnother server owns the profile. Stop the service
    or pkill -f 'cli/index.js serve'
    Error mentions ~/.config/orcaORCA_USER_DATA_PATH isn't set in that shell. Run rm -rf ~/.config/orca and fix step 1
    Desktop over SSH shows an empty workspaceSame cause: the export is below the interactive check in ~/.bashrc
    Service starts then immediately stopsThe supervisor gave up. Check orca-ide serve service installstatus --dry-and run # prints the unit, writes nothing orca-ide serve service install again
    start request repeated too quickly systemctl --user reset-failed 'orca-serve-*.service'
    Pairing link rejectedThe installoffer writesexpired. this unit, then runs daemon-reload, enable and restart — i.e.Restart 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=Orcapairing 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 isfor a manualfresh stepone

    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

    RequirementStatus
    loginctl enable-linger USERNAMEalready yes (persists across boots)
    unit enabled in default.targetdone 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:

    ScopeName
    runtimeCLI 21/10/2026
    runtimeCLI 22/10/2026
    runtimeCLI 25/10/2026
    mobileMobile 21/10/2026 via machine-name
    mobileMobile 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

    SymptomCauseFix
    serve exits 3another Orca serves this profilestop it (§2), check ss -tlnp | grep 6768
    orca-ide status says not running but the service is upwrong profileexport ORCA_USER_DATA_PATH=/home/USERNAME/.orca
    service active, then immediately inactivesupervisor gave uporca-ide serve service status; re-run serve service install
    start request repeated too quicklysystemd start limitsystemctl --user reset-failed 'orca-serve-*.service'
    pairing link rejected / expiredoffer is short-lived and single-usere-run orca-ide serve, mint a fresh one
    port 6768 already in usestale server or another profiless -tlnp | grep 6768, stop the owner
    desktop app shows an empty workspaceit opened on ~/.config/orcalaunch 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-ideafter statusa # runtime reachability for this profilereboot