local setup as code

Feb 17, 2026

categories

setup

local setup as code

having recently joined framer, i wanted to make sure that i hit the ground running after spending the last 7 years leading ai & architecture over at oxbury. one thing that i never quite got nailed down was my local shell/environment setup. sure, i had my very hacked together "dotfiles" that at the end of the day was a single bash script that managed other bash scripts via a bunch of symlinks… it worked well for a time but made repeatability/changes difficult and impossible to diff between machines

due to this, i started looking at better ways of managing these, and stumbled across chezmoi and has made the whole setup of a new machine so seemless

the problem

as developers, we have a ton of tools that we need; from fancy new shiny tools (claude, codex) to a bash script connoisseur swiss-army knife (jq, fzf)

making sure that you remember them all when you are setting up your machine can be time consuming, and when you are wanting to just ship you want to have your trusty toolbox with you at all times

so by making sure our environment is defined as code we can have:

  • consistency

  • familiarity

  • repeatability

the solution

as mentioned above, i ended up going with chezmoi as my personal dotfiles manager because of the ease of use and sharability between different hosts

with a single command i can now setup a new machine with fish, starship (with my fancy prompt) and all the tools that i've grown used to having in my shell

with this setup, it also allows me to experiment by trying different tools/setups out and with a few commands if i don't like what i've done i can revert back to my previous working environment

how does it work?

the main bread and butter of this setup is a chezmoi.toml file that lives in ~/.local/share/chezmoi by default. this defines the what and why

chezmoi.toml

[edit]
  command = "/usr/local/bin/zed"

[template]
  starship_prompt = "true"
  default_shell = "/opt/homebrew/bin/fish"

[permissions]
  "dot_run_once_bootstrap.sh" = 0700
  "dot_packages_*.sh" = 0700

[data]
  github_username = "Cal-Morris"

[git]
  autoCommit = true
  autoPush = true

[edit]
  command = "/usr/local/bin/zed"

[template]
  starship_prompt = "true"
  default_shell = "/opt/homebrew/bin/fish"

[permissions]
  "dot_run_once_bootstrap.sh" = 0700
  "dot_packages_*.sh" = 0700

[data]
  github_username = "Cal-Morris"

[git]
  autoCommit = true
  autoPush = true

[edit]
  command = "/usr/local/bin/zed"

[template]
  starship_prompt = "true"
  default_shell = "/opt/homebrew/bin/fish"

[permissions]
  "dot_run_once_bootstrap.sh" = 0700
  "dot_packages_*.sh" = 0700

[data]
  github_username = "Cal-Morris"

[git]
  autoCommit = true
  autoPush = true

within this directory, you can see a strange layout of files - some have run_* prefixes, some have executable_ this is the magic of chezmoi! it will automagically place files from the chezmoi dir (that is managed and synced via git) into your ~/ for you




adding a new brew package

one of my main reasons for having my dotfiles setup this way is that i have a defined list of brew packages that are installed on my system at anyone time; easy to audit, easy to add new ones

here's a simple of my run_onchange_packages_cli.sh; a simple bash script that allows me to define a list of packages and install them with brew

chezmoi/run_onchange_packages_cli.sh

#!/bin/sh
set -eu

PACKAGES="
git
jq
bat
lazygit
z
fzf
pandoc
gh
codex
ngrok
docker-compose
withgraphite/tap/graphite
"

for pkg in $PACKAGES; do
  if ! brew list "$pkg" >/dev/null 2>&1; then
    echo "▶ Installing $pkg"
    brew install "$pkg"
  else
    echo "✔ $pkg already installed"
  fi
done
#!/bin/sh
set -eu

PACKAGES="
git
jq
bat
lazygit
z
fzf
pandoc
gh
codex
ngrok
docker-compose
withgraphite/tap/graphite
"

for pkg in $PACKAGES; do
  if ! brew list "$pkg" >/dev/null 2>&1; then
    echo "▶ Installing $pkg"
    brew install "$pkg"
  else
    echo "✔ $pkg already installed"
  fi
done
#!/bin/sh
set -eu

PACKAGES="
git
jq
bat
lazygit
z
fzf
pandoc
gh
codex
ngrok
docker-compose
withgraphite/tap/graphite
"

for pkg in $PACKAGES; do
  if ! brew list "$pkg" >/dev/null 2>&1; then
    echo "▶ Installing $pkg"
    brew install "$pkg"
  else
    echo "✔ $pkg already installed"
  fi
done

need to add a new package? add it to the PACKAGES array and run chezmoi apply as if by magic it's now available in my shell. and the best part? when i git pull on my other machines and run chezmoi apply they get the package installed as well (which can be disabled if not desirable with templates)

cal (callum morris)

staff engineer @ framer
prev. leading ai & architecture @ oxbury

i have no idea what i am doing

cal (callum morris)

staff engineer @ framer
prev. leading ai & architecture @ oxbury

i have no idea what i am doing

cal (callum morris)

staff engineer @ framer
prev. leading ai & architecture @ oxbury

i have no idea what i am doing