Dotfiles and machine setup for macOS and Linux, managed with
mise. One mise bootstrap installs system packages,
clones repositories, links dotfiles and installs tools.
curl -L https://raw.githubusercontent.com/samhvw8/dotfiles/main/setup.sh | bashFor a minimal install (servers), pass --minimal:
curl -L https://raw.githubusercontent.com/samhvw8/dotfiles/main/setup.sh | bash -s -- --minimalsetup.sh:
- Installs the Xcode Command Line Tools on macOS, or git and curl on Debian/Ubuntu, asking for your password once.
- Installs mise (or runs
mise self-updatewhen it is older than 2026.9.8), clones this repository to~/.dotfiles, and enables its pre-commit hook. - Asks for your git name and email and saves them in
~/.config/mise/config.local.toml. SetDOTFILES_GIT_NAMEandDOTFILES_GIT_EMAILto skip the prompt. - Links
~/.config/mise/config.tomlto the full or minimal config. - Copies every existing file it is about to replace into
~/.dotfiles-backup-<timestamp>/. - Runs
mise bootstrap. It refreshes package metadata (apt-get update, which needs sudo) only when a package is missing, so an up-to-date machine needs no password.
Then open a new shell. On a full install, run ccp bootstrap to fetch the
Claude Code skills installed from ccp sources; only the ccp hub items created
by hand are stored here.
| Path | Purpose |
|---|---|
home/ |
Dotfiles, linked to the same paths under ~ |
mise/config.toml |
Full install: tools, full-only dotfiles, packages, repos and hooks |
mise/minimal.toml |
Minimal install: a smaller tool set and the minimal .zshrc |
mise/conf.d/dotfiles.toml |
Dotfiles, packages, repos and hooks shared by both installs |
mise/scripts/ |
Bootstrap hook scripts |
mise/snippets/ |
Templated blocks managed inside files such as ~/.gitconfig |
setup.sh |
New-machine installer |
migrate-from-chezmoi.sh |
One-time migration for machines still on chezmoi |
.githooks/pre-commit |
Runs dot:check before each commit |
.okf/ |
Knowledge bundle: how and why this setup works (see below) |
~/.config/mise/config.toml links to mise/config.toml or mise/minimal.toml,
which is what makes a machine full or minimal. mise/conf.d/dotfiles.toml is
linked into ~/.config/mise/conf.d/ on both.
mise bootstrap runs these steps in order. Each one skips work that is already
done, so it is safe to run again at any time:
prepare-host.sh: XDG directories, and Rosetta 2 on macOS.- System packages:
brewandbrew-caskon macOS,apton Linux. mise installsbrewandbrew-caskentries itself; Homebrew is not installed. finish-host.sh: deb-get and zsh as the login shell on Linux.- Repositories:
~/.tmux/plugins/tpmon full installs. - Dotfiles: links and managed blocks.
- Tools from the mise config.
- Full installs only: the
~/.claudelink (see below), Claude Code MCP servers, and FiraCode Nerd Font on Linux.
Dotfiles are linked like this:
- Files under
home/.ccp,home/.configandhome/.local/binare linked one by one. Other files in those directories on the machine are left alone. - Each file directly in
home/has its own entry inmise/conf.d/dotfiles.toml. ~/.zshrclinks to.zshrcon full installs and.zshrc_minimalon minimal ones.~/.claudebelongs to ccp, which repoints it onccp use -g <profile>, so mise does not manage it. Bootstrap only creates it, withccp use -g default, when it does not exist. An existing~/.claudedirectory is left alone;ccp initmoves it into ccp.~/.gitconfigis not linked, because git andghwrite to it. mise manages two marked blocks inside it: your identity fromconfig.local.toml, and an include of~/.base.gitconfig.
mise dot status # linked, missing or different files
mise dot apply # link files added to the repository
mise run dot:save # commit every change in ~/.dotfiles
mise run dot:pull # pull the latest main from origin
mise run dot:cd # open a shell in ~/.dotfiles (exit to return)
mise run dot:status # unapplied dotfiles and uncommitted changes
mise run dot:diff # uncommitted changes and dotfiles waiting to be applied
mise run dot:update # dot:pull, link new dotfiles, install new tools
mise run dot:up # upgrade mise, its tools, ccp sources and hub items
mise run dot:rm <path> # stop managing a path; ~ keeps a real copy
mise run dot:destroy <path> # delete a path from ~ and the repository
mise run dot:add <path> # store a file or directory from ~ and link it
mise run dot:check # find unlinked files and unsaved ccp hub items
mise bootstrap --dry-run # preview the whole machine setup
mise bootstrap # packages, repos, dotfiles and toolsEdit it where it lives. Because it is a link, the change is already in
~/.dotfiles. Nothing is committed automatically; dot:save commits
everything with a message such as Update .zshrc:
mise run dot:save
git -C ~/.dotfiles pushdot:add moves the path into home/ at the same location, adds it to git,
and links it back:
mise run dot:add ~/.config/foo/config.toml
mise run dot:saveFiles inside home/.ccp, home/.config and home/.local/bin are picked up
automatically. A file directly in home/, or a new top-level directory, also
needs an entry in mise/conf.d/dotfiles.toml; dot:add and the pre-commit
hook fail until it has one.
- Tool:
mise use -g <tool>writes tomise/config.tomlthrough the link. - Package: add
"brew:<name>" = { os = "macos" },"brew-cask:<name>" = { os = "macos" }or"apt:<name>" = "latest"tomise/conf.d/dotfiles.tomlfor both installs, or tomise/config.tomlfor full installs only, then runmise bootstrap packages apply.
~/.config/mise/config.local.toml is never committed. It holds the git identity
([vars]), private environment variables such as API keys ([env]), and tools
only that machine uses ([tools]). Apart from the identity that setup.sh asks
for, recreate it by hand on a new machine.
mise gets its GitHub token by running gh auth token itself
(settings.github.credential_command), only when it calls the GitHub API.
mise run dot:update # pull, link, install new tools; `mise bootstrap` when packages or hooks changedThe ccp hub and profiles live in home/.ccp. Skills installed from ccp sources
are not stored here; ccp bootstrap fetches them. A hub item you create by
hand is only on that machine until you store it; dot:check lists such items:
mise run dot:add ~/.ccp/hub/skills/my-skillccp bootstrap --push wrote to chezmoi, which is no longer used; dot:add
replaces it.
The chezmoi source directory is already a clone of this repository, so fetch
the script with its git. Do not git pull there: merging the new layout into
it would confuse chezmoi and hide what this machine changed.
git -C ~/.local/share/chezmoi fetch origin
bash <(git -C ~/.local/share/chezmoi show origin/master:migrate-from-chezmoi.sh) --dry-run
bash <(git -C ~/.local/share/chezmoi show origin/master:migrate-from-chezmoi.sh) --keep-localThe script backs up the chezmoi repository (including unpushed commits) and
every file it manages, keeps tools only that machine uses in
config.local.toml, reuses chezmoi's git identity and minimal setting, runs
setup.sh, then moves the chezmoi directories aside as *.migrated-<timestamp>.
Without --keep-local, the machine's differing files are only saved in the
backup. With it, they are three-way merged into ~/.dotfiles and left
uncommitted; a file that conflicts keeps the repository version and the
conflicted merge is saved in the backup. Review with git -C ~/.dotfiles diff,
then mise run dot:save.
- zsh with zi plugins (syntax highlighting, autosuggestions, fzf-tab, forgit) and the starship prompt; a new shell starts in about 0.26s.
- Ctrl-R searches history with atuin (SQLite; remove
atuinfrommise/config.tomlto switch it off). Ctrl-T and Alt-C are fzf. - fzf, fd, bat, zoxide and atuin come from mise. Their init scripts are cached in
~/.cache/zsh/init/and rebuilt when a tool's version changes. - tmux passes Claude Code notifications and Shift+Enter through
(
allow-passthrough,extended-keys).
mise dot statusshows a file as different. An application replaced the link with a regular file. Copy that file intohome/if its changes should be kept, then runmise dot apply --force.- A bootstrap step fails. Fix the reported problem and run
mise bootstrapagain. Steps that already finished are skipped. - Errors about
[dotfiles]ormise dot. mise is older than 2026.9.8; runmise self-update. - Not sure what a command will change. Add
--dry-run.
More symptoms and fixes: .okf/workflows/troubleshooting.md.
.okf/ is an Open Knowledge Format
bundle describing this setup for people and agents: architecture, workflows,
and the decisions behind them. Start at .okf/index.md. Update the
matching concept in the same commit when the setup changes.
- macOS on Apple silicon, or Debian/Ubuntu Linux
- Internet connection
Until September 2026 this repository was managed with chezmoi. The last chezmoi
layout is tagged chezmoi-final-20260917.