The four moving parts
Every gaal command runs the same four-stage pipeline.- gaal.yaml, the source of truth. You write it (or generate it with
gaal init) and commit it to your dotfiles. Everything downstream reads from this file. - Audit, read the filesystem. gaal scans the local filesystem to discover what’s already there: every installed agent, every skill on disk, every MCP entry in every agent’s JSON config. Audit writes nothing.
- Plan, diff desired vs actual. gaal compares the desired state from
gaal.yamlagainst the actual state from the audit and computes the work to do.gaal sync --dry-runstops at this stage and prints the plan. - Sync, apply through renderers. The plan executes through per-agent renderers, small adapters that know each agent’s native file layout and config format. They write to
.claude/skills/*,.cursor/mcp.json,~/.codex/skills/*, and so on.
The agent registry
gaal ships with a built-in registry of every supported agent: where its skills live, where its MCP config file is, and how its package manager stores extensions. The registry is what makesagents: ["*"] work, when you say “install this skill in every detected agent,” gaal walks the registry, checks which agents are actually installed, and installs only into those.
You can extend the registry with your own entries. See Custom agents.
Three resource types, three guarantees
Every entry ingaal.yaml falls into one of three buckets, and each bucket comes with a strict guarantee:
| Resource | Guarantee |
|---|---|
| Repositories | gaal owns the entire directory at the configured path. Sync clones or updates it; nothing else is written there. |
| Skills | gaal owns the named skill directories it installs. Skills it didn’t install are left alone unless you pass --prune. |
| MCP servers | gaal upserts entries inside the target JSON file. Other keys in that file (your editor settings, other servers you added by hand) are never touched. |
claude_desktop_config.json. It reads, modifies the mcpServers object in place, and writes back.
Scopes
Every config file lives at one of three scopes, and they merge in a strict order:| Priority | File |
|---|---|
| 1 (lowest) | /etc/gaal/config.yaml (system-wide) |
| 2 | ~/.config/gaal/config.yaml (user) |
| 3 (highest) | gaal.yaml in the current directory, or whatever --config points at |
gaal.yaml overrides the user file overrides the system file. Some keys (like telemetry) are restricted to the user/system scope so a checked-in workspace file can’t change them. See Scopes for the full rules.
What gaal doesn’t do
- It doesn’t run your agents. gaal just makes sure each agent has the right files in the right place.
- It doesn’t proxy or intercept LLM calls. The runtime path is between your agent and its model provider.
- It doesn’t push state anywhere. gaal today is local-only, your
gaal.yamland the files it touches stay on your machine. (If you want shared state across a team, that’s what Community Edition will be for.)
Next
The gaal.yaml file
Top-level keys, in detail.
Agents & renderers
The registry, search paths, and how rendering is dispatched.
Scopes
Global, user, and workspace files, and how they merge.
Quickstart
Apply the model in a 5-minute walkthrough.