Install on Linux
The qorin-agent on Linux runs as a systemd service. In the system (multi-user) mode it carries CAP_SETUID + CAP_SETGID so it can drop privileges to the requesting Qorin user before spawning any CLI — the same per-user isolation model as macOS, with native Linux primitives.
Requirements
- A modern Linux (kernel ≥ 5.4, systemd ≥ 245). Tested on Ubuntu 22.04, Debian 12, Fedora 39, Arch.
- A CLI coding agent installed and authenticated for the OS user that will run workspaces — at least one of
claude,codex,cursor-agent,gemini,opencode. sudo. There is no user-mode install: the agent is a system service, and both the installer andqorin-agent service installrequire root.
1. One command
curl -fsSL https://dl.qorin.dev/install.sh | sudo shThat is the whole install. The script:
- downloads
qorin-agent-linux-amd64/-arm64, verifies it againstdl.qorin.dev/SHA256SUMS, and puts it in/usr/local/bin; - signs this machine in to your Qorin account — it opens the browser, or prints a link to open elsewhere when there is no desktop (SSH, headless; see below);
- writes
/etc/systemd/system/qorin-agent.servicewithAmbientCapabilities=CAP_SETUID CAP_SETGID, enables and starts it, and checks that it is actually running before it says so.
It prints what it is about to do before the first privileged action; QORIN_DRY_RUN=1 prints the plan and stops.
| Binary | /usr/local/bin/qorin-agent |
| Service | systemd unit, starts at boot, survives logout |
| Runs as | root — it drops to each person's own UNIX user for their work |
| Needs sudo | yes — the installer re-runs itself under sudo if you forget |
Why not ~/.local/bin | the service runs as root, and a home directory is neither readable by root nor stable across users |
Root is required, and there is no lesser mode
There used to be a systemd --user install that ran without root. It is gone (ADR-022): a per-user agent is a Qorin presence the machine's owner never authorised, and a machine you cannot see you cannot control. One machine now runs exactly one agent, owned by whoever controls the machine.
It also removes a whole class of "it stopped overnight": a --user unit dies at logout unless you remember loginctl enable-linger. A system unit is started by PID 1 and survives by construction.
If you already have a --user unit, the root install removes it for you.
From the dashboard: the same command, with your token
Agents → Connect an agent in the dashboard (web, phone or Mac) shows the same command carrying a one-shot token:
curl -fsSL https://dl.qorin.dev/install.sh | sudo sh -s -- --token <token>Same script, same three steps — except step 2 needs no browser: the token registers the machine with the organisation you were signed in to when you copied it. Tokens last 15 minutes and work once.
Already installed the binary some other way?
Then only the connect-and-run half is missing — and it is one command too:
sudo qorin-agent install # sign in in the browser, then service
sudo qorin-agent enroll <token> # or: with a token from the dashboardBoth refuse to run on a machine that is already connected — that machine belongs to an organisation, and moving it would cut its workspaces off from their owners. To add yourself to a connected machine, see Users & identity below; to move it, sudo qorin-agent logout first.
Just trying it out
qorin-agent serve # foreground; stops when you close the terminalVerify
The dashboard sidebar should list the host as online. If not:
qorin-agent doctor # what the agent itself can see
sudo journalctl -u qorin-agent -n 50 # the service's own log… or see troubleshooting › Agent shows offline.
Users & identity — what counts is who logs in
Installing the daemon (root) and who you are are two separate things. Your identity on a host = the UNIX user who ran the command — so a workspace runs as that user (via setuid from the daemon), with their $HOME, dotfiles, and CLI auth:
sudo qorin-agent installfrom your account → you're mapped to your user (sudo's$SUDO_USER), not root.- run it as root (no sudo) → you're mapped to root (this only works if
claude/codex/… are installed and authenticated for root).
That mapping is created automatically when you log in/enroll — no separate dashboard step. The first workspace just works.
Adding more people (self-service)
Il primo login è diverso da tutti gli altri, ed è l'unico che vuole sudo:
| chi | comando | cosa fa |
|---|---|---|
| chi installa, una volta | sudo qorin-agent login | registra la macchina su Qorin |
| chiunque altro, sempre | qorin-agent login | si registra per sé, subito operativo |
sudo serve perché registrare la macchina significa scrivere le credenziali del servizio e avviare un daemon di sistema: è un atto di amministrazione della macchina, non un'identità. Chi lo esegue non viene registrato come root — Qorin legge SUDO_USER, quindi resta mappato al proprio utente e i suoi workspace girano come lui.
Linux is the canonical multi-user target. Once the machine is enrolled, adding a teammate takes one command and one click:
- Make sure their UNIX user exists on the host (
useradd alice— Qorin doesn't create OS users for you). - The teammate runs this on the host, as their own UNIX user — no
sudo, no token to pass around:shThe agent already knows which machine it is, soqorin-agent loginloginon a machine that's connected means "let me use this one", not "enrol it again". That's it — no approval step. Every workspacealicespawns runs asalice, and she appears in the dashboard under the agent's People, where an admin can suspend or remove her at any time.
Why no approval?
Because it wouldn't protect anything. alice already has a shell on that machine as alice: she can open her files and run claude or codex by hand in the same directory. Qorin isn't granting her access — it's making the access she already has comfortable to use. A gate that stops the convenient path and not the actual one is friction, not security.
What the gate does protect is the machine's enrolment, which needs root, and the ability to keep someone out afterwards — the People list, where suspending takes two seconds.
Plans follow the person, not the machine. Someone from another organization can work on your host, and their own subscription decides what they get (concurrent workspaces, worktree mode, zero-knowledge). An organization in Qorin is a billing and licensing unit, not a fence around a machine.
Agents older than build 41 don't publish their identity yet, so login there still refuses and asks for a token. Host owner → Manage users → Generate a join command instead, then the teammate runs it on the host:
qorin-agent join TOKENUpgrading the agent (sudo qorin-agent upgrade) removes the step.
(You can still map someone by hand in Manage users — type their Qorin member + UNIX username. Mapping to root is allowed but warned.) The per-user setuid requires the system service (it needs root/CAP_SETUID).
Projects outside $HOME (e.g. /var/www)
The folder picker shows each user's $HOME by default — so the UI can't wander into /etc, other users' homes, etc. On servers, projects often live outside home (/var/www, /opt, /srv). Expose extra browsable roots from the dashboard — no SSH needed:
- Hover the host in the sidebar → click the 📁 (browse roots) button.
- Add an absolute directory (e.g.
/var/www) → Save.
The picker then shows Home / /var/www / … as quick-jump chips. Only the account owner can change this list. It's empty by default, so it never weakens the per-user isolation default.
Browsing — and creating folders — runs as the requesting UNIX user (the same setuid mapping used to spawn the CLI), so what's actually reachable is bounded by that user's permissions. System paths (/, /etc, /root, /proc, …) are always blocked, regardless of configuration. Make sure the spawn user can read/write the folder you intend to work in.
Headless fallback (QORIN_EXTRA_ROOTS)
For unattended setups you can also pin roots host-locally via an env var (:-separated absolute dirs) — these layer under the dashboard config:
sudo systemctl edit qorin-agent
# add under [Service]:
# Environment=QORIN_EXTRA_ROOTS=/var/www:/opt
sudo systemctl restart qorin-agentHeadless / VPS install
The flow above works on a remote VPS with no display:
- Add
--no-browserto the install/login command and it prints the URL to copy into your local browser; it polls and waits. - CLI auth (
claude login, etc.) often opens a browser too — SSH-tunnel back to your laptop if needed and run the login from the VPS terminal; the CLI prints a URL you open locally.
Update
qorin-agent upgrade # or click Update on the host in the dashboardUninstall
qorin-agent uninstall # leave + revoke, keep the binary
sudo qorin-agent uninstall --purge # complete removal (binary, data, logs, service user)Next: Add your first host →