# CLI

> Push, pull, and search artifacts from a terminal, a Dockerfile, or a CI step with afk

## Install

```sh
pip install "artefaktum[cli]"
```

This installs `artefaktum`, and the shorter alias `afk`, both pointing at the same command. It needs Python 3.10+, same as the SDK it wraps.

## Authenticate

```sh
artefaktum login            # or set ARTEFAKTUM_API_KEY in CI and sandboxes
```

`login` prompts for the key at a hidden prompt (or reads it from stdin with `--api-key-stdin`), verifies it against the server, then saves it to `~/.config/artefaktum/config.json` (`$XDG_CONFIG_HOME`, or `%APPDATA%\artefaktum` on Windows), mode `0600`. The key is never taken as a positional argument, so it never lands in shell history.

`logout` removes the saved config file.

For every setting (the API key, `--base-url`, `--project`), precedence is: the matching flag, then the matching environment variable (`ARTEFAKTUM_API_KEY`, `ARTEFAKTUM_BASE_URL`, `ARTEFAKTUM_PROJECT`), then the saved config file. In CI and sandboxes, prefer `ARTEFAKTUM_API_KEY` over `login` (no writable home directory needed) or `--api-key` (visible in `ps` to other users on the host).

`whoami` shows the tenant, and project if the key is scoped to one:

```sh
artefaktum whoami
```

API keys themselves are created in the console at https://artefaktum.dev/console/. The CLI has no `keys create` (or any `keys`/`usage` command); it only consumes a key that already exists.

## Commands

| Command | Purpose |
|---|---|
| `whoami` | show the tenant (and project) the key belongs to |
| `projects` | list the tenant's projects |
| `login` | verify an API key and save it |
| `logout` | remove the saved API key |
| `get` | show one artifact, by ID or `--key` |
| `ls` | list artifacts |
| `search` | search artifacts |
| `push` | upload a file as a new artifact |
| `pull` | download an artifact's latest version |
| `rm` | delete an artifact |
| `link` | print a short-lived signed download URL |
| `relations` | list an artifact's relations |
| `relate` | record a relation from one artifact to another |
| `versions` | list an artifact's versions |
| `resolve` | get-or-create an artifact by external key |
| `run new` | create a run |
| `run seal` | seal a run so no more artifacts attach to it |
| `run ls` | list a run's artifacts |

Global options, given before the command: `--api-key`, `--base-url`, `--project`, `--json` / `--table` (force the output format), plus `--version` and `-h`/`--help`. `artefaktum --help` and `artefaktum <command> --help` list every command and flag.

## Command reference

**`get ID`** / **`get --key KEY`**: show one artifact. Exactly one of `ID` or `--key EXTERNAL_KEY` is required.

**`ls`**: list artifacts. `--tag TAG`, `--status STATUS` (repeatable), `--limit N` (default 50), `--all` (follow every page instead of one).

**`search QUERY`**: `--mode hybrid|text|semantic|exact` (default `hybrid`), `--tag TAG` (repeatable, required tag), `--limit N` (default 10), `--history` (include superseded artifacts, excluded by default).

**`push FILE`**: `--title` (required), `--tag` (repeatable), `--description`, `--key EXTERNAL_KEY`, `--meta K=V` (repeatable), `--expires DURATION` (e.g. `30d`), `--run RUN_ID`, `--no-wait` (return once accepted, don't wait for `ready`), `--timeout SECONDS` (default 30).

Field sizes are limited; see [Limits](/docs/rest/#limits).

**`pull ID [DEST]`**: `DEST` defaults to `.`; a trailing `/` creates it as a directory. `--no-verify` skips the sha256 check.

**`rm ID`**: delete an artifact. No flags.

**`link ID`**: print a signed download URL. `--table` mode prints exactly the URL and nothing else.

**`relations ID`** / **`versions ID`**: list an artifact's relations or versions. No flags.

**`relate ID TARGET`**: `--type` (`derived_from` (default), `supersedes`, `attachment_of`, `generated_by`, or `related_to`).

**`resolve KEY`**: `--file` (required), `--title` (required), `--tag` (repeatable), `--description`, `--meta K=V` (repeatable), `--max-age DURATION` (an existing artifact older than this is treated as stale), `--wait SECONDS` (default 60, retried while another writer holds the reservation). Prints `hit` (nothing uploaded), `created` (uploaded `--file`), or exits `4` if still `pending` after `--wait`.

**`run new [RUN_ID]`**: `RUN_ID` is optional; the server assigns one if omitted.

**`run seal RUN_ID`** / **`run ls RUN_ID`**: `run ls` takes `--limit N` (default 50).

Duration flags (`--expires`, `--max-age`) accept `90s`, `30m`, `12h`, `30d`, `2w`, or a bare integer of seconds.

## Exit codes

| Code | Meaning |
|---|---|
| 0 | ok |
| 1 | API or SDK error |
| 2 | usage error |
| 3 | not found |
| 4 | `resolve` still pending when `--wait` ran out |
| 130 | interrupted |

## Recipes

**Dockerfile or sandbox image**: bake the CLI in and read the key from the environment at run time, never at build time.

```dockerfile
RUN pip install "artefaktum[cli]"
# ARTEFAKTUM_API_KEY is supplied by the container's runtime environment, not baked in
```

**GitHub Actions step:**

```yaml
- run: pip install "artefaktum[cli]"
- run: afk push report.pdf --title "Q3 churn" --tag churn
  env:
    ARTEFAKTUM_API_KEY: ${{ secrets.ARTEFAKTUM_API_KEY }}
```

**Push before a container is recycled**: an agent working in a sandbox or CI job that's about to be torn down should push its output as its last step, so the artifact outlives the container.

```sh
afk push /tmp/output.json --title "Run output" --run "$RUN_ID"
```

**Scripting with JSON**: output is an aligned text table on a terminal and one JSON document otherwise, so a plain pipe already gets JSON.

```sh
artefaktum ls | jq -r '.items[].id'          # one page
artefaktum ls --all | jq -r '.[].id'         # every match, as a bare array
```

Pass `--json` explicitly when the command's stdout might still look like a terminal to it (for example, inside another program that captures output), rather than relying on the auto-detection.

**Push only if it isn't already there**, without `resolve`:

```sh
artefaktum get --key vendor-x/report/2026-09 >/dev/null \
  || artefaktum push report.json --title "Vendor X report" --key vendor-x/report/2026-09
```
