Dotfiles and machine setup. setup.sh is the entry point; the declarative
parts live in mise.toml and mise/tools.toml, applied by
mise bootstrap.
| Path | What |
|---|---|
setup.sh |
The whole run, idempotent: Homebrew and the Brewfile, the aur-sorah pacman repository, mise and every bootstrap phase, and the imperative leftovers (rustup, claude plugins). |
mise.toml |
[dotfiles] for the dotfiles, [bootstrap.packages] for macOS app casks and the Arch pacman and AUR packages, [bootstrap.macos] for UI preferences, [bootstrap.linux.systemd.units] for the systemd user units. |
mise/tools.toml |
The global tool set and the [settings] that govern it. Deployed to ~/.config/mise/conf.d/sorah-tools.toml, so it applies in every directory rather than only in this repo. |
Brewfile |
What Homebrew still owns: sudo-requiring casks, formulae, Mac App Store apps. |
mkdir -p ~/git && git clone git@github.com:sorah/config.git ~/git/config
cd ~/git/config && ./setup.shYou have to:
- Accept the Xcode command line tools at the first
gitprompt (macOS). - Clone to
~/git/config—misc/dot.gitconfigis included by absolute path. - Sign in to the App Store first, or the
masentries fail (macOS). - Enter an admin password for the first cask group (macOS).
- Log out and back in, for input sources (AquaSKK/ABC), the fn key action and modifier-key remapping on already-connected keyboards (macOS).
The platform comes from /etc/pacman.conf and uname; pass arch, linux or
mac as $1 to override. [bootstrap.packages] holds every platform's
packages and each entry is applied only where its manager exists, so the casks
are inert on Arch and the pacman:/aur: entries are inert on macOS.
[bootstrap.macos] is macOS-scoped the same way.
./setup.sh converges an existing machine without reinstalling anything, but
applies everything without asking. To transfer ownership step by step instead,
first look:
mise self-update
cd ~/git/config && mise trust
mise bootstrap packages status
mise bootstrap macos defaults status
mise bootstrap dotfiles status
mise bootstrap linux systemd-units statusThen apply:
mise bootstrap --only macos-defaults --yes
mise bootstrap --only dotfiles --yes
mise trust ~/.config/mise/conf.d/sorah-tools.toml
mise bootstrap --only tools --yes
mise bootstrap packages apply --manager aur --yes # Arch
mise bootstrap --only linux-systemd-units --yes # Linux- Every package should already read
installed: mise reads the Homebrew prefix directly, and a Homebrew-owned cask satisfies its entry without mise taking ownership, so no app bundle is replaced and Privacy & Security grants survive. - A dotfile reading
differs (exists but is not a symlink)blocks the whole dotfiles phase, not just its own entry. Move it aside by hand, or let./setup.shdo it. Not--force-dotfiles: for a directory target it deletes the directory. --only macos-defaultsand notmise bootstrap macos defaults apply, which skips thepost-defaultshook that restarts Dock, Finder and SystemUIServer.min_versioninmise.tomlstops an older mise with self-update instructions, so theself-updateabove is only to get it over with early.goplsispacman:goplson Arch and ago:entry inmise/tools.tomlon macOS.~/.gopath/binprecedes both/usr/binand the mise shims in~/.zshrc, sosetup.shdeletes~/.gopath/bin/gopls; ago installcopy left there would keep winning.- An old
bazelisk-binfrom yay conflicts withpacman:bazeliskwithout providing it, which fails the whole pacman transaction.setup.shremoves it first; by hand,sudo pacman -Rdd bazelisk-bin. - On Arch,
packages statusshould show everythinginstalledtoo: both backends read pacman's database, andpacman:resolves groups and virtual provides, sobase-devel,netcat,bind-toolsandebtablescount as installed throughbase-devel's members,openbsd-netcat,bindandiptables.
Finally, strip ~/.config/mise/config.toml down to two settings, deleting the
[tools] and [tool_alias] tables:
mise unuse --global --no-prune $(mise ls --current 2>/dev/null | awk '$3 ~ /config\.toml$/ {print $1}')config.tomloverridesconf.d, so while an entry is duplicated there it, not this repo, decides that tool's version.mise/tools.tomldeclares all of them, so both tables can go entirely.- Some of them are declared here under a different name, so check before
assuming a tool disappeared:
aws-cliandpinactare theaqua:entries,ghisgithub-cli,ubi:sqldef/sqldefissqlite3def, the twoubi:smithy entries are thegithub:[tool_alias]definitions, and any otherubi:owner/repoisgithub:owner/repo. - Keep
[settings] paranoidand[settings] disable_tools; delete the other settings.experimental,lockfile,idiomatic_version_file_enable_toolsandnpm.package_managerlive inmise/tools.tomlnow, and aconf.dfragment serves them once trusted.paranoidis the one that cannot move -- mise wants trust before parsing a symlink into this repo, and an unparsed file cannot be what turns paranoid on -- anddisable_toolsis per machine. --no-prunekeeps the installations. Unrelated tomise prune, which deletes unused tool versions and never edits configuration.
cd ~/git/config && git pull && ./setup.shOr apply just the declarative half:
mise trust && mise trust ~/.config/mise/conf.d/sorah-tools.toml
mise bootstrap --dry-run
mise bootstrap --yes- Both
mise trustcalls are needed after any pull that touchesmise.tomlormise/tools.toml: paranoid mode binds trust to file contents, and an untrusted config is skipped rather than applied. - A full bootstrap runs the
post-defaultshook every time, restarting Dock, Finder, SystemUIServer and ControlCenter.mise bootstrap --only packages,tools --yesavoids that. - A bare
mise bootstrapcannot install theaur:entries on a machine that has no AUR helper yet: mise's AUR backend shells out to yay, yay is a mise tool, and the packages phase runs before the tools phase. It reports them asskipped (neither yay nor paru found)rather than failing, andmise bootstrap packages apply --manager aur --yespicks them up afterwards.setup.shdoes exactly that. - Removals need hands. A tool dropped from
mise/tools.tomlstays installed (mise unuse), a cask dropped from[bootstrap.packages]stays installed (mise bootstrap packages prune --dry-run), a dotfile dropped from[dotfiles]stays deployed (mise bootstrap dotfiles unapply), and a deleted macOS preference keeps its value — mise never deletes a default.prunecovers Homebrew only;pacmanandauranswerdoes not support pruning, so a dropped Arch package needspacman -Rsby hand.
[dotfiles] in mise.toml deploys them. Most are symlinks into the repo, so
editing the live file edits the repo.
~/.config/karabiner/karabiner.json and
~/.config/linearmouse/linearmouse.json are mode = "copy": both apps rewrite
their config in place, which replaces a symlink with a regular file. The repo
is the source of truth, and an apply overwrites the target — plain file or
symlink — without --force.
Platform-specific entries (~/.zshrc_global_env, the Linux .desktop file)
use a logical key with the target in variants, since a dotfile entry has no
os key of its own. An entry whose variants do not match is not deployed.
~/.tmux.reattacher is generated by setup.sh, and ghq.root and
include.path stay git config --global so a machine can override them.
By hand:
- Run
mise bootstrap dotfiles add --changedto capture app-side edits to the copy-mode files into the repo. An apply discards whatever was not captured. - Delete the
<name>.pre-mise.<timestamp>backupssetup.shleaves behind when it moves a conflicting target aside.
[bootstrap.linux.systemd.units] in mise.toml generates them from structured
keys rather than from a unit file in the repo, so every directive is a TOML key
and string values are Tera templates.
mise installs each as dev.mise.<name>.service, not <name>.service.
setup.sh removes the bare-named copies it used to install, disabling and
stopping them first.
homeproxy is declared wanted_by = [] and start = false: installed, but
with no [Install] section and not running. To run it on a machine:
systemctl --user add-wants default.target dev.mise.homeproxy.service
systemctl --user start dev.mise.homeproxyadd-wants rather than enable, which needs an [Install] section. Both
undone by the next apply, which converges the unit back to disabled and
stopped.
mise use -gwrites to~/.config/mise/config.toml, which overrides the repo's fragment. Fold ad-hoc installs back intomise/tools.toml.mise bootstrap statussummarises every declarative part; every apply takes--dry-run.logitech-g-hubstays in the Brewfile because its cask installer runs sudo, which mise's own cask implementation rejects.pacman:andaur:entries can only be"latest". Arch repositories carry one version of each package, and an AUR helper builds the current PKGBUILD.pacman -S --needednever refreshes the sync databases, sosetup.shrunspacman -Sybefore the packages phase. A full-Syustays a manual decision.- yay comes from
github:Jguer/yay, not themise-yayasdf plugin it replaced. Delete the old one withmise uninstall asdf:mise-plugins/mise-yayonce the new one works; while both are installed the shim order decides which mise calls. paru is not usable here at all -- its release binary linkslibalpm.so.15and Arch is on.so.16. - The deprecated
ubi:backend is not used;github:replaces it. Installs made through it linger until removed withmise uninstall --all ubi ubi:kagehq/port-kill ubi:sorah/mairu ubi:ayinke-llc/sdump. A registry tool such ask9smay also have been installed through ubi;mise doctornames those, andmise uninstall --all k9s && mise install k9smoves it back. - The
github:backend queries the GitHub API on install, whose anonymous rate limit a full bootstrap exceeds.setup.shexportsGITHUB_TOKENfromgh auth tokenwhenghis logged in.
Copyright (c) 2020 Sorah Fukumori
Available under the MIT License unless otherwise noted.