Meta makes multi-repo architectures feel like monorepos — without the downsides of monorepos. Keep your repositories independent (their own git history, CI, ownership boundaries), but operate on them as a cohesive unit.
Most multi-repo tools solve the cloning problem. Meta solves the working problem. A .meta file declares your repos. Everything else flows from that: clone them all at once, run any command across them, query their state, snapshot and rollback, understand their dependency graph — and let AI agents do it autonomously.
- Why Meta
- Quick Start
- How It Works
- Installation
- Configuration
- Commands
- Filtering
- Snapshots
- Plugins
- AI Integration
- Architecture
- CLI Reference
- Documentation
- Roadmap
- Contributing
- License
| Problem | How Meta Solves It |
|---|---|
Git submodules are painful — detached HEADs, nested .git state, no batch operations |
Meta treats repos as peers, not hierarchy. Parallel execution built-in. |
| Lerna/Nx/Turborepo assume JavaScript | Meta is language-agnostic. Run cargo test, npm install, or make build — it doesn't care. |
Google's repo tool is rigid |
Meta has an extensible plugin system in any language. |
| AI agents struggle with multi-repo codebases | Meta is AI-native: MCP server, Claude Code skills, JSON output, query DSL — all designed for agents from day one. |
-
Clone a meta repository:
meta git clone https://github.com/org/meta-repo.git
This clones the meta repo and all child repositories defined in its
.metafile. -
Run commands across all repos:
meta git status meta git pull meta exec npm install meta exec cargo test
-
Filter by tags:
meta git pull --tag backend meta exec npm test --tag frontend,shared
-
Query repo state:
meta query "dirty:true AND tag:backend" -
Snapshot before risky changes:
meta git snapshot create before-refactor # ... make changes ... meta git snapshot restore before-refactor # rollback if needed
Meta is a command router on top of a loop engine, built in three layers:
1. Loop Engine — The foundation. Takes a list of directories and a command, runs it in each one (sequential or parallel), aggregates output. Simple, fast, reliable.
2. Meta CLI — The brain. Reads your .meta config, applies filters (tags, include/exclude), discovers plugins, and routes commands. When no plugin claims a command, it falls through to the loop engine via meta exec.
3. Plugins — The specialists. They don't execute — they plan. A plugin receives a request and returns an execution plan (a list of directory/command pairs). The loop engine does the actual work. This means plugins are pure functions, and execution is always consistent.
User runs: meta git status --tag backend
│
▼
Meta CLI: parse args → load .meta → filter by tags → find plugin
│
▼
Plugin (meta-git): "here's the plan" → [{dir: "./api", cmd: "git status"}, ...]
│
▼
Loop Engine: execute plan → aggregate output → report results
Plugins communicate via JSON over stdin/stdout — language-agnostic, process-isolated, easy to debug. You could write a plugin in Python, Go, Rust, or anything else.
macOS/Linux:
curl -fsSL https://raw.githubusercontent.com/gitkb/meta/main/install.sh | bashWindows (PowerShell):
irm https://raw.githubusercontent.com/gitkb/meta/main/install.ps1 | iexbrew install gitkb/tap/meta-clicargo binstall meta-clicargo install --git https://github.com/gitkb/metaMeta projects are configured via a .meta file (JSON) or .meta.yaml/.meta.yml (YAML) in the repository root.
Map project names to repository URLs:
{
"projects": {
"api-service": "git@github.com:org/api-service.git",
"web-app": "git@github.com:org/web-app.git",
"shared-utils": "git@github.com:org/shared-utils.git"
}
}Add tags, custom paths, and dependency tracking:
projects:
api-service:
repo: git@github.com:org/api-service.git
tags: [backend, rust]
web-app:
repo: git@github.com:org/web-app.git
path: apps/web
tags: [frontend, typescript]
shared-utils:
repo: git@github.com:org/shared-utils.git
tags: [shared]Extended format fields:
| Field | Required | Description |
|---|---|---|
repo |
Yes | Git repository URL |
path |
No | Custom clone path (defaults to project name) |
tags |
No | Array of tags for filtering |
meta |
No | Set true if this project contains a nested .meta.yaml |
provides |
No | Array of capabilities this project provides |
depends_on |
No | Array of project names or provided capabilities this depends on |
File priority: .meta.yaml > .meta.yml > .meta
You can mix simple and extended formats in the same file.
Meta repos can contain other meta repos, enabling hierarchical organization of large codebases:
projects:
infrastructure:
repo: git@github.com:org/infrastructure.git
meta: true # This directory has its own .meta.yaml
apps:
repo: git@github.com:org/apps.git
meta: trueWhen meta: true is set, commands with --recursive will descend into the nested meta repo and process its children too:
# Clone everything, including nested meta repos
meta git clone https://github.com/org/top-level.git
# Update all repos recursively
meta git update --recursive
# List entire tree
meta project list --recursiveFor impact analysis and build ordering:
projects:
shared-utils:
repo: git@github.com:org/shared-utils.git
provides: [utils-api]
auth-service:
repo: git@github.com:org/auth-service.git
depends_on: [shared-utils]
api-service:
repo: git@github.com:org/api-service.git
depends_on: [auth-service, utils-api]This enables impact analysis ("what breaks if I change shared-utils?"), topological build ordering, and transitive dependency resolution.
| Command | Description |
|---|---|
meta exec <command> |
Run any command across all repositories |
meta git status |
Git status for all repos |
meta git pull |
Pull latest changes |
meta git push |
Push commits |
meta query "<expr>" |
Query repos by state |
| Command | Description |
|---|---|
meta git clone <url> |
Clone meta repo + all child repos |
meta git update |
Pull changes and clone missing repos |
meta git setup-ssh |
Configure SSH multiplexing |
meta git commit --edit |
Per-repo commit messages via editor |
meta git commit -m "msg" |
Same message across all repos |
meta git snapshot create <name> |
Capture workspace state |
meta git snapshot list |
List snapshots |
meta git snapshot restore <name> |
Restore workspace to snapshot |
| Command | Description |
|---|---|
meta plugin list |
List installed plugins |
meta plugin search <query> |
Search plugin registry |
meta plugin install <name> |
Install a plugin |
meta plugin uninstall <name> |
Remove a plugin |
meta git pull --tag backend
meta exec npm test --tag frontend,sharedmeta git status --include api-service,web-app
meta exec npm install --exclude legacy-appmeta git status --recursive
meta git pull --recursive --depth 2meta query "dirty:true"
meta query "dirty:true AND tag:backend AND branch:main"
meta query "ahead:true"Conditions: dirty, branch, tag, ahead, behind — combined with AND.
Capture the complete state of all repositories for safe batch operations:
meta git snapshot create before-refactor
meta git snapshot list
meta git snapshot restore before-refactor --dry-run
meta git snapshot restore before-refactorSnapshots record each repo's commit SHA, branch, and dirty status. Dirty repos are auto-stashed on restore.
Plugins are standalone executables that extend meta. They're discovered automatically from:
.meta-plugins/in the current or parent directories~/.meta-plugins/- System PATH (binaries named
meta-*)
| Plugin | Description |
|---|---|
git |
Clone, status, update, commit, snapshots, SSH multiplexing |
project |
Project health checks and sync |
rust |
Cargo build, test, and command passthrough |
Plugins communicate via JSON over stdin/stdout. Any language works:
# Meta asks: "What can you do?"
meta-myplugin --meta-plugin-info
# → {"name": "myplugin", "version": "1.0", "commands": ["myplugin run"]}
# Meta asks: "Execute this command"
echo '{"command":"myplugin run","args":[],"projects":[...]}' | meta-myplugin --meta-plugin-exec
# → {"plan": {"commands": [{"dir": "./repo1", "cmd": "..."}]}}See docs/plugin_development.md for the full guide.
Meta is designed for AI agents from day one. Three integration points:
{
"mcpServers": {
"meta": {
"command": "meta-mcp",
"args": []
}
}
}Tools include: project listing, git operations (status/pull/push/commit/diff/branch), build/test, code search, file tree discovery, query DSL, impact analysis, workspace snapshots, and batch execution.
See docs/mcp_server.md for full documentation.
meta init claudeInstalls purpose-built skills that teach Claude Code how to work with multi-repo codebases — using meta git instead of git, creating snapshots before risky changes, filtering by tags, and understanding plugin interception.
Every command supports --json for structured, machine-readable output:
meta git status --json
meta query "dirty:true" --jsonMeta is a Rust workspace of 10 crates:
| Crate | Purpose |
|---|---|
meta_cli |
Main CLI — config loading, plugin routing, filtering |
loop_lib |
Core execution engine — runs commands across directories |
loop_cli |
Standalone loop CLI (usable without meta) |
meta_core |
Shared infrastructure — ~/.meta/ directory, lockfile, atomic store |
meta_plugin_protocol |
Shared types for the plugin contract |
meta_git_cli |
Git plugin — clone, update, status, commit, snapshots |
meta_git_lib |
Shared git library utilities |
meta_project_cli |
Project management plugin |
meta_rust_cli |
Rust/Cargo plugin |
meta_mcp |
MCP server for AI agent integration |
Each plugin is both a workspace member and a child repo in the .meta manifest — meta manages itself with itself.
See docs/architecture_overview.md for the full design.
The loop engine is the foundation that runs commands across directories. It can be used standalone:
loop git status
loop npm install
loop cargo testConfigure with .looprc. See docs/loop.md for details.
Usage: meta [OPTIONS] [COMMAND]...
Arguments:
[COMMAND]... Command to run across repositories
Options:
-c, --config <FILE> Path to .meta config file
-t, --tag <TAGS> Filter by tag(s), comma-separated
-i, --include <DIRS> Include only these directories
-e, --exclude <DIRS> Exclude these directories
-r, --recursive Process nested meta repos
--depth <N> Max recursion depth
--json Output in JSON format
-v, --verbose Verbose output
-s, --silent Silent mode
-h, --help Print help
-V, --version Print version
- Architecture Overview — System design
- MCP Server Guide — AI agent integration
- Plugin Development — Writing plugins
- Claude Code Skills — AI workflow skills
- Advanced Usage — Power-user features
- Loop System — Loop engine details
- FAQ / Troubleshooting — Common issues
- Core CLI + plugin system
- Git plugin with parallel clone
- YAML configuration support
- Project tags and filtering
- JSON output mode
- Nested meta repos (
--recursive) - MCP server for AI agents (29 tools)
- Multi-commit support (
meta git commit --edit) - Plugin help system
- Query DSL for advanced filtering
- Workspace snapshots with rollback
- Dependency tracking and impact analysis
- Claude Code skills integration
- Windows support (PowerShell installer)
- Dependency graph visualization (CLI)
- GUI for visual management
See .context/VISION_PLAN.md for full details.
Contributions welcome! Please see CONTRIBUTING.md.
- Issues: GitHub Issues
- Discussions: GitHub Discussions
MIT License. See LICENSE.