A transparent wrapper for the GitHub CLI (gh) that automatically detects when it's being invoked by an AI tool and ensures all actions are properly attributed to a bot acting on behalf of the user, rather than appearing to come directly from the user.
When AI coding assistants (Claude, Cursor, Gemini, etc.) use the GitHub CLI to perform actions like creating PRs, issues, or comments, those actions appear to come directly from you. This creates:
- Attribution confusion: Was this action taken by you or your AI assistant?
- Audit trail issues: No clear record of AI involvement in repository changes
- Trust concerns: Other developers can't distinguish between human and AI actions
AI-Aligned-GH is a transparent wrapper that:
- Intercepts all
ghcalls without requiring any changes to how AI tools work - Detects AI usage through process tree analysis and environment variables
- Exchanges tokens via the as-a-bot service
- Ensures proper attribution so AI actions show as "as-a-bot[bot] on behalf of @username"
# One-line install
curl -fsSL https://raw.githubusercontent.com/trieloff/ai-aligned-gh/main/install.sh | sh
# Add to PATH (if needed)
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrcUnlike a GitHub CLI extension (which would require AI tools to consciously call gh ai instead of gh), this is a transparent wrapper that intercepts all gh calls:
AI Tool → gh (wrapper) → Detection → Token Exchange → gh (real) → GitHub API
↓ ↓
Our wrapper as-a-bot service
The wrapper installs itself as gh in ~/.local/bin, which must come before the real gh in your PATH:
$ which -a gh
/home/user/.local/bin/gh # Our wrapper (first in PATH)
/usr/bin/gh # Real gh CLIThe wrapper detects AI tools through:
- Environment variables:
CLAUDE_CODE,CURSOR_AI,GEMINI_CLI, etc. - Process tree analysis: Walks up parent processes looking for AI tool signatures
- Process name matching: Identifies
claude,cursor,gemini, etc. in process names
When an AI is detected and performing a write operation:
- Wrapper gets the current repository from
git config - Checks if the as-a-bot GitHub App is installed
- Exchanges user token for bot token via the as-a-bot service
- Executes
ghwith the bot token
Read-only operations (like gh pr list) skip token exchange for performance.
- GitHub CLI: Install from cli.github.com
- GitHub App: Install as-a-bot on your repositories
- Authentication: Be authenticated with
gh auth login - jq (recommended): For JSON parsing during token exchange
Once installed, the wrapper works completely transparently. AI tools continue to call gh normally:
# AI tools just use gh as usual
gh pr create --title "Add new feature" --body "..."
gh issue comment 123 --body "Fixed in latest commit"
# The wrapper automatically handles attribution when AI is detectedSee what's happening under the hood:
GH_AI_DEBUG=true gh pr listOutput:
[DEBUG] Starting AI detection from PID 12345
[DEBUG] Detected Claude in process tree
[INFO] AI detected: claude - checking for bot token exchange...
[DEBUG] Found origin URL: https://github.com/user/repo.git
[DEBUG] Parsed owner: user, repo: repo
[INFO] Successfully exchanged token - actions will be attributed to bot
Force AI detection for testing:
# Simulate different AI environments
OR_APP_NAME=Aider gh issue list
AUGMENT_API_TOKEN=test gh issue list
CLAUDE_CODE=1 gh issue list
CURSOR_AI=1 gh pr view 123
GEMINI_CLI=1 gh repo clone user/repo
KIMI_CLI=1 gh pr create --title "Test" --body "Testing Kimi detection"The wrapper automatically detects:
| AI Tool | Detection Method | Environment Variable |
|---|---|---|
| Aider | Process name + env | OR_APP_NAME=Aider |
| Auggie (Augment Code) | Process name + env | AUGMENT_API_TOKEN |
| Amp (Sourcegraph) | Process name + env | AGENT=amp, AMP_HOME |
| Claude (Anthropic) | Process name + env | CLAUDE_CODE, ANTHROPIC_SHELL |
| Codex CLI (OpenAI) | Process name + env | CODEX_CLI |
| Crush (Charm) | Process name only | (detected via process tree) |
| Cursor | Process name + env | CURSOR_AI |
| Droid (Factory AI) | Process name + env | DROID_CLI |
| Gemini (Google) | Process name + env | GEMINI_CLI |
| Goose (Block) | Process name + env | GOOSE_TERMINAL |
| GitHub Copilot CLI | Process name + env | GITHUB_COPILOT_CLI_MODE=true |
| Kimi CLI | Process name + env | KIMI_CLI |
| OpenCode | Process name + env | OPENCODE_AI |
| Qwen Code (Alibaba) | Process name + env | QWEN_CODE |
| Zed AI | Process name + env | ZED_AI |
| Variable | Description | Default |
|---|---|---|
GH_AI_DEBUG |
Enable debug output | false |
AS_A_BOT_URL |
as-a-bot service URL | https://as-bot-worker.minivelos.workers.dev |
GH_TOKEN |
GitHub token override | (uses gh auth token) |
The wrapper must be found before the real gh in your PATH:
# Check PATH order
echo $PATH | tr ':' '\n'
# Verify wrapper is first
which -a gh- No token storage: Tokens are exchanged on-demand, never stored
- Preserves permissions: Bot tokens have the same permissions as user tokens
- Transparent operation: All actions are logged and auditable
- Fails safely: If token exchange fails, falls back to normal operation
Without AI-Aligned-GH:
trieloff opened pull request #123
With AI-Aligned-GH:
as-a-bot[bot] opened pull request #123 on behalf of @trieloff
Without AI-Aligned-GH:
@trieloff commented: "This has been fixed in the latest commit"
With AI-Aligned-GH:
as-a-bot[bot] commented on behalf of @trieloff: "This has been fixed in the latest commit"
Want to check if a GitHub action was performed by an AI? Use these gh api commands to inspect the provenance:
# Check who created an issue and which app (if any) was used
gh api repos/OWNER/REPO/issues/NUMBER --jq '{
user: .user.login,
app: .performed_via_github_app.slug // "none"
}'
# Example
gh api repos/trieloff/ai-aligned-gh/issues/15 --jq '{
user: .user.login,
app: .performed_via_github_app.slug
}'
# Output: {"user": "trieloff", "app": "as-a-bot"}# Check the latest comment on an issue
gh api repos/OWNER/REPO/issues/NUMBER/comments --jq '.[-1] | {
user: .user.login,
app: .performed_via_github_app.slug // "none"
}'# Check who created a PR
gh api repos/OWNER/REPO/pulls/NUMBER --jq '{
user: .user.login,
app: .performed_via_github_app.slug // "none"
}'
# Note: PRs created with installation tokens show user as "app-name[bot]"
# PRs created with user-to-server tokens show the actual username# Check the latest comment on a PR (same endpoint as issues)
gh api repos/OWNER/REPO/issues/NUMBER/comments --jq '.[-1] | {
user: .user.login,
app: .performed_via_github_app.slug // "none"
}'-
User-to-server token (correct):
user: "your-username",app: "as-a-bot"- Actions are attributed to you but marked as performed via the app
- This is what ai-aligned-gh creates
-
Installation token (incorrect):
user: "as-a-bot[bot]",app: "none"- Actions appear to come from the bot itself
- Loses human attribution
-
Direct user action:
user: "your-username",app: "none"- Regular human action without any AI involvement
The performed_via_github_app field is inconsistently available across GitHub API endpoints (undocumented):
| Action | Has performed_via_github_app? |
|---|---|
| Issue creation | ✅ Yes |
| Issue comments | ✅ Yes |
| PR comments | ✅ Yes |
| Pull request creation | ❌ No |
| PR reviews | ❌ No |
This is a GitHub API limitation, not an issue with our implementation. Even with proper user-to-server tokens, PRs themselves don't include app attribution in the API response.
Check all recent activity in a repo:
# List recent issues with attribution
for issue in $(gh issue list --limit 5 --json number --jq '.[].number'); do
echo -n "Issue #$issue: "
gh api repos/OWNER/REPO/issues/$issue --jq '{
user: .user.login,
app: .performed_via_github_app.slug // "none"
}'
done# Check if wrapper is installed
ls -la ~/.local/bin/gh
# Check PATH order
which -a gh
# Ensure ~/.local/bin is first in PATH
export PATH="$HOME/.local/bin:$PATH"If you see warnings about the app not being installed:
- Visit https://github.com/apps/as-a-bot
- Click "Install" or "Configure"
- Select the repositories where you want AI attribution
- Save the configuration
# Check authentication
gh auth status
# Test token exchange manually
GH_AI_DEBUG=true CLAUDE_CODE=1 gh pr list# Check process tree
ps -ef | grep -E "claude|cursor|gemini"
# Force detection with environment variable
CLAUDE_CODE=1 gh issue listTo add support for a new AI tool:
- Add detection logic to the
detect_ai_toolfunction inexecutable_gh - Add environment variable check (e.g.,
NEW_AI_TOOL) - Add process name pattern matching
- Test with
GH_AI_DEBUG=true - Submit a pull request
Apache 2.0 - See LICENSE file for details
Part of the AI Ecoverse - a comprehensive ecosystem of tools for AI-assisted development:
- yolo - AI CLI launcher with worktree isolation
- am-i-ai - Shared AI detection library (powers this tool)
- ai-aligned-git - Git wrapper for safe AI commit practices
- vibe-coded-badge-action - Badge showing AI-generated code percentage
- gh-workflow-peek - Smarter GitHub Actions log filtering
- upskill - Install Claude/Agent skills from other repositories
- as-a-bot - GitHub App token broker for proper AI attribution
This project is inspired by and follows the design philosophy of ai-aligned-git by @trieloff. The transparent wrapper pattern ensures AI tools don't need to be modified or trained to use special commands - they just work.
"The best interface is no interface. The wrapper is transparent, the AI doesn't know it exists, and yet every action is properly attributed."
