Gaal
A single CLI to keep your local repositories, AI agent skills, and MCP server configurations in sync.
Ask AI about Gaal
Powered by Claude Β· Grounded in docs
I know everything about Gaal. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
gaal
Governed Agent Access Layer β a single CLI to keep your local repositories, AI agent skills, and MCP server configurations in sync.
βββββββ ββββββ ββββββ βββ
ββββββββ βββββββββββββββββββ
βββ βββββββββββββββββββββββ
βββ ββββββββββββββββββββββ
ββββββββββββ ββββββ βββββββββββ
βββββββ βββ ββββββ βββββββββββ
Repository Β· Skills Β· MCP
[!IMPORTANT]
π Full documentation lives at docs.getgaal.com
This README covers the essentials. For complete guides, configuration reference, agent integrations, and tutorials, head over to docs.getgaal.com.
What it does
| 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 |
| Tools | Check that required CLI binaries (e.g. gh, fnm) are on PATH and surface install hints when they are missing |
Quick start
The 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 init
The 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.
Non-interactive (CI / scripts)
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.
Manual setup
If you would rather hand-write your configuration, copy example.gaal.yaml
and edit it. A minimal file looks like this:
repositories:
src/myrepo:
type: git
url: https://github.com/example/myrepo.git
version: main
skills:
- source: vercel-labs/agent-skills
agents: ["*"]
mcps:
- name: filesystem
target: ~/.config/claude/claude_desktop_config.json
inline:
command: uvx
args: [mcp-server-filesystem, /home/user/projects]
tools:
- gh # bare string β required on PATH, no install hint
- name: rtk # full form with an install hint
hint: "cargo install rtk"
The tools: block can also appear inside an individual skills: entry to
document tools required by that specific skill. gaal doctor reports each
tool as β (on PATH) or β (missing); gaal sync prints a one-line
banner per missing tool but never blocks.
Then run:
gaal sync
Usage
One-shot sync
gaal sync
Clones or updates all repositories, installs skills, and upserts MCP entries.
Dry-run (preview changes)
gaal sync --dry-run
Runs 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.
Remove orphan resources
gaal sync --prune
After syncing, removes skills and MCP entries that are no longer declared in the
configuration file. Incompatible with --service.
Force-install into all agents
gaal sync --force
Installs 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.
Continuous service mode
gaal sync --service --interval 10m
Runs a sync loop every 10 minutes. Handles SIGTERM / Ctrl-C cleanly.
Status report
gaal status
Prints the current state of every repository, skill, and MCP entry.
Detailed info
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 cursor
List agents
gaal 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 output
Lists 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.
Health check
gaal doctor
Runs 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 output
Exit codes: 0 = all checks passed, 1 = warnings, 2 = errors.
Discover what is installed
gaal audit
Scans 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.
Generate the JSON Schema
gaal schema
Prints 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 file
VS 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.
Output format
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.
Sandbox mode (safe for CI / testing)
gaal --sandbox /tmp/my-sandbox sync
Redirects all writes to the sandbox directory. Nothing outside it is touched.
Custom config file
gaal --config /path/to/custom.yaml sync
Suppress the banner
gaal --no-banner sync
Verbose / debug output
gaal --verbose sync
Log to file (JSON)
gaal --log-file /var/log/gaal.json sync
Shell completion
gaal 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/gaal
Zsh β 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.fish
PowerShell
gaal completion powershell | Out-String | Invoke-Expression
Configuration reference
See 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.
Agent registry customization
gaal ships with a built-in registry of supported coding agents (claude-code, github-copilot, cursor, windsurf, β¦). 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 unsupported
Use 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.
Graduation path to gaal Community
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-run
Community 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.
Development
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 directory
End-to-end tests
The e2e suite runs gaal inside a hermetic Docker container so it can clone
real repos, write to agent skill dirs, and merge MCP configs without
touching your real $HOME.
make test-e2e # Layer 1: filesystem assertions only (fast, ~45s)
make test-e2e-cli # Layer 2: also installs claude-code + codex CLIs and
# verifies the configs gaal writes are accepted
# (~2 min; runs nightly in CI, not on every PR)
Requires Docker on the host. The Makefile builds gaal for linux/<host-arch>
(amd64 on x86_64, arm64 on Apple Silicon) and forwards --platform to
docker so the binary and image always match. Override with
make test-e2e GOARCH=amd64.
The fixture image (alpine + git + mercurial + python3 + node) is published
to ghcr on every Dockerfile change. Pull it once to skip the slow apk and
npm install on your first local run:
docker pull ghcr.io/getgaal/gaal-e2e:base-latest
docker tag ghcr.io/getgaal/gaal-e2e:base-latest gaal-e2e:base-latest
make test-e2e # reuses the cached base layers; only the binary COPY re-runs
CI uploads the JUnit report (report/e2e-tests.xml) plus
docker logs/docker inspect diagnostics on failure as workflow artifacts.
For interactive debugging β watching every docker exec invocation
(banner) and gaal's stdout/stderr stream live to the terminal:
GAAL_E2E_VERBOSE=1 go test -v -tags e2e -run TestVCS_GitBackend_CloneAndCheckout ./test/e2e/...
Off by default so the per-PR run stays clean; the captured ExecResult
fields are unchanged either way so existing assertions keep working.
See docs/architecture.md for a full description of the internals.
Install
Quick install (macOS / Linux)
curl -fsSL https://raw.githubusercontent.com/getgaal/gaal/main/scripts/install.sh | sh
Installs 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.
With Go
go install github.com/getgaal/gaal@latest
From source
Prerequisites: Go 1.26+
git clone https://github.com/getgaal/gaal.git
cd gaal
make build
The 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/gaal
Privacy
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.
License
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.
