Skip to content
MattKunzePublic

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

Repository files navigation

dotfiles

Dotfiles managed by chezmoi, tools managed by mise. Works on macOS, Linux, and WSL.

Onboarding a new machine

  1. Install fish manually (it's the one thing kept outside this toolchain):

    # macOS (if you have brew):
    brew install fish
    # Debian/Ubuntu: sudo apt install fish
    # Fedora:        sudo dnf install fish
    # Arch:          sudo pacman -S fish
    # NixOS (configuration.nix): environment.systemPackages = [ pkgs.fish ];
  2. Clone and bootstrap:

    git clone https://github.com/MattKunze/dotfiles.git && cd dotfiles
    ./bootstrap.sh

    Debian/Ubuntu note: also sudo apt install libatomic1 — the node binary needs it (preinstalled on macOS/Fedora/Arch equivalents).

    NixOS note: enable nix-ld in your configuration first — programs.nix-ld.enable = true;. All mise tools install as precompiled glibc-linked binaries (the global mise config forces all_compile = false, since building them from source needs a system toolchain NixOS doesn't have), and nix-ld is what lets those binaries run.

    This installs mise + chezmoi into ~/.local/bin, applies all dotfiles, installs polytoken (via a chezmoi run_once script) and every tool in the mise config, and creates ~/.config/secrets/. It prompts for machine type (personal/work); for non-interactive runs (containers, CI) set CHEZMOI_MACHINE_TYPE=personal (or work) instead.

  3. Finish by hand (one-time, per machine):

    chsh -s "$(command -v fish)"   # make fish your login shell
    gh auth login
    tg auth login <handle>         # tangled.org CLI (OAuth flow, like gh)
    atuin login                    # or: atuin register
    opencode                       # OpenCode, first-run setup
    polytoken                      # first-run setup

    Machine-specific keys/env go in ~/.config/secrets/*.fish (fish syntax, sourced at shell startup; see ~/.config/secrets/README.md).

Daily use

Task Command
Apply dotfile changes chezmoi apply (abbr: cma)
Edit a managed file chezmoi edit <path> then chezmoi apply
Pull + apply everywhere chezmoi update (abbr: cmu)
See what would change chezmoi diff (abbr: cmd)
Install/upgrade tools mise install (abbr: mi) / mise upgrade
Everything at once mise run update (abbr: mr update) — also updates polytoken
Fish abbreviations all in dot_config/fish/conf.d/abbr.fish

Layout

.chezmoi.toml.tmpl       prompts for machine type (personal/work) on init
.chezmoidata.yaml        shared defaults (identities, atuin sync servers)
dot_config/              files applied to ~/.config/
  fish/                  shell config; abbreviations in conf.d/abbr.fish
  git/, jj/              identity templated per machine (personal vs work)
  atuin/                 sync address templated per machine
  ghostty/, gh/          terminal + github cli (machine overrides via
                         secrets/ghostty.conf)
  polytoken/             sparse: config.yaml + themes/warm-burnout.yaml only
  mise/config.toml       global tool list (installed by mise install)
  mise/tasks/            mise tasks (mise run update, ...)
  secrets/               README only — actual secret files are untracked
run_onchange_install-packages.sh.tmpl   re-runs `mise install` on config change
run_onchange_sync-warm-burnout-remote.sh.tmpl   repoints the theme checkout
                                        when warm_burnout.url changes
run_once_install-polytoken.sh           installs polytoken if missing
run_once_remove-opencode-v1-path.sh     one-time PATH cleanup (old opencode)
bootstrap.sh             one-shot onboarding script (not applied to $HOME)

Polytoken

Polytoken is not managed by mise — it isn't in mise's registry, and it ships its own updater (release channels, launch-time update checks), which would conflict with mise upgrade. Instead it is installed by the official shell installer into ~/.local/bin alongside mise/chezmoi:

  • Fresh machines: bootstrap.sh → chezmoi init --apply runs run_once_install-polytoken.sh.
  • Already-bootstrapped machines: the same script runs on the next chezmoi apply (installs only if the binary is missing).
  • Updates: mise run update runs polytoken update and regenerates fish completions; polytoken also checks for updates on its own at launch.

Fish completions live in ~/.config/fish/completions/polytoken.fish and fish loads them automatically.

The config dir ~/.config/polytoken is managed sparsely — only config.yaml and the themes/warm-burnout.yaml symlink are in chezmoi; polytoken's own churn (timestamped config.yaml.*.bak backups, prompt_history/) is untracked and listed in .chezmoiignore so it never sneaks in. If polytoken ever rewrites config.yaml (e.g. a config-version migration), chezmoi diff will show it — review and chezmoi merge ~/.config/polytoken/config.yaml instead of blindly applying, or you'd revert the migration.

HTTPie

HTTPie is not in mise's registry (the registry's httpie-go is a separate Go reimplementation), and it's a Python package, so it's installed with the mise-managed uv tool runner into ~/.local/bin (http, https, httpie):

  • Fresh/changed machines: run_onchange_install-packages.sh.tmpl runs uv tool install httpie (or uv tool upgrade httpie if already present) after mise install.
  • Updates: mise run update runs uv tool upgrade httpie.
  • Manual: uv tool install httpie / uv tool upgrade httpie.

Adding a tool

mise registry | grep <name>     # find its backend
mise use -g <name>              # adds to ~/.config/mise/config.toml
mise install

Go-based CLIs without a registry entry can be built from source with the go backend — e.g. tg (tangled.org CLI, module github.com/alyraffauf/tg):

"go:github.com/alyraffauf/tg/cmd/tg" = "latest"   # in dot_config/mise/config.toml

mise install compiles it with the mise-managed go toolchain, exposes the binary via shims, and mise upgrade keeps it current.

Languages work the same way: mise installs the toolchain (go, rust, node), and binaries you build land in ~/go/bin or ~/.cargo/bin (both on PATH). Per-project tool versions: mise use <tool>@<version> inside the project (replaces devenv/direnv).

Testing

./test/smoke.sh builds a bare debian:latest image containing only the documented prerequisites (fish, git, curl, libatomic1), runs bootstrap.sh inside it, and verifies the results: dotfiles applied, polytoken installed, fish starts and loads 67+ abbreviations, mise tools installed, templated config rendered.

The repo is volume-mounted and used directly as the chezmoi source (DOTFILES_LOCAL_SOURCE), so uncommitted changes are tested. To test the true onboarding path (clone from origin), comment out the DOTFILES_LOCAL_SOURCE env in test/smoke.sh after pushing.

Machine type is forced to personal via CHEZMOI_MACHINE_TYPE (no TTY in containers); set work to test work-machine rendering.

Theming

The warm-burnout theme (a fork of felipefdl/warm-burnout, with a polytoken platform added) is pulled by chezmoi as an external into ~/.local/share/warm-burnout — no submodules, and it refreshes with chezmoi update (weekly; force with chezmoi update --refresh-externals). The checkout is a cache, not a working tree. Symlinks into it are managed like any other dotfile:

  • ~/.config/opencode/themes/warm-burnout.json (theme file, via external)
  • ~/.config/opencode/cli.json (activates the theme + shared UI settings; auth lives in the untracked service.json)
  • ~/.config/ghostty/themes/warm-burnout-{dark,light} (ghostty config points at these via theme = dark:warm-burnout-dark,light:warm-burnout-light)
  • ~/.config/polytoken/themes/warm-burnout.yaml (polytoken theme, referenced by theme-file in ~/.config/polytoken/config.yaml)

The external's url lives in .chezmoidata.yaml (warm_burnout.url) so it's declared in one place: .chezmoiexternal.yaml.tmpl clones it on new machines, and run_onchange_sync-warm-burnout-remote.sh re-runs whenever the url changes and repoints the checkouts that already exist (chezmoi's git-repo externals just git pull from whatever origin a checkout already has — they never notice a url change on their own). Changing warm_burnout.url is therefore all it takes to switch forks everywhere on the next chezmoi apply.

The upstream repo also ships themes for bat, eza, alacritty, and others — to wire up another app, add a symlink_ file under the right dot_config/... path pointing into ~/.local/share/warm-burnout/<app>/... (see existing examples), then chezmoi apply.

Ghostty's per-machine settings (e.g. the font) are not templated at all: the managed config ends with config-file = ?~/.config/secrets/ghostty.conf (rendered absolute). Ghostty processes included config last, so keys in that untracked file override the managed defaults, and the ? keeps it optional — machines without the file use the defaults (font: Maple Mono NF). This keeps chezmoi diff clean no matter which shell renders the templates.

Extending

  • New dotfile: chezmoi add ~/.config/foo/bar.conf, then chezmoi apply.
  • Machine-specific bits: wrap content in templates (.tmpl) and branch on .is_work / .machine_type, or add data to .chezmoidata.yaml.
  • Longer term, secrets can move to chezmoi's age/1Password support; the ~/.config/secrets/*.fish mechanism won't need to change.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages