Skip to content

CLI Command Reference

Verified CLI commands — exact syntax that works. Add new entries when a command succeeds.

Purpose: Avoid repeating wrong CLI syntax across sessions.

km (Komodo CLI)

Deploy stack (compose-only changes)

echo "" | km x deploy-stack <name>
  • Feature: Deploy stack after git push (compose.yaml changes only)
  • Gotcha: Must pipe empty string to skip confirmation prompt

Deploy stack with sync (TOML changes)

echo "" | km x run-sync <category> && echo "" | km x deploy-stack <name>
  • Feature: Sync TOML from git then deploy stack
  • Gotcha: Two separate commands chained, both need empty pipe for non-interactive

Run command inside container (non-interactive)

ssh -i ~/.ssh/id_ed25519 -o StrictHostKeyChecking=no root@100.68.251.84 "docker exec <container-name> <shell-command>"
  • Feature: Run non-interactive command inside running container on unraid (docker exec equivalent)
  • Gotcha: Must use SSH — km exec is interactive-only (requires TTY), km x exec parses as km execute exec (wrong subcommand). For development server use ssh 100.126.172.96 "docker exec <container> <cmd>"

Restart / Stop / Start stack

echo "" | km x restart-stack <name>
echo "" | km x stop-stack <name>
echo "" | km x start-stack <name>
  • Feature: Lifecycle operations on deployed stacks

Get container/stack logs

km-logs <container>                  # container logs (auto-detect server)
km-logs <container> -n 100           # tail 100 lines (default: 50)
km-logs <container> -t               # with timestamps
km-logs <container> -g error -g fail # grep AND search
km-logs -S <stack> [services...]     # stack compose logs
  • Feature: Wrapper script at scripts/km/km-logs — reads Komodo API directly, no SSH needed
  • Gotcha: This is NOT a native km subcommand. Symlinked to ~/.local/bin/km-logs

Run resource sync

echo "" | km x commit <sync-name>
  • Feature: Trigger resource sync manually (pulls git changes into Komodo)

List stacks / servers / containers

km list stacks            # all stacks
km list servers           # all servers
km container              # running containers (alias: km cn, km ps)
km container -a           # all containers including stopped
km container -a | grep <name>  # filter by name
  • Feature: Query Komodo for deployed resources and container states
  • Gotcha: km container (alias km cn) not km list containers. Use -a for stopped, -d for down-only

Server stats (via API — no native km command)

KEY=$(grep key ~/.config/komodo/komodo.cli.toml | head -1 | sed 's/.*= "//;s/"//')
SECRET=$(grep secret ~/.config/komodo/komodo.cli.toml | head -1 | sed 's/.*= "//;s/"//')
curl -s -X POST -H "x-api-key: $KEY" -H "x-api-secret: $SECRET" \
  -H "Content-Type: application/json" -d '{"server":"<name>"}' \
  "http://100.126.172.96:9120/read/GetSystemStats"
  • Feature: CPU, memory, disk usage for a server

docker / docker compose

Check container status on remote server

ssh <server> docker ps --filter "name=<container>" --format "{{.Status}}"
  • Feature: Check if container is running on remote server
  • Gotcha: Only use for debugging/investigation, NEVER for deployment

Inspect container network

docker inspect <container> --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'
  • Feature: Get container IP address

Follow container logs

docker logs -f --tail 100 <container>
  • Feature: Stream container logs in real-time

tailscale

Check Tailscale status

tailscale status
  • Feature: Show all Tailscale peers and their IPs

Get device IP

tailscale ip -4 <device>
  • Feature: Resolve Tailscale IPv4 for a device

bd (Beads Issue Tracker)

Find available work

bd ready
  • Feature: List issues ready to be worked on

View issue details

bd show <id>
  • Feature: Display full issue content

Claim and update issue

bd update <id> --claim
  • Feature: Claim ownership of an issue

Close completed work

bd close <id>
  • Feature: Mark issue as completed

Save persistent knowledge

bd remember "<knowledge>"
  • Feature: Save fact for future sessions

Push changes to remote

bd dolt push
  • Feature: Push bd issue tracker state to remote

uv (Python Package Manager)

Install dependencies

uv sync
uv sync --group dev
  • Feature: Sync project dependencies (dev adds ruff, mypy, yamlfix)

Run tool via uv

uv run ruff check .
uv run ruff format --check .
uv run mypy .
  • Feature: Run linting tools without activating venv

gh (GitHub CLI)

Create PR

gh pr create --title "feat: description" --body "Summary"
  • Feature: Create pull request from current branch

View PR checks

gh pr checks
  • Feature: Show CI status for current PR

rclone (unraid)

List remotes

rclone listremotes
  • Feature: List all configured remotes in current config
  • Gotcha: rclone on unraid is a 95-byte shim calling rcloneorig (plugin's renamed binary) with --config=/boot/config/plugins/rclone/.rclone.conf. Real binary is /usr/bin/rclone (uses main config at /root/.config/rclone/rclone.conf)

Show one remote

rclone config show <name>
  • Feature: Display config of a single remote (token shown in plain)

Test OneDrive/Microsoft Graph connection

rclone lsd onedrive:
rclone ls --max-depth 1 onedrive:
rclone about onedrive:
  • Feature: List folders, list files, show quota

Authorize new remote (CLI-only flow, headless)

# On machine with browser (local):
rclone authorize <type>     # e.g. onedrive, drive, dropbox
# → Browser opens, login, copy JSON token printed to terminal

# On unraid (or target server), append to config:
# [remote]
# type = onedrive
# region = global
# drive_id = <id>
# drive_type = personal
# token = <JSON from rclone authorize>

OneDrive gotcha — drive_id/drive_type auto-detect fails for personal accounts

  • Issue: rclone lsd onedrive: fails with unable to get drive_id and drive_type even with valid token (token verified OK via curl https://graph.microsoft.com/v1.0/me/drive returns 200)
  • Fix: Manually set explicit values:
    drive_id = 409E4EC3B7BC0ECB   # from /me/drive response
    drive_type = personal          # or "business"
    
  • Workaround: curl -H "Authorization: Bearer $TOKEN" https://graph.microsoft.com/v1.0/me/drive | grep -oE '"id":"[^"]+"' | head -1

Two config files on unraid

File Used by Notes
/root/.config/rclone/rclone.conf Real /usr/bin/rclone (mount scripts if they use this) Personal/staging edits
/boot/config/plugins/rclone/.rclone.conf rcloneorig shim, web UI :5572, mount-cloud.sh Plugin-owned, persists in /boot
  • Sync both after edits to keep them consistent (except tokens will diverge as they refresh)

Backup config before edit

TS=$(date +%Y%m%d-%H%M%S)
cp /root/.config/rclone/rclone.conf /root/.config/rclone/rclone.conf.bak-${TS}
cp /boot/config/plugins/rclone/.rclone.conf /boot/config/plugins/rclone/.rclone.conf.bak-${TS}

GitOps One-liners

Standard deploy (compose-only)

git add -A && git commit -m "chore(<stack>): <message>" && git push && echo "" | km x deploy-stack <name>

Deploy with sync (TOML changes)

git add -A && git commit -m "chore(<stack>): <message>" && git push && echo "" | km x run-sync <category> && echo "" | km x deploy-stack <name>

Session close

git pull --rebase && bd dolt push && git push && git status
  • Feature: Full session close sequence
  • Gotcha: All three must succeed before session is complete

tofu (OpenTofu / Cloudflare)

Check drift against live infrastructure

```bash export AWS_ACCESS_KEY_ID="$(atuin dotfiles var list | grep R2_ACCESS_KEY_ID | sed 's/export R2_ACCESS_KEY_ID=//')" export AWS_SECRET_ACCESS_KEY="$(atuin dotfiles var list | grep R2_SECRET_ACCESS_KEY | sed 's/export R2_SECRET_ACCESS_KEY=//')" export CLOUDFLARE_API_TOKEN="$(atuin dotfiles var list | grep CLOUDFLARE_API_TOKEN | sed 's/export CLOUDFLARE_API_TOKEN=//')" tofu plan ```

  • Feature: Compares local TF config against Cloudflare + R2 state, shows drift
  • Gotcha: Credentials named R2_* in atuin, must remap to AWS_* env vars. Must be in infrastructure/cloudflare/ dir (or use -chdir)

Bulk domain health check

```bash for entry in vault=vaultwarden git=gitea z=litellm alist=openlist dns=adguard home=homepage komodo=komodo ntfy=ntfy-via-lan photo=immich; do domain="${entry%%=*}"; svc="${entry##*=}" printf "%-22s %-16s " "$domain.minhluc.info" "[$svc]" curl -sS -o /dev/null -w "%{http_code} %{size_download}B %{time_total}s" --max-time 8 "https://$domain.minhluc.info" 2>&1 echo done ```

  • Feature: Check HTTP status + response size + latency for all tunnel domains, with service mapping
  • Gotcha: 502 = container not running (config OK), 000 = DNS/tunnel issue. vault slow (~8s) normal

Read Komodo deployment stderr via API

```bash curl -s -X POST \ -H "x-api-key: $(grep key ~/.config/komodo/komodo.cli.toml | sed 's/.= "//;s/"//')" \ -H "x-api-secret: $(grep secret ~/.config/komodo/komodo.cli.toml | sed 's/.= "//;s/"//')" \ -H "Content-Type: application/json" \ -d '{"id":""}' \ "http://100.126.172.96:9120/read/GetUpdate" | python3 -m json.tool ```

  • Feature: Get full deployment log (stdout + stderr per stage) for any Komodo update
  • Gotcha: UPDATE_ID from km x deploy-stack output link (e.g. 6a26edb5cc0c77a6d6999641). Auth uses x-api-key/x-api-secret headers, NOT Basic auth

Destroy orphaned container via Komodo API

```bash curl -s -X POST \ -H "x-api-key: $(grep key ~/.config/komodo/komodo.cli.toml | sed 's/.= "//;s/"//')" \ -H "x-api-secret: $(grep secret ~/.config/komodo/komodo.cli.toml | sed 's/.= "//;s/"//')" \ -H "Content-Type: application/json" \ -d '{"server":"unraid","container":""}' \ "http://100.126.172.96:9120/execute/DestroyContainer" ```

  • Feature: Remove container that destroy-stack can't reach (orphaned, name conflict)
  • Gotcha: Use full container SHA or name. destroy-stack only removes containers in the project

SSH to unraid via Tailscale

```bash ssh -o StrictHostKeyChecking=no root@100.68.251.84 "" ```

  • Feature: Run commands on unraid host directly (write appdata, docker commands, etc.)
  • Gotcha: Root access, no password needed (Tailscale auth). Use for host-level ops that containers can't do

Komodo REST API (Verified 2026-06-08)

All commands verified against live Komodo v2.2.0. Auth pattern is same for all.

Get stack logs via API

```bash curl -s -X POST \ -H "x-api-key: $(grep key ~/.config/komodo/komodo.cli.toml | sed 's/.= "//;s/"//')" \ -H "x-api-secret: $(grep secret ~/.config/komodo/komodo.cli.toml | sed 's/.= "//;s/"//')" \ -H "Content-Type: application/json" \ -d '{"stack":""}' \ "http://100.126.172.96:9120/read/GetStackLog" ```

  • Feature: Get container stdout logs for a stack (returns {"stdout":"..."})
  • Verified: caddy → 1 line. Use SearchStackLog with {"stack":"<name>","terms":["error"]} for filtered search

Search stack logs with terms

```bash curl -s -X POST \ -H "x-api-key: $(grep key ~/.config/komodo/komodo.cli.toml | sed 's/.= "//;s/"//')" \ -H "x-api-secret: $(grep secret ~/.config/komodo/komodo.cli.toml | sed 's/.= "//;s/"//')" \ -H "Content-Type: application/json" \ -d '{"stack":"","terms":["error","fail"]}' \ "http://100.126.172.96:9120/read/SearchStackLog" ```

  • Feature: AND-search stack logs (all terms must match)

Inspect container via API

```bash curl -s -X POST \ -H "x-api-key: $(grep key ~/.config/komodo/komodo.cli.toml | sed 's/.= "//;s/"//')" \ -H "x-api-secret: $(grep secret ~/.config/komodo/komodo.cli.toml | sed 's/.= "//;s/"//')" \ -H "Content-Type: application/json" \ -d '{"server":"unraid","container":""}' \ "http://100.126.172.96:9120/read/InspectDockerContainer" ```

  • Feature: Full docker inspect JSON (Name, State, NetworkSettings, etc.)
  • Verified: caddy → {"Name":"/caddy","State":{"Status":"running"}}

Get server system stats

```bash curl -s -X POST \ -H "x-api-key: $(grep key ~/.config/komodo/komodo.cli.toml | sed 's/.= "//;s/"//')" \ -H "x-api-secret: $(grep secret ~/.config/komodo/komodo.cli.toml | sed 's/.= "//;s/"//')" \ -H "Content-Type: application/json" \ -d '{"server":""}' \ "http://100.126.172.96:9120/read/GetSystemStats" ```

  • Feature: CPU%, memory (used_gb/total_gb), disk stats
  • Verified: unraid → mem=24.18/31.14GB

Quick verify pattern (auth + endpoint)

```bash KEY=$(grep key ~/.config/komodo/komodo.cli.toml | head -1 | sed 's/.*= "//;s/"//') SECRET=$(grep secret ~/.config/komodo/komodo.cli.toml | head -1 | sed 's/.*= "//;s/"//') curl -s -X POST -H "x-api-key: $KEY" -H "x-api-secret: $SECRET" \ -H "Content-Type: application/json" -d '{}' \ "http://100.126.172.96:9120/read/GetVersion"

```

  • Feature: Verify auth works. Use this pattern as template for all endpoints.
  • Gotcha: Headers MUST be quoted: -H "x-api-key: $KEY" (not -H x-api-key:$KEY)