Version: 6.0.0

# Command Line Interface

Visibox ships with a `visibox` command-line tool for controlling a running Visibox from your shell. It is a lighter alternative to the [AI Assistants](https://manual.spaceage.tv/6.0.0/integrations/ai/) integration for quick one-offs, shell aliases, scripting, and hotkey tools.

The CLI is a thin wrapper over the same [HTTP REST API](https://manual.spaceage.tv/6.0.0/integrations/api/) the Stream Deck plugin and the MCP server use, so anything the CLI can do, any other client can too.

## Installation

Install the CLI from inside Visibox:

1.  Choose **Install CLI Tool…** (on Mac, from the Visibox menu; on Windows, from the File menu).
2.  Visibox installs the command and shows you where it landed. Open a new terminal and run `visibox health` (Mac, or Windows from Command Prompt or PowerShell) or `visibox.cmd health` (Windows from Git Bash or WSL) to confirm it is working.

To remove it later, choose **Install CLI Tool…** again. Visibox detects that it is already installed and offers an **Uninstall** option.

### Where it lands

| Platform | Install path | Invoke as |
| --- | --- | --- |
| macOS | `/usr/local/bin/visibox` | `visibox` |
| Windows | `%LOCALAPPDATA%\Visibox\bin\visibox.cmd` | `visibox` or `visibox.cmd` |

On macOS, `/usr/local/bin` is already on your `$PATH`, so `visibox` works in any shell. You may be asked for your password, since writing there needs administrator rights.

On Windows, Visibox adds `%LOCALAPPDATA%\Visibox\bin` to your user PATH. In **Command Prompt** and **PowerShell**, type `visibox` and Windows resolves it to `visibox.cmd` automatically. In **Git Bash**, **WSL**, or another Unix-style shell on Windows, type `visibox.cmd` explicitly, because those shells do not do that resolution. To shorten it in bash, add `alias visibox=visibox.cmd` to your `~/.bashrc`.

The installed command is a small wrapper that runs the CLI out of the Visibox app itself, so there is no separate runtime to install.

note

You may need to open a new terminal window, or reload your shell profile, after installing so the command is on your `PATH`.

## Quick Start

```
# Is Visibox running?visibox health# What's playing?visibox status# Control playbackvisibox playvisibox stopvisibox nextvisibox prev
```

## Connection and Authentication

By default the CLI connects to `http://127.0.0.1:17736` on your local machine, and localhost connections skip authentication. There is nothing to configure for scripting your own Visibox.

To reach a Visibox on another machine you need a pairing token. See [Remote Pairing](https://manual.spaceage.tv/6.0.0/integrations/remote-pairing/) for how to pair, then pass the token with a flag or an environment variable:

| Flag / Variable | Purpose |
| --- | --- |
| `--host <host>` / `VISIBOX_HOST` | Host to connect to. |
| `--port <port>` / `VISIBOX_PORT` | Port. Default `17736`. |
| `--token <token>` / `VISIBOX_TOKEN` | Pairing token for remote connections. |

The CLI also reads a token from `~/.visibox/mcp-token` if it is there, the same file the MCP server uses, so if MCP already works then the CLI does too.

note

The default port changed in Visibox 6.0. Visibox 5.x used `51736`. Update any script that names the port.

## Counting from One

Song and Clip indices are **one-based by default**, matching the numbers the Controller shows. `visibox play-clip 1` plays the first Clip.

This is the opposite of the [API](https://manual.spaceage.tv/6.0.0/integrations/api/), which is zero-based. The CLI takes the friendlier default because a person is typing it.

To switch, use `--zero-based` on a single command, set `VISIBOX_INDEX_BASE=0`, or make it permanent:

```
visibox config set index-base 0
```

`--one-based` and `--zero-based` cannot both be given at once.

## Playback

| Command | What it does |
| --- | --- |
| `visibox play` | Start playback. |
| `visibox stop` | Stop playback. |
| `visibox pause` | Pause. |
| `visibox resume` | Resume. |
| `visibox next` | Next Clip. |
| `visibox prev` | Previous Clip. |
| `visibox random` | A random Clip from the active Song. |
| `visibox next-song` | Next Song. |
| `visibox prev-song` | Previous Song. |
| `visibox restart` | Restart the current Clip. |
| `visibox stop-all` | Stop all playing Clips. |
| `visibox play-toggle` | Toggle play and stop. |
| `visibox pause-toggle` | Toggle pause and resume. |
| `visibox play-clip <index>` | Play the Clip at that position. |
| `visibox release-clip <index>` | Release the Clip at that position. |
| `visibox song <index|id>` | Switch to a Song by position or ID. |
| `visibox trigger <clipId>` | Trigger a Clip, respecting retrigger behavior. |
| `visibox release <clipId>` | Release a Clip by ID. |
| `visibox seek <clipId> <percent>` | Seek within a Clip, 0 to 100. |

`play-clip` and `release-clip` both take `-s, --song <songId>` to work on a Song other than the active one.

A few commands take a flag for the optional part of the action:

| Command | Flag | Effect |
| --- | --- | --- |
| `next`, `prev` | `--any-song` | Cross into the next or previous Song. |
| `random` | `--any-song` | Pick from every Song, not only the active one. |
| `next-song`, `prev-song` | `--no-stop` | Leave playing Clips running while the Song changes. |
| `song` | `--stop-playing <true|false>` | Whether switching Songs stops playback. Default `true`. |
| `trigger` | `--activate-song <true|false>` | Whether triggering a Clip selects its Song. Default `true`. |

For any [API action](https://manual.spaceage.tv/6.0.0/integrations/api/#available-actions) without a command of its own, use `action`:

```
visibox action RECORD_TOGGLE nowvisibox action TRIGGER_CLIP_IN abc123 --velocity 90
```

`action` takes the action name, then its parameters in order. `--velocity <n>` sets a trigger velocity from 0 to 127. Indices follow your index-base setting, like `play-clip`.

`song` works out for itself whether you gave it a position or an ID. Force the reading with `--index <n>` or `--id <id>` if a Song ID of yours happens to be all digits.

## Real-Time Control

| Command | What it does |
| --- | --- |
| `visibox controls` | List the Project’s Controls, their letters and their names. |
| `visibox control <letter> <value>` | Set a Control by its letter, `0` to `1`. Percentages work: `50%`. |
| `visibox targets [--clip <id>]` | List the Targets a Control can bind to, with their IDs. `--clip` lists one Clip’s Targets. |
| `visibox param <targetId> <value>` | Set a bound parameter directly by its Target ID, skipping Controls. |

`controls` also shows each Control’s current value when Visibox has one. `control` and `param` both accept negative values, for example `visibox control A -0.5`.

`param` takes the value in the Target’s own units, not 0 to 1. `visibox targets --json` shows each Target’s range and unit. A percentage such as `50%` maps onto that range instead.

See [Real-Time Control](https://manual.spaceage.tv/6.0.0/real-time-control/) for what Controls and Targets are.

### Releasing a Clip

`release` and `release-clip` are the note-off half of a held button, new in 6.0. They stop a Clip that is in [Gate launch mode](https://manual.spaceage.tv/6.0.0/launch-modes/) and do nothing to a Clip in any other launch mode.

That makes them safe to fire unconditionally, which is what a hotkey tool wants:

```
# on key downvisibox play-clip 3# on key upvisibox release-clip 3
```

## System

| Command | What it does |
| --- | --- |
| `visibox fullscreen` | Toggle the Output window full screen. |
| `visibox mute` | Toggle output mute. |
| `visibox volume <0-100>` | Set the master output level. |
| `visibox panic` | Emergency reload. Restart all Visibox windows. |
| `visibox undo` | Undo the last project edit. |
| `visibox redo` | Redo the last undone project edit. |

`fullscreen` and `mute` flip the current state. Add `on` or `off` to set it instead: `visibox mute on` mutes, `visibox mute off` unmutes, and `visibox fullscreen on` goes full screen.

## Query

| Command | What it returns |
| --- | --- |
| `visibox health` | Whether Visibox is running and reachable. |
| `visibox status` | The active project and playback state. |
| `visibox app-state` | Full screen, mute, volume, the audio settings, the render caps, the Output’s transform and targets, the OSC port, camera preconnect, and the MIDI inputs. |
| `visibox projects` | All open projects. |
| `visibox recent` | Recently opened projects, with their paths. |
| `visibox project [id]` | Detail for a project. Defaults to the active one. |
| `visibox summary` | Names and counts for a project, as JSON. |
| `visibox playstate` | What is playing in a project, as JSON. |
| `visibox songs` | Songs in the active Project. Songs in the active Setlist are numbered; any others follow, unnumbered. |
| `visibox clips <songIndexOrId>` | Clips in a Song. A number counts Songs in the active Setlist. |
| `visibox clip <ids...>` | One or more Clips by ID, as JSON. |
| `visibox effects` | Effects the Project uses, as JSON. |
| `visibox visualizers` | Visualizers the Project uses, as JSON. |
| `visibox presets` | Available Visualizer and Effect presets. |
| `visibox preset <kind> <id>` | One preset with its data, as JSON. |
| `visibox preset-controls <kind> <id>` | The adjustable controls a preset exposes. |
| `visibox preset-validate <kind> <file>` | Check a preset file without saving it. |
| `visibox cameras` | Connected cameras and video inputs. |
| `visibox audio-devices` | Audio output and input devices. |
| `visibox version` | CLI, app, and API versions from the running Visibox. |

`presets` takes `-k, --kind <effect\|visualizer>` and `-s, --source <app\|user\|plugin>` to narrow the list, and `--include-data` to include each preset’s full data. `effects` and `visualizers` take `--ids <a,b>` to pick some, and `--include-data` as well. `<kind>` is `effect` or `visualizer`.

`preset-validate` prints whether the preset is valid, then any errors and warnings, and exits `1` when it is not. `audio-devices` marks the current device with `*` and shows each device’s ID, which the `audio:set-output-device` and `audio:set-default-input` edits take. ASIO outputs are listed but cannot be selected over the API.

`visibox --version` is different: it prints the CLI’s own version without contacting Visibox.

## Editing

A single `edit` command dispatches any edit the API supports:

```
visibox edit song:update-title --param songId=abc123 --param title="New Title"visibox edit clip:delete --param clipId=xyz789
```

Run `visibox edit list` to print every available edit name, grouped by kind. Running `visibox edit` with no name does the same thing.

To see what one edit takes:

```
visibox edit song:set-timeline --describe
```

For nested parameters, pass the whole object at once instead of repeating `--param`:

```
visibox edit clip:update-options --params-json '{"clipId":"xyz789","options":{"speed":1.5}}'
```

App-wide settings go through `edit` too, with no Project needed:

```
visibox edit render:set-caps --param resolutionCap=1080 --param frameRateCap=60visibox edit output:set-transform --param rotation=90 --param flip=horizontalvisibox edit output-target:set-enabled --param targetId=<id> --param enabled=true
```

`visibox app-state` shows the current values and each Output target’s ID. The [API](https://manual.spaceage.tv/6.0.0/integrations/api/#app-settings-edits) lists every app settings edit.

A `--param` value that parses as JSON is coerced, so `--param volume=0.5` sends a number and `--param mute=true` sends a boolean.

Edit parameters are always zero-based, whatever your index-base setting is.

## JSON Output

Append `--json` to any command for machine-readable output instead of formatted text. This is the right mode for piping into `jq`, `grep`, or another script:

```
visibox status --json | jq '.project.name'visibox songs --json | jq -r '.[].title'
```

With `--json`, errors go to standard error as JSON too, so a script can tell an application error from a connection failure without parsing prose.

## Targeting a Specific Project

Most commands default to the active Project. Use `--project <id>` to target another:

```
visibox songs --project abc123visibox play --project abc123
```

## Global Options

| Option | Description |
| --- | --- |
| `--json` | Output raw JSON instead of formatted text. |
| `--host <host>` | Visibox host. Default `127.0.0.1`. |
| `--port <port>` | Visibox port. Default `17736`. |
| `--token <token>` | Auth token for remote connections. |
| `--project <id>` | Target Project ID. Defaults to the active Project. |
| `--timeout <ms>` | Request timeout in milliseconds. Default `5000`. |
| `--one-based` | Treat Song and Clip indices as one-based. This is the default. |
| `--zero-based` | Treat Song and Clip indices as zero-based. |
| `--version` | Print the CLI version and exit. |

## Configuration

`visibox config` reads and writes preferences in `~/.visibox/config.json`:

```
visibox config getvisibox config get index-basevisibox config set index-base 0
```

`index-base` is the only key, and it takes `0` or `1`.

## Exit Codes

| Code | Meaning |
| --- | --- |
| `0` | Success. |
| `1` | Application error. Visibox returned an error, or refused the action. |
| `2` | Connection error. Visibox is not running or is unreachable. |

Exit codes make the CLI friendly to shell scripts: check `$?` or chain with `&&` and `\|\|` like any other Unix tool.

note

As of 6.0, an action Visibox refuses exits `1` rather than `0`. A script that checked only for a connection failure now catches a refused action too.

## Examples

The examples below are written for bash (macOS, Linux, WSL, Git Bash). On Windows, run them from Git Bash or WSL, or translate the loops and `jq` pipelines to PowerShell. In Git Bash, substitute `visibox.cmd` for `visibox`.

```
# Fire off a panic reload from a Stream Deck button, keyboard shortcut tool, or hotkey appvisibox panic# Rotate through songs on a timer (for example, in a soundcheck script)for i in 1 2 3 4 5; do  visibox song $i  sleep 30done# Dump a set list for a show documentvisibox songs --json | jq -r '.[] | "\(.index). \(.title)"'# Trigger the first Clip of every Song in sequence (hands-off preview)visibox songs --json | jq -r '.[].id' | while read songId; do  visibox song "$songId"  visibox play-clip 1  sleep 15done# Bail out of a script if Visibox isn't runningvisibox health || { echo "Visibox is not running"; exit 1; }
```

tip

The CLI, the [Stream Deck plugin](https://manual.spaceage.tv/6.0.0/stream-deck/), and [AI Assistants](https://manual.spaceage.tv/6.0.0/integrations/ai/) are three ways to reach the same API. Reach for the CLI when you want scripting or shell-speed control, the Stream Deck for physical buttons, and an AI assistant when you want to drive Visibox with natural language.

Source: https://manual.spaceage.tv/6.0.0/integrations/cli/
