@kernelius/forge-cli 0.1.2 → 0.1.3

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/CHANGELOG.md ADDED
@@ -0,0 +1,46 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.3] - 2026-02-01
9
+
10
+ ### Fixed
11
+ - **repos list**: Now correctly uses `/api/repositories/user/:username` endpoint instead of non-existent `/api/repositories`
12
+ - **issues list**: Properly handles API response format `{ issues: [...] }` instead of expecting array directly
13
+ - **prs list**: Uses correct `/pulls` endpoint instead of `/pull-requests`
14
+ - **prs view**: Uses correct `/pulls` endpoint instead of `/pull-requests`
15
+ - **prs create**: Uses correct `/pulls` endpoint instead of `/pull-requests`
16
+ - **prs merge**: Fetches PR by number first to obtain ID before calling merge endpoint
17
+ - **prs close**: Fetches PR by number first to obtain ID before calling patch endpoint
18
+ - **prs comment**: Fetches PR by number first to obtain ID before calling comments endpoint
19
+ - Improved error handling with proper author username fallbacks
20
+
21
+ ### Changed
22
+ - All PR commands now properly handle merged state (shows 🟣 icon)
23
+ - PR state display now shows "merged" for merged PRs instead of just closed
24
+
25
+ ## [0.1.2] - 2026-01-31
26
+
27
+ ### Added
28
+ - Dynamic version reading from package.json
29
+
30
+ ### Changed
31
+ - Default API URL changed to production: `https://forge-api.kernelius.com`
32
+
33
+ ## [0.1.1] - 2026-01-31
34
+
35
+ ### Added
36
+ - Initial release with basic commands
37
+ - Auth commands: `login`, `logout`, `whoami`, `config`
38
+ - Repository commands: `list`, `view`, `clone`, `create`
39
+ - Issue commands: `list`, `view`, `create`, `close`, `comment`
40
+ - Pull request commands: `list`, `view`, `create`, `merge`, `close`, `comment`
41
+ - OpenClaw SKILL.md for agent integration
42
+ - Support for agent API keys (`forge_agent_` prefix)
43
+
44
+ [0.1.3]: https://github.com/kernelius-hq/forge-cli/compare/v0.1.2...v0.1.3
45
+ [0.1.2]: https://github.com/kernelius-hq/forge-cli/compare/v0.1.1...v0.1.2
46
+ [0.1.1]: https://github.com/kernelius-hq/forge-cli/releases/tag/v0.1.1
package/dist/index.js CHANGED
@@ -226,7 +226,11 @@ function createReposCommand() {
226
226
  );
227
227
  repos.command("list").description("List accessible repositories").action(async () => {
228
228
  try {
229
- const repositories = await apiGet("/api/repositories");
229
+ const user = await apiGet("/api/users/me");
230
+ const result = await apiGet(
231
+ `/api/repositories/user/${user.username}`
232
+ );
233
+ const repositories = result.repos || [];
230
234
  if (repositories.length === 0) {
231
235
  console.log(chalk2.yellow("No repositories found"));
232
236
  return;
@@ -234,7 +238,8 @@ function createReposCommand() {
234
238
  console.log(chalk2.bold(`Repositories (${repositories.length})`));
235
239
  console.log();
236
240
  for (const repo of repositories) {
237
- const identifier = `@${repo.ownerIdentifier}/${repo.name}`;
241
+ const ownerName = repo.owner?.identifier || repo.owner?.username || user.username;
242
+ const identifier = `@${ownerName}/${repo.name}`;
238
243
  const visibility = repo.visibility === "private" ? "\u{1F512}" : "\u{1F310}";
239
244
  console.log(`${visibility} ${chalk2.cyan(identifier)}`);
240
245
  if (repo.description) {
@@ -338,9 +343,10 @@ function createIssuesCommand() {
338
343
  issues.command("list").description("List issues in a repository").requiredOption("--repo <repo>", "Repository (@owner/name)").option("--state <state>", "Filter by state (open/closed)", "open").action(async (options) => {
339
344
  try {
340
345
  const [ownerIdentifier, name] = parseRepoArg2(options.repo);
341
- const issuesList = await apiGet(
346
+ const result = await apiGet(
342
347
  `/api/repositories/${ownerIdentifier}/${name}/issues?state=${options.state}`
343
348
  );
349
+ const issuesList = result.issues || [];
344
350
  if (issuesList.length === 0) {
345
351
  console.log(chalk3.yellow(`No ${options.state} issues found`));
346
352
  return;
@@ -355,7 +361,7 @@ function createIssuesCommand() {
355
361
  `${stateIcon} #${issue.number} ${chalk3.cyan(issue.title)}`
356
362
  );
357
363
  console.log(
358
- chalk3.dim(` by @${issue.author.username} \xB7 ${new Date(issue.createdAt).toLocaleDateString()}`)
364
+ chalk3.dim(` by @${issue.author?.username || "unknown"} \xB7 ${new Date(issue.createdAt).toLocaleDateString()}`)
359
365
  );
360
366
  }
361
367
  } catch (error) {
@@ -464,9 +470,10 @@ function createPrsCommand() {
464
470
  prs.command("list").description("List pull requests in a repository").requiredOption("--repo <repo>", "Repository (@owner/name)").option("--state <state>", "Filter by state (open/closed/merged)", "open").action(async (options) => {
465
471
  try {
466
472
  const [ownerIdentifier, name] = parseRepoArg3(options.repo);
467
- const prsList = await apiGet(
468
- `/api/repositories/${ownerIdentifier}/${name}/pull-requests?state=${options.state}`
473
+ const result = await apiGet(
474
+ `/api/repositories/${ownerIdentifier}/${name}/pulls?state=${options.state}`
469
475
  );
476
+ const prsList = result.pullRequests || [];
470
477
  if (prsList.length === 0) {
471
478
  console.log(chalk4.yellow(`No ${options.state} pull requests found`));
472
479
  return;
@@ -478,11 +485,11 @@ function createPrsCommand() {
478
485
  );
479
486
  console.log();
480
487
  for (const pr of prsList) {
481
- const stateIcon = pr.state === "open" ? "\u{1F7E2}" : pr.state === "merged" ? "\u{1F7E3}" : "\u26AA";
488
+ const stateIcon = pr.merged ? "\u{1F7E3}" : pr.state === "open" ? "\u{1F7E2}" : "\u26AA";
482
489
  console.log(`${stateIcon} #${pr.number} ${chalk4.cyan(pr.title)}`);
483
490
  console.log(
484
491
  chalk4.dim(
485
- ` ${pr.headBranch} \u2192 ${pr.baseBranch} by @${pr.author.username} \xB7 ${new Date(pr.createdAt).toLocaleDateString()}`
492
+ ` ${pr.headBranch} \u2192 ${pr.baseBranch} by @${pr.author?.username || "unknown"} \xB7 ${new Date(pr.createdAt).toLocaleDateString()}`
486
493
  )
487
494
  );
488
495
  }
@@ -495,13 +502,13 @@ function createPrsCommand() {
495
502
  try {
496
503
  const [ownerIdentifier, name] = parseRepoArg3(options.repo);
497
504
  const pr = await apiGet(
498
- `/api/repositories/${ownerIdentifier}/${name}/pull-requests/${options.number}`
505
+ `/api/repositories/${ownerIdentifier}/${name}/pulls/${options.number}`
499
506
  );
500
- const stateIcon = pr.state === "open" ? "\u{1F7E2}" : pr.state === "merged" ? "\u{1F7E3}" : "\u26AA";
507
+ const stateIcon = pr.merged ? "\u{1F7E3}" : pr.state === "open" ? "\u{1F7E2}" : "\u26AA";
501
508
  console.log(`${stateIcon} ${chalk4.bold(`#${pr.number} ${pr.title}`)}`);
502
509
  console.log(
503
510
  chalk4.dim(
504
- `${pr.headBranch} \u2192 ${pr.baseBranch} by @${pr.author.username} \xB7 ${new Date(pr.createdAt).toLocaleDateString()}`
511
+ `${pr.headBranch} \u2192 ${pr.baseBranch} by @${pr.author?.username || "unknown"} \xB7 ${new Date(pr.createdAt).toLocaleDateString()}`
505
512
  )
506
513
  );
507
514
  console.log();
@@ -509,13 +516,13 @@ function createPrsCommand() {
509
516
  console.log(pr.body);
510
517
  console.log();
511
518
  }
512
- console.log(chalk4.dim(`State: ${pr.state}`));
519
+ console.log(chalk4.dim(`State: ${pr.merged ? "merged" : pr.state}`));
513
520
  if (pr.mergedAt) {
514
521
  console.log(
515
522
  chalk4.dim(`Merged: ${new Date(pr.mergedAt).toLocaleDateString()}`)
516
523
  );
517
524
  }
518
- if (pr.closedAt) {
525
+ if (pr.closedAt && !pr.merged) {
519
526
  console.log(
520
527
  chalk4.dim(`Closed: ${new Date(pr.closedAt).toLocaleDateString()}`)
521
528
  );
@@ -529,7 +536,7 @@ function createPrsCommand() {
529
536
  try {
530
537
  const [ownerIdentifier, name] = parseRepoArg3(options.repo);
531
538
  const pr = await apiPost(
532
- `/api/repositories/${ownerIdentifier}/${name}/pull-requests`,
539
+ `/api/repositories/${ownerIdentifier}/${name}/pulls`,
533
540
  {
534
541
  headBranch: options.head,
535
542
  baseBranch: options.base,
@@ -547,15 +554,15 @@ function createPrsCommand() {
547
554
  process.exit(1);
548
555
  }
549
556
  });
550
- prs.command("merge").description("Merge a pull request").requiredOption("--repo <repo>", "Repository (@owner/name)").requiredOption("--number <number>", "PR number").option("--method <method>", "Merge method (merge/squash/rebase)", "merge").action(async (options) => {
557
+ prs.command("merge").description("Merge a pull request").requiredOption("--repo <repo>", "Repository (@owner/name)").requiredOption("--number <number>", "PR number").option("--message <message>", "Custom merge commit message").action(async (options) => {
551
558
  try {
552
559
  const [ownerIdentifier, name] = parseRepoArg3(options.repo);
553
- await apiPost(
554
- `/api/repositories/${ownerIdentifier}/${name}/pull-requests/${options.number}/merge`,
555
- {
556
- mergeMethod: options.method
557
- }
560
+ const pr = await apiGet(
561
+ `/api/repositories/${ownerIdentifier}/${name}/pulls/${options.number}`
558
562
  );
563
+ await apiPost(`/api/pulls/${pr.id}/merge`, {
564
+ commitMessage: options.message
565
+ });
559
566
  console.log(chalk4.green("\u2713 Pull request merged successfully"));
560
567
  } catch (error) {
561
568
  console.error(chalk4.red(`Error: ${error.message}`));
@@ -565,12 +572,12 @@ function createPrsCommand() {
565
572
  prs.command("close").description("Close a pull request without merging").requiredOption("--repo <repo>", "Repository (@owner/name)").requiredOption("--number <number>", "PR number").action(async (options) => {
566
573
  try {
567
574
  const [ownerIdentifier, name] = parseRepoArg3(options.repo);
568
- await apiPatch(
569
- `/api/repositories/${ownerIdentifier}/${name}/pull-requests/${options.number}`,
570
- {
571
- state: "closed"
572
- }
575
+ const pr = await apiGet(
576
+ `/api/repositories/${ownerIdentifier}/${name}/pulls/${options.number}`
573
577
  );
578
+ await apiPatch(`/api/pulls/${pr.id}`, {
579
+ state: "closed"
580
+ });
574
581
  console.log(chalk4.green("\u2713 Pull request closed successfully"));
575
582
  } catch (error) {
576
583
  console.error(chalk4.red(`Error: ${error.message}`));
@@ -580,12 +587,12 @@ function createPrsCommand() {
580
587
  prs.command("comment").description("Add a comment to a pull request").requiredOption("--repo <repo>", "Repository (@owner/name)").requiredOption("--number <number>", "PR number").requiredOption("--body <body>", "Comment text").action(async (options) => {
581
588
  try {
582
589
  const [ownerIdentifier, name] = parseRepoArg3(options.repo);
583
- await apiPost(
584
- `/api/repositories/${ownerIdentifier}/${name}/pull-requests/${options.number}/comments`,
585
- {
586
- body: options.body
587
- }
590
+ const pr = await apiGet(
591
+ `/api/repositories/${ownerIdentifier}/${name}/pulls/${options.number}`
588
592
  );
593
+ await apiPost(`/api/pulls/${pr.id}/comments`, {
594
+ body: options.body
595
+ });
589
596
  console.log(chalk4.green("\u2713 Comment added successfully"));
590
597
  } catch (error) {
591
598
  console.error(chalk4.red(`Error: ${error.message}`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kernelius/forge-cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Command-line tool for Kernelius Forge - the agent-native Git platform",
5
5
  "type": "module",
6
6
  "bin": {
@@ -9,7 +9,8 @@
9
9
  "files": [
10
10
  "dist",
11
11
  "README.md",
12
- "SKILL.md"
12
+ "SKILL.md",
13
+ "CHANGELOG.md"
13
14
  ],
14
15
  "scripts": {
15
16
  "build": "tsup",