Config-driven macOS AI development environment β extensible, reliable, and maintainable.
Add a new agent = add a folder. No code changes.
AI_SETUP/
βββ setup.sh # Bash bootstrap β installs brew+node, runs orchestrator
βββ nuke.sh # Bash bootstrap β runs teardown
βββ package.json / tsconfig.json
β
βββ src/
β βββ orchestrate.ts # Main entry: foundations β select agents β install β MCP β auth
β βββ nuke.ts # Teardown: select agents β uninstall β cleanup β remove foundations
β βββ ai-init.ts # Project scaffolder: select agent β copy scaffold + plugins
β βββ core/
β β βββ types.ts # AgentConfig, AgentDriver, PluginConfig, Context interfaces
β β βββ registry.ts # Auto-discovers agents/ and plugins/ folders
β β βββ config.ts # Reads + validates agent.json
β β βββ runner.ts # Builds Context objects for drivers
β βββ lib/
β β βββ ui.ts # Terminal output (chalk colors, headers, steps)
β β βββ shell.ts # exec, retry, safeRm, sudoRm
β β βββ prompts.ts # Interactive menus (inquirer)
β β βββ mcp.ts # Write MCP configs to disk
β β βββ template.ts # Deep-copy scaffold dirs with {{VAR}} replacement
β βββ foundations/
β βββ index.ts # Install/uninstall in order: brew β node β python β git
β βββ homebrew.ts
β βββ node.ts
β βββ python.ts
β βββ git.ts
β
βββ agents/ # One folder per agent (data, not code)
β βββ claude/
β β βββ agent.json # Config: name, MCP paths, cleanup paths
β β βββ driver.ts # 4 functions: isInstalled, install, authenticate, uninstall
β β βββ mcp/ # Global MCP JSON files
β β βββ scaffold/ # Files copied into new projects by ai-init
β βββ codex/
β β βββ agent.json # Config: name, MCP paths (TOML), cleanup paths
β β βββ driver.ts # npm install, ChatGPT auth, npm uninstall
β β βββ mcp/ # Global MCP TOML (merged into ~/.codex/config.toml)
β β βββ scaffold/ # AGENTS.md, .codex/, .agents/skills/
β βββ cursor/
β βββ vscode/
β βββ _template/ # Copy this to add a new agent
β
βββ plugins/ # Optional cross-agent project add-ons
βββ _template/
# Setup everything
chmod +x setup.sh && ./setup.sh
# Scaffold a new project
ai-init
# Teardown everything
chmod +x nuke.sh && ./nuke.sh
# Dry run (see what would happen without doing it)
./setup.sh --dry-run
./nuke.sh --dry-run| Agent | Icon | Global MCPs | Project Scaffold |
|---|---|---|---|
| Claude Code | π€ | sequential-thinking, memory | CLAUDE.md, rules, skills, .mcp.json |
| VS Code | π | puppeteer | copilot-instructions.md, .instructions.md, skills, .vscode/mcp.json |
# 1. Copy the template
cp -r agents/_template agents/opencode
# 2. Edit the config
# agents/opencode/agent.json β name, MCP paths, cleanup paths
# agents/opencode/driver.ts β isInstalled, install, authenticate, uninstall
# 3. Add MCP configs
# agents/opencode/mcp/global.json
# 4. Add scaffold files
# agents/opencode/scaffold/ β rules, skills, project MCP, etc.
# 5. Done. Run ./setup.sh β OpenCode appears in the menu automatically.import type { AgentDriver, Context } from "../../src/core/types.js";
export const driver: AgentDriver = {
async isInstalled() { /* return true if installed */ },
async install(ctx) { /* install the agent */ },
async authenticate(ctx) { /* prompt user to log in */ },
async uninstall(ctx) { /* remove the agent */ },
};
export default driver;Codex is unique among the agents because it uses TOML configuration (not JSON) and has a richer per-project structure: subagents, command rules, skills, and shared .agents/ skills.
Installs the CLI via npm install -g @openai/codex, then merges MCP servers into ~/.codex/config.toml (preserving your existing model, sandbox, and approval settings):
# Your existing settings stay untouched
# model = "gpt-5.4"
# approval_policy = "on-request"
[mcp_servers.context7]
command = "npx"
args = ["-y", "@upstash/context7-mcp"]
[mcp_servers.sequential-thinking]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-sequential-thinking"]
[mcp_servers.memory]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-memory"]myapp/
βββ AGENTS.md # Project instructions for Codex
βββ .agents/
β βββ skills/ # Shared skills (usable by any subagent)
β βββ code-review/
β β βββ SKILL.md # Structured review workflow
β βββ testing-strategy/
β βββ SKILL.md # Unit/integration/E2E patterns
βββ .codex/
βββ config.toml # Project-level MCP servers + settings
βββ agents/
β βββ explorer.toml # Read-only codebase exploration (skills disabled)
β βββ reviewer.toml # PR review (code-review + testing-strategy enabled)
βββ rules/
β βββ default.rules # Starlark command policies
βββ skills/
βββ project-conventions/
βββ SKILL.md # Coding standards, git workflow, docs
The framework detects config format from file extension:
| Source file | Read as | Destination file | Write as |
|---|---|---|---|
mcp/global.json |
JSON | ~/.cursor/mcp.json |
JSON (overwrite) |
mcp/global.toml |
TOML | ~/.codex/config.toml |
TOML (merge) |
TOML destinations are merged (not overwritten) β your existing config.toml settings are preserved. JSON destinations use the existing overwrite behavior.
Each .toml file in .codex/agents/ defines a subagent with its own model, sandbox, and skill configuration:
# .codex/agents/reviewer.toml
name = "reviewer"
description = "PR reviewer focused on correctness, security, and missing tests."
sandbox_mode = "read-only"
model_reasoning_effort = "high"
[[skills.config]]
path = ".agents/skills/code-review/SKILL.md"
enabled = trueSubagents toggle shared skills independently β the explorer disables review skills, the reviewer enables them.
.codex/rules/default.rules uses Starlark syntax:
prefix_rule(
pattern = ["git", ["status", "log", "diff"]],
decision = "allow",
)
prefix_rule(
pattern = ["git", ["push", "reset", "rebase"]],
decision = "prompt",
justification = "Destructive git operations need human review.",
)Plugins are optional add-ons that inject files into projects during ai-init.
# 1. Copy the template
cp -r plugins/_template plugins/git-hooks
# 2. Edit plugins/git-hooks/plugin.json
{
"name": "Git Hooks",
"id": "git-hooks",
"description": "Husky + commitlint pre-commit hooks",
"icon": "πͺ",
"compatibleAgents": [] // empty = compatible with all agents
}
# 3. Add files under plugins/git-hooks/files/
# These are copied to the project root preserving directory structure.
# Supports {{PROJECT_DIR}} and {{PROJECT_NAME}} tokens.
# 4. Done. Plugin appears in ai-init menu automatically.- Bash bootstrap ensures Homebrew + Node exist
orchestrate.tsinstalls foundations (brew, node, python, git)- Auto-discovers
agents/*/agent.json - Interactive checkbox: pick which agents to set up
- For each agent: install β write global MCP β authenticate
- Injects
ai-initshell function into~/.zshrc
- Safety gate (type NUKE to confirm)
- Auto-discovers all agents
- For each: run
driver.uninstall()β remove cleanup paths β remove MCP configs - Removes
ai-initfrom shell configs - Uninstalls foundations in reverse order
- Prompt for project name
- Select one agent from discovered list
- Optionally select plugins
- Deep-copy
agents/<id>/scaffold/into new project - Replace
{{PROJECT_DIR}}and{{PROJECT_NAME}}tokens in copied files - Copy plugin files into project
| Principle | Implementation |
|---|---|
| Convention over configuration | Agents discovered by folder existence β no central registry |
| Data, not code | MCP configs, rules, skills are plain files β edit with any editor |
| Typed driver contract | AgentDriver interface enforces consistent 4-function API |
| Idempotent | Every step checks before acting (already installed β skip) |
| Dry run | --dry-run flag prints actions without executing |
| Isolated agents | One agent's broken config can't affect another |
| Template tokens | {{PROJECT_DIR}} replaced at scaffold time for dynamic values |
| Agent | Global MCP(s) | Project MCPs |
|---|---|---|
| Claude Code | sequential-thinking + memory | filesystem + github |
| Codex | context7 + sequential-thinking + memory | git + filesystem |
| Cursor | fetch | brave-search + git |
| VS Code | puppeteer | sqlite + postgres |
| # | Claude Code | Codex | Cursor | VS Code |
|---|---|---|---|---|
| 1 | api-design β REST, Zod, rate limiting, OpenAPI | code-review β Structured review, security, correctness | react-components β Functional, hooks, lazy loading | typescript-strict β Strict config, generics, utility types |
| 2 | error-handling β Error classes, tracing, circuit breakers | testing-strategy β Unit, integration, E2E patterns | tailwind-patterns β Utility-first, responsive, dark mode | full-stack-patterns β Shared types, typed API, e2e safety |
| 3 | project-conventions β Code org, git workflow, docs |
{ "name": "OpenCode", // Display name "id": "opencode", // Must match folder name "description": "Terminal AI", // Shown in menus "icon": "π₯οΈ", // Menu icon "requires": ["homebrew", "node"], "installMethod": "custom", // "custom" | "brew-cask" | "brew" | "npm-global" "command": "opencode", // CLI command to check installation "mcp": { "global.json": { // File under mcp/ β destination path "path": "~/.opencode/mcp.json" } }, "cleanup": { "paths": ["~/.opencode"], // Removed by nuke (user-level) "sudoPaths": [] // Removed by nuke (with sudo) } }