claude-issue-solver 1.6.6 → 1.7.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.
package/README.md CHANGED
@@ -4,6 +4,18 @@ Automatically solve GitHub issues using [Claude Code](https://claude.ai/code).
4
4
 
5
5
  This CLI tool fetches an issue from your repo, creates a worktree, opens Claude Code in a new terminal to solve it, and creates a PR when done.
6
6
 
7
+ > **⚠️ DISCLAIMER: USE AT YOUR OWN RISK**
8
+ >
9
+ > This tool runs Claude Code with the `--dangerously-skip-permissions` flag, which allows Claude to execute commands and modify files **without asking for confirmation**. This is powerful but potentially risky.
10
+ >
11
+ > **Before using this tool:**
12
+ > - Understand that Claude will have unrestricted access to your codebase
13
+ > - Review what Claude is doing in the terminal
14
+ > - Use git to review changes before merging PRs
15
+ > - Never run this on production systems or sensitive repositories without careful consideration
16
+ >
17
+ > By using this tool, you accept full responsibility for any changes made to your code.
18
+
7
19
  ## Demo
8
20
 
9
21
  ```bash
@@ -78,6 +90,12 @@ claude-issue pr 42
78
90
  # Clean up worktree and branch after PR is merged
79
91
  claude-issue clean 42
80
92
 
93
+ # Clean all worktrees (shows PR/issue status)
94
+ claude-issue clean
95
+
96
+ # Navigate to a worktree or open its PR
97
+ claude-issue go
98
+
81
99
  # Show help
82
100
  claude-issue --help
83
101
  ```
@@ -135,8 +153,9 @@ claude-issue --help
135
153
 
136
154
  - Use `/exit` in Claude to end the session and trigger PR creation
137
155
  - Worktrees share the same `.git` so commits are visible in main repo
138
- - Run `claude-issue clean <number>` after merging to clean up
156
+ - Run `claude-issue clean` after merging to clean up - it shows PR status (merged/open/closed)
139
157
  - You can work on multiple issues in parallel - each gets its own worktree
158
+ - Use `claude-issue go` to quickly navigate to worktrees or open PRs in browser
140
159
 
141
160
  ## License
142
161
 
@@ -45,6 +45,7 @@ const fs = __importStar(require("fs"));
45
45
  const path = __importStar(require("path"));
46
46
  const os = __importStar(require("os"));
47
47
  const child_process_1 = require("child_process");
48
+ const github_1 = require("../utils/github");
48
49
  const git_1 = require("../utils/git");
49
50
  function closeWindowsWithPath(folderPath, issueNumber) {
50
51
  if (os.platform() !== 'darwin')
@@ -119,6 +120,30 @@ function closeWindowsWithPath(folderPath, issueNumber) {
119
120
  // VS Code not running or no matching windows
120
121
  }
121
122
  }
123
+ function getStatusLabel(wt) {
124
+ if (!wt.branch) {
125
+ return chalk_1.default.yellow('(orphaned folder)');
126
+ }
127
+ if (wt.prStatus) {
128
+ switch (wt.prStatus.state) {
129
+ case 'merged':
130
+ return chalk_1.default.green('✓ PR merged');
131
+ case 'open':
132
+ return chalk_1.default.blue('◐ PR open');
133
+ case 'closed':
134
+ return chalk_1.default.red('✗ PR closed');
135
+ }
136
+ }
137
+ if (wt.issueStatus) {
138
+ switch (wt.issueStatus.state) {
139
+ case 'closed':
140
+ return chalk_1.default.dim('● Issue closed');
141
+ case 'open':
142
+ return chalk_1.default.cyan('○ Issue open');
143
+ }
144
+ }
145
+ return chalk_1.default.dim('? Unknown');
146
+ }
122
147
  function getIssueWorktrees() {
123
148
  const projectRoot = (0, git_1.getProjectRoot)();
124
149
  const projectName = (0, git_1.getProjectName)();
@@ -184,9 +209,21 @@ async function cleanAllCommand() {
184
209
  console.log(chalk_1.default.yellow('\nNo issue worktrees found.'));
185
210
  return;
186
211
  }
212
+ // Fetch status for all worktrees
213
+ const statusSpinner = (0, ora_1.default)('Fetching issue and PR status...').start();
214
+ const worktreesWithStatus = worktrees.map((wt) => ({
215
+ ...wt,
216
+ issueStatus: (0, github_1.getIssueStatus)(parseInt(wt.issueNumber, 10)),
217
+ prStatus: wt.branch ? (0, github_1.getPRForBranch)(wt.branch) : null,
218
+ }));
219
+ statusSpinner.stop();
187
220
  console.log(chalk_1.default.bold('\n🧹 Found issue worktrees:\n'));
188
- for (const wt of worktrees) {
189
- console.log(` ${chalk_1.default.cyan(`#${wt.issueNumber}`)}\t${wt.branch || chalk_1.default.yellow('(orphaned folder)')}`);
221
+ for (const wt of worktreesWithStatus) {
222
+ const status = getStatusLabel(wt);
223
+ console.log(` ${chalk_1.default.cyan(`#${wt.issueNumber}`)}\t${status}`);
224
+ if (wt.branch) {
225
+ console.log(chalk_1.default.dim(` \t${wt.branch}`));
226
+ }
190
227
  console.log(chalk_1.default.dim(` \t${wt.path}`));
191
228
  console.log();
192
229
  }
@@ -319,12 +356,21 @@ async function cleanCommand(issueNumber) {
319
356
  const branchName = worktree.branch;
320
357
  const worktreePath = worktree.path;
321
358
  const isOrphaned = !branchName;
359
+ // Fetch status
360
+ const statusSpinner = (0, ora_1.default)('Fetching issue and PR status...').start();
361
+ const issueStatus = (0, github_1.getIssueStatus)(issueNumber);
362
+ const prStatus = branchName ? (0, github_1.getPRForBranch)(branchName) : null;
363
+ statusSpinner.stop();
364
+ const wtWithStatus = {
365
+ ...worktree,
366
+ issueStatus,
367
+ prStatus,
368
+ };
369
+ const status = getStatusLabel(wtWithStatus);
322
370
  console.log();
323
371
  console.log(chalk_1.default.bold(`🧹 Cleaning up issue #${issueNumber}`));
324
- if (isOrphaned) {
325
- console.log(chalk_1.default.yellow(` (Orphaned folder - no git worktree reference)`));
326
- }
327
- else {
372
+ console.log(` Status: ${status}`);
373
+ if (!isOrphaned) {
328
374
  console.log(chalk_1.default.dim(` Branch: ${branchName}`));
329
375
  }
330
376
  console.log(chalk_1.default.dim(` Folder: ${worktreePath}`));
@@ -11,3 +11,12 @@ export interface IssueListItem {
11
11
  export declare function getIssue(issueNumber: number): Issue | null;
12
12
  export declare function listIssues(limit?: number): IssueListItem[];
13
13
  export declare function createPullRequest(title: string, body: string, branch: string, base?: string): string;
14
+ export interface IssueStatus {
15
+ state: 'open' | 'closed';
16
+ }
17
+ export interface PRStatus {
18
+ state: 'open' | 'closed' | 'merged';
19
+ url: string;
20
+ }
21
+ export declare function getIssueStatus(issueNumber: number): IssueStatus | null;
22
+ export declare function getPRForBranch(branch: string): PRStatus | null;
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getIssue = getIssue;
4
4
  exports.listIssues = listIssues;
5
5
  exports.createPullRequest = createPullRequest;
6
+ exports.getIssueStatus = getIssueStatus;
7
+ exports.getPRForBranch = getPRForBranch;
6
8
  const child_process_1 = require("child_process");
7
9
  function getIssue(issueNumber) {
8
10
  try {
@@ -32,3 +34,30 @@ function createPullRequest(title, body, branch, base = 'main') {
32
34
  const output = (0, child_process_1.execSync)(`gh pr create --title "${title}" --body "${body.replace(/"/g, '\\"')}" --head "${branch}" --base "${base}"`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
33
35
  return output.trim();
34
36
  }
37
+ function getIssueStatus(issueNumber) {
38
+ try {
39
+ const output = (0, child_process_1.execSync)(`gh issue view ${issueNumber} --json state`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
40
+ const data = JSON.parse(output);
41
+ return {
42
+ state: data.state.toLowerCase(),
43
+ };
44
+ }
45
+ catch {
46
+ return null;
47
+ }
48
+ }
49
+ function getPRForBranch(branch) {
50
+ try {
51
+ const output = (0, child_process_1.execSync)(`gh pr list --head "${branch}" --state all --json state,url --limit 1`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
52
+ const data = JSON.parse(output);
53
+ if (data.length === 0)
54
+ return null;
55
+ return {
56
+ state: data[0].state.toLowerCase(),
57
+ url: data[0].url,
58
+ };
59
+ }
60
+ catch {
61
+ return null;
62
+ }
63
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-issue-solver",
3
- "version": "1.6.6",
3
+ "version": "1.7.0",
4
4
  "description": "Automatically solve GitHub issues using Claude Code",
5
5
  "main": "dist/index.js",
6
6
  "bin": {