{"slug": "example-of-claude-code-git-integration", "title": "Example of Claude Code Git Integration", "summary": "A developer shared a bash script that integrates Claude Code with GitHub Issues, enabling automated local processing of issue commands. The script creates a branch, sets up a Node.js environment, and uses the GitHub CLI to comment on issues, demonstrating a practical workflow for AI-assisted development.", "body_md": "|\n#!/bin/bash |\n|\n# |\n|\n# Local Claude Code Handler for GitHub Issues |\n|\n# Processes GitHub issues by creating branches and calling Claude Code directly |\n|\n# |\n|\n|\n|\nset -e |\n|\n|\n|\n# Get environment variables passed from the monitor |\n|\nISSUE_NUMBER=\"${ISSUE_NUMBER}\" |\n|\nISSUE_TITLE=\"${ISSUE_TITLE}\" |\n|\nISSUE_AUTHOR=\"${ISSUE_AUTHOR}\" |\n|\nISSUE_COMMAND=\"${ISSUE_COMMAND}\" |\n|\nREPO_OWNER=\"${REPO_OWNER}\" |\n|\nREPO_NAME=\"${REPO_NAME}\" |\n|\nGITHUB_TOKEN=\"${GITHUB_TOKEN}\" |\n|\n|\n|\n# Configuration |\n|\nREPO=\"${REPO_OWNER}/${REPO_NAME}\" |\n|\nBRANCH_NAME=\"claude-bot/issue-${ISSUE_NUMBER}\" |\n|\n|\n|\n# Get project root |\n|\nSCRIPT_DIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\" |\n|\nPROJECT_ROOT=\"$( cd \"$SCRIPT_DIR/../..\" && pwd )\" |\n|\n|\n|\n# Log file location |\n|\nLOG_DIR=\"$PROJECT_ROOT/logs/claude-handler\" |\n|\nmkdir -p \"$LOG_DIR\" |\n|\nLOG_FILE=\"$LOG_DIR/handler-local-$(date +%Y%m%d).log\" |\n|\n|\n|\n# Function to log with timestamp |\n|\nlog() { |\n|\necho \"[$(date '+%Y-%m-%d %H:%M:%S')] $1\" | tee -a \"$LOG_FILE\" |\n|\n} |\n|\n|\n|\n# Function to add a comment to the issue |\n|\nadd_issue_comment() { |\n|\nlocal comment=\"$1\" |\n|\nlog \"Adding comment to issue #$ISSUE_NUMBER\" |\n|\n|\n|\ngh issue comment \"$ISSUE_NUMBER\" \\ |\n|\n--repo \"$REPO\" \\ |\n|\n--body \"$comment\" |\n|\n} |\n|\n|\n|\n# Function to get the default branch of the repository |\n|\nget_default_branch() { |\n|\ngh repo view \"$REPO\" --json defaultBranchRef --jq '.defaultBranchRef.name' |\n|\n} |\n|\n|\n|\n# Set up Node.js environment for Claude Code |\n|\nsetup_node_env() { |\n|\nlog \"Setting up Node.js environment...\" |\n|\n|\n|\n# Load NVM if available |\n|\nif [ -s \"$HOME/.nvm/nvm.sh\" ]; then |\n|\nsource \"$HOME/.nvm/nvm.sh\" |\n|\nnvm use 22.16.0 >/dev/null 2>&1 || { |\n|\nlog \"Installing Node.js 22.16.0...\" |\n|\nnvm install 22.16.0 |\n|\nnvm use 22.16.0 |\n|\n} |\n|\nelif [ -s \"/usr/local/share/nvm/nvm.sh\" ]; then |\n|\nsource \"/usr/local/share/nvm/nvm.sh\" |\n|\nnvm use 22.16.0 >/dev/null 2>&1 || { |\n|\nlog \"Installing Node.js 22.16.0...\" |\n|\nnvm install 22.16.0 |\n|\nnvm use 22.16.0 |\n|\n} |\n|\nfi |\n|\n|\n|\nNODE_VERSION=$(node --version) |\n|\nlog \"Using Node.js: $NODE_VERSION\" |\n|\n} |\n|\n|\n|\nlog \"=== Processing Issue #$ISSUE_NUMBER Locally ===\" |\n|\nlog \"Title: $ISSUE_TITLE\" |\n|\nlog \"Author: $ISSUE_AUTHOR\" |\n|\nlog \"Command: $ISSUE_COMMAND\" |\n|\nlog \"Branch will be: $BRANCH_NAME\" |\n|\n|\n|\n# Get the default branch |\n|\nDEFAULT_BRANCH=$(get_default_branch) |\n|\nlog \"Repository default branch: $DEFAULT_BRANCH\" |\n|\n|\n|\n# First, acknowledge the issue |\n|\nACKNOWLEDGMENT=\"👋 Hello @$ISSUE_AUTHOR! I'm Claude, and I'll help you with this issue. |\n|\n|\n|\nI'm analyzing your request and will create a branch to work on it locally. Here's what I understand: |\n|\n|\n|\n**Request**: $ISSUE_COMMAND |\n|\n|\n|\nI'll start working on this and provide updates as I progress. Creating branch \\`$BRANCH_NAME\\` from \\`$DEFAULT_BRANCH\\`...\" |\n|\n|\n|\nadd_issue_comment \"$ACKNOWLEDGMENT\" |\n|\n|\n|\n# Change to project root |\n|\ncd \"$PROJECT_ROOT\" |\n|\n|\n|\n# Clean up any stale git state |\n|\nlog \"Cleaning up git state\" |\n|\ngit reset --hard HEAD 2>/dev/null || true |\n|\ngit clean -fd 2>/dev/null || true |\n|\ngit checkout \"$DEFAULT_BRANCH\" 2>/dev/null || true |\n|\n|\n|\n# Configure Git for GitHub operations |\n|\nlog \"Configuring Git authentication\" |\n|\ngit config --global user.name \"Claude Bot\" |\n|\ngit config --global user.email \"claude-bot@anthropic.com\" |\n|\n|\n|\n# Clear any existing credential helpers |\n|\ngit config --global --unset-all credential.helper || true |\n|\n|\n|\n# Set up token-based authentication |\n|\nif [ -n \"$GITHUB_TOKEN\" ]; then |\n|\nlog \"Using GITHUB_TOKEN for authentication\" |\n|\n# Create credential helper that returns the token |\n|\ngit config --global credential.helper \"!f() { |\n|\nif [ \\\"\\$1\\\" = \\\"get\\\" ]; then |\n|\necho \\\"username=token\\\" |\n|\necho \\\"password=$GITHUB_TOKEN\\\" |\n|\nfi |\n|\n}; f\" |\n|\n|\n|\n# Also set the remote URL to use token authentication |\n|\nCURRENT_REMOTE=$(git config --get remote.origin.url || echo \"\") |\n|\nif [[ \"$CURRENT_REMOTE\" == *\"github.com\"* ]] && [[ \"$CURRENT_REMOTE\" != *\"@\"* ]]; then |\n|\n# Convert https://github.com/... to https://token:TOKEN@github.com/... |\n|\nNEW_REMOTE=$(echo \"$CURRENT_REMOTE\" | sed \"s|https://github.com/|https://token:$GITHUB_TOKEN@github.com/|\") |\n|\ngit remote set-url origin \"$NEW_REMOTE\" |\n|\nlog \"Updated remote URL for token auth\" |\n|\nfi |\n|\nelse |\n|\nlog \"Using gh CLI for authentication\" |\n|\ngit config --global credential.helper \"!gh auth git-credential\" |\n|\nfi |\n|\n|\n|\n# Create and switch to the branch |\n|\nlog \"Creating branch: $BRANCH_NAME\" |\n|\n|\n|\n# Clean up ALL existing claude-bot branch references (not just current) |\n|\nlog \"Cleaning up all claude-bot branch references\" |\n|\ngit branch -D $(git branch | grep \"claude-bot\" | xargs) 2>/dev/null || true |\n|\ngit branch -d -r $(git branch -r | grep \"origin/claude-bot\" | xargs) 2>/dev/null || true |\n|\nrm -rf \".git/refs/remotes/origin/claude-bot\" 2>/dev/null || true |\n|\nrm -f \".git/refs/remotes/origin/claude-bot\"* 2>/dev/null || true |\n|\nfind .git -name \"*.lock\" -delete 2>/dev/null || true |\n|\n|\n|\n# Ensure git directories have proper permissions |\n|\nmkdir -p .git/logs/refs/heads .git/refs/remotes/origin |\n|\nchmod -R 755 .git/logs .git/refs 2>/dev/null || true |\n|\nchown -R $(whoami):$(whoami) .git/logs .git/refs 2>/dev/null || true |\n|\n|\n|\n# First switch away from default branch to avoid fetch conflicts |\n|\ngit checkout HEAD~0 2>/dev/null || true |\n|\n|\n|\n# Fetch updates from origin |\n|\nlog \"Fetching updates from origin\" |\n|\ngit fetch origin || { |\n|\nlog \"Error: Could not fetch from origin. Check GitHub authentication.\" |\n|\nadd_issue_comment \"❌ Error: Could not fetch from GitHub repository. Please check authentication setup.\" |\n|\nexit 1 |\n|\n} |\n|\n|\n|\n# Switch to default branch first, then create new branch |\n|\ngit checkout \"$DEFAULT_BRANCH\" || { |\n|\nlog \"Error: Could not switch to default branch $DEFAULT_BRANCH\" |\n|\nadd_issue_comment \"❌ Error: Could not switch to default branch \\`$DEFAULT_BRANCH\\`.\" |\n|\nexit 1 |\n|\n} |\n|\n|\n|\ngit checkout -b \"$BRANCH_NAME\" || { |\n|\nlog \"Error: Could not create branch $BRANCH_NAME\" |\n|\nadd_issue_comment \"❌ Error: Could not create branch \\`$BRANCH_NAME\\`. Please check for permission issues.\" |\n|\nexit 1 |\n|\n} |\n|\n|\n|\n# Update issue with execution status |\n|\nEXECUTION_COMMENT=\"🚀 **Starting work on branch \\`$BRANCH_NAME\\`** |\n|\n|\n|\nI'm now working on your request locally with Claude Code. I'll implement the changes and run tests before creating a pull request. |\n|\n|\n|\n**Current status**: Analyzing request and implementing changes...\" |\n|\n|\n|\nadd_issue_comment \"$EXECUTION_COMMENT\" |\n|\n|\n|\n# Set up Node.js environment |\n|\nsetup_node_env |\n|\n|\n|\n# Create a direct command prompt for Claude Code |\n|\nCLAUDE_PROMPT_FILE=\"/tmp/claude_issue_${ISSUE_NUMBER}_prompt.txt\" |\n|\ncat > \"$CLAUDE_PROMPT_FILE\" << EOF |\n|\nYou are working on GitHub issue #$ISSUE_NUMBER: \"$ISSUE_TITLE\" within this repository. |\n|\n|\n|\nREQUEST: $ISSUE_COMMAND |\n|\n|\n|\nI need you to implement this request now. Here's what you should do: |\n|\n|\n|\n1. Read the project structure and understand the codebase |\n|\n2. Implement the specific request above |\n|\n3. Follow existing patterns and conventions |\n|\n4. Create or modify files as needed |\n|\n5. Do not create placeholder files - implement actual functionality |\n|\n|\n|\nThe current branch is: $BRANCH_NAME |\n|\n|\n|\nStart by exploring the codebase and then implement the request completely. |\n|\nEOF |\n|\n|\n|\nlog \"Launching Claude Code with issue prompt...\" |\n|\n|\n|\n# Set up environment variables for Claude Code automation |\n|\nexport CLAUDE_PROMPT_FILE=\"$CLAUDE_PROMPT_FILE\" |\n|\nexport CLAUDE_AUTOMODE=\"true\" |\n|\nexport CI=\"true\" |\n|\nexport ANTHROPIC_AUTO_APPROVE=\"true\" |\n|\nexport CLAUDE_NON_INTERACTIVE=\"true\" |\n|\n|\n|\n# Run Claude Code with the prompt file |\n|\nlog \"Executing Claude Code in automated mode...\" |\n|\nCLAUDE_EXIT_CODE=0 |\n|\n|\n|\n# Try the simplest approach first - just use --print for text generation |\n|\nlog \"Using Claude Code --print for text generation...\" |\n|\ntimeout 960 claude --print --dangerously-skip-permissions < \"$CLAUDE_PROMPT_FILE\" > \"/tmp/claude_output_${ISSUE_NUMBER}.txt\" 2>&1 || CLAUDE_EXIT_CODE=$? |\n|\n|\n|\n# If that fails, try a simple interactive approach with timeout |\n|\nif [ $CLAUDE_EXIT_CODE -ne 0 ]; then |\n|\nlog \"Text generation failed, trying interactive approach with extended timeout...\" |\n|\nCLAUDE_EXIT_CODE=0 |\n|\n|\n|\n# Simple approach: send prompt and exit command with extended timeout |\n|\ntimeout 1920 bash -c \" |\n|\n{ |\n|\ncat '$CLAUDE_PROMPT_FILE' |\n|\necho '' |\n|\necho 'Please complete this task and implement the changes needed.' |\n|\necho '' |\n|\n# Give extended time for processing then send exit |\n|\nsleep 160 |\n|\necho 'exit' |\n|\n} | claude --dangerously-skip-permissions |\n|\n\" || CLAUDE_EXIT_CODE=$? |\n|\nfi |\n|\n|\n|\n# Check if we got any output from the --print method |\n|\nif [ -s \"/tmp/claude_output_${ISSUE_NUMBER}.txt\" ]; then |\n|\nlog \"Claude Code --print generated output, creating response file\" |\n|\n|\n|\n# Create a response file with the generated content |\n|\necho \"# Claude Code Response for Issue #$ISSUE_NUMBER\" > \"CLAUDE_RESPONSE_${ISSUE_NUMBER}.md\" |\n|\necho \"\" >> \"CLAUDE_RESPONSE_${ISSUE_NUMBER}.md\" |\n|\necho \"**Original Request**: $ISSUE_COMMAND\" >> \"CLAUDE_RESPONSE_${ISSUE_NUMBER}.md\" |\n|\necho \"\" >> \"CLAUDE_RESPONSE_${ISSUE_NUMBER}.md\" |\n|\necho \"**Generated Response**:\" >> \"CLAUDE_RESPONSE_${ISSUE_NUMBER}.md\" |\n|\necho \"\" >> \"CLAUDE_RESPONSE_${ISSUE_NUMBER}.md\" |\n|\ncat \"/tmp/claude_output_${ISSUE_NUMBER}.txt\" >> \"CLAUDE_RESPONSE_${ISSUE_NUMBER}.md\" |\n|\n|\n|\ngit add \"CLAUDE_RESPONSE_${ISSUE_NUMBER}.md\" |\n|\n|\n|\n# Clean up temp file |\n|\nrm -f \"/tmp/claude_output_${ISSUE_NUMBER}.txt\" |\n|\n|\n|\n# Reset exit code since we got output |\n|\nCLAUDE_EXIT_CODE=0 |\n|\n|\n|\nelif [ $CLAUDE_EXIT_CODE -ne 0 ]; then |\n|\nlog \"Claude Code execution failed with exit code: $CLAUDE_EXIT_CODE\" |\n|\n|\n|\n# Determine the type of failure |\n|\nif [ $CLAUDE_EXIT_CODE -eq 124 ]; then |\n|\nFAILURE_REASON=\"Claude Code execution timed out\" |\n|\nelif [ $CLAUDE_EXIT_CODE -eq 1 ]; then |\n|\nFAILURE_REASON=\"Claude Code encountered an error during execution\" |\n|\nelse |\n|\nFAILURE_REASON=\"Claude Code failed with exit code $CLAUDE_EXIT_CODE\" |\n|\nfi |\n|\n|\n|\n# Create a detailed fallback implementation file |\n|\necho \"# Implementation Status for Issue #$ISSUE_NUMBER\" > \"IMPLEMENTATION_ISSUE_${ISSUE_NUMBER}.md\" |\n|\necho \"\" >> \"IMPLEMENTATION_ISSUE_${ISSUE_NUMBER}.md\" |\n|\necho \"**Original Request**: $ISSUE_COMMAND\" >> \"IMPLEMENTATION_ISSUE_${ISSUE_NUMBER}.md\" |\n|\necho \"\" >> \"IMPLEMENTATION_ISSUE_${ISSUE_NUMBER}.md\" |\n|\necho \"**Status**: $FAILURE_REASON\" >> \"IMPLEMENTATION_ISSUE_${ISSUE_NUMBER}.md\" |\n|\necho \"**Timestamp**: $(date)\" >> \"IMPLEMENTATION_ISSUE_${ISSUE_NUMBER}.md\" |\n|\necho \"**Branch**: \\`$BRANCH_NAME\\`\" >> \"IMPLEMENTATION_ISSUE_${ISSUE_NUMBER}.md\" |\n|\necho \"\" >> \"IMPLEMENTATION_ISSUE_${ISSUE_NUMBER}.md\" |\n|\necho \"**Next Steps**:\" >> \"IMPLEMENTATION_ISSUE_${ISSUE_NUMBER}.md\" |\n|\necho \"- Check the logs in \\`$LOG_FILE\\`\" >> \"IMPLEMENTATION_ISSUE_${ISSUE_NUMBER}.md\" |\n|\necho \"- Verify Claude Code is properly installed and configured\" >> \"IMPLEMENTATION_ISSUE_${ISSUE_NUMBER}.md\" |\n|\necho \"- Consider manual implementation or re-running with different parameters\" >> \"IMPLEMENTATION_ISSUE_${ISSUE_NUMBER}.md\" |\n|\n|\n|\ngit add \"IMPLEMENTATION_ISSUE_${ISSUE_NUMBER}.md\" |\n|\n|\n|\n# Also notify in the issue comment |\n|\nadd_issue_comment \"⚠️ **Claude Code Execution Failed** |\n|\n|\n|\n$FAILURE_REASON |\n|\n|\n|\nI've created a status file on branch \\`$BRANCH_NAME\\` with details. Please check the logs or try manual implementation.\" |\n|\n|\n|\n# Clean up temp files |\n|\nrm -f \"/tmp/claude_output_${ISSUE_NUMBER}.txt\" |\n|\nfi |\n|\n|\n|\n# Clean up prompt file |\n|\nrm -f \"$CLAUDE_PROMPT_FILE\" |\n|\n|\n|\n# Check what changes were made |\n|\nlog \"Checking for changes...\" |\n|\nif git diff --quiet && git diff --staged --quiet; then |\n|\nlog \"No changes were made by Claude Code\" |\n|\n|\n|\nFINAL_COMMENT=\"⚠️ **Implementation Incomplete** |\n|\n|\n|\nI created a branch and ran Claude Code, but no changes were generated. The request was: |\n|\n|\n|\n> $ISSUE_COMMAND |\n|\n|\n|\nThis might mean: |\n|\n- The request needs more specific details |\n|\n- Claude Code encountered an issue during execution |\n|\n- Manual implementation is required |\n|\n|\n|\nPlease check the branch \\`$BRANCH_NAME\\` and provide more details if needed, or implement the changes manually.\" |\n|\n|\n|\nelse |\n|\nlog \"Changes detected, committing and creating PR...\" |\n|\n|\n|\n# Add all changes |\n|\ngit add -A |\n|\n|\n|\n# Commit the changes |\n|\ngit commit -m \"Implement #$ISSUE_NUMBER: $ISSUE_TITLE |\n|\n|\n|\n$ISSUE_COMMAND |\n|\n|\n|\n🤖 Implemented locally with Claude Code\" || { |\n|\nlog \"Error: Could not commit changes\" |\n|\nadd_issue_comment \"❌ Error: Could not commit changes to branch \\`$BRANCH_NAME\\`.\" |\n|\nexit 1 |\n|\n} |\n|\n|\n|\n# Push the branch |\n|\nlog \"Pushing branch to origin\" |\n|\ngit push origin \"$BRANCH_NAME\" || { |\n|\nlog \"Error: Could not push branch $BRANCH_NAME\" |\n|\nadd_issue_comment \"❌ Error: Could not push branch \\`$BRANCH_NAME\\` to GitHub. Please check permissions.\" |\n|\nexit 1 |\n|\n} |\n|\n|\n|\n# Create pull request |\n|\nlog \"Creating pull request\" |\n|\nPR_URL=$(gh pr create \\ |\n|\n--repo \"$REPO\" \\ |\n|\n--title \"Implement #$ISSUE_NUMBER: $ISSUE_TITLE\" \\ |\n|\n--body \"Fixes #$ISSUE_NUMBER |\n|\n|\n|\n**Original Request**: $ISSUE_COMMAND |\n|\n|\n|\n**Implementation**: This PR was automatically generated by Claude Code running locally in response to the GitHub issue. |\n|\n|\n|\n🤖 Implemented locally with Claude Code\" \\ |\n|\n--base \"$DEFAULT_BRANCH\" \\ |\n|\n--head \"$BRANCH_NAME\" 2>&1) || { |\n|\nlog \"Error creating pull request: $PR_URL\" |\n|\nadd_issue_comment \"❌ Error: Could not create pull request. Branch \\`$BRANCH_NAME\\` has been pushed with changes.\" |\n|\nexit 1 |\n|\n} |\n|\n|\n|\n# Clean up Claude response file after successful PR creation |\n|\nif [ -f \"CLAUDE_RESPONSE_${ISSUE_NUMBER}.md\" ]; then |\n|\nlog \"Removing Claude response file after successful PR creation\" |\n|\ngit rm \"CLAUDE_RESPONSE_${ISSUE_NUMBER}.md\" |\n|\ngit commit -m \"Clean up Claude response file |\n|\n|\n|\n🤖 Automated cleanup after PR creation\" || { |\n|\nlog \"Warning: Could not remove Claude response file\" |\n|\n} |\n|\n|\n|\n# Push the cleanup commit |\n|\ngit push origin \"$BRANCH_NAME\" || { |\n|\nlog \"Warning: Could not push cleanup commit\" |\n|\n} |\n|\nfi |\n|\n|\n|\nFINAL_COMMENT=\"✅ **Implementation Complete!** |\n|\n|\n|\nI've successfully implemented the requested changes using Claude Code and created a pull request: |\n|\n|\n|\n**Pull Request**: $PR_URL |\n|\n**Branch**: \\`$BRANCH_NAME\\` |\n|\n|\n|\nThe implementation has been completed locally and is ready for review. Please check the PR for details on what was implemented.\" |\n|\nfi |\n|\n|\n|\nadd_issue_comment \"$FINAL_COMMENT\" |\n|\nlog \"Issue #$ISSUE_NUMBER processing completed successfully\" |\n|\n|\n|\nexit 0 |", "url": "https://wpnews.pro/news/example-of-claude-code-git-integration", "canonical_source": "https://gist.github.com/mosgaragedev/e3f995cf0101c2fc7f4317bf3b4d65bc", "published_at": "2026-08-28 00:03:59+00:00", "updated_at": "2026-08-28 00:18:19.682545+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents", "ai-tools"], "entities": ["Claude Code", "GitHub", "Anthropic"], "alternates": {"html": "https://wpnews.pro/news/example-of-claude-code-git-integration", "markdown": "https://wpnews.pro/news/example-of-claude-code-git-integration.md", "text": "https://wpnews.pro/news/example-of-claude-code-git-integration.txt", "jsonld": "https://wpnews.pro/news/example-of-claude-code-git-integration.jsonld"}}