# CLI reference

> Every systemone command and option, the environment variables it reads, exit codes, and recipes for scripts, CI and AI coding agents.

Source: https://dev.systemonemodels.tech/docs/cli

Install with `pip install systemonemodels` (Python 3.10+). It provides the
`systemone` command and the `systemone` Python package. Source:
[systemonemodels/systemonemodels-sdk](https://github.com/systemonemodels/systemonemodels-sdk).

Model references are always `namespace/name`, for example
`biplov/snake-balanced-multilingual`. Versions are immutable strings such as
`0.1.0`; `latest` means the newest published version.

## Configuration

| Variable | Meaning |
| --- | --- |
| `SYSTEMONE_TOKEN` | Access token (`s1_pat_…`). Takes precedence over a stored login. An empty value is ignored. |
| `SYSTEMONE_ENDPOINT` | API base URL. Defaults to `https://api.systemonemodels.tech`. |
| `SYSTEMONE_HOME` | Directory holding the stored login (`config.json`, mode `0600`). |
| `SYSTEMONE_CACHE` | Directory for downloaded files. Defaults to `~/.cache/systemone`. |

Every command exits `0` on success and `1` on an error it can explain,
printing one line that starts with `error` to stderr — including when the
registry cannot be reached. Wrong or missing arguments exit `2` with a usage
message.

## systemone login

Signs in and stores a token.

| Option | Meaning |
| --- | --- |
| *(none)* | Browser login: prints a one-time code and opens `/device` for a person to approve. Needs a terminal. |
| `--no-browser` | Same, but only prints the address — for SSH sessions. |
| `--token TEXT` | Store this token instead. Non-interactive. |
| `--paste` | Prompt for a token with hidden input. |
| `--endpoint URL` | Use another registry, and remember it. |

Tokens created by browser login are named after the machine and can be revoked
at [Settings → Access tokens](https://dev.systemonemodels.tech/settings/tokens).

## systemone logout, whoami, version

`logout` revokes the stored token on the registry and forgets the login,
registry address included, so the next `login` goes to the default registry
unless given `--endpoint`. A token given in `SYSTEMONE_TOKEN` is never touched.
(Before 0.2.1, `logout` only forgot the token and left it valid.) `whoami`
prints the account the token belongs to. `version` prints the client version.

## systemone search [QUERY]

| Option | Meaning |
| --- | --- |
| `--capability` | `choice`, `score`, `rank`, `classify`, `extract` or `route` |
| `--architecture` | e.g. `laya`, `jev` |
| `--license` | e.g. `apache-2.0` |
| `--sort` | `relevance` (default), `recent`, `stars`, `downloads`, `accuracy`, `latency` |
| `--limit` | Default 20 |

```bash
systemone search routing --capability route --sort latency
```

## systemone show REPO

Prints a model's metadata: architecture, capabilities, licence, evaluation
numbers (accuracy, calibration error, latency) and downloads.

## systemone pull REPO

| Option | Meaning |
| --- | --- |
| `--version TEXT` | Defaults to the latest. |
| `--variant TEXT` | Only this top-level folder, e.g. `onnx-int8`. |
| `--dest, -d PATH` | Link the files into this folder. Without it, prints the cache path. |

Files are verified against their SHA-256 and cached by content, so a second pull
downloads nothing and files shared between variants are stored once.

```bash
systemone pull biplov/snake-balanced-multilingual --variant onnx-int8 --dest ./snake
```

## systemone push [SOURCE]

Publishes models from a folder, the current one by default. If SOURCE holds
weights itself, it is the model; otherwise every model underneath is listed and
you choose which to publish. Variants of one model — a checkpoint and its
exports — become one version of one repository, a folder each. Repositories
that do not exist are created.

| Option | Meaning |
| --- | --- |
| `--repo, -r TEXT` | `namespace/name` for one model. Default: your namespace and the model's name. |
| `--namespace, -n TEXT` | Publish under this organization. |
| `--version TEXT` | Default: the next minor after the latest, from `0.1.0`. Versions are immutable. |
| `--variant TEXT` | Put one model's files under this folder, e.g. `coreml-int8`. |
| `--manifest PATH` | Use this `systemone.yaml` instead of inferring one. |
| `--readme PATH` | The model card. Default: the model's `README.md`, else one generated from its evaluation. |
| `--license TEXT` | Default: the model card's front matter, else `apache-2.0`. |
| `--notes TEXT` | Release notes. |
| `--private` | Create new repositories private. |
| `--all` | Publish every model found, without asking which. |
| `--yes, -y` | Do not ask for confirmation. |
| `--dry-run` | Print the manifests, model cards and files, and stop. |

A model folder directly holds `model.onnx`, `model.safetensors`, a `.gguf`
file or a `.mlpackage`; datasets, virtual environments and caches are never
searched. In a terminal, `push` asks before publishing unless the folder was
named with `--repo` or `--yes` is passed. Without a terminal it never prompts:
pass the model's own folder, or `--all`. Files the registry already holds are not uploaded again.
Publishing requires a verified email address.

## systemone create REPO, validate MANIFEST

`create` makes an empty repository (`--private` to hide it). `validate`
checks a `systemone.yaml` with the same rules the registry applies on publish.

## systemone cache info | clear

`info` prints where the cache is and how much it holds. `clear` empties it;
`--yes` skips the confirmation.

## Python

```python
from systemone import Client, snapshot_download

path = snapshot_download("biplov/snake-balanced-multilingual", variant="onnx-int8")

with Client() as registry:  # reads the same configuration as the CLI
    results = registry.search("routing", capability="route")
    model = registry.model("biplov/snake-balanced-multilingual")
```

Errors derive from `systemone.SystemOneError`: `AuthError`, `NotFound`,
`ApiError` (with `status`, `code` and `errors`), `ConnectionFailed`,
`LoginFailed` and `ChecksumMismatch`.

## For scripts, CI and AI coding agents

Browser login needs a person to approve it, so automated callers should use a
token and never prompt:

1. A person creates a token once at [Settings → Access tokens](https://dev.systemonemodels.tech/settings/tokens)
   (read for pulling, write for publishing).
2. Provide it as `SYSTEMONE_TOKEN` — no `login` step is needed.
3. Check access with `systemone whoami` before doing anything else.

```bash
export SYSTEMONE_TOKEN=s1_pat_...
systemone whoami
systemone search "ticket routing" --capability route --limit 5
systemone pull acme/support-router --variant onnx-int8 --dest ./model
systemone push ./exports/router --repo acme/support-router --dry-run
systemone push ./exports/router --repo acme/support-router
```

Always `--dry-run` a push first. Leave `--version` out and `push` picks the
next free version; a published version can never be replaced. Anything the CLI does can also be done over
[the HTTP API](https://dev.systemonemodels.tech/docs/api).
