# sparku CLI

> All sparku commands, their flags, token search order, and exit codes.

## Installation

Settings > Custom Integrations > "sparku" line > "Install…". Creates a symbolic link `/usr/local/bin/sparku` pointing to the utility inside `SparkU.app/Contents/Helpers/sparku`; the link updates with the app.

```bash
sparku version
sparku help
```

## Token

The token is searched in order until a non-empty value is found:

1. `--token <token>`
2. `--token-file <path>`
3. `SPARKU_TOKEN_<ADDRESS>` (address uppercase, hyphens → `_`)
4. `SPARKU_TOKEN`
5. `SPARKU_TOKEN_FILE` (path to file with token)

The socket address can be overridden by the `SPARKU_SOCKET` environment variable or the `--socket` flag (default `~/.sparku/run/api.sock`).

> [!NOTE]
> SparkU unavailability is checked **before** token check: `sparku push … || [ $?
> -eq 69 ]` in a script reliably catches "SparkU not running", even if the token is also not configured.

## push

Writes fields (upsert — partial update, old values of undeclared keys are left alone).

```
sparku push <address> field=value … [field:=json …] [--ttl 5m] [--bind]
```

- `field=value` — string, server coerces it to field type;
- `field:=json` — value as-is, parsed as JSON;
- `--ttl` — TTL for this write: number of seconds or `5m` / `1h30m` (otherwise — default TTL from integration settings);
- `--bind` — values live as long as the script that called `sparku`: once it exits or crashes, they're cleared (see [binding to a process](/docs/api/concepts.md#binding-to-a-process)).

```bash
sparku push deploy progress=0.4 stage=build
sparku push deploy progress=70% --ttl 10m
sparku push deploy stage=build --bind
sparku push queue items:='[{"title": "Build"}]'
```

## end

Clears all values for an integration (like TTL expiration, but immediate).

```
sparku end <address>
```

```bash
sparku end deploy
```

## notify

Flash indicator and line for a few seconds (at most once per 2 seconds per integration).

```
sparku notify <address> ["text"] [--state value] [--color red] [--duration 4]
```

- text — positional argument, up to 120 characters (longer is truncated);
- `--state` — state field value (takes its label, icon, and color);
- `--color` — semantic color (`blue`, `green`, `orange`, `red`, `purple`, `pink`, `yellow`, `teal`, `indigo`, `gray`, `success`, `warning`, `error`);
- `--duration` — 1…10 seconds, default 4.

At least `text` or `--state` is required.

```bash
sparku notify deploy "Build failed" --state failed
sparku notify server "CPU 95%" --color red --duration 6
```

## glow

Coordinate glow: spots of light at given places of the island outline. Each call
replaces the whole frame.

```
sparku glow <address> position:color[:intensity[:width]] … [--intensity 1.2] [--ttl 5]
sparku glow <address> --off
```

- position — 0…1 left to right across the island, 0.5 is the middle under the notch;
- color — a semantic name (`blue`, `red`, `success`, …) or `#RRGGBB`;
- intensity — 0…1, default 1; width — half-width of the spot as a fraction of the
  island width, default 0.08;
- `--intensity` — outline thickness and glow strength, 0.2…3;
- `--ttl` — how long a frame stays lit without the next one, default 5 seconds;
- `--off` — turn it off.

```bash
sparku glow deploy 0.2:green 0.5:orange:0.6 0.8:#ff3b30
sparku glow build 0.5:blue:1:0.5 --ttl 1h      # a wide band for an hour
sparku glow deploy --off
```

For visualizations with dozens of frames per second, send `POST …/glow` directly over
the socket — see [HTTP API](/docs/api/http.md).

## ask

Ask a question on the Island. Waits for answer (connection stays open until answered or `--timeout` expires).

```
sparku ask <address> "question" [-o id:label …] [--multi] [--custom]
           [--accept Yes --decline No --comment] [--title …]
           [--timeout 10m] [--attach file]
```

- `-o id:label` (repeatable) — answer option; without `-o` and without `--custom` the question becomes a confirmation with two buttons;
- `--multi` — can select multiple options (requires ≥ 2 options);
- `--custom` — adds a free-form answer field;
- `--accept` / `--decline` — button labels (default "Yes" / "No");
- `--comment` — allow a comment on decline;
- `--title` — question title;
- `--timeout` — 5 seconds to 1 day, default 10 minutes; format — number of seconds or `90s` / `10m` / `2h`;
- `--attach` — absolute or relative path to a file that can be opened from the question.

Answer is printed to stdout: selected options — id one per line, custom answer — as text, decline reason (`--comment`) — as text too.

```bash
if sparku ask deploy "Deploy?"; then ./deploy.sh; fi
env=$(sparku ask deploy "Where?" -o prod:Prod -o stage:Staging)
sparku ask deploy "Delete branch?" --accept Delete --decline Keep --comment
```

An integration can have at most one unanswered question at a time — a second `ask` gets `409 dialog_pending`.

## listen

Prints taps on card controls.

```
sparku listen <address> [--exec "command"] [--reconnect]
```

- without `--exec` — each event as NDJSON line by line to stdout (good for `jq`, `while read`);
- with `--exec` — runs a command on each event; data arrives **only** through the environment (`SPARKU_SLUG`, `SPARKU_CONTROL`, `SPARKU_VALUE`, `SPARKU_EVENT`), nothing is substituted into the command text;
- `--reconnect` — reconnect if SparkU closes the connection (e.g., restarts), instead of exiting with error.

```bash
sparku listen deploy --exec './on-click.sh'   # $SPARKU_CONTROL, $SPARKU_VALUE
sparku listen deploy --reconnect | jq .
```

## import

Offers an integration from a `.sparku` file to you and waits for consent in SparkU Settings.

```
sparku import <file.sparku>
```

On consent, prints to stdout `export SPARKU_TOKEN_<ADDRESS>=…`, so an installer can do:

```bash
eval "$(sparku import deploy.sparku)"
```

User decline — exit code `77`.

## doctor

Checks the environment step by step: socket, SparkU version, (if address is given) token, and integration existence.

```
sparku doctor [address]
```

```bash
sparku doctor
sparku doctor deploy
```

## openapi

The API description in OpenAPI 3.1 (JSON) — for client generators and AI agents.

```
sparku openapi [address]
```

Without an address — the general schema of all `/v1` routes; it doesn't need SparkU and is also on the site: [/openapi.json](/openapi.json). With an address — the schema of that integration: the `push` body lists its fields with types, bounds and state values, so a generated client catches a typo in a field name.

```bash
sparku openapi deploy > deploy.openapi.json
```

## version / help

```
sparku version
sparku help
```

## Exit codes

### `push`, `end`, `doctor`, `notify`, `listen`, `import`

Codes from `<sysexits.h>` to not overlap with `ask` codes:

| Code | Meaning | When |
|---|---|---|
| `0` | success | |
| `64` | invalid arguments (`EX_USAGE`) | flag typo, missing required argument |
| `65` | values failed validation (`EX_DATAERR`) | HTTP 400, 411, 413, 422 |
| `67` | integration with this address not found (`EX_NOUSER`) | HTTP 404 |
| `69` | SparkU unavailable or API disabled (`EX_UNAVAILABLE`) | no socket, HTTP 409, 503 |
| `70` | SparkU internal error (`EX_SOFTWARE`) | HTTP 5xx |
| `75` | too frequent, retry later (`EX_TEMPFAIL`) | HTTP 429 (`notify` more than once per 2s) |
| `76` | unexpected response (`EX_PROTOCOL`) | CLI and app versions don't match |
| `77` | no token or wrong token (`EX_NOPERM`) | HTTP 401, 403; `sparku import` user decline |

`69` is checked first: a script can reliably distinguish "SparkU not running" from any other error, even if the token is also not configured.

### `ask`

Separate scheme — doesn't overlap with `<sysexits.h>`, so shell `if sparku ask deploy "Deploy?"; then …` works:

| Code | Meaning |
|---|---|
| `0` | answer received (choice or custom text — to stdout) |
| `1` | declined |
| `2` | timeout, question removed from Island ("Hide"), or SparkU closed |

`409 dialog_pending` (integration already has an unanswered question) is returned as code `69`, as are all other unavailability errors.
