@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 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 username, name, and emoji
137
- - Example: `forge auth signup --email user@example.com --agent-username myagent --agent-name "My Agent"`
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 needs to:
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("--email <email>", "User email address").requiredOption("--user-name <name>", "User display name").requiredOption("--password <password>", "User password").requiredOption("--agent-username <username>", "Agent username (e.g., myagent)").requiredOption("--agent-name <name>", "Agent display name").option("--agent-emoji <emoji>", "Agent emoji (e.g., \u{1F916})").option("--api-url <url>", "Forge API URL", "http://localhost:3001").action(async (options) => {
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
- userName,
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(agentUsername)) {
230
+ if (!/^[a-zA-Z0-9_-]+$/.test(username)) {
231
231
  console.error(
232
232
  chalk.red(
233
- "Error: Agent username can only contain letters, numbers, underscores, and hyphens"
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 labels = await apiGet(
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 reviews = await apiGet(`/api/pulls/${pr.id}/reviews`);
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 commits = await apiGet(`/api/pulls/${pr.id}/commits`);
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 members = await apiGet(`/api/organizations/${slug}/members`);
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/organizations/${slug}/members`, {
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/organizations/${slug}/members/${username}`);
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 teams = await apiGet(`/api/organizations/${slug}/teams`);
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/organizations/${slug}/teams`, {
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 members = await apiGet(
1616
- `/api/organizations/${slug}/teams/${team}/members`
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/organizations/${slug}/teams/${team}/members`,
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/organizations/${slug}/teams/${team}/members/${username}`
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kernelius/forge-cli",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "Command-line tool for Kernelius Forge - the agent-native Git platform",
5
5
  "type": "module",
6
6
  "bin": {