Skip to main content
gaal is a small, opinionated state engine. Once you understand the four moving parts you understand the whole product.

The four moving parts

Every gaal command runs the same four-stage pipeline.
  1. 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.
  2. 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.
  3. Plan, diff desired vs actual. gaal compares the desired state from gaal.yaml against the actual state from the audit and computes the work to do. gaal sync --dry-run stops at this stage and prints the plan.
  4. 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 makes agents: ["*"] 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 in gaal.yaml falls into one of three buckets, and each bucket comes with a strict guarantee:
ResourceGuarantee
Repositoriesgaal owns the entire directory at the configured path. Sync clones or updates it; nothing else is written there.
Skillsgaal owns the named skill directories it installs. Skills it didn’t install are left alone unless you pass --prune.
MCP serversgaal upserts entries inside the target JSON file. Other keys in that file (your editor settings, other servers you added by hand) are never touched.
The MCP guarantee is the one that matters most: gaal will not clobber your 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:
PriorityFile
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
A workspace 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.yaml and 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.