{
  "name": "v3.6",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "claude-comment-webhook",
        "options": {}
      },
      "id": "181e695e-f50a-4e4c-be6a-b0c6e8567760",
      "name": "GitLab Comment Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -1840,
        -368
      ]
    },
    {
      "parameters": {
        "jsCode": "// Process GitLab comment webhook and detect @claude-code mentions\nconst webhookData = $('GitLab Comment Webhook').first().json.body;\n\n// Only process issue comment events\nif (webhookData.object_kind !== 'note' || webhookData.object_attributes?.noteable_type !== 'Issue') {\n  return [];\n}\n\nconst comment = webhookData.object_attributes.note;\nconst author = webhookData.user;\nconst issue = webhookData.issue;\n\n// Check if comment mentions @claude-code\nif (!comment.includes('@claude-code')) {\n  return [];\n}\n\n// Extract command text (everything after @claude-code) - use same pattern as other workflows\nconst commandText = comment.replace(/@claude-code\\s*/, '').trim();\nconst commandTextShort = commandText.length > 50 ? commandText.substring(0, 47) + '...' : commandText;\n\n// Build context matching other workflows\nreturn [{\n  json: {\n    commandText: commandText,\n    commandTextShort: commandTextShort,\n    issueTitle: issue.title,\n    issueId: issue.iid,\n    issueDescription: issue.description,\n    issueUrl: issue.url,\n    issueAuthor: author.name,\n    projectId: webhookData.project.id,\n    projectName: webhookData.project.name,\n    projectPath: webhookData.project.path,\n    projectNamespace: webhookData.project.path_with_namespace,\n    commentId: webhookData.object_attributes.id,\n    commentAuthor: author.name,\n    commentUrl: webhookData.object_attributes.url,\n    branchName: `claude-${issue.iid}-${webhookData.object_attributes.id}`,\n    timestamp: new Date().toISOString()\n  }\n}];"
      },
      "id": "3085ff04-7c67-4f81-9527-4cd49d4b4400",
      "name": "Process Comment",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1504,
        -368
      ]
    },
    {
      "parameters": {
        "command": "=cd /workspace/{{ $('Process Comment').item.json.projectName }} && git checkout main && git pull origin main && git reset --hard HEAD && git clean -fd"
      },
      "id": "08c48068-82d4-4c7a-a6d0-3007f24304d5",
      "name": "Workspace Cleanup",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [
        -1280,
        -368
      ]
    },
    {
      "parameters": {
        "command": "=cd /workspace/{{ $('Process Comment').item.json.projectName }} && git checkout -b {{ $('Process Comment').item.json.branchName }}"
      },
      "id": "ca1246ec-7f82-45b9-bfa3-03b63ab39e57",
      "name": "Create Branch",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [
        -1056,
        -368
      ]
    },
    {
      "parameters": {
        "command": "=cd /workspace/{{ $('Process Comment').item.json.projectName }} && git config user.name \"{{ $('Process Comment').item.json.commentAuthor }}\" && git config user.email \"claude-code@automated\" && echo '{{ $('Prepare Prompt').item.json.implementPromptEscaped }}' | claude --dangerously-skip-permissions"
      },
      "id": "751dede3-a05f-4c1f-b171-bb25e959a9f3",
      "name": "Implement Code",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [
        -1280,
        -144
      ]
    },
    {
      "parameters": {
        "command": "=cd /workspace/{{ $('Process Comment').item.json.projectName }} && git add . && git commit -m \"Implement: {{ $('Process Comment').item.json.issueTitle }}\""
      },
      "id": "13c96190-7a78-4519-9a09-350621963656",
      "name": "Commit Initial Implementation",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [
        -1056,
        -144
      ]
    },
    {
      "parameters": {
        "command": "=cd /workspace/{{ $('Process Comment').item.json.projectName }} && echo '{{ $('Prepare Validation Prompt').item.json.validationPromptEscaped }}' | claude --dangerously-skip-permissions"
      },
      "id": "25623a34-0a84-46ea-8fdf-12de07804bb5",
      "name": "Validate and Fix Build",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [
        -1280,
        64
      ]
    },
    {
      "parameters": {
        "command": "=  cd /workspace/{{ $('Process Comment').item.json.projectName }} && git add . && if git diff --cached --quiet; then echo \"No changes to commit\"; else git commit -m \"Fix: Address build errors and syntax issues\"; fi && git push -u origin {{ $('Process Comment').item.json.branchName }}"
      },
      "id": "6b61c6d6-b0d0-479d-9862-7770c6bb3cee",
      "name": "Commit Fixes and Push",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [
        -1056,
        64
      ]
    },
    {
      "parameters": {
        "command": "=cd /workspace/{{ $('Process Comment').item.json.projectName }} && glab mr create --title \"Claude Implementation: {{ $('Process Comment').item.json.commandTextShort }}\" --description \"Auto-implementation by Claude Code for issue #{{ $('Process Comment').item.json.issueId }}\\n\\nOriginal request: {{ $('Process Comment').item.json.commandText }}\\n\\nImplemented via @claude-code automation.\" --source-branch {{ $('Process Comment').item.json.branchName }} --target-branch main"
      },
      "id": "b1de4a07-d652-4045-a91e-47bc4f13558d",
      "name": "Create MR",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [
        -1504,
        288
      ]
    },
    {
      "parameters": {
        "jsCode": "// Create implementation prompt with full issue context\nconst context = $('Process Comment').item.json;\n\nconst implementPrompt = `GitLab Issue Implementation Request\n\nOriginal Issue:\nTitle: ${context.issueTitle}\nDescription: ${context.issueDescription}\nAuthor: ${context.issueAuthor}\nURL: ${context.issueUrl}\n\nComment from ${context.commentAuthor}:\n${context.commandText}\n\nCommand Type: @claude-code\n\nPlease follow these steps:\n\n1. DESIGN FIRST: Create a design preview/mockup of what you're about to build:\n   - Save a design preview as 'design-preview.png' in the project root\n   - If you cannot generate an image, create 'design-description.txt' with detailed UI description:\n     * What UI components will be created\n     * How they will be laid out\n     * Key visual elements and styling\n     * User interactions and flow\n     * Color scheme and visual hierarchy\n\n2. IMPLEMENT: Then implement the requested changes following your design\n   - Focus on implementing the functionality described in the issue and comment\n   - Follow the design you created in step 1\n   - Ensure the implementation matches your design preview\n\nThe workflow will handle committing and pushing your changes automatically.`;\n\n// Escape the prompt for shell execution\nconst implementPromptEscaped = implementPrompt.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"'\\\"'\\\"'\");\n\nreturn [{\n  json: {\n    ...context,\n    implementPrompt: implementPrompt,\n    implementPromptEscaped: implementPromptEscaped\n  }\n}];"
      },
      "id": "92746059-1d00-4949-9900-baa268746649",
      "name": "Prepare Prompt",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1504,
        -144
      ]
    },
    {
      "parameters": {
        "jsCode": "// Create Flutter-specific validation prompt with retry limit\nconst context = $('Process Comment').item.json;\n\nconst validationPrompt = `Flutter Error Detection and Fix\n\nCRITICAL: The initial implementation has been committed. Your job is to detect and fix ONLY actual Flutter errors.\n\nREQUIRED STEPS:\n1. Run: flutter analyze | grep \"error \u2022\" to find all errors\n2. IF errors are found:\n   - Analyze each error message carefully\n   - Fix ONLY the specific errors shown (missing imports, syntax errors, type errors, etc.)\n   - Do NOT change working code or modify structure\n   - Do NOT reformat or add features\n3. After fixing, run: flutter analyze | grep \"error \u2022\" again to verify errors are gone\n4. Repeat steps 1-3 until no errors remain OR maximum 3 attempts reached\n5. IF no errors found initially, do nothing - leave code as is\n\nRETRY LIMIT: Maximum 3 fix attempts. If errors persist after 3 attempts:\n- Stop trying to fix\n- Leave a comment in the code explaining what errors could not be fixed\n- Do not continue the loop\n\nIMPORTANT: \n- Use \"flutter analyze | grep \\\"error \u2022\\\"\" command to detect errors\n- Only fix actual Flutter analysis errors\n- Do not modify working code\n- Verify fixes by re-running the error detection command\n- Stop when no errors remain OR after 3 attempts\n- Prevent infinite loops by respecting the retry limit`;\n\n// Escape the prompt for shell execution\nconst validationPromptEscaped = validationPrompt.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"'\\\"'\\\"'\");\n\nreturn [{\n  json: {\n    ...context,\n    validationPrompt: validationPrompt,\n    validationPromptEscaped: validationPromptEscaped\n  }\n}];"
      },
      "id": "13059283-b888-462c-bfac-443ea7cbe68a",
      "name": "Prepare Validation Prompt",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1504,
        64
      ]
    },
    {
      "parameters": {
        "jsCode": "// Extract MR URL from glab output and prepare success comment\nconst mrOutput = $('Create MR').item.json;\nconst context = $('Process Comment').item.json;\n\nlet mrUrl = '';\nif (mrOutput.exitCode === 0 && mrOutput.stdout) {\n  // Extract MR URL from glab output\n  const urlMatch = mrOutput.stdout.match(/https:\\/\\/[^\\s]+/g);\n  if (urlMatch && urlMatch.length > 0) {\n    mrUrl = urlMatch[urlMatch.length - 1]; // Get the last URL which should be the MR URL\n  }\n}\n\n// Create success comment\nconst successComment = `\u2705 **Implementation Complete!**\n\nI've successfully implemented your request: \"${context.commandTextShort}\"\n\n**Branch Created:** \\`${context.branchName}\\`\n${mrUrl ? `**Merge Request:** ${mrUrl}` : '**Note:** Merge request creation may have failed - please check manually.'}\n\n**What was implemented:**\nThe changes have been committed to the feature branch and are ready for review.\n\n---\n*\ud83e\udd16 Automated response via @claude-code*`;\n\nconst commentEscaped = successComment.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"'\\\"'\\\"'\");\n\nreturn [{\n  json: {\n    ...context,\n    mrUrl: mrUrl,\n    successComment: successComment,\n    commentEscaped: commentEscaped,\n    mrExitCode: mrOutput.exitCode,\n    mrOutput: mrOutput.stdout || mrOutput.stderr\n  }\n}];"
      },
      "id": "c678f231-52a9-4e61-82c0-296a62e0d691",
      "name": "Prepare Success Comment",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1280,
        288
      ]
    },
    {
      "parameters": {
        "operation": "createComment",
        "owner": "={{ $('Process Comment').item.json.projectNamespace.split('/')[0] }}",
        "repository": "={{ $('Process Comment').item.json.projectName }}",
        "issueNumber": "={{ $('Process Comment').item.json.issueId }}",
        "body": "={{ $('Prepare Success Comment').item.json.successComment }}"
      },
      "id": "9e60d57b-ea4e-4fe3-a914-c1017b594201",
      "name": "Post Success Comment",
      "type": "n8n-nodes-base.gitlab",
      "typeVersion": 1,
      "position": [
        -1056,
        288
      ],
      "credentials": {
        "gitlabApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "content": "## Preparation",
        "height": 192,
        "width": 816,
        "color": 5
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1696,
        -432
      ],
      "typeVersion": 1,
      "id": "33b32a85-0102-4aea-a0b5-853574f5829a",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "content": "## Implementation",
        "height": 240,
        "width": 816,
        "color": 3
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1696,
        -240
      ],
      "typeVersion": 1,
      "id": "35c79c99-fceb-480d-bd6c-b1a417d52d77",
      "name": "Sticky Note1"
    },
    {
      "parameters": {
        "content": "## Review\n## and Fix",
        "height": 208,
        "width": 816,
        "color": 6
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1696,
        0
      ],
      "typeVersion": 1,
      "id": "86013b29-24a2-42fc-a36b-d3649cdec866",
      "name": "Sticky Note2"
    },
    {
      "parameters": {
        "content": "## Create MR\n## and Notify",
        "height": 224,
        "width": 816,
        "color": 5
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1696,
        208
      ],
      "typeVersion": 1,
      "id": "bbf21137-c7fe-45ef-8edd-500349db68c1",
      "name": "Sticky Note3"
    }
  ],
  "connections": {
    "GitLab Comment Webhook": {
      "main": [
        [
          {
            "node": "Process Comment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Comment": {
      "main": [
        [
          {
            "node": "Workspace Cleanup",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Workspace Cleanup": {
      "main": [
        [
          {
            "node": "Create Branch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Branch": {
      "main": [
        [
          {
            "node": "Prepare Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Prompt": {
      "main": [
        [
          {
            "node": "Implement Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Implement Code": {
      "main": [
        [
          {
            "node": "Commit Initial Implementation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Commit Initial Implementation": {
      "main": [
        [
          {
            "node": "Prepare Validation Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Validation Prompt": {
      "main": [
        [
          {
            "node": "Validate and Fix Build",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate and Fix Build": {
      "main": [
        [
          {
            "node": "Commit Fixes and Push",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Commit Fixes and Push": {
      "main": [
        [
          {
            "node": "Create MR",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create MR": {
      "main": [
        [
          {
            "node": "Prepare Success Comment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Success Comment": {
      "main": [
        [
          {
            "node": "Post Success Comment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "83760934-05b9-4731-be91-a69594261028",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "KRzL0kx7EIwEWlLm",
  "tags": []
}