Skip to content

CLI Reference

The dotfiles CLI is organized around a subject-first command hierarchy (dotfiles <subject> <verb> [args]):

Terminal window
# Managed tool configurations (.tool.ts) & packages
dotfiles tool list
dotfiles tool info fzf
dotfiles tool which fzf
dotfiles tool which --bin fzf
dotfiles tool install fzf
dotfiles tool uninstall fzf
dotfiles tool update fzf
dotfiles tool check --json
dotfiles tool validate fzf --json
dotfiles tool files fzf
dotfiles tool scaffold
dotfiles tool add owner/my-tool # example: a repository publishing my-tool.tool.ts
# System, binary, and storage path queries
dotfiles path
dotfiles path list
dotfiles path get target
dotfiles path get binaries
# Interactive shell integration & collision audits
dotfiles shell init zsh
dotfiles shell audit
# Isolated dotfiles virtual environments
dotfiles venv list
dotfiles venv create myenv
dotfiles venv delete myenv
# System state, drift detection, and orchestration
dotfiles state generate
dotfiles state diff
dotfiles state cleanup
dotfiles state log fzf --tail 50
# Download cache cleanup
dotfiles cache clear
# Web dashboard UI
dotfiles dashboard
dotfiles dashboard start --port 8080
# AI Agent skill definitions
dotfiles skill
dotfiles skill copy .agents/skills/
# Self-management
dotfiles self version
dotfiles self upgrade
dotfiles self upgrade --check
# Top-level convenience shortcuts
dotfiles g # shortcut for dotfiles state generate
dotfiles i fzf # shortcut for dotfiles tool install fzf
dotfiles u # shortcut for dotfiles tool update
dotfiles version # shortcut for dotfiles self version

For everyday convenience, the most high-frequency commands provide top-level root shortcuts (registered as hidden commands to preserve clean --help output) along with single-letter aliases:

ShortcutCanonical CommandDescription
dotfiles generate, dotfiles gdotfiles state generateCompile and link shims, symlinks, blocks, and templates
dotfiles install [tool...], dotfiles idotfiles tool install [tool...]Install one or all configured tools
dotfiles update [tool...], dotfiles udotfiles tool update [tool...]Upgrade tools to their latest available release
dotfiles versiondotfiles self versionPrint the dotfiles CLI version

Inside their respective domains, the same single-letter aliases are supported:

  • dotfiles state g -> dotfiles state generate
  • dotfiles tool i -> dotfiles tool install
  • dotfiles tool u -> dotfiles tool update

Manage cached upstream archives and binaries under paths.generatedDir/cache/downloads.

Remove cached downloads for versions no longer installed. Keep downloads belonging to a currently installed version of any tool, including downloads shared by tools. Use the recorded installed versions, including pinned versions, rather than the latest version available upstream. Accept no positional arguments or command-specific flags.

Successful installations record download ownership, including cache hits, and run this cleanup automatically by default. Configure the policy with downloader.pruneCache. An explicit --prune-cache=true or --prune-cache=false overrides configuration for the current command. Ownership is still recorded with that flag, so a later manual clear can prune those versions. Manual clearing bypasses the automatic policy and also works when downloader.cache.enabled is false. Failed installations do not change ownership or trigger pruning. Cleanup errors after an installation are warnings; errors during manual clearing fail the command.

Match downloads cached before ownership tracking against recorded download URLs and configured sources for installed versions. Scan both the current layout and the older separate metadata/ and binaries/ layout. Remove entries without an installed match and unusable current records. Keep shared legacy blobs whenever any installed URL references them. If an older installation records only latest, keep downloads from its configured release repository until a successful install records a concrete version. Protect downloads used by an installation in progress. The manual command reports the number of removed downloads and bytes reclaimed, and warns about skipped unsafe or unrecognized entries, on stderr in both output modes. It leaves other caches, installed binaries, and the installation registry untouched. With --dry-run, report that cleanup was skipped and remove nothing.

Terminal window
dotfiles tool update --prune-cache=false
dotfiles cache clear --prune-cache=false # manual cleanup still runs
dotfiles cache clear --dry-run

Commands that manage configured tools, lifecycles, and binary lookups.

Lists all configured tools, including their installation method, status, version, and binaries.

  • --json: Output tool list in JSON format.

Displays detailed metadata, dependencies, configuration paths, and on-disk binary locations for a specific tool.

  • --json: Output tool metadata and locations in JSON format.

Finds the .tool.ts configuration file that configures a tool or binary name. When passed --bin, resolves and prints the absolute path of the installed executable binary on disk.

  • --bin: Output the path to the installed binary executable instead of the configuration file.
  • --json: Output result in JSON format.

(Alias: i, Root shortcuts: dotfiles install, dotfiles i)

Installs the named tools, by tool name or by binary name. With no argument, installs every configured tool, in dependency order.

Named disabled tools, including tools disabled by a non-matching platform block, are skipped with [<tool>] Skipping installation: tool is disabled for this configuration at INFO level on stderr. Skipping leaves the exit status at 0 and continues to the next named tool without installation or artifact generation. --force does not override a disabled tool. Batch installation skips disabled tools silently; quiet and shim modes suppress the INFO message.

  • -f, --force: Force reinstallation even if already installed.
  • --shim-mode: Quiet output, used by generated shims when they install on first use.

Removes installed tools and their associated binaries, shims, and symlinks. With no argument, uninstalls every configured tool in reverse dependency order.

(Alias: u, Root shortcuts: dotfiles update, dotfiles u)

Updates installed tools to their latest available release. With no argument, updates all installed tools. Tools that are not installed, disabled tools, and tools with no installation method are skipped during batch updates. Every other tool a batch update cannot update, such as one whose installation record cannot be read, is logged with its cause, and the update goes on to the next tool.

Exit status: 0 when every requested tool was updated or was left alone by design: already up to date, ahead of the latest release, pinned, not installed or disabled during a batch update, or skipped during a batch update because its installation method cannot check for updates. Non-zero when any tool could not be updated: its installation record could not be read, its update check failed, or its reinstall failed. Updating named tools stops at the first such tool. Updating everything goes on to every other tool first, logging each failure with its cause, and then exits non-zero. A tool name that is not configured, and a single named tool that is not installed, also exit non-zero; among several named tools, one that is not installed is skipped. <binary> @update from a shim exits with the status of update.

A tool whose configuration pins a version is not updated, whatever its installation method. A version is pinned when the one its installation asks for is anything other than "latest", and it is named in one of two places:

  • .version(), which counts as a pin whatever the installation method. update reports Tool "<tool>" is pinned to version `<version>`. Set version to "latest" in the tool config to enable updates.
  • An install parameter, for the methods that take one: version for github-release, gitea-release, apt, dnf, pacman, npm and uv, and source.version for dmg and pkg installed from a GitHub release. The parameter takes precedence over .version(), so when both are set it is the parameter that pins the tool, and update names it: Tool "<tool>" is pinned to version `<version>` by its "<parameter>" install parameter. Set "<parameter>" to "latest" in the tool config to enable updates.

This holds for named tools, for updating everything, for <binary> @update from a shim, and for the dashboard’s update action, with or without --force. Nothing is checked upstream or installed for the tool, update exits successfully, and the dashboard returns the same message as its error. tool check still reports a newer upstream release for a pinned tool, since reporting installs nothing.

Some installation methods have no way to learn the latest version upstream: manual, curl-binary, curl-tar, curl-script, zsh-plugin, and dmg/pkg downloaded from a direct URL rather than a GitHub release. Nothing can tell whether such a tool is current, so update never reports it as up to date:

  • Named tools (dotfiles tool update <tool>, <binary> @update from a shim, and the dashboard’s update action): warns Update check not supported for installer "<method>", performing regular install instead and reinstalls the tool, with or without --force.
  • Updating everything (no tool names): warns Update check not supported for installer "<method>" and skips the tool. With --force it is reinstalled like every other installed tool.

Reinstalling such a tool records the version the installer detects, such as through the versionArgs of curl-script. If the installer detects none, the reinstall records a new YYYY-MM-DD-HH-MM-SS timestamp. It never records the version the previous installation left.

A tool installed at a version newer than the latest release upstream, such as a prerelease or a release upstream has since withdrawn, is never moved back to that older release. update reports <installed> is ahead of the latest known version (<latest>) and leaves the tool alone. With --force it reinstalls the installed version, announced as Force updating: reinstalling installed version <installed>, which is ahead of the latest known version (<latest>). To move to the older release, run dotfiles tool install --force <tool>, which installs the release the configuration resolves.

A forced reinstall of a tool that had no update finishes with Successfully reinstalled version <version>; Successfully updated to version <version> is reported only for an update, or for a reinstall of a tool nothing could check.

A tool counts as up to date only when its installation method’s query says so. The update check fails when that query fails, prints no version, or cannot tell a current package from a failed lookup. Examples are a registry that cannot be reached, an apt, brew, dnf or pacman package that is not installed, or a github-release or gitea-release tool without a valid repo. dotfiles tool update <tool> then fails with the query’s error, which names the command and either what it printed or the line of its answer that decided. Updating everything logs Update check failed: <error> for the tool and moves on to the next one. --force does not bypass a failed check, named or not; dotfiles tool install --force <tool> reinstalls a tool without checking upstream.

The dashboard’s update action makes the same decisions as dotfiles tool update <tool>. A failed check answers with the query’s error and installs nothing, and a tool that is not installed is refused. A tool whose check finds no newer release is not reinstalled; it is reported as up to date, or as <installed> is ahead of the latest known version (<latest>) when the installed version is newer.

  • -f, --force: Re-download and reinstall even if already up to date. A failed update check still fails the update.
  • --shim-mode: Used by generated shims running <binary> @update, which print nothing of their own. update then reports only what became of the tool: that it is pinned, already up to date, ahead of the latest release, moving to a new release, updated, or reinstalled without an update check. The progress of checking and installing is left out, and errors are reported as always.

Checks available updates from upstream releases without installing.

Each tool is reported with one status:

StatusOutputMeaning
update-available<tool>: update available (<installed> -> <latest>)A newer release counts as an update.
up-to-date<tool>: up to date (<installed>)The installed version is the latest, or no newer one counts as an update (the package manager says so, or updateCheck.constraint excludes it).
ahead-of-latest<tool> (<installed>) is ahead of the latest known version (<latest>)The installed version is newer than the latest release upstream. tool update never replaces it with the older release.
unsupported<tool>: update check not supported (<method>)The installation method cannot check for updates (see tool update), so nothing was compared.
not-installed<tool>: not installed (latest: <latest>), or <tool>: not installeddotfiles has not installed the tool, so there is nothing to compare. The latest release is named when the installation method can find it without an installation. brew, apt, dnf and pacman can only describe an installed package, so they are not asked.

In agent mode (AGENT=1) each tool is one line, tool:<tool> status:<status> current:<installed> latest:<latest> cached:<true|false>, or tool:<tool> status:unsupported current:<installed> installer:<method>. current is empty for a tool that is not installed.

A tool is reported as up to date only when its installation method’s query says so. When the query fails, the check fails, whether the tool is installed or not (see tool update); tool check logs Update check failed: <error> for that tool and leaves it out of its plain and agent-mode output. A tool whose installation record cannot be read is logged as Reading the installation record failed: <error> and left out the same way. Under --json, either is listed with the status failed.

Exit status: 0 unless the check of a tool failed, whatever the checks found, including an available update, a tool that is not installed, and an installation method that cannot check for updates. Disabled tools, tools with no installation method, and tools whose update checks are turned off with updateCheck.enabled are skipped, named or not. Non-zero when the check of any tool failed, or when a named tool is not configured, which fails before anything is checked. tool check still checks and reports every other tool first, and under --json prints the whole array before exiting.

  • --json: Output update status in JSON format. Each entry carries tool, status, currentVersion, latestVersion, and cached. status is one of the statuses above, or failed for a tool whose check failed, whose entry also carries error, the cause that was logged. currentVersion is absent for a tool that is not installed or whose installation record could not be read, and latestVersion when nothing upstream named one.

Validates tool configuration files for syntax, schema, or structural errors, then type-checks the TypeScript configuration.

A tool that breaks a load-time check fails the configuration load, as it does for every other command, so validate exits non-zero with that error instead of listing it among its findings (and prints no JSON under --json).

The type-check runs the TypeScript compiler over the CLI-owned .generated/tsconfig.json (regenerated first, so the bin-name registry is current) and reports each diagnostic as a validation error attributed to the tool whose .tool.ts it is in, with the file, line, and column. The compiler is the tsc binary declared by a configured tool — the scaffolded typescript.tool.ts installs microsoft/typescript-go pinned to typescript/v7.0.2 — and is run from that tool’s current directory; it is deliberately not exposed on PATH, so it never shadows another project’s TypeScript. When no tool declares tsc, or the tool is not installed yet, validate fails with a message naming dotfiles tool scaffold and dotfiles tool install typescript; it never skips silently. A JSON-configured project has nothing to type-check, and --dry-run skips the step because the generated program is not written to disk; both are announced.

  • --json: Output validation results in JSON format (type-check diagnostics appear in errors).

Displays a tree view of files in the tool installation directory or lists all managed files.

  • --json: Output file tree in JSON format.

Writes starter .tool.ts configuration files into the primary tool configs directory, creating that directory if it does not exist. Loading a configuration never creates tool files. When a name is provided, generates a single starter <name>.tool.ts file.

An existing file is left untouched, so running it again adds what is missing without discarding local edits.

  • -f, --force: Overwrite tool configurations that already exist.

Downloads a remote tool configuration into the first configured toolConfigsDir directory (normally tools/ in your dotfiles project). The tool name is the repository name: a repository named my-tool must publish my-tool.tool.ts.

Accepted argument forms, using an example repository owner/my-tool:

Terminal window
dotfiles tool add owner/my-tool
dotfiles tool add https://github.com/owner/my-tool
dotfiles tool add http://github.com/owner/my-tool
dotfiles tool add github.com/owner/my-tool
dotfiles tool add owner/my-tool.git
dotfiles tool add owner/my-tool/
dotfiles tool add owner/my-tool.tool.ts

The .git, trailing /, and .tool.ts forms also work with the GitHub URL prefixes above. Do not combine .git with a trailing /: .git is stripped before /, so owner/my-tool.git/ retains .git in the repository name and requests my-tool.git.tool.ts from owner/my-tool.git. A .tool.ts suffix selects the repository owner/my-tool, not a path inside it. File browser URLs containing /blob/ or /tree/ and subdirectory paths are not accepted. There is no option for selecting a branch.

Remote repository layout: Place <repo-name>.tool.ts at the root of the repository’s default branch, exporting a default defineTool configuration. For the example above:

my-tool/ # repository, on its default branch
└── my-tool.tool.ts

The command requests only this root file. It does not search tools/ or .dotfiles/, select another branch, or copy companion files used by imports, symlinks, templates, or shell configuration. Provide any required companion files separately. An upstream binary repository is usable only if it also publishes the required tool configuration at this location.

Fails with an error if the remote configuration is missing or the local file already exists without --force.

  • -f, --force: Overwrite existing tool configuration.

After adding: tool add only downloads the configuration. It does not generate shims or completions, load shell configuration, or install the tool binary. Review the downloaded configuration before generating or installing it, then run:

Terminal window
# Continue the owner/my-tool example from your dotfiles project
dotfiles generate # generate shims, completions, and shell integration
dotfiles install my-tool # install the configured tool immediately

dotfiles generate and dotfiles install are shortcuts for state generate and tool install. Alternatively, run a binary declared with a shim to trigger installation on first use; its name can differ from my-tool. Ensure your generated shell configuration is loaded when using shell aliases, functions, or completions.


Queries configured system, target, binary, cache, and storage directories.

With no arguments, dotfiles path prints all resolved directories. Specifying a path name (or using dotfiles path get <name>) prints that specific directory path.

Supported directory names: target, binaries, cache, dotfiles, generated, toolConfigs, shellScripts, home.

  • --json: Output paths in JSON format.

Prints all resolved configuration and runtime directories.

  • --json: Output directory list in JSON format.

Prints the absolute path of a specific configuration or runtime directory.

  • --json: Output result in JSON format.

Interactive shell integration, PATH exports, completion scripts, and collision audits.

Emits shell export strings and initialization hooks (similar to brew shellenv). Supports zsh, bash, powershell, and fish.

Detects collisions across aliases, functions, and binaries, and reports every shim dotfiles state generate would have to write over a file it did not create. Run it before dotfiles state generate --overwrite.

  • --json: Output conflict analysis in JSON format.

Manages isolated dotfiles environments — a directory with its own dotfiles.config.ts, tools/ and XDG_CONFIG_HOME, activated by prepending its bin directory to PATH. See virtual-environments.md. It is the dotfiles equivalent of a Python virtual environment, not a Python one.

Lists detected virtual environments in the current working directory and indicates which environment is currently active.

  • --json: Output environment list in JSON format.

Creates an environment directory, named env by default.

Removes an environment directory. On an interactive terminal it first asks Delete environment at '<dir>'? [y/N] and only y or yes deletes; anything else cancels. Without a terminal to ask on (pipes, CI, AGENT=1) it refuses and exits non-zero instead of deleting.

  • -f, --force: Skip the confirmation prompt. Required when there is no interactive terminal.

System state, drift detection, and orchestration.

(Alias: g, Root shortcuts: dotfiles generate, dotfiles g)

Writes the shims, symlinks, copies, shell initialization scripts and completions the configuration calls for, and removes the artifacts of declarations that have gone.

  • --overwrite: Replace files that the generator did not create, instead of leaving them in place. See shell audit for finding them first.

Inspects 3-way differences and drift status between repository declarations, the files currently on disk, and the recorded base state in SQLite.

Reports state across all symlinks, copies, templates, and managed blocks: in-sync, local-drift, upstream-update, conflict, missing, or unmanaged. When differences exist, prints a unified line diff.

  • --json: Output drift evaluation and diffs in JSON format.

Uninstalls every tool that is recorded as installed but is no longer configured or has been disabled, removing its binaries, shims and symlinks. Artifacts of tools that are still configured are reconciled by dotfiles state generate, not here.

Displays file operations and installation log entries.

  • -n, --tail <N>: Number of entries to show from the end of the log (default: 50).
  • --since <YYYY-MM-DD>: Only show operations recorded on or after that date.
  • --type <kind>: Filter by file kind (shim, binary, symlink, copy, config, completion, …).
  • --status: Show current file states for tools instead of operation history.
  • --json: Output log entries in JSON format.

Launches the local web dashboard visualization client and server.

  • -p, --port <port>: Dashboard HTTP port (default: 8080).
  • -H, --host <address>: Address to bind to (default: 127.0.0.1).

Starts the local HTTP dashboard server and prints its URL.


Prints the embedded dotfiles skill’s complete SKILL.md, including frontmatter, to stdout. Output is identical in human and agent modes. It works offline without configuration files or credentials. Output-write failures return an error. The command takes no positional arguments or command-specific flags.

Extracts the single bundled dotfiles skill and its references into <path>/dotfiles. It includes tool-creation instructions for ~/.dotfiles, preferring GitHub release binaries and Bun for npm packages. Existing bundled files are overwritten with the embedded contents.


CLI binary version and upgrade management.

Prints the CLI version string.

Upgrades or downgrades the dotfiles CLI binary from GitHub Releases. With a version argument, moves to exactly that release.

  • --check: Check for available updates without applying them.
  • -f, --force: Re-download and reinstall even if already up to date.
  • --prerelease: Consider prereleases when looking for the latest version.

The following flags are available on all commands:

  • -c, --config <path>: Path to configuration file (default: dotfiles.config.ts).
  • -d, --dry-run: Simulate operations without modifying the filesystem.
  • --prune-cache <bool>: Override automatic cleanup after successful installs. When omitted, use downloader.pruneCache, whose default is true. See cache cleanup for retention and manual clearing.
  • --trace: Enable source location tracing in logs.
  • --log <level>: Set log level (verbose, default, quiet).
  • --platform <os>: Override target platform (macos, linux, windows; darwin is accepted as a spelling of macos). Any other value is rejected.
  • --arch <arch>: Override target architecture (amd64, arm64).
  • --libc <libc>: Override the detected C library (gnu, musl, unknown), which is what ctx.systemInfo.libc reports on a Linux target. Off Linux there is no C library to select, so the flag is ignored and libc stays unknown. Any other value is rejected.
  • -v, --verbose: Enable verbose logging.
  • -q, --quiet: Enable quiet logging.
  • --version: Print the version and exit, like dotfiles self version.

--platform, --arch and --libc resolve to one target that governs the whole run: the configuration is loaded for it, install selects release assets for it, and every hook and function-valued install parameter reports it through ctx.systemInfo. Each flag that overrides what the machine reports is warned about, because the output of a run carried out for another machine otherwise looks like this machine’s.

The CLI automatically adapts its output stream based on the AGENT environment variable:

  • Agent Mode (AGENT=1): Token-conservative output designed for LLMs and automated agents:
    • JSON (--json) is minified onto a single line with zero extra whitespace.
    • Directory trees (dotfiles tool files) render using compact indented bullets (* file).
    • Terminal dividers and decorative whitespace are omitted.
    • Query outputs emit flat key-value pairs, such as the lines of tool check.
    • ANSI colors in diagnostic logs are suppressed.
  • Human Mode (AGENT=0 or unset): Visually polished interactive output:
    • JSON (--json) is pretty-printed with 2-space indentation.
    • Directory trees render with box-drawing glyphs (├─, └─, │ ).
    • Validation tags use structured tags ([OK], [WARN], [ERROR]).

dotfiles state generate writes the CLI’s own zsh completion script, so no tool configuration has to declare it.

  • The script is written to ${shellScriptsDir}/zsh/completions/_dotfiles. shellScriptsDir defaults to ${generatedDir}/shell-scripts, and the generated main.zsh adds that completions directory to fpath.
  • Subcommands that take a tool name (tool install, tool update, tool uninstall, tool which, tool files, state log, tool validate) complete it from the configured tools; tool which also completes configured binary names.
  • Reload completions with autoload -U compinit && compinit (or restart your shell) after running dotfiles state generate.
  • dotfiles completion zsh still prints the same script for manual use.