Setup automation for a Mac: the Homebrew bundle, setup.sh with its tasks/*.sh, and the
dotfiles submodule synced into ~. It is the legacy half of the machine configuration and is
migrating into Tapppi/systems, which already owns a narrow
set (its AGENTS.md lists what). This repo is public: keep private values and secrets out of it.
setup.sh: the entry point../setup.sh <task>dispatches totasks/and defines the shared helpers. Its dispatchcasenames every command with a one-line description, and the README describes each task.tasks/:init.sh(system init),install.sh(software, runtimes, the document skills' tools, dotfiles sync, agent harnesses),config.sh(app configuration),macos.sh(macOS defaults; a separate task because it kills Finder, Dock and ControlCenter),projects.sh(per-workspace plugins and env from.tapppi-projectmanifests). Each function's header comment documents it.Brewfile: the Homebrew manifest for Apple Silicon Macs.dotfiles/: a submodule (Tapppi/dotfiles) with its ownAGENTS.md: shell and harness config, and the user-level agent instructions inagents/..extra(git identity, personal aliases),.path(PATH extensions),.credentials.dist(the template for~/.config/bash/.credentials);backup.sh,restore.shandrestore.bom;hooks/(git hooks).docs/: harnesses.md (how setup configures the agent harnesses, and why tool-owned config is re-asserted), skills.md (how skills and plugins reach a repo), conventions.md (shell, Brewfile, PATH and XDG conventions).
- Never run
setup.sh,tasks/*.shordotfiles/bootstrap.sh. They change system configuration, install software and needsudo; the owner runs them. The one exception: thetool-update-reviewskill's apply step may run./setup.sh projects, only that subcommand, when an accepted suggestion edits a filetasks/projects.shmanages (workspace.tapppi-project.jsonmanifests, renderedmise.local.toml). That task is idempotent, needs nosudoand touches no system-wide state. The exception covers no other automation. - Edit dotfiles in the submodule, never in
~. Change the source indotfiles/home/ordotfiles/config/and copy the changed file into place; the files under~/,~/.claude/,~/.codex/,~/.cursor/,~/.pi/and~/.config/are deployment targets. The generated user-level instruction files are edited one step further back, indotfiles/agents/. Live files with no dotfiles source (~/.config/bash/.credentials,~/.codex/config.toml,~/.claude.json) are changed by the owner or the owning tool's CLI and never copied into dotfiles. - Tool-owned config is re-asserted, not vendored. Keep the re-asserting steps last in
install(), afterinstall_dotfiles, and make every dispatch that runsinstall_dotfilesre-assert too. Never copy a tool's key intodotfiles/home/; harnesses.md explains why. shellcheckevery modified.shfile before committing, and never introduce new warnings.- Bootstrap code must be portable to the stock BSD userland, since it can run before the GNU tools are installed; everything else may assume GNU. conventions.md has the pitfalls.
- Keep scripts idempotent, and fail in functions with
return 1, notexit 1. - Never commit
.credentials, keys, tokens, passwords,.DS_Storeor backup tarballs.
bash hooks/install.sh # once after cloning: core.hooksPath
shellcheck setup.sh tasks/*.sh backup.sh restore.sh
shellcheck dotfiles/bootstrap.sh dotfiles/config/bash/.functions dotfiles/agents/render.sh
dotfiles/agents/render.sh --check # generated instructions are current
brew bundle check --file=Brewfile # read-onlyThere is no test suite.
.editorconfig sets the formatting: tabs (width 2) for code, and for Markdown spaces with
two-space list indentation, prose wrapped at 100 columns and fenced code with a language. Shell
style, Brewfile rules and PATH layering are in conventions.md.
Git work here follows the ikeh-git:git-workflows skill from the ikeh-git plugin, which
.claude/settings.json enables; load it before the first commit. Commits are SSH-signed through
1Password; messages are imperative and concise ("Add podman", "Update dotfiles"). Use the
configured git identity, never change it, and add no AI attribution. This repo and dotfiles use
master.
The plugin's two guards run on every Bash call:
- Push guard. A push to
originof an agent branch (agent/, any conventional-commit prefix,debug/orbackup/: the plugin's default list, since this repo sets nobranchPrefixes) runs without a prompt, including--force-with-lease --force-if-includesuntil the branch's PR carries a review or comment. Every other push prompts. Name the branch on each push, and keepmainandmasterout of agent branch names: theaskrules prompt for any push whose text contains them. - Worktree guard. Whole-tree staging in the main checkout is denied, and so is any rebase of
master.requireWorktreeis off, so a small change may be committed from the main checkout by explicit path. Do not use thecamalias here: it stages every change.
The guard decides how you may push, never whether: push only when the request calls for it, and
answer a prompt rather than reshaping the command until it stops. Committed enablement installs
nothing: on a new machine, run claude plugin install ikeh-git@ikeh --scope local in this repo.
dotfiles has its own history on master, and this repo tracks its commit. Run from this repo's
root, never cd into the submodule, and stage only the paths you changed:
git -C dotfiles add <specific paths>
git -C dotfiles commit -m "Description of change"
git -C dotfiles push origin master
git add dotfiles
git commit -m "Update dotfiles"