Interactive terminal app to browse and manage your personal GitHub repositories. Built with Ink (React for CLIs) and the GitHub GraphQL API.
π Visit our website: gh-manager-cli.dev | Source
Stop clicking through GitHub's slow web interface. Managing dozens of repos on github.com means endless page loads, multiple clicks per action, and no keyboard shortcuts.
gh-manager-cli replaces tedious web clicking with powerful terminal commands:
- Slow pagination (page-by-page) β Whole account loaded in the background, browse and search everything instantly
- Multiple clicks per action β Single keypress for any operation
- No bulk operations β Archive, delete, or modify multiple repos at once
- Buried settings menus β Direct keyboard shortcuts for everything
- Page refresh after each action β Instant updates with no reload
Perfect for:
- Spring cleaning: Archive old projects and delete forgotten forks
- Professional profiles: Keep only your best work visible
- Fork management: Identify and sync outdated forks
- Consistent naming: Bulk rename repositories with patterns
- Quick decisions: See all metadata at a glance to decide what stays
Fast, keyboard-first GitHub repo management from your terminal
| Getting Started | Features | Development |
|---|---|---|
| π₯ Installation | π Features Overview | π οΈ Development Guide |
| π Token & Security | β¨οΈ Usage & Controls | π§ͺ Testing |
| β Troubleshooting | πΊοΈ Roadmap | π Wiki Home |
# Run with npx (no install)
npx gh-manager-cli@latestOn first run, you'll be prompted to authenticate with GitHub (OAuth recommended).
- Authentication: GitHub OAuth (recommended) or Personal Access Token with secure storage
- Repository Listing: Browse all your personal repositories with metadata (stars, forks, language, etc.)
- Background Fetch-All: Loads your entire account in the background after the first page, so filtering/sorting/search are instant and complete
- Interactive Sorting: Modal-based sort selection (updated, pushed, name, stars) with modal-based direction selection
- Fuzzy Search: Instant typo-tolerant search over the full cached repository set β no network calls in the search path (powered by fuse.js)
- View Filters: Single
Vmodal consolidating visibility, archive, and fork filters into three grouped sections β set any combination in one session (All / Public / Private[/Internal] Β· All / Unarchived / Archived Β· All / Forks only / Non-forks only). The fork filter runs entirely client-side over the cached set - Fork Ahead/Behind Tracking: After the background fetch-all completes, forks are enriched with both ahead and behind commit counts in a separate lightweight pass (batched 5 at a time to avoid rate-limit issues)
- Stars Mode: View and manage starred repositories (personal account only)
- Repository Actions:
- View detailed info (
I) - Shows repository metadata, language, size, and timestamps - Open in browser (Enter/
O) β for forks a chooser lets you open this repo or the upstream - Jump to PRs/Issues (
L) β chooser modal for the selected repo's open pull requests or issues; counts are shown inline on every row so you can spot backlogs at a glance - Jump to upstream (
P) β moves cursor to the parent if loaded; otherwise fetches and shows it - Create new repository (
Ctrl+N) β prompts for a name (with the personal/organisation slug shown in front), choose visibility withTab, and surfaces GitHub errors inline - Rename repository (
Ctrl+R) with inline validation and automatic cache update - Transfer repository to another owner (
Shift+M) β destination picker (personal account + visible organisations) with a manual-entry fallback for owners the token can't list, then requires a verification code, shows a final confirmation, and surfaces GitHub errors inline - Copy repository URL to clipboard (
C) with SSH/HTTPS options - Delete repository (
DelorBackspace) with secure two-step confirmation - Archive/unarchive repositories (
Ctrl+A) with confirmation prompts - Change repository visibility (
Ctrl+V) - Switch between Public, Private, and Internal (enterprise only) - Star/unstar repositories (
Ctrl+S) - Toggle star status for any repository - Sync forks with upstream (
Ctrl+F) with ahead/behind counts and automatic conflict detection
- View detailed info (
- Bulk Operations (
Bto enter Bulk Select mode):- Select multiple repositories with
Space;Xunselects all (while every other shortcut is disabled in bulk mode) - Bulk actions reuse the global shortcuts:
Ctrl+Sstar/unstar,Ctrl+Aarchive/unarchive,Ctrl+Vvisibility,Deldelete,Shift+Mtransfer (move) to another owner/org - Star and archive auto-detect a safe toggle; if the selection is mixed, an intent modal asks the explicit target. Visibility always prompts for the destination (Public / Private / Internal for enterprise orgs). Transfer opens a destination picker (personal account + visible orgs, plus manual-entry fallback)
- Selections persist across search, filter, and sort changes (select from different searches, then bulk-act)
- Confirmation flow: review list with ability to unselect β count prompt β (delete and transfer) a 4-character verification code
- Per-repo progress reporting with partial-failure summary; transferred repos are removed from the current list
- Select multiple repositories with
- Keyboard Navigation: Full keyboard control (arrow keys, PageUp/Down,
Ctrl+G/G) - Display Density: Toggle between compact/cozy/comfy spacing (
T) - Colour Themes: Four themes (Default, Ocean, Forest, Monochrome) cycled with
Shift+T, persisted across restarts; the selected-row highlight is theme-aware and tuned per theme for readable contrast - Visual Indicators: Fork status, private/internal/archived badges, language colors, visibility status
- Enterprise Support: Full support for GitHub Enterprise with Internal repository visibility
- Organization Context: Switch between personal and organization accounts with ENT badge for enterprise orgs
- Interactive Modals: Sort selection, visibility filtering, organization switching, and visibility change dialogs
- Balanced Layout: Repository items with spacing above and below for better visual hierarchy
- Loading States: Contextual loading screens for sorting and refreshing operations
- Rate Limit Monitoring: Dual API rate limit display (GraphQL & REST) with real-time usage deltas and visual warnings
- Preference Persistence: UI settings (sort, density, visibility/archive/fork filters, fork commit tracking, colour theme) saved between sessions
- Client-side Filtering & Sorting: Once the account is cached via background fetch-all, visibility/archive/fork filtering and all sorting run locally over the complete set β instant, with no server refetch
- Cross-platform: Works on macOS, Linux, and Windows
- Secure Storage: Token stored with proper file permissions (0600)
- Error Handling: Graceful error recovery with retry mechanisms
- Performance: Light bulk GraphQL queries, virtualized rendering, and
React.memo-optimized rows for instant keyboard navigation - Comprehensive Logging: Structured JSON logging with automatic rotation and configurable verbosity
brew tap wiiiimm/tap
brew install gh-manager-cliRun instantly without installing:
npx gh-manager-cli@latestInstall globally for persistent gh-manager-cli command:
npm install -g gh-manager-cli@latest
gh-manager-cliDownload standalone executables from GitHub Releases:
- Linux:
gh-manager-cli-linux-x64 - macOS:
gh-manager-cli-macos-x64 - Windows:
gh-manager-cli-windows-x64.exe
Make the binary executable (Linux/macOS):
chmod +x gh-manager-cli-*
./gh-manager-cli-*Prerequisites:
- Node.js 18+
- pnpm
Install and build:
pnpm install
pnpm buildRun locally:
node dist/index.js
# Or add to PATH for dev
pnpm link
gh-manager-cliThe app supports two authentication methods:
The easiest and most secure way to authenticate:
- Device Flow: No need to handle callback URLs - just enter a code on GitHub's website
- Browser-based: Opens GitHub's authorization page automatically
- Secure: No client secrets or sensitive data in the app
- Full Permissions: Automatically requests all necessary scopes for complete functionality
- User-friendly: No manual token management required
When you first run the app, select "GitHub OAuth (Recommended)" from the authentication options. The app will:
- Display a device code for you to enter on GitHub
- Open your browser to GitHub's device authorization page
- Wait for you to authorize the app
- Securely store the OAuth token for future use
Alternative method for users who prefer manual token management:
- Provide via env var:
GITHUB_TOKENorGH_TOKEN, or enter when prompted on first run. - Recommended: classic PAT with
reposcope for listing both public and private repos. - Validation: a minimal
viewer { login }request verifies the token.
- Storage: tokens are saved as JSON in your OS user config directory with POSIX perms
0600.- macOS:
~/Library/Preferences/gh-manager-cli/config.json - Linux:
~/.config/gh-manager-cli/config.json - Windows:
%APPDATA%\gh-manager-cli\config.json
- macOS:
- Revocation: you can revoke tokens at any time in your GitHub settings.
Note: Tokens are stored in plaintext on disk with restricted permissions. Future work may add OS keychain support.
Choose the least-privileged token for the features you plan to use:
- Browsing/searching repos (public only):
public_repo - Browsing/searching repos (includes private):
repo - Archive/Unarchive repository:
repo(and you must have admin or maintainer rights on the repo) - Sync fork with upstream:
repo(you must have push rights to your fork) - Delete repository:
delete_repo(and admin rights on the repo)
Notes:
- Organization repositories may require that your token is SSO-authorized if the org enforces SSO.
- If organization data doesnβt appear in the switcher, ensure your token is authorized for that org and consider adding
read:org(some org setups require it to list memberships). - Fine-grained PATs: grant Repository access to the repos you need and enable at least:
- Metadata: Read
- Contents: Read (list/search), Read & Write (sync/archive)
- Administration: Manage (only if you need delete)
If in doubt, the classic
reposcope plusdelete_repo(for deletion) is the simplest equivalent.
Launch the app, then use the keys below:
-
--org, -o <slug>: Start in a specific organisation context (if accessible). Ignores the flag if you donβt have access or if the slug isnβt an organisation.- Examples:
gh-manager-cli --org acmegh-manager-cli -o acmenpx gh-manager-cli@latest --org=@acmenpx gh-manager-cli@latest -o=@acme
- Notes:
- Leading
@is optional. - Personal usernames are not supported by
--org/-o(use default personal context).
- Leading
- Examples:
-
--token, -t <pat>: Use a Personal Access Token just for this run. Does not persist to config.- Examples:
gh-manager-cli --token ghp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXgh-manager-cli -t=ghp_XXXXXXXXXXXXXXXXXXXXXXXXXXXX
- Precedence: CLI token >
GITHUB_TOKEN/GH_TOKENenv vars > stored config. - Security: Supplying tokens on the command line may be captured in shell history. Prefer env vars or the interactive prompt when possible.
- Examples:
-
--help, -h: Show usage information and exit. -
--version, -v: Print the current version and exit.
- Top/Bottom:
Ctrl+G(top),G(bottom) - Page Navigation: ββ Arrow keys, PageUp/PageDown
- Search:
/to enter search mode β instant, typo-tolerant fuzzy search over the full cached set (no network calls). Matches as you type; searches name, owner, description, and language- Down arrow or Enter: Start browsing search results
- Esc: Clear search and return to full repository list
- Sort:
Sopens sort modal with options:- Updated: When the repository was last modified
- Pushed: When code was last pushed
- Name: Alphabetical by repository name
- Stars: Number of stars
- Sort Direction:
Dto open sort direction modal (ascending/descending) - Display Density:
Tto toggle compact/cozy/comfy - Colour Theme:
Shift+Tto cycle themes (Default β Ocean β Forest β Monochrome); selection persists across restarts. Each theme defines its own selected-row highlight (a darker on-theme background) so the highlighted repository stays high-contrast - Fork Status: Always enabled β shows commits ahead and behind upstream once enrichment completes (see below). Unrelated to the fork view filter (see below)
- View Filters:
Vopens the consolidated View Filters modal containing three grouped sections β Visibility (All / Public / Private[/Internal for enterprise]), Archive (All / Unarchived / Archived), and Fork (All / Forks only / Non-forks only). Move between groups with ββ, change a group's value live with ββ (radio-style), then Enter (orY/Apply) to apply and close, Esc/Cto cancel. The Visibility group is hidden in stars mode; Archive and Fork remain available there. All three selections persist across restarts, and reset to All when you switch organisation or scope (own β starred) - Stars Mode:
Shift+S(personal account only) to toggle between your own repos and your starred repos- Footer hint shows
Shift+S Starredin normal mode andShift+S My Reposin starred mode
- Footer hint shows
- Open in browser: Enter or
Oβ non-forks open directly; forks show a chooser (This repository / Parent/upstream, Esc cancels) - Open PRs / Issues:
Lβ chooser modal (Pull Requests / Issues) for the selected repo. Counts are shown inline on every row asβ N PRs β M issues, colour-coded (muted at 0, default 1β9, amber 10β29, red 30+) so growing backlogs stand out. Esc/C cancels - Jump to upstream:
P(on a fork) β moves cursor to the parent if it is already loaded; otherwise fetches the parent and shows it in the Info modal - Refresh:
R - Organisation switcher:
Wto switch between personal account and organisations - Logout:
Ctrl+L - Quit:
Q
- Create repository:
Ctrl+Nto create a new repository in the current context (personal or organisation)- Prompts for a name with the owner slug (
owner/) shown in front Tabcycles visibility (Private/Public, plus Internal for enterprise organisations)- Enter to create; GitHub errors (e.g. name already exists) are shown inline
- Prompts for a name with the owner slug (
- Repository info:
Ito view detailed metadata (size, language, timestamps) - Cache info:
Kto inspect Apollo cache status - Archive/Unarchive:
Ctrl+Awith confirmation prompt - Change visibility:
Ctrl+Vto change repository visibility (Public/Private/Internal) - Delete repository:
DelorBackspace(with two-step confirmation modal)- Type confirmation code β confirm (Y/Enter)
- Cancel: press
Cor Esc
- Star/Unstar:
Ctrl+Sto toggle star status for any repository - Sync fork:
Ctrl+F(for forks only, shows ahead/behind counts and handles conflicts) - Rename repository:
Ctrl+Rwith inline validation - Transfer repository:
Shift+M(Move) to transfer ownership to another user or organisation- Destination picker lists the personal account + organisations the token can see; pick with β/β + Enter, press
M(or select "Enter a different ownerβ¦") to switch to manual entry for owners the token can't list - Requires typing a randomly generated verification code (like delete), then a final confirmation before transferring
- GitHub errors (e.g. insufficient permissions) are shown inline
- Destination picker lists the personal account + organisations the token can see; pick with β/β + Enter, press
- Bulk Transfer (Bulk Select mode):
Shift+Mwithin Bulk Select mode to move multiple repos at once- Flow: review list (unselect) β destination picker (same as the single-repo flow, with manual fallback) β count prompt β 4-character verification code β sequential execution with per-repo progress
- Transferred repos are removed from the current list; partial-failure report shown at completion
- Copy URL:
Cto copy repository URL to clipboard (SSH/HTTPS options)
- Esc: Cancels modals, clears search, or returns to normal listing (does not quit)
The header displays the current owner context (Personal Account or Organization name), active sort and direction, fork status tracking state, and active search/filter.
Status bar shows loaded count vs total. A rate-limit line displays remaining/limit and the reset time; it turns yellow when remaining β€ 10% of the limit.
- Uses GitHub GraphQL
viewer.repositorieswithownerAffiliations: OWNER, ordered byUPDATED_AT DESC. - Background fetch-all: the first page renders immediately, then the remaining repositories load in the background until the whole account is cached locally. Filtering, sorting, and search then operate over the complete set, client-side and instant.
- Fetches 100 repos per page by default (configurable via
REPOS_PER_FETCHenvironment variable, 1-100). - Reads
totalCountfrom the first page and shows background-load progress (loaded/total) while filling. The list stays usable from the first page throughout; very large accounts simply take longer to finish loading.
When you quit the app with Q, gh-manager-cli prints a short end-of-session report as two distinct framed panels:
- π Session Summary β session duration, total operations performed, and a per-operation breakdown (e.g. "2 repositories archived", "1 repository transferred"). If nothing was changed, it simply notes "No changes were made this session."
- β± Estimated time saved β a rough, friendly estimate of how much time you saved versus performing those operations by hand on github.com (each operation type has a conservative manual-time weight, e.g. delete β 45s, transfer β 60s, star β 6s). Shown only when at least one operation was performed.
- π Thank you β a separate sponsorship/feedback panel.
Both single-repo and bulk actions are counted. The summary is not shown when exiting via Ctrl+C.
Stack:
- UI:
ink,ink-text-input,ink-spinner - API:
@octokit/graphql, Apollo Client - Config paths:
env-paths - Language: TypeScript
- Build:
tsup(CJS output with shebang)
Scripts:
pnpm build # build to dist/
pnpm build:binaries # build cross-platform binaries to ./binaries/
pnpm dev # watch mode
pnpm start # run normally
pnpm start:debug # run with debug mode enabled
pnpm start:dev # run with 5 repos per page and debug modeThe project uses a two-phase automated release workflow:
- Triggers: On feature/fix commits to
mainbranch - Version Calculation: Uses semantic-release to analyze commit messages:
feat:β Minor version bump (1.0.0 β 1.1.0)fix:β Patch version bump (1.0.0 β 1.0.1)BREAKING CHANGE:β Major version bump (1.0.0 β 2.0.0)
- Actions:
- Analyzes commits since last release
- Calculates new version number
- Updates
package.jsonandCHANGELOG.md - Creates git tag
- Publishes to NPM
- Commits changes as
chore(release): X.Y.Z
- Triggers: On
chore(release):commits (from Phase 1) - Actions:
- Builds binaries for Linux, macOS, Windows
- Creates GitHub release with changelog
- Uploads binaries to release
- Publishes to GitHub Packages
- Updates Homebrew formula
Developer merges PR with commits:
- feat: add new feature
- fix: resolve bug
β
Phase 1: semantic-release analyzes commits
β
Calculates version: 1.2.3 β 1.3.0 (feat = minor)
Creates commit: "chore(release): 1.3.0"
β
Phase 2: Build workflow triggers
β
Builds binaries with version 1.3.0
β
Creates GitHub release with binaries
β
Publishes to GitHub Packages & updates Homebrew
To manually trigger a release:
# Update version in package.json
npm version patch # or minor/major
git push origin mainBoth NPM and Homebrew will be automatically updated within minutes of any version change.
Environment variables:
REPOS_PER_FETCH: Number of repositories to fetch per page (1-100, default: 100)GH_MANAGER_DEBUG=1: Enables debug mode with performance metrics, detailed errors, and console loggingGH_TOKEN: GitHub Personal Access Token (alternative to OAuth authentication)NO_COLOR: Disable colored output in terminal
Project layout:
src/index.tsxβ CLI entry, flag parsing, error handling, end-of-session summarysrc/types.tsβ shared typessrc/ui/App.tsxβ token bootstrap, rendersRepoListsrc/ui/views/βRepoList.tsx(main list UI, key handling, modal management) andRepoList.main.tsxsrc/ui/OrgSwitcher.tsxβ organisation switching componentsrc/ui/hooks/βuseThemeand other shared hookssrc/ui/components/β modular componentsmodals/β Delete, Archive, Sync, Info, Logout, Rename, Transfer, CopyUrl, CreateRepo, ChangeVisibility, Visibility, Sort, SortDirection, ArchiveFilter, Star, Unstar, OpenInBrowser, and the Bulk* modals (Confirm, Review, Intent, Progress, Code, DeleteCode, TransferCode, TransferDestination, Visibility) plusbulkActions.tsrepo/β RepoRow (memoised withReact.memo), FilterInput, RepoListHeaderauth/β AuthMethodSelector, OAuthProgresscommon/β SlowSpinner and shared UI elements
src/services/βgithub.ts(GraphQL client and queries),oauth.ts(device-flow auth),apolloMeta.ts(Apollo cache management)src/config/βconfig.ts(token read/write and UI preferences),constants.ts,themes.ts(colour themes)src/lib/βlogger.ts(structured logging with rotation),utils.ts(truncate, formatDate),session.ts(usage tracking + summary),fuzzySearch.ts(fuse.js search)viewlogs.shβ utility script for viewing logs
gh-manager-cli includes comprehensive logging for debugging and monitoring purposes.
Logs are automatically written to your system's standard log directory:
- macOS:
~/Library/Logs/gh-manager-cli/gh-manager-cli.log - Linux:
~/.local/state/gh-manager-cli-log/gh-manager-cli.log - Windows:
%LOCALAPPDATA%\gh-manager-cli\Log\gh-manager-cli.log
Use the included viewlogs.sh script to quickly view recent log entries:
./viewlogs.sh # View last 50 lines
./viewlogs.sh 100 # View last 100 lines
./viewlogs.sh -f # Follow log in real-time- Structured JSON: Each log entry includes timestamp, level, message, and contextual data
- Automatic Rotation: Logs rotate at 5MB with up to 5 historical files kept
- Comprehensive Coverage: Tracks app lifecycle, API calls, user actions, and errors
- Debug Mode: Set
GH_MANAGER_DEBUG=1to enable verbose logging to console
- Application startup/shutdown with version info
- Authentication events (login/logout)
- Repository operations (fetch, delete, archive, visibility changes)
- API performance metrics and rate limit status
- Error details with stack traces
- User interface component lifecycle
gh-manager-cli includes built-in Apollo Client caching to reduce GitHub API calls and improve performance. Caching is always enabled for optimal performance.
Run with GH_MANAGER_DEBUG=1 to enable debugging features:
GH_MANAGER_DEBUG=1 npx gh-manager-cli@latestDebug mode provides:
- Apollo performance metrics: Query execution time, cache hit/miss indicators
- Detailed error messages: Full GraphQL and network errors for troubleshooting
- Data source tracking: Shows whether data came from cache or network
-
Performance Indicators (visible in debug mode):
- From cache: YES = Data served from cache
- Query time < 50ms = Likely cache hit
- Network status codes = Shows Apollo's internal cache state
-
API Credits: Monitor the API counter in the header - it should remain stable when navigating previously loaded data
-
Cache Inspection: Press
K(available anytime) to see:- Cache file location and size
- Recent cache entries with timestamps
- Cache age for each query type
Even with caching enabled, API credits may decrease due to:
- First-time requests: Initial data must be fetched and cached
- Cache expiration: Default 30-minute TTL (customize with
APOLLO_TTL_MS) - Pagination: New pages beyond the cache are fetched from API
- Cache-and-network policy: Updates stale cache data in background
- Sorting changes: Different sort orders create new cache entries
# Number of repositories to fetch per page (1-100, default: 100)
REPOS_PER_FETCH=10 npx gh-manager-cli@latest
# Custom cache TTL (milliseconds) - default: 30 minutes
APOLLO_TTL_MS=1800000 npx gh-manager-cli@latest
# Enable debug mode to see cache performance
GH_MANAGER_DEBUG=1 npx gh-manager-cli@latest
# Combine multiple environment variables
REPOS_PER_FETCH=5 GH_MANAGER_DEBUG=1 npx gh-manager-cli@latest- Invalid token: enter a valid PAT (recommended scope:
repo). - Rate limited: wait for the reset shown in the banner or reduce navigation.
- Network errors: check connectivity and press
rto retry.
For the up-to-date task board, see TODOs.md.
Recently implemented:
- β OAuth login flow as an alternative to Personal Access Token
- β Density toggle for row spacing (compact/cozy/comfy)
- β
Colour themes (Default, Ocean, Forest, Monochrome) cycled with
Shift+T - β Repo actions (archive/unarchive, delete, change visibility, rename, transfer) with confirmations
- β
Bulk Select mode (
B) β bulk star, archive/unarchive, visibility, delete, and transfer - β
Organization support and switching (press
W) with enterprise detection - β Background fetch-all with instant client-side fuzzy search (fuse.js)
- β Fork ahead/behind enrichment after fetch-all completes
- β Modal-based sort and visibility filtering
- β GitHub Enterprise support with Internal repository visibility
- β
Change repository visibility modal (
Ctrl+V) - β
Copy repository URL to clipboard (
C) with SSH/HTTPS options - β End-of-session usage summary with time-saved estimate
- β Enhanced rate limit display showing both GraphQL and REST API limits with delta tracking
Highlights on deck:
- Optional OS keychain storage via
keytar - Language filter and indicators
- Additional sort fields (created, size) and more CLI flags
If you find gh-manager-cli useful, consider supporting its development:
π GitHub Sponsors - Support directly through GitHub β Buy Me a Coffee - One-time coffee donations
Your support helps maintain and improve this project. Thank you! π
MIT



