Reference
Command catalog: the repo's aliases, helper commands, and daily moves.
This is the "what command was that again?" page. The same catalog is available in the terminal with groundwork-help, so the help follows you even when the docs are not open.
groundwork-help show everythinggroundwork-help update filter commandsgroundwork-help git show Git helpersgroundwork-help project show scaffoldersgroundwork-help context show AI context helpers#Why not package.json?
A package.json would be valid, and this setup does install Node and pnpm for JavaScript projects. But Groundwork itself is not a JavaScript package; it is a macOS/chezmoi project whose first-run path has to work before Node exists. The most useful commands should also work from any folder after setup, so the primary interface is a normal shell command installed to ~/.local/bin: groundwork-help.
Repo-maintenance commands live as shell scripts under scripts/; for example, CI and humans both run scripts/validate-groundwork. That validator includes ShellCheck linting for checked-in and rendered shell scripts, so agent edits get the same shell review locally and in GitHub Actions. If a future workflow genuinely needs Node libraries, adding a tiny package.json with pnpm scripts as wrappers would be fine. It just should not be the only way a beginner discovers or runs Groundwork commands.
The ownership rule is simple: a command that performs work in child processes lives in ~/.local/bin; a shell function is reserved for work that must change the current shell, such as cd, an export, or activation. Self-updating commands split in two: update-all is a stable launcher that synchronizes Groundwork and then hands the same invocation to the freshly applied runner, groundwork-update-run, which holds the actual update stages. A fix delivered by the sync therefore governs the rest of that same invocation, and the launcher itself never needs to change.
A separate hand-written man page would duplicate the same command contract in a third place. Groundwork follows the modern CLI layers instead: every substantial helper owns complete -h/--help output, groundwork-help provides searchable offline discovery across helpers, and this site teaches the larger workflow. If Groundwork later grows into a stable multi-command suite, its man pages should be generated from that command definition rather than maintained separately.
#Daily Groundwork commands
groundwork-help | Show the command catalog. Add a query to filter it. |
groundwork-help --pick | Fuzzy-pick a command from the catalog with fzf; prints it and copies it to the clipboard when possible. |
update-all | Run a visible batched refresh: synchronize Groundwork, resume in the freshly applied groundwork-update-run runner, attempt brew update up to three times with short backoff, then run brew upgrade --require-sha/cleanup against that refreshed metadata, mise upgrade, and latest-track AI updates. It stops before later stages when a required stage fails and records success only after the complete batch. With the beta channel on, it also prints the xcodes workflow without downloading a beta. |
groundwork-configure | Review and selectively change this machine's setup answers (profile, work machine, password manager, code directory, identity, and so on). It shows current values, changes only what you pick, previews the dotfile diff, and applies only after you confirm — promoting the config atomically under a lock with a timestamped backup. Use it to change a setting; plain chezmoi init only regenerates from your existing answers. |
chezmoi diff | Preview managed-file changes before applying them. |
chezmoi apply | Apply this repo to your home directory. |
chezmoi update --init | Pull the Groundwork repo and apply it. --init also refreshes the setup answers when new questions were added — answers you already gave are kept, only new questions are asked. This syncs config; it does not upgrade already-installed tools to latest. |
chezmoi edit ~/.zshrc | Edit the source template for a managed file. |
chezmoi cd | Jump into the Groundwork source repo. |
#AI context sharing
Use these when you want a chat app, reviewer, or second agent to see the exact files you chose, with each path attached to its contents. Keep the bundle small: copy the files that explain the question, not the whole repo.
copy-context AGENTS.md src tests | Copy selected files or folders to the clipboard with path headers and contents. |
copy-context --stdout src/foo.ts | Print the payload first so you can inspect what you are about to paste. |
copy-context --paths-only docs | Copy only the selected file list when you want to discuss scope before sharing contents. |
#Repository navigation
groundwork-repos | Table of every Git repository discovered under your configured roots (~/.config/groundwork/repos.conf): branch, dirty/clean as symbol + word, ahead/behind, worktree marker, path. Discovery is dynamic — a fresh clone appears within the cache TTL (30 s), or immediately with --refresh, with no config edit. See Repository navigation. |
groundwork-repos pick | Fuzzy-pick a discovered repository (fzf) with a live git-status preview, then open or reuse its lazygit tmux window. Inside tmux it becomes a window (also on Ctrla then ShiftR); outside, it creates or attaches the repos session. |
groundwork-repos changed | Open one lazygit tmux window per repository with uncommitted work — the fastest way to see everything your agents left unreviewed (also on Ctrla then ShiftG). |
#Project scaffolders
new-project my-app | Create a starter repo with AGENTS.md, shared agent folders, editor settings, and ignored local/secrets files. |
groundwork-docker-build-scratch review . | Build a disposable Docker image under the ephemeral-build contract. The wrapper owns the syntax nobody should hand-type: it applies dev.roost.ephemeral=true, generates the RFC 3339 dev.roost.built timestamp itself, tags <project>/scratch:<purpose> (project derived from the context, or --project), validates the purpose as a legal tag component, and prints the resulting image ID. --rm-after removes the image right after a successful build (prove-and-delete); allowlisted docker build arguments go after -- (--file/-f, --target, --platform, --build-arg, --secret, --ssh, --no-cache, --pull, --progress; anything else is refused by name — --output/--push are unsupported because the contract requires a local, inspectable image). See Platforms. |
new-wiki ~/code/llm-wiki | Create a private knowledge wiki where sources live in raw/, an agent maintains wiki/, and Obsidian can browse the vault. |
obsidian-plugins ~/code/llm-wiki | Install the Groundwork-managed Obsidian plugin set into a vault. |
#GitHub auth
gh auth login | Sign in to GitHub for gh and HTTPS Git operations. |
gh auth setup-git | Install gh as Git's HTTPS credential helper. |
#Dev runtimes
mise use node@24 | Pin a runtime/tool version in the current project. |
mise upgrade | Upgrade globally managed mise tools, including floating baselines such as Node LTS. Takes effect at your next prompt, even in already-open terminals. |
pnpm | Package manager installed through mise for JavaScript projects. |
python | Python installed and versioned by mise. Avoid relying on macOS system Python. |
uv | Fast Python package, project, script, tool, and virtualenv manager. |
#Git commands
git status | Show changed, staged, and untracked files. |
git diff | Inspect unstaged changes before asking an agent to continue. |
git add -p | Stage changes in reviewable chunks. |
git commit -m "message" | Commit the staged changes with a short message. |
git show --stat | Review the latest commit summary. |
#Groundwork safety
chezmoi diff | Preview what Groundwork would change before applying. |
chezmoi apply | Apply the source repo to the home directory. |
groundwork-restore | Restore the first-run backup of managed files and macOS defaults. Does not uninstall apps or undo Homebrew upgrades. |
groundwork-doctor | Read-only machine health report. It covers the shell runtime (managed zsh installed, registered, selected as your login shell, and actually running here) and Docker: daemon reachability, log rotation, image store, disk usage, and leftover containers, images, and volumes, each with owner-scoped cleanup guidance. It never deletes or changes anything. |
groundwork-doctor --shell | Run only the shell runtime section: managed zsh installed, registered, selected as login shell, and running here. |
groundwork-doctor --runtimes | Flag any mise-managed runtime that was adopted inside the five-day release floor. This closes a real gap: a cooldown only filters what you acquire — it never retires a version already on disk, so anything installed before the floor existed stays until something says so. It reads the release date from the tool's own backend rather than from mise's upgrade warning, which only appears when mise's version cache happens to be cold. |
groundwork-doctor --docker | Run only the Docker section of the health report. |
groundwork-docker-tidy | Dry-run Docker tidy, by enumeration: every image labeled dev.roost.ephemeral=true is inspected individually and reported as eligible (its strict-parsed dev.roost.built label is past the 72-hour grace, every tag sits in the scratch namespace */scratch:*, and no container — running or stopped — references it), retained (inside the grace window), protected (a non-scratch tag or a container reference refuses deletion — a scratch image retagged groundwork:latest keeps its label, so the tag check is the backstop), or unverified (missing jq, or a missing or malformed build label — retained and explained, never "probably old"); exited containers carrying the label are judged by the same grace window against their CreatedAt. The label is the consent, so your real groundwork image, base images, and other projects' images are structurally out of reach — and dangling images and builder cache are daemon-wide state this command never touches. See Platforms for the ephemeral-build contract. |
groundwork-docker-tidy --yes | Remove the eligible set: exited containers carrying the label whose CreatedAt is past the same 72-hour grace (container state under an ephemeral image is disposable only after the grace, and the status is re-checked immediately before removal), then each eligible image — deduplicated by image ID, re-checked immediately before deletion, and deleted by explicit image ID, never by a broad prune. A multi-tag image that only partly cleans up is reported as partially cleaned, naming the removed tags and why the image stayed. Weekly, or before a large build, is plenty; update-all prints a one-line nudge when tidy-eligible leftovers have piled up. |
groundwork-docker-cache-tidy | Dry-run preview of the daemon-wide cleanup: stopped containers, dangling images, and builder cache from every project on this machine, not just Groundwork. That is exactly why it is a separate command — it says what it touches, and update-all and scheduled agent paths never invoke it. |
groundwork-docker-cache-tidy --yes | Apply the daemon-wide cleanup: prune stopped containers and dangling images, and prune builder cache toward a 5 GB retention target. --keep-storage asks Docker to prune eligible cache for the selected builder while retaining a target — it does not guarantee total cache lands at or below the number. Never volumes, never tagged images. |
#The shell runtime
Shell adoption and Ctrla then ShiftY are covered by automated tests and verified on Apple Silicon macOS. Intel macOS, native Linux, and WSL2 receipts are still being collected — and Groundwork's rule is that support follows verification, not intent — so treat those platforms as provisional for these two commands until the receipts land. Recovery (--revert) is designed to work regardless, including with Homebrew broken or missing.
Groundwork owns the interactive shell itself, not only its configuration. The zsh that runs your prompt, plugins, completions, and tmux integration is the one Homebrew installs, so it behaves the same on macOS, Linux, and WSL2 and update-all keeps it current along with everything else. Your operating system's own shell is never modified or removed — it stays as the recovery path.
Adopting it is a deliberate step, never something an apply does behind your back, because it changes your account's login-shell record and needs sudo to register the shell in /etc/shells. It also never replaces the shell process you are sitting in: new terminals pick it up, and the command prints an exec line if you want to switch the current one immediately.
Recovery is designed for the bad day. Adoption records the exact login shell you had first, so --revert restores that shell rather than guessing a platform default — and both --status and --revert work with Homebrew missing or broken, since that is precisely when you need them. Groundwork never modifies or removes your operating system's shell.
groundwork-shell-adopt | Make Groundwork's Homebrew zsh your login shell: registers it in /etc/shells (idempotent, needs sudo), runs chsh, then verifies the account record actually changed. |
groundwork-shell-adopt --status | Report the shell runtime state — managed zsh and version, the account's login shell, the $SHELL session value, the recorded previous shell, and /etc/shells registration — and change nothing. |
groundwork-shell-adopt --revert | Restore the login shell you had before adopting — the exact one, recorded at adoption, not a guessed default (on Linux that is often bash, not zsh). It deliberately works with Homebrew missing or broken, because that is the incident it exists for. |
groundwork-shell-adopt --revert-to <shell> | Restore a specific login shell, for the case where no previous one was recorded. |
#Shell aliases and search
ll | Detailed file listing with hidden files, Git status, and directories first. |
lt | Tree view of the current folder, two levels deep; the quick shape-of-a-repo view. |
ltt | Tree view, three levels deep, when lt is not enough. |
lg | Open lazygit. |
vim / vi | Open Neovim. |
cat | Use bat for syntax-highlighted file viewing. |
z name | Jump to a recent/frequent folder with zoxide. |
| CtrlR | Search shell history with Atuin. |
atuin ai inline | Run Atuin's opt-in English-to-shell assistant after setup. |
| AltC | Fuzzy-pick a folder, preview it as a tree, and cd into it. |
| CtrlT | Fuzzy-pick files with a bat preview and insert the chosen paths into the current command. |
mkdir -p folder | Create a folder, including parent folders if needed. |
pwd / open . | Print the current folder / open it in Finder. |
rg text / fd name | Search file contents / find files by name. |
rga text | Search hidden and gitignored files too, while still skipping .git internals. |
rgf [text] | Fuzzy-pick ripgrep results, preview with bat, and open the selected line in the editor. |
y | Open Yazi, a visual file browser with inline preview; quit to land the shell in whatever folder you were browsing. |
largest [path] | Show the 50 largest files and folders under a path, then print a cleanup guide that routes each kind of result to its owning tool. |
largest --files / | Show only files on the startup filesystem. A complete macOS scan requires Full Disk Access for the terminal. |
largest --folders ~ | Show only folders under your home folder. Add -n N to change the result count. |
#tmux commands
tmux new -s name | Start a named tmux session. |
tmux attach -t name | Attach to an existing session. |
tmuxp load .tmuxp.yaml | Start a reusable project layout from a checked-in config file. |
tmuxp freeze > .tmuxp.yaml | Capture the current session as a starter layout config. |
tmux-fresh | Start tmux without restoring the previous resurrect snapshot. |
~/.config/tmux/plugins/tpm/bin/update_plugins all | Update tmux plugins from a normal shell when TPM's tmux pane is hard to read. |
| Ctrla then ShiftY | Copy the last completed command and its output into a tmux buffer (and the clipboard when supported), selected by semantic prompt marks; a platform + working-directory line is prepended so pasted output tells an agent where it ran. Review for secrets before pasting into an AI tool. |
| Ctrla then ShiftR | Repo picker popup: fuzzy-search every repository discovered under your configured roots, preview its git status, and jump to (or open) its lazygit window. See tmux repo windows. |
| Ctrla then ShiftG | Open a lazygit window for every repository with uncommitted changes (groundwork-repos changed). |
| Ctrla then z | Zoom the active pane to fill the screen; press again to restore. The status line shows Z while zoomed — this is what happened if a pane suddenly took over the screen. |
| Ctrla then x | Close the active pane. It asks first, because x sits next to z (zoom). |
| Ctrla then Ctrls | Save a tmux-resurrect snapshot now. |
| Ctrla then Ctrlr | Restore the last tmux-resurrect snapshot. |
| Ctrla then ShiftU | Update tmux plugins with TPM. Press Esc or Enter if the update pane does not repaint. |
| Ctrla then ShiftI | Install missing tmux plugins with TPM. |
| Ctrla then r | Reload the tmux config. |
| Ctrla then P | Rename the active pane. |
| Ctrla then , | Rename the active window. |
| Ctrla then & | Close the current window and all panes inside it. |
tmux kill-session -t name | End a named tmux session. |
tmux kill-server | End every live tmux session; snapshots are separate. |
| Alth/j/k/l | Move between tmux panes and Neovim splits with the same keys. |
#Mac and display commands
defaultbrowser | List or set the default browser. After setup, run defaultbrowser zen. |
browser-extensions | List or open the recommended extension links for Zen, Chrome, and Dia. |
raycast-extensions | List or open the recommended Raycast Store entries for browser bookmarks, tabs, Anybox, GitHub, Homebrew, project openers, and optional AI. |
betterdisplaycli | BetterDisplay's CLI for display automation. |
open -a Zen | Open a macOS app from the shell. The zen alias does this for Zen. |
#Practice
Ask for help first
Run groundwork-help, then groundwork-help update, then groundwork-help project. Notice which commands are aliases, functions, keys, or real executables.
Trace one command
Run which groundwork-help, which new-project, and type update-all. That teaches where commands come from: installed scripts, shell functions, and aliases.