This content originally appeared on DEV Community and was authored by Satyajit Roy
Dev Setup on Autopilot
Every developer knows the ritual. A new laptop arrives shiny, fast, and brimming with potential. Or perhaps you’re upgrading your existing machine, or starting a new role with a fresh corporate setup. The excitement is palpable, but then reality hits: the painstaking process of recreating your perfect development environment.
For years, I’ve lived this saga. Like many of you, I have my carefully curated arsenal of tools, fonts, and configurations that make me productive. My terminal needs to look just right, my version managers must be in place, and a dozen specific CLI utilities are non-negotiable.
The Deja Vu of Re-Setup
The problem isn’t just the initial setup; it’s the memory part. I’d spend hours, sometimes days, painstakingly recalling, searching, and reinstalling. Let me give you some concrete examples of the frustration:
The Elusive brew Formula: You remember using
brew
to install that niche CLI tool for managing cloud resources, but was it brew installaws-cli
orbrew install awscli
? Did it have a specific--with-zsh-completion
flag? Or was itaws-cli@2
because the latest version broke a script? You spend 15 minutes in brew search and then another 10 digging through old documentation or~/.zsh_history
(if you even remembered to back it up).The Go Tooling Conundrum: You need
protoc-gen-go-grpc
. Did yougo install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
? Or was it an olderv1.2.3
because the team’s build system isn’t on the newestprotobuf
? Or, even worse, did you download a pre-compiled binary from a GitHub Release because it was faster, and now you have no idea where it came from?The Perfect Font, Gone: Your beautiful coding font, say “Fira Code Nerd Font Mono” suddenly isn’t rendering correctly. Was it version
v3.0.2
orv3.1.1
of Nerd Fonts? And which specific*.ttf
file within the archive did you copy to~/Library/Fonts
? Now you’re hunting through GitHub Releases, downloading multi-gigabyte archives just to find that one precise file.-
Dotfiles’ Blind Spots: While a
~/.dotfiles
repository is a lifesaver for shell aliases (alias gcm='git commit -m'
) or Vim plugins, they notoriously fall short when it comes to:-
Actual Software Installation: Your dotfiles won’t magically install Homebrew, or
git
itself, orNode.js
, or theRust
toolchain. They assume these foundational tools are already there. -
Installation Methods: Your
shellrc
might expectpyenv
to be in your$PATH
, but it won’t tell you ifpyenv
was installed viabrew
,git clone
, or a custom script. -
System-Level Settings: Those macOS
defaults write
commands that perfect your trackpad speed, hide desktop icons, or ensure hidden files are always visible, these are often scattered notes or manual tweaks, not cleanly managed.
-
Actual Software Installation: Your dotfiles won’t magically install Homebrew, or
This constant “re-setup tax” was a major pain point, a recurring nightmare that chipped away at my valuable time and focus. I wanted a way to truly encapsulate my entire development environment, not just bits and pieces.
My Solution: Introducing setup-devbox
That frustration finally boiled over, and I decided to tackle it head-on. I focused on a piece of software that solves this exact problem: setup-devbox
.
setup-devbox
is my answer to the “new laptop dilemma.” It’s a command-line tool that lets you define your entire development environment in declarative YAML
files. This isn’t just about listing tools; it’s about stating the desired end-state of your machine, which is repeatable every single time, in a format that’s both human-readable and machine-executable.
Why Declarative YAML
?
The power of declarative YAML is that it acts as your single source of truth. It lives alongside your code in version control, meaning:
-
Readability: It’s easy to glance at
tools.yaml
and instantly know what’s supposed to be installed. - Version Control: You can track changes to your environment setup over time, just like you track changes to your application code.
-
Shareability: Want to onboard a new team member to an identical setup? Share your
setup-devbox
config files. -
No More Guesswork: No more trying to remember a specific brew flag or the exact go install command. The
YAML
specifies it all.
What setup-devbox
Manages:
When you define your environment, setup-devbox
steps up to handle the heavy lifting across several crucial domains:
Tools (and Their Installation Methods!): This is where it shines. You define tools like
git
,Node.js
,kubectl
, or even specific versions ofgh
(GitHub CLI). Crucially, you also tellsetup-devbox
how to install them: –brew
: For standard packages onmacOS
andLinux
. –cargo
: For your favorite Rust CLI tools. –github
: For tools distributed as GitHub Releases (e.g., specific versions ofterraform
orhelm
). –url
: For direct downloads of binaries or installers that don’t fit other categories (e.g., a specific Go installer.pkg
).
It intelligently uses the correct installer and even handlesrename_to
for convenience (e.g.,cli
togh
).macOS System Settings (
defaults write
): Tired of manually changing Finder settings or keyboard behaviors after a clean install?setup-devbox
lets you declare thosedefaults write
commands directly in yoursettings.yaml
, ensuring consistency every time.Shell Configuration (
.zshrc
,.bashrc
etc.): Beyond just aliases, you can define raw lines of configuration to be injected into your shell startup files. This includes everything from$PATH
modifications to eval “$(starship init zsh)
” or complexfzf
bindings.Fonts: My coding experience isn’t complete without specific fonts, often Nerd Fonts.
setup-devbox
automates the download and installation of these, ensuring my terminal looks perfect on every machine.
At present it support GitHub, Brew, Cargo, Rustup, Go, Pip and Direct URL.
Here are examples of my tools.yaml
- name: git-spellcheck
version: 0.0.1
source: github
repo: kodelint/git-spellcheck
tag: v0.0.1
rename_to: git-spellcheck
- name: git-pr
version: 0.1.0
source: github
repo: kodelint/git-pr
tag: v0.1.0
rename_to: git-pr
- name: cli
version: "2.74.0"
source: github
repo: cli/cli
tag: v2.74.0
rename_to: gh
- name: delta
version: "0.18.2"
source: github
repo: dandavison/delta
tag: 0.18.2
rename_to: delta
Example of fonts.yaml
fonts:
- name: 0xProto
version: 3.4.0
source: github
repo: ryanoasis/nerd-fonts
tag: v3.4.0
install_only: ["regular", "Mono"]
Example of shellrc.yaml
Example of shellrc.yaml
shellrc:
shell: zsh
raw_configs:
- export PATH=$HOME/bin:$PATH
- export PATH=$HOME/.cargo/bin:$PATH
- export PATH=$HOME/go/bin:$PATH
- eval "$(starship init zsh)"
- "[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh"
- zle -N fzf-history-widget - bindkey '^R' fzf-history-widget
- 'export FZF_CTRL_R_OPTS="--no-preview --scheme=history --tiebreak=index --bind=ctrl-r:toggle-sort"'
- | export FZF_CTRL_T_OPTS="
--preview 'bat --style=numbers --color=always {} || cat {}'
--preview-window=right:80%
--bind ctrl-b:preview-page-up,ctrl-f:preview-page-down"
aliases:
- name: code
value: cd $HOME/Documents/github/
- name: gocode
value: cd $HOME/go/src/
- name: edconf
value: zed $HOME/.zshrc
- name: g
value: git
- name: gs
value: g status
Example of settings.yaml
settings:
macos:
- domain: NSGlobalDomain
key: AppleShowAllExtensions
value: "true"
type: bool
- domain: com.apple.finder
key: AppleShowAllFiles
value: "true"
type: bool
- domain: com.apple.dock
key: expose-animation-duration
value: "0.1"
type: float
- domain: NSGlobalDomain
key: KeyRepeat
value: "1"
type: int
- domain: com.apple.finder
key: ShowPathbar
value: "true"
type: bool
The Magic of State Management
The core idea is simple yet powerful: you run setup-devbox now
, and it springs into action. But it’s not a dumb script that reinstalls everything every time. It leverages an internal state.json
file. This file acts as setup-devbox
‘s memory, keeping track of what has already been installed and configured, and how.
This means that:
Idempotency: Running
setup-devbox
now multiple times won’t break anything or perform redundant work. If a tool is already installed and matches your desired version,setup-devbox
simply skips it.Efficiency: Only missing or outdated components are installed or updated, saving you precious time and bandwidth.
Reliability: The
state.json
ensures that your environment progresses predictably towards the desired state you’ve defined.
This means that whether I’m upgrading my MacBook, spinning up a new virtual machine, or onboarding onto a client’s specific environment, I can replicate my ideal setup with minimal effort. The entire “re-setup tax” is almost eliminated, freeing me up to do what I love: develop.
Reclaim Your Setup Time, Forever
Building setup-devbox
has transformed my personal development workflow from a recurring chore into a one-command automation. My development environment is no longer a collection of scattered memories and manual steps; it’s a declarative, version-controlled blueprint that setup-devbox brings to life with intelligent efficiency.
If you, like me, have suffered the “new laptop setup” headache too many times, I genuinely believe setup-devbox can be a game-changer for you. It’s my personal solution to a universal developer problem, and I’m excited to share it with the community.
Head over to the GitHub Repository: setup-devbox
, explore the configuration examples, and give setup-devbox
a try. I’m actively developing it, and your feedback, ideas, or even contributions would be incredibly valuable.
Repository: setup-devbox
Happy Developing!!
This content originally appeared on DEV Community and was authored by Satyajit Roy