Reproducible, Ansible-driven setup for a personal development machine — shell, dotfiles, CLI tools, editors, and language runtimes — applied to the local host with a single command.
See docs/CATALOG.md for the full list of tools that get installed, what each one is, and why it's useful.
| Platform | Status |
|---|---|
| Ubuntu / Debian | Supported (the original target) |
| WSL (Ubuntu) | Supported (same apt path) |
| macOS (Apple Silicon) | Supported — every task installs via Homebrew on the Darwin branch; verified by the macos CI job |
| Windows (native) | Use WSL or the Docker image below |
The safest way to see a full run without touching your own machine:
docker build -t mtkhawaja/dev-env:latest . && docker run -it --rm mtkhawaja/dev-env:latestOn Windows (PowerShell):
docker build -t mtkhawaja/dev-env:latest . ; if ($?) { docker run -it --rm mtkhawaja/dev-env:latest }./run_docker.sh is a shortcut for the build-and-run above.
Warning: A full run modifies your home directory — it replaces
~/.zshrc,~/.zshenv, and~/.oh-my-zsh, and force-overwrites~/.dotfiles. Try it in the Docker container first.
Run the convenience script, which detects your OS, installs Ansible (Homebrew on macOS, the Ansible PPA on Linux), installs the required collections, and then runs the playbook:
curl -s https://raw.githubusercontent.com/mtkhawaja/dev-environment/main/setup.sh | bashBootstrap logs are written to ~/.ansible-dev-env-bootstrap/.
# Install Ansible
sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install -y ansible
# Run the playbook directly from this repo
ansible-pull -U https://github.com/mtkhawaja/dev-environment.git -i localhost, local.yamlWith Ansible already installed, run against the local host from a checkout:
ansible-galaxy collection install -r requirements.yml # one-time: community.general
ansible-playbook -i localhost, local.yaml # full run
ansible-playbook -i localhost, local.yaml --tags modern-cli # run one area onlyEvery task is tagged (a broad initial-setup plus an area tag like zsh, python, modern-cli), so --tags lets you run or re-run a single area. A second run with the same tags should report changed=0.
local.yaml is the single play and entry point: it loads shared variables from src/ansible/vars/main.yml, runs pre-tasks (base packages, directories), then imports one task file per area from src/ansible/tasks/. Adding a new area means adding a task file there and an import_tasks line in local.yaml. Dotfiles live in a separate repo (mtkhawaja/dotfiles) and are applied with GNU Stow.
Contributors: see CLAUDE.md for repo conventions and .claude/skills/adding-a-tool/ for the cross-platform tool-install guide.