Skip to content

Repository files navigation

title system-config
category reference
component overview
status active
version 5.2.0
last_updated 2026-08-28
tags
overview
chezmoi
mise
zsh
mcp
vscode
policy
agents
priority critical

system-config

Declarative configuration for a single macOS workstation: the shell surface, runtime defaults, editor and terminal baseline, SSH client policy, the user-level MCP catalog and default projections for seven AI tool hosts, and a root-owned permission floor for agent CLIs.

This is a deployment repository, not a library. Its output is the state of $HOME (and one file under /Library) on the machine it is applied to. Almost nothing it produces lives inside its own directory.

AGENTS.md is the canonical repository operating contract; docs/README.md is the annotated documentation index. This README is an orientation document; where it and AGENTS.md disagree, AGENTS.md wins.

Public repository. It contains configuration structure, policy, and documentation. Secret material, credentials, and resolved token values are never committed — secrets live in 1Password and are resolved at launch.

What it manages

Domain Surface Entry point
Shell zsh startup, PATH, 15 zshrc.d modules, agentic-mode gating home/dot_zshenv.tmplhome/dot_zshrc.tmpl
Runtimes global mise defaults home/dot_config/mise/
Env direnv helpers and policy home/dot_config/direnv/
Android canonical SDK root, Android CLI defaults, host/project capability reporting home/dot_androidrc.tmpl, ng-doctor android
SSH (client) ~/.ssh/config, conf.d/, allowed_signers home/private_dot_ssh/
Terminal 14 iTerm2 dynamic profiles + color presets iterm2/, scripts/install-iterm2-profiles.sh
Editor reviewed subset of VS Code user settings, profiles, extensions vscode/, scripts/sync-vscode.sh
MCP managed catalog projected across 7 user-level hosts. Cloudflare and 1Password are explicit-only; bare Codex also leaves web and RunPod disabled. App/user tables survive concurrent writes. scripts/mcp-servers.json, scripts/mcp-codex-profiles.json, scripts/sync-mcp.sh
Git identity shared commit/push gate, runtime adapters, and a fail-open SessionStart mismatch announcer; fail-silent live hook registration remains operator-controlled home/dot_local/bin/executable_git-identity-*, docs/git-identity.md
Agent permissions root-owned unconditional deny floor for Claude Code macos/claude-code/
Policy canonical live policy consumed by a sibling repo policies/host-capability-substrate/
Maintenance system update orchestration, health reporting scripts/system-update.sh, ng-doctor

Deployment mechanisms

Four distinct mechanisms put state on the machine. They have different ownership, different failure modes, and different privilege. Knowing which one owns a path is a prerequisite for changing it — docs/ai-tool-config-ownership.md is the map, and chezmoi source-path <path> is the fastest test. The four mechanisms are exhaustive over on-disk, host-scope paths only. The map also enumerates two surfaces that none of them deploy — app-installed extension config (the Claude GUI's DXT surface and its grants, §2.2a) and account-scope connectors that resolve server-side (§1, class "Account-managed") — both of which carry real authorization and are invisible to every mechanism below. Enumeration there is legibility, not governance.

  1. chezmoihome/ is the source tree. Measure the current managed-target inventory with chezmoi managed; do not copy its mutable total into general architecture prose. Go templates, not Jinja2. Guard possibly absent map keys with hasKey before reading them; | default cannot recover from missingkey=error.
  2. Repo scriptsscripts/sync-mcp.sh, scripts/sync-vscode.sh, scripts/install-iterm2-profiles.sh, scripts/mcp-usage-collector.sh. These write files chezmoi does not own, usually because the host application also writes them and only a specific block is managed.
  3. Root installmacos/claude-code/managed-settings.json, deployed by a manual sudo install to /Library/Application Support/ClaudeCode/. Not chezmoi. This is the only unconditional control on the host.
  4. Unmanaged but documented — paths this repo deliberately does not own (for example ~/.claude/settings.json, which the application appends to). Documented so drift is legible, not so it is enforced.

Configuration layers

Agent and shell behavior on this host is decided by layers with very different force. The distinction matters: most of what reads like policy is advisory.

Layer Binds at runtime? Mechanism
Root-owned managed settings Yes, unconditionally root:wheel file; survives permission-bypass modes
Host permission and sandbox settings Yes per-tool settings resolution + OS sandbox
Machine instruction files (~/.claude/CLAUDE.md) No loaded as context; not in any enforcement chain. Chezmoi-managed since 2026-08-21 (home/dot_claude/CLAUDE.md), so drift is now visible — but visibility is not binding force
Entity and project contracts (AGENTS.md, CLAUDE.md) No convention, plus whatever CI actually runs

Treat only the first two as controls. The rest describe intent.

Repository layout

home/        chezmoi source tree — the bulk of the deployed surface
scripts/     sync, update, and validation tooling
  system-update.d/   drop-in update plugins
iterm2/      dynamic profile and color-preset definitions
vscode/      managed user-setting keys, profile and extension manifests
macos/       root-owned configuration deployed by sudo, not chezmoi
policies/    canonical live policy; vendored byte-identically by a sibling repo
tests/       isolated suites (see validation caveat below)
docs/        docs/README.md is the authoritative annotated index

Boundaries

Owned elsewhere, deliberately:

  • Project-local decisions.mise.toml, .envrc, .vscode/, project MCP files, and project agent contracts belong to each project repo. See docs/project-conventions.md.
  • Host-capability-substrate — the sibling repo owns the kernel, schemas, ADRs and charter. This repo owns the live policy bytes it consumes. A byte change to policies/host-capability-substrate/tiers.yaml de-synchronizes the sibling's vendored snapshot until it is re-vendored, so it needs a coordinated change, not a unilateral edit.
  • Git identity registry — produced by a separate private repo; this repo is a consumer and enforcer only. See docs/git-identity.md.

Validation

scripts/validate-repo.sh is the single gate CI runs (.github/workflows/repo-validation.yml). It covers:

  • shellcheck (pinned to 0.11.0 via .mise.toml) over tracked *.sh plus two named templates
  • jq shape checks on the MCP and VS Code JSON manifests
  • tests/system-update, tests/android, tests/vscode, tests/mcp-vscode, tests/mcp-codex, tests/mcp-claude-desktop, tests/git-identity-gate
  • an isolated production-equivalent SessionStart launcher with a hostile outer environment; no live agent configuration is read or changed
  • scripts/policy-lint.sh, scripts/check-instruction-bridge.sh
  • repo-contract greps (no fish surface, no stale path references)

Known coverage gaps, stated rather than implied: these suites — tests/jr-style, tests/mise-config, and tests/policies — are not invoked by the gate. Some ng-doctor rows are skip/advisory rather than assertions, so a green summary is not by itself evidence of a healthy host. There is no secret or PII scanner in the gate.

Common commands

chezmoi apply --dry-run          # always preview first
chezmoi apply
chezmoi source-path <path>       # who owns this file?

ng-doctor                        # environment health report
ng-doctor --summary
system-update --check            # preview; --list shows plugins

scripts/sync-mcp.sh --dry-run
scripts/codex-mcp-readiness.sh --source
scripts/audit-agent-config.sh --source
scripts/sync-vscode.sh --check   # value-blind drift report
scripts/install-iterm2-profiles.sh

scripts/validate-repo.sh         # the gate CI runs

Conventions

  • Conventional commits; signed commits; linear history on main.
  • zsh is the only managed interactive shell. bash is script/runtime only. fish is not managed here and must not be reintroduced.
  • Documentation carries YAML frontmatter (title, category, component, status, version, last_updated, tags, priority). This is convention; nothing enforces it.
  • Secrets: 1Password is the current transitional human/workstation provider. OpenBao is intended for future machine/runtime authority only after real capability and local adoption. Root policy owns logical cohorts and aliases; projects own required names and command-scoped launchers; system-config owns local projections and adapters. Existing Dev bindings are frozen migration debt, not a generic project API. Values never enter persistent config.

system-update maintains relevant binaries, including Codex and the 1Password CLI when their owning update lanes run. It does not sync MCP config, select a Codex profile, approve a provider, or activate a secrets cutover. A tool update and a configuration/app restart are therefore followed by the separate source/dry-run checks above, not an automatic live rewrite.

About

macOS 26.0 development environment orchestration with contracts, observability, and multi-repo management

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages