yeet Commands

The client command index, grouped by the work you are trying to do.

For agent-readable CLI context, run the command with --help-agent.

yeet --help-agent
yeet run --help-agent
yeet vm images --help-agent

For recipes, start with Workflows. Use this page as a command reference once you know the workflow you need.

Global flags

These flags work across commands:

  • --host=<catch-host>: target a catch host. Also set by CATCH_HOST.
  • --service=<svc>: force a service name when a command can infer one.
  • --tty: force TTY mode for remote commands.
  • --no-tty: disable TTY mode for remote commands.
  • --progress=auto|tty|plain|quiet: choose progress output.

Host shortcuts:

yeet status@<catch-host>

See How Commands Work for service selection and argument routing.

If catch denies a command with missing yeet permission, update the matching Tailscale grant. See Tailscale Access Grants.

Deploy

run

Install or update a service from a payload:

Run new-service deploy commands from a Service Workspace. A successful deploy writes or updates yeet.toml in the active workspace.

yeet run --web
yeet run <svc> ./compose.yml
yeet run -p 8080:80 <svc> nginx:alpine
yeet run <svc> ./Dockerfile
yeet run <svc> ./bin/<svc> -- --app-flag value
yeet run <svc> ./bin/<svc> --run-as=app:app
yeet run <svc> ./job.sh --cron="0 9 * * *" -- --job-arg foo
yeet run <vm> vm://ubuntu/26.04

Target a specific host with <svc>@<catch-host> when needed:

yeet run <svc>@<catch-host> ./compose.yml

<svc> must use lowercase letters, numbers, and dashes, start with a letter, and end with a letter or number.

Common flags:

  • --web: open the local guided deploy form with a read-only, reconnecting terminal mirror and 1,000 lines of scrollback.
  • --pull: pull fresh images for Compose and image payloads.
  • --force: redeploy even when yeet detects no payload or config change.
  • -p HOST:CONTAINER: publish host ports for image, Dockerfile, Python, and TypeScript payloads. iso deployments reject published ports.
  • --publish-reset: replace or clear the saved published-port list.
  • --net=<mode[,mode...]>: choose service network modes such as svc, svc,ts, lan, lan,ts, iso, or iso,ts. VMs support svc, lan, svc,lan, and iso. VM lan networking prompts to prepare a host bridge when one is not ready.
  • --service-root=<path-or-dataset>: choose the initial service root.
  • --zfs: treat --service-root as a ZFS dataset.
  • --run-as=<user>[:<group>]: run a native binary or script as an existing host account. Native services default to yeet-svc.
  • --sandbox=on|off: select the native Bubblewrap sandbox or the explicit direct-execution escape hatch. Fresh native services default to on.
  • --sandbox-ro=SOURCE[:DEST]: expose a read-only file or directory. Repeat the flag for multiple paths.
  • --sandbox-rw=SOURCE[:DEST]: expose a writable directory. Repeat the flag for multiple paths.
  • --cron="M H DOM MON DOW": schedule a native binary or script. Omitting the flag on later runs preserves an installed schedule; a non-empty value replaces it.
  • --snapshots=on|off|inherit: override service snapshot policy.
  • --env-file=<path>: upload an environment file before deploy.
  • --vcpus, --memory, --disk: set initial VM resources.
  • --image-policy=prompt|update|cached: choose stale VM image behavior.

Network flags on run define an initial deployment. For an existing non-VM service, a network difference stops before redeployment and directs you to yeet service set <svc> .... Payload and unrelated configuration updates still use yeet run when the requested network matches Catch's desired state.

An existing native run also preserves Catch's active sandbox state and exposures. A sandbox difference stops before redeployment and prints the equivalent yeet service set command. Existing native services without sandbox metadata report legacy; choose on or off explicitly through service set.

Related guides:

iso supports VMs, native binaries and scripts, timer-backed jobs, and container-backed payloads. It cannot combine with svc or lan. Supported container-backed services may combine iso,ts; VMs use iso alone and can install Tailscale inside the guest. Native and timer iso networking is independent of --run-as; it does not change workload privileges or claim to contain a hostile host-root process. Compose files pass a fail-closed safe-profile check before Catch starts containers.

stage

Upload a payload without applying it. This adds a review point between "bytes arrived" and "service changed":

yeet stage <svc> ./bin/<svc>
yeet stage <svc> show
yeet stage <svc> commit
yeet stage <svc> clear

Scheduled jobs

Use run --cron to deploy or redeploy a scheduled native binary or script:

yeet run backup ./backup --cron="0 3 * * *" --run-as=backup --net=iso -- --full
yeet run <svc>

The second command replays saved configuration and preserves the installed schedule. Returning to ordinary service mode requires yeet rm and recreation without --cron. To change timing without a local payload, use yeet service set <svc> --cron="...". It works only for an existing scheduled native binary or script, never converts an ordinary, container, or VM service, cannot clear a schedule or combine with another service mutation, and preserves the server-side payload and other settings. After Catch applies it, yeet updates a matching yeet.toml; run yeet service sync <svc> if the local config is absent or cannot be saved. Use Cron Jobs for timer behavior.

Observe And Control

status

Show host or service status:

yeet status
yeet status <svc>
yeet status <svc-a> <svc-b>
yeet status <svc>@<catch-host>

info

Show host storage and inventory, or detailed service information when a service is supplied:

yeet info
yeet info --host=<catch-host>
yeet info <svc>
yeet info <svc> --format=json

For native services, info reports authoritative sandbox state as legacy, on, or off plus every normalized read-only and writable exposure.

logs

Show service logs:

yeet logs <svc>
yeet logs -f <svc>

start, stop, restart

Control a service:

yeet start <svc>
yeet stop <svc>
yeet restart <svc>

enable, disable

Enable or disable autostart for systemd-backed services:

yeet enable <svc>
yeet disable <svc>

events

Show catch events:

yeet events
yeet events@<catch-host>

Remove

remove / rm

Remove a service:

yeet rm <svc>

Remove service data and the local config entry too:

yeet rm --clean <svc>

Useful flags:

  • --clean: delete service data and the local yeet.toml entry.
  • --yes: skip prompts. This does not imply --clean or --clean-data.
  • --clean-config: delete the local yeet.toml entry.
  • --clean-data: delete service data, including VM guest disks.

Read confirmation prompts carefully before deleting data. --yes answers the prompt; it does not decide that data should be deleted.

Config, Env, And Files

edit

Open the current service config in $EDITOR:

yeet edit <svc>

env show, env edit, env copy, env set

Inspect and manage a service env file:

yeet env show <svc>
yeet env edit <svc>
yeet env copy <svc> ./app.env
yeet env set <svc> PORT=8080 LOG_LEVEL=debug
yeet env set <svc> LOG_LEVEL=

copy / cp

Copy files between local paths and service data or VM guests:

yeet copy ./config.yml <svc>:config/config.yml
yeet copy ./configs/ <svc>:config/
yeet copy ./configs/*.yml <vm>:~/configs/
yeet copy <vm>:"/var/log/*.log" ./logs/
yeet copy --force-proxy ./configs/ <vm>:~/configs/

Regular service endpoints are relative to the service data directory. VM endpoints target the guest filesystem.

config

Show or update local yeet client config:

yeet config
yeet config --host=<catch-host>
yeet config --workspace ~/yeet-services
yeet config --add-workspace ~/lab-services
yeet config --remove-workspace ~/lab-services
yeet config --clear-workspaces

--workspace replaces the registered workspace list with an existing directory. --add-workspace adds another existing directory.

Services

service generations

Show generation state:

yeet service generations <svc>

Generations track deployed definitions and install artifacts. They are not storage snapshots. Rollback changes what was deployed; snapshots recover data.

service rollback

Roll a non-VM service back to the previous deployed generation:

yeet service rollback <svc>

VM services do not support generation rollback. Use yeet snapshots restore for VM disk recovery.

service set

Change settings that require an explicit service update:

yeet service set <svc> -p 80:80 -p 443:443
yeet service set <svc> --publish-reset -p 443:443
yeet service set backup --cron="30 2 * * *"
yeet service set <svc> --service-root=/srv/apps/<svc> --copy
yeet service set <svc> --service-root=tank/apps/<svc> --zfs --copy
yeet service set <svc> --run-as=yeet-svc
yeet service set <svc> --run-as=app:app
yeet service set <svc> --run-as=root
yeet service set <svc> --sandbox=on
yeet service set <svc> --sandbox=off
yeet service set <svc> --sandbox-ro=/etc/app --sandbox-ro=/etc/ssl
yeet service set <svc> --sandbox-ro=reset --sandbox-ro=/etc/app
yeet service set <svc> --net=iso
yeet service set <svc> --net=ts --ts-tags=tag:app
yeet service set <svc> --net=host
yeet service set <svc> --ts-exit=
yeet service set <svc> --snapshots=off
yeet service set <svc> --snapshots=inherit

service set --cron changes only the schedule of an already scheduled native binary or script. It never converts an ordinary, container, or VM service into a scheduled service, cannot clear a schedule or combine with another service mutation, and preserves the server-side payload and other settings. After Catch applies the change, yeet updates a matching yeet.toml; run yeet service sync <svc> if the local config is absent or cannot be saved.

Sandbox flags apply only to existing native binaries, shebang scripts, and scheduled jobs. --sandbox accepts on or off. The legacy state shown by yeet info cannot be selected; it remains until the service receives an explicit choice.

--sandbox-ro accepts a read-only file or directory. --sandbox-rw accepts a writable directory. Both accept SOURCE or SOURCE:DEST and can be repeated. Each access class mentioned by the command is the complete desired list for that class. Catch refuses an implicit removal. Include every entry to preserve or use --sandbox-ro=reset or --sandbox-rw=reset to replace that list. Unmentioned classes remain unchanged.

An exposure-only mutation of an off service changes the resulting state to on, which activates the sandbox and may install Bubblewrap. Repeat --sandbox=off in the same command to edit dormant configuration while retaining direct execution:

yeet service set api --sandbox=off --sandbox-ro=/etc/api

Sandbox settings can combine with each other but not with cron, identity, network, service-root, publication, or snapshot changes in the same service set command. --sandbox=off is independent of --run-as=root and network mode; apply those separate choices in separate operations. See Native Sandboxing.

Network flags on service set apply only to existing non-VM services. The change restarts the service immediately. --net replaces the complete mode set. The remaining network flags patch one setting; --ts-tags=, --ts-ver=, --ts-exit=, --macvlan-parent=, --macvlan-vlan=, and --macvlan-mac= clear optional values. Omitted settings stay unchanged. --net= and an empty --ts-auth-key are invalid.

The complete network family is --net, --ts-tags, --ts-ver, --ts-exit, --ts-auth-key, --macvlan-parent, --macvlan-vlan, and --macvlan-mac. Whenever the resulting modes include ts, the resulting tags must be non-empty. A supplied auth key is transient and never appears in info output or yeet.toml.

VM network settings stay under vm set, not service set:

yeet vm set <vm> --net=lan
yeet vm set <vm> --net=svc,lan --macvlan-parent=vmbr0

Stop the service before moving a service root. Use --copy to copy the old root or --empty to create a fresh root.

--run-as applies only to native binaries, scripts, and cron jobs. Changing it performs one rollback-safe identity migration: yeet stops the workload, updates the systemd unit and service-root ownership, and restores the previous state if the new unit cannot start. A service-root move and identity change can be done together:

yeet service set <svc> \
  --service-root=/var/lib/yeet/services/<svc> \
  --copy \
  --run-as=yeet-svc

ZFS-backed service roots stay on their dataset. Docker users belong in Compose user: settings, and VM users are managed inside the guest. A non-root native service cannot bind a privileged host port directly; use a higher port, put a root-owned proxy in front, or explicitly choose --run-as=root.

Custom service-root parents must be root-owned and not group- or world-writable so the workload cannot replace paths while Catch is operating on them. Custom run-as accounts keep their configured supplementary groups in the systemd workload; review powerful memberships such as docker. Service shells opened with yeet ssh <svc> clear supplementary groups and can therefore be more restricted than the running unit.

service sync

Sync live service settings back into an existing yeet.toml entry:

yeet service sync <svc>
yeet service sync --all
yeet service sync <svc> --config ./yeet.toml

Use service sync when Catch applied a remote service set mutation but yeet could not update the local project file. Catch remains authoritative in that partial-success case. Native sync also writes the authoritative sandbox, sandbox_ro, and sandbox_rw fields.

Docker

docker outdated

Check Compose services for upstream image updates without changing containers:

yeet docker outdated
yeet docker outdated <svc>
yeet docker outdated --format=json

docker pull

Prefetch images for a Compose service without restarting:

yeet docker pull <svc>

docker update

Pull images and recreate Compose containers:

yeet docker update <svc>
yeet docker update <svc-a> <svc-b>@<catch-host>
yeet docker update --outdated

docker push

Push a local image to the catch host:

yeet docker push <svc> <local-image>:<tag> --run

VMs

vm images

Show catalog and cache state, update image bundles, import local images, or prune old cache entries:

yeet vm images catalog
yeet vm images
yeet vm images update
yeet vm images update vm://nixos/26.05
yeet vm images import lab/ubuntu ./dist/my-vm
yeet vm images rm lab/ubuntu --yes
yeet vm images prune --dry-run

Official catalog images are published from yeetrun/yeet-vm-images. Use VMs for the full VM image workflow.

vm runtime

Inspect and manage the host Firecracker and matching jailer pair independently from guest images, packages, kernels, and users:

yeet vm runtime status
yeet vm runtime status <vm> --format=json-pretty
yeet vm runtime update
yeet vm runtime upgrade <vm>
yeet vm runtime upgrade <vm> --restart
yeet vm runtime rollback <vm> --restart

status distinguishes the live running pair from configured, staged, and previous identities. update changes cache state only. upgrade stages by default, so the running VM is unchanged until its next start. --restart starts the trial immediately.

Runtime policy is manual by default. The optional stage-on-restart policy stages promoted releases during host reconciliation without restarting VMs:

yeet vm runtime policy defaults show
yeet vm runtime policy defaults set stage-on-restart --channel=stable
yeet vm runtime policy <vm> manual
yeet vm runtime policy <vm> inherit

Use --channel=candidate only as an explicit opt-in. Existing EOL or revoked runtimes are reported in status; a revoked runtime cannot be newly selected. Guest package updates and the guest agent cannot request a host runtime change. A natural guest reboot only consumes a candidate already staged by trusted host state.

Import and select a custom immutable pair:

yeet vm runtime import lab-v1 ./dist/runtime
yeet vm runtime upgrade <vm> --to=local:lab-v1

Preview cache cleanup and protect an otherwise unreferenced runtime when needed:

yeet vm runtime prune --dry-run
yeet vm runtime protect <runtime-id>
yeet vm runtime unprotect <runtime-id>

An explicit --restart trial creates a protected disk recovery point for a ZFS-backed VM. Raw disks have launcher rollback but no disk recovery point. See VMs for lifecycle, policy, recovery, and retention details.

vm set

Stop the VM before changing VM resources or networking:

yeet stop <vm>
yeet vm set <vm> --vcpus=6 --memory=6g --disk=128g
yeet vm set <vm> --net=lan
yeet vm set <vm> --net=svc,lan --macvlan-parent=vmbr0
yeet vm set <vm> --net=iso
yeet start <vm>

All existing VM network changes remain under vm set. The network flags on service set are for non-VM services.

An iso VM cannot combine iso with svc, lan, or Yeet-managed ts. Install Tailscale inside the guest when it needs a tailnet identity.

vm console

Stream a VM serial console:

yeet vm console <vm>

Detach by pressing Enter, then typing ~..

Snapshots

Snapshots are yeet recovery points for ZFS-backed service roots and VM disks. They are for storage state.

Common flow

yeet snapshots list <svc>
yeet snapshots inspect <svc> <snapshot>
yeet snapshots create <svc> --comment "before upgrade"
yeet snapshots clone <svc> <snapshot> <svc>-recover
yeet snapshots restore <svc> <snapshot> --stop --yes

Other snapshot commands

yeet snapshots defaults show
yeet snapshots defaults set --enabled=true --keep-last=5 --max-age=7d
yeet snapshots protect <svc> <snapshot>
yeet snapshots unprotect <svc> <snapshot>
yeet snapshots rm <svc> <snapshot>

For VM disk recovery:

yeet snapshots create <vm> --comment "before risky change"
yeet snapshots restore <vm> <snapshot> --stop --start --yes

For a running VM, catch pauses the guest while it takes one atomic ZFS snapshot of the disk, then resumes it. The result is crash-consistent disk state. It does not include guest memory or VMM runtime state. Raw-disk VMs cannot be snapshotted. Restore replaces the VM disk state only.

Use ZFS for snapshot defaults, retention, clone-first recovery, and VM restore behavior.

Connect And Debug

ssh

Open a catch host shell, a service shell, or a VM guest shell:

yeet ssh
yeet ssh <svc>
yeet ssh --force-proxy <vm>
yeet ssh -- uname -a
yeet ssh <svc> -- ls -la

After yeet init, host and regular service shells use catch over Tailscale and do not require host SSH keys or a host password. Interactive regular service shells use the service account's configured shell when it is usable, then the catch host user's preferred shell, with /bin/sh as the fallback.

yeet ssh <svc> starts in the service data directory. Native services keep the service's persisted UID and GID. Docker Compose services open a host-side shell as the catch process identity, normally root; they do not enter a container. VM services still connect to the guest operating system with SSH because the guest has its own authentication boundary.

ip

Show connectable service or VM IP endpoints:

yeet ip <svc>

For iso, yeet info shows policy and reconciliation state. yeet ip prints only the stable VM or component endpoints that Catch can connect to; it omits internal router and link addresses.

tailscale / ts

Set up Tailscale OAuth for the catch host or run Tailscale commands for a service identity:

yeet tailscale --setup
yeet tailscale <svc> -- status
yeet ts <svc> serve --bg 3000
yeet ts <svc> update

Use Tailscale for tag and OAuth setup. Use Networking before choosing plain --net=ts; most Tailscale-exposed services should use svc,ts unless they are intentionally tailnet-only or use an exit node.

Host Setup And Upgrade

init

Install or update catch on a machine host over SSH:

yeet init root@<machine-host>
yeet --host=morpheus-catch init root@<machine-host>
yeet init --workspace ~/yeet-services root@<machine-host>
yeet init --no-workspace root@<machine-host>
yeet init --data-dir=/srv/yeet-data root@<machine-host>
yeet init --zfs --data-dir=flash/yeet/data --services-root=flash/yeet/services root@<machine-host>
yeet init

Fresh installs store catch state in /var/lib/yeet. The service root defaults to <data-dir>/services, which is /var/lib/yeet/services with the default data directory. Explicit custom filesystem roots and ZFS datasets remain in place when you rerun yeet init.

When an interactive init or upgrade finds the eligible historical layout, it can offer to move that state to /var/lib/yeet and remove the inactive source after validation with one consent. If init cannot prompt, use yeet host set and yeet host cleanup explicitly as described below.

The default catch Tailscale hostname is catch. Use the global --host target before init when adding another catch host to the same tailnet.

For normal setup, run yeet init root@<machine-host> and answer the prompts. For unattended setup, these flags answer init prompts:

FlagWhat it does
--ts-client-secret=<secret>Tailscale OAuth client secret for catch enrollment
--ts-auth-key=<key>Preauthorized Tailscale auth key for the catch node
--workspace <path>Create or adopt a service workspace and register it for the selected host
--no-workspaceSkip workspace setup during init
--install-dockerAnswers yes to installing Docker when Docker is missing on a supported host
--install-vm-toolsAnswers yes to installing VM tools when the host can run VMs

On supported Debian/Ubuntu VM hosts, interactive yeet init can also prepare br0 for VM --net=lan networking after confirmation.

Use Host Setup for the full bootstrap flow.

host set

Change catch host storage after install:

yeet info
yeet host set --data-dir=/srv/yeet-data
yeet host set --services-root=/srv/yeet-services --migrate-services=none
yeet host set --zfs --data-dir=flash/yeet/data --services-root=flash/yeet/services --migrate-services=all
yeet host set --iso-pool=172.30.0.0/16

Use --data-dir for catch state and registry data. Use --services-root for the default root of services that do not have their own explicit root. If you change --services-root, choose --migrate-services=all to move affected services or --migrate-services=none to pin them at their existing roots. Run yeet info before or after the change to see the current host data directory, services root, catch service root, and service/VM inventory.

With --zfs, --data-dir and --services-root are dataset names. A ZFS services root is a dataset prefix, so migrated services and catch use child datasets such as flash/yeet/services/<svc>.

Use --iso-pool to select an RFC1918 IPv4 /16 before the host has any active, reserved, or tombstoned iso allocation. Catch checks live routes, Docker networks, and persisted state before applying it. Existing iso workloads are never renumbered automatically.

Without --yes, yeet prints the plan and asks before applying it. If --migrate-services is omitted in an interactive terminal, yeet asks whether to migrate affected services. With --yes, pass the migration mode explicitly.

When services move, yeet updates matching entries in the local yeet.toml. Pass --config ./yeet.toml when the project config is somewhere else.

For a generic custom host-storage migration, yeet host set copies and validates the requested state but never deletes the old source. Run yeet host cleanup --from=<exact-journaled-source> --yes explicitly after validation. Custom roots are preserved unless the plan explicitly includes them. ZFS datasets are not copied or deleted implicitly.

host cleanup

Remove an exact journaled inactive source after a finalized host-storage migration reconnects and validates the new state:

yeet host set \
  --data-dir=/var/lib/yeet \
  --services-root=/var/lib/yeet/services \
  --migrate-services=all \
  --yes
yeet host cleanup --from=/root/yeet-data --yes

Cleanup refuses arbitrary paths and revalidates the active Catch and service state before deletion. If deletion alone fails, rerun the same command to resume the pending cleanup safely.

upgrade

Check and install public yeet/catch releases:

yeet upgrade check
yeet upgrade
yeet upgrade --host=<catch-host>
yeet upgrade --force
yeet upgrade --nightly
yeet upgrade check --nightly
yeet upgrade --version v0.6.1 --force

When run from a service workspace with yeet.toml, yeet upgrade includes all project catch hosts plus the default catch host. Use --host=<catch-host> to upgrade one catch host.

Use --nightly to target the latest nightly release. Use --version to target a specific public release tag; do not use both in the same command.

version

Show the catch server version for the selected host:

yeet version

list-hosts

List tailnet hosts matching tags:

yeet list-hosts

This command uses the local Tailscale client for discovery. Normal yeet commands do not require a local Tailscale client API, but your workstation still needs network reachability to the catch Tailscale address.

Host Mounts

mount

Mount a network filesystem on the host. With no arguments, list mounts:

yeet mount host:/export data-share --type=nfs --opts=defaults
yeet mount

umount

Unmount by mount name:

yeet umount data-share