chiefwiggum 1.3.38 → 1.3.41

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 (2) hide show
  1. package/dist/cli.cjs +180 -19
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -95,6 +95,14 @@ async function multilineText(options) {
95
95
  });
96
96
  });
97
97
  }
98
+ async function multiselect2(options) {
99
+ const result = await p.multiselect({
100
+ message: options.message,
101
+ options: options.options,
102
+ required: options.required ?? false
103
+ });
104
+ return handleCancel(result);
105
+ }
98
106
  async function searchSelect(options) {
99
107
  const { message, items, placeholder = "Type to filter...", maxVisible = 10 } = options;
100
108
  const readline = await import("readline");
@@ -440,9 +448,10 @@ Then list open issues: gh issue list --state open
440
448
  Use this to update issue status on the project board (replace <issue_number> and <status_name>):
441
449
 
442
450
  \`\`\`bash
443
- # Get repo owner and project number
451
+ # Get repo owner, project number, and project ID
444
452
  OWNER=$(gh repo view --json owner -q .owner.login)
445
453
  PROJECT_NUM=$(gh repo view --json projectsV2 -q '.projectsV2.Nodes[0].number')
454
+ PROJECT_ID=$(gh repo view --json projectsV2 -q '.projectsV2.Nodes[0].id')
446
455
 
447
456
  # Get the issue's item ID in the project
448
457
  ITEM_ID=$(gh project item-list $PROJECT_NUM --owner $OWNER --format json | jq -r '.items[] | select(.content.number == <issue_number>) | .id')
@@ -452,7 +461,7 @@ FIELD_ID=$(gh project field-list $PROJECT_NUM --owner $OWNER --format json | jq
452
461
  STATUS_ID=$(gh project field-list $PROJECT_NUM --owner $OWNER --format json | jq -r '.fields[] | select(.name == "Status") | .options[] | select(.name == "<status_name>") | .id')
453
462
 
454
463
  # Update status (use "In Progress" when starting, "Done" when complete)
455
- gh project item-edit --project-id $PROJECT_NUM --id $ITEM_ID --field-id $FIELD_ID --single-select-option-id $STATUS_ID
464
+ gh project item-edit --project-id $PROJECT_ID --id $ITEM_ID --field-id $FIELD_ID --single-select-option-id $STATUS_ID
456
465
  \`\`\`
457
466
 
458
467
  If any step fails (no project linked, field not found), skip and continue.
@@ -1395,10 +1404,14 @@ Create 5-15 issues.${projectName ? ` Add each to project "${projectName}".` : ""
1395
1404
  const total = issues.length;
1396
1405
  console.log(import_picocolors7.default.dim(` Creating ${total} issues...`));
1397
1406
  let projectNumber = null;
1407
+ let projectId = null;
1408
+ let statusFieldId = null;
1409
+ let todoOptionId = null;
1410
+ const owner = repoName.split("/")[0];
1398
1411
  if (projectName) {
1399
1412
  try {
1400
1413
  const projectsOutput = (0, import_node_child_process6.execSync)(
1401
- `gh project list --owner ${repoName.split("/")[0]} --format json`,
1414
+ `gh project list --owner ${owner} --format json`,
1402
1415
  { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
1403
1416
  );
1404
1417
  const projects = JSON.parse(projectsOutput);
@@ -1407,11 +1420,35 @@ Create 5-15 issues.${projectName ? ` Add each to project "${projectName}".` : ""
1407
1420
  if (projectNumber) {
1408
1421
  try {
1409
1422
  (0, import_node_child_process6.execSync)(
1410
- `gh project link ${projectNumber} --owner ${repoName.split("/")[0]} --repo ${repoName}`,
1423
+ `gh project link ${projectNumber} --owner ${owner} --repo ${repoName}`,
1411
1424
  { stdio: ["pipe", "pipe", "pipe"] }
1412
1425
  );
1413
1426
  } catch {
1414
1427
  }
1428
+ try {
1429
+ const repoProjectsOutput = (0, import_node_child_process6.execSync)(
1430
+ `gh repo view --json projectsV2 -q '.projectsV2.Nodes[] | select(.number == ${projectNumber}) | .id'`,
1431
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
1432
+ );
1433
+ projectId = repoProjectsOutput.trim() || null;
1434
+ } catch {
1435
+ }
1436
+ if (projectId) {
1437
+ try {
1438
+ const fieldsOutput = (0, import_node_child_process6.execSync)(
1439
+ `gh project field-list ${projectNumber} --owner ${owner} --format json`,
1440
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
1441
+ );
1442
+ const fields = JSON.parse(fieldsOutput);
1443
+ const statusField = fields.fields?.find((f) => f.name === "Status");
1444
+ if (statusField) {
1445
+ statusFieldId = statusField.id;
1446
+ const todoOption = statusField.options?.find((o) => o.name === "Todo");
1447
+ todoOptionId = todoOption?.id || null;
1448
+ }
1449
+ } catch {
1450
+ }
1451
+ }
1415
1452
  }
1416
1453
  } catch {
1417
1454
  }
@@ -1425,6 +1462,13 @@ Create 5-15 issues.${projectName ? ` Add each to project "${projectName}".` : ""
1425
1462
  availableLabels = new Set(labelsOutput.trim().split("\n").filter(Boolean));
1426
1463
  } catch {
1427
1464
  }
1465
+ try {
1466
+ (0, import_node_child_process6.execSync)(
1467
+ `gh label create chiefwiggum --description "Created by Chief Wiggum CLI" --color "FFA500" 2>/dev/null || true`,
1468
+ { stdio: ["pipe", "pipe", "pipe"] }
1469
+ );
1470
+ } catch {
1471
+ }
1428
1472
  let created = 0;
1429
1473
  let failed = 0;
1430
1474
  const failedIssues = [];
@@ -1438,7 +1482,8 @@ Create 5-15 issues.${projectName ? ` Add each to project "${projectName}".` : ""
1438
1482
  process.stdout.write(`\r ${bar} ${progress}% (${i + 1}/${total}) Creating: ${issue.title.slice(0, 40)}...`.padEnd(100));
1439
1483
  try {
1440
1484
  const validLabels = issue.labels.filter((label) => availableLabels.size === 0 || availableLabels.has(label));
1441
- const labelsArg = validLabels.length > 0 ? `--label "${validLabels.join(",")}"` : "";
1485
+ const allLabels = ["chiefwiggum", ...validLabels];
1486
+ const labelsArg = `--label "${allLabels.join(",")}"`;
1442
1487
  const escapeForShell = (str) => {
1443
1488
  return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/`/g, "\\`").replace(/\$/g, "\\$").replace(/!/g, "\\!").replace(/\n/g, "\\n");
1444
1489
  };
@@ -1451,10 +1496,23 @@ Create 5-15 issues.${projectName ? ` Add each to project "${projectName}".` : ""
1451
1496
  }).trim();
1452
1497
  if (projectNumber && issueUrl) {
1453
1498
  try {
1454
- (0, import_node_child_process6.execSync)(
1455
- `gh project item-add ${projectNumber} --owner ${repoName.split("/")[0]} --url "${issueUrl}"`,
1456
- { stdio: ["pipe", "pipe", "pipe"] }
1499
+ const addOutput = (0, import_node_child_process6.execSync)(
1500
+ `gh project item-add ${projectNumber} --owner ${owner} --url "${issueUrl}"`,
1501
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
1457
1502
  );
1503
+ if (projectId && statusFieldId && todoOptionId) {
1504
+ const itemIdMatch = addOutput.match(/Added item\s+(\S+)/i);
1505
+ const itemId = itemIdMatch?.[1];
1506
+ if (itemId) {
1507
+ try {
1508
+ (0, import_node_child_process6.execSync)(
1509
+ `gh project item-edit --project-id ${projectId} --id ${itemId} --field-id ${statusFieldId} --single-select-option-id ${todoOptionId}`,
1510
+ { stdio: ["pipe", "pipe", "pipe"] }
1511
+ );
1512
+ } catch {
1513
+ }
1514
+ }
1515
+ }
1458
1516
  } catch {
1459
1517
  }
1460
1518
  }
@@ -1478,7 +1536,11 @@ Create 5-15 issues.${projectName ? ` Add each to project "${projectName}".` : ""
1478
1536
  }
1479
1537
  }
1480
1538
  if (projectName && projectNumber) {
1481
- console.log(import_picocolors7.default.green(` \u2713 Added to board "${projectName}"`));
1539
+ if (todoOptionId) {
1540
+ console.log(import_picocolors7.default.green(` \u2713 Added to board "${projectName}" (Todo column)`));
1541
+ } else {
1542
+ console.log(import_picocolors7.default.green(` \u2713 Added to board "${projectName}"`));
1543
+ }
1482
1544
  }
1483
1545
  } else {
1484
1546
  console.log(import_picocolors7.default.green(" \u2713 GitHub Issues created"));
@@ -1711,11 +1773,110 @@ init_loop();
1711
1773
  // src/commands/clean.ts
1712
1774
  init_cjs_shims();
1713
1775
  var import_node_fs4 = require("fs");
1776
+ var import_node_child_process7 = require("child_process");
1714
1777
  var import_picocolors8 = __toESM(require("picocolors"), 1);
1715
1778
  init_prompts();
1779
+ init_new();
1780
+ async function removeIssues(numbers, action) {
1781
+ let success = 0;
1782
+ let failed = 0;
1783
+ for (const num of numbers) {
1784
+ try {
1785
+ if (action === "delete") {
1786
+ (0, import_node_child_process7.execSync)(`gh issue delete ${num} --yes`, { stdio: ["pipe", "pipe", "pipe"] });
1787
+ } else {
1788
+ (0, import_node_child_process7.execSync)(`gh issue close ${num}`, { stdio: ["pipe", "pipe", "pipe"] });
1789
+ }
1790
+ console.log(import_picocolors8.default.green(`\u2713 #${num} ${action === "delete" ? "deleted" : "closed"}`));
1791
+ success++;
1792
+ } catch {
1793
+ console.log(import_picocolors8.default.red(`\u2717 #${num} failed`));
1794
+ failed++;
1795
+ }
1796
+ }
1797
+ console.log();
1798
+ console.log(`${action === "delete" ? "Deleted" : "Closed"}: ${success}, Failed: ${failed}`);
1799
+ }
1800
+ async function cleanGitHubIssues() {
1801
+ let issues = [];
1802
+ try {
1803
+ const output = (0, import_node_child_process7.execSync)(
1804
+ `gh issue list --label chiefwiggum --state open --json number,title,createdAt --limit 100`,
1805
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
1806
+ );
1807
+ issues = JSON.parse(output);
1808
+ } catch {
1809
+ console.log(import_picocolors8.default.yellow("Could not fetch GitHub issues."));
1810
+ return;
1811
+ }
1812
+ if (issues.length === 0) {
1813
+ console.log(import_picocolors8.default.dim("No open issues with 'chiefwiggum' label found."));
1814
+ return;
1815
+ }
1816
+ console.log();
1817
+ console.log(`Found ${issues.length} issues with 'chiefwiggum' label:`);
1818
+ for (const issue of issues) {
1819
+ console.log(` ${import_picocolors8.default.cyan(`#${issue.number}`)} - ${issue.title}`);
1820
+ }
1821
+ console.log();
1822
+ const action = await select2({
1823
+ message: "What would you like to do with these issues?",
1824
+ options: [
1825
+ { value: "close", label: "Close all", hint: "reversible" },
1826
+ { value: "delete", label: "Delete all", hint: "permanent" },
1827
+ { value: "pick", label: "Pick which to remove" },
1828
+ { value: "cancel", label: "Cancel" }
1829
+ ]
1830
+ });
1831
+ if (action === "cancel") {
1832
+ return;
1833
+ }
1834
+ if (action === "pick") {
1835
+ const selected = await multiselect2({
1836
+ message: "Select issues to remove (space to toggle, enter to confirm)",
1837
+ options: issues.map((i) => ({
1838
+ value: String(i.number),
1839
+ label: `#${i.number} - ${i.title}`
1840
+ }))
1841
+ });
1842
+ if (selected.length === 0) {
1843
+ console.log(import_picocolors8.default.yellow("No issues selected."));
1844
+ return;
1845
+ }
1846
+ const pickAction = await select2({
1847
+ message: `${selected.length} issues selected. Close or delete?`,
1848
+ options: [
1849
+ { value: "close", label: "Close", hint: "reversible" },
1850
+ { value: "delete", label: "Delete", hint: "permanent" }
1851
+ ]
1852
+ });
1853
+ await removeIssues(selected, pickAction);
1854
+ } else {
1855
+ const issueNumbers = issues.map((i) => String(i.number));
1856
+ const confirmMsg = action === "delete" ? `DELETE ${issues.length} issues? This cannot be undone!` : `Close ${issues.length} issues?`;
1857
+ const confirmed = await confirm2({
1858
+ message: confirmMsg,
1859
+ initialValue: false
1860
+ });
1861
+ if (confirmed) {
1862
+ await removeIssues(issueNumbers, action);
1863
+ }
1864
+ }
1865
+ }
1716
1866
  async function cmdClean() {
1717
1867
  console.log(import_picocolors8.default.bold("Clean Project"));
1718
1868
  console.log();
1869
+ const tracker = getProjectTracker();
1870
+ if (tracker === "github") {
1871
+ const cleanIssues = await confirm2({
1872
+ message: "Clean up GitHub Issues created by Chief Wiggum?",
1873
+ initialValue: false
1874
+ });
1875
+ if (cleanIssues) {
1876
+ await cleanGitHubIssues();
1877
+ }
1878
+ console.log();
1879
+ }
1719
1880
  const filesToRemove = [];
1720
1881
  if ((0, import_node_fs4.existsSync)(".chiefwiggum")) filesToRemove.push(".chiefwiggum/");
1721
1882
  if ((0, import_node_fs4.existsSync)("specs")) filesToRemove.push("specs/");
@@ -1749,7 +1910,7 @@ async function cmdClean() {
1749
1910
  // src/commands/config.ts
1750
1911
  init_cjs_shims();
1751
1912
  var import_node_fs5 = require("fs");
1752
- var import_node_child_process7 = require("child_process");
1913
+ var import_node_child_process8 = require("child_process");
1753
1914
  var import_picocolors9 = __toESM(require("picocolors"), 1);
1754
1915
  init_prompts();
1755
1916
  var CONFIG_FILE2 = ".chiefwiggum/CLAUDE.md";
@@ -1782,17 +1943,17 @@ function saveConfig2(config2) {
1782
1943
  }
1783
1944
  function checkGitHubCLI2() {
1784
1945
  try {
1785
- (0, import_node_child_process7.execSync)("which gh", { stdio: ["pipe", "pipe", "pipe"] });
1946
+ (0, import_node_child_process8.execSync)("which gh", { stdio: ["pipe", "pipe", "pipe"] });
1786
1947
  } catch {
1787
1948
  return { ok: false, reason: "not_installed" };
1788
1949
  }
1789
1950
  try {
1790
- (0, import_node_child_process7.execSync)("gh auth status", { stdio: ["pipe", "pipe", "pipe"] });
1951
+ (0, import_node_child_process8.execSync)("gh auth status", { stdio: ["pipe", "pipe", "pipe"] });
1791
1952
  } catch {
1792
1953
  return { ok: false, reason: "not_authenticated" };
1793
1954
  }
1794
1955
  try {
1795
- const repo = (0, import_node_child_process7.execSync)("gh repo view --json nameWithOwner -q .nameWithOwner", {
1956
+ const repo = (0, import_node_child_process8.execSync)("gh repo view --json nameWithOwner -q .nameWithOwner", {
1796
1957
  encoding: "utf-8",
1797
1958
  stdio: ["pipe", "pipe", "pipe"]
1798
1959
  }).trim();
@@ -1882,7 +2043,7 @@ async function selectOrCreateProjectBoard2(knownRepo) {
1882
2043
  let repoName = knownRepo || "";
1883
2044
  if (!repoName) {
1884
2045
  try {
1885
- repoName = (0, import_node_child_process7.execSync)("gh repo view --json nameWithOwner -q .nameWithOwner", {
2046
+ repoName = (0, import_node_child_process8.execSync)("gh repo view --json nameWithOwner -q .nameWithOwner", {
1886
2047
  encoding: "utf-8",
1887
2048
  stdio: ["pipe", "pipe", "pipe"]
1888
2049
  }).trim();
@@ -1893,7 +2054,7 @@ async function selectOrCreateProjectBoard2(knownRepo) {
1893
2054
  }
1894
2055
  let existingProjects = [];
1895
2056
  try {
1896
- const projectsOutput = (0, import_node_child_process7.execSync)(`gh project list --owner ${repoName.split("/")[0]} --format json`, {
2057
+ const projectsOutput = (0, import_node_child_process8.execSync)(`gh project list --owner ${repoName.split("/")[0]} --format json`, {
1897
2058
  encoding: "utf-8",
1898
2059
  stdio: ["pipe", "pipe", "pipe"]
1899
2060
  });
@@ -1921,7 +2082,7 @@ async function selectOrCreateProjectBoard2(knownRepo) {
1921
2082
  });
1922
2083
  console.log(import_picocolors9.default.cyan(`Creating board "${projectName}"...`));
1923
2084
  try {
1924
- const createOutput = (0, import_node_child_process7.execSync)(
2085
+ const createOutput = (0, import_node_child_process8.execSync)(
1925
2086
  `gh project create --owner ${repoName.split("/")[0]} --title "${projectName}"`,
1926
2087
  { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
1927
2088
  );
@@ -1930,7 +2091,7 @@ async function selectOrCreateProjectBoard2(knownRepo) {
1930
2091
  console.log(import_picocolors9.default.green(`\u2713 Board "${projectName}" created`));
1931
2092
  if (projectNumber) {
1932
2093
  try {
1933
- (0, import_node_child_process7.execSync)(`gh project link ${projectNumber} --owner ${repoName.split("/")[0]} --repo ${repoName}`, {
2094
+ (0, import_node_child_process8.execSync)(`gh project link ${projectNumber} --owner ${repoName.split("/")[0]} --repo ${repoName}`, {
1934
2095
  stdio: ["pipe", "pipe", "pipe"]
1935
2096
  });
1936
2097
  console.log(import_picocolors9.default.green(`\u2713 Linked to ${repoName}`));
@@ -1945,14 +2106,14 @@ async function selectOrCreateProjectBoard2(knownRepo) {
1945
2106
  }
1946
2107
  } else if (selectedProject !== "__none__") {
1947
2108
  try {
1948
- const projectsOutput = (0, import_node_child_process7.execSync)(
2109
+ const projectsOutput = (0, import_node_child_process8.execSync)(
1949
2110
  `gh project list --owner ${repoName.split("/")[0]} --format json`,
1950
2111
  { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
1951
2112
  );
1952
2113
  const projects = JSON.parse(projectsOutput);
1953
2114
  const project = projects.projects?.find((p2) => p2.title === selectedProject);
1954
2115
  if (project?.number) {
1955
- (0, import_node_child_process7.execSync)(
2116
+ (0, import_node_child_process8.execSync)(
1956
2117
  `gh project link ${project.number} --owner ${repoName.split("/")[0]} --repo ${repoName}`,
1957
2118
  { stdio: ["pipe", "pipe", "pipe"] }
1958
2119
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chiefwiggum",
3
- "version": "1.3.38",
3
+ "version": "1.3.41",
4
4
  "description": "Autonomous coding agent CLI. Point it at a plan, watch it build.",
5
5
  "type": "module",
6
6
  "bin": {