Skip to content

tabsp/dotfiles

Repository files navigation

dotfiles

中文

CI Release License: MIT Demo Platform Built With Ratatui

dotman is a tiny Rust TUI dotfiles manager for my personal macOS/Linux environment. It uses a flat YAML config to install software, link config files, create directories, clean old paths, and run setup commands — all in a Plan -> Review -> Run flow with per-machine state and persistent run history.

Preview

Try the interactive demo at dotfiles.tabsp.com — the real Ratatui TUI rendered in the browser by a side-effect-free Rust/WebAssembly state machine. Plan, Review, Run, and Replay are fully navigable; nothing ever executes.

dotman main menu

dotfiles workspace

What's Inside

Layer Tools
Terminal Ghostty
Shell Fish with numbered conf.d modules and Fisher plugins
Multiplexer tmux with tmux-status; herdr
Software Neovim (LazyVim), mise, lazygit, btop, fastfetch, yazi
Enhancement · prompt Starship, tealdeer, markdownlint-cli2
Enhancement · cli ripgrep, fd, bat, eza, dua-cli, gum, tree-sitter-cli, delta, trash-cli, pay-respects, gitleaks
Enhancement · data fzf, zoxide, jq, yq, direnv, Atuin
Font Maple Mono NF

Quick Start

Install the latest dotman release with the checksum-verifying installer:

curl -fsSL https://github.com/tabsp/dotfiles/releases/latest/download/install.sh | sh

The installer detects macOS/Linux and arm64/x86_64, verifies the release SHA-256, and installs to ~/.local/bin. Set DOTMAN_VERSION=v0.3.3 to pin a release or DOTMAN_INSTALL_DIR to choose another directory.

If Homebrew is already available, install and upgrade through the Tap instead:

brew install tabsp/tap/dotman

Update an installation created by install.sh in place:

dotman self update

Homebrew owns installations created through the Tap. Upgrade those with:

brew upgrade dotman

To prevent the two package managers from overwriting each other, self update detects Homebrew Cellar installations and refuses to modify them.

Then run it. On first launch, dotman initializes the default dotfiles profile and opens the main menu. Choose Deploy, adjust the Plan, then review the selected actions before starting the Run:

dotman

This clones https://github.com/tabsp/dotfiles.git to ~/.local/share/dotman/repos/main, loads dotman.yaml, and opens the TUI.

For unattended setup (CI, scripted setup):

dotman deploy --headless

Headless mode uses the same execution and result model as the TUI, prints live action output and a final ran / changed / no change / failed summary, saves the run to history, and exits non-zero for failed or aborted runs.

To initialize this repository explicitly:

dotman init https://github.com/tabsp/dotfiles.git --branch main --profile main
dotman deploy

Usage

dotman                       # TUI main menu (auto-inits on first run)
dotman deploy                # TUI: sync → plan → review → run
dotman plan                  # TUI: show plan only, no execution
dotman init [repo]           # initialize a dotfiles profile
dotman sync                  # git pull current profile
dotman status                # show profile and repo state
dotman doctor                # check prerequisites
dotman profile list          # list configured profiles
dotman profile add <name> <repo>
dotman profile remove <name>
dotman history               # TUI: browse past runs
dotman run <ulid>            # TUI: replay a past run
dotman new-link <target> <source>
dotman deploy --headless     # headless: non-interactive deploy
dotman plan --headless       # headless: emit JSON plan to stdout

Global options:

--headless         no prompts; use safe defaults and fail on ambiguity
--bootstrap-git    allow dotman to install git before profile/bootstrap work
--config <path>    use a dotman.yaml directly and bypass profile resolution
--no-init          fail instead of auto-initializing when no config is found

TUI Keys

The footer shows only the primary keys for the current screen:

Screen Primary keys
Main menu ↑↓ navigate, Enter open, q quit
Plan ↑↓ navigate, Space toggle, s save, r review, q back
Review ↑↓ scroll, r run, q back
Run / Result ↑↓ scroll, Tab filter, Enter fold, f follow when paused, q abort/back
History ↑↓ navigate, Enter open, d delete, q back
Run replay ↑↓ navigate, Space fold, q back

Direct main-menu keys (d deploy, p plan, h history), Vim navigation (j/k, gg, G), Home/End, PageUp/PageDown, arrow-key filter switching, and equivalent Enter/Space actions remain available as unlisted convenience keys.

Result labels are intentional: Ran means a shell command completed; Changed means dotman installed, created, linked, backed up, or cleaned something. Errors are shown before warnings, while the final run result remains visible if saving history fails.

Configuration

Deployment steps live in dotman.yaml in your dotfiles repo:

package_managers:
  macos: brew
  ubuntu: brew
  arch: pacman

auto_install_pkg_manager: true

default_shell: fish

install:
  [ghostty, fish, tmux, neovim, lazygit, btop, ripgrep, fzf, starship, atuin]

links:
  ~/.config/fish: config/fish
  ~/.config/nvim: config/nvim
  ~/.config/ghostty: config/ghostty
  ~/.tmux.conf: config/tmux.conf

create:
  - ~/.config/fish-local
  - ~/Workspace/tries

shell:
  - command: fish -lc 'fisher update'
    description: Sync fish plugins
    optional: true
    if: command -v fish >/dev/null 2>&1

clean:
  - target: ~/.config/old-tool
    force: true

YAML field reference:

  • package_managers — per-platform package manager.
  • auto_install_pkg_manager — if true, attempts to install the package manager itself (e.g. Homebrew) before any install steps.
  • default_shell — login shell to switch to automatically. dotman resolves the real path with command -v and ensures it is listed in /etc/shells.
  • install: [name] — list of tool names to install. dotman picks the right install command for your platform from its internal tool database.
  • links: — map of target -> source. dotman also accepts list entries with target, source, backup, and relink for per-link behavior.
  • create: — directories to ensure exist.
  • shell: — list of shell commands. Supports description, optional: true, and if: (condition guard).
  • clean: — paths to remove. By default only symlinks are removed; use force: true to back up and remove regular files/directories.

Profile configuration (repo URL, branch, checkout path, auto-sync) lives at ~/.config/dotman/config.toml. dotman manages this automatically — you don't need to create or edit it by hand.

Per-machine selections are stored under ~/.local/share/dotman/selection/, scoped by the normalized dotman.yaml path. Small config edits therefore keep existing choices; newly added item IDs use their plan defaults.

Run logs are at ~/.local/share/dotman/runs/<ulid>.json and can be browsed with dotman history or dotman run <id>.

How It Works

The deployment pipeline is:

resolve profile → sync repo (git pull) → load dotman.yaml → build plan → review → execute → save history

dotman's profile system manages the dotfiles repo itself (URL, branch, clone path, auto-sync). The deployment config (dotman.yaml) only describes what to deploy — installs, links, creates, shell commands.

Auto-init triggers automatically when no profile or config is found. Headless mode uses non-interactive defaults. In the TUI, deployment changes are shown in Plan and Review before Run starts.

Local Overrides

Machine-specific paths, tokens, and temporary tool setup should stay out of the shared repository.

Fish loads local-only files from:

~/.config/fish-local/*.fish

For first-time setup on a new machine, follow docs/new-machine.md.

Development

make build
make format        # format all supported tracked files
make format-check  # check formatting without modifying files
make lint
make secret-check  # scan the working tree and Git history for secrets
make test
make config-check  # run the complete local configuration validation
make ci

Before committing, format the repository, run the complete configuration validation, and review the resulting diff:

make format
make config-check
git diff

Automated releases

Pushing a vX.Y.Z tag that matches the version in Cargo.toml builds and tests all four release targets, publishes their archives, checksums, and install.sh, then generates, installs, tests, and pushes Formula/dotman.rb to tabsp/homebrew-tap. Manual workflow runs are only for retrying an existing semantic release tag and build that tag rather than the selected UI branch.

The Homebrew publication uses a write-enabled SSH Deploy Key scoped to the public tabsp/homebrew-tap repository. Its private key is stored in this repository as the HOMEBREW_TAP_DEPLOY_KEY Actions secret; no personal access token is required.

About

macOS/Linux dotfiles with a tiny Rust TUI manager, bootstrap workflow, and terminal-first development setup.

Topics

Resources

License

Stars

1 star

Watchers

1 watching

Forks

Packages

 
 
 

Contributors