claude-issue-solver 1.2.0 โ†’ 1.4.0

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.
@@ -1 +1,2 @@
1
+ export declare function cleanAllCommand(): Promise<void>;
1
2
  export declare function cleanCommand(issueNumber: number): Promise<void>;
@@ -36,6 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.cleanAllCommand = cleanAllCommand;
39
40
  exports.cleanCommand = cleanCommand;
40
41
  const chalk_1 = __importDefault(require("chalk"));
41
42
  const ora_1 = __importDefault(require("ora"));
@@ -46,6 +47,94 @@ const child_process_1 = require("child_process");
46
47
  const github_1 = require("../utils/github");
47
48
  const git_1 = require("../utils/git");
48
49
  const helpers_1 = require("../utils/helpers");
50
+ function getIssueWorktrees() {
51
+ const projectRoot = (0, git_1.getProjectRoot)();
52
+ const projectName = (0, git_1.getProjectName)();
53
+ const parentDir = path.dirname(projectRoot);
54
+ const worktrees = [];
55
+ // Get all worktrees from git
56
+ const output = (0, git_1.exec)('git worktree list --porcelain', projectRoot);
57
+ if (!output)
58
+ return worktrees;
59
+ const lines = output.split('\n');
60
+ let currentPath = '';
61
+ let currentBranch = '';
62
+ for (const line of lines) {
63
+ if (line.startsWith('worktree ')) {
64
+ currentPath = line.replace('worktree ', '');
65
+ }
66
+ else if (line.startsWith('branch refs/heads/')) {
67
+ currentBranch = line.replace('branch refs/heads/', '');
68
+ // Check if this is an issue branch
69
+ const match = currentBranch.match(/^issue-(\d+)-/);
70
+ if (match && currentPath.includes(`${projectName}-issue-`)) {
71
+ worktrees.push({
72
+ path: currentPath,
73
+ branch: currentBranch,
74
+ issueNumber: match[1],
75
+ });
76
+ }
77
+ }
78
+ }
79
+ return worktrees;
80
+ }
81
+ async function cleanAllCommand() {
82
+ const projectRoot = (0, git_1.getProjectRoot)();
83
+ const worktrees = getIssueWorktrees();
84
+ if (worktrees.length === 0) {
85
+ console.log(chalk_1.default.yellow('\nNo issue worktrees found.'));
86
+ return;
87
+ }
88
+ console.log(chalk_1.default.bold('\n๐Ÿงน Found issue worktrees:\n'));
89
+ for (const wt of worktrees) {
90
+ console.log(` ${chalk_1.default.cyan(`#${wt.issueNumber}`)}\t${wt.branch}`);
91
+ console.log(chalk_1.default.dim(` \t${wt.path}`));
92
+ console.log();
93
+ }
94
+ const { confirm } = await inquirer_1.default.prompt([
95
+ {
96
+ type: 'confirm',
97
+ name: 'confirm',
98
+ message: `Remove all ${worktrees.length} worktree(s) and delete branches?`,
99
+ default: false,
100
+ },
101
+ ]);
102
+ if (!confirm) {
103
+ console.log(chalk_1.default.dim('Cancelled.'));
104
+ return;
105
+ }
106
+ console.log();
107
+ for (const wt of worktrees) {
108
+ const spinner = (0, ora_1.default)(`Cleaning issue #${wt.issueNumber}...`).start();
109
+ try {
110
+ // Remove worktree
111
+ if (fs.existsSync(wt.path)) {
112
+ (0, child_process_1.execSync)(`git worktree remove "${wt.path}" --force`, {
113
+ cwd: projectRoot,
114
+ stdio: 'pipe',
115
+ });
116
+ }
117
+ // Delete branch
118
+ try {
119
+ (0, child_process_1.execSync)(`git branch -D "${wt.branch}"`, {
120
+ cwd: projectRoot,
121
+ stdio: 'pipe',
122
+ });
123
+ }
124
+ catch {
125
+ // Branch may already be deleted
126
+ }
127
+ spinner.succeed(`Cleaned issue #${wt.issueNumber}`);
128
+ }
129
+ catch (error) {
130
+ spinner.fail(`Failed to clean issue #${wt.issueNumber}`);
131
+ }
132
+ }
133
+ // Prune stale worktrees
134
+ (0, child_process_1.execSync)('git worktree prune', { cwd: projectRoot, stdio: 'pipe' });
135
+ console.log();
136
+ console.log(chalk_1.default.green(`โœ… Cleaned up ${worktrees.length} issue worktree(s)!`));
137
+ }
49
138
  async function cleanCommand(issueNumber) {
50
139
  const spinner = (0, ora_1.default)(`Fetching issue #${issueNumber}...`).start();
51
140
  const issue = (0, github_1.getIssue)(issueNumber);
@@ -122,6 +122,10 @@ Instructions:
122
122
  const runnerScript = path.join(worktreePath, '.claude-runner.sh');
123
123
  const runnerContent = `#!/bin/bash
124
124
  cd "${worktreePath}"
125
+
126
+ # Set terminal title
127
+ echo -ne "\\033]0;Issue #${issueNumber}: ${issue.title.replace(/"/g, '\\"').slice(0, 50)}\\007"
128
+
125
129
  echo "๐Ÿค– Claude Code - Issue #${issueNumber}: ${issue.title}"
126
130
  echo "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”"
127
131
  echo ""
@@ -164,14 +168,24 @@ $COMMIT_LIST
164
168
 
165
169
  if [ -n "$PR_URL" ]; then
166
170
  echo ""
167
- echo "โœ… PR created: $PR_URL"
171
+ echo "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”"
172
+ echo "โœ… PR CREATED!"
173
+ echo ""
174
+ echo " $PR_URL"
175
+ echo ""
176
+ echo "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”"
168
177
  echo ""
178
+ # Update terminal title with PR info
179
+ PR_NUM=$(echo "$PR_URL" | grep -oE '[0-9]+$')
180
+ echo -ne "\\033]0;Issue #${issueNumber} โ†’ PR #\$PR_NUM\\007"
169
181
  fi
170
182
  else
171
183
  # PR exists, just push new commits
172
184
  git push origin "${branchName}" 2>/dev/null
173
185
  echo ""
174
- echo "๐Ÿ“ค Pushed new commits to existing PR #$EXISTING_PR"
186
+ echo "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”"
187
+ echo "๐Ÿ“ค Pushed new commits to PR #$EXISTING_PR"
188
+ echo "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”"
175
189
  echo ""
176
190
  fi
177
191
  fi
package/dist/index.js CHANGED
@@ -72,15 +72,25 @@ program
72
72
  });
73
73
  // Clean command
74
74
  program
75
- .command('clean <issue>')
75
+ .command('clean [issue]')
76
76
  .alias('rm')
77
- .description('Remove worktree and branch for an issue')
78
- .action(async (issue) => {
79
- const issueNumber = parseInt(issue, 10);
80
- if (isNaN(issueNumber)) {
81
- console.log(chalk_1.default.red(`โŒ Invalid issue number: ${issue}`));
82
- process.exit(1);
77
+ .option('-a, --all', 'Clean all issue worktrees')
78
+ .description('Remove worktree and branch for an issue (or all with --all)')
79
+ .action(async (issue, options) => {
80
+ if (options.all) {
81
+ await (0, clean_1.cleanAllCommand)();
82
+ }
83
+ else if (issue) {
84
+ const issueNumber = parseInt(issue, 10);
85
+ if (isNaN(issueNumber)) {
86
+ console.log(chalk_1.default.red(`โŒ Invalid issue number: ${issue}`));
87
+ process.exit(1);
88
+ }
89
+ await (0, clean_1.cleanCommand)(issueNumber);
90
+ }
91
+ else {
92
+ // No issue and no --all flag, show all and let user choose
93
+ await (0, clean_1.cleanAllCommand)();
83
94
  }
84
- await (0, clean_1.cleanCommand)(issueNumber);
85
95
  });
86
96
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-issue-solver",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "Automatically solve GitHub issues using Claude Code",
5
5
  "main": "dist/index.js",
6
6
  "bin": {