Getting started
zenops is a declarative system configuration tool. It reads a TOML config
from ~/.config/zenops/config.toml and keeps your shell environment,
aliases, dotfile symlinks, and $PATH in sync with what you’ve declared.
Run zenops apply to make the system match the config; run zenops status
to see what would change without touching anything.
Install
cargo install zenops
zenops supports macOS, Fedora 42, Ubuntu 24.04 LTS, and Arch Linux. A host
outside that matrix fails to start with Unsupported host: … rather than
degrading silently.
Initialise a config
The fastest path, if you already have a zenops config repo:
zenops init git@github.com:you/dotfiles.git --apply
zenops init clones the repo into ~/.config/zenops/, validates the
config.toml, and (with --apply) chains into zenops apply. From a clean
start, write ~/.config/zenops/config.toml by hand — the
configuration reference documents every section.
A minimal config:
[user]
name = "Ada Lovelace"
email = "ada@example.com"
[shell]
type = "bash"
[shell.environment]
EDITOR = "hx"
[shell.alias]
ll = "ls -la"
The apply loop
zenops status # see what would change
zenops apply # make the system match the config
zenops doctor # diagnose the environment
zenops pkg # list configured packages and their detect state
status is read-only. apply writes files, sets up symlinks, and updates
shell init under ~/.config/. Both speak structured output: pass
-o json for NDJSON events suitable for piping into another tool.
What this site documents
- The configuration reference — every section, every field, every enum variant, generated from the schema that ships with each release.
- The command-line interface — every subcommand and flag, generated from the clap definitions.
The same site is served by zenops docs (embedded in the binary, works
offline) and is published to GitHub Pages at https://bjorn-ove.github.io/zenops/.
Configuration file
The ~/.config/zenops/config.toml reference. Pick a section or type from
the sidebar, or use the search box to filter across field names, types,
and descriptions. Each enum variant carries a copy-paste TOML example, and
deep links like #/PkgConfig$field-detect survive bookmarks and shares.
The data driving this page is generated from zenops schema at release
time — what you see matches the binary you have installed.
Command-Line Help for zenops
This document contains the help content for the zenops command-line program.
Command Overview:
zenops↴zenops apply↴zenops status↴zenops pkg↴zenops repo↴zenops repo status↴zenops repo diff↴zenops repo add↴zenops repo pull↴zenops repo commit↴zenops repo push↴zenops init↴zenops import↴zenops doctor↴zenops schema↴zenops completions↴zenops docs↴
zenops
ZenOps: your system’s calm overseer
Usage: zenops [OPTIONS] <COMMAND>
Subcommands:
apply— Reconcile the live system withconfig.toml: prompt per change (unless--yes), write generated files, create symlinks, run shell init for anypkgthat needs it. Honours the zenops repo’s git state — a dirty repo prompts for commit-and-push or aborts under--yeswithout--allow-dirtystatus— Read-only sibling ofApply: report what would change without touching the filesystempkg— List every configured package and whether its dependencies are metrepo— Git pass-through against the zenops config repo (~/.config/zenops). Lets the user run common git operations withoutcd-inginit— Set up~/.config/zenops. With a URL, clones an existing zenops config repo and validates it has aconfig.toml. Without a URL, bootstraps a brand-new repo on disk by interactively prompting for shell, name, and email, writing a minimalconfig.toml, and making the initial commit. The bootstrap form refuses to run if~/.config/zenopsalready exists (even empty); the clone form allows an empty target. Authentication (SSH key, HTTPS credential helper) uses whatever git is already configured to useimport— Take an existing on-disk config under~/.config/<x>/or~/.<x>into the zenops repo: copy the files intoconfigs/<key>/, replace the originals with symlinks, and append a[[pkg.<key>.configs]]block toconfig.toml. Strict path classification — anything other than the two supported shapes is rejecteddoctor— Diagnose the local environment: config dir, git, shell, package manager, and package health. Read-only; keeps running even whenconfig.tomlis missing or fails to parse, so it stays useful on a broken machineschema— Dump JSON Schema for every structured surface (command output events and theconfig.tomlinput) as a single bundle to stdout. The schema shape is versioned under the zenops crate version embedded in the bundlecompletions— Print a shell completion script for zenops to stdoutdocs— Serve the embedded documentation site over HTTP on localhost. The site bundles the configuration reference (driven by the same schema aszenops schema), the CLI reference, and prose chapters. Works offline — every asset is embedded in the binary
Options:
-
--color <COLOR>— When to colorize outputDefault value:
autoPossible values:
auto: Color when the target stream is a TTY andNO_COLORis unsetalways: Force color regardless of TTY orNO_COLORnever: Never emit ANSI escapes
-
-o,--output <OUTPUT>— How to render status and apply eventsDefault value:
humanPossible values:
human: Human-readable text to stdout, with optional ANSI colorjson: Newline-delimited JSON to stdout, one event per line
zenops apply
Reconcile the live system with config.toml: prompt per change (unless --yes), write generated files, create symlinks, run shell init for any pkg that needs it. Honours the zenops repo’s git state — a dirty repo prompts for commit-and-push or aborts under --yes without --allow-dirty
Usage: zenops apply [OPTIONS]
Options:
-p,--pull-config— Pull the latest version of the config using git pull –rebase in the zenops config directory-y,--yes— Apply every change without prompting-n,--dry-run— Show each prompt with its diff, but apply nothing--allow-dirty— Proceed even when the zenops config repo has uncommitted changes. Required alongside--yeswhen the repo is dirty; without it,--yeson a dirty repo aborts so automation surfaces divergence instead of silently applying uncommitted state
zenops status
Read-only sibling of Apply: report what would change without touching the filesystem
Usage: zenops status [OPTIONS]
Options:
-d,--diff— Show a diff of what would change-a,--all— Also list items that already match the desired state
zenops pkg
List every configured package and whether its dependencies are met
Usage: zenops pkg [OPTIONS] [PATTERN]...
Arguments:
<PATTERN>— Only list packages whose name or key contains one of these substrings (case-insensitive). Multiple patterns are ORed —zenops pkg git curlshows both
Options:
--all— Include packages withenable = "disabled"--all-hints— Show every install hint, not just the one for the detected package manager-v,--verbose— Show diagnostic details (the detect strategy that matched)
zenops repo
Git pass-through against the zenops config repo (~/.config/zenops). Lets the user run common git operations without cd-ing
Usage: zenops repo <COMMAND>
Subcommands:
status—git status [-- <files>...]in the zenops repodiff—git diff [-- <files>...]in the zenops repoadd—git add [-- <files>...]in the zenops repopull—git pullin the zenops repo.--rebaseaccepts the same values as upstream git (true,false,merges,interactive); a bare--rebase(no value) maps to--rebasewith no argumentcommit—git commitin the zenops repopush—git pushin the zenops repo
zenops repo status
git status [-- <files>...] in the zenops repo
Usage: zenops repo status [FILES]...
Arguments:
<FILES>— Optional path filter passed after--
zenops repo diff
git diff [-- <files>...] in the zenops repo
Usage: zenops repo diff [FILES]...
Arguments:
<FILES>— Optional path filter passed after--
zenops repo add
git add [-- <files>...] in the zenops repo
Usage: zenops repo add [FILES]...
Arguments:
<FILES>— Files to stage
zenops repo pull
git pull in the zenops repo. --rebase accepts the same values as upstream git (true, false, merges, interactive); a bare --rebase (no value) maps to --rebase with no argument
Usage: zenops repo pull [OPTIONS]
Options:
-
-r,--rebase <REBASE>— Optional--rebase[=value].Noneruns a plain pullPossible values: ``,
false,true,merges,interactive
zenops repo commit
git commit in the zenops repo
Usage: zenops repo commit [OPTIONS]
Options:
-a,--all— Pass-ato stage all tracked, modified files first-m,--message <MESSAGE>— Commit message; if omitted git opens the editor as usual
zenops repo push
git push in the zenops repo
Usage: zenops repo push
zenops init
Set up ~/.config/zenops. With a URL, clones an existing zenops config repo and validates it has a config.toml. Without a URL, bootstraps a brand-new repo on disk by interactively prompting for shell, name, and email, writing a minimal config.toml, and making the initial commit. The bootstrap form refuses to run if ~/.config/zenops already exists (even empty); the clone form allows an empty target. Authentication (SSH key, HTTPS credential helper) uses whatever git is already configured to use
Usage: zenops init [OPTIONS] [URL]
Arguments:
<URL>— Git URL to clone (SSH or HTTPS). Passed verbatim togit clone. Omit to bootstrap a fresh repo at~/.config/zenopsinstead of cloning
Options:
-b,--branch <BRANCH>— Check out this branch or tag after cloning (default: remote’s HEAD). Only valid with a URL--apply— After cloning, runzenops apply-y,--yes— With--apply, apply every change without prompting (equivalent tozenops apply --yes). Only meaningful together with--apply
zenops import
Take an existing on-disk config under ~/.config/<x>/ or ~/.<x> into the zenops repo: copy the files into configs/<key>/, replace the originals with symlinks, and append a [[pkg.<key>.configs]] block to config.toml. Strict path classification — anything other than the two supported shapes is rejected.
Re-running import on an already-managed root reconciles: new files in the directory are added to the entry’s symlinks array, and array entries whose home-side counterpart is gone are dropped (along with the repo-side copy).
Usage: zenops import [OPTIONS] <PATH>
Arguments:
<PATH>— Path to take over. Absolute, cwd-relative, or shell-expanded (e.g.~/.config/foo). Must canonicalize to either~/.config/<x>or~/.<x>
Options:
--pkg <PKG>— Override the derived pkg key. Defaults to<x>(with the leading dot stripped for~/.<x>shapes)--source <SOURCE>— Override the in-repo destination, relative to~/.config/zenops. Defaults toconfigs/<pkg-key>--brew <PKG>— Brew package(s) to record underinstall_hint.brew.packages. Repeatable. Required for new pkgs unless--no-install-hint--no-install-hint— For new pkgs, writeinstall_hint.brew.packages = []instead of prompting for a brew package-y,--yes— Accept every prompt with its default; required to run without a TTY when prompts would otherwise be needed-n,--dry-run— Show the planned import without writing anything
zenops doctor
Diagnose the local environment: config dir, git, shell, package manager, and package health. Read-only; keeps running even when config.toml is missing or fails to parse, so it stays useful on a broken machine
Usage: zenops doctor
zenops schema
Dump JSON Schema for every structured surface (command output events and the config.toml input) as a single bundle to stdout. The schema shape is versioned under the zenops crate version embedded in the bundle
Usage: zenops schema
zenops completions
Print a shell completion script for zenops to stdout.
Normally sourced automatically by the built-in zenops pkg; you don’t need to invoke this by hand.
Usage: zenops completions <SHELL>
Arguments:
-
<SHELL>— Shell to generate completions forPossible values:
bash,elvish,fish,powershell,zsh
zenops docs
Serve the embedded documentation site over HTTP on localhost. The site bundles the configuration reference (driven by the same schema as zenops schema), the CLI reference, and prose chapters. Works offline — every asset is embedded in the binary
Usage: zenops docs [OPTIONS]
Options:
-
-p,--port <PORT>— Port to bind. Defaults to 0 (random ephemeral port); the bound URL is printed on startupDefault value:
0 -
--open— Open the served URL in the default browser after binding
This document was generated automatically by
clap-markdown.