vibebusiness 1.2.49 → 1.2.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/.next/standalone/.env +1 -1
  2. package/.next/standalone/.next/BUILD_ID +1 -1
  3. package/.next/standalone/.next/app-build-manifest.json +20 -20
  4. package/.next/standalone/.next/app-path-routes-manifest.json +1 -1
  5. package/.next/standalone/.next/build-manifest.json +4 -4
  6. package/.next/standalone/.next/prerender-manifest.json +1 -1
  7. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  9. package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
  10. package/.next/standalone/.next/server/app/api/analyze/route.js +1 -1
  11. package/.next/standalone/.next/server/app/api/analyze/route.js.nft.json +1 -1
  12. package/.next/standalone/.next/server/app/api/config/route.js.nft.json +1 -1
  13. package/.next/standalone/.next/server/app/api/epics/[id]/ideas/route.js.nft.json +1 -1
  14. package/.next/standalone/.next/server/app/api/epics/[id]/route.js.nft.json +1 -1
  15. package/.next/standalone/.next/server/app/api/epics/route.js.nft.json +1 -1
  16. package/.next/standalone/.next/server/app/api/goals/[id]/kpis/route.js.nft.json +1 -1
  17. package/.next/standalone/.next/server/app/api/goals/[id]/route.js.nft.json +1 -1
  18. package/.next/standalone/.next/server/app/api/goals/route.js.nft.json +1 -1
  19. package/.next/standalone/.next/server/app/api/hypotheses/[id]/route.js.nft.json +1 -1
  20. package/.next/standalone/.next/server/app/api/hypotheses/route.js.nft.json +1 -1
  21. package/.next/standalone/.next/server/app/api/ideas/[id]/comments/route.js.nft.json +1 -1
  22. package/.next/standalone/.next/server/app/api/ideas/[id]/implement/route.js +1 -1
  23. package/.next/standalone/.next/server/app/api/ideas/[id]/implement/route.js.nft.json +1 -1
  24. package/.next/standalone/.next/server/app/api/ideas/[id]/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/ideas/[id]/transition/route.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/api/ideas/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/implementations/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/kpis/refresh/route.js +1 -1
  29. package/.next/standalone/.next/server/app/api/kpis/refresh/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/provider-status/route.js +1 -0
  31. package/.next/standalone/.next/server/app/api/provider-status/route.js.nft.json +1 -0
  32. package/.next/standalone/.next/server/app/api/social/[id]/publish/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/social/[id]/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/api/social/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/goals/[id]/page_client-reference-manifest.js +1 -1
  36. package/.next/standalone/.next/server/app/goals/page.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/goals/page_client-reference-manifest.js +1 -1
  38. package/.next/standalone/.next/server/app/hypotheses/[id]/page_client-reference-manifest.js +1 -1
  39. package/.next/standalone/.next/server/app/hypotheses/page.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/hypotheses/page_client-reference-manifest.js +1 -1
  41. package/.next/standalone/.next/server/app/ideas/[id]/page.js +1 -1
  42. package/.next/standalone/.next/server/app/ideas/[id]/page.js.nft.json +1 -1
  43. package/.next/standalone/.next/server/app/ideas/[id]/page_client-reference-manifest.js +1 -1
  44. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  45. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  46. package/.next/standalone/.next/server/app/roadmap/[id]/page_client-reference-manifest.js +1 -1
  47. package/.next/standalone/.next/server/app/roadmap/page.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/roadmap/page_client-reference-manifest.js +1 -1
  49. package/.next/standalone/.next/server/app/sessions/page.js.nft.json +1 -1
  50. package/.next/standalone/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  51. package/.next/standalone/.next/server/app/settings/page.js +1 -1
  52. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  53. package/.next/standalone/.next/server/app/settings.html +1 -1
  54. package/.next/standalone/.next/server/app/settings.rsc +2 -2
  55. package/.next/standalone/.next/server/app/social/page.js +1 -1
  56. package/.next/standalone/.next/server/app/social/page_client-reference-manifest.js +1 -1
  57. package/.next/standalone/.next/server/app/social.html +1 -1
  58. package/.next/standalone/.next/server/app/social.rsc +2 -2
  59. package/.next/standalone/.next/server/app-paths-manifest.json +12 -11
  60. package/.next/standalone/.next/server/chunks/3794.js +92 -17
  61. package/.next/standalone/.next/server/middleware-build-manifest.js +1 -1
  62. package/.next/standalone/.next/server/pages/404.html +1 -1
  63. package/.next/standalone/.next/server/pages/500.html +1 -1
  64. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  65. package/.next/standalone/data/business-context.json +60 -6
  66. package/.next/standalone/data/goals.json +50 -10
  67. package/.next/standalone/data/ideas.json +1278 -597
  68. package/.next/standalone/data/implementations.json +101 -0
  69. package/.next/standalone/data/posthog.json +68 -0
  70. package/.next/standalone/data/sessions.json +5 -4
  71. package/.next/standalone/data/social.json +86 -3
  72. package/.next/standalone/package.json +1 -1
  73. package/.next/standalone/scripts/analyze.ts +10 -0
  74. package/.next/standalone/scripts/implement.ts +37 -30
  75. package/.next/standalone/scripts/skills/social-media.ts +172 -2
  76. package/.next/static/chunks/59-76eecfb6e8216043.js +1 -0
  77. package/.next/static/chunks/app/goals/[id]/page-051064c3146131cc.js +1 -0
  78. package/.next/static/chunks/app/ideas/[id]/page-adaeb619cd0425e9.js +1 -0
  79. package/.next/static/chunks/app/roadmap/[id]/page-3822586c0d64fff1.js +1 -0
  80. package/.next/static/chunks/app/settings/page-2204cc936ec9474b.js +1 -0
  81. package/.next/static/chunks/app/social/page-018893f87b308651.js +1 -0
  82. package/.next/static/chunks/{main-61d2f25883998186.js → main-c99f3473a63aa803.js} +1 -1
  83. package/.next/static/css/d8bd6d69d1ff97e3.css +3 -0
  84. package/dist/bin/vibebusiness.js +12 -0
  85. package/dist/scripts/analyze.js +170 -68
  86. package/dist/scripts/chat.js +137 -36
  87. package/dist/scripts/heartbeat.js +617 -348
  88. package/dist/scripts/implement.js +218 -70
  89. package/dist/scripts/init.js +164 -16
  90. package/dist/scripts/provider.js +428 -0
  91. package/dist/scripts/scan.js +44 -5
  92. package/package.json +1 -1
  93. package/.next/static/chunks/59-a053b1c0e85128de.js +0 -1
  94. package/.next/static/chunks/app/goals/[id]/page-8dbeab5cc8cf0988.js +0 -1
  95. package/.next/static/chunks/app/ideas/[id]/page-89e3625db9017166.js +0 -1
  96. package/.next/static/chunks/app/roadmap/[id]/page-f437e783039534c4.js +0 -1
  97. package/.next/static/chunks/app/settings/page-d2d630a799b6b495.js +0 -1
  98. package/.next/static/chunks/app/social/page-69e480936711ccf2.js +0 -1
  99. package/.next/static/css/179dd3e0738c2fe4.css +0 -3
  100. /package/.next/static/{zIIaTqrawBK1MmHg37JOr → p1Sl4kPMQcYC3c1LgbNSP}/_buildManifest.js +0 -0
  101. /package/.next/static/{zIIaTqrawBK1MmHg37JOr → p1Sl4kPMQcYC3c1LgbNSP}/_ssgManifest.js +0 -0
@@ -1369,6 +1369,107 @@
1369
1369
  "[2026-02-21T03:14:02.477Z] Create PR only mode — skipping implementation",
1370
1370
  "[2026-02-21T03:14:02.490Z] No commits to push, skipping PR creation"
1371
1371
  ]
1372
+ },
1373
+ {
1374
+ "id": "impl-mly92zre",
1375
+ "idea_id": "idea-073e5d92",
1376
+ "status": "completed",
1377
+ "repo_name": "vibebusiness",
1378
+ "branch_name": "ai/idea-073e5d92-fix-critical-shell-injection-in-implemen",
1379
+ "workspace_path": "/Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g0",
1380
+ "logs": [
1381
+ "[2026-02-22T21:19:05.353Z] Implementation started",
1382
+ "[2026-02-22T21:19:05.357Z] Using pre-configured worktree: /Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g0",
1383
+ "[2026-02-22T21:19:05.361Z] Running Claude Code to implement changes (timeout: 600s (model: sonnet))...",
1384
+ "[2026-02-22T21:19:05.372Z] Using pre-configured worktree: /Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g1",
1385
+ "[2026-02-22T21:19:05.377Z] Running Claude Code to implement changes (timeout: 600s (model: sonnet))...",
1386
+ "[2026-02-22T21:19:05.386Z] Using pre-configured worktree: /Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g2",
1387
+ "[2026-02-22T21:19:05.396Z] Using pre-configured worktree: /Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g3",
1388
+ "[2026-02-22T21:19:05.403Z] Running Claude Code to implement changes (timeout: 600s (model: sonnet))...",
1389
+ "[2026-02-22T21:19:05.423Z] Using pre-configured worktree: /Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g4",
1390
+ "[2026-02-22T21:19:05.455Z] Running Claude Code to implement changes (timeout: 600s (model: sonnet))...",
1391
+ "[2026-02-22T21:19:05.466Z] Using pre-configured worktree: /Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g5",
1392
+ "[2026-02-22T21:19:05.477Z] Running Claude Code to implement changes (timeout: 600s (model: sonnet))...",
1393
+ "[2026-02-22T21:19:35.372Z] ...Claude Code working (30s elapsed, 0 chars output, 30s since last output)",
1394
+ "[2026-02-22T21:19:35.380Z] ...Claude Code working (30s elapsed, 0 chars output, 30s since last output)",
1395
+ "[2026-02-22T21:19:35.401Z] ...Claude Code working (30s elapsed, 0 chars output, 30s since last output)",
1396
+ "[2026-02-22T21:19:35.412Z] ...Claude Code working (30s elapsed, 0 chars output, 30s since last output)",
1397
+ "[2026-02-22T21:19:35.466Z] ...Claude Code working (30s elapsed, 0 chars output, 30s since last output)",
1398
+ "[2026-02-22T21:19:35.481Z] ...Claude Code working (30s elapsed, 0 chars output, 30s since last output)",
1399
+ "[2026-02-22T21:19:43.621Z] Claude Code completed successfully in 38s (1000 chars)",
1400
+ "[2026-02-22T21:19:43.657Z] Changes detected, staging and committing...",
1401
+ "[2026-02-22T21:19:43.739Z] Skipping PR creation (--skip-pr)",
1402
+ "[2026-02-22T21:20:04.844Z] Claude Code completed successfully in 59s (1005 chars)",
1403
+ "[2026-02-22T21:20:04.899Z] Changes detected, staging and committing...",
1404
+ "[2026-02-22T21:20:04.975Z] Skipping PR creation (--skip-pr)",
1405
+ "[2026-02-22T21:20:05.021Z] Claude Code completed successfully in 60s (1202 chars)",
1406
+ "[2026-02-22T21:20:05.065Z] Changes detected, staging and committing...",
1407
+ "[2026-02-22T21:20:05.127Z] Skipping PR creation (--skip-pr)",
1408
+ "[2026-02-22T21:20:05.412Z] ...Claude Code working (60s elapsed, 0 chars output, 60s since last output)",
1409
+ "[2026-02-22T21:20:05.467Z] ...Claude Code working (60s elapsed, 0 chars output, 60s since last output)",
1410
+ "[2026-02-22T21:20:05.480Z] ...Claude Code working (60s elapsed, 0 chars output, 60s since last output)",
1411
+ "[2026-02-22T21:20:35.414Z] ...Claude Code working (90s elapsed, 0 chars output, 90s since last output)",
1412
+ "[2026-02-22T21:20:35.468Z] ...Claude Code working (90s elapsed, 0 chars output, 90s since last output)",
1413
+ "[2026-02-22T21:20:35.483Z] ...Claude Code working (90s elapsed, 0 chars output, 90s since last output)",
1414
+ "[2026-02-22T21:20:42.632Z] Claude Code completed successfully in 97s (1206 chars)",
1415
+ "[2026-02-22T21:20:42.685Z] Changes detected, staging and committing...",
1416
+ "[2026-02-22T21:20:42.735Z] Skipping PR creation (--skip-pr)",
1417
+ "[2026-02-22T21:21:05.414Z] ...Claude Code working (120s elapsed, 0 chars output, 120s since last output)",
1418
+ "[2026-02-22T21:21:05.481Z] ...Claude Code working (120s elapsed, 0 chars output, 120s since last output)",
1419
+ "[2026-02-22T21:21:35.414Z] ...Claude Code working (150s elapsed, 0 chars output, 150s since last output)",
1420
+ "[2026-02-22T21:21:35.483Z] ...Claude Code working (150s elapsed, 0 chars output, 150s since last output)",
1421
+ "[2026-02-22T21:22:05.416Z] ...Claude Code working (180s elapsed, 0 chars output, 180s since last output)",
1422
+ "[2026-02-22T21:22:05.483Z] ...Claude Code working (180s elapsed, 0 chars output, 180s since last output)",
1423
+ "[2026-02-22T21:22:35.417Z] ...Claude Code working (210s elapsed, 0 chars output, 210s since last output)",
1424
+ "[2026-02-22T21:22:35.484Z] ...Claude Code working (210s elapsed, 0 chars output, 210s since last output)",
1425
+ "[2026-02-22T21:23:05.416Z] ...Claude Code working (240s elapsed, 0 chars output, 240s since last output)",
1426
+ "[2026-02-22T21:23:05.483Z] ...Claude Code working (240s elapsed, 0 chars output, 240s since last output)",
1427
+ "[2026-02-22T21:23:17.057Z] Claude Code completed successfully in 252s (2194 chars)",
1428
+ "[2026-02-22T21:23:17.098Z] Changes detected, staging and committing...",
1429
+ "[2026-02-22T21:23:17.156Z] Skipping PR creation (--skip-pr)",
1430
+ "[2026-02-22T21:23:35.417Z] ...Claude Code working (270s elapsed, 0 chars output, 270s since last output)",
1431
+ "[2026-02-22T21:24:04.053Z] Claude Code completed successfully in 299s (2310 chars)",
1432
+ "[2026-02-22T21:24:04.121Z] Changes detected, staging and committing...",
1433
+ "[2026-02-22T21:24:04.199Z] Skipping PR creation (--skip-pr)"
1434
+ ]
1435
+ },
1436
+ {
1437
+ "id": "impl-mly949xm",
1438
+ "idea_id": "idea-073e5d92",
1439
+ "status": "completed",
1440
+ "repo_name": "vibebusiness",
1441
+ "branch_name": "ai/idea-073e5d92-fix-critical-shell-injection-in-implemen",
1442
+ "workspace_path": "/Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g0",
1443
+ "logs": [
1444
+ "[2026-02-22T21:20:05.193Z] Implementation started",
1445
+ "[2026-02-22T21:20:05.195Z] Using pre-configured worktree: /Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g0",
1446
+ "[2026-02-22T21:20:05.196Z] Running Claude Code to implement changes (timeout: 600s (model: sonnet))...",
1447
+ "[2026-02-22T21:20:35.199Z] ...Claude Code working (30s elapsed, 0 chars output, 30s since last output)",
1448
+ "[2026-02-22T21:21:05.200Z] ...Claude Code working (60s elapsed, 0 chars output, 60s since last output)",
1449
+ "[2026-02-22T21:21:30.701Z] Claude Code completed successfully in 86s (1241 chars)",
1450
+ "[2026-02-22T21:21:30.721Z] Changes detected, staging and committing...",
1451
+ "[2026-02-22T21:21:30.799Z] Skipping PR creation (--skip-pr)"
1452
+ ]
1453
+ },
1454
+ {
1455
+ "id": "impl-mly9641i",
1456
+ "idea_id": "idea-073e5d92",
1457
+ "status": "completed",
1458
+ "repo_name": "vibebusiness",
1459
+ "branch_name": "ai/idea-073e5d92-fix-critical-shell-injection-in-implemen",
1460
+ "workspace_path": "/Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g0",
1461
+ "logs": [
1462
+ "[2026-02-22T21:21:30.870Z] Implementation started",
1463
+ "[2026-02-22T21:21:30.871Z] Using pre-configured worktree: /Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g0",
1464
+ "[2026-02-22T21:21:30.872Z] Running Claude Code to implement changes (timeout: 600s (model: sonnet))...",
1465
+ "[2026-02-22T21:22:00.877Z] ...Claude Code working (30s elapsed, 0 chars output, 30s since last output)",
1466
+ "[2026-02-22T21:22:30.876Z] ...Claude Code working (60s elapsed, 0 chars output, 60s since last output)",
1467
+ "[2026-02-22T21:23:00.877Z] ...Claude Code working (90s elapsed, 0 chars output, 90s since last output)",
1468
+ "[2026-02-22T21:23:30.878Z] ...Claude Code working (120s elapsed, 0 chars output, 120s since last output)",
1469
+ "[2026-02-22T21:23:36.366Z] Claude Code completed successfully in 125s (1664 chars)",
1470
+ "[2026-02-22T21:23:36.408Z] Changes detected, staging and committing...",
1471
+ "[2026-02-22T21:23:36.507Z] Skipping PR creation (--skip-pr)"
1472
+ ]
1372
1473
  }
1373
1474
  ]
1374
1475
  }
@@ -0,0 +1,68 @@
1
+ {
2
+ "last_updated": "2026-02-22T21:45:00.000Z",
3
+ "integration_status": {
4
+ "sdk_installed": true,
5
+ "api_key_valid": true,
6
+ "provider_generated": true,
7
+ "pageview_tracker": true,
8
+ "event_helper": true,
9
+ "kpi_adapter": true
10
+ },
11
+ "framework": {
12
+ "framework": "nextjs",
13
+ "typescript": true,
14
+ "appRouter": true,
15
+ "srcDir": true
16
+ },
17
+ "generated_files": [
18
+ "website/src/components/PostHogProvider.tsx",
19
+ "website/src/components/PostHogPageview.tsx",
20
+ "website/src/lib/posthog.ts"
21
+ ],
22
+ "detected_events": [
23
+ {
24
+ "event": "waitlist_signup_success",
25
+ "location": "website/src/app/page.tsx",
26
+ "type": "website"
27
+ },
28
+ {
29
+ "event": "waitlist_signup_error",
30
+ "location": "website/src/app/page.tsx",
31
+ "type": "website"
32
+ },
33
+ {
34
+ "event": "checkout_completed",
35
+ "location": "website/src/components/TrackCheckoutComplete.tsx",
36
+ "type": "website"
37
+ },
38
+ {
39
+ "event": "command_run",
40
+ "location": "bin/ai-analyst.ts",
41
+ "type": "cli",
42
+ "properties": ["command", "dryRun", "session", "task", "type", "deep", "minimal"]
43
+ },
44
+ {
45
+ "event": "heartbeat_task",
46
+ "location": "scripts/heartbeat.ts",
47
+ "type": "backend",
48
+ "properties": ["taskType", "success", "errorType"]
49
+ }
50
+ ],
51
+ "kpi_mappings": {
52
+ "kpi-beta-signups": "waitlist_signup_success",
53
+ "kpi-paying-users": "checkout_completed",
54
+ "kpi-cli-init-count": "command_run[command=init]",
55
+ "kpi-cli-vibe-count": "command_run[command=vibe]",
56
+ "kpi-cli-scan-count": "command_run[command=scan]"
57
+ },
58
+ "unmapped_events": [
59
+ {
60
+ "event": "waitlist_signup_error",
61
+ "reason": "No matching KPI — useful for error monitoring in PostHog dashboards"
62
+ },
63
+ {
64
+ "event": "heartbeat_task",
65
+ "reason": "Operational metric — useful in PostHog dashboards but no business KPI match"
66
+ }
67
+ ]
68
+ }
@@ -341,18 +341,19 @@
341
341
  {
342
342
  "id": "session-4a6293fb",
343
343
  "created_at": "2026-02-19T20:11:45.297Z",
344
- "completed_at": null,
344
+ "completed_at": "2026-02-22T00:00:00.000Z",
345
345
  "type": "quick",
346
- "status": "running",
346
+ "status": "failed",
347
347
  "repos_analyzed": [
348
348
  "vibebusiness"
349
349
  ],
350
350
  "ideas_generated": [],
351
- "error_message": null,
351
+ "error_message": "Session timed out — marked failed by dedup-triage-and-approve-inbox meta-task on 2026-02-22. Was stuck in 'running' with 0 ideas generated since 2026-02-19T20:11:45.",
352
352
  "logs": [
353
353
  "[2026-02-19T20:11:45.297Z] Session started",
354
354
  "[2026-02-19T20:11:45.301Z] Generated quick analysis prompt",
355
- "[2026-02-19T20:11:45.301Z] Running Claude Code analysis..."
355
+ "[2026-02-19T20:11:45.301Z] Running Claude Code analysis...",
356
+ "[2026-02-22T00:00:00.000Z] Session marked failed by meta-task cleanup (zombie session — no ideas generated, stuck in running state)"
356
357
  ]
357
358
  }
358
359
  ]
@@ -1,11 +1,94 @@
1
1
  {
2
- "last_updated": "2026-02-20T22:50:48.200Z",
2
+ "last_updated": "2026-02-22T21:40:50.506Z",
3
3
  "platform": "x",
4
4
  "username": "@luisgmey",
5
5
  "credentials_valid": true,
6
- "drafts": [],
6
+ "drafts": [
7
+ {
8
+ "id": "draft-a53d0edc",
9
+ "text": "6 months ago I had 47 product ideas and shipped 0 of them.\n\nThis week I shipped 6 updates without writing a single line of code.\n\nI built an AI product manager that runs on autopilot.\n\nHere's exactly how it works 🧵",
10
+ "source": "thread",
11
+ "source_ref": null,
12
+ "status": "draft",
13
+ "created_at": "2026-02-22T21:40:50.506Z",
14
+ "published_at": null,
15
+ "tweet_id": null,
16
+ "tweet_url": null,
17
+ "is_thread": true,
18
+ "thread_tweets": [
19
+ "6 months ago I had 47 product ideas and shipped 0 of them.\n\nThis week I shipped 6 updates without writing a single line of code.\n\nI built an AI product manager that runs on autopilot.\n\nHere's exactly how it works 🧵",
20
+ "The real indie hacker problem isn't building.\n\nIt's deciding *what* to build.\n\n20 ideas → 0 shipped. Every week.\n\nAnalysis paralysis kills more products than bad code.\n\nI was stuck here for 18 months.",
21
+ "So I built VibeBusiness.\n\nAn autonomous AI that:\n→ Analyzes your codebase\n→ Reviews your metrics\n→ Decides what to build next\n→ Implements it\n→ Ships it\n→ Verifies the results\n\nThe full PM loop. Zero humans required.",
22
+ "It runs on a heartbeat pattern.\n\nEvery few hours it checks:\n• What's broken?\n• What's growing?\n• What would move the needle most?\n\nThen it acts. Creates branches. Opens PRs. Ships code.\n\nThis is what 'AI-native' actually means.",
23
+ "This week alone it shipped:\n→ Stripe payment integration\n→ OG meta tags for link previews\n→ Social proof section\n→ npm README update\n→ Hero copy improvements\n\nAll from one command: `vibebusiness heartbeat`",
24
+ "It's live on npm right now.\n\n`npm install -g vibebusiness`\n\nConnects to your repo in 60 seconds.\n\nI need 20 indie hackers to beta test.\n\nShip code solo and struggle with prioritization? DM me. 👋\n\n#buildinpublic",
25
+ "What's the #1 thing blocking you from shipping more?\n\nA) Too many ideas, can't prioritize\nB) Not enough coding time\nC) Stuck in planning/research hell\nD) Fear of shipping something broken\n\nDrop your answer 👇"
26
+ ],
27
+ "scheduled_date": "2026-02-23"
28
+ },
29
+ {
30
+ "id": "draft-301d9eae",
31
+ "text": "Hot take: most AI coding tools just make you faster at the wrong things.\n\nFaster at writing code ≠ faster at shipping.\n\nVibeBusiness skips 'how do I build this?' and starts with 'what should I build next?'\n\nDifferent layer. Way bigger leverage.\n\n#buildinpublic",
32
+ "source": "insight",
33
+ "source_ref": null,
34
+ "status": "draft",
35
+ "created_at": "2026-02-22T21:40:50.506Z",
36
+ "published_at": null,
37
+ "tweet_id": null,
38
+ "tweet_url": null,
39
+ "media_paths": null,
40
+ "scheduled_date": "2026-02-24"
41
+ },
42
+ {
43
+ "id": "draft-3da42b09",
44
+ "text": "Stripe just went live in VibeBusiness. 🎉\n\nThe AI now factors in:\n→ Your MRR and churn\n→ Who's paying (and who's dropping off)\n→ Where the funnel breaks\n\nMost tools show you the data.\nThis one decides what to build based on it.\n\nDay 4 of 90. #buildinpublic",
45
+ "source": "insight",
46
+ "source_ref": null,
47
+ "status": "draft",
48
+ "created_at": "2026-02-22T21:40:50.506Z",
49
+ "published_at": null,
50
+ "tweet_id": null,
51
+ "tweet_url": null,
52
+ "media_paths": null,
53
+ "scheduled_date": "2026-02-25"
54
+ },
55
+ {
56
+ "id": "draft-138c8256",
57
+ "text": "I run `vibebusiness heartbeat` 3x per day.\n\nEach time: AI scans my codebase, checks metrics, picks the highest-leverage task, and ships it.\n\nHere's what one heartbeat actually looks like — step by step 🧵",
58
+ "source": "thread",
59
+ "source_ref": null,
60
+ "status": "draft",
61
+ "created_at": "2026-02-22T21:40:50.506Z",
62
+ "published_at": null,
63
+ "tweet_id": null,
64
+ "tweet_url": null,
65
+ "is_thread": true,
66
+ "thread_tweets": [
67
+ "I run `vibebusiness heartbeat` 3x per day.\n\nEach time: AI scans my codebase, checks metrics, picks the highest-leverage task, and ships it.\n\nHere's what one heartbeat actually looks like — step by step 🧵",
68
+ "Step 1: Read state.\n\nThe AI reads TODO.md, STATUS.md, MEMORY.md, and all data files.\n\nIt knows:\n• What's been done\n• What's blocked\n• Current metrics\n• What's been tried before\n\nContext is everything.",
69
+ "Step 2: Reason.\n\nClaude asks:\n→ What's the most important thing right now?\n→ Can I execute this autonomously?\n→ What's the expected impact?\n\nIt outputs a structured decision with a confidence score.\n\nNo vibes. Just logic.",
70
+ "Step 3: Execute.\n\nIf autonomous → implements directly\nIf human-needed → flags to Blocked\n\nNo wasted cycles. No hallucinated shell commands.\n\nThere's a 3-layer safety gate to stop the AI from acting on things it can't actually do.",
71
+ "Step 4: Verify + update state.\n\nAfter shipping, it updates STATUS.md.\n\nNext heartbeat starts with full context.\n\nThis is continuous improvement — without a PM, a standup, or a quarterly OKR session.",
72
+ "The hardest part wasn't the code.\n\nIt was teaching the AI to know when NOT to act.\n\nMost AI agents fail here — they try everything and hallucinate through blockers.\n\nWhat's your biggest fear about autonomous AI agents? 👇\n\n#buildinpublic"
73
+ ],
74
+ "scheduled_date": "2026-02-26"
75
+ },
76
+ {
77
+ "id": "draft-1dffa7b2",
78
+ "text": "Week 1 of building VibeBusiness in public: done.\n\nShipped:\n✅ Stripe payments live\n✅ npm package published\n✅ Landing page + OG tags\n✅ Social proof section\n\nNext milestone: 20 beta users.\n\nSolo dev who can't prioritize what to build? I want you.\n\nWhat's your stack? 👇 #buildinpu...",
79
+ "source": "insight",
80
+ "source_ref": null,
81
+ "status": "draft",
82
+ "created_at": "2026-02-22T21:40:50.506Z",
83
+ "published_at": null,
84
+ "tweet_id": null,
85
+ "tweet_url": null,
86
+ "media_paths": null,
87
+ "scheduled_date": "2026-02-27"
88
+ }
89
+ ],
7
90
  "metrics": {
8
- "followers_count": 334,
91
+ "followers_count": 335,
9
92
  "post_streak_days": 0,
10
93
  "total_posts": 0,
11
94
  "last_post_date": null
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibebusiness",
3
- "version": "1.2.49",
3
+ "version": "1.2.53",
4
4
  "description": "AI-powered autonomous product manager. Research. Build. Ship. Grow.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "private": false,
@@ -21,6 +21,7 @@ import { v4 as uuidv4 } from 'uuid';
21
21
  import { getAnalysisPrompt } from '../src/lib/prompts';
22
22
  import type { AnalystConfig as ImportedAnalystConfig, BusinessConfig } from '../src/lib/types';
23
23
  import { atomicWriteFileSync } from './lib/json-lock';
24
+ import { requireClaudeCLI } from './lib/ai-provider';
24
25
 
25
26
  // Local type alias for compatibility
26
27
  type AnalystConfig = ImportedAnalystConfig;
@@ -454,6 +455,8 @@ async function runClaudeAnalysis(
454
455
  config: AnalystConfig,
455
456
  timeoutMs: number = 600000 // 10 minute default timeout
456
457
  ): Promise<string> {
458
+ requireClaudeCLI('codebase analysis');
459
+
457
460
  return new Promise((resolve, reject) => {
458
461
  // Build the command to run Claude Code
459
462
  // We'll use the --print flag to get the response directly
@@ -562,6 +565,13 @@ async function runClaudeAnalysis(
562
565
 
563
566
  // Generate a codebase snapshot for the heartbeat
564
567
  async function generateCodebaseSnapshot(config: AnalystConfig): Promise<void> {
568
+ try {
569
+ requireClaudeCLI('codebase snapshot');
570
+ } catch {
571
+ console.log('Skipping codebase snapshot (Claude Code CLI not available)');
572
+ return;
573
+ }
574
+
565
575
  const snapshotPath = path.join(DATA_DIR, 'codebase-snapshot.json');
566
576
 
567
577
  console.log('Generating codebase snapshot...');
@@ -14,11 +14,13 @@
14
14
  * npx tsx scripts/implement.ts --idea=idea-demo003
15
15
  */
16
16
 
17
- import { execSync, spawn } from 'child_process';
17
+ import { execFileSync, spawn } from 'child_process';
18
18
  import * as fs from 'fs';
19
19
  import * as path from 'path';
20
- import { cleanGitState, exec } from './lib/git-utils';
20
+ import { cleanGitState, exec, execGit } from './lib/git-utils';
21
+ import { validateBranchName, sanitizeForCommitMessage } from './lib/shell-safe';
21
22
  import { atomicWriteFileSync } from './lib/json-lock';
23
+ import { requireClaudeCLI } from './lib/ai-provider';
22
24
 
23
25
  // Types (duplicated to avoid import issues with tsx)
24
26
  interface RepoConfig {
@@ -269,19 +271,19 @@ function setupWorkspace(repo: RepoConfig, workspaceDir: string, implId: string):
269
271
  const currentOrigin = exec('git remote get-url origin', repoWorkspace);
270
272
  if (!currentOrigin.includes('github.com')) {
271
273
  addLog(implId, `Repointing origin from local path to ${repo.github_url}`);
272
- exec(`git remote set-url origin ${repo.github_url}`, repoWorkspace);
274
+ execGit(['remote', 'set-url', 'origin', repo.github_url], repoWorkspace);
273
275
  }
274
276
  } catch {
275
277
  // If remote doesn't exist, add it
276
- exec(`git remote add origin ${repo.github_url}`, repoWorkspace);
278
+ execGit(['remote', 'add', 'origin', repo.github_url], repoWorkspace);
277
279
  }
278
280
  }
279
281
 
280
282
  // Update existing clone
281
283
  addLog(implId, `Updating existing clone at ${repoWorkspace}`);
282
- exec(`git fetch origin`, repoWorkspace);
283
- exec(`git checkout ${repo.default_branch || 'main'}`, repoWorkspace);
284
- exec(`git pull origin ${repo.default_branch || 'main'}`, repoWorkspace);
284
+ exec('git fetch origin', repoWorkspace);
285
+ execGit(['checkout', repo.default_branch || 'main'], repoWorkspace);
286
+ execGit(['pull', 'origin', repo.default_branch || 'main'], repoWorkspace);
285
287
  } else {
286
288
  // Clone fresh — prefer github_url, fall back to local path
287
289
  const cloneSource = repo.github_url || repo.path;
@@ -289,7 +291,7 @@ function setupWorkspace(repo: RepoConfig, workspaceDir: string, implId: string):
289
291
  throw new Error(`No github_url or path configured for repo: ${repo.name}`);
290
292
  }
291
293
  addLog(implId, `Cloning ${cloneSource} to ${repoWorkspace}`);
292
- exec(`git clone ${cloneSource} ${repoWorkspace}`);
294
+ execGit(['clone', cloneSource, repoWorkspace]);
293
295
  }
294
296
 
295
297
  return repoWorkspace;
@@ -297,20 +299,21 @@ function setupWorkspace(repo: RepoConfig, workspaceDir: string, implId: string):
297
299
 
298
300
  // Create feature branch
299
301
  function createBranch(workspacePath: string, branchName: string, defaultBranch: string, implId: string): void {
302
+ validateBranchName(branchName);
300
303
  addLog(implId, `Creating branch: ${branchName}`);
301
304
 
302
305
  // Make sure we're on the default branch
303
- exec(`git checkout ${defaultBranch}`, workspacePath);
306
+ execGit(['checkout', defaultBranch], workspacePath);
304
307
 
305
308
  // Check if branch already exists
306
309
  try {
307
- exec(`git rev-parse --verify ${branchName}`, workspacePath);
310
+ execGit(['rev-parse', '--verify', branchName], workspacePath);
308
311
  // Branch exists, check it out
309
312
  addLog(implId, `Branch ${branchName} already exists, checking out`);
310
- exec(`git checkout ${branchName}`, workspacePath);
313
+ execGit(['checkout', branchName], workspacePath);
311
314
  } catch {
312
315
  // Branch doesn't exist, create it
313
- exec(`git checkout -b ${branchName}`, workspacePath);
316
+ execGit(['checkout', '-b', branchName], workspacePath);
314
317
  }
315
318
  }
316
319
 
@@ -417,6 +420,8 @@ async function runImplementation(
417
420
  timeoutMs: number = 300000,
418
421
  options: { model?: string; scoped?: boolean } = {}
419
422
  ): Promise<boolean> {
423
+ requireClaudeCLI('implementation');
424
+
420
425
  const modelLabel = options.model ? ` (model: ${options.model})` : '';
421
426
  addLog(implId, `Running Claude Code to implement changes (timeout: ${timeoutMs / 1000}s${modelLabel})...`);
422
427
 
@@ -530,7 +535,7 @@ function createPR(
530
535
  ): { url: string; number: number } | null {
531
536
  // Check if there are commits ahead of default branch
532
537
  try {
533
- const ahead = exec(`git rev-list --count ${defaultBranch}..${branchName}`, workspacePath);
538
+ const ahead = execGit(['rev-list', '--count', `${defaultBranch}..${branchName}`], workspacePath);
534
539
  if (parseInt(ahead, 10) === 0) {
535
540
  addLog(implId, 'No commits to push, skipping PR creation');
536
541
  return null;
@@ -540,7 +545,7 @@ function createPR(
540
545
  }
541
546
 
542
547
  addLog(implId, `Pushing branch ${branchName} to origin`);
543
- exec(`git push -u origin ${branchName}`, workspacePath, 30000);
548
+ execGit(['push', '-u', 'origin', branchName], workspacePath, 30000);
544
549
 
545
550
  addLog(implId, 'Creating PR with gh CLI');
546
551
 
@@ -564,11 +569,11 @@ Idea ID: \`${idea.id}\`
564
569
  `;
565
570
 
566
571
  try {
567
- const prOutput = exec(
568
- `gh pr create --title "${title.replace(/"/g, '\\"')}" --body "${body.replace(/"/g, '\\"')}" --base ${defaultBranch}`,
569
- workspacePath,
570
- 30000
571
- );
572
+ const prOutput = execFileSync(
573
+ 'gh',
574
+ ['pr', 'create', '--title', title, '--body', body, '--base', defaultBranch],
575
+ { cwd: workspacePath, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 30000 }
576
+ ).trim();
572
577
 
573
578
  // Extract PR URL and number
574
579
  const urlMatch = prOutput.match(/https:\/\/github\.com\/[^\s]+\/pull\/(\d+)/);
@@ -670,22 +675,23 @@ async function main(): Promise<void> {
670
675
  try { exec('git fetch origin', workspacePath); } catch {}
671
676
 
672
677
  // Check out or create the feature branch
678
+ validateBranchName(branchName);
673
679
  addLog(impl.id, `Checking out branch: ${branchName}`);
674
680
  try {
675
- exec(`git checkout ${branchName}`, workspacePath);
681
+ execGit(['checkout', branchName], workspacePath);
676
682
  // Merge latest main into feature branch to stay current
677
683
  addLog(impl.id, `Merging origin/${defaultBranch} into ${branchName}...`);
678
684
  try {
679
- exec(`git merge origin/${defaultBranch} --no-edit`, workspacePath);
685
+ execGit(['merge', `origin/${defaultBranch}`, '--no-edit'], workspacePath);
680
686
  } catch {
681
687
  addLog(impl.id, 'Merge conflict detected, aborting merge');
682
- exec('git merge --abort', workspacePath);
688
+ execGit(['merge', '--abort'], workspacePath);
683
689
  }
684
690
  } catch {
685
691
  // Branch doesn't exist yet, create it from latest default branch
686
- exec(`git checkout ${defaultBranch}`, workspacePath);
687
- exec(`git pull origin ${defaultBranch}`, workspacePath);
688
- exec(`git checkout -b ${branchName}`, workspacePath);
692
+ execGit(['checkout', defaultBranch], workspacePath);
693
+ execGit(['pull', 'origin', defaultBranch], workspacePath);
694
+ execGit(['checkout', '-b', branchName], workspacePath);
689
695
  }
690
696
  } else {
691
697
  // Full workspace setup (original behavior)
@@ -746,7 +752,7 @@ async function main(): Promise<void> {
746
752
  addLog(impl.id, `Skipping junk file: ${file}`);
747
753
  continue;
748
754
  }
749
- exec(`git add "${file}"`, workspacePath);
755
+ execGit(['add', file], workspacePath);
750
756
  }
751
757
  } else {
752
758
  exec('git add -A', workspacePath);
@@ -755,10 +761,11 @@ async function main(): Promise<void> {
755
761
  // Only commit if there are staged changes
756
762
  const staged = exec('git diff --cached --stat', workspacePath);
757
763
  if (staged.trim().length > 0) {
764
+ const safeTitle = sanitizeForCommitMessage(idea.title);
758
765
  const commitMsg = scope
759
- ? `feat: ${idea.title} (sub-task)\n\nImplemented by AI Product Manager\nIdea: ${idea.id}`
760
- : `feat: ${idea.title}\n\nImplemented by AI Product Manager\nIdea: ${idea.id}`;
761
- exec(`git commit -m "${commitMsg}"`, workspacePath);
766
+ ? `feat: ${safeTitle} (sub-task)\n\nImplemented by AI Product Manager\nIdea: ${idea.id}`
767
+ : `feat: ${safeTitle}\n\nImplemented by AI Product Manager\nIdea: ${idea.id}`;
768
+ execGit(['commit', '-m', commitMsg], workspacePath);
762
769
  } else {
763
770
  addLog(impl.id, 'No staged changes after filtering, skipping commit');
764
771
  }
@@ -773,7 +780,7 @@ async function main(): Promise<void> {
773
780
  // Still push the branch so work isn't lost when workspace is deleted
774
781
  try {
775
782
  addLog(impl.id, `Pushing branch ${branchName} to origin`);
776
- exec(`git push -u origin ${branchName}`, workspacePath, 30000);
783
+ execGit(['push', '-u', 'origin', branchName], workspacePath, 30000);
777
784
  } catch (pushError) {
778
785
  addLog(impl.id, `Warning: Failed to push branch: ${(pushError as Error).message}`);
779
786
  // Don't fail the whole task if push fails - code is still committed locally