{
  "name": "Project Lazy Coder - Main Workflow",
  "nodes": [
    {
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "id": "telegram-trigger",
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "typeVersion": 1.1,
      "position": [
        250,
        300
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Parse incoming Telegram message\nconst message = $input.first().json.message;\nconst chatId = message.chat.id;\nconst text = message.text || '';\nconst username = message.from.username || 'user';\n\n// Parse command\nlet command = null;\nlet content = text;\n\nif (text.startsWith('/')) {\n  const parts = text.split(' ');\n  command = parts[0].substring(1).toLowerCase();\n  content = parts.slice(1).join(' ');\n}\n\n// Generate workflow ID\nconst workflowId = `WF_${Date.now().toString(36).toUpperCase()}`;\n\nreturn {\n  json: {\n    chatId,\n    username,\n    command,\n    content,\n    workflowId,\n    originalMessage: text,\n    timestamp: new Date().toISOString(),\n    testAttempt: 0,\n    uiAttempt: 0,\n    maxRetries: 3\n  }\n};"
      },
      "id": "parse-message",
      "name": "Parse Message",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        450,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "condition-new",
              "leftValue": "={{ $json.command }}",
              "rightValue": "new",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "check-command",
      "name": "Is /new Command?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        650,
        300
      ]
    },
    {
      "parameters": {
        "chatId": "={{ $json.chatId }}",
        "text": "={{ '\u2705 Request received!\\n\ud83c\udd94 Workflow: ' + $json.workflowId + '\\n\\n\ud83d\udcdd Feature: ' + $json.content + '\\n\\n\u23f3 Starting development...' }}",
        "additionalFields": {}
      },
      "id": "send-ack",
      "name": "Send Acknowledgment",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        850,
        200
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{ $json.chatId }}",
        "text": "={{ '\u2753 Unknown command: /' + $json.command + '\\n\\nAvailable commands:\\n/new <feature> - Create new feature\\n/status - Check status\\n/cancel - Cancel current task' }}",
        "additionalFields": {}
      },
      "id": "send-unknown",
      "name": "Send Unknown Command",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        850,
        400
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Build Claude Code command\nconst data = $input.first().json;\nconst content = data.content;\nconst workflowId = data.workflowId;\n\n// Project path - UPDATE THIS\nconst projectPath = process.env.PROJECT_PATH || '/Users/padidamabhinay/your-project';\n\n// Build prompt for Claude\nconst prompt = `Implement this feature request:\n\n${content}\n\nInstructions:\n1. Read existing code to understand patterns\n2. Implement the feature\n3. Add tests if applicable\n4. Git add and commit with descriptive message\n\nAfter completion, output: DONE: <summary of changes>`;\n\n// Escape for shell\nconst escapedPrompt = prompt.replace(/'/g, \"'\\\\''\");\n\nreturn {\n  json: {\n    ...data,\n    projectPath,\n    claudeCommand: `cd '${projectPath}' && claude -p '${escapedPrompt}' --dangerously-skip-permissions 2>&1`,\n    phase: 'code_generation'\n  }\n};"
      },
      "id": "build-claude-cmd",
      "name": "Build Claude Command",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1050,
        200
      ]
    },
    {
      "parameters": {
        "chatId": "={{ $json.chatId }}",
        "text": "\ud83d\udcbb Running Claude Code...",
        "additionalFields": {}
      },
      "id": "notify-claude",
      "name": "Notify: Claude Running",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        1250,
        200
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "command": "={{ $json.claudeCommand }}",
        "options": {
          "timeout": 300000
        }
      },
      "id": "run-claude",
      "name": "Execute Claude Code",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [
        1450,
        200
      ],
      "continueOnFail": true
    },
    {
      "parameters": {
        "jsCode": "// Parse Claude output and prepare for testing\nconst input = $input.first().json;\nconst data = $('Build Claude Command').first().json;\n\nconst stdout = input.stdout || '';\nconst stderr = input.stderr || '';\nconst exitCode = input.exitCode;\n\nconst claudeSuccess = exitCode === 0 || stdout.includes('DONE:');\n\nreturn {\n  json: {\n    ...data,\n    claudeOutput: stdout,\n    claudeError: stderr,\n    claudeExitCode: exitCode,\n    claudeSuccess,\n    phase: 'testing'\n  }\n};"
      },
      "id": "parse-claude-output",
      "name": "Parse Claude Output",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1650,
        200
      ]
    },
    {
      "parameters": {
        "jsCode": "// Build test command\nconst data = $input.first().json;\nconst projectPath = data.projectPath;\n\n// Detect test framework and build command\n// Try pytest first, then npm test\nconst testCommand = `cd '${projectPath}' && (python -m pytest --tb=short -v 2>&1 || npm test 2>&1 || echo 'NO_TESTS_FOUND')`;\n\nreturn {\n  json: {\n    ...data,\n    testCommand,\n    testAttempt: (data.testAttempt || 0) + 1\n  }\n};"
      },
      "id": "build-test-cmd",
      "name": "Build Test Command",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1850,
        200
      ]
    },
    {
      "parameters": {
        "chatId": "={{ $json.chatId }}",
        "text": "={{ '\ud83e\uddea Running tests (attempt ' + $json.testAttempt + '/' + $json.maxRetries + ')...' }}",
        "additionalFields": {}
      },
      "id": "notify-tests",
      "name": "Notify: Tests Running",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        2050,
        200
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "command": "={{ $json.testCommand }}",
        "options": {
          "timeout": 120000
        }
      },
      "id": "run-tests",
      "name": "Execute Tests",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [
        2250,
        200
      ],
      "continueOnFail": true
    },
    {
      "parameters": {
        "jsCode": "// Parse test results\nconst input = $input.first().json;\nconst data = $('Build Test Command').first().json;\n\nconst stdout = input.stdout || '';\nconst stderr = input.stderr || '';\nconst exitCode = input.exitCode;\n\n// Check if tests passed\nconst noTests = stdout.includes('NO_TESTS_FOUND') || stdout.includes('no tests ran');\nconst testsPassed = exitCode === 0 || noTests;\n\n// Extract error info for fix prompt\nlet errorInfo = '';\nif (!testsPassed) {\n  errorInfo = stdout + '\\n' + stderr;\n  // Limit error length\n  if (errorInfo.length > 2000) {\n    errorInfo = errorInfo.substring(0, 2000) + '\\n... (truncated)';\n  }\n}\n\nreturn {\n  json: {\n    ...data,\n    testOutput: stdout,\n    testError: stderr,\n    testExitCode: exitCode,\n    testsPassed,\n    noTests,\n    errorInfo,\n    phase: testsPassed ? 'ui_testing' : 'test_fix'\n  }\n};"
      },
      "id": "parse-test-results",
      "name": "Parse Test Results",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2450,
        200
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "tests-passed",
              "leftValue": "={{ $json.testsPassed }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "check-tests",
      "name": "Tests Passed?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        2650,
        200
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "can-retry",
              "leftValue": "={{ $json.testAttempt }}",
              "rightValue": "={{ $json.maxRetries }}",
              "operator": {
                "type": "number",
                "operation": "lt"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "can-retry-tests",
      "name": "Can Retry?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        2850,
        350
      ]
    },
    {
      "parameters": {
        "jsCode": "// Build fix command for Claude\nconst data = $input.first().json;\nconst projectPath = data.projectPath;\nconst errorInfo = data.errorInfo;\n\nconst fixPrompt = `The tests failed with these errors:\n\n${errorInfo}\n\nPlease fix the code to make the tests pass. After fixing, output: FIXED: <what you fixed>`;\n\nconst escapedPrompt = fixPrompt.replace(/'/g, \"'\\\\''\");\n\nreturn {\n  json: {\n    ...data,\n    claudeCommand: `cd '${projectPath}' && claude -p '${escapedPrompt}' --dangerously-skip-permissions 2>&1`,\n    phase: 'test_fix'\n  }\n};"
      },
      "id": "build-fix-cmd",
      "name": "Build Fix Command",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3050,
        250
      ]
    },
    {
      "parameters": {
        "chatId": "={{ $json.chatId }}",
        "text": "={{ '\ud83d\udd27 Tests failed. Auto-fixing (attempt ' + $json.testAttempt + '/' + $json.maxRetries + ')...' }}",
        "additionalFields": {}
      },
      "id": "notify-fixing",
      "name": "Notify: Fixing",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        3250,
        250
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "command": "={{ $json.claudeCommand }}",
        "options": {
          "timeout": 300000
        }
      },
      "id": "run-fix",
      "name": "Execute Fix",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [
        3450,
        250
      ],
      "continueOnFail": true
    },
    {
      "parameters": {
        "chatId": "={{ $json.chatId }}",
        "text": "={{ '\u274c Tests failed after ' + $json.maxRetries + ' attempts.\\n\\nLast error:\\n' + $json.errorInfo.substring(0, 500) + '\\n\\nReply /retry to try again or /cancel to stop.' }}",
        "additionalFields": {}
      },
      "id": "notify-test-fail",
      "name": "Notify: Test Failed",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        3050,
        450
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{ $json.chatId }}",
        "text": "\u2705 All tests passed! Starting UI testing...",
        "additionalFields": {}
      },
      "id": "notify-tests-passed",
      "name": "Notify: Tests Passed",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        2850,
        100
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Build UI test command\nconst data = $input.first().json;\nconst projectPath = data.projectPath;\nconst workflowId = data.workflowId;\nconst screenshotDir = `${projectPath}/screenshots/${workflowId}`;\n\n// UI test script path\nconst scriptPath = '/Users/padidamabhinay/Library/CloudStorage/OneDrive-AshokaBuildersIndiaPvtLtd/project_lazy_coder/scripts/ui_test.py';\nconst url = 'http://localhost:3000';  // Update as needed\n\nconst instructions = 'Check if the UI renders correctly, all elements are visible, no errors displayed';\n\nreturn {\n  json: {\n    ...data,\n    uiCommand: `python3 '${scriptPath}' '${url}' '${instructions}' '${screenshotDir}'`,\n    screenshotDir,\n    uiAttempt: (data.uiAttempt || 0) + 1,\n    phase: 'ui_testing'\n  }\n};"
      },
      "id": "build-ui-cmd",
      "name": "Build UI Test Command",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3050,
        100
      ]
    },
    {
      "parameters": {
        "chatId": "={{ $json.chatId }}",
        "text": "={{ '\ud83c\udfa8 Running UI tests (attempt ' + $json.uiAttempt + '/' + $json.maxRetries + ')...' }}",
        "additionalFields": {}
      },
      "id": "notify-ui-test",
      "name": "Notify: UI Testing",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        3250,
        100
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "command": "={{ $json.uiCommand }}",
        "options": {
          "timeout": 60000
        }
      },
      "id": "run-ui-test",
      "name": "Execute UI Test",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [
        3450,
        100
      ],
      "continueOnFail": true
    },
    {
      "parameters": {
        "jsCode": "// Parse UI test results\nconst input = $input.first().json;\nconst data = $('Build UI Test Command').first().json;\n\nconst stdout = input.stdout || '';\nconst stderr = input.stderr || '';\n\nlet uiResult = { passed: false, issues: ['Failed to parse result'], screenshot: null };\n\ntry {\n  uiResult = JSON.parse(stdout);\n} catch (e) {\n  uiResult.issues = ['Parse error: ' + e.message, 'Output: ' + stdout.substring(0, 500)];\n}\n\nreturn {\n  json: {\n    ...data,\n    uiPassed: uiResult.passed,\n    uiIssues: uiResult.issues || [],\n    uiObservations: uiResult.observations || [],\n    screenshotPath: uiResult.screenshot,\n    phase: uiResult.passed ? 'complete' : 'ui_fix'\n  }\n};"
      },
      "id": "parse-ui-results",
      "name": "Parse UI Results",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3650,
        100
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "ui-passed",
              "leftValue": "={{ $json.uiPassed }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "check-ui",
      "name": "UI Passed?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        3850,
        100
      ]
    },
    {
      "parameters": {
        "jsCode": "// Build final success message (no UI testing)\nconst data = $input.first().json;\n\nconst message = `\u2705 **Task Complete!**\n\n\ud83d\udccb **Task:** ${data.content}\n\ud83d\udd27 **Workflow ID:** ${data.workflowId}\n\ud83d\udcca **Test Attempts:** ${data.testAttempt + 1}\n\nAll tests passed! Your code is ready.`;\n\nreturn {\n  json: {\n    ...data,\n    finalMessage: message,\n    success: true\n  }\n};"
      },
      "id": "build-final",
      "name": "Build Final Message",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        4050,
        0
      ]
    },
    {
      "parameters": {
        "chatId": "={{ $json.chatId }}",
        "text": "={{ $json.finalMessage }}",
        "additionalFields": {}
      },
      "id": "send-final",
      "name": "Send Final Result",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        4250,
        0
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "has-screenshot",
              "leftValue": "={{ $json.screenshotPath }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "has-screenshot",
      "name": "Has Screenshot?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        4450,
        0
      ]
    },
    {
      "parameters": {
        "chatId": "={{ $json.chatId }}",
        "operation": "sendPhoto",
        "file": "={{ $json.screenshotPath }}",
        "additionalFields": {
          "caption": "\ud83d\udcf8 Final UI Screenshot"
        }
      },
      "id": "send-screenshot",
      "name": "Send Screenshot",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        4650,
        -50
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "Parse Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Message": {
      "main": [
        [
          {
            "node": "Is /new Command?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is /new Command?": {
      "main": [
        [
          {
            "node": "Send Acknowledgment",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send Unknown Command",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Acknowledgment": {
      "main": [
        [
          {
            "node": "Build Claude Command",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Claude Command": {
      "main": [
        [
          {
            "node": "Notify: Claude Running",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify: Claude Running": {
      "main": [
        [
          {
            "node": "Execute Claude Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Claude Code": {
      "main": [
        [
          {
            "node": "Parse Claude Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Claude Output": {
      "main": [
        [
          {
            "node": "Build Test Command",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Test Command": {
      "main": [
        [
          {
            "node": "Notify: Tests Running",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify: Tests Running": {
      "main": [
        [
          {
            "node": "Execute Tests",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Tests": {
      "main": [
        [
          {
            "node": "Parse Test Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Test Results": {
      "main": [
        [
          {
            "node": "Tests Passed?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Tests Passed?": {
      "main": [
        [
          {
            "node": "Notify: Tests Passed",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Can Retry?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify: Tests Passed": {
      "main": [
        [
          {
            "node": "Build Final Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Can Retry?": {
      "main": [
        [
          {
            "node": "Build Fix Command",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Notify: Test Failed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Fix Command": {
      "main": [
        [
          {
            "node": "Notify: Fixing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify: Fixing": {
      "main": [
        [
          {
            "node": "Execute Fix",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Fix": {
      "main": [
        [
          {
            "node": "Build Test Command",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build UI Test Command": {
      "main": [
        [
          {
            "node": "Notify: UI Testing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify: UI Testing": {
      "main": [
        [
          {
            "node": "Execute UI Test",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute UI Test": {
      "main": [
        [
          {
            "node": "Parse UI Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse UI Results": {
      "main": [
        [
          {
            "node": "UI Passed?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "UI Passed?": {
      "main": [
        [
          {
            "node": "Build Final Message",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Build Fix Command",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Final Message": {
      "main": [
        [
          {
            "node": "Send Final Result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Final Result": {
      "main": [
        [
          {
            "node": "Has Screenshot?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Screenshot?": {
      "main": [
        [
          {
            "node": "Send Screenshot",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [],
  "triggerCount": 1,
  "updatedAt": "2026-01-10T12:00:00.000Z",
  "versionId": "1",
  "active": false
}