This document describes how to use the --pattern flag to route different repositories to different GitHub Apps.
The --pattern flag allows you to explicitly specify which GitHub App should handle authentication for specific repository patterns. This is useful when you have multiple GitHub Apps configured and want fine-grained control over which app is used for which repositories.
- Multiple Organizations: Different GitHub Apps for different organizations
- Enterprise + Cloud: Separate apps for GitHub Enterprise and GitHub.com
- Access Control: Different permission scopes for different repository groups
- Testing: Use a test app for specific repos while keeping production app for others
Without --pattern (Auto-matching):
# All repos use first matching pattern from config
git config --global credential.helper '!/path/to/gh-app-auth git-credential'- Relies on pattern priority in config file
- First match wins
- Less explicit about which app handles which repo
With --pattern (Explicit routing):
# Explicitly route specific org to specific app
git config credential.'https://github.com/myorg'.helper '!/path/to/gh-app-auth git-credential --pattern "github.com/myorg/*"'- Git's native URL scoping
- Explicit app selection
- Multiple apps can coexist
First, set up your apps in ~/.config/gh/extensions/gh-app-auth/config.yml:
github_apps:
- app_id: 111111
name: "AmadeusITGroup App"
private_key_path: ~/.config/gh/extensions/gh-app-auth/keys/amadeus.pem
patterns:
- "github.com/AmadeusITGroup/*"
- app_id: 222222
name: "Personal Projects App"
private_key_path: ~/.config/gh/extensions/gh-app-auth/keys/personal.pem
patterns:
- "github.com/myusername/*"
- "github.com/myorg/*"
- app_id: 333333
name: "Enterprise App"
private_key_path: ~/.config/gh/extensions/gh-app-auth/keys/enterprise.pem
patterns:
- "github.enterprise.com/*/*"# AmadeusITGroup repositories
git config --global credential.'https://github.com/AmadeusITGroup'.helper ""
git config --global --add credential.'https://github.com/AmadeusITGroup'.helper \
'!/home/youruser/.local/share/gh/extensions/gh-app-auth/gh-app-auth git-credential --pattern "github.com/AmadeusITGroup/*"'
# Personal repositories
git config --global credential.'https://github.com/myorg'.helper ""
git config --global --add credential.'https://github.com/myorg'.helper \
'!/home/youruser/.local/share/gh/extensions/gh-app-auth/gh-app-auth git-credential --pattern "github.com/myorg/*"'
# Enterprise repositories
git config --global credential.'https://github.enterprise.com'.helper ""
git config --global --add credential.'https://github.enterprise.com'.helper \
'!/home/youruser/.local/share/gh/extensions/gh-app-auth/gh-app-auth git-credential --pattern "github.enterprise.com/*/*"'For even finer control, configure at the repository level:
cd /path/to/your/repo
# Use specific app for this repo only
git config credential.helper ""
git config --add credential.helper \
'!/home/youruser/.local/share/gh/extensions/gh-app-auth/gh-app-auth git-credential --pattern "github.com/AmadeusITGroup/*"'Combine specific and fallback configurations:
# Specific organization
git config --global credential.'https://github.com/AmadeusITGroup'.helper \
'!/path/to/gh-app-auth git-credential --pattern "github.com/AmadeusITGroup/*"'
# Global fallback (no pattern - uses auto-matching)
git config --global credential.helper \
'!/path/to/gh-app-auth git-credential'- Git calls credential helper with repository URL
- Helper reads
--patternflag (if provided) - Pattern matching:
- With
--pattern: Searches config for app with exactly this pattern - Without
--pattern: Uses URL-based matching (original behavior)
- With
- App found: Generates credentials and returns to git
- No app found: Silently exits (git tries next helper or prompts)
Patterns must match exactly as configured in your config file:
patterns:
- "github.com/AmadeusITGroup/*" # ✓ Correct
- "github.com/org/*" # ✓ Correct
- "github.enterprise.com/*/*" # ✓ CorrectThe pattern you pass to --pattern must be identical:
# ✓ Correct - exact match
--pattern "github.com/AmadeusITGroup/*"
# ✗ Wrong - won't match
--pattern "github.com/AmadeusITGroup"
--pattern "AmadeusITGroup/*"Scenario: You work with two organizations, each with its own GitHub App.
Setup:
# Organization A
git config --global credential.'https://github.com/orgA'.helper \
'!gh-app-auth git-credential --pattern "github.com/orgA/*"'
# Organization B
git config --global credential.'https://github.com/orgB'.helper \
'!gh-app-auth git-credential --pattern "github.com/orgB/*"'Usage:
# Automatically uses orgA's app
git clone https://github.com/orgA/private-repo
# Automatically uses orgB's app
git clone https://github.com/orgB/private-repoScenario: You have repos on both GitHub Enterprise and GitHub.com.
Setup:
# Enterprise
git config --global credential.'https://github.enterprise.com'.helper \
'!gh-app-auth git-credential --pattern "github.enterprise.com/*/*"'
# Cloud
git config --global credential.'https://github.com'.helper \
'!gh-app-auth git-credential --pattern "github.com/*/*"'Scenario: Test a new GitHub App on one repository before rolling out.
Setup:
cd /path/to/test-repo
# Use test app for this repo only
git config credential.helper \
'!gh-app-auth git-credential --pattern "github.com/org/test-repo"'export GH_APP_AUTH_DEBUG_LOG=1
# or
export GH_APP_AUTH_DEBUG_LOG=/tmp/gh-app-auth-debug.log
# Run your git command
git clone https://github.com/org/repo
# View logs
tail -f ~/.config/gh/extensions/gh-app-auth/debug.logLog shows: no_pattern_match
Cause: The pattern doesn't exist in any configured app.
Solution: Check your config file and ensure the pattern matches exactly:
gh app-auth list # View configured patternsCause: Git isn't calling your credential helper.
Solution: Verify git configuration:
git config --get-all credential.helper
git config --get-all credential."https://github.com/org".helperLog shows: app_matched_by_pattern with unexpected app_id
Cause: Multiple apps might have the same pattern.
Solution: Make patterns unique per app, or use more specific URL scoping in git config.
# Global credential helpers
git config --global --get-regexp credential
# Repository-specific helpers
cd /path/to/repo
git config --get-regexp credential
# Test which helper git would use
GIT_TRACE=1 git ls-remote https://github.com/org/repo 2>&1 | grep credential- Minimal overhead: Pattern matching is a simple string comparison
- No network calls: Matching happens locally before authentication
- Caching: Tokens are still cached per repository URL
- Same speed: Identical performance to auto-matching mode
Patterns are visible in git configuration:
git config --list | grep credentialThis is safe because patterns are public information (repository URLs), not secrets.
Private keys remain protected:
- Stored separately from patterns
- File permissions:
0600 - Never logged or exposed
Tokens generated via pattern routing have the same security as auto-matched tokens:
- Short-lived (1 hour expiration)
- Scoped to repository
- Cached securely
Before (auto-matching):
git config --global credential.helper '!gh-app-auth git-credential'After (pattern routing):
# Clear old config
git config --global --unset credential.helper
# Add pattern-specific configs
git config --global credential.'https://github.com/orgA'.helper \
'!gh-app-auth git-credential --pattern "github.com/orgA/*"'
git config --global credential.'https://github.com/orgB'.helper \
'!gh-app-auth git-credential --pattern "github.com/orgB/*"'
# Optional: Add fallback for unmatched repos
git config --global credential.helper '!gh-app-auth git-credential'- Keep existing config (auto-matching)
- Add one pattern-specific config for testing
- Verify it works with debug logging
- Add more patterns incrementally
- Remove fallback once all repos covered
# Try gh-app-auth first, fall back to gh CLI
git config --global credential.helper \
'!gh-app-auth git-credential --pattern "github.com/myorg/*"'
git config --global --add credential.helper \
'!gh auth git-credential'Repository config takes precedence over global:
# Global: use App A
git config --global credential.'https://github.com/org'.helper \
'!gh-app-auth git-credential --pattern "github.com/org/*"'
# This repo: use App B instead
cd /path/to/special-repo
git config credential.helper \
'!gh-app-auth git-credential --pattern "github.com/specialorg/*"'