@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 +46 -0
- package/dist/index.js +46 -31
- package/package.json +3 -2
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
465
|
-
`/api/repositories/${ownerIdentifier}/${name}/
|
|
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.
|
|
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
|
|
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}/
|
|
505
|
+
`/api/repositories/${ownerIdentifier}/${name}/pulls/${options.number}`
|
|
496
506
|
);
|
|
497
|
-
const stateIcon = pr.
|
|
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
|
|
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}/
|
|
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("--
|
|
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
|
|
551
|
-
`/api/repositories/${ownerIdentifier}/${name}/
|
|
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
|
|
566
|
-
`/api/repositories/${ownerIdentifier}/${name}/
|
|
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
|
|
581
|
-
`/api/repositories/${ownerIdentifier}/${name}/
|
|
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(
|
|
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.
|
|
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",
|