Kitout

Declare a Mac setup in YAML, check what already matches, and read the dry-run plan before Kitout touches the machine.

$ kitout apply --dry-run

Status and dry-run stay read-only. Real apply remains explicit.

kitout apply --dry-run no changes made
$ kitout apply --dry-run

[dry-run] Kitout is running in dry-run mode. No changes will be made.
Config: ./kitout.yaml

> Inspecting Homebrew taps...
> Checking symlink: /Users/example/.zshrc...

[dry-run] Previewing planned changes:
dry-run Would add Homebrew tap vwall/kitout
dry-run Would install cask ghostty
dry-run Would replace symlink /Users/example/.zshrc

[dry-run] No changes made because --dry-run was used.
No shell commands will run without explicit approval.
This excerpt follows Kitout's human dry-run output: inspect the plan, then decide whether a real apply is appropriate.

Local-first runbook.

Kitout now starts in the setup repo by default. Initialize the local config, keep the selected file visible, and preview before apply.

  1. 1

    Initialize the repo

    Create or reuse ./kitout.yaml, with optional repo-local agent guidance.

    kitout init --agents
  2. 2

    Run doctor

    Check macOS, Homebrew, Git, shell, config validity, and paths.

    kitout doctor
  3. 3

    Read status

    See satisfied, missing, changed, skipped, and failed resources.

    kitout status
  4. 4

    Preview before apply

    Preview changes without filesystem writes or shell execution.

    kitout apply --dry-run

Preview command: kitout apply --dry-run · Managed upgrades: kitout upgrade --dry-run · Other config: --config /path/to/kitout.yaml · Detailed guide: first real run

Agents get the same guardrails.

Kitout does not add AI behavior. It gives Codex and other coding agents durable repo guidance, read-only context, JSON reports, and one-resource explanations so they can answer without guessing.

Setup repo
kitout init --agents
kitout context
kitout status --json
kitout apply --dry-run --json
One resource
kitout explain 'symlink:/Users/example/.zshrc'
context

Lists declared resources and safe commands without live checks.

json

Feeds stable status and dry-run output to tools and agents.

approval

Real apply, shell resources, and risky changes stay human-approved.

opt out

Use kitout init --no-agents-warning when a repo intentionally has no AGENTS.md.

Agent workflow: agent context guide · Release: Kitout 2.5.0

YAML that explains itself.

The starter config stays complete, and the legend maps each block to the Mac setup resource Kitout checks before apply.

kitout.yaml
version: 1

brew:
  taps:
    - vwall/kitout
  packages:
    - git
    - gh
    - asdf
  casks:
    - ghostty
    - visual-studio-code

directories:
  - ~/.config
  - ~/.codex/skills

asdf:
  plugins:
    - name: ruby
      url: https://github.com/asdf-vm/asdf-ruby.git
      versions:
        - 3.3.6

repos:
  - path: ~/code/example
    url: git@github.com:example/example.git
    branch: main

copies:
  - source: ./codex/skills/nuxt-practices
    target: ~/.codex/skills/nuxt-practices

symlink_groups:
  - source_root: ./home
    target_root: "~"
    paths:
      - .zshrc
      - .gitconfig

security:
  filevault:
    required: true
  firewall:
    enabled: true

ssh:
  keys:
    - path: ~/.ssh/id_ed25519
      type: ed25519

login_shell:
  path: homebrew:fish

Config legend

Read the file by job. Each group links to the resource behavior behind that YAML block.

Riskier sections stay visible in status and dry-run output before a real apply asks for approval.

Apply follows the plan.

Dry-run shows what would change. Real apply rechecks current state, makes the needed changes, and reports what changed, stayed unchanged, or failed. Add --json when tools need structured output. Managed Homebrew upgrades stay separate: kitout upgrade --dry-run previews updates for installed formulae and casks declared in the selected config.

$ kitout apply

Kitout is planning changes for your Mac setup...
Config: ./kitout.yaml

> Inspecting Homebrew packages...
> Inspecting Homebrew casks...
> Checking directory: ~/.config...
> Checking repo: ~/code/example...

Applying changes:
> Installing formula gh...
> Cloning repository ~/code/example...

Results:
✓ done  brew: gh              installed formula
✓ done  repo: ~/code/example   cloned repository
✓ ok    directory: ~/.config   directory exists
✓ ok    cask: ghostty          cask is installed

Summary: 2 changed, 2 unchanged

Status names the current state

Every resource reports satisfied, missing, changed, skipped, or failed.

Apply starts from the same plan

Only resources that need work are applied, and risky changes ask first.

Upgrade stays separate

Apply installs missing managed Homebrew items; upgrade refreshes outdated installed ones.

Doctor explains blockers

Prerequisites fail early, before resource checks become noisy.

JSON is for automation

Agents and scripts can read stable reports without scraping text.

fail: Homebrew Homebrew is not available

fix: Install Homebrew, then rerun kitout doctor.

fail: Path permissions 1 configured write target(s) may not be writable

fix: Fix ownership or permissions for the listed paths, then rerun kitout doctor.

Safety rules by default.

Kitout keeps inspection and mutation separate, so each risky action stays visible before it touches the machine.

Install after the runbook is clear.

The public install path is short. The first useful run still goes through init, doctor, status, and dry-run before a real apply.

Homebrew
brew tap vwall/kitout
brew install kitout
Source
go install ./cmd/kitout
First pass
kitout init --agents
kitout doctor
kitout status
kitout apply --dry-run
kitout upgrade --dry-run

Docs without a framework.

GitHub remains the source of truth. This page now acts as the front door, with the Markdown docs grouped by the job you are doing.