Commands and usage
Use dotfiles to bring a machine into the state described by this checkout. Start with Getting started for a first installation, or the Windows guide for PowerShell examples.
The examples use the checkout behind your installed dotfiles launcher and
your saved profile. Before installation, use ./dotfiles.sh on Linux or
.\dotfiles.ps1 on Windows; see Wrapper bootstrap.
Update, remove, and check prompt when no profile is selected. Read-only list
needs an existing selection or an explicit --profile.
Everyday commands
Section titled “Everyday commands”| I want to… | Command |
|---|---|
| See the available tasks | dotfiles list |
| Preview an update | dotfiles update --dry-run |
| Sync the repository and apply updates | dotfiles update |
| Validate configuration and repository files | dotfiles check |
| Read the latest run | dotfiles log |
| Preview removal | dotfiles remove --dry-run |
Use --profile base or --profile desktop to override the saved role for one
run. Neither profile is a user-files-only mode.
Back up existing configuration before the first apply:
installing links can replace regular files and empty directories without a
backup. Changes to linked application settings may take effect immediately.
Apply configuration
Section titled “Apply configuration”Update
Section titled “Update”update is the default command: running dotfiles by itself applies an update.
Tasks inspect current state and avoid changes that are already satisfied.
The Update lifecycle explains the CLI release check,
repository synchronization, restarts, dependency updates, and partial results.
To work on symlinks, first preview that selection:
dotfiles update --only symlinks --dry-runAfter reviewing it, remove --dry-run to apply. Startup can still check for a
CLI update: filters select tasks, not startup behavior. Use the
lifecycle controls when you need to
keep a binary, checkout, or dependency set fixed.
Select tasks
Section titled “Select tasks”Use selectors from list, not package names or partial task names:
dotfiles listdotfiles update --only symlinks,git-hooks --dry-run--onlyruns the named tasks. Repeat the flag or separate selectors with commas.--skipexcludes tasks and takes precedence over--only.- Selectors match exactly after case, punctuation, and whitespace normalization. Full task labels also work; arbitrary substrings do not.
- Unknown selectors and a filter selecting no tasks are errors.
--only packagesmeans all active native packages, not a single package and not the AUR package list.
Dependencies are not automatically included by --only. An omitted
blocking prerequisite produces a warning and is assumed satisfied. Use
--with-deps to include both blocking prerequisites and ordering predecessors:
dotfiles list --graph update --only systemd --with-depsdotfiles update --only systemd --with-deps --dry-runInspect the graph first: this can add repository work, packages, AUR setup,
symlinks, and file permissions. --skip is applied after expansion, so it can remove a
prerequisite again. --with-deps is available only for update and update graphs.
Unattended runs
Section titled “Unattended runs”Select the profile explicitly, disable prompts, and require a complete result when automation depends on one:
dotfiles update --profile base --non-interactive --fail-on-skipThis applies configuration. Add --dry-run to preview instead.
Non-terminal stdin and JSON Lines output also disable prompts. Any present
CI variable (even CI=false) disables prompts and enables strict skip handling.
Tasks that are genuinely inapplicable are not failures.
Only one update, remove, or check can run against a repository at a time.
Previews count too; linked worktrees share the same lock. list and log
remain available while a run is active.
Dry-run scope
Section titled “Dry-run scope”--dry-run previews planned configuration changes. It is not a sandbox or a
promise of zero writes.
| Activity | What a preview still does |
|---|---|
| Wrapper bootstrap | Can download a binary, or build one with --build, before the CLI starts |
| CLI release check | Can read caches and query GitHub; does not replace the binary or write release caches |
| Repository task | Can query remote refs, but does not fetch or merge; omit it with --no-repo-update |
| Bookkeeping | Writes a run log and acquires the repository lock |
| Selection | Can save an interactive profile choice or an explicit --overlay |
| Inspection | Reads host state and invokes external tools; their effects are not sandboxed |
| Overlay scripts | Executes --check and, when needed, --dryrun; the scripts must honor those modes |
For discovery without task probes, use an existing binary’s list command.
It does not execute tasks or scripts, acquire the run lock, create a run log,
or save profile/overlay selections.
Discover tasks
Section titled “Discover tasks”dotfiles listdotfiles list --alldotfiles list --graph updatedotfiles list --format jsonThe normal listing groups selectors by update, remove, and check. It hides
tasks whose platform or configuration clearly rules them out; --all includes
them. A visible task is a possibility, not proof that its tools are installed
or that anything needs changing.
Graph output shows every node, including internal tasks, with selection labels:
default, requested, dependency, filtered, or skipped.
requires <- means the predecessor must succeed; after <- means wait for it
without inheriting its failure. Filters annotate the graph rather than hiding
its excluded nodes. Internal tasks cannot be selected directly.
Use --format plain for tab-separated records or --format json for JSON.
list still needs loadable configuration and an existing profile selection;
it never opens the profile prompt. Explicit linked-worktree overlays retain
their separate confirmation requirement.
Console output
Section titled “Console output”Check the header’s profile, platform, overlay, and dry-run indicator first. Tasks print as they finish, so output order is not configuration order.
| Status | Meaning |
|---|---|
✓ / CHANGED or PASSED | Changes applied, or a check passed |
~ / PLANNED | A dry run found changes to make |
○ / CURRENT | Already satisfied; shown with --verbose |
⊘ / SKIPPED | Work was not performed; read the reason |
⊘ / BLOCKED | A required predecessor did not complete successfully |
⊘ / INTERRUPTED | Work stopped during cancellation |
✗ / FAILED | An operation failed |
--verbose adds current tasks, decisions, and timings. --no-symbols uses the
text labels above; NO_COLOR disables color. Inapplicable and internal tasks
do not appear in normal rows or totals, but remain in logs.
Indented actions describe files or packages. The final counts describe
tasks, not the number of action lines. Failed, interrupted, blocked, and
skipped work appears before successful counts. Exit 0 with skipped work is
not necessarily a complete installation. Use --fail-on-skip when it must be.
Remove
Section titled “Remove”Preview with the original profile and overlay while their sources still exist:
dotfiles remove --dry-runRemove --dry-run only after reviewing the result. If your saved selection has
changed, pass the original --profile and --overlay explicitly.
| Removed integration | Result |
|---|---|
| Managed home links | Replaced with real copies of the configured sources |
| Managed Git hooks and launcher | Removed only if they still match their managed state |
| Active overlay scripts | Their removal actions run when their checks find managed state |
Remove is not rollback. The copies contain current configured content, not your pre-install files. A missing home target can also receive a copy; existing non-link targets and links that no longer point to the managed source are preserved. Keep the checkout until copying succeeds.
Packages, registry settings, PATH, services, system files, permissions, login shell, Git/agent settings, completions, editor extensions, and agent deployments remain. See Remove tasks before planning a cleanup.
check validates configuration and sources and runs available repository
analyzers. It does not install or repair configuration and has no --dry-run.
It does write a log, acquire the run lock, and resolve/save selections.
dotfiles checkThe config-diagnostics task fails on configuration diagnostics, including
warnings. Missing optional tools are visible skips; --fail-on-skip and CI
make them fatal.
See Testing for scoped checks and prerequisites. Task filtering cannot bypass malformed configuration loaded at startup.
After a failure, use the exact dotfiles log --id … -v command printed by the
CLI. IDs stay stable even after later runs; numeric history indexes do not.
dotfiles log # newest rundotfiles log --verbose # newest run, with diagnosticsdotfiles log --list # history and stable run IDsdotfiles log --list --format jsondotfiles log 2 # third-newest rundotfiles log --task symlinks --verbose # one task in the newest rundotfiles log --raw # original stored recordsUse the actual history ID with --id, optionally adding --task and either
--verbose or --raw. --id cannot be combined with an index, --list, or
--command; verbose and raw are mutually exclusive.
--command update, remove, or check filters history before selecting an
index. Historical install and uninstall filters remain supported; they
are not current execution commands.
Normal viewing shows actions, outcomes, warnings, context, and failed-command
output. Verbose adds task starts, checks, timings, and debug details.
An unchecked nonzero command exit is not necessarily a task failure: some
tools use exit codes to report state. Successful stdout is usually not saved;
--raw cannot recover output that was never retained. Oversized subprocess
output is marked truncated and is not accepted as a complete inventory.
Each restarted or elevated process has a separate log linked to its parent.
unfinished means no finish record exists; the process may still be running.
Retention targets the newest 50 logs without deleting active ones. Reading
logs does not start another logged run.
Log locations
Section titled “Log locations”DOTFILES_LOG_DIR overrides the location, including with a relative path.
Otherwise:
| Platform | Preferred location | Home-directory fallback |
|---|---|---|
| Linux | $XDG_STATE_HOME/dotfiles/logs | ~/.local/state/dotfiles/logs |
| Windows | %LOCALAPPDATA%\dotfiles\logs | %USERPROFILE%\AppData\Local\dotfiles\logs |
Empty or relative standard state/home variables are ignored. The final
fallback is ./dotfiles/logs. An unreadable directory is an error, not empty
history. Review logs for private paths, configuration, and tool output before
sharing them.
Repository and overlay paths
Section titled “Repository and overlay paths”--root . selects the checkout you are standing in. Without --root, dotfiles
tries DOTFILES_ROOT, candidate paths relative to its executable, then the
current directory. Wrappers set DOTFILES_ROOT to their own checkout.
--root chooses configuration, not the executable. An installed launcher
can still obtain a binary from another checkout. Use the intended checkout’s
wrapper or built binary when that distinction matters.
Use --overlay <PATH> for private or machine-specific additions. Unlike
--profile, an explicit overlay is saved for future runs, including during
check or dry-run; list does not save it. See Private overlays
for setup, path precedence, linked-worktree confirmation, merging, and scripts.
Wrapper bootstrap
Section titled “Wrapper bootstrap”The repository wrappers obtain the CLI and forward its arguments:
./dotfiles.sh list --profile base.\dotfiles.ps1 list --profile desktopIf a usable cached binary is absent, the wrapper downloads a release into
bin/ and verifies its SHA-256 checksum. It also verifies build provenance
when gh is available. Missing gh produces a warning; a failed verification
with gh present blocks bootstrap. See
Build provenance verification.
Even wrapper help, list, and dry-run can download files. Use an existing binary directly to avoid bootstrap.
The publisher comes from the checkout’s GitHub origin remote unless
DOTFILES_RELEASE_REPO=owner/repo explicitly selects another publisher.
Unsupported/missing remotes fail instead of falling back to this project’s
releases. Forks without release assets need a deliberate publisher choice or
a source build. The
setup guide explains both
routes. --build selects source compilation for that invocation only;
without it the wrapper uses its download/cached-binary route.
Release binaries retain their publishing repository for self-update.
Changing origin or the bootstrap override does not redirect an existing
binary’s updates. Normal development builds do not self-update.
After the launcher and path tasks succeed, open a new shell. The installed
launcher in ~/.local/bin delegates back to this checkout; it is not a
standalone installation. Keep the checkout at a stable path.
Shell completions
Section titled “Shell completions”The completions task installs Zsh or PowerShell registration. Open a new shell
after installation. Task completion uses the current binary’s read-only
discovery and carries forward --root, --profile, and --overlay; it does
not prompt for or save a profile.
For managed shell behavior beyond the CLI, see Application settings.
Command summary
Section titled “Command summary”| Command | Purpose |
|---|---|
update (default) | Apply configured state and update dependencies when their version rules allow it |
remove | Detach a limited set of integrations, not restore machine defaults |
check | Validate configuration and repository files |
list | Discover selectors or inspect a dependency graph |
log | Read retained runs |
help [command] | Show command-specific usage |
completions <shell> | Emit shell registration; hidden support command |
Command options
Section titled “Command options”Options may appear before or after an explicit command. With no command, they
apply to update. Use dotfiles <command> --help for full syntax, and
dotfiles --version or -V for the version.
| Option | Commands | Purpose |
|---|---|---|
-p, --profile; --root; --overlay | update, remove, check, list | Select role and configuration sources |
-n, --dry-run | update, remove | Preview planned changes |
--only; --skip | update, remove, check; list with --graph | Include/exclude selectors |
--with-deps | update; list with an update graph | Expand --only to predecessors |
--no-repo-update | update | Use current checkout content |
-v, --verbose | update, remove, check, log | Show diagnostics |
-q, --quiet | update, remove, check | Keep only warnings and incomplete outcomes |
--format human|jsonl | update, remove, check | Choose execution output |
--no-parallel | update, remove, check | Run selected work sequentially |
--non-interactive | update, remove, check | Disable prompts |
--fail-on-skip | update, remove, check | Fail on unmet applicable work |
--no-symbols | update, remove, check | Use text status labels |
--format table|plain|json | list; log with --list | Choose discovery/history output |
--graph update|remove|check | list | Inspect a command graph |
--all | list without --graph | Include clearly inapplicable tasks |
--skip-attestation | update, remove | Bypass self-update provenance, never checksums |
--skip-attestation does not affect bootstrap; DOTFILES_SKIP_ATTESTATION=1
affects both layers. Neither is a routine workaround for verification errors.
Selecting repository with both --only and --no-repo-update is an error.
Execution output for scripts
Section titled “Execution output for scripts”Quiet mode preserves logs and exit policy. Warnings and failed, blocked,
skipped, or interrupted rows remain on stderr. It conflicts with --verbose
and an explicit --format.
For a focused, non-interactive diagnostic stream, use JSON Lines:
dotfiles check --profile base --only config-diagnostics --format jsonlEach stdout line is one object with schema: 1, run_id, context, and
type. Record types include run_start, run_scope, run_context,
task_result, task_duration, message, and run_finish. Task results carry
IDs, selectors, statuses, reasons, and action counts; finish records include
outcome and exit code. Stored statuses use names such as ok, dry_run, and
not_applicable, rather than the human display labels.
JSON Lines disables prompts. Parse errors and logging warnings can still
appear on stderr; detailed actions and subprocess diagnostics remain in logs.
Group records by run ID: restarted/elevated children have their own IDs and
parent_run_id links. Tolerate additional fields/types and missing finish
records after a force quit.
Closing stdout does not cancel an update. A closed pipe stops further stdout output, but managed work continues.
Interrupting a run
Section titled “Interrupting a run”- Press Ctrl-C once to stop dispatching new work and wait for in-flight work.
- Press it again to request a force quit. An interactive prompt defaults to no.
- Confirming, or pressing Ctrl-C while that prompt is open, exits immediately. In non-interactive mode the second Ctrl-C force quits without asking.
Neither graceful cancellation nor force quit rolls back completed changes. Force quit can leave external installers running; inspect them before retrying.
Exit behavior
Section titled “Exit behavior”| Exit code | Meaning |
|---|---|
0 | Succeeded under the selected skip policy |
1 | Configuration/runtime failure, task failure, or unmet work under strict policy |
2 | Invalid command-line usage |
130 | Interrupted; a genuine task failure takes precedence during graceful shutdown |
For recovery, use Troubleshooting.