claude-issue-solver 1.10.1 → 1.12.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 +16 -0
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +232 -0
- package/dist/commands/list.js +4 -1
- package/dist/index.js +16 -2
- package/dist/utils/github.d.ts +5 -0
- package/dist/utils/github.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
<img src="claude-issue-solver-logo.webp" alt="Claude Issue Solver Logo" width="200">
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
|
+
[](https://www.npmjs.com/package/claude-issue-solver)
|
|
8
|
+
[](https://www.npmjs.com/package/claude-issue-solver)
|
|
9
|
+
[](https://opensource.org/licenses/MIT)
|
|
10
|
+
|
|
7
11
|
Automatically solve GitHub issues using [Claude Code](https://claude.ai/code).
|
|
8
12
|
|
|
9
13
|
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.
|
|
@@ -67,6 +71,17 @@ Open issues for my-project:
|
|
|
67
71
|
npm install -g claude-issue-solver
|
|
68
72
|
```
|
|
69
73
|
|
|
74
|
+
Then run the setup wizard to check/install requirements:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
claude-issue init
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
This will:
|
|
81
|
+
- Check for Node.js, GitHub CLI, Claude Code, and Git
|
|
82
|
+
- Install missing tools (on macOS via Homebrew)
|
|
83
|
+
- Guide you through authentication for `gh` and `claude`
|
|
84
|
+
|
|
70
85
|
Or install from source:
|
|
71
86
|
|
|
72
87
|
```bash
|
|
@@ -125,6 +140,7 @@ claude-issue --help
|
|
|
125
140
|
| `claude-issue pr <number>` | - | Create PR for solved issue |
|
|
126
141
|
| `claude-issue clean [number]` | `rm` | Remove worktree and branch |
|
|
127
142
|
| `claude-issue go [number]` | - | Navigate to worktree |
|
|
143
|
+
| `claude-issue init` | - | Setup wizard for requirements |
|
|
128
144
|
|
|
129
145
|
### Command Options
|
|
130
146
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function initCommand(): Promise<void>;
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.initCommand = initCommand;
|
|
40
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
41
|
+
const ora_1 = __importDefault(require("ora"));
|
|
42
|
+
const child_process_1 = require("child_process");
|
|
43
|
+
const os = __importStar(require("os"));
|
|
44
|
+
function commandExists(cmd) {
|
|
45
|
+
try {
|
|
46
|
+
(0, child_process_1.execSync)(`which ${cmd}`, { stdio: 'pipe' });
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function isGhAuthenticated() {
|
|
54
|
+
try {
|
|
55
|
+
(0, child_process_1.execSync)('gh auth status', { stdio: 'pipe' });
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function isClaudeAuthenticated() {
|
|
63
|
+
try {
|
|
64
|
+
// Claude Code stores auth in ~/.claude or similar
|
|
65
|
+
// Just check if it runs without error
|
|
66
|
+
(0, child_process_1.execSync)('claude --version', { stdio: 'pipe' });
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function installWithBrew(pkg) {
|
|
74
|
+
if (!commandExists('brew')) {
|
|
75
|
+
console.log(chalk_1.default.yellow(`\n Homebrew not found. Please install ${pkg} manually.`));
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
console.log(chalk_1.default.dim(`\n Running: brew install ${pkg}`));
|
|
80
|
+
(0, child_process_1.spawnSync)('brew', ['install', pkg], { stdio: 'inherit' });
|
|
81
|
+
return commandExists(pkg === 'gh' ? 'gh' : pkg);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function installWithNpm(pkg) {
|
|
88
|
+
try {
|
|
89
|
+
console.log(chalk_1.default.dim(`\n Running: npm install -g ${pkg}`));
|
|
90
|
+
(0, child_process_1.spawnSync)('npm', ['install', '-g', pkg], { stdio: 'inherit' });
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function runGhAuth() {
|
|
98
|
+
try {
|
|
99
|
+
console.log(chalk_1.default.dim('\n Running: gh auth login'));
|
|
100
|
+
console.log(chalk_1.default.cyan(' Follow the prompts to authenticate with GitHub:\n'));
|
|
101
|
+
(0, child_process_1.spawnSync)('gh', ['auth', 'login'], { stdio: 'inherit' });
|
|
102
|
+
return isGhAuthenticated();
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function runClaudeAuth() {
|
|
109
|
+
try {
|
|
110
|
+
console.log(chalk_1.default.dim('\n Running: claude'));
|
|
111
|
+
console.log(chalk_1.default.cyan(' Follow the prompts to authenticate with Anthropic:\n'));
|
|
112
|
+
(0, child_process_1.spawnSync)('claude', ['--help'], { stdio: 'inherit' });
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
async function initCommand() {
|
|
120
|
+
console.log(chalk_1.default.bold('\n🔧 Claude Issue Solver - Setup\n'));
|
|
121
|
+
const platform = os.platform();
|
|
122
|
+
const isMac = platform === 'darwin';
|
|
123
|
+
const requirements = [
|
|
124
|
+
{
|
|
125
|
+
name: 'Node.js',
|
|
126
|
+
check: () => {
|
|
127
|
+
try {
|
|
128
|
+
const version = (0, child_process_1.execSync)('node --version', { encoding: 'utf-8' }).trim();
|
|
129
|
+
const major = parseInt(version.replace('v', '').split('.')[0], 10);
|
|
130
|
+
return major >= 18;
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
installCmd: 'https://nodejs.org/ or: brew install node',
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: 'GitHub CLI',
|
|
140
|
+
check: () => commandExists('gh'),
|
|
141
|
+
install: () => installWithBrew('gh'),
|
|
142
|
+
authCheck: isGhAuthenticated,
|
|
143
|
+
auth: runGhAuth,
|
|
144
|
+
installCmd: isMac ? 'brew install gh' : 'https://cli.github.com/',
|
|
145
|
+
authCmd: 'gh auth login',
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: 'Claude Code',
|
|
149
|
+
check: () => commandExists('claude'),
|
|
150
|
+
install: () => installWithNpm('@anthropic-ai/claude-code'),
|
|
151
|
+
authCheck: isClaudeAuthenticated,
|
|
152
|
+
auth: runClaudeAuth,
|
|
153
|
+
installCmd: 'npm install -g @anthropic-ai/claude-code',
|
|
154
|
+
authCmd: 'claude (follow prompts)',
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: 'Git',
|
|
158
|
+
check: () => commandExists('git'),
|
|
159
|
+
installCmd: isMac ? 'xcode-select --install' : 'apt install git',
|
|
160
|
+
},
|
|
161
|
+
];
|
|
162
|
+
let allPassed = true;
|
|
163
|
+
for (const req of requirements) {
|
|
164
|
+
const spinner = (0, ora_1.default)(`Checking ${req.name}...`).start();
|
|
165
|
+
// Check if installed
|
|
166
|
+
if (req.check()) {
|
|
167
|
+
// Check if authenticated (if applicable)
|
|
168
|
+
if (req.authCheck && !req.authCheck()) {
|
|
169
|
+
spinner.warn(chalk_1.default.yellow(`${req.name} - not authenticated`));
|
|
170
|
+
if (req.auth) {
|
|
171
|
+
const authSpinner = (0, ora_1.default)(`Authenticating ${req.name}...`).start();
|
|
172
|
+
authSpinner.stop();
|
|
173
|
+
if (req.auth()) {
|
|
174
|
+
console.log(chalk_1.default.green(` ✓ ${req.name} authenticated`));
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
console.log(chalk_1.default.red(` ✗ ${req.name} authentication failed`));
|
|
178
|
+
console.log(chalk_1.default.dim(` Run manually: ${req.authCmd}`));
|
|
179
|
+
allPassed = false;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
spinner.succeed(chalk_1.default.green(`${req.name}`));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
spinner.fail(chalk_1.default.red(`${req.name} - not found`));
|
|
189
|
+
// Try to install
|
|
190
|
+
if (req.install && isMac) {
|
|
191
|
+
const installSpinner = (0, ora_1.default)(`Installing ${req.name}...`).start();
|
|
192
|
+
installSpinner.stop();
|
|
193
|
+
if (req.install()) {
|
|
194
|
+
console.log(chalk_1.default.green(` ✓ ${req.name} installed`));
|
|
195
|
+
// Now check auth if needed
|
|
196
|
+
if (req.authCheck && !req.authCheck() && req.auth) {
|
|
197
|
+
console.log(chalk_1.default.yellow(` → ${req.name} needs authentication`));
|
|
198
|
+
if (req.auth()) {
|
|
199
|
+
console.log(chalk_1.default.green(` ✓ ${req.name} authenticated`));
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
console.log(chalk_1.default.red(` ✗ ${req.name} authentication failed`));
|
|
203
|
+
console.log(chalk_1.default.dim(` Run manually: ${req.authCmd}`));
|
|
204
|
+
allPassed = false;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
console.log(chalk_1.default.red(` ✗ Failed to install ${req.name}`));
|
|
210
|
+
console.log(chalk_1.default.dim(` Install manually: ${req.installCmd}`));
|
|
211
|
+
allPassed = false;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
console.log(chalk_1.default.dim(` Install: ${req.installCmd}`));
|
|
216
|
+
allPassed = false;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
console.log();
|
|
221
|
+
if (allPassed) {
|
|
222
|
+
console.log(chalk_1.default.green.bold('✅ All requirements met! You\'re ready to use claude-issue.\n'));
|
|
223
|
+
console.log(chalk_1.default.dim('Try running:'));
|
|
224
|
+
console.log(chalk_1.default.cyan(' claude-issue list # List open issues'));
|
|
225
|
+
console.log(chalk_1.default.cyan(' claude-issue # Interactive issue selection'));
|
|
226
|
+
console.log(chalk_1.default.cyan(' claude-issue new "Title" # Create and solve new issue\n'));
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
console.log(chalk_1.default.yellow.bold('⚠️ Some requirements are missing.\n'));
|
|
230
|
+
console.log(chalk_1.default.dim('Please install the missing requirements and run `claude-issue init` again.\n'));
|
|
231
|
+
}
|
|
232
|
+
}
|
package/dist/commands/list.js
CHANGED
|
@@ -16,7 +16,10 @@ async function listCommand() {
|
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
18
|
for (const issue of issues) {
|
|
19
|
-
|
|
19
|
+
const labels = issue.labels.length > 0
|
|
20
|
+
? ' ' + issue.labels.map(l => chalk_1.default.hex(`#${l.color}`).bold(`[${l.name}]`)).join(' ')
|
|
21
|
+
: '';
|
|
22
|
+
console.log(` ${chalk_1.default.cyan(`#${issue.number}`)}\t${issue.title}${labels}`);
|
|
20
23
|
}
|
|
21
24
|
console.log();
|
|
22
25
|
}
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ const clean_1 = require("./commands/clean");
|
|
|
15
15
|
const select_1 = require("./commands/select");
|
|
16
16
|
const go_1 = require("./commands/go");
|
|
17
17
|
const new_1 = require("./commands/new");
|
|
18
|
+
const init_1 = require("./commands/init");
|
|
18
19
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
19
20
|
const packageJson = require('../package.json');
|
|
20
21
|
const program = new commander_1.Command();
|
|
@@ -22,8 +23,14 @@ program
|
|
|
22
23
|
.name('claude-issue')
|
|
23
24
|
.description('Automatically solve GitHub issues using Claude Code')
|
|
24
25
|
.version(packageJson.version);
|
|
25
|
-
//
|
|
26
|
-
|
|
26
|
+
// Commands that skip requirements check
|
|
27
|
+
const skipRequirementsCommands = ['init'];
|
|
28
|
+
// Check requirements before any command (except init)
|
|
29
|
+
program.hook('preAction', (thisCommand) => {
|
|
30
|
+
const commandName = thisCommand.name();
|
|
31
|
+
if (skipRequirementsCommands.includes(commandName)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
27
34
|
if (!(0, git_1.isGitRepo)()) {
|
|
28
35
|
console.log(chalk_1.default.red('❌ Not in a git repository'));
|
|
29
36
|
process.exit(1);
|
|
@@ -120,4 +127,11 @@ program
|
|
|
120
127
|
.action(async (title, options) => {
|
|
121
128
|
await (0, new_1.newCommand)(title, options);
|
|
122
129
|
});
|
|
130
|
+
// Init command - guided setup
|
|
131
|
+
program
|
|
132
|
+
.command('init')
|
|
133
|
+
.description('Check and install requirements (gh, claude-code)')
|
|
134
|
+
.action(async () => {
|
|
135
|
+
await (0, init_1.initCommand)();
|
|
136
|
+
});
|
|
123
137
|
program.parse();
|
package/dist/utils/github.d.ts
CHANGED
|
@@ -4,9 +4,14 @@ export interface Issue {
|
|
|
4
4
|
body: string;
|
|
5
5
|
url: string;
|
|
6
6
|
}
|
|
7
|
+
export interface Label {
|
|
8
|
+
name: string;
|
|
9
|
+
color: string;
|
|
10
|
+
}
|
|
7
11
|
export interface IssueListItem {
|
|
8
12
|
number: number;
|
|
9
13
|
title: string;
|
|
14
|
+
labels: Label[];
|
|
10
15
|
}
|
|
11
16
|
export declare function createIssue(title: string, body?: string, labels?: string[]): number | null;
|
|
12
17
|
export declare function getIssue(issueNumber: number): Issue | null;
|
package/dist/utils/github.js
CHANGED
|
@@ -48,7 +48,7 @@ function getIssue(issueNumber) {
|
|
|
48
48
|
}
|
|
49
49
|
function listIssues(limit = 20) {
|
|
50
50
|
try {
|
|
51
|
-
const output = (0, child_process_1.execSync)(`gh issue list --state open --limit ${limit} --json number,title`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
51
|
+
const output = (0, child_process_1.execSync)(`gh issue list --state open --limit ${limit} --json number,title,labels`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
52
52
|
return JSON.parse(output);
|
|
53
53
|
}
|
|
54
54
|
catch {
|