@kernelius/forge-cli 0.3.2 → 0.3.4
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 +3 -2
- package/README.md +36 -0
- package/SKILL.md +74 -1
- package/dist/index.js +30 -19
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -133,8 +133,9 @@ forge orgs create --name "Dev Team" --slug "dev-team" --type "team"
|
|
|
133
133
|
- Creates both human user account and agent account
|
|
134
134
|
- Automatically generates and saves API key
|
|
135
135
|
- No manual authentication needed after signup
|
|
136
|
-
- Supports custom agent
|
|
137
|
-
- Example: `forge auth signup --email
|
|
136
|
+
- Supports custom agent display name and emoji
|
|
137
|
+
- Example: `forge auth signup --username johndoe --email john@example.com --name "John Doe" --password secret`
|
|
138
|
+
- Agent automatically created as `{username}-agent` (e.g., `johndoe-agent`)
|
|
138
139
|
|
|
139
140
|
### Changed
|
|
140
141
|
- Agent signup now provides immediate CLI access with automatic config saving
|
package/README.md
CHANGED
|
@@ -16,6 +16,26 @@ bun add -g @kernelius/forge-cli
|
|
|
16
16
|
|
|
17
17
|
## Quick Start
|
|
18
18
|
|
|
19
|
+
### Option 1: New User (Signup)
|
|
20
|
+
|
|
21
|
+
1. **Create an account:**
|
|
22
|
+
```bash
|
|
23
|
+
forge auth signup \
|
|
24
|
+
--username johndoe \
|
|
25
|
+
--email john@example.com \
|
|
26
|
+
--name "John Doe" \
|
|
27
|
+
--password secret
|
|
28
|
+
```
|
|
29
|
+
This automatically creates your user account and agent, and logs you in!
|
|
30
|
+
|
|
31
|
+
2. **Start using:**
|
|
32
|
+
```bash
|
|
33
|
+
forge repos list
|
|
34
|
+
forge issues create --repo @owner/repo --title "Bug found"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Option 2: Existing User (Login)
|
|
38
|
+
|
|
19
39
|
1. **Get your API key** from Forge at `/settings/agents`
|
|
20
40
|
2. **Login:**
|
|
21
41
|
```bash
|
|
@@ -32,6 +52,22 @@ bun add -g @kernelius/forge-cli
|
|
|
32
52
|
### Authentication
|
|
33
53
|
|
|
34
54
|
```bash
|
|
55
|
+
# Create a new account (signup)
|
|
56
|
+
forge auth signup \
|
|
57
|
+
--username johndoe \
|
|
58
|
+
--email john@example.com \
|
|
59
|
+
--name "John Doe" \
|
|
60
|
+
--password secret
|
|
61
|
+
|
|
62
|
+
# Optional: customize agent
|
|
63
|
+
forge auth signup \
|
|
64
|
+
--username johndoe \
|
|
65
|
+
--email john@example.com \
|
|
66
|
+
--name "John Doe" \
|
|
67
|
+
--password secret \
|
|
68
|
+
--agent-name "Johnny's Assistant" \
|
|
69
|
+
--agent-emoji "🚀"
|
|
70
|
+
|
|
35
71
|
# Login with agent API key
|
|
36
72
|
forge auth login --token forge_agent_xxx...
|
|
37
73
|
|
package/SKILL.md
CHANGED
|
@@ -40,7 +40,18 @@ Before using any forge commands, ensure the user is authenticated:
|
|
|
40
40
|
forge auth whoami
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
If not authenticated, the user
|
|
43
|
+
If not authenticated, the user can either:
|
|
44
|
+
|
|
45
|
+
**Option 1: Create a new account (signup)**
|
|
46
|
+
```bash
|
|
47
|
+
forge auth signup \
|
|
48
|
+
--username johndoe \
|
|
49
|
+
--email john@example.com \
|
|
50
|
+
--name "John Doe" \
|
|
51
|
+
--password secret
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Option 2: Login with existing API key**
|
|
44
55
|
1. Get an agent API key from Forge at `/settings/agents`
|
|
45
56
|
2. Login with: `forge auth login --token forge_agent_xxx...`
|
|
46
57
|
|
|
@@ -106,6 +117,24 @@ forge issues close --repo @owner/repo --number 42
|
|
|
106
117
|
forge issues comment --repo @owner/repo --number 42 --body "This is fixed now"
|
|
107
118
|
```
|
|
108
119
|
|
|
120
|
+
**List comments on an issue:**
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
forge issues comments --repo @owner/repo --number 42
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Reopen an issue:**
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
forge issues reopen --repo @owner/repo --number 42
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Edit an issue:**
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
forge issues edit --repo @owner/repo --number 42 --title "New title" --body "Updated description"
|
|
136
|
+
```
|
|
137
|
+
|
|
109
138
|
## Pull Requests
|
|
110
139
|
|
|
111
140
|
**List pull requests:**
|
|
@@ -148,6 +177,50 @@ forge prs close --repo @owner/repo --number 10
|
|
|
148
177
|
forge prs comment --repo @owner/repo --number 10 --body "Looks good to me!"
|
|
149
178
|
```
|
|
150
179
|
|
|
180
|
+
**Submit a review:**
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# Approve a PR
|
|
184
|
+
forge prs review --repo @owner/repo --number 10 --state approve --body "LGTM!"
|
|
185
|
+
|
|
186
|
+
# Request changes
|
|
187
|
+
forge prs review --repo @owner/repo --number 10 --state request_changes --body "Please fix X"
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**View PR diff:**
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
forge prs diff --repo @owner/repo --number 10
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**List commits in a PR:**
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
forge prs commits --repo @owner/repo --number 10
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Templates
|
|
203
|
+
|
|
204
|
+
**List available templates:**
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
forge templates list
|
|
208
|
+
# Filter by organization type:
|
|
209
|
+
forge templates list --org-type healthcare
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**View template details:**
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
forge templates view patient-record
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**Create repository from template:**
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
forge repos create --name my-patient-repo --template patient-record --visibility private
|
|
222
|
+
```
|
|
223
|
+
|
|
151
224
|
## Important Notes
|
|
152
225
|
|
|
153
226
|
- **Always specify `--repo @owner/repo`** when working with issues or PRs
|
package/dist/index.js
CHANGED
|
@@ -216,37 +216,42 @@ function createAuthCommand() {
|
|
|
216
216
|
process.exit(1);
|
|
217
217
|
}
|
|
218
218
|
});
|
|
219
|
-
auth.command("signup").description("Create a new user account with an agent").requiredOption("--
|
|
219
|
+
auth.command("signup").description("Create a new user account with an agent").requiredOption("--username <username>", "Your username (e.g., johndoe)").requiredOption("--email <email>", "User email address").requiredOption("--name <name>", "Your full name").requiredOption("--password <password>", "User password").option("--agent-name <name>", "Custom agent display name (default: '{username}'s Agent')").option("--agent-emoji <emoji>", "Agent emoji (default: random)").option("--api-url <url>", "Forge API URL", "http://localhost:3001").action(async (options) => {
|
|
220
220
|
try {
|
|
221
221
|
const {
|
|
222
|
+
username,
|
|
222
223
|
email,
|
|
223
|
-
|
|
224
|
+
name,
|
|
224
225
|
password,
|
|
225
|
-
agentUsername,
|
|
226
226
|
agentName,
|
|
227
227
|
agentEmoji,
|
|
228
228
|
apiUrl
|
|
229
229
|
} = options;
|
|
230
|
-
if (!/^[a-zA-Z0-9_-]+$/.test(
|
|
230
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(username)) {
|
|
231
231
|
console.error(
|
|
232
232
|
chalk.red(
|
|
233
|
-
"Error:
|
|
233
|
+
"Error: Username can only contain letters, numbers, underscores, and hyphens"
|
|
234
234
|
)
|
|
235
235
|
);
|
|
236
236
|
process.exit(1);
|
|
237
237
|
}
|
|
238
|
+
const agentUsername = `${username}-agent`;
|
|
239
|
+
const finalAgentName = agentName || `${username}'s Agent`;
|
|
238
240
|
console.log(chalk.dim("Creating user account and agent..."));
|
|
241
|
+
console.log(chalk.dim(` Human username: ${username}`));
|
|
242
|
+
console.log(chalk.dim(` Agent username: ${agentUsername}`));
|
|
239
243
|
const response = await fetch(`${apiUrl}/api/agents/signup`, {
|
|
240
244
|
method: "POST",
|
|
241
245
|
headers: {
|
|
242
246
|
"Content-Type": "application/json"
|
|
243
247
|
},
|
|
244
248
|
body: JSON.stringify({
|
|
249
|
+
username,
|
|
245
250
|
userEmail: email,
|
|
246
|
-
userName,
|
|
251
|
+
userName: name,
|
|
247
252
|
userPassword: password,
|
|
248
253
|
agentUsername,
|
|
249
|
-
agentName,
|
|
254
|
+
agentName: finalAgentName,
|
|
250
255
|
agentEmoji
|
|
251
256
|
})
|
|
252
257
|
});
|
|
@@ -1044,9 +1049,10 @@ function createIssuesCommand() {
|
|
|
1044
1049
|
issues.command("labels").description("List repository labels").requiredOption("--repo <repo>", "Repository (@owner/name)").action(async (options) => {
|
|
1045
1050
|
try {
|
|
1046
1051
|
const [ownerIdentifier, name] = parseRepoArg2(options.repo);
|
|
1047
|
-
const
|
|
1052
|
+
const result = await apiGet(
|
|
1048
1053
|
`/api/repositories/${ownerIdentifier}/${name}/labels`
|
|
1049
1054
|
);
|
|
1055
|
+
const labels = result.labels || [];
|
|
1050
1056
|
if (labels.length === 0) {
|
|
1051
1057
|
console.log(chalk4.yellow("No labels found"));
|
|
1052
1058
|
return;
|
|
@@ -1364,7 +1370,8 @@ function createPrsCommand() {
|
|
|
1364
1370
|
const pr = await apiGet(
|
|
1365
1371
|
`/api/repositories/${ownerIdentifier}/${name}/pulls/${options.number}`
|
|
1366
1372
|
);
|
|
1367
|
-
const
|
|
1373
|
+
const result = await apiGet(`/api/pulls/${pr.id}/reviews`);
|
|
1374
|
+
const reviews = result.reviews || [];
|
|
1368
1375
|
if (reviews.length === 0) {
|
|
1369
1376
|
console.log(chalk5.yellow("No reviews found"));
|
|
1370
1377
|
return;
|
|
@@ -1398,7 +1405,8 @@ function createPrsCommand() {
|
|
|
1398
1405
|
const pr = await apiGet(
|
|
1399
1406
|
`/api/repositories/${ownerIdentifier}/${name}/pulls/${options.number}`
|
|
1400
1407
|
);
|
|
1401
|
-
const
|
|
1408
|
+
const result = await apiGet(`/api/pulls/${pr.id}/commits`);
|
|
1409
|
+
const commits = result.commits || [];
|
|
1402
1410
|
if (commits.length === 0) {
|
|
1403
1411
|
console.log(chalk5.yellow("No commits found"));
|
|
1404
1412
|
return;
|
|
@@ -1541,7 +1549,8 @@ function createOrgsCommand() {
|
|
|
1541
1549
|
});
|
|
1542
1550
|
orgs.command("members").description("List organization members").argument("<slug>", "Organization slug").action(async (slug) => {
|
|
1543
1551
|
try {
|
|
1544
|
-
const
|
|
1552
|
+
const result = await apiGet(`/api/orgs/${slug}/members`);
|
|
1553
|
+
const members = result.members || [];
|
|
1545
1554
|
if (members.length === 0) {
|
|
1546
1555
|
console.log(chalk6.yellow("No members found"));
|
|
1547
1556
|
return;
|
|
@@ -1559,7 +1568,7 @@ function createOrgsCommand() {
|
|
|
1559
1568
|
});
|
|
1560
1569
|
orgs.command("member-add").description("Add a member to organization").argument("<slug>", "Organization slug").argument("<username>", "Username to add").option("--role <role>", "Member role (owner/admin/member)", "member").action(async (slug, username, options) => {
|
|
1561
1570
|
try {
|
|
1562
|
-
await apiPost(`/api/
|
|
1571
|
+
await apiPost(`/api/orgs/${slug}/members`, {
|
|
1563
1572
|
username,
|
|
1564
1573
|
role: options.role
|
|
1565
1574
|
});
|
|
@@ -1571,7 +1580,7 @@ function createOrgsCommand() {
|
|
|
1571
1580
|
});
|
|
1572
1581
|
orgs.command("member-remove").description("Remove a member from organization").argument("<slug>", "Organization slug").argument("<username>", "Username to remove").action(async (slug, username) => {
|
|
1573
1582
|
try {
|
|
1574
|
-
await apiDelete(`/api/
|
|
1583
|
+
await apiDelete(`/api/orgs/${slug}/members/${username}`);
|
|
1575
1584
|
console.log(chalk6.green(`\u2713 Removed @${username} from @${slug}`));
|
|
1576
1585
|
} catch (error) {
|
|
1577
1586
|
console.error(chalk6.red(`Error: ${error.message}`));
|
|
@@ -1580,7 +1589,8 @@ function createOrgsCommand() {
|
|
|
1580
1589
|
});
|
|
1581
1590
|
orgs.command("teams").description("List organization teams").argument("<slug>", "Organization slug").action(async (slug) => {
|
|
1582
1591
|
try {
|
|
1583
|
-
const
|
|
1592
|
+
const result = await apiGet(`/api/orgs/${slug}/teams`);
|
|
1593
|
+
const teams = result.teams || [];
|
|
1584
1594
|
if (teams.length === 0) {
|
|
1585
1595
|
console.log(chalk6.yellow("No teams found"));
|
|
1586
1596
|
return;
|
|
@@ -1600,7 +1610,7 @@ function createOrgsCommand() {
|
|
|
1600
1610
|
});
|
|
1601
1611
|
orgs.command("team-create").description("Create a team in organization").argument("<slug>", "Organization slug").requiredOption("--name <name>", "Team name").option("--description <desc>", "Team description").action(async (slug, options) => {
|
|
1602
1612
|
try {
|
|
1603
|
-
const team = await apiPost(`/api/
|
|
1613
|
+
const team = await apiPost(`/api/orgs/${slug}/teams`, {
|
|
1604
1614
|
name: options.name,
|
|
1605
1615
|
description: options.description
|
|
1606
1616
|
});
|
|
@@ -1612,9 +1622,10 @@ function createOrgsCommand() {
|
|
|
1612
1622
|
});
|
|
1613
1623
|
orgs.command("team-members").description("List team members").argument("<slug>", "Organization slug").argument("<team>", "Team name").action(async (slug, team) => {
|
|
1614
1624
|
try {
|
|
1615
|
-
const
|
|
1616
|
-
`/api/
|
|
1625
|
+
const result = await apiGet(
|
|
1626
|
+
`/api/orgs/${slug}/teams/${team}/members`
|
|
1617
1627
|
);
|
|
1628
|
+
const members = result.members || [];
|
|
1618
1629
|
if (members.length === 0) {
|
|
1619
1630
|
console.log(chalk6.yellow("No team members found"));
|
|
1620
1631
|
return;
|
|
@@ -1632,7 +1643,7 @@ function createOrgsCommand() {
|
|
|
1632
1643
|
orgs.command("team-add-member").description("Add a member to team").argument("<slug>", "Organization slug").argument("<team>", "Team name").argument("<username>", "Username to add").action(async (slug, team, username) => {
|
|
1633
1644
|
try {
|
|
1634
1645
|
await apiPost(
|
|
1635
|
-
`/api/
|
|
1646
|
+
`/api/orgs/${slug}/teams/${team}/members`,
|
|
1636
1647
|
{
|
|
1637
1648
|
username
|
|
1638
1649
|
}
|
|
@@ -1646,7 +1657,7 @@ function createOrgsCommand() {
|
|
|
1646
1657
|
orgs.command("team-remove-member").description("Remove a member from team").argument("<slug>", "Organization slug").argument("<team>", "Team name").argument("<username>", "Username to remove").action(async (slug, team, username) => {
|
|
1647
1658
|
try {
|
|
1648
1659
|
await apiDelete(
|
|
1649
|
-
`/api/
|
|
1660
|
+
`/api/orgs/${slug}/teams/${team}/members/${username}`
|
|
1650
1661
|
);
|
|
1651
1662
|
console.log(chalk6.green(`\u2713 Removed @${username} from team ${team}`));
|
|
1652
1663
|
} catch (error) {
|