Saddle
Keep your agents, skills, commands, and configurations in sync across Claude Code, Codex, Copilot, Cursor, Gemini, and OpenCode on every machine.
Install / Use
/learn @ndizazzo/SaddleQuality Score
Category
Development & EngineeringSupported Platforms
README
Quick Start
# Clone and set up
git clone https://github.com/ndizazzo/saddle.git ~/dev/ai
cd ~/dev/ai && pnpm install
# Launch the interactive installer
npx saddle
# Or run non-interactively
npx saddle --yes --all # apply everything
npx saddle --dry-run --all # preview first
npx saddle --check # verify sync
npx saddle --uninstall # clean removal
The interactive TUI detects which AI tools are installed and walks you through linking skills, agents, commands, and config files for each.
What Gets Synced
| Tool | Home | Skills | Agents | Commands | Root File | Config Files |
| ----------- | -------------------- | :----: | :----: | :------: | :---------: | :-------------------------------------: |
| Claude Code | ~/.claude | ✓ | ✓ | ✓ | — | — |
| Codex | ~/.codex | ✓ | ✓ | ✓ | AGENTS.md | — |
| Copilot | ~/.copilot | ✓ | ✓ | ✓ | — | — |
| Cursor | ~/.cursor | ✓ | ✓ | ✓ | — | — |
| Gemini | ~/.gemini | ✓ | ✓ | ✓ | GEMINI.md | configurations/gemini/ → ~/.gemini/ |
| OpenCode | ~/.config/opencode | ✓ | ✓ | ✓ | AGENTS.md | opencode/ → ~/.config/opencode/ |
Features
Interactive TUI — A beautiful terminal interface built with Ink. Browse tools, preview diffs, toggle individual actions — all from your terminal.
Headless-ready — Full non-interactive mode for CI/CD. --dry-run, --yes, --all, --check — automate everything.
Smart Symlinks — Creates relative symlinks, detects existing content, shows diffs before replacing, and backs up what was there.
Lockfile Tracking — Know exactly what Saddle installed. Verify sync status with --check. Safely uninstall with --uninstall.
YAML Rules — Declarative per-tool rules define what gets linked where. Add new tools by writing a single YAML file.
Zero Config — Detects installed tools automatically. Grays out what's missing. Just run saddle and go.
How It Works
1. Define — Keep agents, skills, commands, and configs in one canonical repo.
2. Detect — Saddle finds which AI tools are installed on your machine.
3. Link — Symlinks wire each tool to your canonical definitions. Done.
Canonical Layout
saddle/
├── agents/ # Per-tool instruction files and shared agent definitions
│ ├── codex/AGENTS.md
│ ├── gemini/GEMINI.md
│ └── opencode/AGENTS.md
├── commands/ # Slash command files → each tool's commands/
├── skills/ # Skill subdirectories → each tool's skills/
├── configurations/
│ └── gemini/ # Gemini-specific config → ~/.gemini/
├── opencode/ # OpenCode-specific config → ~/.config/opencode/
├── rules/ # Per-tool installer rules (YAML)
│ ├── claude.yaml
│ ├── codex.yaml
│ ├── copilot.yaml
│ ├── cursor.yaml
│ ├── gemini.yaml
│ └── opencode.yaml
└── scripts/ # Repo maintenance helpers
Keep the real files in this repo and rebuild tool-specific links on each machine. Do not sync ~/.claude, ~/.codex, ~/.cursor, ~/.gemini, ~/.copilot, or ~/.config/opencode symlinks directly between machines.
CLI Reference
saddle [options]
| Flag | Description |
| ------------------- | ------------------------------------------------------------- |
| --dry-run | Preview changes without writing to disk |
| --yes | Auto-confirm replacements without prompting |
| --all | Select every available profile |
| --profile id1,id2 | Apply specific profile IDs by name |
| --list | Print available profiles and exit |
| --check | Verify installed symlinks are in sync (exit 0 clean, 1 drift) |
| --uninstall | Remove symlinks recorded in lockfile |
| --verbose | Show extra detail (source paths, resolved targets) |
| --quiet | Suppress ok/link/skip/mkdir output; errors and summary only |
Interactive Mode
The TUI is built with Ink and @inkjs/ui. It presents selectable profiles grouped by tool, with per-action toggling and diff previews.
Profiles for tools not detected on the system are shown grayed out with a "NOT INSTALLED" badge and cannot be selected.
Non-Interactive Mode
When piped or used with --yes, Saddle falls back to a plain-text installer. Ideal for CI/CD pipelines and headless environments.
# Preview all changes
npx saddle --dry-run --all
# Apply everything, no prompts
npx saddle --yes --all
# Apply specific profiles
npx saddle --profile claude-skills-skills,cursor-directory-agents --yes
Configuration
| Variable | Default | Description |
| ------------------ | ------------------------------ | ----------------------- |
| SADDLE_DIR | ~/.config/saddle | Base config directory |
| SADDLE_CONFIG | ~/.config/saddle/config.yaml | Path to config file |
| SADDLE_RULES_DIR | ~/.config/saddle/rules | Path to rules directory |
Writing Rules
Rules are YAML files that define how to sync a tool's configurations. Each rule describes what to link and where. Place custom rules in ~/.config/saddle/rules/ (or set SADDLE_RULES_DIR to override).
Rule Schema
tool: claude # Unique identifier for this tool
label: Claude Code # Display name in the TUI
binary: # How to detect if tool is installed (optional)
which: claude # Try `which claude` to detect
# OR
paths: # Or check these paths on specific platforms
darwin: /Applications/Claude.app
linux: /usr/bin/claude
home: ~/.claude # Tool's config directory (supports ~)
enabled: true # Include in sync (default: true)
mode: multi-select # Selection mode: multi-select (default) or single-select
mappings: # List of what to link
- type: skills # Type: skills | file | directory
source: skills # Path relative to repo root
target: skills # Path relative to home (or . for home itself)
itemType: skill # Optional: type hint for skills mapping
- type: file # Link a single file
source: agents/claude/AGENTS.md
target: AGENTS.md # File name in home
- type: directory # Link files from a directory
source: configs/claude
target: . # Flatten files directly into home
Key Fields
| Field | Required | Type | Notes |
| ---------- | -------- | ------- | -------------------------------------------------- |
| tool | ✓ | string | Machine-readable identifier (lowercase, no spaces) |
| label | ✗ | string | Display name; defaults to capitalized tool |
| binary | ✗ | object | Detection method; omit to never detect |
| home | ✓ | string | Tool's config directory; supports ~ |
| enabled | ✗ | boolean | Default: true. Set false to skip syncing |
| mode | ✗ | string | Selection mode (see below) |
| mappings | ✓ | array | List of symlink definitions |
Selection Mode
Control how users can select items from this rule:
-
multi-select(default) — User can select any combination of profiles. UI shows checkboxes[x]/[ ]. Useful for skills, agents, commands where you might want multiple at once. -
single-select— User can select only one profile from this rule at a time. UI shows radio buttons(•)/( ). Useful when alternatives are mutually exclusive (e.g., multiple config files targeting the same destination).
Example: oh-my-openagent.yaml has 3 file mappings all targeting oh-my-openagent.json. Setting mode: single-select ensures only one alternative config gets installed:
tool: oh-my-openagent
label: OpenCode Config
home: ~/.config/opencode
enabled: true
mode: single-select # Only allow ONE of the three files
mappings:
- type: file
source: oh-my-openagent/config.openai.json
target: oh-my-openagent.json
- type: file
source: oh-my-ope
