Governed Agent Access Layer — a single CLI to keep your local repositories, AI agent skills, and MCP server configurations in sync.
📚 Full docs: docs.getgaal.com
██████╗ █████╗ █████╗ ██╗
██╔════╝ ██╔══██╗██╔══██╗██║
██║ ███╗███████║███████║██║
██║ ██║██╔══██║██╔══██║██║
╚██████╔╝██║ ██║██║ ██║███████╗
╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝
Repository · Skills · MCP
If you use more than one AI coding agent (Claude Code, Cursor, Codex, GitHub Copilot, …) across more than one machine, gaal keeps your skills, MCP servers, and repositories in one YAML and reconciles every agent on every machine to match.
| Resource | Description |
|---|---|
| Repositories | Clone or update multi-protocol repos (git, hg, svn, bzr, tar, zip) from a single YAML file |
| Skills | Download and install SKILL.md collections into your local AI agent directories (Claude, Copilot, Cursor, …) |
| MCPs | Upsert MCP server entries into agent JSON config files without overwriting your existing configuration |
Plus a lightweight tools check: gaal doctor and gaal sync verify that required CLI binaries (e.g. gh, fnm) are on PATH and surface install hints when they are missing.
One file. Three resources. Every agent.
schema: 1
repositories:
- source: github.com/getgaal/gaal
path: ~/code/gaal
skills:
- source: github.com/obra/superpowers
agents: ["*"]
global: true
mcps:
- inline:
mcpServers:
context7:
command: npx
args: ["-y", "@upstash/context7-mcp"]
agents: ["claude-code", "cursor", "codex"]Run gaal sync. gaal figures out which agents are installed and writes to the right place for each.
curl -fsSL https://raw.githubusercontent.com/getgaal/gaal/main/scripts/install.sh | shInstalls the latest release binary to ~/.local/bin/gaal. Pin a specific
version with VERSION=v0.1.2, or pick a different directory with
INSTALL_DIR=/usr/local/bin.
Pass GAAL_INSTALL_DEBUG=1 for verbose output, or run
curl -fsSL https://raw.githubusercontent.com/getgaal/gaal/main/scripts/install.sh | sh -s -- --help
to see all options.
go install github.com/getgaal/gaal@latestPrerequisites: Go 1.26+
git clone https://github.com/getgaal/gaal.git
cd gaal
make buildThe binary is written to dist/gaal. Copy it to your $PATH:
sudo cp dist/gaal /usr/local/bin/gaal
# or, user-local:
cp dist/gaal ~/.local/bin/gaalThe fastest way to get a working gaal.yaml is to run the interactive init
wizard. It scans your machine for installed skills and MCP servers, asks you
a few questions, and writes a configuration you can sync right away.
gaal initThe wizard asks two questions before doing anything:
- How to create the file — start from an empty documented skeleton, or import the skills and MCP servers detected on this machine.
- Where the configuration applies — project-scoped (
./gaal.yaml) or global-scoped (~/.config/gaal/config.yaml).
When you pick the import mode, gaal runs an audit under the selected scope and presents a multi-select list grouped by agent. Everything is preselected by default; press Enter to confirm, or Space to toggle individual entries.
The wizard prompts are bypassable via flags:
# Empty skeleton, project-scoped
gaal init --empty --scope project
# Import everything detected, global-scoped, overwrite existing file
gaal init --import-all --scope global --force--empty and --import-all are mutually exclusive; one of them is required
when stdin is not a TTY.
If you would rather hand-write your configuration, copy example.gaal.yaml
and edit it. See Configuration reference for the
full data model, including the tools: block (bare strings or {name, hint}
objects) that documents required CLI binaries.
Then run:
gaal syncThree of us built gaal: @Theosakamg, @gmoigneu, and @gregqualls. We all do a lot of agentic coding across several machines and several agents (Claude Code, Cursor, Codex, Copilot, plus whatever launched this week), and we all kept hitting the same wall.
Install an MCP server in one agent, you install it again in the next. Update a skill, you update it everywhere or it rots. Try a new agent and the whole setup has to be rebuilt from scratch. Each agent reads config from a different file in a different format, so even copying between them is manual. The setups drift the moment you stop babysitting them.
This is not a personal frustration. Search "MCP configuration drift" or "syncing skills across agents" and you'll find the same complaint from a long line of developers running more than one tool. We were tired of solving it with shell scripts and chezmoi templates and wanted one source of truth that knew about every agent on every machine.
gaal auto-detects 17 coding agents. Use agents: ["*"] and a skill or MCP lands in every detected agent. Extend the registry yourself for anything missing, see Configuration reference.
| Claude Code | Cursor | Codex |
| GitHub Copilot | Amp | Cline |
| Roo | Continue | Gemini CLI |
| Goose | Kilo | Kiro CLI |
| OpenCode | OpenHands | Trae |
| Warp | Windsurf |
gaal syncClones or updates all repositories, installs skills, and upserts MCP entries.
gaal sync --dry-runRuns the full sync planning pipeline but performs no writes to disk. Prints what sync would do — which repos would be cloned or updated, which skills would be installed, and which MCP entries would be created.
Supports --output text|table|json and --sandbox. Incompatible with --service.
Exit codes: 0 = nothing to change, 1 = changes pending, 2 = error.
gaal sync --pruneAfter syncing, removes skills and MCP entries that are no longer declared in the
configuration file. Incompatible with --service.
gaal sync --forceInstalls skills into every registered agent even when the agent's configuration
directory does not exist yet. Useful when bootstrapping a machine where some
agents are not installed yet. Only applies to agents: ["*"] wildcard entries.
gaal sync --service --interval 10mRuns a sync loop every 10 minutes. Handles SIGTERM / Ctrl-C cleanly.
gaal statusPrints the current state of every repository, skill, and MCP entry.
gaal info <repo|skill|mcp|agent> [name]Shows a full information card for every entry of the given package type, combining the configuration spec with the current runtime state.
gaal info skill # all skill entries
gaal info skill vercel-labs/agent-skills # filter by source (substring, case-insensitive)
gaal info repo workspace/myrepo
gaal info mcp claude
gaal info agent # list all registered agents
gaal info agent cursorgaal agents # all registered agents (installed first)
gaal agents --installed # only agents detected on this machine
gaal agents cursor # detailed view for one agent
gaal agents -o json # machine-readable outputLists every registered coding agent and whether it is installed on this machine. Pass a name for a detailed view with search paths, skill counts, and MCP config.
gaal doctorRuns sanity checks on your configuration: validates gaal.yaml, checks that skill sources are reachable, verifies MCP target files, and reports agent and telemetry status.
gaal doctor --offline # skip network checks
gaal doctor --no-upsell # suppress the Community Edition message
gaal doctor -o json # machine-readable JSON outputExit codes: 0 = all checks passed, 1 = warnings, 2 = errors.
gaal auditScans all known agent directories and reports every skill and MCP server found on
the machine, regardless of whether it is declared in gaal.yaml. Useful for
spotting skills installed manually or by another tool.
gaal schemaPrints the JSON Schema (draft-07) that describes the full structure of a gaal.yaml
configuration file. Useful for IDE validation, documentation, and LLM JSON mode.
gaal schema -f schema.json # write to a fileVS Code: the workspace settings.json already maps schema.json to every
*.gaal.yaml file — run gaal schema -f schema.json once and YAML
auto-completion / inline validation activate automatically.
GoLand / IntelliJ: go to Languages & Frameworks → Schemas and DTDs →
JSON Schema Mappings, add schema.json and associate it with your gaal.yaml files.
Both status and info support the -o / --output flag:
gaal status -o json # machine-readable JSON
gaal info repo -o json| Format | Description |
|---|---|
text |
Human-friendly plain-text output (default) |
table |
Coloured pterm tables |
json |
Structured JSON, suitable for scripting / CI |
When --output json is set the ASCII banner is automatically suppressed.
gaal --sandbox /tmp/my-sandbox syncRedirects all writes to the sandbox directory. Nothing outside it is touched.
gaal --config /path/to/custom.yaml syncgaal --no-banner syncgaal --verbose syncgaal --log-file /var/log/gaal.json syncgaal generates completion scripts for bash, zsh, fish, and PowerShell.
Bash — current session
source <(gaal completion bash)Bash — permanent (add to ~/.bashrc)
gaal completion bash > ~/.local/share/bash-completion/completions/gaalZsh — current session
source <(gaal completion zsh)Zsh — permanent
gaal completion zsh > "${fpath[1]}/_gaal"Fish
gaal completion fish | source
# or permanently:
gaal completion fish > ~/.config/fish/completions/gaal.fishPowerShell
gaal completion powershell | Out-String | Invoke-ExpressionSee docs/config.md for the full technical reference:
data model, file locations by OS, merge rules, scope restriction policy
(including why workspace cannot override telemetry), schema generation,
validation, and agent contribution rules.
Quick overview — the three config levels (lowest → highest priority):
| Priority | File |
|---|---|
| 1 — lowest | /etc/gaal/config.yaml (global) |
| 2 | $XDG_CONFIG_HOME/gaal/config.yaml (user; defaults to ~/.config/gaal/config.yaml on Linux / macOS) |
| 3 — highest | gaal.yaml in CWD, or --config path |
See example.gaal.yaml for a fully annotated
configuration file.
gaal ships with a built-in registry of supported coding agents. You can extend it with your own agent definitions by creating a file at:
| OS | Path |
|---|---|
| Linux | $XDG_CONFIG_HOME/gaal/agents.yaml (defaults to ~/.config/gaal/agents.yaml) |
| macOS | $XDG_CONFIG_HOME/gaal/agents.yaml (defaults to ~/.config/gaal/agents.yaml) |
| Windows | %AppData%\gaal\agents.yaml |
Custom entries are merged with the built-in list. User-defined entries can override built-in entries. Each entry follows the same format as the built-in registry:
agents:
my-agent:
project_skills_dir: .my-agent/skills # relative path, no ".."
global_skills_dir: ~/.my-agent/skills # must start with ~/
mcp_config_file: ~/.my-agent/mcp.json # empty string if unsupportedUse gaal agents to list all registered agents (built-in + custom) and verify your additions. gaal info agent provides the same information in an alternative layout.
When your team outgrows single-user gaal (shared configs, drift detection, approval workflows), gaal Community Edition picks up where the standalone CLI leaves off.
The migration command validates your current configuration and confirms it is ready to push to a Community instance:
gaal migrate --to community https://community.example.com
gaal migrate --to community https://community.example.com --dry-runCommunity Edition is not yet publicly available. Running gaal migrate today
validates your YAML and prints what would be migrated. Subscribe at
https://getgaal.com to be notified when Community ships.
make build # compile to dist/gaal
make test # run the full unit-test suite
make coverage # unit tests + coverage reports in report/
make lint # gofmt + go vet
make sandbox # one-shot sync in an isolated /tmp directorySee docs/testing.md for the e2e test suite, and
docs/architecture.md for a full description of the internals.
This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).
Copyright (C) 2026 @Theosakamg / @gmoigneu / @gregqualls .
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. See the LICENSE file for the full text.
gaal collects no data by default. You can opt in to anonymous usage telemetry on first run. See the Privacy Policy for full details on what is and isn't collected.