claude-issue-solver 1.16.0 โ†’ 1.18.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.
@@ -236,13 +236,13 @@ async function cleanAllCommand() {
236
236
  console.log(chalk_1.default.yellow(` Run this command from the main project directory for best results.`));
237
237
  console.log(chalk_1.default.dim(` cd ${projectRoot}\n`));
238
238
  }
239
- // Fetch status for all worktrees
239
+ // Fetch status for all worktrees in parallel
240
240
  const statusSpinner = (0, ora_1.default)('Fetching issue and PR status...').start();
241
- const worktreesWithStatus = worktrees.map((wt) => ({
241
+ const worktreesWithStatus = await Promise.all(worktrees.map(async (wt) => ({
242
242
  ...wt,
243
- issueStatus: (0, github_1.getIssueStatus)(parseInt(wt.issueNumber, 10)),
244
- prStatus: wt.branch ? (0, github_1.getPRForBranch)(wt.branch) : null,
245
- }));
243
+ issueStatus: await (0, github_1.getIssueStatusAsync)(parseInt(wt.issueNumber, 10)),
244
+ prStatus: wt.branch ? await (0, github_1.getPRForBranchAsync)(wt.branch) : null,
245
+ })));
246
246
  statusSpinner.stop();
247
247
  console.log(chalk_1.default.bold('\n๐Ÿงน Found issue worktrees:\n'));
248
248
  for (const wt of worktreesWithStatus) {
@@ -516,13 +516,13 @@ async function cleanMergedCommand() {
516
516
  console.log(chalk_1.default.yellow(` Run this command from the main project directory for best results.`));
517
517
  console.log(chalk_1.default.dim(` cd ${projectRoot}\n`));
518
518
  }
519
- // Fetch status for all worktrees
519
+ // Fetch status for all worktrees in parallel
520
520
  const statusSpinner = (0, ora_1.default)('Fetching PR status...').start();
521
- const worktreesWithStatus = worktrees.map((wt) => ({
521
+ const worktreesWithStatus = await Promise.all(worktrees.map(async (wt) => ({
522
522
  ...wt,
523
- issueStatus: (0, github_1.getIssueStatus)(parseInt(wt.issueNumber, 10)),
524
- prStatus: wt.branch ? (0, github_1.getPRForBranch)(wt.branch) : null,
525
- }));
523
+ issueStatus: await (0, github_1.getIssueStatusAsync)(parseInt(wt.issueNumber, 10)),
524
+ prStatus: wt.branch ? await (0, github_1.getPRForBranchAsync)(wt.branch) : null,
525
+ })));
526
526
  statusSpinner.stop();
527
527
  // Filter to only merged PRs
528
528
  const mergedWorktrees = worktreesWithStatus.filter((wt) => wt.prStatus?.state === 'merged');
@@ -105,7 +105,8 @@ ${commitList}
105
105
  ---
106
106
 
107
107
  ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code)`;
108
- const prUrl = (0, child_process_1.execSync)(`gh pr create --title "Fix #${issueNumber}: ${issue.title.replace(/"/g, '\\"')}" --body "${prBody.replace(/"/g, '\\"')}" --head "${branchName}" --base main`, { cwd: worktreePath, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
108
+ const baseBranch = (0, git_1.getDefaultBranch)();
109
+ const prUrl = (0, child_process_1.execSync)(`gh pr create --title "Fix #${issueNumber}: ${issue.title.replace(/"/g, '\\"')}" --body "${prBody.replace(/"/g, '\\"')}" --head "${branchName}" --base ${baseBranch}`, { cwd: worktreePath, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
109
110
  pushSpinner.succeed('PR created!');
110
111
  console.log();
111
112
  console.log(chalk_1.default.green(`โœ… PR created: ${prUrl}`));
@@ -59,17 +59,18 @@ async function solveCommand(issueNumber) {
59
59
  console.log();
60
60
  const projectRoot = (0, git_1.getProjectRoot)();
61
61
  const projectName = (0, git_1.getProjectName)();
62
+ const baseBranch = (0, git_1.getDefaultBranch)();
62
63
  const branchSlug = (0, helpers_1.slugify)(issue.title);
63
64
  const branchName = `issue-${issueNumber}-${branchSlug}`;
64
65
  const worktreePath = path.join(path.dirname(projectRoot), `${projectName}-${branchName}`);
65
- // Fetch latest main
66
- const fetchSpinner = (0, ora_1.default)('Fetching latest main...').start();
66
+ // Fetch latest base branch
67
+ const fetchSpinner = (0, ora_1.default)(`Fetching latest ${baseBranch}...`).start();
67
68
  try {
68
- (0, child_process_1.execSync)('git fetch origin main --quiet', { cwd: projectRoot, stdio: 'pipe' });
69
- fetchSpinner.succeed('Fetched latest main');
69
+ (0, child_process_1.execSync)(`git fetch origin ${baseBranch} --quiet`, { cwd: projectRoot, stdio: 'pipe' });
70
+ fetchSpinner.succeed(`Fetched latest ${baseBranch}`);
70
71
  }
71
72
  catch {
72
- fetchSpinner.warn('Could not fetch origin/main');
73
+ fetchSpinner.warn(`Could not fetch origin/${baseBranch}`);
73
74
  }
74
75
  // Check if worktree already exists
75
76
  if (fs.existsSync(worktreePath)) {
@@ -86,7 +87,7 @@ async function solveCommand(issueNumber) {
86
87
  });
87
88
  }
88
89
  else {
89
- (0, child_process_1.execSync)(`git worktree add "${worktreePath}" -b "${branchName}" origin/main`, {
90
+ (0, child_process_1.execSync)(`git worktree add "${worktreePath}" -b "${branchName}" origin/${baseBranch}`, {
90
91
  cwd: projectRoot,
91
92
  stdio: 'pipe',
92
93
  });
@@ -139,7 +140,7 @@ echo ""
139
140
 
140
141
  # Function to create PR
141
142
  create_pr() {
142
- COMMITS=$(git log origin/main..HEAD --oneline 2>/dev/null | wc -l | tr -d ' ')
143
+ COMMITS=$(git log origin/${baseBranch}..HEAD --oneline 2>/dev/null | wc -l | tr -d ' ')
143
144
 
144
145
  if [ "$COMMITS" -gt 0 ]; then
145
146
  # Check if PR already exists
@@ -151,7 +152,7 @@ create_pr() {
151
152
 
152
153
  git push -u origin "${branchName}" 2>/dev/null
153
154
 
154
- COMMIT_LIST=$(git log origin/main..HEAD --pretty=format:'- %s' | head -10)
155
+ COMMIT_LIST=$(git log origin/${baseBranch}..HEAD --pretty=format:'- %s' | head -10)
155
156
 
156
157
  PR_URL=$(gh pr create \\
157
158
  --title "Fix #${issueNumber}: ${issue.title.replace(/"/g, '\\"')}" \\
@@ -167,7 +168,7 @@ $COMMIT_LIST
167
168
 
168
169
  ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code)" \\
169
170
  --head "${branchName}" \\
170
- --base main 2>/dev/null)
171
+ --base ${baseBranch} 2>/dev/null)
171
172
 
172
173
  if [ -n "$PR_URL" ]; then
173
174
  echo ""
@@ -4,5 +4,6 @@ export declare function getProjectRoot(): string;
4
4
  export declare function getProjectName(): string;
5
5
  export declare function isGitRepo(): boolean;
6
6
  export declare function branchExists(branchName: string): boolean;
7
+ export declare function getDefaultBranch(): string;
7
8
  export declare function getCommitCount(worktreePath: string): number;
8
9
  export declare function getCommitList(worktreePath: string, limit?: number): string;
package/dist/utils/git.js CHANGED
@@ -6,6 +6,7 @@ exports.getProjectRoot = getProjectRoot;
6
6
  exports.getProjectName = getProjectName;
7
7
  exports.isGitRepo = isGitRepo;
8
8
  exports.branchExists = branchExists;
9
+ exports.getDefaultBranch = getDefaultBranch;
9
10
  exports.getCommitCount = getCommitCount;
10
11
  exports.getCommitList = getCommitList;
11
12
  const child_process_1 = require("child_process");
@@ -69,9 +70,31 @@ function branchExists(branchName) {
69
70
  return false;
70
71
  }
71
72
  }
73
+ function getDefaultBranch() {
74
+ // Try to get from remote HEAD
75
+ try {
76
+ const output = exec('git symbolic-ref refs/remotes/origin/HEAD');
77
+ if (output) {
78
+ // Output is like "refs/remotes/origin/main" or "refs/remotes/origin/develop"
79
+ const match = output.match(/refs\/remotes\/origin\/(.+)/);
80
+ if (match) {
81
+ return match[1];
82
+ }
83
+ }
84
+ }
85
+ catch {
86
+ // Ignore
87
+ }
88
+ // Fallback: check if develop exists, otherwise main
89
+ if (branchExists('develop') || exec('git ls-remote --heads origin develop')) {
90
+ return 'develop';
91
+ }
92
+ return 'main';
93
+ }
72
94
  function getCommitCount(worktreePath) {
73
95
  try {
74
- const output = exec('git log origin/main..HEAD --oneline', worktreePath);
96
+ const baseBranch = getDefaultBranch();
97
+ const output = exec(`git log origin/${baseBranch}..HEAD --oneline`, worktreePath);
75
98
  if (!output)
76
99
  return 0;
77
100
  return output.split('\n').filter(Boolean).length;
@@ -81,5 +104,6 @@ function getCommitCount(worktreePath) {
81
104
  }
82
105
  }
83
106
  function getCommitList(worktreePath, limit = 10) {
84
- return exec(`git log origin/main..HEAD --pretty=format:'- %s' | head -${limit}`, worktreePath);
107
+ const baseBranch = getDefaultBranch();
108
+ return exec(`git log origin/${baseBranch}..HEAD --pretty=format:'- %s' | head -${limit}`, worktreePath);
85
109
  }
@@ -25,7 +25,9 @@ export interface PRStatus {
25
25
  url: string;
26
26
  }
27
27
  export declare function getIssueStatus(issueNumber: number): IssueStatus | null;
28
+ export declare function getIssueStatusAsync(issueNumber: number): Promise<IssueStatus | null>;
28
29
  export declare function getPRForBranch(branch: string): PRStatus | null;
30
+ export declare function getPRForBranchAsync(branch: string): Promise<PRStatus | null>;
29
31
  /**
30
32
  * Get all open PRs with their head branch names (single API call)
31
33
  * Returns a Set of issue numbers that have open PRs from issue-{number}-* branches
@@ -5,9 +5,13 @@ exports.getIssue = getIssue;
5
5
  exports.listIssues = listIssues;
6
6
  exports.createPullRequest = createPullRequest;
7
7
  exports.getIssueStatus = getIssueStatus;
8
+ exports.getIssueStatusAsync = getIssueStatusAsync;
8
9
  exports.getPRForBranch = getPRForBranch;
10
+ exports.getPRForBranchAsync = getPRForBranchAsync;
9
11
  exports.getIssuesWithOpenPRs = getIssuesWithOpenPRs;
10
12
  const child_process_1 = require("child_process");
13
+ const util_1 = require("util");
14
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
11
15
  function createIssue(title, body, labels) {
12
16
  try {
13
17
  let cmd = `gh issue create --title "${title.replace(/"/g, '\\"')}"`;
@@ -71,6 +75,18 @@ function getIssueStatus(issueNumber) {
71
75
  return null;
72
76
  }
73
77
  }
78
+ async function getIssueStatusAsync(issueNumber) {
79
+ try {
80
+ const { stdout } = await execAsync(`gh issue view ${issueNumber} --json state`);
81
+ const data = JSON.parse(stdout);
82
+ return {
83
+ state: data.state.toLowerCase(),
84
+ };
85
+ }
86
+ catch {
87
+ return null;
88
+ }
89
+ }
74
90
  function getPRForBranch(branch) {
75
91
  try {
76
92
  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'] });
@@ -86,6 +102,21 @@ function getPRForBranch(branch) {
86
102
  return null;
87
103
  }
88
104
  }
105
+ async function getPRForBranchAsync(branch) {
106
+ try {
107
+ const { stdout } = await execAsync(`gh pr list --head "${branch}" --state all --json state,url --limit 1`);
108
+ const data = JSON.parse(stdout);
109
+ if (data.length === 0)
110
+ return null;
111
+ return {
112
+ state: data[0].state.toLowerCase(),
113
+ url: data[0].url,
114
+ };
115
+ }
116
+ catch {
117
+ return null;
118
+ }
119
+ }
89
120
  /**
90
121
  * Get all open PRs with their head branch names (single API call)
91
122
  * Returns a Set of issue numbers that have open PRs from issue-{number}-* branches
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-issue-solver",
3
- "version": "1.16.0",
3
+ "version": "1.18.0",
4
4
  "description": "Automatically solve GitHub issues using Claude Code",
5
5
  "main": "dist/index.js",
6
6
  "bin": {