The Qoren command line

Install the Qoren CLI, sign in from your terminal, and drive environments, agents and jobs from scripts and CI with JSON output and clear exit codes.

On this page

qoren does from a terminal what the console does in a browser: create environments, deploy and message agents, read logs, and check what you are spending. Use it when you want to script your fleet, run it from CI, or simply stay in the terminal you already have open.

Every client goes through Qoren's proxyThe console, the qoren CLI and the @qoren/sdk package all call Qoren's proxy at qoren.sh/api/mg. The proxy checks who is calling, applies your plan's entitlements and records an audit trail, then passes the call to Qoren's API, which manages your environments.Consolebrowser sessionCLIqoren, qrn_ tokenSDK@qoren/sdkQoren proxyqoren.sh/api/mgwho is callingplan entitlementsaudit trailQoren APIcontrol planeYourenvironmentsAtlasJunoNo client calls Qoren's API directly.
The CLI, the SDK and the console all reach your environments through the same Qoren API, with the same account and plan limits.

The CLI is not a side door. It sends every request through the same gate the console uses, which checks who you are and what your plan allows. So it can do exactly what your account can do in a browser, and nothing more. For the full list of commands and flags, see the Qoren CLI command reference.

Before you start#

  • Node.js 20 or newer.
  • A Qoren account on a plan that includes API access: Ultimate, Business or Enterprise (a free trial of one of them counts). The CLI signs in with an access token, and tokens are API access, so on Starter, Pro or with no plan every command is refused and exits with code 4. The web console works on every plan. See plans and the free trial.

Install the CLI#

npm install -g @qoren/cli
qoren --version

The package puts one command on your path: qoren.

Sign in#

  1. Run qoren login. Your browser opens a Qoren page titled Connect the Qoren CLI. If it does not open, the terminal prints the link to visit.
  2. Check the page. It shows who you are Signing in as, the Token name, and the local address it is Returning to.
  3. Click Authorize. Nothing is granted until you do. If your plan does not include API access, the page says so instead and links to an upgrade.
  4. Back in the terminal, the CLI checks that the new token works, stores it, and prints who you are signed in as.

The CLI waits up to five minutes for you to approve. If you take longer, run qoren login again. The token it creates shows up in the console under Settings, CLI tokens, named cli unless you choose a name:

qoren login --name laptop

On a computer with no browser, create a token in the console instead (see create and revoke access tokens) and paste it. The prompt does not echo what you type:

qoren login --token

Check who you are signed in as#

qoren whoami

It prints the profile, the server, your account, your organization, where the credential came from (the config file or QOREN_TOKEN) with the first characters of the token, and whether the server accepted it. If the token is fine but your plan does not include API access, the status says so and names the plans that do. The token itself is never printed, so the output is safe to paste into a bug report.

Sign out#

qoren logout          # forget the current profile
qoren logout --all    # forget every profile on this computer

Signing out only deletes the copy on this computer. The token still works until you revoke it under Settings, CLI tokens.

Use more than one login#

Each login is stored as a named profile, so you can keep several side by side and pick one per command:

qoren login --profile work
qoren env ls --profile work
QOREN_PROFILE=work qoren env ls

The most recent login becomes the default.

Use interactive mode#

Run qoren with nothing after it and it opens full screen: your environments, agents, jobs, a chat pane and your account, all on the keyboard. qoren tui does the same thing explicitly.

KeyWhat it does
tab, shift+tabNext or previous section
1 to 5Jump to Environments, Agents, Jobs, Chat or Account
arrow keys, j, kMove within a list
enterOpen what is selected
rRefresh
?Every key for the section you are in
q or ctrl+cQuit

Two things it does that a single command cannot. When you message an agent, the reply streams in as the agent writes it, naming the tool it is running. And when a region cannot run the size you asked for, it offers you the closest region that can, instead of telling you which flag to add.

Interactive mode uses the same account and the same plan limits as the commands. Anything it cannot do yet, the commands still can.

Read output in a script#

Every command takes --json. In that mode stdout carries only the result, as JSON. Progress, notes and warnings go to stderr, so piping into another tool is always safe, even for commands that follow a long job.

qoren env ls --json | jq -r '.[].name'
qoren agent ls --json | jq -r '.[] | select(.status != "running") | ._id'

Errors are structured in --json mode too, written to stderr:

{
  "error": "No active subscription.",
  "detail": null
}

When the server sent a structured refusal, detail carries it. A plan without API access, for example:

{
  "error": "Your Pro plan does not include API access. It is included on the Ultimate, Business and Enterprise plans. Personal access tokens, the CLI and the SDK need one of them: upgrade at https://qoren.sh/pricing. The web console keeps working on every plan.",
  "detail": {
    "code": "api_access_required",
    "plan": "pro",
    "plans": ["Ultimate", "Business", "Enterprise"],
    "upgradeUrl": "https://qoren.sh/pricing"
  }
}

Colour switches off by itself when output is not a terminal, and with --no-color or the NO_COLOR variable.

Exit codes#

CodeMeaningWhat to do
0SuccessNothing
1The request failedRead the error message; it came from the server
2The command was typed wrongCheck the arguments and flags with --help
3Not signed in, or the credential was refusedRun qoren login, or check QOREN_TOKEN
4The plan does not allow this: no active plan, or a plan without API accessChoose or upgrade a plan in the console, then run it again

Keeping 3 and 4 apart from 1 lets a CI job tell "my token was revoked" from "that environment does not exist" from "the plan does not cover this". Two commands also exit 1 on their own result: qoren agent exec when the command it ran exits non-zero, and qoren agent doctor when the checkup needs attention or fails.

Follow long-running work#

Creating an environment, deploying an agent, resizing, removing and messaging are all jobs: the server answers straight away with a job id and does the work in steps. By default the CLI follows the job and prints one line for each step as it starts, so a deploy that takes minutes shows where it has got to. If the connection drops for a moment, it prints reconnecting… once and keeps waiting.

To get the job id back immediately instead, add --no-wait, then follow the job later:

JOB=$(qoren env create --name staging --size s-1vcpu-2gb-70gb-intel --no-wait --json | jq -r .jobId)
qoren jobs watch "$JOB"

qoren jobs ls lists recent jobs with how many steps are done, qoren jobs get <id> prints every step and the error if one failed, and qoren jobs cancel <id> asks a running job to stop (a step already running finishes first).

Choose a size and a region#

--size takes the size's slug, the value in the slug column of qoren account options. Today the four plan sizes are:

SizeSlug
Lights-1vcpu-2gb-70gb-intel
Standards-2vcpu-2gb-90gb-intel
Heavys-2vcpu-4gb-120gb-intel
Maxs-4vcpu-8gb-240gb-intel

Your plan sets the largest size you may use. See environment sizes for how many agents each one holds and what it costs.

Leave --region off and the platform picks a region that can run the size you asked for. Name a region and it is pinned: a region you chose is never swapped for another. If it cannot run that size, the create is refused, and the message names the closest region that can plus the sizes your region does have. Run the command again with --auto-region to accept the suggested region, or with one of the listed sizes.

qoren env resize is refused the same way when the environment's region cannot run the new size. An environment cannot change region, so pick one of the sizes the message lists. Resizing only goes up, and it restarts the environment, so its agents are unreachable while it runs.

Set environment variables#

VariableEffect
QOREN_TOKENThe token to use. The config file is not read at all
QOREN_API_URLThe server to talk to (default https://qoren.sh)
QOREN_PROFILEWhich stored login to use
XDG_CONFIG_HOMEWhere the config file lives
NO_COLORTurn colour off

When several apply, QOREN_TOKEN wins, then --api-url, then the named profile. Stored logins live in ~/.config/qoren/config.json (or $XDG_CONFIG_HOME/qoren/config.json), readable only by your user.

Run the CLI in CI#

Create a token for the pipeline under Settings, CLI tokens (see create and revoke access tokens), store it as a secret, and expose it as QOREN_TOKEN. It overrides any stored login, so a pipeline never picks up a developer's profile by accident.

- name: Deploy the agent
  env:
    QOREN_TOKEN: ${{ secrets.QOREN_TOKEN }}
  run: |
    npm install -g @qoren/cli
    qoren agent create --env "$ENV_ID" --template deploy-bot --name "Deploy bot" --json

Branch on the exit code when you need to:

qoren agent create --env "$ENV_ID" --template deploy-bot --name "Deploy bot"
case $? in
  0) echo "deployed" ;;
  3) echo "The Qoren token is missing, revoked or refused" ; exit 1 ;;
  4) echo "The Qoren plan does not cover this (no plan, or no API access)" ; exit 1 ;;
  *) echo "The deploy failed" ; exit 1 ;;
esac

Call an endpoint that has no command#

The CLI has commands for what people do most, not for every endpoint. qoren api reaches any other one with the same credential and the same rules, and prints the raw JSON answer:

qoren api GET fleetSummary
qoren api GET machines --query limit=5
qoren api POST agents --data @agent.json
cat agent.json | qoren api POST agents --data @-

The path is relative to the API root, so agents, not /api/mg/agents. To script in TypeScript instead of shell, use the Qoren SDK, which the CLI itself is built on.

Frequently asked questions#

Where is my token stored?

In ~/.config/qoren/config.json, or under $XDG_CONFIG_HOME/qoren when that is set, written so only your user can read it. It is a bearer token, so treat the file like a password. If you set QOREN_TOKEN, the file is not read at all.

How do I cut off a computer I no longer have?

Open Settings, CLI tokens in the console and revoke that token by name. Revoking does not touch your other tokens. Anything using the revoked token is refused within about 30 seconds.

Can the CLI do things the console cannot?

No. Both go through the same gate with the same account, so the CLI is bounded by exactly the same plan limits and permissions. Some operator-only endpoints are closed to both, and the CLI has no commands for them.

Which plans can use the CLI?

Ultimate, Business and Enterprise, which include API access. On Starter or Pro the console does everything the CLI does; upgrade on the pricing page to script it. A plan change reaches a token that is already in use within about 30 seconds.

Does it work in CI without a browser?

Yes. Create a token under Settings, CLI tokens, set it as QOREN_TOKEN, and add --json so the job can read the output. No login step or browser is involved.

Why does deploying an agent take minutes?

Deploying installs and configures the agent on its environment in a series of steps. The CLI prints each step as it starts, so you can see where it is. Add --no-wait if you would rather not watch.

Was this page helpful?

Last updated