Skip to content

CLI Reference

Complete reference for the dotfiles command-line interface.

These flags are available for all commands:

--help, -h Show help for command
--verbose, -v Enable verbose output
--dry-run Show what would be done without making changes
--log-json Output logs in JSON format (for log aggregation)
--unattended Run without prompts, using defaults (ideal for CI/CD and IaC)

Content-overlay flags belong to bootstrap.sh, not dotfiles. The --content-repo, --content-ref, --content-path, --content-dir, --content-auth-cmd, and --no-persist-content-dir flags are consumed by the bootstrap script to materialize a content overlay; the dotfiles binary reads the resulting overlay via the DOTFILES_CONTENT_DIR environment variable. They are never dotfiles install --content-... flags.

Install modules with dependency resolution.

Terminal window
dotfiles install [modules...] [flags]

Arguments:

  • modules - Optional list of modules to install. If omitted, installs all modules (or those in the configured profile).

Flags:

--profile string Use a specific profile: a name from profiles/ (e.g. minimal,
developer) or a path to a profile file
--unattended Run without prompts, use default answers
--fail-fast Stop on first module failure (default: continue)
-v, --verbose Stream all script output in real-time (disables compact mode)
--dry-run Preview changes without applying them
--force Force reinstall even if up-to-date
--skip-failed Skip modules that failed previously
--update-only Only update existing modules, don't install new ones
--prompt-dependencies Show prompts for auto-included dependencies

Examples:

Terminal window
# Install all modules
dotfiles install
# Install specific modules
dotfiles install git zsh neovim
# Use a profile
dotfiles install --profile minimal
# Use a profile file kept outside this repo
dotfiles install --profile ~/projects/thing/profiles/thing.yml
# Preview without changes
dotfiles install --dry-run
# Automated installation (no prompts)
dotfiles install --unattended
# Verbose output for debugging
dotfiles install -v
# Stop on first error
dotfiles install --fail-fast

Profile resolution:

A --profile argument that contains a / or ends in .yml/.yaml is treated as a path to a profile file — a leading ~ is expanded, and relative paths are taken from the working directory. Anything else is a bare name, resolved to <dotfiles-dir>/profiles/<name>.yml as before.

A profile requested explicitly — through --profile or the DOTFILES_PROFILE environment variable — must load. If it is missing or malformed the command exits non-zero. Only the profile configured in config.yml falls back to installing all modules, since that one is a default rather than a request.

Interactive Module Selection (TTY mode):

When no modules are specified, you’ll see a compact grid-based selector:

┌─ Select modules to install ──────────────────────────────────┐
│ │
│ [x] 1password [x] git [ ] neovim │
│ [ ] golang [x] docker [ ] python │
│ [x] fish [ ] tmux [ ] zsh │
│ [ ] aws [x] kubernetes [ ] terraform │
│ │
│ Navigate: ↑/↓/←/→ Toggle: Space Select All: A Continue: Enter
│ Preview: git - Configure git with SSH signing and useful defaults
└───────────────────────────────────────────────────────────────┘

Progress Tracking:

During installation, you’ll see real-time progress:

┌─────────────────────────────────────────────────────────────┐
│ Installing 5 modules ████████░░░░ 3/5 (60%) │
│ Current: git • Elapsed: 45s • Est. remaining: ~30s │
└─────────────────────────────────────────────────────────────┘
✓ Executed install.sh

Completion Summary:

┌─────────────────────────────────────────────────────────────┐
│ ✓ Installation complete ██████████████ 5/5 (100%) │
│ Success: 5 • Failed: 0 • Skipped: 0 • Time: 2m15s │
└─────────────────────────────────────────────────────────────┘
✓ 1password (8s)
✓ ssh (12s)
✓ git (15s)
✓ zsh (45s)
✓ neovim (35s)

Non-TTY Output (for CI/CD):

When piped or in non-interactive mode, output uses plain text:

[INFO] Detecting system...
[OK] System: ubuntu/amd64 (pkg: apt)
[MULTISELECT] Select modules to install (using defaults: git, zsh)
[PROGRESS] 1/2: git
[OK] Executed install.sh
[PROGRESS] 2/2: zsh
[OK] Executed install.sh
[SUMMARY] Completed in 1m23s: 2 succeeded, 0 failed, 0 skipped

Output Modes:

The install command has three output modes:

  1. Compact Mode (default in TTY):

    • Grid-based module selector with preview
    • Progress bar with time estimates
    • Spinning indicators during script execution
    • Compact one-line summaries on success
    • Auto-expanding error boxes on failure (shows last 30 lines)
    • Recommended for interactive use
  2. Verbose Mode (--verbose or -v):

    • Streams all script output in real-time
    • Shows debug information and detailed progress
    • Useful for debugging module issues
    • Recommended when troubleshooting
  3. Non-TTY Mode (automatic when piped):

    • Plain text output suitable for logs
    • No ANSI colors or interactive elements
    • Used automatically in CI/CD pipelines
    • Uses default module selections when stdin is non-interactive

Smart Output Handling:

  • Sudo detection: Scripts using sudo automatically stream output to preserve password prompts
  • Error expansion: Failed scripts automatically show their output for debugging
  • Buffered success: Successful scripts show compact summaries to reduce noise
  • Pattern recognition: Extracts operations from script output (e.g., “Installing packages…“)

List all available modules with their status.

Terminal window
dotfiles list [flags]

Flags:

-v, --verbose Show additional module details

Examples:

Terminal window
# List modules
dotfiles list
# Verbose output with tags and dependencies
dotfiles list -v

Output:

Name Description OS Status
----------- ----------------------------------- ----------------- -------------
1password Install and configure 1Password CLI macos,ubuntu,arch installed
ssh Configure SSH keys and settings macos,ubuntu,arch installed
git Configure git with SSH signing macos,ubuntu,arch installed
zsh Install and configure Zsh macos,ubuntu,arch not installed
neovim Install Neovim and symlink config macos,ubuntu,arch failed

The listing shows all ~30 modules (truncated above). When a content overlay contributes modules, an extra Source column is inserted (before Status) tagging each module as built-in, override, or custom.

Status Values:

  • installed - Module is currently installed
  • not installed - Module has not been installed
  • failed - Last installation attempt failed

Show status of installed modules with detailed information.

Terminal window
dotfiles status [flags]

Flags:

-v, --verbose Show operation history and full details

Examples:

Terminal window
# Show installed modules
dotfiles status
# Show detailed information including operation history
dotfiles status -v

Output:

Installed Modules:
Name Version Status Installed OS
──────────── ────────── ─────────── ───────────────────── ──────────
git 1.0.0 installed 2026-02-10 10:30:00 ubuntu
zsh 1.0.0 installed 2026-02-10 10:31:15 ubuntu
neovim 1.0.0 failed 2026-02-10 10:32:00 ubuntu
3 modules installed (1 failed)

Verbose Output: Shows operation history for rollback tracking:

  • Files deployed (created, modified, symlinked)
  • Directories created
  • Scripts executed
  • Packages installed

Uninstall modules and rollback their changes.

Terminal window
dotfiles uninstall <modules...> [flags]

Arguments:

  • modules - One or more modules to uninstall (required)

Flags:

--force Skip confirmation prompts and continue on errors
--unattended Skip confirmation prompts (for automated environments)
--dry-run Preview rollback plan without executing
-v, --verbose Show detailed rollback information

Examples:

Terminal window
# Uninstall a module
dotfiles uninstall git
# Uninstall multiple modules
dotfiles uninstall git zsh neovim
# Preview what would be uninstalled
dotfiles uninstall git --dry-run
# Unattended mode (auto-confirm)
dotfiles uninstall git --unattended
# Force uninstall (no prompts, continue on errors)
dotfiles uninstall git --force
# Verbose uninstall with detailed output
dotfiles uninstall git -v

Output:

Uninstalling git...
Rollback plan (5 operations):
1. Remove: /home/user/.gitconfig
2. Restore /home/user/.bashrc from /home/user/.bashrc.backup
3. Remove directory: /home/user/.config/git
4. Package was installed: git (manual removal may be needed)
5. Script was executed: install.sh (manual cleanup may be needed)
? Proceed with uninstall of git? [y/N]: y
✓ Removed /home/user/.gitconfig
✓ Restored /home/user/.bashrc
✓ Removed directory /home/user/.config/git
ℹ Package git installed (manual removal may be needed)
ℹ Script install.sh executed (manual cleanup may be needed)
✓ Uninstalled git successfully

Rollback Operations:

  • Created files/symlinks: Removed
  • Modified files: Restored from backup (if available)
  • Created directories: Removed if empty
  • Scripts: Informational only, not automatically reversed
  • Packages: Informational only, manual removal needed

Exit Codes:

  • 0 - All modules uninstalled successfully
  • 1 - One or more modules failed to uninstall (unless --force used)

Generate a new module skeleton with standard structure.

Terminal window
dotfiles new <module-name> [flags]

Arguments:

  • module-name - Name of the module to create (lowercase alphanumeric with hyphens)

Flags:

--priority int Module priority (1-100, default: 50)
--depends strings Comma-separated list of dependencies
--os strings Comma-separated list of supported OSes (default: all)
--description string Module description

Examples:

Terminal window
# Create a basic module
dotfiles new tmux
# Create with priority and dependencies
dotfiles new my-module --priority 35 --depends git,zsh
# Create with OS restrictions
dotfiles new mac-only --os darwin
# Create with full metadata
dotfiles new advanced \
--priority 40 \
--depends git \
--os ubuntu,arch \
--description "Advanced configuration module"

Generated Structure:

modules/my-module/
├── module.yml # Module configuration
├── install.sh # Installation script
├── verify.sh # Verification script (optional)
├── os/ # OS-specific scripts (optional)
│ ├── ubuntu.sh
│ ├── macos.sh
│ └── arch.sh
├── files/ # Template/config files (placeholder)
└── README.md # Module documentation

Generated module.yml:

name: my-module
version: 1.0.0
description: TODO: Add description
priority: 50
os:
- all
dependencies: []
requires: []
files: []
prompts: []
tags: []

Next Steps After Generation:

  1. Edit module.yml to configure module
  2. Implement install.sh with installation logic
  3. Add configuration files to files/ directory
  4. Update README.md with documentation
  5. Test with dotfiles install my-module --dry-run

Retrieve a secret from the configured secrets provider. This is an internal command typically called by module scripts via the get_secret helper function.

Terminal window
dotfiles get-secret --ref <reference> [flags]

Flags:

--ref string Secret reference (e.g., op://vault/item/field)

Examples:

Terminal window
# Get a secret from 1Password
dotfiles get-secret --ref "op://Private/GitHub/token"
# Typically used in module scripts:
API_KEY=$(get_secret "op://Private/API/key")

Output:

secret-value-here

Error Cases:

  • Secrets provider not configured
  • Not authenticated
  • Secret not found
  • Invalid reference format

Render a Go template file. This is an internal command typically called by module scripts via the render_template helper function.

Terminal window
dotfiles render-template --src <source> --dest <destination> [flags]

Flags:

--src string Source template file path
--dest string Destination file path
--module string Module name whose config.yml settings populate .Module
(overrides DOTFILES_MODULE_NAME)

The subcommand builds the same template context as the in-process runner — including .User, the module’s .Module settings, .XDGConfigHome, and any content-overlay values (it reloads the layered config via config.Load). The module whose settings populate .Module is chosen by --module if given, otherwise by the DOTFILES_MODULE_NAME environment variable that the runner exports to every script — so module authors just call the render_template helper and get the right context automatically, while a manual invocation can select the module explicitly with --module.

Examples:

Terminal window
# Render a template
dotfiles render-template --src config.tmpl --dest ~/.config/app/config
# Typically used in module scripts:
render_template "$DOTFILES_MODULE_DIR/files/config.tmpl" ~/.config/app/config

Template Context:

Templates have access to (see the creating-modules guide for detail):

  • .User.name, .User.email, .User.github_userlowercase keys (.User.Name renders empty)
  • .OS, .Arch, .Home, .DotfilesDir, .XDGConfigHome
  • .Module.<key> - this module’s config.yml settings only (not prompt answers)
  • .Secrets - always an empty map here; secrets reach scripts via the get_secret helper
  • .Env.<VAR> - environment overrides, incl. DOTFILES_PROMPT_* (prompt answers), e.g. index .Env "DOTFILES_PROMPT_SSH_KEY_TYPE"

Template Functions:

  • env "VAR" - Get environment variable
  • default "val1" "val2" - First non-empty value
  • upper, lower - Case conversion
  • contains "substr" - String contains
  • join "," - Join slice
  • trimSpace - Trim whitespace

Show help for any command.

Terminal window
dotfiles help [command]

Examples:

Terminal window
# Show general help
dotfiles help
# Show help for install command
dotfiles help install

The CLI uses standard exit codes:

  • 0 - Success
  • 1 - General error
  • 2 - Invalid arguments or flags

Module Installation:

  • If any module fails during install and --fail-fast is not set, the command continues and returns 1 at the end
  • With --fail-fast, returns 1 immediately on first failure

These environment variables affect CLI behavior:

Terminal window
DOTFILES_DIR # Override dotfiles directory (default: ~/.dotfiles)
DOTFILES_PROFILE # Override profile from config.yml
Terminal window
DOTFILES_INTERACTIVE # Force interactive/non-interactive mode
DOTFILES_DRY_RUN # Force dry-run mode
DOTFILES_VERBOSE # Force verbose output

Module scripts receive many more environment variables. See Creating Modules — Environment Variables for a complete list.

Main configuration file at ~/.dotfiles/config.yml. The committed file ships generic engine defaults (secrets.provider: noop, empty user.*); personalize via a content overlay rather than editing it in place:

profile: developer
secrets:
provider: noop # opt into "1password" from your overlay
user:
name: ""
email: ""
github_user: ""
modules:
ssh:
key_type: ed25519
key_source: generate # generate | agent | 1password | none
git:
default_branch: main

Profile definitions in ~/.dotfiles/profiles/*.yml:

profiles/minimal.yml
modules:
- git
- zsh

Module state tracked in ~/.dotfiles/.state/*.json:

{
"name": "git",
"version": "1.0.0",
"status": "installed",
"installed_at": "2026-02-09T10:30:00Z",
"updated_at": "2026-02-09T10:30:05Z",
"os": "ubuntu",
"checksum": "",
"operations": [
{
"type": "script_run",
"action": "executed",
"path": "/home/user/.dotfiles/modules/git/install.sh",
"timestamp": "2026-02-09T10:30:01Z"
},
{
"type": "file_deploy",
"action": "symlinked",
"path": "/home/user/.gitconfig",
"timestamp": "2026-02-09T10:30:02Z",
"metadata": {
"source": "/home/user/.dotfiles/modules/git/gitconfig",
"type": "symlink"
}
},
{
"type": "dir_create",
"action": "created",
"path": "/home/user/.config/git",
"timestamp": "2026-02-09T10:30:03Z"
}
]
}

Operations Field (added in v1.1.0): Tracks all operations for rollback capability. See Rollback Guide for details.

Use -v flag to see detailed execution:

Terminal window
dotfiles install -v

Shows:

  • System detection details
  • Module discovery process
  • Dependency resolution steps
  • Script output (stdout/stderr)
  • File operations
  • State changes

Preview changes without applying them:

Terminal window
dotfiles install --dry-run

Shows:

  • Execution plan
  • What scripts would run
  • What files would be deployed
  • No actual changes made

View module installation state:

Terminal window
# List all state files
ls -la ~/.dotfiles/.state/
# View specific module state
cat ~/.dotfiles/.state/git.json | jq .

Remove state to force reinstall:

Terminal window
rm ~/.dotfiles/.state/module-name.json
dotfiles install module-name

Use --unattended flag for non-interactive environments:

Terminal window
# GitHub Actions, Jenkins, etc.
dotfiles install --unattended

This:

  • Uses default answers for all prompts
  • Skips interactive confirmations
  • Suitable for automation

The CLI is designed to be scriptable:

#!/bin/bash
set -euo pipefail
# Bootstrap new system
curl -sfL https://url/to/bootstrap.sh | bash
# Install specific modules
~/.dotfiles/bin/dotfiles install --unattended git zsh neovim
# Verify installation
~/.dotfiles/bin/dotfiles list | grep -q "git.*installed"
Terminal window
# Run bootstrap
curl -sfL https://url/to/bootstrap.sh | bash
# Configure user settings
vim ~/.dotfiles/config.yml
# Install all modules
dotfiles install
Terminal window
# Install new module
dotfiles install neovim
# Check status
dotfiles list
Terminal window
# Edit config
vim ~/.dotfiles/config.yml
# Reinstall to apply changes
rm ~/.dotfiles/.state/module-name.json
dotfiles install module-name
Terminal window
# Run with verbose output
dotfiles install module-name -v
# Check state for errors
cat ~/.dotfiles/.state/module-name.json
# Reset and retry
rm ~/.dotfiles/.state/module-name.json
dotfiles install module-name -v