@clawcard/cli 1.1.0 → 1.1.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawcard/cli",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "The ClawCard CLI — manage your agent keys, billing, and setup from the terminal",
5
5
  "bin": {
6
6
  "clawcard": "./bin/clawcard.mjs"
@@ -11,6 +11,9 @@ const COMMANDS = [
11
11
  [" logout", "Clear session"],
12
12
  [" whoami", "Show current account"],
13
13
  ["", ""],
14
+ [orange.bold("Agent"), ""],
15
+ [" agent", "Show your agent's identity"],
16
+ ["", ""],
14
17
  [orange.bold("Keys"), ""],
15
18
  [" keys", "Interactive key management"],
16
19
  [" keys create", "Create a new API key"],
@@ -34,6 +34,26 @@ export async function keysCommand() {
34
34
  export async function keysCreateCommand() {
35
35
  requireAuth();
36
36
 
37
+ // Check if user already has an active key
38
+ try {
39
+ const existing = await listAgents();
40
+ const active = existing.filter((a) => a.status === "active");
41
+ if (active.length > 0) {
42
+ p.log.warn(
43
+ `You already have an active key: ${orange(active[0].name || "unnamed")} (${active[0].keyPrefix}...)`
44
+ );
45
+ p.log.info(
46
+ `To create a new key, first revoke the existing one with: ${chalk.dim("clawcard keys revoke")}`
47
+ );
48
+ p.log.info(
49
+ chalk.dim("This will close all cards, delete credentials, and return allocated budget to your account balance.")
50
+ );
51
+ return;
52
+ }
53
+ } catch {
54
+ // couldn't check — proceed and let the API handle it
55
+ }
56
+
37
57
  const name = await p.text({
38
58
  message: "Key name",
39
59
  placeholder: "my-agent",
@@ -82,16 +102,15 @@ export async function keysCreateCommand() {
82
102
  p.log.success("Copied to clipboard");
83
103
  }
84
104
 
85
- if (result.email || result.phone) {
86
- p.log.info(
87
- [
88
- result.email && `Email: ${result.email}`,
89
- result.phone && `Phone: ${result.phone}`,
90
- ]
91
- .filter(Boolean)
92
- .join("\n")
93
- );
94
- }
105
+ // Show provisioned resources
106
+ const details = [
107
+ `Name: ${orange.bold(result.name || "unnamed")}`,
108
+ result.email && `Email: ${result.email}`,
109
+ result.phone && `Phone: ${result.phone}`,
110
+ `Limit: $${(result.spendLimitCents / 100).toFixed(2)}`,
111
+ ].filter(Boolean).join("\n");
112
+
113
+ p.note(details, "Your Agent");
95
114
  } catch (err) {
96
115
  s.stop("Failed to create key");
97
116
  p.log.error(err.message);
@@ -189,6 +208,41 @@ export async function keysInfoCommand(keyIdOrPrefix) {
189
208
  }
190
209
  }
191
210
 
211
+ export async function agentStatusCommand() {
212
+ requireAuth();
213
+
214
+ const s = p.spinner();
215
+ s.start("Fetching agent...");
216
+
217
+ try {
218
+ const agents = await listAgents();
219
+ const active = agents.filter((a) => a.status === "active");
220
+
221
+ if (!active.length) {
222
+ s.stop("");
223
+ p.log.info("No active agent. Create one with: clawcard keys create");
224
+ return;
225
+ }
226
+
227
+ const agent = await getAgent(active[0].id);
228
+ s.stop("");
229
+
230
+ const info = [
231
+ `Name: ${orange.bold(agent.name || "unnamed")}`,
232
+ `Key: ${chalk.dim(agent.keyPrefix + "...")}`,
233
+ `Email: ${agent.email || "-"}`,
234
+ `Phone: ${agent.phone || "-"}`,
235
+ `Limit: $${(agent.spendLimitCents / 100).toFixed(2)}`,
236
+ `Status: ${chalk.green("active")}`,
237
+ ].join("\n");
238
+
239
+ p.note(info, "Your Agent");
240
+ } catch (err) {
241
+ s.stop("Failed");
242
+ p.log.error(err.message);
243
+ }
244
+ }
245
+
192
246
  export async function keysRevokeCommand() {
193
247
  requireAuth();
194
248
 
package/src/index.js CHANGED
@@ -88,6 +88,15 @@ keys
88
88
  await keysRevokeCommand();
89
89
  });
90
90
 
91
+ // Agent status
92
+ program
93
+ .command("agent")
94
+ .description("Show your agent's identity (email, phone, key)")
95
+ .action(async () => {
96
+ const { agentStatusCommand } = await import("./commands/keys.js");
97
+ await agentStatusCommand();
98
+ });
99
+
91
100
  // Setup
92
101
  program
93
102
  .command("setup")
@@ -179,13 +188,18 @@ if (process.argv.length <= 2) {
179
188
 
180
189
  const options = loggedIn
181
190
  ? [
191
+ {
192
+ value: "agent",
193
+ label: "My Agent",
194
+ hint: "email, phone, key details",
195
+ },
182
196
  {
183
197
  value: "setup",
184
198
  label: "Setup",
185
199
  hint: "set up your agent",
186
200
  },
187
201
  { value: "billing", label: "Billing", hint: "check balance & top up" },
188
- { value: "referral", label: "Referral", hint: "share & earn $10" },
202
+ { value: "referral", label: "Referral", hint: "share & earn $5" },
189
203
  { value: "whoami", label: "Who am I?", hint: "show current account" },
190
204
  { value: "logout", label: "Logout", hint: "clear session" },
191
205
  { value: "help", label: "Help", hint: "show all commands" },
@@ -215,6 +229,7 @@ if (process.argv.length <= 2) {
215
229
  signup: () => import("./commands/signup.js").then((m) => m.signupCommand()),
216
230
  logout: () => import("./commands/logout.js").then((m) => m.logoutCommand()),
217
231
  whoami: () => import("./commands/whoami.js").then((m) => m.whoamiCommand()),
232
+ agent: () => import("./commands/keys.js").then((m) => m.agentStatusCommand()),
218
233
  keys: () => import("./commands/keys.js").then((m) => m.keysCommand()),
219
234
  setup: () => import("./commands/setup.js").then((m) => m.setupCommand()),
220
235
  billing: () =>