AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
Multi-repository orchestration CLI for unified PR workflows
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Multi-repo workflow tool for synchronized branches, linked PRs, and atomic merges.
gr1 has reached 1.0 and is now in maintenance mode. gr2 is the active development target, bringing declarative workspace specs, lane-aware execution, and a migration path from gr1. See the migration playbook for details. gr1 will receive critical bug fixes only.
The Rust gr2 prototype is frozen as reference material; active gr2 work is Python-first and governed by the core-engine seam.README 전문 보기 ↗gr1 has reached 1.0 and is now in maintenance mode. gr2 is the active development target, bringing declarative workspace specs, lane-aware execution, and a migration path from gr1. See the migration playbook for details. gr1 will receive critical bug fixes only.
The Rust gr2 prototype is frozen as reference material; active gr2 work is Python-first and governed by the core-engine seam.
Manage multiple related repositories as a single workspace with synchronized branches, linked pull requests, and atomic merges.
Inspired by Android's repo tool, gitgrip brings manifest-based multi-repo management to any project.
| Term | Definition |
|---|---|
| Gripspace | The .gitgrip/ directory — workspace-level config, state, and manifest. One per workspace, shared across all griptrees. |
| Griptree | A worktree-based checkout managed by gitgrip. Each agent or feature branch gets its own griptree with isolated code but shared gripspace config. |
| Manifest | The config file (gripspace.yml) inside .gitgrip/ that defines repos, scripts, hooks, and workspace settings. |
| Repo | A git repository within the workspace. Multiple repos coexist under one gripspace. |
gr2 is the workspace layer for multi-repo work: a workspace over your repos,
isolated lanes to work in, and one grouped review per slice. Install the alpha
from PyPI (the package is gitgrip; the command is gr2):
uv tool install --pre gitgrip # or: pip install --pre gitgrip
Start with gr2/README.md for the five-minute walk. Everything
below installs the Rust gr1 gr.
brew tap synapt-dev/tap
brew install synapt-dev/tap/gitgrip
If you installed from the earlier tap, run brew untap laynepenney/tap as
well. That tap is archived, and leaving both tapped makes the bare formula
name ambiguous.
cargo install gitgrip
Pre-built binaries for Linux, macOS (Intel & Apple Silicon), and Windows are available on the releases page.
git clone https://github.com/synapt-dev/grip.git
cd grip
cargo build --release
# Binary is at target/release/gr (or gr.exe on Windows)
# Install to ~/.cargo/bin:
cargo install --path .
Create a new repo to hold your workspace config (e.g., my-workspace), then add a gripspace.yml:
version: 1
manifest:
url: [email protected]:your-org/my-workspace.git
repos:
frontend:
url: [email protected]:your-org/frontend.git
path: ./frontend
default_branch: main
backend:
url: [email protected]:your-org/backend.git
path: ./backend
default_branch: main
shared:
url: [email protected]:your-org/shared-libs.git
path: ./shared
default_branch: main
settings:
pr_prefix: "[cross-repo]"
merge_strategy: all-or-nothing
From a manifest URL:
gr init [email protected]:your-org/my-workspace.git
From existing local directories:
# Auto-scan current directory for git repos
gr init --from-dirs
# Scan specific directories
gr init --from-dirs --dirs ./frontend ./backend
# Interactive mode - preview and edit manifest before saving
gr init --from-dirs --interactive
This creates the gripspace at .gitgrip/ with the manifest at .gitgrip/spaces/main/gripspace.yml (with legacy .gitgrip/manifests/manifest.yaml compatibility).
# Check status of all repos
gr status
# Create a feature branch across all repos
gr branch feature/new-feature
# Make changes, commit in each repo, then create linked PRs
gr pr create --title "Add new feature"
# Sync all repos with latest from remote
gr sync
Work through the layered gripspaces codelab with its runnable fixture. The six chapters start from a clean workspace, then build through materialization, composition, overrides, and extension.
| Command | Description |
|---|---|
gr init <url> | Initialize workspace from manifest repo |
gr init --from-dirs | Initialize workspace from existing local directories |
gr sync | Pull latest from all repos (parallel by default) |
gr sync --sequential | Pull repos one at a time |
gr status | Show status of all repos |
gr branch [name] | Create or list branches |
gr checkout <branch> | Checkout branch across repos |
gr checkout -b <branch> | Create and checkout branch in one command |
gr checkout add <name> | Create an independent child checkout from cached repos |
gr add [files] | Stage changes across repos |
gr diff | Show diff across repos |
gr commit -m "msg" | Commit across repos |
gr push | Push across repos |
gr pr create | Create linked PRs |
gr pr status | Show PR status |
gr pr merge | Merge all linked PRs |
gr pr checks | Show CI check status |
gr pr diff | Show PR diff |
gr repo add <url> | Add a new repository to workspace |
gr repo list | List all repositories |
gr repo remove <name> | Remove a repository |
gr group list | List all groups and repos |
gr group add <group> <repos> | Add repos to a group |
gr group remove <group> <repos> | Remove repos from a group |
gr manifest schema | Show manifest schema specification |
gr init <manifest-url>Initialize a new workspace by cloning the manifest repository and all defined repos.
gr init --from-dirsInitialize a workspace from existing local git repositories. Discovers repos, extracts remote URLs and default branches, and generates a manifest.
| Option | Description |
|---|---|
--from-dirs | Create workspace from existing directories |
--dirs <paths> | Specific directories to scan (default: all subdirs) |
-i, --interactive | Preview manifest and confirm before writing |
Features:
gr sync [options]Pull latest changes from the manifest and all repositories. Syncs in parallel by default for faster performance.
| Option | Description |
|---|---|
--sequential | Sync repos one at a time (slower but ordered output) |
--group <name> | Only sync repos in this group |
-f, --force | Force sync even with local changes |
--reset-refs | Hard-reset reference repos to configured upstream branches |
gr statusShow status of all repositories including branch, changes, and sync state.
gr cache <subcommand>Manage the machine-level bare-repo cache used by workspace repos.
By default caches live under ~/.grip/cache/, keyed by canonical repo identity.
You can override the cache root with GRIP_CACHE_DIR when you need a custom or
isolated cache location.
| Subcommand | Description |
|---|---|
gr cache status | Show whether each workspace repo has a cache and where it lives |
gr cache bootstrap | Create missing caches without touching existing ones |
gr cache update | Fetch updates into existing caches |
gr cache remove <repo> | Remove one repo cache explicitly |
Examples:
# See where caches are currently resolved
gr cache status
# Create missing caches before materializing child checkouts
gr cache bootstrap
# Use a custom cache root for an isolated environment
GRIP_CACHE_DIR=/tmp/grip-cache gr cache status
gr checkout <branch>Checkout a branch across all repos. Can also create branches with the -b flag.
| Option | Description |
|---|---|
-b | Create branch if it doesn't exist |
--base | Checkout the griptree base branch (griptree workspaces only) |
gr checkout add <name>Create an independent child checkout under .grip/checkouts/<name>/ using the
workspace cache as an accelerator.
Unlike gr tree add, this creates normal child clones with their own .git
directories. The checkout keeps the canonical remote URL as origin; the cache
is only used to speed up materialization.
| Option | Description |
|---|---|
--repo <name> | Only materialize specific repos |
--group <name> | Only materialize repos in a group |
Examples:
# Materialize all repos into an independent child checkout
gr checkout add sandbox
# Materialize only the docs group
gr checkout add docs-only --group docs
# Materialize just one repo
gr checkout add app-only --repo app
gr checkout listShow the currently materialized child checkouts under
.grip/checkouts/.
Examples:
# List all materialized child checkouts
gr checkout list
gr checkout remove <name>Remove a materialized child checkout under .grip/checkouts/<name>/.
This deletes the child clone only. It does not delete the shared cache under
~/.grip/cache/.
Examples:
# Remove a disposable child checkout
gr checkout remove sandbox
gr branch [name]Create a new branch across all repositories, or list existing branches. Manifest repo is always included.
| Option | Description |
|---|---|
-r, --repo <repos...> | Only operate on specific repos |
-d, --delete | Delete the branch |
-m, --move | Move commits to new branch |
gr pr createCreate linked PRs across repos with changes.
Run from inside a repo, it opens PRs for the repos on that repo's branch and
lists any other repo with commits ahead on a different branch. Run from the
workspace root with repos on different branches, it refuses and names each
group. --repo includes repos regardless of branch (--repo manifest selects
the manifest).
| Option | Description |
|---|---|
-t, --title <title> | PR title |
-b, --body <body> | PR body |
-d, --draft | Create as draft |
--push | Push branches first |
--repo <repos> | Only these repos, comma-separated, whatever branch they are on (manifest names the manifest) |
--base <branch> | Base branch for the PR (overrides the grip target) |
gr pr mergeMerge all linked PRs atomically.
| Option | Description |
|---|---|
-m, --method <method> | merge, squash, or rebase. Defaults to settings.merge_method, or a merge commit |
--skip-gate <gate> | Waive ONE named gate and no others: approval, checks, mergeable. Repeatable |
-f, --force | Waive every gate. Prefer --skip-gate |
-u, --update | Update branch from base if behind, then retry merge |
--auto | Enable auto-merge (merges when all checks pass) |
Three gates run before a merge: approval (a formal platform approval exists),
checks (status checks are passing), and mergeable (the platform reports the
PR as mergeable). Waiving one names it; --force waives all three.
Prefer --skip-gate whenever a single gate does not apply to your workflow. A
workspace that ratifies by review comments rather than formal approvals, for
example, can never pass the approval gate — reaching for --force there
suppresses the check and mergeability gates too, every time, invisibly.
Whatever is waived is printed at the moment of the merge, alongside the resolved target:
MERGING acme/widgets#412 fix/parser -> main method=Merge WAIVED=approval
suppressed: widgets PR #412: no formal approval [approval]
gr pr merge takes no PR number — it merges whatever PR the current branch
owns — so that line is what tells you the command resolved to the PR you meant.
Merge method. With no --method, the method comes from settings.merge_method
in the manifest, defaulting to merge — a real merge commit with two parents.
The host is never asked to choose a method, only whether the chosen one is
permitted; if it is not, the merge is refused rather than silently performed with
a different strategy.
After a merge, the resulting commit is checked in the local repository and a
warning is printed if it does not have two parents. A hosting platform reports
that a merge happened, not which strategy produced the commit.
gr repo add <url>Add a new repository to the workspace. Parses the URL, updates the manifest, and optionally clones the repo.
| Option | Description |
|---|---|
--path <path> | Local path (default: ./<repo-name>) |
--name <name> | Name in manifest (default: from URL) |
--branch <branch> | Default branch (default: main) |
--no-clone | Only update manifest, skip cloning |
If the workspace is on a feature branch, the new repo will be checked out to that branch automatically.
gr forall -c "<command>"Run a command in each repository (like AOSP's repo forall).
| Option | Description |
|---|---|
-c, --command | Command to run (required) |
-r, --repo <repos...> | Only run in specific repos |
--include-manifest | Include manifest repo |
--continue-on-error | Continue if command fails |
Environment variables available in command:
REPO_NAME - Repository nameREPO_PATH - Absolute path to repoREPO_URL - Repository URLThe manifest file (gripspace.yml) inside your gripspace (.gitgrip/) defines the workspace:
version: 1
# Inherit from shared gripspace repositories (optional)
gripspaces:
- url: [email protected]:your-org/base-workspace.git
rev: main # Pin to branch/tag/commit (default: remote HEAD)
manifest:
url: [email protected]:your-org/workspace.git
# Generate files from gripspace + local parts
composefile:
- dest: CLAUDE.md
parts:
- gripspace: base-workspace
src: CODI.md
- src: LOCAL_DOCS.md
repos:
repo-name:
url: [email protected]:your-org/repo.git
path: ./local-path
default_branch: main
settings:
pr_prefix: "[cross-repo]"
merge_strategy: all-or-nothing
Compose workspaces from shared base configurations using gripspaces:. External gripspace repos are cloned into .gitgrip/spaces/ and their manifests are merged into the local gripspace.
What gets merged: repos, scripts, env, hooks, linkfiles, and copyfiles. Local values always win on conflict. Resolution is recursive (max depth 5) with cycle detection.
gripspaces:
- url: [email protected]:org/platform-base.git # Shared infra repos + hooks
- url: [email protected]:org/frontend-tools.git # Frontend tooling scripts
rev: v2.0.0 # Pin to a specific version
gitgrip supports multiple hosting platforms. The platform is auto-detected from the repository URL.
| Platform | URL Patterns |
|---|---|
| GitHub | [email protected]:org/repo.git, https://github.com/org/repo.git |
| GitLab | [email protected]:group/repo.git, https://gitlab.com/group/repo.git |
| Azure DevOps | [email protected]:v3/org/project/repo, https://dev.azure.com/org/project/_git/repo |
| Bitbucket | [email protected]:org/repo.git, https://bitbucket.org/org/repo.git |
Each platform requires its own authentication:
GitHub:
export GITHUB_TOKEN=your-token
# or
gh auth login
GitLab:
export GITLAB_TOKEN=your-token
# or
glab auth login
Azure DevOps:
export AZURE_DEVOPS_TOKEN=your-pat
# or
az login
Bitbucket:
export BITBUCKET_TOKEN=your-app-password
A single manifest can contain repos from different platforms:
repos:
frontend:
url: [email protected]:org/frontend.git
path: ./frontend
backend:
url: [email protected]:org/backend.git
path: ./backend
infra:
url: https://dev.azure.com/org/project/_git/infra
path: ./infra
For GitHub Enterprise, GitLab self-hosted, or Azure DevOps Server, add a platform config:
repos:
internal:
url: [email protected]:team/repo.git
path: ./internal
platform:
type: gitlab
baseUrl: https://gitlab.company.com
Work on multiple branches simultaneously without switching. Each griptree is an isolated worktree-based checkout that shares the same gripspace config (.gitgrip/) but has its own code directories.
# Create a griptree for a feature branch
gr tree add feat/new-feature
# Creates a sibling directory with all repos on that branch:
# ../feat-new-feature/
# ├── frontend/
# ├── backend/
# └── shared/
# Work in the griptree
cd ../feat-new-feature
gr status
# List all griptrees
gr tree list
# Lock to prevent accidental removal
gr tree lock feat/new-feature
# Remove when done (branches are preserved)
gr tree remove feat/new-feature
Upstream Tracking:
Each griptree records per-repo upstream defaults so repos can track different branches:
# tree add sets branch tracking to each repo's configured upstream
gr tree add feat/new-feature
# Sync uses per-repo upstream when on the griptree base branch
# and repairs missing upstream tracking automatically
gr sync
# Rebase onto each repo's configured upstream
gr rebase --upstream
# Return to the griptree base branch
gr checkout --base
# Optional all-in-one post-merge return flow
gr tree return --autostash --prune-current --prune-remote
Benefits:
Use gr as the primary command:
gr status
gr sync
gr branch feature/foo
The long form gitgrip also works.
Generate shell completions for tab completion:
# Bash
gr completions bash > ~/.local/share/bash-completion/completions/gr
# Or add to ~/.bashrc:
eval "$(gr completions bash)"
# Zsh
gr completions zsh > ~/.zfunc/_gr
# Or add to ~/.zshrc:
eval "$(gr completions zsh)"
# Fish
gr completions fish > ~/.config/fish/completions/gr.fish
# PowerShell
gr completions powershell >> $PROFILE
Supported shells: bash, zsh, fish, elvish, powershell
gh CLIglab CLIaz CLIAdditional documentation is available in the docs/ folder:
View the manifest schema from the CLI:
gr manifest schema # YAML format
gr manifest schema --format json # JSON format
gr manifest schema --format markdown # Markdown table
gitgrip includes a skill file for AI coding assistants (Claude Code, Codex, etc.).
Copy the skill file to your workspace:
mkdir -p .claude/skills/gitgrip
cp docs/SKILL.md .claude/skills/gitgrip/SKILL.md
Or copy from an existing gitgrip workspace.
The skill file teaches AI assistants to:
gr commands instead of raw git commandsgitgrip can run as a stdio MCP server that exposes agent operations as tools:
gitgrip_agent_contextgitgrip_agent_buildgitgrip_agent_testgitgrip_agent_verifygitgrip_agent_generate_contextAdd this to your MCP client config (for example .mcp.json):
{
"mcpServers": {
"gitgrip": {
"type": "stdio",
"command": "gitgrip",
"args": ["mcp", "server"]
}
}
}
This project was originally written in TypeScript and published to npm as gitgrip. It was rewritten in Rust for better performance and additional features.
MIT
gr forall -c "cmd" | Run command in each repo |
gr tree add <branch> | Create a worktree-based workspace |
gr tree list | List all griptrees |
gr tree remove <branch> | Remove a griptree |
gr tree return | Return to griptree base branch, sync, and optionally prune feature branch |
gr pull | Pull latest changes across repos |
gr rebase | Rebase across repos |
gr rebase --upstream | Rebase onto per-repo upstream (griptree-aware) |
gr grep <pattern> | Search across all repos |
gr prune | Clean up merged branches (dry-run) |
gr prune --execute | Delete merged branches |
gr gc | Run garbage collection across repos |
gr cherry-pick <sha> | Cherry-pick commits across repos |
gr ci run/list/status | CI/CD pipeline operations |
gr link | Manage file links |
gr run <script> | Run workspace scripts |
gr env | Show environment variables |
gr cache status | Show machine-level cache state for workspace repos |
gr cache bootstrap | Materialize missing machine-level repo caches |
gr cache update | Fetch updates into existing machine-level repo caches |
gr bench | Run performance benchmarks |
gr completions <shell> | Generate shell completions |