A powerful CLI and TUI utility for syncing GitHub repositories locally. Features an interactive setup wizard, fast incremental sync, Git LFS support, and release management.
1. Download the latest release for your platform:
Download GitHubby - Linux, macOS, Windows (amd64 & arm64)
2. Run it:
./githubbyThat's it! The interactive setup wizard will guide you through:
- GitHub authentication (opens browser for OAuth)
- Sync configuration
- Dashboard
- Interactive TUI - Beautiful terminal interface with setup wizard and dashboard
- Fast Sync - Incremental sync skips unchanged repos (seconds, not minutes)
- Parallel Processing - 4 concurrent workers for faster synchronization
- Full Branch Backup - Fetches all branches, not just the default
- Git LFS Support - Automatic detection and configuration
- Secure Auth - OAuth device flow with system keychain storage
- Release Cleanup - Filter and remove old GitHub releases
- Auto-Update - Automatic updates on launch with seamless restart
- Scheduled Sync - Cron-based recurring sync for unattended operation
- Profile-Based CLI - Run saved TUI profiles from the command line
- Docker Support - Minimal
scratchimage for containerized sync - Cross-Platform - Linux, macOS, and Windows
Download the latest release for your platform from the releases page:
| Platform | Architecture | Download |
|---|---|---|
| Linux | amd64 | githubby_*_linux_amd64.tar.gz |
| Linux | arm64 | githubby_*_linux_arm64.tar.gz |
| macOS | Intel | githubby_*_darwin_amd64.tar.gz |
| macOS | Apple Silicon | githubby_*_darwin_arm64.tar.gz |
| Windows | amd64 | githubby_*_windows_amd64.zip |
| Windows | arm64 | githubby_*_windows_arm64.zip |
If you have Go installed:
go install github.com/Didstopia/githubby@latestdocker pull ghcr.io/didstopia/githubby:latest
docker run --rm ghcr.io/didstopia/githubby:latest versiongit clone https://github.com/Didstopia/githubby.git
cd githubby
make buildJust run githubby to launch the TUI:
githubbyFirst run opens the Setup Wizard:
- Choose authentication method (OAuth recommended)
- Browser opens for GitHub authorization
- Configure default sync directory and username
- Press Enter to open the Dashboard
Dashboard lets you:
- Create and manage sync profiles (user or organization)
- Sync individual profiles or all at once
- View sync history and status
- Access release cleanup tools
CLI, scheduled, and Docker workflows cannot use the interactive OAuth browser flow. Instead, provide a GitHub personal access token (PAT) via the GITHUB_TOKEN environment variable:
- Go to github.com/settings/tokens
- Click Generate new token (classic) (or use a fine-grained token)
- Select the
reposcope (required for private repositories; public repos work without scopes) - Copy the token and export it:
export GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxOr pass it directly with --token:
githubby sync --token ghp_... --user <username> --target ~/reposFor Docker Compose, create a .env file next to docker-compose.yaml:
GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Tip: The interactive TUI (
githubby login) stores tokens in the system keychain. CLI and scheduled modes will pick up that stored token automatically ifGITHUB_TOKENis not set — but headless environments (Docker, CI) have no keychain, so the environment variable is required.
For scripts and automation, use CLI flags directly:
# Sync all repositories for a user
githubby sync --user <username> --target ~/repos
# Sync an organization's repositories
githubby sync --org <orgname> --target ~/repos
# Include private repositories
githubby sync --user <username> --target ~/repos --include-private
# Filter repositories
githubby sync --user <username> --target ~/repos \
--include "myproject-*" \
--exclude "*-archive"
# Dry run (preview without changes)
githubby sync --user <username> --target ~/repos --dry-run
# Verbose output (shows fast-sync decisions)
githubby sync --user <username> --target ~/repos --verboseRun saved TUI profiles directly from the CLI — no interactive mode needed:
# Sync a specific profile by name
githubby sync --profile "my-profile"
# Sync all saved profiles
githubby sync --all-profilesProfiles are created in the interactive TUI and stored in ~/.githubby/state.yaml. Each profile saves the sync type (user/org), source, target directory, and filter settings.
Use --schedule with any sync mode to run recurring syncs in the foreground. The schedule uses standard cron syntax:
# Sync every 6 hours
githubby sync --user <username> --target ~/repos --schedule "0 */6 * * *"
# Sync all profiles every 30 minutes
githubby sync --all-profiles --schedule "@every 30m"
# Sync a profile on a cron schedule
githubby sync --profile "my-profile" --schedule "@hourly"The scheduler runs an immediate sync on start, then follows the cron schedule. Overlapping runs are automatically skipped. Use Ctrl+C to stop.
Supported schedule formats:
| Format | Example | Description |
|---|---|---|
| Cron | 0 */6 * * * |
Standard 5-field cron expression |
@every |
@every 30m |
Fixed interval (s, m, h) |
@hourly |
@hourly |
Predefined schedules |
@daily |
@daily |
Once per day at midnight |
Run GitHubby in a container for unattended scheduled sync:
# One-off sync
docker run --rm \
-e GITHUB_TOKEN=ghp_... \
-v ~/repos:/repos \
ghcr.io/didstopia/githubby:latest \
sync --user <username> --target /repos
# Scheduled sync (runs every 6 hours)
docker run -d --restart unless-stopped \
-e GITHUB_TOKEN=ghp_... \
-v ~/repos:/repos \
ghcr.io/didstopia/githubby:latest \
sync --user <username> --target /repos --schedule "0 */6 * * *"Or use docker-compose.yaml for persistent setups:
services:
# Syncs every saved TUI profile every 6 hours (at :00 past every 6th hour).
sync-all-profiles:
image: ghcr.io/didstopia/githubby:latest
command: ["sync", "--all-profiles", "--schedule", "0 */6 * * *"]
environment:
- GITHUB_TOKEN=${GITHUB_TOKEN}
volumes:
- ./repos:/repos # local directory for cloned repositories
- githubby-state:/root/.githubby # persists profiles & sync history
restart: unless-stopped
# Syncs a single user's repositories every 30 minutes.
sync-user:
image: ghcr.io/didstopia/githubby:latest
command: ["sync", "--user", "myuser", "--target", "/repos", "--schedule", "*/30 * * * *"]
environment:
- GITHUB_TOKEN=${GITHUB_TOKEN}
volumes:
- ./repos:/repos
restart: unless-stopped
volumes:
githubby-state:A fully commented docker-compose.yaml is included in the repository.
githubby login # OAuth device flow (opens browser)
githubby login --with-token # Use personal access token from stdin
githubby auth status # Check authentication status
githubby logout # Remove stored credentials# Remove releases older than 30 days
githubby clean --repository owner/repo --filter-days 30
# Keep only the 10 most recent releases
githubby clean --repository owner/repo --filter-count 10
# Dry run
githubby clean --repository owner/repo --filter-days 30 --dry-runGitHubby automatically keeps itself up to date:
Automatic updates on launch: When you run any command (CLI or TUI), GitHubby checks for updates and automatically installs them before proceeding. The app restarts seamlessly after updating:
Checking for updates...
Updating to v1.1.0...
Update complete! Restarting...
TUI update flow: The TUI shows a blocking modal during startup update, then restarts automatically. After launch, you can also press u to update if a newer version becomes available.
Manual update commands:
githubby update # Check and install updates
githubby update --check # Check only, don't installNote: Dev builds and the update, version, and help commands skip auto-update to prevent loops.
GitHubby uses smart timestamp comparison to skip unchanged repositories:
- Single API call fetches all repo metadata including
pushed_attimestamps - Local check compares against
.git/FETCH_HEADmodification time - Skip fetch if no pushes occurred since last sync
Result: Syncing 100+ repos takes ~2-10 seconds when most are unchanged, compared to minutes with traditional full-fetch approaches.
Use --verbose to see fast-sync decisions:
[fast-sync] owner/repo: skipping fetch (up-to-date, pushed_at=..., last_fetch=...)
Config file: ~/.githubby.yaml
# Global settings
verbose: false
dry-run: false
# Sync defaults
user: ""
org: ""
target: ""
include-private: false
include: []
exclude: []
# Clean defaults
repository: ""
filter-days: -1
filter-count: -1Token resolution priority:
--tokenflagGITHUB_TOKENenvironment variable- System keychain (OAuth tokens)
- Config file
--token, -t GitHub API token (overrides stored token)
--verbose, -v Enable verbose output
--dry-run, -D Simulate operations without making changes
- Go 1.24+
- Git
make build # Build binary
make test # Run tests with race detection
make lint # Run linters
make clean # Clean build artifactsgithubby/
├── cmd/githubby/main.go # Entry point
├── internal/
│ ├── auth/ # OAuth & keychain storage
│ ├── cli/ # Cobra commands
│ ├── config/ # Configuration management
│ ├── git/ # Git and LFS operations
│ ├── github/ # GitHub API client
│ ├── schedule/ # Cron-based sync scheduling
│ ├── sync/ # Repository sync logic
│ ├── state/ # TUI state management
│ ├── tui/ # Terminal UI (Bubble Tea)
│ │ └── screens/ # TUI screens (onboarding, dashboard, etc.)
│ └── update/ # Auto-update functionality
└── .github/workflows/ # CI/CD
Contributions are welcome!
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please ensure your code passes make lint and make test before submitting.
MIT License - see LICENSE for details.