@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 +46 -0
- package/dist/index.js +37 -30
- 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
|
@@ -226,7 +226,11 @@ function createReposCommand() {
|
|
|
226
226
|
);
|
|
227
227
|
repos.command("list").description("List accessible repositories").action(async () => {
|
|
228
228
|
try {
|
|
229
|
-
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 || [];
|
|
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
|
|
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
|
|
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
|
|
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
|
|
468
|
-
`/api/repositories/${ownerIdentifier}/${name}/
|
|
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.
|
|
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
|
|
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}/
|
|
505
|
+
`/api/repositories/${ownerIdentifier}/${name}/pulls/${options.number}`
|
|
499
506
|
);
|
|
500
|
-
const stateIcon = pr.
|
|
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
|
|
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}/
|
|
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("--
|
|
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
|
|
554
|
-
`/api/repositories/${ownerIdentifier}/${name}/
|
|
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
|
|
569
|
-
`/api/repositories/${ownerIdentifier}/${name}/
|
|
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
|
|
584
|
-
`/api/repositories/${ownerIdentifier}/${name}/
|
|
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.
|
|
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",
|