---
title: Install the CLI
description: Install ops on your machine and sign it in with a device code.
order: 1
---

`ops` is the command line client. It talks to the same API as the console, so anything it
does is checked against your role and written to the audit log.

## Install with one line

Open your project in the console and go to **Develop**. Press **Copy** beside the install
line and paste it into a terminal:

```sh
curl -sSL --fail-with-body -H "Authorization: Bearer <code>" https://ops.syncronet.dev/api/v1/cli/install.sh | sh
```

The copied line carries a code that works once, within ten minutes. It installs the
current release for your machine, checks its checksum, and signs the machine in with your
role in that project. Nothing else is needed.

## Or log in by hand

If `ops` is already installed, or the copied line has expired, sign in with a device code:

```sh
ops login
```

`ops` prints a code and a link. Open the link in a browser where you are signed in to the
console, check that the code matches, pick the role the machine gets and, if you like, pin
it to one project. Then approve. The terminal prints who you are signed in as, and the
token is saved in `~/.config/ops/config.json`.

A token never carries more than you hold. Pin it with `--project` to keep a machine inside
one project:

```sh
ops login --project rungholt
```

## Choose a project

Most commands act in one project. Pick it once:

```sh
ops projects         # the projects you can see
ops use rungholt     # the one the other commands act in
ops whoami           # who this token acts as, and what it may do
```

## In CI

A pipeline needs no config file. Set the token and the project in its environment:

| variable | what it holds |
| --- | --- |
| `OPS_TOKEN` | a token minted in the console, see [Tokens](../develop/tokens.md) |
| `OPS_PROJECT` | the project slug |
| `OPS_API_URL` | another ops address, when yours is not the default |

## It keeps itself current

Any command may first update `ops` to the release ops serves, then run what you typed.
`ops update` updates now, and `ops update --check` only says whether there is a newer
release. Set `OPS_NO_UPDATE=1` to switch the automatic check off.

## Exit codes

| code | meaning |
| --- | --- |
| 0 | done |
| 1 | the command failed, and ops said why |
| 2 | the command was called wrongly. `ops help` lists the commands |
| 3 | no credential. Run `ops login` |
| 4 | refused. Your role does not allow it |
