chiefwiggum 1.3.20 → 1.3.22
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.
- package/dist/cli.cjs +160 -22
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -818,7 +818,7 @@ function checkGitHubCLI() {
|
|
|
818
818
|
async function setupProjectConfig() {
|
|
819
819
|
const existingConfig = getConfig();
|
|
820
820
|
if ((0, import_node_fs3.existsSync)(CONFIG_FILE)) {
|
|
821
|
-
if (existingConfig.projectTracker === "github" && existingConfig.githubProject
|
|
821
|
+
if (existingConfig.projectTracker === "github" && !existingConfig.githubProject) {
|
|
822
822
|
const ghCheck = checkGitHubCLI();
|
|
823
823
|
if (ghCheck.ok) {
|
|
824
824
|
const projectName = await selectOrCreateProjectBoard(ghCheck.repo);
|
|
@@ -932,16 +932,45 @@ async function selectOrCreateProjectBoard(knownRepo) {
|
|
|
932
932
|
});
|
|
933
933
|
console.log(import_picocolors7.default.cyan(`Creating board "${projectName}"...`));
|
|
934
934
|
try {
|
|
935
|
-
(0, import_node_child_process6.execSync)(
|
|
936
|
-
|
|
937
|
-
|
|
935
|
+
const createOutput = (0, import_node_child_process6.execSync)(
|
|
936
|
+
`gh project create --owner ${repoName.split("/")[0]} --title "${projectName}"`,
|
|
937
|
+
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
938
|
+
);
|
|
939
|
+
const projectNumberMatch = createOutput.match(/projects\/(\d+)/);
|
|
940
|
+
const projectNumber = projectNumberMatch ? projectNumberMatch[1] : null;
|
|
938
941
|
console.log(import_picocolors7.default.green(`\u2713 Board "${projectName}" created`));
|
|
942
|
+
if (projectNumber) {
|
|
943
|
+
try {
|
|
944
|
+
(0, import_node_child_process6.execSync)(`gh project link ${projectNumber} --owner ${repoName.split("/")[0]} --repo ${repoName}`, {
|
|
945
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
946
|
+
});
|
|
947
|
+
console.log(import_picocolors7.default.green(`\u2713 Linked to ${repoName}`));
|
|
948
|
+
} catch {
|
|
949
|
+
console.log(import_picocolors7.default.dim(` Note: Board created at org level. Link manually from repo's Projects tab.`));
|
|
950
|
+
}
|
|
951
|
+
}
|
|
939
952
|
return projectName;
|
|
940
953
|
} catch {
|
|
941
954
|
console.log(import_picocolors7.default.yellow("Could not create board. Issues will be created without one."));
|
|
942
955
|
return null;
|
|
943
956
|
}
|
|
944
957
|
} else if (selectedProject !== "__none__") {
|
|
958
|
+
try {
|
|
959
|
+
const projectsOutput = (0, import_node_child_process6.execSync)(
|
|
960
|
+
`gh project list --owner ${repoName.split("/")[0]} --format json`,
|
|
961
|
+
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
962
|
+
);
|
|
963
|
+
const projects = JSON.parse(projectsOutput);
|
|
964
|
+
const project = projects.projects?.find((p2) => p2.title === selectedProject);
|
|
965
|
+
if (project?.number) {
|
|
966
|
+
(0, import_node_child_process6.execSync)(
|
|
967
|
+
`gh project link ${project.number} --owner ${repoName.split("/")[0]} --repo ${repoName}`,
|
|
968
|
+
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
969
|
+
);
|
|
970
|
+
console.log(import_picocolors7.default.green(`\u2713 Linked "${selectedProject}" to ${repoName}`));
|
|
971
|
+
}
|
|
972
|
+
} catch {
|
|
973
|
+
}
|
|
945
974
|
return selectedProject;
|
|
946
975
|
}
|
|
947
976
|
return null;
|
|
@@ -1107,9 +1136,8 @@ Write directly to CLAUDE.md.`;
|
|
|
1107
1136
|
if (projectName) {
|
|
1108
1137
|
console.log(import_picocolors7.default.dim(` Issues will be added to board: ${projectName}`));
|
|
1109
1138
|
}
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
const issuesPrompt = `You are creating GitHub Issues based on specs.
|
|
1139
|
+
console.log(import_picocolors7.default.dim(" Planning issues..."));
|
|
1140
|
+
const issuesPrompt = `You are planning GitHub Issues based on specs.
|
|
1113
1141
|
|
|
1114
1142
|
Here is the PRD:
|
|
1115
1143
|
<prd>
|
|
@@ -1121,21 +1149,102 @@ Here is the Technical Specification:
|
|
|
1121
1149
|
${techGenerated}
|
|
1122
1150
|
</technical>
|
|
1123
1151
|
|
|
1124
|
-
|
|
1152
|
+
Generate a JSON array of issues to create. Each issue should have:
|
|
1153
|
+
- title: Clear, actionable title
|
|
1154
|
+
- body: Description of the task (markdown supported)
|
|
1155
|
+
- labels: Array of labels (e.g., ["phase-1", "enhancement"])
|
|
1156
|
+
|
|
1125
1157
|
Break down the work into granular issues (1-2 hours each).
|
|
1126
1158
|
Group related issues with labels like "phase-1", "phase-2", etc.
|
|
1127
|
-
|
|
1128
|
-
For each issue, run a command like:
|
|
1129
|
-
gh issue create --title "Issue title" --body "Description of the task" --label "phase-1"
|
|
1130
|
-
|
|
1131
|
-
${projectInstruction}
|
|
1132
|
-
|
|
1133
1159
|
Create 5-15 issues covering the full implementation.
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1160
|
+
|
|
1161
|
+
Output ONLY valid JSON, no other text:
|
|
1162
|
+
[
|
|
1163
|
+
{"title": "...", "body": "...", "labels": ["phase-1", "enhancement"]},
|
|
1164
|
+
...
|
|
1165
|
+
]`;
|
|
1166
|
+
const result = await runClaude({ prompt: issuesPrompt });
|
|
1167
|
+
let issues = [];
|
|
1168
|
+
let usedFallback = false;
|
|
1169
|
+
try {
|
|
1170
|
+
const jsonMatch = result.output.match(/\[[\s\S]*\]/);
|
|
1171
|
+
if (jsonMatch) {
|
|
1172
|
+
issues = JSON.parse(jsonMatch[0]);
|
|
1173
|
+
}
|
|
1174
|
+
} catch {
|
|
1175
|
+
}
|
|
1176
|
+
if (issues.length === 0) {
|
|
1177
|
+
console.log(import_picocolors7.default.dim(" Generating issues directly..."));
|
|
1178
|
+
const fallbackPrompt = `Create GitHub Issues using gh CLI for this project.
|
|
1179
|
+
PRD: ${prdGenerated.slice(0, 2e3)}
|
|
1180
|
+
Tech: ${techGenerated.slice(0, 2e3)}
|
|
1181
|
+
Run: gh issue create --title "..." --body "..." --label "phase-1"
|
|
1182
|
+
Create 5-15 issues.${projectName ? ` Add each to project "${projectName}".` : ""}`;
|
|
1183
|
+
await runClaude({ prompt: fallbackPrompt });
|
|
1184
|
+
usedFallback = true;
|
|
1185
|
+
}
|
|
1186
|
+
if (!usedFallback) {
|
|
1187
|
+
const total = issues.length;
|
|
1188
|
+
console.log(import_picocolors7.default.dim(` Creating ${total} issues...`));
|
|
1189
|
+
let projectNumber = null;
|
|
1190
|
+
if (projectName) {
|
|
1191
|
+
try {
|
|
1192
|
+
const projectsOutput = (0, import_node_child_process6.execSync)(
|
|
1193
|
+
`gh project list --owner ${repoName.split("/")[0]} --format json`,
|
|
1194
|
+
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
1195
|
+
);
|
|
1196
|
+
const projects = JSON.parse(projectsOutput);
|
|
1197
|
+
const project = projects.projects?.find((p2) => p2.title === projectName);
|
|
1198
|
+
projectNumber = project?.number?.toString() || null;
|
|
1199
|
+
} catch {
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
let created = 0;
|
|
1203
|
+
let failed = 0;
|
|
1204
|
+
for (let i = 0; i < issues.length; i++) {
|
|
1205
|
+
const issue = issues[i];
|
|
1206
|
+
const progress = Math.round((i + 1) / total * 100);
|
|
1207
|
+
const barWidth = 20;
|
|
1208
|
+
const filled = Math.round(progress / 100 * barWidth);
|
|
1209
|
+
const empty = barWidth - filled;
|
|
1210
|
+
const bar = import_picocolors7.default.green("\u2588".repeat(filled)) + import_picocolors7.default.dim("\u2591".repeat(empty));
|
|
1211
|
+
process.stdout.write(`\r ${bar} ${progress}% (${i + 1}/${total}) Creating: ${issue.title.slice(0, 40)}...`.padEnd(100));
|
|
1212
|
+
try {
|
|
1213
|
+
const labelsArg = issue.labels.length > 0 ? `--label "${issue.labels.join(",")}"` : "";
|
|
1214
|
+
const body = issue.body.replace(/"/g, '\\"').replace(/`/g, "\\`");
|
|
1215
|
+
const title = issue.title.replace(/"/g, '\\"');
|
|
1216
|
+
const createCmd = `gh issue create --title "${title}" --body "${body}" ${labelsArg}`;
|
|
1217
|
+
const issueUrl = (0, import_node_child_process6.execSync)(createCmd, {
|
|
1218
|
+
encoding: "utf-8",
|
|
1219
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
1220
|
+
}).trim();
|
|
1221
|
+
if (projectNumber && issueUrl) {
|
|
1222
|
+
try {
|
|
1223
|
+
(0, import_node_child_process6.execSync)(
|
|
1224
|
+
`gh project item-add ${projectNumber} --owner ${repoName.split("/")[0]} --url "${issueUrl}"`,
|
|
1225
|
+
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
1226
|
+
);
|
|
1227
|
+
} catch {
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
created++;
|
|
1231
|
+
} catch {
|
|
1232
|
+
failed++;
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
process.stdout.write("\r" + " ".repeat(100) + "\r");
|
|
1236
|
+
console.log(import_picocolors7.default.green(` \u2713 Created ${created} GitHub Issues`));
|
|
1237
|
+
if (failed > 0) {
|
|
1238
|
+
console.log(import_picocolors7.default.yellow(` \u26A0 ${failed} issues failed to create`));
|
|
1239
|
+
}
|
|
1240
|
+
if (projectName && projectNumber) {
|
|
1241
|
+
console.log(import_picocolors7.default.green(` \u2713 Added to board "${projectName}"`));
|
|
1242
|
+
}
|
|
1243
|
+
} else {
|
|
1244
|
+
console.log(import_picocolors7.default.green(" \u2713 GitHub Issues created"));
|
|
1245
|
+
if (projectName) {
|
|
1246
|
+
console.log(import_picocolors7.default.green(` \u2713 Added to board "${projectName}"`));
|
|
1247
|
+
}
|
|
1139
1248
|
}
|
|
1140
1249
|
} else {
|
|
1141
1250
|
console.log();
|
|
@@ -1388,16 +1497,45 @@ async function selectOrCreateProjectBoard2(knownRepo) {
|
|
|
1388
1497
|
});
|
|
1389
1498
|
console.log(import_picocolors9.default.cyan(`Creating board "${projectName}"...`));
|
|
1390
1499
|
try {
|
|
1391
|
-
(0, import_node_child_process7.execSync)(
|
|
1392
|
-
|
|
1393
|
-
|
|
1500
|
+
const createOutput = (0, import_node_child_process7.execSync)(
|
|
1501
|
+
`gh project create --owner ${repoName.split("/")[0]} --title "${projectName}"`,
|
|
1502
|
+
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
1503
|
+
);
|
|
1504
|
+
const projectNumberMatch = createOutput.match(/projects\/(\d+)/);
|
|
1505
|
+
const projectNumber = projectNumberMatch ? projectNumberMatch[1] : null;
|
|
1394
1506
|
console.log(import_picocolors9.default.green(`\u2713 Board "${projectName}" created`));
|
|
1507
|
+
if (projectNumber) {
|
|
1508
|
+
try {
|
|
1509
|
+
(0, import_node_child_process7.execSync)(`gh project link ${projectNumber} --owner ${repoName.split("/")[0]} --repo ${repoName}`, {
|
|
1510
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
1511
|
+
});
|
|
1512
|
+
console.log(import_picocolors9.default.green(`\u2713 Linked to ${repoName}`));
|
|
1513
|
+
} catch {
|
|
1514
|
+
console.log(import_picocolors9.default.dim(` Note: Board created at org level. Link manually from repo's Projects tab.`));
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1395
1517
|
return projectName;
|
|
1396
1518
|
} catch {
|
|
1397
1519
|
console.log(import_picocolors9.default.yellow("Could not create board."));
|
|
1398
1520
|
return null;
|
|
1399
1521
|
}
|
|
1400
1522
|
} else if (selectedProject !== "__none__") {
|
|
1523
|
+
try {
|
|
1524
|
+
const projectsOutput = (0, import_node_child_process7.execSync)(
|
|
1525
|
+
`gh project list --owner ${repoName.split("/")[0]} --format json`,
|
|
1526
|
+
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
1527
|
+
);
|
|
1528
|
+
const projects = JSON.parse(projectsOutput);
|
|
1529
|
+
const project = projects.projects?.find((p2) => p2.title === selectedProject);
|
|
1530
|
+
if (project?.number) {
|
|
1531
|
+
(0, import_node_child_process7.execSync)(
|
|
1532
|
+
`gh project link ${project.number} --owner ${repoName.split("/")[0]} --repo ${repoName}`,
|
|
1533
|
+
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
1534
|
+
);
|
|
1535
|
+
console.log(import_picocolors9.default.green(`\u2713 Linked "${selectedProject}" to ${repoName}`));
|
|
1536
|
+
}
|
|
1537
|
+
} catch {
|
|
1538
|
+
}
|
|
1401
1539
|
return selectedProject;
|
|
1402
1540
|
}
|
|
1403
1541
|
return null;
|