Skip to content

Workflows

Task-oriented walkthroughs for shll, the meta-CLI for the shll toolkit. Each section starts from a goal and shows which shll command gets you there and what it actually does under the hood. For install paths and shell wiring, see Install & shell wiring.

Clean-machine bootstrap

From a fresh machine to a fully wired toolkit:

curl -fsSL https://shll.ai/install | sh                                  # bootstrap: trust + install shll, then install the roster
shll setup shell                                                         # pure rc wiring — no trust flag
exec $SHELL                                                              # reload so the shell integration takes effect

The one-liner runs a preflight and a Homebrew bootstrap before expanding to the trust + install steps below (pass a subset with | sh -s -- hop wt). Minimal Ubuntu/Debian images ship without curl — sudo apt-get install -y curl before the one-liner. Step by step:

  1. Preflight. The script probes git (on macOS via xcode-select -p — the /usr/bin/git CLT shim false-positives), curl, and tmux, reporting every miss at once with its per-platform fix command. Missing curl (or git on a Linux machine without Homebrew) is fatal; missing tmux only warns, with its install hint.
  2. Homebrew bootstrap (only when brew is absent). The official installer runs headlessly with NONINTERACTIVE=1 — on macOS this installs the Command Line Tools via softwareupdate; on Linux the preflight has already guaranteed git. The script then uses the absolute brew path, evals brew shellenv in-process, and prints the rc line to keep for future shells. An existing Homebrew (≥ 6.0.4; on 6.0.0–6.0.3, brew update first) is used as-is and no bootstrap runs.
  3. brew trust --formula sahil87/tap/shll && brew install sahil87/tap/shll puts the shll binary on PATH. The brew trust is required on Homebrew 6.0+ (which makes tap-trust a hard install requirement) — shll’s formula runs a sandboxed install that needs a real trust record. shll can’t trust its own formula before it exists, so this one-time bootstrap uses brew trust directly.
  4. shll install walks the roster (run-kit, rk-desktop, fab-kit, wt, idea, tu, hop) and, for each brew-managed tool you don’t already have, runs brew trust --formula sahil87/tap/<formula> then brew install — so it owns trust for the six brew tools. rk-desktop is not a brew formula: it delegates to rk desktop install (and skips with a note when rk is absent or the platform is unsupported — never a failure). Idempotent — re-running installs only what’s still missing. Pass --no-trust to skip the trust step if you manage trust yourself; see the tap-trust troubleshooting. (Formula names are always tap-qualified sahil87/tap/<formula> — homebrew/core carries an unrelated run-kit, so a bare brew install run-kit installs the wrong software.)
  5. shll setup shell appends a single sentinel-wrapped eval block to your rc file. It is pure rc-wiring — trust is shll install’s job, not the shell half’s (there is no --trust-tap flag).
  6. exec $SHELL reloads the shell so the eval line takes effect; hop, wt, and the rest are now live.

Day-to-day: shll update

shll update

One command to upgrade everything you have installed. The sequence:

  1. brew update --quiet, exactly once. A single metadata refresh for the whole run — shll tells each delegated per-tool update that advertises --skip-brew-update to skip its own internal brew update, so there’s no redundant refresh. (A tool predating that flag runs its own brew update, costing one extra refresh for that tool — see shll update.)
  2. Self-upgrade. If shll itself was installed via brew, it runs brew upgrade sahil87/tap/shll first. A from-source shll is skipped here (no formula to upgrade).
  3. Per-tool upgrade, by delegation. For each installed roster tool, shll update invokes that tool’s own update subcommand (with --skip-brew-update when the tool advertises it) rather than calling brew upgrade directly. This preserves each tool’s post-upgrade side effects — e.g. rk’s daemon restart — that a bare brew upgrade would silently drop. rk-desktop delegates to rk desktop update (it has no brew formula). A brew-managed tool that exposes no update subcommand falls back to brew upgrade.

Uninstalled tools are skipped (graceful degradation), and the loop is best-effort: a single tool’s failure doesn’t abort the rest. brew’s progress streams straight to your terminal.

shll update prints a [N/M] progress header before each tool and a timing summary tail at the end (Done — N of M tools succeeded in <dur>., or a X succeeded, Y failed in <dur> form on partial failure). The tail reports exit-code outcomes and run duration — it never claims “updated” vs. “up-to-date”, since the sub-tools’ own output streamed past.

Preview without changing anything:

shll update --dry-run

--dry-run runs the read-only probes (so the preview is accurate) but performs no writes — no brew update, no brew upgrade, no <tool> update. It prints an aligned table of the exact commands the real run would execute, in roster order (shll (self) first when brew-installed), then exits 0. The same flag exists on shll install.

You can also scope a run to specific tools: shll update hop wt upgrades just those (plus shll update shll for the self-upgrade alone). A named-but-not-installed target is an error here (unlike a whole-roster run, which silently skips it).

Composing shell-init

eval "$(shll shell-init zsh)"

shll shell-init <shell> concatenates the shell-init output of every installed shll tool, in roster order, into a single blob — replacing what would otherwise be one eval line per tool. (You normally don’t run this by hand; shll setup shell writes the eval line for you.)

The composition is eval-safe by construction, which matters because the output is fed straight to eval:

  • A tool that isn’t installed (binary not on PATH) is silently omitted — no error, no partial output.
  • A tool whose shell-init errors has its output dropped; the error note goes to stderr only, never into the eval’d stdout.
  • shll injects only #-prefixed comment separators (# ── <tool> ──) between blocks — shell no-ops, never executable code or color escapes.

So eval "$(shll shell-init zsh)" is safe even when shll exits non-zero or a sub-tool is broken: at worst you get a shell with one fewer integration loaded, never a parse error. The order is deterministic (roster order), so a composed blob reads the same way every time.

Version dump for bug reports

$ shll version
shll        v0.0.5
run-kit     v1.5.3
rk-desktop  not installed
fab-kit     v1.9.4
wt          v0.0.5
idea        v0.0.2
tu          v0.4.13
hop         v0.1.5

One column-aligned row for shll itself plus each roster tool — plain text, no colors, designed to paste cleanly into a Slack thread or GitHub issue. An uninstalled tool renders as not installed. Each tool’s version probe has a 2-second timeout (<tool> --version; rk-desktop probes rk desktop status instead), so one hung tool can’t block the dump (a timeout also shows as not installed); worst case the whole table finishes in well under 15 seconds even if every tool hangs.

The composition model

shll has no state, no database, and no special knowledge of the tools it wraps. Every subcommand is a thin coordinator over the per-tool CLIs and brew:

shll commandWhat it actually runs
shll installbrew trust --formula sahil87/tap/<formula> then brew install sahil87/tap/<formula> per missing brew-managed tool (--no-trust skips the trust step); rk desktop install for rk-desktop
shll updatebrew update --quiet once, self-upgrade, then each installed tool’s own update (delegated; rk desktop update for rk-desktop; brew upgrade fallback only when a brew-managed tool has no update)
shll shell-init zshconcatenates the stdout of each installed tool’s <tool> shell-init zsh
shll versioninvokes <tool> --version per tool (rk desktop status for rk-desktop), formats as a table

This is Constitution Principle IV — Composition, Not Replacement: hop update, wt shell-init, etc. continue to work standalone. shll’s only job is to fan out, collect output, and degrade gracefully when a tool is missing.

See also

  • Install & shell wiring — every install path and the full shll setup shell rc-wiring contract.
  • shll.ai — the always-current command reference.