Clean, straightforward dotfiles setup for Linux, macOS, and WSL:
Supported OS: Ubuntu, Ubuntu (WSL), and macOS. Focus: A Homebrew-first, zsh-focused dotfiles toolkit.
- 🍺 Brew-first package install
- 🧾 Release verification (SHA256 + optional GPG on checksum)
- 🧩 Default skel profile deployment
- 🌃 Starship Tokyo Night preset by default
- 📝 Nano syntax highlighting via nanorc
- 🧱 tmux via Homebrew + oh-my-tmux base config
- 🤖 Optional inference tools (
--install-inference: ollama + llmfit) - 🧪 Dry-run support
- 🔎 Verbose debug mode when needed
- ♻️ Safe re-runs (backup-and-replace by default; use
--preserveto keep existing files) - 🔒 Single-run lock to prevent concurrent installer collisions
- 📋 Optional machine-readable install report (
--report-json)
chmod +x install.sh
# preview changes first
./install.sh --dry-run --verbose
# run install
./install.sh -yBy default, existing files like ~/.zshrc are backed up to .bak.<date> and replaced with fresh skel copies.
If the deployed file already matches skel exactly, the backup and copy are skipped (idempotent reruns).
Use --preserve to keep existing files unchanged without any backups.
# Latest main branch — one-liner, no version required:
curl -fsSL https://dot.rly.wtf/bootstrap.sh | bash
# Pinned to a specific release (recommended for reproducible installs):
curl -fsSL https://dot.rly.wtf/bootstrap.sh | bash -s -- --ref v1.0.6
# Branch (unverified):
curl -fsSL https://dot.rly.wtf/bootstrap.sh | bash -s -- --ref my-branchNote: The refless form downloads the current
mainbranch directly. It skips checksum verification and may include unreleased changes. Use--refwith a release tag for a verified, reproducible install. Branches are also supported but skip checksum verification.
.
├── bootstrap.sh
├── install.sh
├── inventory/
│ └── default.yaml
├── packages/
│ └── packages.yaml
├── scripts/
│ ├── lib/brew-env.sh
│ ├── lib/install-flags.sh
│ ├── setup-starship.sh
│ └── post-install-checks.sh
├── test/
│ ├── root-configs.sh
│ ├── lib/test-shims.sh
│ ├── backup-collision.sh
│ ├── bootstrap-e2e.sh
│ ├── brew-env.sh
│ ├── installer-lock.sh
│ ├── installer-idempotency.sh
│ ├── preserve-flag.sh
│ ├── tmux-oh-my.sh
│ ├── report-json.sh
│ ├── skel-merge.sh
│ ├── ssh-config-migration.sh
│ ├── inference-opt-in.sh
│ ├── nanorc-optional-failure.sh
│ ├── release-reproducible.sh
│ └── suite.bats
└── skel/
└── default/
├── .zshrc
├── .zshenv
├── .tmux.conf.local
├── .gitconfig
├── .ssh/config
└── .config/
├── brew-init.sh
└── starship.toml
- Standard mode: concise stage updates + status emojis
--verbose: extra🔎debug lines--dry-run: commands are printed with🧪and not executed- Post-install checks use traffic lights (
🟢 / 🟡 / 🔴)
--ref <ref>(release tag or branch; release tags get checksum verification)--host <host>(advanced optional profile name; most users can ignore this)--pyver <ver>--create-home-pyver--install-inference(use with-yfor non-interactive runs)--dry-run--preserve(keep existing files untouched; opt out of backup-and-replace)--brew-only--no-apt--verbose--from-release(set internally by bootstrap)--report-json <path>(writes a JSON phase summary)--no-lock(advanced/debug; disables install lock guard)
BOOTSTRAP_GPG_FINGERPRINTto enforce expected checksum signer fingerprint inbootstrap.sh
TAG=v1.0.0
REPO_NAME="$(basename "$PWD")"
mkdir -p dist
tar --sort=name --mtime='UTC 1970-01-01' --owner=0 --group=0 --numeric-owner \
--exclude='.git' --exclude='./dist' -cf - . | gzip -n > "dist/${REPO_NAME}-${TAG}.tar.gz"
(cd dist && sha256sum "${REPO_NAME}-${TAG}.tar.gz" > "${REPO_NAME}-${TAG}.tar.gz.sha256")Verify deterministic archive output:
./test/release-reproducible.sh "$TAG"On macOS, install GNU tar first for deterministic-archive verification:
brew install gnu-tar
packages/packages.yaml is the single source of truth for package lists
(brew and apt_minimal sections).
The default brew set includes core tools like tmux, ripgrep, fzf, and fd.
Repository AI guidance lives in AGENTS.md and includes:
- DRY/minimal change expectations
- Idempotency and safe-default requirements
- Ample, purposeful section/function comments in shell scripts and tests
- Existing files in
$HOMEare backed up to.bak.<date>and replaced with fresh skel copies by default. If the deployed file already matches skel exactly, the backup and copy are skipped. Use--preserveto keep existing files unchanged. ~/.zshenvis deployed fromskel/default/.zshenvvia the samedeploy_skel_profilepath as.zshrc; it respects--preserveand idempotency in the same way.- Existing
~/.ssh/configis auto-migrated to~/.ssh/config.localwhen local file is absent; managed~/.ssh/configthen includes~/.ssh/config.local. If~/.ssh/config.localalready exists it is backed up before migration.--preserveskips the SSH migration entirely, leaving both files untouched.
GitHub Actions runs a CI workflow that checks:
- shell syntax (
bash -n) - shellcheck linting
- no duplicate repo-root shell config files
- installer/bootstrap help output
- installer idempotency behavior (backup-and-replace by default; no new backups when file matches skel)
- backup collision handling for deterministic
.bak.<date>[.<n>]naming - skel directory merge behavior (preserve existing files, copy missing files)
- SSH config include migration behavior (
test/ssh-config-migration.sh) - oh-my-tmux bootstrap/preserve/override behavior (
test/tmux-oh-my.sh) - installer lock contention behavior (
test/installer-lock.sh) - report JSON validity/escaping checks (
test/report-json.sh) - inference installer opt-in behavior (
test/inference-opt-in.sh) - optional nanorc clone failure handling (
test/nanorc-optional-failure.sh) - brew environment resolution scenarios (
test/brew-env.sh) - bootstrap end-to-end README curl flow (
test/bootstrap-e2e.sh) - DRY BATS installer suite (
test/suite.bats) running all integration checks - release reproducibility verification (
test/release-reproducible.sh, tag workflow)
Release notes live in CHANGELOG.md.
Released under UNLICENSE. See UNLICENSE.