The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "AIDP - Main Workflow v8",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "aidp-trigger",
"responseMode": "responseNode",
"options": {}
},
"id": "webhook-trigger",
"name": "Jira Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
240,
300
]
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// ============================================\n// AIDP v8 - Smart Issue Parser\n// ============================================\n\n// Get issue from webhook (handles both formats)\nconst issue = $input.item.json.body?.issue || $input.item.json.issue;\nif (!issue) throw new Error('No issue found in webhook payload');\n\nconst fields = issue.fields || {};\nconst jiraKey = issue.key;\nconst projectKey = jiraKey.split('-')[0];\nconst summary = fields.summary || '';\n\n// ============================================\n// EXTRACT DESCRIPTION\n// ============================================\nlet description = '';\n\nif (typeof fields.description === 'string') {\n description = fields.description;\n} else if (fields.description?.content) {\n const extractText = (node) => {\n if (!node) return '';\n if (node.type === 'text') return node.text || '';\n if (node.content) return node.content.map(extractText).join('');\n return '';\n };\n description = fields.description.content.map(extractText).join('\\n');\n}\n\n// ============================================\n// KNOWN REPOS MAPPING\n// ============================================\nconst KNOWN_REPOS = {\n 'SCRUM': { url: 'https://github.com/andresKillem/vidaconvida', branch: 'main' },\n 'VIDA': { url: 'https://github.com/andresKillem/vidaconvida', branch: 'main' },\n 'TEST': { url: 'https://github.com/andresKillem/aidp-test-repo', branch: 'main' }\n};\n\n// ============================================\n// EXTRACT REPO URL FROM DESCRIPTION\n// ============================================\nlet repoUrl = null;\nlet baseBranch = 'main';\n\n// Multiple patterns to find GitHub URL\nconst patterns = [\n /https:\\/\\/github\\.com\\/[\\w.-]+\\/[\\w.-]+/gi,\n /github\\.com\\/[\\w.-]+\\/[\\w.-]+/gi\n];\n\nfor (const pattern of patterns) {\n const matches = description.match(pattern);\n if (matches && matches.length > 0) {\n repoUrl = matches[0];\n if (!repoUrl.startsWith('http')) repoUrl = 'https://' + repoUrl;\n repoUrl = repoUrl.replace(/\\.git$/, '').replace(/\\|.*$/, '').replace(/\\]$/, '');\n break;\n }\n}\n\n// Fallback to project mapping\nif (!repoUrl) {\n const mapping = KNOWN_REPOS[projectKey] || KNOWN_REPOS['SCRUM'];\n repoUrl = mapping.url;\n baseBranch = mapping.branch;\n}\n\n// ============================================\n// EXTRACT BASE BRANCH FROM DESCRIPTION\n// ============================================\nconst branchMatch = description.match(/(?:branch|base)[:\\s]+(\\w+)/i);\nif (branchMatch) {\n baseBranch = branchMatch[1];\n}\n\n// Auto-detect branch for known repos (all use main now)\nif (repoUrl.includes('vidaconvida')) baseBranch = 'main';\nif (repoUrl.includes('aidp-test-repo')) baseBranch = 'main';\n\n// ============================================\n// EXTRACT ACCEPTANCE CRITERIA\n// ============================================\nlet acceptanceCriteria = '';\nconst acMatch = description.match(/acceptance\\s*criteria[:\\s]*([\\s\\S]*?)(?=h2\\.|##|$)/i);\nif (acMatch) acceptanceCriteria = acMatch[1].trim();\n\n// ============================================\n// GENERATE BRANCH NAME\n// ============================================\nconst slugify = (text) => text.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').substring(0, 50);\nconst branchName = `ai/${jiraKey.toLowerCase()}-${slugify(summary)}`;\n\n// ============================================\n// EXTRACT OWNER AND REPO FROM URL\n// ============================================\nconst repoMatch = repoUrl.match(/github\\.com\\/([^/]+)\\/([^/]+)/);\nconst owner = repoMatch ? repoMatch[1] : 'andresKillem';\nconst repo = repoMatch ? repoMatch[2].replace('.git', '').replace(/[\\|\\]].*$/, '') : 'vidaconvida';\n\n// ============================================\n// DEBUG INFO\n// ============================================\nconst debugInfo = {\n descriptionLength: description.length,\n descriptionPreview: description.substring(0, 200),\n foundRepoInDescription: description.includes('github.com'),\n extractedUrl: repoUrl\n};\n\nreturn {\n jiraKey,\n projectKey,\n jiraUrl: `https://polarpipeline.atlassian.net/browse/${jiraKey}`,\n summary,\n description,\n acceptanceCriteria,\n priority: fields.priority?.name || 'Medium',\n reporter: fields.reporter?.displayName || 'Unknown',\n repoUrl,\n owner,\n repo,\n baseBranch,\n branchName,\n debugInfo\n};"
},
"id": "parse-issue",
"name": "Parse Issue Data",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
460,
300
]
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const data = $input.item.json;\n\nconst prompt = `# Task: ${data.summary}\n\n## Context\n- **Repository**: ${data.repoUrl}\n- **Base Branch**: ${data.baseBranch}\n- **Feature Branch**: ${data.branchName}\n- **Jira Issue**: [${data.jiraKey}](${data.jiraUrl})\n\n## Requirements\n${data.description}\n\n## Acceptance Criteria\n${data.acceptanceCriteria || 'Use best judgment based on the requirements above.'}\n\n## Instructions\n1. Explore the codebase first\n2. Plan before coding\n3. Implement the feature\n4. Commit with conventional format (feat/fix/chore)\n5. Push to feature branch\n\n## Constraints\n- DO NOT modify unrelated files\n- DO NOT create a PR - only commit and push\n- Keep changes minimal and focused`;\n\nconst promptB64 = Buffer.from(prompt).toString('base64');\n\nreturn { ...data, prompt, promptB64 };"
},
"id": "build-prompt",
"name": "Build Prompt",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
680,
300
]
},
{
"parameters": {
"command": "={{ 'docker exec aidp-claude-executor /usr/local/bin/aidp-executor \"' + $json.repoUrl + '\" \"' + $json.branchName + '\" \"' + $json.promptB64 + '\" \"' + $json.jiraKey + '\" \"' + $json.baseBranch + '\"' }}"
},
"id": "execute-claude",
"name": "Execute Claude Code",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
900,
300
]
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const input = $input.item.json;\nconst stdout = input.stdout || '';\nconst stderr = input.stderr || '';\nlet result;\n\ntry {\n const jsonMatch = stdout.match(/\\{[\\s\\S]*\"status\"\\s*:\\s*\"[^\"]+\"[\\s\\S]*\\}/);\n if (jsonMatch) {\n result = JSON.parse(jsonMatch[0]);\n } else {\n throw new Error('No valid JSON result found');\n }\n} catch (e) {\n result = {\n status: 'error',\n error_message: e.message,\n raw_output: stdout.substring(0, 500),\n stderr: stderr.substring(0, 500)\n };\n}\n\nconst orig = $('Build Prompt').item.json;\nconst success = result.status === 'success';\n\nreturn {\n ...orig,\n executorResult: result,\n success,\n commitCount: result.commit_count || 0,\n filesChanged: result.files_changed || 0\n};"
},
"id": "parse-result",
"name": "Parse Result",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1120,
300
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "check-success",
"leftValue": "={{ $json.success }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "check-success",
"name": "Success?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1340,
300
]
},
{
"parameters": {
"owner": {
"__rl": true,
"value": "={{ $json.owner }}",
"mode": "expression"
},
"repository": {
"__rl": true,
"value": "={{ $json.repo }}",
"mode": "expression"
},
"title": "={{ '[' + $json.jiraKey + '] ' + $json.summary }}",
"body": "={{ '## Summary\\n\\n' + $json.summary + '\\n\\n## Jira Issue\\n\\n[' + $json.jiraKey + '](' + $json.jiraUrl + ')\\n\\n## Changes\\n\\n- Commits: ' + $json.commitCount + '\\n- Files changed: ' + $json.filesChanged + '\\n\\n---\\n_Generated by AIDP_' }}",
"base": "={{ $json.baseBranch }}",
"head": "={{ $json.branchName }}"
},
"id": "create-pr",
"name": "Create PR",
"type": "n8n-nodes-base.github",
"typeVersion": 1,
"position": [
1560,
200
],
"credentials": {
"githubApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const pr = $input.item.json;\nconst orig = $('Parse Result').item.json;\nreturn { ...orig, prNumber: pr.number, prUrl: pr.html_url };"
},
"id": "extract-pr",
"name": "Extract PR Info",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1780,
200
]
},
{
"parameters": {
"resource": "issueComment",
"operation": "add",
"issueKey": "={{ $json.jiraKey }}",
"comment": "={{ '\u2705 *AIDP Completed*\\n\\n\ud83d\udd17 PR: [#' + $json.prNumber + '](' + $json.prUrl + ')\\n\ud83d\udcca ' + $json.commitCount + ' commits, ' + $json.filesChanged + ' files\\n\ud83c\udf3f Branch: `' + $json.branchName + '`' }}"
},
"id": "jira-comment-success",
"name": "Jira Comment Success",
"type": "n8n-nodes-base.jira",
"typeVersion": 1,
"position": [
2000,
200
],
"credentials": {
"jiraSoftwareCloudApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"resource": "issueComment",
"operation": "add",
"issueKey": "={{ $json.jiraKey }}",
"comment": "={{ '\u274c *AIDP Failed*\\n\\nError: ' + ($json.executorResult?.error_message || 'Unknown') + '\\n\\nRepo: ' + $json.repoUrl + '\\nDebug: ' + JSON.stringify($json.debugInfo || {}) }}"
},
"id": "jira-comment-error",
"name": "Jira Comment Error",
"type": "n8n-nodes-base.jira",
"typeVersion": 1,
"position": [
1560,
450
],
"credentials": {
"jiraSoftwareCloudApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ status: 'processed', jiraKey: $json.jiraKey, repoUrl: $json.repoUrl, debug: $json.debugInfo }) }}"
},
"id": "respond-webhook",
"name": "Respond to Webhook",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
2220,
300
]
}
],
"connections": {
"Jira Webhook": {
"main": [
[
{
"node": "Parse Issue Data",
"type": "main",
"index": 0
}
]
]
},
"Parse Issue Data": {
"main": [
[
{
"node": "Build Prompt",
"type": "main",
"index": 0
}
]
]
},
"Build Prompt": {
"main": [
[
{
"node": "Execute Claude Code",
"type": "main",
"index": 0
}
]
]
},
"Execute Claude Code": {
"main": [
[
{
"node": "Parse Result",
"type": "main",
"index": 0
}
]
]
},
"Parse Result": {
"main": [
[
{
"node": "Success?",
"type": "main",
"index": 0
}
]
]
},
"Success?": {
"main": [
[
{
"node": "Create PR",
"type": "main",
"index": 0
}
],
[
{
"node": "Jira Comment Error",
"type": "main",
"index": 0
}
]
]
},
"Create PR": {
"main": [
[
{
"node": "Extract PR Info",
"type": "main",
"index": 0
}
]
]
},
"Extract PR Info": {
"main": [
[
{
"node": "Jira Comment Success",
"type": "main",
"index": 0
}
]
]
},
"Jira Comment Success": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Jira Comment Error": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1",
"saveManualExecutions": true,
"saveDataSuccessExecution": "all",
"saveDataErrorExecution": "all"
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
githubApijiraSoftwareCloudApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
AIDP - Main Workflow v8. Uses executeCommand, github, jira. Webhook trigger; 11 nodes.
Source: https://github.com/andresKillem/aidp/blob/8839fb212f6336a3aa9793485da729542e0fd7da/n8n-workflows/main-workflow-v8.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
AIDP - Main Workflow v3. Uses executeCommand, github, jira. Webhook trigger; 12 nodes.
AIDP - Main Workflow v7. Uses executeCommand, github, jira. Webhook trigger; 12 nodes.
AIDP - Main Workflow v5. Uses executeCommand, github, jira. Webhook trigger; 12 nodes.
This n8n workflow template uses community nodes and is only compatible with the self-hosted version of n8n.
GitHub PR Deep-Link & Routing Validator (n8n + ExecuteCommand + GitHub Comment). Uses executeCommand, github. Webhook trigger; 5 nodes.