Cubicle

Networking and SSH commands

Reference for the cubicle commands tunnel install, uninstall and status, connect, disconnect, status, devices list and revoke, ssh-config and ssh, covering the root network helper, the private WireGuard network, JSON status fields, SSH aliases, host keys and exit codes.

These commands give your computer private network access to your Boxes and set up OpenSSH for them. connect and ssh need the tunnel, an optional network helper that runs as root. Every command here that calls the API needs your interactive login: API keys cannot use the private network or SSH. Networking explains how the private network works.

BOX is a Box ID or ORG/NAME, such as acme/job-1; see Box arguments.

cubicle tunnel install

Installs the root network helper, or updates it to this CLI's version.

cubicle tunnel install [--yes]
FlagValueDefaultMeaning
--yes, -ynoneOffInstall without asking first. sudo may still ask for your password.
  • The command explains what it installs and asks Install the tunnel? [y/N]. When the tunnel is already installed, it asks Update the tunnel? [y/N] instead and replaces the helper with this CLI version's copy.
  • Any answer other than y or yes stops with Cancelled. and exits 1.
  • Without a terminal, and without --yes, it fails with confirmation required; pass --yes.
  • It then runs the installer with sudo and prints Tunnel installed. If the installer fails, the command ends with tunnel install failed.
  • On Linux without an active systemd-resolved, it fails with systemd-resolved is required or systemd-resolved must be active; see platform requirements.
  • --json has no effect.

Files the CLI writes lists the paths the helper installs, and platform requirements the service it runs as on Linux and macOS.

cubicle tunnel install
The Cubicle tunnel gives this computer private network access to your Boxes
…
Install the tunnel? [y/N] y
Tunnel installed.

cubicle tunnel uninstall

Disconnects the private network and removes the root network helper.

cubicle tunnel uninstall [--yes]
FlagValueDefaultMeaning
--yes, -ynoneOffRemove without asking first. sudo may still ask for your password.
  • When the tunnel is not installed, it fails with the tunnel is not installed.
  • It asks Remove the tunnel? [y/N], with the same rules as tunnel install.
  • It prints Tunnel removed. Device identity is retained in /var/lib/cubicle/cli.
  • The CLI, your login and this computer's device keys stay. Reinstalling reuses the device keys.
  • --json has no effect.
cubicle tunnel uninstall --yes
Tunnel removed. Device identity is retained in /var/lib/cubicle/cli.

cubicle tunnel status

Prints whether the tunnel is installed and connected.

cubicle tunnel status [--json]

No options besides --json.

  • Output: not installed; run `cubicle tunnel install` , installed, connected or installed, disconnected.
  • Installed means the helper's file /etc/cubicle/cli-helper.json exists. The command does not check that the helper answers.
  • --json prints installed and the fields of cubicle status.
cubicle tunnel status
installed, connected

cubicle connect

Connects this computer to the private network, so that you can reach your Boxes by private address and DNS name.

cubicle connect

No options. The command always prints JSON: the state, as cubicle status prints it.

  • It starts a background process and waits up to 15 s for it to connect. The process keeps running after the command returns.
  • The first time, the process registers this computer as a device. It then opens a session and refreshes it every 10 s. Each refresh updates the routed Boxes; see Which Boxes a session can reach.
  • When already connected with the same login, it prints the current state. When connected with another login, it disconnects that one first.
  • The connection ends with disconnect, logout or tunnel uninstall, or when the computer restarts. It does not reconnect by itself.
ErrorCause
the Cubicle tunnel is not installed; run `cubicle tunnel install` The helper is not installed.
the Cubicle tunnel helper is not responding; reinstall it with `cubicle tunnel install` The helper is installed but does not answer.
VPN startup timed out; inspect vpn.logNo connection within 15 s, and no error was recorded.
api_key_not_allowed: API keys cannot use this routeCB_CLI_API_KEY is set.
key_unavailable: device key is already registered or revokedThis computer's device was revoked.
vpn_unavailable: …Cubicle cannot give this computer a network address right now.

Other errors that the background process hits are printed as they are, and it logs to ~/.config/cubicle/vpn.log. The private network guide's Troubleshooting has the fix for each error, and Reach a service in a Box covers services on other ports.

cubicle connect
{
  "connected": true,
  "apiUrl": "https://api.cubicle.sh",
  "identity": "dev@example.com",
  "sessionId": "…",
  "boxes": [
    {
      "boxId": "0b3f6c2e-8d4a-4f6e-9c1d-7a2b5e8f9d10",
      "name": "job-1",
      "org": "acme",
      "address": "…",
      "generation": 3,
      "hostname": "job-1.acme.cubicle.internal"
    }
  ],
  "endpoint": "…",
  "expiresAt": "…"
}

cubicle disconnect

Leaves the private network.

cubicle disconnect

No options.

  • It stops the background process, which closes the session, and the helper removes the routes and DNS settings.
  • It always prints { "connected": false }, also when you were not connected.
cubicle disconnect
{
  "connected": false
}

cubicle status

Prints the private network's state as JSON.

cubicle status

No options. The command always prints JSON. It asks the background process and does not call the API. Without a background process, it prints { "connected": false }.

FieldMeaning
connectedWhether the private network is up: the session is live and routes are in place.
errorThe last refresh's error, when it failed. For example login expired; run `cubicle login` .
apiUrlThe API the connection belongs to.
identityThe login the connection belongs to.
sessionIdThe current session's ID.
boxesThe routed Boxes, each with boxId, name, org, address, generation and hostname.
endpointThe Gateway's WireGuard address, as host:port.
expiresAtWhen the current lease ends unless it is refreshed. A lease lasts 30 s and never outlives your login.
  • If refreshes stop for more than 30 s, the helper removes the routes and DNS settings on its own.
  • While the computer sleeps, nothing refreshes the session, and its lease lapses. When the computer wakes, the background process removes the routes and opens a new session. If that fails, it tries again every 10 s, and cubicle status shows the error.

cubicle devices

A device is a WireGuard key that the root helper keeps for this computer, one for each login (API URL and identity). cubicle connect registers it, named after the computer's hostname.

cubicle devices list

Lists your devices, including revoked ones, oldest first.

cubicle devices list

No options. The command always prints JSON: an array with id, name, address (the device's private network address), created_at and revoked_at.

cubicle devices list
[
  {
    "id": "e2a4c6e8-0b1d-4f3a-8c5e-7a9b1c3d5e7f",
    "name": "dev-laptop",
    "address": "…",
    "created_at": "2026-11-01T14:03:55.218Z",
    "revoked_at": null
  }
]

cubicle devices revoke

Revokes a device permanently.

cubicle devices revoke DEVICE_ID

No options.

  • Open connections from the device close, and its key can never connect again.
  • An unknown ID fails with not_found: device not found.
  • The command prints nothing.
  • cubicle connect on that computer then fails with key_unavailable: device key is already registered or revoked; Devices explains how to enroll it again.
cubicle devices revoke e2a4c6e8-0b1d-4f3a-8c5e-7a9b1c3d5e7f

cubicle ssh-config

Writes an OpenSSH alias and a pinned host key for a Box.

cubicle ssh-config BOX [--alias NAME] [--identity FILE] [--accept-new-host-key] [--json]
FlagValueDefaultMeaning
--aliasNamecubicle-<org>-<box>The Host name to write. For acme/job-1 the default is cubicle-acme-job-1.
--identityPath~/.ssh/id_ed25519The private key to write as IdentityFile. A path you pass is written as given, so use a full path.
--accept-new-host-keynoneOffReplace a pinned host key that no longer matches the key the API publishes.
  • The command reads the Box's SSH details from the API. It writes a Host block to ~/.ssh/cubicle_config, the host key to ~/.ssh/cubicle_known_hosts, and an Include line to ~/.ssh/config once. Running it again replaces the alias's block.
  • It does not connect the private network. The alias works while cubicle connect is connected.
  • The Box needs a published host key and a guest account for you, which a grant creates. Otherwise it fails with box has no trusted host key or guest account yet (<reason>); retry when it is running.
  • A host key that differs from the pinned one fails with the host key for jevbox-<box ID> changed. Verify the box was restored or replaced, then rerun with --accept-new-host-key. jevbox-<box ID> is the name the Box's host key is pinned under; see SSH and host-key pinning.
  • Output: configured: ssh <alias>. When SSH would not work yet, it adds (not ready: <reason>), for example no_active_key when your account has no SSH key.
  • --json prints configPath, knownHostsPath and hostAlias.

Calls GET /v1/boxes/{box} and GET /v1/boxes/{box}/ssh. What the CLI writes shows the block it writes. Copy files over SSH and Use the alias with other tools use the alias with scp, rsync and editors.

cubicle ssh-config acme/job-1
configured: ssh cubicle-acme-job-1

cubicle ssh

Connects the private network, writes the Box's alias and opens SSH.

cubicle ssh BOX [--alias NAME] [--identity FILE] [--accept-new-host-key] [-- SSH_ARGS...]

The options are the same as for cubicle ssh-config.

  • It connects as cubicle connect does, writes the alias as ssh-config does, then runs ssh <alias> SSH_ARGS... in your terminal.
  • Everything after -- is passed to ssh after the alias, for example a remote command.
  • It exits with ssh's exit code, or 255 when ssh reports none.
  • The private network stays connected after ssh exits.
  • It does not print the configured: line, and --json has no effect.
  • You need a grant on the Box and an ssh-ed25519 key on your account; see cubicle keys add.
cubicle ssh acme/job-1 -- uname -s
Linux

On this page