claude-issue-solver 1.8.3 → 1.10.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 +7 -0
- package/dist/commands/new.d.ts +4 -0
- package/dist/commands/new.js +23 -0
- package/dist/commands/select.js +13 -1
- package/dist/index.js +10 -0
- package/dist/utils/github.d.ts +6 -0
- package/dist/utils/github.js +47 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,6 +46,7 @@ Open issues for my-project:
|
|
|
46
46
|
## Features
|
|
47
47
|
|
|
48
48
|
- 🎯 **Interactive issue selection** - Lists open issues with arrow-key navigation
|
|
49
|
+
- ✨ **Create and solve** - Create new issues and start solving them immediately
|
|
49
50
|
- 🌿 **Worktree isolation** - Each issue gets its own worktree, work on multiple issues in parallel
|
|
50
51
|
- 🤖 **Automatic PR creation** - Creates a PR that closes the issue when merged
|
|
51
52
|
- 📁 **Works with any repo** - Auto-detects project name from git remote
|
|
@@ -100,6 +101,12 @@ claude-issue clean
|
|
|
100
101
|
# Navigate to a worktree or open its PR
|
|
101
102
|
claude-issue go
|
|
102
103
|
|
|
104
|
+
# Create a new issue and solve it immediately
|
|
105
|
+
claude-issue new "Add dark mode support"
|
|
106
|
+
|
|
107
|
+
# With description and labels
|
|
108
|
+
claude-issue new "Fix login bug" -b "Users can't login on mobile" -l bug
|
|
109
|
+
|
|
103
110
|
# Show help
|
|
104
111
|
claude-issue --help
|
|
105
112
|
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.newCommand = newCommand;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const ora_1 = __importDefault(require("ora"));
|
|
9
|
+
const github_1 = require("../utils/github");
|
|
10
|
+
const solve_1 = require("./solve");
|
|
11
|
+
async function newCommand(title, options) {
|
|
12
|
+
const spinner = (0, ora_1.default)('Creating issue...').start();
|
|
13
|
+
const issueNumber = (0, github_1.createIssue)(title, options.body, options.label);
|
|
14
|
+
if (!issueNumber) {
|
|
15
|
+
spinner.fail('Failed to create issue');
|
|
16
|
+
console.log(chalk_1.default.dim('Make sure you have write access to this repository.'));
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
spinner.succeed(`Created issue #${issueNumber}`);
|
|
20
|
+
console.log(chalk_1.default.dim(`Title: ${title}\n`));
|
|
21
|
+
// Now solve it immediately
|
|
22
|
+
await (0, solve_1.solveCommand)(issueNumber);
|
|
23
|
+
}
|
package/dist/commands/select.js
CHANGED
|
@@ -17,7 +17,19 @@ async function selectCommand() {
|
|
|
17
17
|
console.log(chalk_1.default.yellow('No open issues found.'));
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
// Filter out issues that already have open PRs
|
|
21
|
+
const issuesWithPRs = (0, github_1.getIssuesWithOpenPRs)();
|
|
22
|
+
const availableIssues = issues.filter((issue) => !issuesWithPRs.has(issue.number));
|
|
23
|
+
if (availableIssues.length === 0) {
|
|
24
|
+
console.log(chalk_1.default.yellow('All open issues already have PRs in progress.'));
|
|
25
|
+
console.log(chalk_1.default.dim('Use `claude-issue go` to navigate to existing worktrees.'));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (issuesWithPRs.size > 0) {
|
|
29
|
+
const skipped = issues.length - availableIssues.length;
|
|
30
|
+
console.log(chalk_1.default.dim(`(${skipped} issue${skipped > 1 ? 's' : ''} with open PRs hidden)\n`));
|
|
31
|
+
}
|
|
32
|
+
const choices = availableIssues.map((issue) => ({
|
|
21
33
|
name: `#${issue.number}\t${issue.title}`,
|
|
22
34
|
value: issue.number,
|
|
23
35
|
}));
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,7 @@ const pr_1 = require("./commands/pr");
|
|
|
14
14
|
const clean_1 = require("./commands/clean");
|
|
15
15
|
const select_1 = require("./commands/select");
|
|
16
16
|
const go_1 = require("./commands/go");
|
|
17
|
+
const new_1 = require("./commands/new");
|
|
17
18
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
18
19
|
const packageJson = require('../package.json');
|
|
19
20
|
const program = new commander_1.Command();
|
|
@@ -110,4 +111,13 @@ program
|
|
|
110
111
|
}
|
|
111
112
|
await (0, go_1.goCommand)(issueNumber);
|
|
112
113
|
});
|
|
114
|
+
// New command - create issue and solve it
|
|
115
|
+
program
|
|
116
|
+
.command('new <title>')
|
|
117
|
+
.description('Create a new issue and immediately start solving it')
|
|
118
|
+
.option('-b, --body <body>', 'Issue description')
|
|
119
|
+
.option('-l, --label <label...>', 'Add labels to the issue')
|
|
120
|
+
.action(async (title, options) => {
|
|
121
|
+
await (0, new_1.newCommand)(title, options);
|
|
122
|
+
});
|
|
113
123
|
program.parse();
|
package/dist/utils/github.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export interface IssueListItem {
|
|
|
8
8
|
number: number;
|
|
9
9
|
title: string;
|
|
10
10
|
}
|
|
11
|
+
export declare function createIssue(title: string, body?: string, labels?: string[]): number | null;
|
|
11
12
|
export declare function getIssue(issueNumber: number): Issue | null;
|
|
12
13
|
export declare function listIssues(limit?: number): IssueListItem[];
|
|
13
14
|
export declare function createPullRequest(title: string, body: string, branch: string, base?: string): string;
|
|
@@ -20,3 +21,8 @@ export interface PRStatus {
|
|
|
20
21
|
}
|
|
21
22
|
export declare function getIssueStatus(issueNumber: number): IssueStatus | null;
|
|
22
23
|
export declare function getPRForBranch(branch: string): PRStatus | null;
|
|
24
|
+
/**
|
|
25
|
+
* Get all open PRs with their head branch names (single API call)
|
|
26
|
+
* Returns a Set of issue numbers that have open PRs from issue-{number}-* branches
|
|
27
|
+
*/
|
|
28
|
+
export declare function getIssuesWithOpenPRs(): Set<number>;
|
package/dist/utils/github.js
CHANGED
|
@@ -1,11 +1,36 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createIssue = createIssue;
|
|
3
4
|
exports.getIssue = getIssue;
|
|
4
5
|
exports.listIssues = listIssues;
|
|
5
6
|
exports.createPullRequest = createPullRequest;
|
|
6
7
|
exports.getIssueStatus = getIssueStatus;
|
|
7
8
|
exports.getPRForBranch = getPRForBranch;
|
|
9
|
+
exports.getIssuesWithOpenPRs = getIssuesWithOpenPRs;
|
|
8
10
|
const child_process_1 = require("child_process");
|
|
11
|
+
function createIssue(title, body, labels) {
|
|
12
|
+
try {
|
|
13
|
+
let cmd = `gh issue create --title "${title.replace(/"/g, '\\"')}"`;
|
|
14
|
+
if (body) {
|
|
15
|
+
cmd += ` --body "${body.replace(/"/g, '\\"')}"`;
|
|
16
|
+
}
|
|
17
|
+
if (labels && labels.length > 0) {
|
|
18
|
+
for (const label of labels) {
|
|
19
|
+
cmd += ` --label "${label.replace(/"/g, '\\"')}"`;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const output = (0, child_process_1.execSync)(cmd, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
23
|
+
// Output is the issue URL, extract the number
|
|
24
|
+
const match = output.trim().match(/\/issues\/(\d+)$/);
|
|
25
|
+
if (match) {
|
|
26
|
+
return parseInt(match[1], 10);
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
9
34
|
function getIssue(issueNumber) {
|
|
10
35
|
try {
|
|
11
36
|
const output = (0, child_process_1.execSync)(`gh issue view ${issueNumber} --json title,body,url`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
@@ -61,3 +86,25 @@ function getPRForBranch(branch) {
|
|
|
61
86
|
return null;
|
|
62
87
|
}
|
|
63
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Get all open PRs with their head branch names (single API call)
|
|
91
|
+
* Returns a Set of issue numbers that have open PRs from issue-{number}-* branches
|
|
92
|
+
*/
|
|
93
|
+
function getIssuesWithOpenPRs() {
|
|
94
|
+
try {
|
|
95
|
+
const output = (0, child_process_1.execSync)(`gh pr list --state open --json headRefName --limit 100`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
96
|
+
const data = JSON.parse(output);
|
|
97
|
+
const issueNumbers = new Set();
|
|
98
|
+
for (const pr of data) {
|
|
99
|
+
// Match branches like "issue-42-fix-bug"
|
|
100
|
+
const match = pr.headRefName.match(/^issue-(\d+)-/);
|
|
101
|
+
if (match) {
|
|
102
|
+
issueNumbers.add(parseInt(match[1], 10));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return issueNumbers;
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return new Set();
|
|
109
|
+
}
|
|
110
|
+
}
|