Corral
Automatically clone and organise GitHub repositories by visibility and language.
Contents
Getting started
- Install — Homebrew, Arch, source, or Docker
- Quick Start — clone and organise in one command
Features & Capabilities
Reference & Operational
Install
Homebrew (macOS / Linux)
brew install sebastienrousseau/tap/corralctl
Arch Linux (AUR)
yay -S corralctl-bin # or: paru -S corralctl-bin
Build from source
Requires Go 1.26+ and Git:
git clone https://github.com/sebastienrousseau/corral.git
cd corral
make build # compiles ./corralctl
macOS
brew install go git gh
Ubuntu / Debian / WSL2
sudo apt install golang git
Install gh separately following the GitHub CLI installation guide.
Fedora / RHEL
sudo dnf install golang git gh
Quick Start
Run Corral with an owner name (GitHub username or organization) to clone and automatically sort all repositories into a clean local directory hierarchy:
# Log in to GitHub CLI first (or set GITHUB_TOKEN)
gh auth login
# Run Corral for your profile
./corralctl my-username
This converges your local directory structure into a structured mirror:
~/Code/
├── Public/
│ ├── go/
│ │ └── corral/
│ ├── rust/
│ │ └── my-crate/
│ └── other/
│ └── dotfiles/
└── Private/
└── python/
└── internal-tool/
Features
| Feature |
Description |
| Structured Layout |
Automatically sorts repositories into Public/ and Private/ trees, sub-grouped by primary language (e.g. go, rust, python). |
| Smart Syncing |
Compares remote pushed_at metadata to skip redundant network calls, speeding up syncs by 10x-50x. |
| Interactive Selection |
A fully featured Terminal UI (TUI) selector dashboard to search, preview, and select repositories to clone. |
| Legacy Migration |
Automatically moves existing flat directory layouts into the new structure and cleans up empty folders. |
| Concurrency |
Processes clones and pulls concurrently with configurable worker limits (--concurrency). |
| Batch Commands |
Batch execute Git commands concurrently across all cloned repositories using exec. |
| Zero Configuration |
No configuration files required — simple, sensible defaults that work out of the box. |
Architecture
A single run resolves git, fetches every repository concurrently from GitHub, optionally lets you pick a subset interactively, then dispatches clone / smart-sync / skip decisions across a worker pool. Smart sync consults a per-repository .corral-state.json sidecar to skip a git pull when the upstream pushed_at is unchanged.
graph TD
A[User Shell] --> B{corralctl}
B --> C[Pre-flight: exec.LookPath git]
C -- Missing --> Z1[Exit: git not found on PATH]
C -- OK --> D[Resolve auto/token/gh auth]
D --> E[GitHub API: list repos]
E --> E1["First page<br/>+ resp.LastPage"]
E1 --> E2{LastPage > 1?}
E2 -- Yes --> E3["Concurrent fetch<br/>pages 2..N (max 5)"]
E2 -- No --> F
E3 --> F[Filtered repository set]
F --> F1{TUI selector?}
F1 -- "--select" --> F2[Interactive TUI<br/>/sort, /all, /none, search]
F1 -- No --> G
F2 --> G[Layout template render<br/>Visibility/Language/Name]
G --> H["Worker pool<br/>(--concurrency)"]
H --> I{Already cloned?}
I -- No --> J["git clone (+ blobless/<br/>depth/single-branch)"]
I -- "Yes (--no-sync)" --> K[SKIP]
I -- Yes --> L{Smart sync:<br/>pushed_at advanced?}
L -- No --> M[SKIP up-to-date]
L -- "Yes (or --force-sync)" --> N[git pull --rebase --autostash]
N --> N1["+ optional submodule update<br/>(--ignore-submodule-failures)"]
J & N1 --> O[Stamp .corral-state.json]
O & K & M --> P{All workers done?}
P -- No --> H
P -- Yes --> Q[Cleanup empty legacy dirs]
Q --> R{--orphans?}
R -- Yes --> S[Walk baseDir<br/>parse .git/config]
R -- No --> T[Print summary]
S --> T
Interactive TUI Mode
By passing the -i or --interactive flag, you can launch the selection dashboard:
./corralctl -i my-username
Keybindings
[space] — Toggle selection of the current repository.
[ctrl+a] — Select all currently filtered repositories.
[ctrl+n] — Deselect all currently filtered repositories.
[/] — Enter command / filter mode.
[enter] — Confirm selection and begin cloning/syncing.
[esc] — Exit the application silently.
In-Session Commands
Press / inside the TUI to enter Command Mode. Commands support prefix-based autocompletion (press [tab] or [right-arrow] to autocomplete):
/sort <field> — Sort repositories. Fields:
name — Alphabetical sort by repository name.
language / lang — Alphabetical sort by language.
visibility / vis — Alphabetical sort by visibility (Private/Public).
public — Prioritize public repositories at the top.
private — Prioritize private repositories at the top.
/all — Select all filtered repositories.
/none — Deselect all filtered repositories.
/exit / /quit — Cancel and exit silently.
/help — Display the in-session help panel overlay.
Layout Customization
By default, Corral uses the layout {{.Visibility}}/{{.Language}}/{{.Name}}. You can override this using the --layout flag:
./corralctl --layout "{{.Owner}}/{{.Name}}" my-org
Supported placeholders:
{{.Owner}} — GitHub owner name.
{{.Name}} — Repository name.
{{.Language}} — Primary language normalized to lowercase.
{{.Visibility}} — Repository visibility (Public or Private).
Smart Syncing
Corral stores synchronization metadata next to each repository's .git/ folder inside a .corral-state.json sidecar file:
- No Redundant Pulls: If the remote repository has not received new pushes since the last sync,
git pull is skipped completely.
- Overrides: To bypass smart checks and force Corral to perform a full
git pull, pass the --force-sync flag.
- Skip Syncing entirely: Pass
--no-sync to skip updates on all cloned repositories.
Exec Mode
Execute arbitrary shell commands concurrently across your organized repositories:
# Check git status for all Go/Rust private repositories
./corralctl exec "git status -s" --languages go,rust --visibility private
MCP Server (for AI agents)
Corral ships a Model Context Protocol server that exposes your local, Corral-organised workspace to AI coding agents — Claude Code, Cursor, Cline, Codex CLI, Aider, and anything else that speaks MCP. No network calls are made and the GitHub API is not contacted; the server is a read-only window into the clones already on disk.
Where GitHub's own MCP server covers the remote API surface (issues, PRs, search), corral-mcp covers the dimension only it can — your local mirror, organised by visibility and language, queryable without a round-trip.
| Name |
Purpose |
corral_list_repos |
Filter local clones by visibility / language / name / sync state |
corral_find_repo |
Resolve a fuzzy name to one clone (returns candidates on ambiguity) |
corral_get_repo_metadata |
Full metadata for one clone, including current branch |
corral_status_summary |
Workspace summary: counts by visibility and language |
corral_workspace_index |
Full structured index in a single call |
Resources
corral://workspace/index
corral://repo/{owner}/{name}/state
corral://repo/{owner}/{name}/tree
corral://repo/{owner}/{name}/file/{path} (bounded at 1 MiB; path-traversal protected)
Install
Claude Code:
claude mcp add corral -- corralctl mcp
Cursor / Cline (mcp.json):
{
"mcpServers": {
"corral": {
"command": "corralctl",
"args": ["mcp"]
}
}
}
Docker (no local install required) — the same binary the MCP Registry advertises, mounted against your workspace:
{
"mcpServers": {
"corral": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-v", "${HOME}/Code:/home/corral/Code:ro",
"ghcr.io/sebastienrousseau/corral:latest",
"mcp", "--root", "/home/corral/Code"
]
}
}
}
Sandbox a different root (defaults to --base-dir, then $HOME/Code):
corralctl mcp --root /custom/workspace
Safety
- Read-only by default. Phase-3 write tools (
corral_sync_repo, corral_clone_repo) are reserved for a follow-up release; --enable-mutations is a placeholder flag today.
- Path-traversal protected. File-resource lookups canonicalise both the configured root and the candidate path before comparison, so a malicious
{path} cannot escape the sandbox via .. or symlinks.
- stdio-only. No HTTP endpoint, no listening port — the server only ever speaks to the parent process that launched it.
Usage & Flags
Positional Arguments
corralctl <owner> [base_dir] [limit]
<owner> — GitHub username or organization (Required).
[base_dir] — Root directory to save repositories (Default: $HOME/Code).
[limit] — Maximum repositories to fetch (Default: 1000).
Command Options
| Option |
Short |
Default |
Description |
--base-dir |
— |
$HOME/Code |
Root directory for cloned repos |
--limit |
-l |
1000 |
Maximum repositories to fetch |
--concurrency |
-c |
1 |
Number of concurrent worker threads |
--dry-run |
-n |
off |
Preview actions without making changes |
--orphans |
-o |
off |
Detect local repositories no longer on GitHub |
--protocol |
-p |
https |
Protocol to clone: ssh or https |
--no-sync |
— |
off |
Skip pulling latest changes for existing clones |
--force-sync |
— |
off |
Force git pull regardless of cached state |
--layout |
— |
... |
Templated path layout for repositories |
--interactive |
-i |
off |
Launch the interactive selector TUI dashboard |
--recurse-submodules |
— |
off |
Initialise submodules on clone and sync |
--output |
— |
text |
Output format: text, json, or ndjson |
--auth |
— |
auto |
Auth mode: auto, token, or gh |
--visibility |
— |
all |
Filter by visibility: all, public, private |
--include-forks |
— |
off |
Include forked repositories |
--include-archived |
— |
off |
Include archived repositories |
--languages |
— |
— |
Comma-separated language filter (e.g. go,rust) |
--exclude-languages |
— |
— |
Comma-separated language exclude list |
--clone-depth |
— |
0 |
Shallow clone depth (0 disables shallow clone) |
Examples
To inspect the package layout and programmatically run Corral modules, see the self-contained, copy-pasteable Go code examples in the examples directory:
- Interactive Selector — Programmatically configure and launch the selection checklist TUI in AltScreen mode.
- GitHub Repository Fetcher — Query the GitHub REST API using
github.FetchReposWithOptions with stars sorting and language constraints.
- Git Syncing — Call the
git helper package to perform clones, query branches, and resolve origin URLs.
- Engine Orchestrator — Integrate the core engine
engine.Run to run repository syncing with custom filters, layout structures, and dry-run pre-flights.
Troubleshooting
| Error Message |
Cause |
Solution |
ERROR: git not found on PATH |
Git is not installed or missing from the current PATH environment. |
Install git via your package manager. |
ERROR: GITHUB_TOKEN environment variable not set |
--auth token was specified but no environment variable is present. |
Run export GITHUB_TOKEN=$(gh auth token) or switch to --auth auto. |
FAILED: owner/repo |
Authentication error or network failure during clone/pull. |
Check connectivity and confirm gh auth status displays a valid session. |
Frequently Asked Questions
- Does it work with GitLab or other hosts?
No. Corral is specifically built to integrate with the GitHub API and GitHub CLI (gh).
- What happens to repositories deleted on GitHub?
Corral never deletes your local checkouts. To see repositories that no longer exist upstream, run Corral with the --orphans flag.
- Can I run it inside Cron or systemd timers?
Yes. The command runs non-interactively by default. All Git command credential prompts are bypassed to ensure automated jobs never hang.
- How are repositories with no primary language stored?
They default to the other/ language category (e.g. Public/other/my-repo).
THE ARCHITECT ᛫ Sebastien Rousseau
THE ENGINE ᛞ EUXIS ᛫ Enterprise Unified Execution Intelligence System
License
Licensed under the GNU General Public License v3.0.
Back to Top