bro-toolkitportable Mac setup

Dotfiles and CLI

One repo, one command, fully reversible.

My Claude skills, tmux layout, shell helpers and a kbro CLI, set up on a fresh Mac in one run. Every edit sits inside a marker block, so removing it leaves nothing behind.

  • Bash + zsh + tmux
  • macOS (Darwin) only
  • v0.2.0 · pre-stable
  • No package manager
~/claude/bro-toolkit % ./install.sh
[ok]  initialized state file at /tmp/newmac/.bro-toolkit-state.json
[bro] installing components: kbro zsh tmux claude
[bro] installing kbro CLI
[ok]  linked /tmp/newmac/.local/bin/kbro -> /tmp/newmac/claude/bro-toolkit/bin/kbro
[ok]  kbro component installed (run:  kbro help )
[bro] installing zsh integration -> /tmp/newmac/.zshrc
[ok]  backed up: /tmp/newmac/.zshrc -> /tmp/newmac/.bro-toolkit-backups/20260823T211701Z/.zshrc
[ok]  wrote marker block to /tmp/newmac/.zshrc
[ok]  zsh component installed
[bro] installing tmux integration -> /tmp/newmac/.tmux.conf
[ok]  backed up: /tmp/newmac/.tmux.conf -> /tmp/newmac/.bro-toolkit-backups/20260823T211701Z/.tmux.conf
[ok]  wrote marker block to /tmp/newmac/.tmux.conf
[ok]  tmux component installed
[bro] (reload running tmux sessions with:  tmux source-file ~/.tmux.conf)
[bro] installing Claude skills (symlinks) -> /tmp/newmac/.claude/skills
[ok]  linked /tmp/newmac/.claude/skills/pull -> /tmp/newmac/claude/bro-toolkit/claude/skills/pull
[ok]  linked 2 skill(s)
[bro] wiring preferences into /tmp/newmac/.claude/CLAUDE.md
[ok]  wrote marker block to /tmp/newmac/.claude/CLAUDE.md
[ok]  claude component installed
[ok]  install complete
[bro] next: open a new shell or run:  source ~/.zshrc  &&  tmux source-file ~/.tmux.conf

Real output, captured on a throwaway $HOME at /tmp/newmac so the paths stay short. There is no GUI — this is the whole product surface.

What it is

A new Mac, set up the way the old one was

Setting up a new machine used to be an afternoon of archaeology. Dig the tmux bindings out of an old gist. Paste four snippets back into .zshrc and hope the order still works. Remember where the Claude skills lived. Then find out a month later that the two laptops have drifted apart.

This is that afternoon, as one repo. ./install.sh writes a single marker block into ~/.zshrc, ~/.tmux.conf and ~/.claude/CLAUDE.md, symlinks the skills and the kbro CLI, and records what it did in ~/.bro-toolkit-state.json. Because every edit is bounded by markers, ./uninstall.sh can take all of it back out.

Tour

Four commands, and what they print

~/claude/bro-toolkit % ./install.sh --dry-run zsh tmux
[dry-run] init state file /tmp/newmac/.bro-toolkit-state.json
[warn] DRY RUN — nothing will be modified
[bro] installing components: zsh tmux
[bro] installing zsh integration -> /tmp/newmac/.zshrc
[dry-run] backup /tmp/newmac/.zshrc -> /tmp/newmac/.bro-toolkit-backups/20260823T211811Z/.zshrc
[dry-run] append marker block to /tmp/newmac/.zshrc
[dry-run] state: mark zsh=installed
[ok]  zsh component installed
[bro] installing tmux integration -> /tmp/newmac/.tmux.conf
[dry-run] backup /tmp/newmac/.tmux.conf -> /tmp/newmac/.bro-toolkit-backups/20260823T211811Z/.tmux.conf
[dry-run] append marker block to /tmp/newmac/.tmux.conf
[dry-run] state: mark tmux=installed
[ok]  tmux component installed
[bro] (reload running tmux sessions with:  tmux source-file ~/.tmux.conf)
[ok]  install complete

Before anything

Read the plan first

Both entry points take --dry-run. It prints every backup, symlink and marker block it would write, then exits without touching a file. Naming components installs only those.

  • Same code path as the real run
  • Components: kbro, zsh, tmux, claude
~ % kbro status
bro-toolkit v0.2.0
repo:  /tmp/newmac/claude/bro-toolkit

version:      0.2.0
repo:         /tmp/newmac/claude/bro-toolkit
installed at: 2026-08-23T21:17:01Z
last update:  2026-08-23T21:17:01Z
components:
  - claude         installed    2026-08-23T21:17:01Z
  - kbro           installed    2026-08-23T21:17:01Z
  - tmux           installed    2026-08-23T21:17:01Z
  - zsh            installed    2026-08-23T21:17:01Z

After install

What is actually on this box

The installer records each component in ~/.bro-toolkit-state.json with a timestamp. kbro status reads it back, so you can tell a half-installed machine from a finished one.

  • Per-component install and uninstall times
  • Version and repo path the state was written by
~ % kbro doctor
[bro] checking repo integrity
[ok]  installers dir present
[ok]  kbro is executable
[ok]  VERSION file present
[bro] checking touchpoints
[ok]  marker block present in /tmp/newmac/.zshrc
[ok]  marker block present in /tmp/newmac/.tmux.conf
[ok]  marker block present in /tmp/newmac/.claude/CLAUDE.md
[bro] checking symlinks
[ok]  kbro symlink ok
[ok]  skill symlink ok: k1-ubr-check
[ok]  skill symlink ok: pull

When it drifts

Check the disk, not the state file

State files lie. kbro doctor ignores the JSON and looks at what is really there: the three marker blocks, the kbro symlink, and one line per bundled skill.

  • Reports missing blocks as skipped, not failed
  • Safe to run any time — it reads only
~/claude/bro-toolkit % ./uninstall.sh --dry-run
[warn] DRY RUN — nothing will be modified
[bro] uninstalling components: claude tmux zsh kbro
[bro] removing Claude skill symlinks from /tmp/newmac/.claude/skills
[dry-run] rm /tmp/newmac/.claude/skills/k1-ubr-check
[dry-run] rm /tmp/newmac/.claude/skills/pull
[bro] removing preferences include from /tmp/newmac/.claude/CLAUDE.md
[dry-run] remove marker block from /tmp/newmac/.claude/CLAUDE.md
[ok]  claude component removed
[bro] removing tmux integration from /tmp/newmac/.tmux.conf
[dry-run] remove marker block from /tmp/newmac/.tmux.conf
[ok]  tmux component removed
[bro] removing zsh integration from /tmp/newmac/.zshrc
[dry-run] remove marker block from /tmp/newmac/.zshrc
[ok]  zsh component removed
[bro] removing kbro CLI
[dry-run] rm /tmp/newmac/.local/bin/kbro
[ok]  kbro component removed
[ok]  uninstall complete
[bro] state file (kept for audit):  /tmp/newmac/.bro-toolkit-state.json
[bro] backups (kept):               /tmp/newmac/.bro-toolkit-backups

The exit

Every trace, listed

Uninstall runs the components in reverse and prints each removal by name. Marker blocks come out of the three dotfiles, symlinks are deleted only if they still point at this repo.

  • Originals restored from the timestamped backups
  • State file and backups deliberately kept

How it works

Clone, preview, install, reload

Four steps on a new machine, in this order. Three of them take under a minute.

01

Clone the repo

Into ~/claude/bro-toolkit. The scripts resolve their own path, so anywhere else works too. Nothing outside that folder has changed yet.

02

Dry-run it

./install.sh --dry-run prints every backup, symlink and marker block it would write, then exits. Read it before the real run.

03

Run the installer

./install.sh backs up each dotfile, appends the marker blocks, links kbro and the skills, and writes the state file.

04

Reload the shell

source ~/.zshrc and tmux source-file ~/.tmux.conf. Then kbro status confirms which components landed.

Features

What’s actually in it

One-command install

One run sets up all four components. Name them — zsh, tmux, claude, kbro — to install a subset.

Dry-run on both ends

Install and uninstall both take --dry-run, printing the full plan without writing a byte.

Marker blocks

Each edited dotfile gets exactly one BRO-TOOLKIT-MANAGED block. Nothing is written outside it.

Timestamped backups

Every file touched is copied to ~/.bro-toolkit-backups/<timestamp>/ before the first edit.

Idempotent re-runs

A block that already matches is skipped, so re-running never leaves a file with two of them.

The kbro CLI

One dispatcher for help, version, status, doctor, install, uninstall, update and list.

Drift diagnostics

kbro doctor checks the repo, all three marker blocks and every symlink the installer created.

Skills as symlinks

Claude skills link into ~/.claude/skills, so a git pull in the repo updates them with no re-install.

tmux pane layout

Alt+arrow and Alt+1..5 select panes with no prefix; inactive panes dim and borders show pane titles.

Built with

Shell scripts, and where the state lives

  • Bash
  • zsh
  • tmux
  • Git
  • python3 (optional)
  • Claude Code skills
  • GitHub Pages

No server, no telemetry, no package manager. State is a JSON file at ~/.bro-toolkit-state.json and backups sit in ~/.bro-toolkit-backups/, both on your machine only. python3 is used to write the state file if it exists, and skipped with a warning if it doesn’t.

Install
git clone https://github.com/kbrovibes/bro-toolkit.git ~/claude/bro-toolkit && cd ~/claude/bro-toolkit && ./install.sh

./install.sh --dry-run  ·  ./install.sh zsh tmux  ·  ./uninstall.sh

Requires macOS: scripts/lib/common.sh checks uname -s and exits on anything that isn’t Darwin. Restart your shell afterwards, or source ~/.zshrc.

FAQ

Reasonable questions

Is it safe to run on a machine I care about?

It backs up every file it touches before the first edit, writes only inside marker blocks, and --dry-run shows the whole plan. Read install.sh before you run it anyway.

How do I get rid of it?

./uninstall.sh removes each marker block and symlink, and originals are restored from ~/.bro-toolkit-backups/<timestamp>/. The state file and the backups are kept on purpose, for audit.

Does it work on Linux?

No. scripts/lib/common.sh checks uname -s and exits on anything that isn’t Darwin. macOS is the only platform it has been run on.

Will it clobber my existing config?

It appends a block rather than rewriting the file. If something already occupies a skill symlink path, that file is backed up first, and uninstall refuses to remove anything it didn’t create.

Is it stable?

No. v0.2.0, pre-stable, expect re-runs and breaking changes. There is no licence file in the repo yet, so treat it as something to read and copy from rather than depend on.