A simple tool to quickly setup my development environment on a new machine or after a fresh OS installation.
- Installs packages listed at packages.yaml (Homebrew on macOS, DNF/Flatpak on Linux)
- Symlinks dotfiles to your home directory using GNU Stow
- Backs up existing dotfiles before replacing them
- Sets up asdf with plugins (nodejs, python, rust, uv, etc) and global npm/pip/cargo/bun packages. Check packages.yaml
- Installs VSCode extensions from your configuration
- Installs LazyVim for Neovim configuration
- Provides a dry-run mode to preview changes before applying
# Clone the repository
git clone https://github.com/gcaracuel/dotfiles.git
cd dotfiles
# Run the setup (installs personal packages + dotfiles)
./main.sh
# Include work-related packages
./main.sh --work
# Preview what would happen without making changes
./main.sh --dry-runNo prerequisites needed - the script automatically installs Homebrew, GNU Stow, and other dependencies.
| Flag | Description |
|---|---|
--work |
Include work packages (excluded by default) |
--skip-packages |
Skip package installation, LazyVim, and VSCode extensions (only symlink dotfiles) |
--skip-stow |
Skip dotfiles, only install packages |
--force-brew |
Force using Homebrew on Linux (for container testing) |
--dry-run |
Preview changes without applying them |
--help |
Show usage information |
dotfiles/
├── README.md
├── AGENTS.md # Guidelines for AI agents
├── main.sh # Entry point
├── packages.yaml # Package definitions
├── justfile # Container testing (requires just command runner)
├── scripts/
│ ├── prerequisites.sh
│ ├── packages.sh
│ ├── stow.sh
│ ├── asdf.sh
│ ├── vscode.sh
│ ├── lazyvim.sh
│ └── utils.sh
├── .devcontainer/ # Container testing
│ ├── fedora/
│ └── homebrew/
└── dotfiles/ # Stow-managed dotfiles (mirrors $HOME)
├── .zshrc
├── .gitconfig
├── .config/
│ └── ...
└── ...
Packages are defined in packages.yaml using a unified schema:
packages:
- name: neovim # Default package name
description: Text editor
gui: false # false=CLI, true=GUI
work: false # false=personal, true=work-only
# No overrides = same name on all platforms
- name: dust
description: du replacement
gui: false
work: false
overrides:
linux: du-dust # Different name on Linux
- name: rectangle
description: Window management
gui: true
work: false
overrides:
linux: null # macOS-only (skip on Linux)
- name: visual-studio-code
description: Code editor
gui: true
work: false
overrides:
linux: com.visualstudio.code # Flatpak ID on Linux
# VSCode extensions
vscode_extensions:
- golang.go
- ms-python.python
- rust-lang.rust-analyzer
# ... see packages.yaml for full list
# Language-specific packages
npm:
- "@anthropics/claude-code"
pip:
- jrnl
cargo:
- eza # ls replacement
- zellij # Terminal multiplexer
bun:
- openportal # Mobile-first web UI for OpenCodeEach package entry has:
name: Default package name (used if no override)description: Human-readable descriptiongui:falsefor CLI tools (brew/dnf),truefor GUI apps (cask/flatpak)work:falsefor personal packages,truefor work-only packagesoverrides(optional): Platform-specific package namesmacos: macOS package name (ornullto skip on macOS)linux: Linux package name (ornullto skip on Linux)
Benefits:
- Single source of truth per package
- Cross-platform differences are explicit
- Easy to see which packages are available on which OS
- ~40% less YAML compared to old structure
VSCode extensions are installed via the code --install-extension command:
- Extensions are listed in the
vscode_extensionsarray inpackages.yaml - Extension IDs can be found in the VSCode marketplace (e.g.,
golang.go) - Installation is idempotent (skips already-installed extensions)
- Requires VSCode to be installed first (via GUI packages)
- Gracefully skips if VSCode is not available
Before stowing, existing dotfiles are backed up to:
~/.dotfiles-backup/<timestamp>/
To rollback:
cd ~/.dotfiles-backup/2026-01-30_10-30-45
stow . --target=$HOME- macOS: Full support (Homebrew + Casks)
- Linux (Fedora): Full support (DNF + Flatpak)
- Other Linux: Use
--force-brewflag to install Homebrew on Linux
The script automatically installs asdf version manager:
- Version: Pinned to
v0.17.0(configurable inscripts/prerequisites.sh) - Note: Pre-built binaries only available from v0.15.0 onwards
- Location:
~/.asdf/ - Architecture: Auto-detects OS and CPU (darwin/linux, amd64/arm64)
- Binary Download: Downloads pre-built binaries from GitHub releases
- PATH Management: Temporarily added to PATH during script execution
After installation, manually add asdf to your shell:
echo 'export PATH="$HOME/.asdf/bin:$PATH"' >> ~/.zshrc
source ~/.zshrcThe script will remind you to do this at the end.
Some things still require manual setup after running the script:
- SSH key generation
- Git configuration (name, email)
- Application logins (1Password, etc.)
These are printed at the end of the script execution.
Local testing uses Docker containers to verify the bootstrap script works correctly (requires just):
# Interactive test selection
just test
# Test in Fedora (native Linux)
just test-fedora
# Test with forced Homebrew
just test-brew
# Open shell for manual testing
just test-fedora-shell
just test-brew-shell
# Clean up
just cleanThe Homebrew container uses --force-brew to override OS detection and run brew commands.
The script automatically installs VSCode extensions from packages.yaml:
- Installs after GUI packages (ensures VSCode is available)
- Uses
code --install-extensioncommand - Idempotent: skips already-installed extensions
- Case-insensitive extension ID matching
- Gracefully skips if VSCode not installed (with warning)
- Tied to
--skip-packagesflag
Example extensions:
- Language support: Python, Go, Rust, Java, Terraform
- Tools: Docker, GitHub Actions, Jupyter
- AI: Gemini Code Assist, IntelliCode
The script automatically installs LazyVim for Neovim configuration:
- Detects if LazyVim is already installed (skips if present)
- Backs up existing
~/.config/nvimbefore installation - Clones the LazyVim starter repository
- Removes
.gitfolder so you can add to your own repo
Both VSCode extensions and LazyVim installation are tied to --skip-packages - if you skip packages, these are also skipped.
This repository used to to cover dotfiles and packages installation using a complicated Ansible approach which if desires is still accesible via git tag: https://github.com/gcaracuel/dotfiles/releases/tag/0.x
I want to quit MacOS and fully switch back to Linux which will simplify (or not) a lot this repository. The plan is to run Fedora Sway Atomic or NixOS running Sway/Hyprland as work machines and Fedora or another NixOs for personal use. In that scenario Nix will be key point so home-manager sounds like the dotfiles substitute, even on Fedora Atomic Nix would be the thing to have very same features for packages than the atomicity of the system itself so is a win-win, even if combined with Faltpaks for simplicity around GUI applications.