Tillered Docs

CLI reference

Complete reference for the Arctic command-line interface

The Arctic CLI (arctic) manages Arctic agents and clusters. It follows the pattern arctic <command> [subcommand] [flags].

Most read commands map to a collection (list) or a single item (get). Output goes to stdout; progress messages, prompts, and errors go to stderr, so you can pipe machine-readable output cleanly.

bootstrap

Initialize an Arctic agent with a license file.

Synopsis

arctic bootstrap --url <agent-url> --license-file <path> [flags]

Description

Bootstrap initializes an agent with a license. This:

  1. Uploads the license to the agent
  2. Generates a unique peer identity (Ed25519 key pair)
  3. Creates OAuth2 credentials for API access
  4. Saves the cluster to your CLI config file and sets it as current

Flags

FlagDescription
--urlAgent URL (e.g. http://192.168.1.10:8080). Provide via the global --url flag
--license-filePath to the license JSON file (required)
--nameHuman-readable name for this peer (optional)

Output

Peer ID:        peer_01HXYZ...
Cluster ID:     clu_01HABC...
Client ID:      cli_01HXYZ...
License ID:     lic_abc123...
Expires:        2025-12-31 23:59:59 UTC
Max Nodes:      10
Max Services:   100

Configuration saved to ~/.config/arctic/config.yaml
Set as current cluster: clu_01HABC...

Examples

# Basic bootstrap
arctic bootstrap \
  --url http://192.168.1.10:8080 \
  --license-file license.json

# With a peer name
arctic bootstrap \
  --url http://192.168.1.10:8080 \
  --license-file license.json \
  --name prod-svr-1

Notes

  • An agent can only be bootstrapped once. To re-bootstrap, reset the agent's database.
  • The license file is license.json, provided by Tillered.
  • For multi-peer clusters, prefer arctic compose apply over running bootstrap by hand.

cluster

Manage cluster operations.

Synopsis

arctic cluster <subcommand> [flags]

Subcommands

SubcommandDescription
initInitialize cluster for legacy upgraded agents
identityShow cluster identity of a peer
syncTrigger cluster synchronization
statusShow gossip status for diagnostics

cluster init

Initialize a cluster on a legacy agent that predates cluster IDs. Required scope: urn:tillered:arctic:admin.

arctic cluster init [--force]
FlagDescription
--forceForce reinitialize even if a cluster already exists
Cluster initialized
Cluster ID:       clu_01HABC...
Created By:       peer_01HXYZ...
Oldest Peer:      peer_01HXYZ...
Was Created:      true

Notes:

  • New agents have a cluster initialized during bootstrap. This command exists for upgraded agents only.
  • --force regenerates the cluster ID and destroys existing cluster state.

cluster identity

Show the cluster identity of a peer. This is a public endpoint and requires no authentication.

arctic cluster identity
Peer ID:     peer_01KBYMHC35F0N070F3XXMEZAZR
Public Key:  qnGyPtol7lqzLYU3989eaC+K4xda0w9KXlcEOM9cSBQ=
License ID:  lic_01KB45EYP1VJ1RZEGJDPKJQ9V4
Cluster ID:  clu_01KBYMHMRJ92E090P50VRKG4ZC
Version:     v1.4.0

Use -j for JSON output:

{
  "peer_id": "peer_01KBYMHC35F0N070F3XXMEZAZR",
  "public_key": "qnGyPtol7lqzLYU3989eaC+K4xda0w9KXlcEOM9cSBQ=",
  "license_id": "lic_01KB45EYP1VJ1RZEGJDPKJQ9V4",
  "cluster_id": "clu_01KBYMHMRJ92E090P50VRKG4ZC",
  "version": "v1.4.0"
}

The version field reports the agent build that answered the request, so the exact value depends on the peer you query.

cluster sync

Trigger immediate cluster synchronization. Required scope: urn:tillered:arctic:admin.

arctic cluster sync

This forces a gossip round and reconciliation across the agent's reconcilers instead of waiting for the next periodic resync. Use it to speed up propagation after adding a peer or changing config.

cluster status

Show gossip status for diagnostics. Required scope: urn:tillered:arctic:admin.

arctic cluster status
Gossip Status
-------------
Local Peer:        peer_01KBYMHC35F0N070F3XXMEZAZR
Cluster ID:        clu_01KBYMHMRJ92E090P50VRKG4ZC

Peer Status:
  peer_01KBYMD32Z2RVDE3G5Y9M530QR:
    Last Seen:     2025-12-09 10:15:30 UTC
    Status:        healthy
    Registry Hash: a1b2c3d4...

Registry:
  Services:        5
  Routes:          12
  Hash:            e5f6g7h8...

Use -j for JSON output. Useful for diagnosing synchronization issues and detecting registry drift between peers.


completion

Generate shell completion scripts for the Arctic CLI.

Synopsis

arctic completion <shell>
ArgumentDescription
shellShell type: bash, zsh, or fish

Installation

# Bash: add to ~/.bashrc
source <(arctic completion bash)

# Zsh: add to ~/.zshrc
source <(arctic completion zsh)

# Fish: save to the completions directory
arctic completion fish > ~/.config/fish/completions/arctic.fish

Features

  • Command completion: arctic pe<TAB> completes to peers.
  • Subcommand completion: arctic peers l<TAB> completes to list.
  • Flag completion: arctic peers list --<TAB> lists available flags.
  • Value completion: peer IDs and service IDs complete from the local cache (see arctic cache).

Example session

$ arctic <TAB>
bootstrap    cache        cluster      completion   compose
config       credentials  health       license      mcp
peers        routes       services     state

$ arctic peers <TAB>
add       delete    get       list      remove-self  update

$ arctic peers list --<TAB>
--local         --remote        --client-id     --client-secret
--config        --context       --debug         --insecure
--json          --no-headers    --output        --quiet
--timeout       --token         --url           --yes
-c              -j              -o              -q              -y

compose

Manage Arctic clusters declaratively from a YAML configuration file. This is the recommended way to deploy and operate a cluster.

See the compose guide for a walkthrough and the configuration reference for the full schema.

Synopsis

arctic compose <subcommand> [config-file] [flags]

Subcommands

SubcommandDescription
applyApply cluster configuration from YAML
diffShow differences between config and cluster state
exportExport cluster configuration to YAML
validateValidate YAML syntax and schema
initGenerate a starter configuration template
fmtFormat a configuration file

compose apply

Apply cluster configuration from a YAML file. Required scope: urn:tillered:arctic:admin.

arctic compose apply <config-file> [flags]
FlagDefaultDescription
--dry-runfalseShow changes without applying
--prunefalseDelete resources not in config
--ignore-unreachablefalseSkip unreachable peers
--license-fileLicense file for bootstrap
--credentials-fileWrite credentials to a JSON file on bootstrap
--env-fileWrite credentials to a .env file on bootstrap
--save-configtrueSave cluster to CLI config and set as current (use --save-config=false to disable)
--skip-validatefalseSkip pre-validation checks (not recommended)
--skip-preflightfalseSkip pre-flight peer connectivity checks
--skip-requiresfalseSkip the requires block version checks
--strictfalseTreat validation warnings as errors
--backup-retention0Override preferences.backup_retention for this run (1-100; 0 uses the configured default)
--state-dirOverride the .arctic/ state directory location
--no-lockfalseSkip cluster-wide lock acquisition (the local file lock still applies). Required when the server peer is unreachable or compose modifies server.peer
# Validate and apply
arctic compose apply cluster.yaml

# Preview changes without applying
arctic compose apply cluster.yaml --dry-run

# Apply and prune resources not in config
arctic compose apply cluster.yaml --prune

# Bootstrap and save credentials in one step
arctic compose apply cluster.yaml \
  --license-file license.json \
  --credentials-file creds.json

# Apply without saving to CLI config
arctic compose apply cluster.yaml --save-config=false

Example output:

Validating cluster.yaml...
OK - Configuration valid

Checking cluster state...
  peer-a: bootstrapped
  peer-b: bootstrapped

Planning changes...
  + Create service: web-tunnel (peer-a -> peer-b)
  + Create route: 0.0.0.0/0 -> 10.0.0.0/8

Applying changes...
  [OK] Created service web-tunnel
  [OK] Created route 10.0.0.0/8

Apply complete: 1 service created, 1 route created

compose diff

Show differences between the configuration file and current cluster state. Required scopes: urn:tillered:arctic:peers.read, urn:tillered:arctic:services.read.

arctic compose diff <config-file> [flags]
FlagDescription
--skip-preflightSkip pre-flight peer connectivity checks
--skip-requiresSkip the requires block version checks
--state-dirOverride the .arctic/ state directory location
Comparing cluster.yaml with cluster state...

Services:
  ~ web-tunnel: bandwidth_limit_mbps changed (0 -> 100)
  + new-tunnel: will be created
  - old-tunnel: will be deleted (with --prune)

Routes:
  + 10.0.0.0/8: will be added to web-tunnel

compose export

Export the current cluster configuration to YAML. Required scopes: urn:tillered:arctic:peers.read, urn:tillered:arctic:services.read.

arctic compose export [flags]
FlagDescription
--fileOutput file path (defaults to stdout)
arctic compose export
arctic compose export --file cluster.yaml

compose validate

Validate configuration YAML syntax and schema. Runs locally; no agent connection or auth required.

arctic compose validate <config-file> [flags]
FlagDefaultDescription
--strictfalseTreat warnings as errors

Use -j for JSON output and -q to suppress non-error output (both are global flags).

Validating cluster.yaml...
OK - Configuration valid

Schema version: v1
Peers: 2
Services: 1
Routes: 1

compose init

Generate a starter configuration template.

arctic compose init [flags]
FlagDefaultDescription
--fileOutput file path (defaults to stdout)
--minimalfalseGenerate a minimal config without comments
arctic compose init                       # full example to stdout
arctic compose init --file cluster.yaml   # full example to a file
arctic compose init --minimal             # minimal config

compose fmt

Format a configuration file to canonical form. Reorders keys to the canonical order, normalizes to 2-space indentation, and preserves comments.

arctic compose fmt <config-file> [flags]
FlagDefaultDescription
--writefalseWrite formatted output back to the file
--checkfalseCheck if the file is formatted (exit 1 if not)
arctic compose fmt cluster.yaml            # print formatted config
arctic compose fmt cluster.yaml --write    # format in place
arctic compose fmt cluster.yaml --check    # CI check

Exit codes

CodeCondition
0Success
2Usage or validation error
3Configuration error
4Connection error
7Lock contention (another apply holds the lock)

config

Manage the Arctic CLI's local configuration file.

Synopsis

arctic config <subcommand> [flags]

Subcommands

SubcommandDescription
listList all clusters and peers
viewView the full configuration
currentShow the current cluster context
use-clusterSet the current cluster
add-peerAdd a peer to a cluster
delete-peerDelete a peer from the cluster configuration

config list

arctic config list
ID                    NAME         URL                           LICENSE    CURRENT
clu_01HXYZABC123...   agent-a      http://192.168.1.10:8080      lic_...    *
clu_01HXYZDEF789...   agent-b      http://192.168.1.20:8080      lic_...

config view

View the full configuration file.

arctic config view

config current

Show the current cluster context.

arctic config current
Cluster ID:      clu_01HABC...
Name:            Production
Customer ID:     cust_...
Peer Count:      3
Default Peer:    peer_01HXYZ...
Default URL:     http://192.168.1.10:8080
Format:          cluster

config use-cluster

Set the current cluster context by ID or name.

arctic config use-cluster <cluster-id-or-name>
arctic config use-cluster Production
arctic config use-cluster clu_01HABCDEF...

config add-peer

Add a peer entry to a cluster in your local config (does not contact the agent).

arctic config add-peer --peer-id <id> --peer-url <url> [flags]
FlagDescription
--peer-idPeer ID (required)
--peer-urlAgent URL (required)
--clusterCluster ID or name (defaults to current cluster)
--nameHuman-readable name for the peer
arctic config add-peer \
  --peer-id peer_01HXYZ... \
  --peer-url http://192.168.1.30:8080 \
  --name agent-c \
  --cluster Production

config delete-peer

Remove a peer entry from a cluster in your local config.

arctic config delete-peer <peer-id-or-name> [flags]
FlagDescription
--clusterCluster ID or name (defaults to current cluster)
arctic config delete-peer agent-c
arctic config delete-peer agent-c --cluster Production

Requires confirmation unless --yes is specified.


credentials

Manage OAuth2 API credentials. Alias: credential.

Synopsis

arctic credentials <subcommand> [flags]

Subcommands

SubcommandDescription
listList all credentials
createCreate a new credential
revokeRevoke a credential
rotateRotate the shared cluster credential secret

credentials list

List credentials for the current license. Required scope: urn:tillered:arctic:credentials.read.

arctic credentials list

Each entry shows the client ID, scopes, license ID, creation time, and last-used time. The client secret is never returned by list. Use -j for JSON output.

credentials create

Create a new credential. Required scope: urn:tillered:arctic:credentials.write.

arctic credentials create [--scopes <list>]
FlagDescription
--scopesComma-separated scopes (optional; omit for full access)

The client secret is shown once, on stderr, and cannot be retrieved again:

arctic credentials create --scopes urn:tillered:arctic:peers.read,urn:tillered:arctic:services.read
IMPORTANT: Save the client_secret below. It will NOT be shown again.

Credential created successfully:
  Client ID:     cli_01HXYZ...
  Client Secret: sec_abc123...

  Scopes: urn:tillered:arctic:peers.read, urn:tillered:arctic:services.read

credentials revoke

Revoke a credential by client ID. Required scope: urn:tillered:arctic:credentials.write.

arctic credentials revoke <client-id>
arctic credentials revoke cli_01HXYZ...

credentials rotate

Rotate the shared cluster credential secret. The old secret keeps working for 24 hours so peers can pick up the new one via gossip. Required scope: urn:tillered:arctic:credentials.write.

arctic credentials rotate [--update-config]
FlagDescription
--update-configUpdate the CLI config file with the rotated secret
IMPORTANT: Save the new client_secret below. The old secret expires in 24 hours.

Cluster credential rotated successfully:
  Client ID:     cli_01HXYZ...
  Client Secret: sec_def456...
  Version:       2
  Rotated By:    peer_01HXYZ...

The new credential will be gossiped to all cluster peers.

health

Check Arctic agent health. Requires no authentication.

Synopsis

arctic health [flags]

Flags

FlagDescription
--readyzCheck readiness (/readyz) instead of liveness (/livez)
arctic health                                  # liveness, current context
arctic health --readyz                         # readiness
arctic health --url http://192.168.1.30:8080   # specific agent
arctic health -j                               # JSON output

Default output:

Peer ID:     peer_01KBYMHC35F0N070F3XXMEZAZR
Name:        agent-1
URL:         http://192.168.3.251:8080
Status:      ok
Timestamp:   2025-12-09 04:43:41 UTC

JSON output:

{
  "peer_id": "peer_01KBYMHC35F0N070F3XXMEZAZR",
  "name": "agent-1",
  "url": "http://192.168.3.251:8080",
  "status": "ok",
  "timestamp": "2025-12-09 04:43:41 UTC"
}

Liveness (/livez) indicates the process is running. Readiness (/readyz) indicates the agent is ready to serve requests, and may return not-ready during startup. Both are unauthenticated, which makes them suitable for load balancers and Kubernetes probes.

Scripting example

arctic health --url http://192.168.1.10:8080
case $? in
    0) echo "Agent healthy" ;;
    4) echo "Agent unreachable"; send_alert "Arctic agent down" ;;
    *) echo "Unexpected error" ;;
esac

license

Manage the agent license. The agent re-verifies the license on every startup.

Synopsis

arctic license <subcommand> [flags]

Subcommands

SubcommandDescription
statusShow license usage status
updateUpdate the license

license status

Show license usage status. Required scope: urn:tillered:arctic:admin.

arctic license status
License Information
-------------------
License ID:     lic_abc123...
Customer ID:    cust_xyz789...
Customer Name:  Acme Corp

Validity
--------
Issued:         2024-01-01 00:00:00 UTC
Expires:        2025-12-31 23:59:59 UTC
Status:         Valid (350 days remaining)

Limits
------
Max Nodes:      10
Max Services:   100

Metadata
--------
Issuer:         Tillered
Key ID:         2024Q4
Algorithm:      Ed25519

Use -o json for JSON output.

license update

Update the agent license with a new license file. Required scope: urn:tillered:arctic:admin.

arctic license update --license-file <path>
FlagDescription
--license-filePath to the new license file (required)
arctic license update --license-file new-license.json
License updated
Customer ID:    cust_xyz789...
License ID:     lic_def456...
Expires:        2026-12-31 23:59:59 UTC
Max Nodes:      20
Max Services:   200

Notes:

  • The new license must be for the same customer.
  • Connected peers receive the updated license via gossip.

peers

Manage cluster peers. Alias: peer.

Synopsis

arctic peers <subcommand> [flags]

Subcommands

SubcommandDescription
listList all peers
getGet details of a specific peer
addAdd a remote peer
updateUpdate peer metadata
deleteDelete a peer
remove-selfRemove the local peer from the cluster

peers list

List peers in the cluster. Required scope: urn:tillered:arctic:peers.read.

arctic peers list [flags]
FlagDescription
--localShow only the local peer (mutually exclusive with --remote)
--remoteShow only remote peers (mutually exclusive with --local)
arctic peers list
arctic peers list --remote
arctic peers list -j
ID                               NAME       ADDRESS
peer_01KBYMHC35F0N070F3XXMEZAZR  agent-1    192.168.3.251:8080
peer_01KBYMD32Z2RVDE3G5Y9M530QR  agent-2    10.10.40.95:8080

peers get

Get a specific peer by ID. Required scope: urn:tillered:arctic:peers.read.

arctic peers get <peer-id>
ID:          peer_01KBYMHC35F0N070F3XXMEZAZR
Name:        agent-1
Public Key:  qnGyPtol7lqzLYU3989eaC+K4xda0w9KXlcEOM9cSBQ=
Is Local:    Yes
Address:     192.168.3.251:8080
Created At:  2025-12-08 09:26:30 UTC

peers add

Add a remote peer to the cluster. Required scope: urn:tillered:arctic:peers.write.

arctic peers add <peer-address> [flags]
FlagDescription
--nameHuman-readable name for the peer
arctic peers add 192.168.1.20:8080
arctic peers add 192.168.1.20:8080 --name prod-svr

This contacts the remote peer, performs a handshake (exchanging public keys), verifies both signatures against the license, then records the peer locally. The remote peer adds the local peer via gossip.

peers update

Update a peer's metadata. Required scope: urn:tillered:arctic:peers.write.

arctic peers update <peer-id> [flags]
FlagDefaultDescription
--nameHuman-readable name for the peer
--qostrueEnable QoS for this peer (use --qos=false to disable)
arctic peers update peer_01HXYZ... --name prod-svr-2
arctic peers update peer_01HXYZ... --qos=false

peers delete

Delete a remote peer. Required scope: urn:tillered:arctic:peers.write.

arctic peers delete <peer-id> [--yes]
arctic peers delete peer_01HXYZ...
arctic peers delete peer_01HXYZ... --yes

To remove the local peer, use remove-self.

peers remove-self

Gracefully remove the local peer from the cluster. Required scope: urn:tillered:arctic:admin.

arctic peers remove-self [--yes]

This deactivates the local peer and broadcasts the deactivation so other peers drop it from their databases. Services involving this peer become inactive.


routes

Manage CIDR-based routing rules for services. Alias: route.

Synopsis

arctic routes <subcommand> --service <service-id> [flags]

Subcommands

SubcommandDescription
listList routes for a service
addAdd a route to a service
updateUpdate a route
deleteDelete a route

routes list

List routes for a service. Required scope: urn:tillered:arctic:services.read.

arctic routes list --service <service-id>
ID      PRIORITY  SOURCE CIDR           DEST CIDR
6       100       10.0.0.0/8            192.168.100.0/24
7       200       10.1.0.0/16           192.168.200.0/24

routes add

Add a route to a service. Required scope: urn:tillered:arctic:services.write.

arctic routes add --service <service-id> [flags]
FlagDescription
--serviceService ID (required)
--priorityRoute priority (lower value = higher priority)
--source-cidrSource CIDR (e.g. 10.0.0.0/8)
--dest-cidrDestination CIDR (e.g. 192.168.100.0/24)

At least one of --source-cidr or --dest-cidr is required.

# Source and destination CIDR
arctic routes add --service svc_01HSVCABC123... \
  --priority 100 \
  --source-cidr 10.0.0.0/8 \
  --dest-cidr 192.168.100.0/24

# Destination only
arctic routes add --service svc_01HSVCABC123... \
  --priority 100 \
  --dest-cidr 192.168.100.0/24

routes update

Update a route. Required scope: urn:tillered:arctic:services.write.

arctic routes update --service <service-id> --route <route-id> [flags]
FlagDescription
--serviceService ID (required)
--routeRoute ID (required)
--priorityNew priority
--source-cidrNew source CIDR
--dest-cidrNew destination CIDR
arctic routes update --service svc_01HSVCABC123... --route 6 --priority 200

routes delete

Delete a route. Required scope: urn:tillered:arctic:services.write.

arctic routes delete --service <service-id> --route <route-id> [--yes]
arctic routes delete --service svc_01HSVCABC123... --route 6 --yes

Route priority and specificity

Routes are matched by specificity first, then priority breaks ties. Specificity order, most specific first: MACVLAN interface match, source plus destination CIDR, source-only CIDR, destination-only CIDR. When two routes have equal specificity, the lower --priority value wins.

PrioritySource CIDRDest CIDROrder
20010.1.0.0/16192.168.100.0/241st (source + dest)
10010.0.0.0/8(none)2nd (source only)
100(none)192.168.0.0/163rd (dest only)

services

Manage services for network routing. Alias: service.

Synopsis

arctic services <subcommand> [flags]

Subcommands

SubcommandDescription
listList services
getGet details of a specific service
createCreate a new service
updateUpdate service settings
deleteDelete a service

services list

List services. Required scope: urn:tillered:arctic:services.read.

arctic services list [flags]
FlagDescription
--source-peerFilter by source peer ID
--target-peerFilter by target peer ID
--requires-interfaceFilter to services requiring a MACVLAN interface
arctic services list
arctic services list --target-peer peer_01HXYZ...
arctic services list -j

Table output is a compact view with a per-service flags column:

ID                              SOURCE          TARGET          TRANSPORT  FLAGS
svc_01KBYMNEVYN9NC4M3RB3ZGN4RZ  agent-1         agent-2         tcp        I
svc_01KBYMP88A7MBM1KTXBYSFA7VK  agent-2         agent-1         tcp        IT

FLAGS: I=interface, T=transparent, Q=qos, -=none

Use -j or -o json for full detail with all fields.

services get

Get a specific service by ID. Required scope: urn:tillered:arctic:services.read.

arctic services get <service-id>
ID:                     svc_01KBYMNEVYN9NC4M3RB3ZGN4RZ
Source Peer ID:         peer_01KBYMHC35F0N070F3XXMEZAZR
Source Peer Name:       agent-1
Target Peer ID:         peer_01KBYMD32Z2RVDE3G5Y9M530QR
Target Peer Name:       agent-2
Transport:              tcp
Requires Interface:     Yes
Interface MAC:          4a:cc:db:76:cf:59
Actual Interface IPv4:  192.168.3.219
Fully Transparent:      No
Created At:             2025-12-08 09:28:44 UTC
Updated At:             2025-12-08 09:28:44 UTC
Data Source:            source

If the source peer is unreachable, the CLI queries the target peer for service data. Interface details may then be incomplete and Data Source: local is shown.

services create

Create a new service. Required scope: urn:tillered:arctic:services.write.

arctic services create --target-peer <id> [flags]
FlagDefaultDescription
--target-peerTarget peer ID (required)
--source-peerlocal peerSource peer ID
--transporttcpTransport type: tcp or kcp
--requires-interfacefalseCreate a MACVLAN interface
--desired-ipv4IPv4 CIDR for the interface
--fully-transparentfalseEnable fully transparent mode
--bandwidth-limit0Bandwidth limit in Mbps (0 = unlimited)
arctic services create --target-peer peer_01HXYZ...

arctic services create \
  --target-peer peer_01HXYZ... \
  --requires-interface \
  --desired-ipv4 192.168.100.10/24

arctic services create \
  --target-peer peer_01HXYZ... \
  --transport kcp \
  --bandwidth-limit 1000

services update

Update a service's settings. Required scope: urn:tillered:arctic:services.write.

arctic services update <service-id> [flags]
FlagDescription
--requires-interface[=BOOL]Set the MACVLAN interface requirement
--fully-transparent[=BOOL]Set fully transparent mode
--bandwidth-limitBandwidth limit in Mbps (0 = unlimited)
--desired-ipv4IPv4 CIDR for the interface
arctic services update svc_01HSVCABC123... --requires-interface
arctic services update svc_01HSVCABC123... --requires-interface=false
arctic services update svc_01HSVCABC123... --bandwidth-limit 500

services delete

Delete a service. Required scope: urn:tillered:arctic:services.write.

arctic services delete <service-id> [--yes]

Deleting a service removes its routes and MACVLAN interface (if any) and updates the firewall and data-plane state.


cache

Manage the local completion cache. Shell completion uses this cache to suggest peer and service IDs.

Synopsis

arctic cache <subcommand>

Subcommands

SubcommandDescription
refreshFetch peers and services from the cluster and update the cache
statusShow cache location, age, and contents
deleteDelete the cache file

cache refresh

arctic cache refresh
Cache updated: 2 success, 0 failed (84ms)

cache status

arctic cache status
Cache Location: ~/.config/arctic/cache.json
Last Updated:   2025-12-09 04:43:41 UTC (12m ago)
TTL:            1h

Cluster: clu_01HABC...
  Peers:    3
  Services: 5

If the cache is older than its TTL, a hint to run arctic cache refresh is printed.

cache delete

arctic cache delete [--yes]

Prompts for confirmation unless --yes is set.


state

Manage the local .arctic/ working-directory state used by compose apply.

Synopsis

arctic state <subcommand> [flags]

Subcommands

SubcommandDescription
unlockRelease stale local and cluster locks

state unlock

Release a stale lock left behind by an interrupted compose apply. The lock ID is the positional argument and comes from the contention error message.

arctic state unlock <lock-id> [flags]
FlagDescription
--state-dirOverride the .arctic/ state directory location
--forceAdmin override on the cluster tier; bypasses the holder-id check when releasing the cluster lock
--cluster-onlySkip the local file lock; only release the cluster lock
--local-onlySkip the cluster lock; only release the local file lock
arctic state unlock 01HXYZLOCK...
Released local lock 01HXYZLOCK...

If the lock ID does not match the recorded holder, the command reports a mismatch and exits with a usage error unless --force is supplied on the cluster tier.


mcp

Start a Model Context Protocol (MCP) stdio server so an LLM agent can drive cluster management. The server reads and writes MCP messages over stdio.

Synopsis

arctic mcp [flags]

Flags

FlagDefaultDescription
--allow-writefalseEnable write tools (e.g. compose apply). Omit to restrict to read-only tools

By default only read-only tools are exposed. Pass --allow-write to permit mutating operations.


Global flags

These flags work with any command.

Context and connection

FlagDescription
--context, -cContext to use (peer ID, peer name, cluster ID, or cluster name)
--urlOverride the agent URL for this command
--tokenUse a specific bearer token instead of configured credentials
--client-idOverride the OAuth client ID (e.g. cli_01HXYZ...)
--client-secretOverride the OAuth client secret (e.g. sec_...)
--insecureSkip TLS certificate validation (testing only)
arctic peers list --context prod-cluster
arctic peers list --client-id cli_01HXYZ... --client-secret sec_abc123...

Output control

FlagDescription
--output, -oOutput format: table, json, or yaml
--json, -jShorthand for -o json
--no-headersOmit column headers in table output
--quiet, -qSuppress non-error output

Table format is a compact view for list commands. Use -j or -o json for full detail. Errors always go to stderr regardless of output format.

Confirmation and debugging

FlagDescription
--yes, -ySkip confirmation prompts for destructive operations
--debug, --verbose, -vEnable debug logging
--traceShow full HTTP request and response traces
--timeoutRequest timeout (e.g. 30s, 1m30s)
--configPath to the config file (default ~/.config/arctic/config.yaml)

Environment variables

FlagEnvironment variable
--configARCTIC_CONFIG
--contextARCTIC_CONTEXT
--urlARCTIC_URL
--tokenARCTIC_TOKEN
--client-idARCTIC_CLIENT_ID
--client-secretARCTIC_CLIENT_SECRET

Exit codes

CodeNameDescription
0SuccessCommand completed successfully
1General errorUnspecified error
2Usage errorInvalid arguments, unknown flags, or a missing required value
3Config errorMissing or invalid configuration
4Connection errorAgent could not be reached
5Auth errorInvalid or expired credentials
6Partial failureSome operations succeeded, others failed
7Lock contentionA compose apply lock is held by another process
130InterruptedThe operation was cancelled (Ctrl+C) at a prompt

Exit codes are independent of output format. Error messages are always written to stderr.

arctic health --url http://192.168.1.10:8080
case $? in
    0) echo "healthy" ;;
    4) echo "unreachable" ;;
    5) echo "auth failed" ;;
    *) echo "error" ;;
esac

On this page