GitHubby

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.
Quick Start
1. Download the latest release for your platform:
Download GitHubby - Linux, macOS, Windows (amd64 & arm64)
2. Run it:
./githubby
That's it! The interactive setup wizard will guide you through:
- GitHub authentication (opens browser for OAuth)
- Sync configuration
- Dashboard
Features
- 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
scratch image for containerized sync
- Cross-Platform - Linux, macOS, and Windows
Installation
Download Binary (Recommended)
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 |
Go Install
If you have Go installed:
go install github.com/Didstopia/githubby@latest
Docker
docker pull ghcr.io/didstopia/githubby:latest
docker run --rm ghcr.io/didstopia/githubby:latest version
Build from Source
git clone https://github.com/Didstopia/githubby.git
cd githubby
make build
Usage
Interactive Mode (Recommended)
Just run githubby to launch the TUI:
githubby
First 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
Authentication for Non-Interactive Use
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
repo scope (required for private repositories; public repos work without scopes)
- Copy the token and export it:
export GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Or pass it directly with --token:
githubby sync --token ghp_... --user <username> --target ~/repos
For 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 if GITHUB_TOKEN is not set — but headless environments (Docker, CI) have no keychain, so the environment variable is required.
CLI Mode (Automation)
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 --verbose
Profile-Based Sync
Run 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-profiles
Profiles 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.
Scheduled Sync
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 |
Docker
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.
Authentication Commands
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
Release Cleanup
# 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-run
Updates
GitHubby 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 install
Note: Dev builds and the update, version, and help commands skip auto-update to prevent loops.
How Fast Sync Works
GitHubby uses smart timestamp comparison to skip unchanged repositories:
- Single API call fetches all repo metadata including
pushed_at timestamps
- Local check compares against
.git/FETCH_HEAD modification 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=...)
Configuration
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: -1
Token resolution priority:
--token flag
GITHUB_TOKEN environment variable
- System keychain (OAuth tokens)
- Config file
Global Flags
--token, -t GitHub API token (overrides stored token)
--verbose, -v Enable verbose output
--dry-run, -D Simulate operations without making changes
Development
Prerequisites
Build & Test
make build # Build binary
make test # Run tests with race detection
make lint # Run linters
make clean # Clean build artifacts
Project Structure
githubby/
├── 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
Contributing
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.
License
MIT License - see LICENSE for details.