@kernelius/forge-cli 0.1.1 → 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
@@ -2,6 +2,9 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { Command as Command5 } from "commander";
5
+ import { readFileSync } from "fs";
6
+ import { fileURLToPath } from "url";
7
+ import { dirname, join as join2 } from "path";
5
8
 
6
9
  // src/commands/auth.ts
7
10
  import { Command } from "commander";
@@ -223,7 +226,11 @@ function createReposCommand() {
223
226
  );
224
227
  repos.command("list").description("List accessible repositories").action(async () => {
225
228
  try {
226
- 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 || [];
227
234
  if (repositories.length === 0) {
228
235
  console.log(chalk2.yellow("No repositories found"));
229
236
  return;
@@ -231,7 +238,8 @@ function createReposCommand() {
231
238
  console.log(chalk2.bold(`Repositories (${repositories.length})`));
232
239
  console.log();
233
240
  for (const repo of repositories) {
234
- const identifier = `@${repo.ownerIdentifier}/${repo.name}`;
241
+ const ownerName = repo.owner?.identifier || repo.owner?.username || user.username;
242
+ const identifier = `@${ownerName}/${repo.name}`;
235
243
  const visibility = repo.visibility === "private" ? "\u{1F512}" : "\u{1F310}";
236
244
  console.log(`${visibility} ${chalk2.cyan(identifier)}`);
237
245
  if (repo.description) {
@@ -335,9 +343,10 @@ function createIssuesCommand() {
335
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) => {
336
344
  try {
337
345
  const [ownerIdentifier, name] = parseRepoArg2(options.repo);
338
- const issuesList = await apiGet(
346
+ const result = await apiGet(
339
347
  `/api/repositories/${ownerIdentifier}/${name}/issues?state=${options.state}`
340
348
  );
349
+ const issuesList = result.issues || [];
341
350
  if (issuesList.length === 0) {
342
351
  console.log(chalk3.yellow(`No ${options.state} issues found`));
343
352
  return;
@@ -352,7 +361,7 @@ function createIssuesCommand() {
352
361
  `${stateIcon} #${issue.number} ${chalk3.cyan(issue.title)}`
353
362
  );
354
363
  console.log(
355
- 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()}`)
356
365
  );
357
366
  }
358
367
  } catch (error) {
@@ -461,9 +470,10 @@ function createPrsCommand() {
461
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) => {
462
471
  try {
463
472
  const [ownerIdentifier, name] = parseRepoArg3(options.repo);
464
- const prsList = await apiGet(
465
- `/api/repositories/${ownerIdentifier}/${name}/pull-requests?state=${options.state}`
473
+ const result = await apiGet(
474
+ `/api/repositories/${ownerIdentifier}/${name}/pulls?state=${options.state}`
466
475
  );
476
+ const prsList = result.pullRequests || [];
467
477
  if (prsList.length === 0) {
468
478
  console.log(chalk4.yellow(`No ${options.state} pull requests found`));
469
479
  return;
@@ -475,11 +485,11 @@ function createPrsCommand() {
475
485
  );
476
486
  console.log();
477
487
  for (const pr of prsList) {
478
- 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";
479
489
  console.log(`${stateIcon} #${pr.number} ${chalk4.cyan(pr.title)}`);
480
490
  console.log(
481
491
  chalk4.dim(
482
- ` ${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()}`
483
493
  )
484
494
  );
485
495
  }
@@ -492,13 +502,13 @@ function createPrsCommand() {
492
502
  try {
493
503
  const [ownerIdentifier, name] = parseRepoArg3(options.repo);
494
504
  const pr = await apiGet(
495
- `/api/repositories/${ownerIdentifier}/${name}/pull-requests/${options.number}`
505
+ `/api/repositories/${ownerIdentifier}/${name}/pulls/${options.number}`
496
506
  );
497
- 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";
498
508
  console.log(`${stateIcon} ${chalk4.bold(`#${pr.number} ${pr.title}`)}`);
499
509
  console.log(
500
510
  chalk4.dim(
501
- `${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()}`
502
512
  )
503
513
  );
504
514
  console.log();
@@ -506,13 +516,13 @@ function createPrsCommand() {
506
516
  console.log(pr.body);
507
517
  console.log();
508
518
  }
509
- console.log(chalk4.dim(`State: ${pr.state}`));
519
+ console.log(chalk4.dim(`State: ${pr.merged ? "merged" : pr.state}`));
510
520
  if (pr.mergedAt) {
511
521
  console.log(
512
522
  chalk4.dim(`Merged: ${new Date(pr.mergedAt).toLocaleDateString()}`)
513
523
  );
514
524
  }
515
- if (pr.closedAt) {
525
+ if (pr.closedAt && !pr.merged) {
516
526
  console.log(
517
527
  chalk4.dim(`Closed: ${new Date(pr.closedAt).toLocaleDateString()}`)
518
528
  );
@@ -526,7 +536,7 @@ function createPrsCommand() {
526
536
  try {
527
537
  const [ownerIdentifier, name] = parseRepoArg3(options.repo);
528
538
  const pr = await apiPost(
529
- `/api/repositories/${ownerIdentifier}/${name}/pull-requests`,
539
+ `/api/repositories/${ownerIdentifier}/${name}/pulls`,
530
540
  {
531
541
  headBranch: options.head,
532
542
  baseBranch: options.base,
@@ -544,15 +554,15 @@ function createPrsCommand() {
544
554
  process.exit(1);
545
555
  }
546
556
  });
547
- 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) => {
548
558
  try {
549
559
  const [ownerIdentifier, name] = parseRepoArg3(options.repo);
550
- await apiPost(
551
- `/api/repositories/${ownerIdentifier}/${name}/pull-requests/${options.number}/merge`,
552
- {
553
- mergeMethod: options.method
554
- }
560
+ const pr = await apiGet(
561
+ `/api/repositories/${ownerIdentifier}/${name}/pulls/${options.number}`
555
562
  );
563
+ await apiPost(`/api/pulls/${pr.id}/merge`, {
564
+ commitMessage: options.message
565
+ });
556
566
  console.log(chalk4.green("\u2713 Pull request merged successfully"));
557
567
  } catch (error) {
558
568
  console.error(chalk4.red(`Error: ${error.message}`));
@@ -562,12 +572,12 @@ function createPrsCommand() {
562
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) => {
563
573
  try {
564
574
  const [ownerIdentifier, name] = parseRepoArg3(options.repo);
565
- await apiPatch(
566
- `/api/repositories/${ownerIdentifier}/${name}/pull-requests/${options.number}`,
567
- {
568
- state: "closed"
569
- }
575
+ const pr = await apiGet(
576
+ `/api/repositories/${ownerIdentifier}/${name}/pulls/${options.number}`
570
577
  );
578
+ await apiPatch(`/api/pulls/${pr.id}`, {
579
+ state: "closed"
580
+ });
571
581
  console.log(chalk4.green("\u2713 Pull request closed successfully"));
572
582
  } catch (error) {
573
583
  console.error(chalk4.red(`Error: ${error.message}`));
@@ -577,12 +587,12 @@ function createPrsCommand() {
577
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) => {
578
588
  try {
579
589
  const [ownerIdentifier, name] = parseRepoArg3(options.repo);
580
- await apiPost(
581
- `/api/repositories/${ownerIdentifier}/${name}/pull-requests/${options.number}/comments`,
582
- {
583
- body: options.body
584
- }
590
+ const pr = await apiGet(
591
+ `/api/repositories/${ownerIdentifier}/${name}/pulls/${options.number}`
585
592
  );
593
+ await apiPost(`/api/pulls/${pr.id}/comments`, {
594
+ body: options.body
595
+ });
586
596
  console.log(chalk4.green("\u2713 Comment added successfully"));
587
597
  } catch (error) {
588
598
  console.error(chalk4.red(`Error: ${error.message}`));
@@ -602,8 +612,13 @@ function parseRepoArg3(arg) {
602
612
  }
603
613
 
604
614
  // src/index.ts
615
+ var __filename2 = fileURLToPath(import.meta.url);
616
+ var __dirname2 = dirname(__filename2);
617
+ var packageJson = JSON.parse(
618
+ readFileSync(join2(__dirname2, "../package.json"), "utf-8")
619
+ );
605
620
  var program = new Command5();
606
- program.name("forge").description("CLI tool for Kernelius Forge - the agent-native Git platform").version("0.1.0");
621
+ program.name("forge").description("CLI tool for Kernelius Forge - the agent-native Git platform").version(packageJson.version);
607
622
  program.addCommand(createAuthCommand());
608
623
  program.addCommand(createReposCommand());
609
624
  program.addCommand(createIssuesCommand());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kernelius/forge-cli",
3
- "version": "0.1.1",
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",