argus-media-cli 0.1.1 → 0.3.0

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.
Files changed (3) hide show
  1. package/README.md +24 -12
  2. package/dist/index.js +381 -34
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -17,7 +17,7 @@ npx argus-media-cli upload photo.jpg
17
17
  ## Setup
18
18
 
19
19
  ```bash
20
- argus login
20
+ argus-media-cli login
21
21
  ```
22
22
 
23
23
  Or set your API key as an environment variable:
@@ -31,37 +31,49 @@ export ARGUS_API_KEY=ak_your_key_here
31
31
  ### Upload
32
32
 
33
33
  ```bash
34
- argus upload photo.jpg
35
- argus upload hero.png --project campaign-q2 --tags hero,banner
34
+ argus-media-cli upload photo.jpg
35
+ argus-media-cli upload hero.png --project campaign-q2 --tags hero,banner
36
36
  ```
37
37
 
38
38
  ### Search
39
39
 
40
40
  ```bash
41
- argus search "sunset landscape"
42
- argus search --project website --status ready --json
41
+ argus-media-cli search "sunset landscape"
42
+ argus-media-cli search --project website --status ready --json
43
43
  ```
44
44
 
45
45
  ### List
46
46
 
47
47
  ```bash
48
- argus list
49
- argus list --project website --limit 20
48
+ argus-media-cli list
49
+ argus-media-cli list --project website --limit 20
50
50
  ```
51
51
 
52
52
  ### Get
53
53
 
54
54
  ```bash
55
- argus get <asset-id>
56
- argus get abc12345 --json
55
+ argus-media-cli get <asset-id>
56
+ argus-media-cli get abc12345 --json
57
57
  ```
58
58
 
59
59
  ### Login
60
60
 
61
61
  ```bash
62
- argus login # Interactive prompt
63
- argus login --key ak_xxx # Non-interactive
64
- argus login --url http://localhost:8787 # Custom API URL
62
+ argus-media-cli login # Interactive prompt
63
+ argus-media-cli login --key ak_xxx # Non-interactive
64
+ argus-media-cli login --url http://localhost:8787 # Custom API URL
65
+ ```
66
+
67
+ ### API Keys
68
+
69
+ Manage API keys for the current workspace. Works with either a session (from
70
+ `login`) or an existing API key. Use this to rotate a dead or expired key:
71
+
72
+ ```bash
73
+ argus-media-cli login # Magic-link session (no key needed)
74
+ argus-media-cli keys list # List active keys
75
+ argus-media-cli keys create --name "MCP" # Mint a new key (shown once)
76
+ argus-media-cli keys revoke <id> # Revoke a key (admin only)
65
77
  ```
66
78
 
67
79
  ## Options
package/dist/index.js CHANGED
@@ -23,22 +23,27 @@ async function saveConfig(config) {
23
23
  function getBaseUrl(config) {
24
24
  return process.env.ARGUS_BASE_URL || config.baseUrl || "https://argus.build";
25
25
  }
26
- function getApiKey(config) {
27
- const key = process.env.ARGUS_API_KEY || config.apiKey;
28
- if (!key) {
29
- console.error("Error: No API key configured.");
30
- console.error("Run `argus login` to authenticate, or set ARGUS_API_KEY.");
31
- process.exit(1);
26
+ function getAuthHeaders(config) {
27
+ // API key takes precedence (CI / backward compat)
28
+ const apiKey = process.env.ARGUS_API_KEY || config.apiKey;
29
+ if (apiKey) {
30
+ return { Authorization: `Bearer ${apiKey}` };
31
+ }
32
+ // Session-based auth (interactive login)
33
+ const sessionId = config.sessionId;
34
+ if (sessionId) {
35
+ return { Cookie: `session=${sessionId}` };
32
36
  }
33
- return key;
37
+ console.error("Error: Not authenticated.");
38
+ console.error("Run `argus-media-cli login` to sign in, or set ARGUS_API_KEY.");
39
+ process.exit(1);
34
40
  }
35
41
  async function apiRequest(config, method, path, body) {
36
42
  const url = `${getBaseUrl(config)}${path}`;
37
- const apiKey = getApiKey(config);
38
43
  const opts = {
39
44
  method,
40
45
  headers: {
41
- Authorization: `Bearer ${apiKey}`,
46
+ ...getAuthHeaders(config),
42
47
  ...(body ? { "Content-Type": "application/json" } : {}),
43
48
  },
44
49
  ...(body ? { body: JSON.stringify(body) } : {}),
@@ -92,6 +97,8 @@ function formatAssetDetail(a) {
92
97
  lines.push(` Project: ${a.project}`);
93
98
  if (a.url)
94
99
  lines.push(` URL: ${a.url}`);
100
+ if (a.displayUrl)
101
+ lines.push(` Display: ${a.displayUrl}`);
95
102
  if (a.tags?.length)
96
103
  lines.push(` Tags: ${a.tags.join(", ")}`);
97
104
  if (a.uploadedBy)
@@ -118,6 +125,7 @@ function formatAssetDetail(a) {
118
125
  // ─── Commands ──────────────────────────────────────────────────────────────
119
126
  async function cmdLogin(args, flags) {
120
127
  const config = await loadConfig();
128
+ // Backward-compat: --key sets API key directly (useful for CI)
121
129
  if (flags.key) {
122
130
  config.apiKey = flags.key;
123
131
  await saveConfig(config);
@@ -132,35 +140,71 @@ async function cmdLogin(args, flags) {
132
140
  }
133
141
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
134
142
  const ask = (q) => new Promise((resolve) => rl.question(q, resolve));
135
- console.log("Argus CLI Login");
136
- console.log("Get your API key at https://argus.build/ui\n");
137
- const key = await ask("API key: ");
143
+ const baseUrl = getBaseUrl(config);
144
+ console.log("\x1b[1mArgus CLI Login\x1b[0m\n");
145
+ const email = (await ask("Email: ")).trim().toLowerCase();
146
+ if (!email) {
147
+ rl.close();
148
+ console.error("No email provided.");
149
+ process.exit(1);
150
+ }
151
+ // Request magic code
152
+ console.log("Sending login code...");
153
+ const magicRes = await fetch(`${baseUrl}/auth/magic`, {
154
+ method: "POST",
155
+ headers: { "Content-Type": "application/json" },
156
+ body: JSON.stringify({ email }),
157
+ });
158
+ if (!magicRes.ok) {
159
+ rl.close();
160
+ const err = await magicRes.json().catch(() => ({ error: "Request failed" }));
161
+ console.error(`Error: ${err.error || "Could not send login code."}`);
162
+ process.exit(1);
163
+ }
164
+ console.log(`\nCheck your email for a 6-digit code.\n`);
165
+ const code = (await ask("Code: ")).trim();
138
166
  rl.close();
139
- if (!key.trim()) {
140
- console.error("No key provided.");
167
+ if (!code) {
168
+ console.error("No code provided.");
169
+ process.exit(1);
170
+ }
171
+ // Verify code and get session
172
+ const verifyRes = await fetch(`${baseUrl}/auth/magic/verify`, {
173
+ method: "POST",
174
+ headers: { "Content-Type": "application/json" },
175
+ body: JSON.stringify({ email, code, source: "cli" }),
176
+ });
177
+ if (!verifyRes.ok) {
178
+ const err = await verifyRes.json().catch(() => ({ error: "Verification failed" }));
179
+ console.error(`Error: ${err.error || "Invalid or expired code."}`);
180
+ process.exit(1);
181
+ }
182
+ const data = await verifyRes.json();
183
+ if (!data.session) {
184
+ console.error("Error: No session returned from server.");
141
185
  process.exit(1);
142
186
  }
143
- config.apiKey = key.trim();
187
+ config.sessionId = data.session;
188
+ delete config.apiKey; // prefer session auth
144
189
  await saveConfig(config);
145
- // Verify the key works
190
+ console.log("\nAuthenticated! Session saved to ~/.argus/config.json");
191
+ // Show usage summary
146
192
  try {
147
193
  const res = await apiRequest(config, "GET", "/usage");
148
- console.log(`\nAuthenticated! Workspace tier: ${res.tier}`);
194
+ console.log(`Workspace tier: ${res.tier}`);
149
195
  console.log(`Assets: ${res.assets?.used ?? 0}/${res.assets?.limit ?? "unlimited"}`);
150
196
  }
151
- catch (e) {
152
- console.error(`\nWarning: Could not verify key — ${e.message}`);
153
- console.log("Key saved anyway. Check it with `argus list`.");
197
+ catch {
198
+ // non-fatal
154
199
  }
155
200
  }
156
201
  async function cmdUpload(args, flags) {
157
202
  const filePath = args[0];
158
203
  if (!filePath) {
159
- console.error("Usage: argus upload <file> [--project NAME] [--tags a,b,c]");
204
+ console.error("Usage: argus-media-cli upload <file> [--project NAME] [--tags a,b,c]");
160
205
  process.exit(1);
161
206
  }
162
207
  const config = await loadConfig();
163
- const apiKey = getApiKey(config);
164
208
  const baseUrl = getBaseUrl(config);
165
209
  // Read file
166
210
  const fileData = await readFile(filePath);
@@ -177,7 +221,7 @@ async function cmdUpload(args, flags) {
177
221
  form.append("tags", flags.tags);
178
222
  const res = await fetch(`${baseUrl}/assets/upload`, {
179
223
  method: "POST",
180
- headers: { Authorization: `Bearer ${apiKey}` },
224
+ headers: { ...getAuthHeaders(config) },
181
225
  body: form,
182
226
  });
183
227
  if (!res.ok) {
@@ -194,6 +238,8 @@ async function cmdUpload(args, flags) {
194
238
  console.log(`Status: ${asset.status}`);
195
239
  if (asset.url)
196
240
  console.log(`URL: ${asset.url}`);
241
+ if (asset.displayUrl)
242
+ console.log(`Display: ${asset.displayUrl}`);
197
243
  }
198
244
  }
199
245
  async function cmdSearch(args, flags) {
@@ -233,7 +279,7 @@ async function cmdList(_args, flags) {
233
279
  async function cmdGet(args, flags) {
234
280
  const id = args[0];
235
281
  if (!id) {
236
- console.error("Usage: argus get <asset-id>");
282
+ console.error("Usage: argus-media-cli get <asset-id>");
237
283
  process.exit(1);
238
284
  }
239
285
  const config = await loadConfig();
@@ -261,6 +307,234 @@ async function cmdUsage(_args, flags) {
261
307
  console.log(` Storage: ${data.storage?.used != null ? formatBytes(data.storage.used) : "0 B"} / ${data.storage?.limit != null ? formatBytes(data.storage.limit) : "unlimited"}`);
262
308
  }
263
309
  }
310
+ // ─── Phase 2: Generative Commands ─────────────────────────────────────────
311
+ async function cmdCreativeDirection(args, flags) {
312
+ const id = args[0];
313
+ if (!id) {
314
+ console.error("Usage: argus-media-cli creative-direction <asset-id> [--purpose TEXT] [--audience TEXT] [--tone TEXT] [--style TEXT]");
315
+ process.exit(1);
316
+ }
317
+ const config = await loadConfig();
318
+ const body = {};
319
+ if (flags.purpose)
320
+ body.purpose = flags.purpose;
321
+ if (flags.audience)
322
+ body.audience = flags.audience;
323
+ if (flags.tone)
324
+ body.tone = flags.tone;
325
+ if (flags.style)
326
+ body.style = flags.style;
327
+ const data = (await apiRequest(config, "POST", `/assets/${id}/creative-direction`, body));
328
+ if (flags.json) {
329
+ console.log(JSON.stringify(data, null, 2));
330
+ return;
331
+ }
332
+ const cd = data.creativeDirection;
333
+ console.log(`\x1b[1mCreative Direction\x1b[0m${data.cached ? " (cached)" : ""}\n`);
334
+ console.log(cd.rationale);
335
+ if (cd.googleFontsUrl)
336
+ console.log(`\nGoogle Fonts: ${cd.googleFontsUrl}`);
337
+ if (cd.typography?.length) {
338
+ console.log(`\n\x1b[1mTypography:\x1b[0m`);
339
+ for (const t of cd.typography) {
340
+ console.log(` ${t.role}: ${t.css.fontFamily} (${t.css.fontWeight}) — ${t.semantic}`);
341
+ }
342
+ }
343
+ if (cd.colors?.length) {
344
+ console.log(`\n\x1b[1mColors:\x1b[0m`);
345
+ for (const c of cd.colors) {
346
+ console.log(` ${c.role}: ${c.css.color} — ${c.semantic}`);
347
+ }
348
+ }
349
+ if (cd.layout?.length) {
350
+ console.log(`\n\x1b[1mLayout:\x1b[0m`);
351
+ for (const l of cd.layout) {
352
+ console.log(` ${l.pattern} — ${l.semantic}`);
353
+ }
354
+ }
355
+ }
356
+ async function cmdTypography(args, flags) {
357
+ const id = args[0];
358
+ if (!id) {
359
+ console.error("Usage: argus-media-cli typography <asset-id> [--purpose TEXT]");
360
+ process.exit(1);
361
+ }
362
+ const config = await loadConfig();
363
+ const body = {};
364
+ if (flags.purpose)
365
+ body.purpose = flags.purpose;
366
+ const data = (await apiRequest(config, "POST", `/assets/${id}/typography`, body));
367
+ if (flags.json) {
368
+ console.log(JSON.stringify(data, null, 2));
369
+ return;
370
+ }
371
+ const typo = data.typography;
372
+ console.log(`\x1b[1mTypography Suggestions\x1b[0m${data.cached ? " (cached)" : ""}\n`);
373
+ if (typo.pairings?.length) {
374
+ for (const t of typo.pairings) {
375
+ console.log(` ${t.role}: ${t.css.fontFamily} (${t.css.fontWeight}) — ${t.semantic}`);
376
+ if (t.googleFontsUrl)
377
+ console.log(` Font: ${t.googleFontsUrl}`);
378
+ }
379
+ }
380
+ if (typo.googleFontsUrl)
381
+ console.log(`\nGoogle Fonts: ${typo.googleFontsUrl}`);
382
+ if (typo.rationale)
383
+ console.log(`\n${typo.rationale}`);
384
+ }
385
+ async function cmdPalette(args, flags) {
386
+ const id = args[0];
387
+ if (!id) {
388
+ console.error("Usage: argus-media-cli palette <asset-id>");
389
+ process.exit(1);
390
+ }
391
+ const config = await loadConfig();
392
+ const data = (await apiRequest(config, "POST", `/assets/${id}/palette`));
393
+ if (flags.json) {
394
+ console.log(JSON.stringify(data, null, 2));
395
+ return;
396
+ }
397
+ const palette = data.palette;
398
+ console.log(`\x1b[1mColor Palette\x1b[0m${data.cached ? " (cached)" : ""}\n`);
399
+ if (palette.colors?.length) {
400
+ for (const c of palette.colors) {
401
+ console.log(` ${c.role}: ${c.css.color} — ${c.semantic}`);
402
+ }
403
+ }
404
+ if (palette.rationale)
405
+ console.log(`\n${palette.rationale}`);
406
+ }
407
+ async function cmdCohesion(args, flags) {
408
+ if (args.length < 2) {
409
+ console.error("Usage: argus-media-cli cohesion <asset-id> <asset-id> [<asset-id>...] [--purpose TEXT] [--brand TEXT]");
410
+ process.exit(1);
411
+ }
412
+ const config = await loadConfig();
413
+ const body = { assetIds: args };
414
+ if (flags.purpose || flags.brand) {
415
+ const context = {};
416
+ if (flags.purpose)
417
+ context.purpose = flags.purpose;
418
+ if (flags.brand)
419
+ context.brandName = flags.brand;
420
+ body.context = context;
421
+ }
422
+ const data = (await apiRequest(config, "POST", "/assets/compare-cohesion", body));
423
+ if (flags.json) {
424
+ console.log(JSON.stringify(data, null, 2));
425
+ return;
426
+ }
427
+ const c = data.cohesion;
428
+ console.log(`\x1b[1mCohesion Report\x1b[0m${data.cached ? " (cached)" : ""}\n`);
429
+ console.log(` Overall: ${c.overallScore}/100`);
430
+ console.log(` Typography: ${c.typography.score}/100 — ${c.typography.consistency}`);
431
+ console.log(` Color: ${c.color.score}/100 — ${c.color.harmony}`);
432
+ console.log(` Mood: ${c.mood.score}/100 — ${c.mood.alignment}`);
433
+ if (c.suggestions?.length) {
434
+ console.log(`\n\x1b[1mSuggestions:\x1b[0m`);
435
+ for (const s of c.suggestions) {
436
+ const sev = s.severity === "high" ? "\x1b[31m" : s.severity === "medium" ? "\x1b[33m" : "\x1b[32m";
437
+ console.log(` ${sev}${s.severity}\x1b[0m ${s.asset.slice(0, 8)}: ${s.suggestion}`);
438
+ }
439
+ }
440
+ if (c.rationale)
441
+ console.log(`\n${c.rationale}`);
442
+ }
443
+ // ─── API Key Management ───────────────────────────────────────────────────
444
+ async function cmdKeys(args, flags) {
445
+ const sub = args[0];
446
+ const rest = args.slice(1);
447
+ if (!sub || sub === "list" || sub === "ls") {
448
+ return cmdKeysList(rest, flags);
449
+ }
450
+ if (sub === "create" || sub === "new") {
451
+ return cmdKeysCreate(rest, flags);
452
+ }
453
+ if (sub === "revoke" || sub === "delete" || sub === "rm") {
454
+ return cmdKeysRevoke(rest, flags);
455
+ }
456
+ console.error(`Unknown keys subcommand: ${sub}`);
457
+ console.error("Usage: argus-media-cli keys <list|create|revoke>");
458
+ process.exit(1);
459
+ }
460
+ async function cmdKeysList(_args, flags) {
461
+ const config = await loadConfig();
462
+ const data = (await apiRequest(config, "GET", "/keys"));
463
+ if (flags.json) {
464
+ console.log(JSON.stringify(data, null, 2));
465
+ return;
466
+ }
467
+ const keys = data.keys || [];
468
+ if (!keys.length) {
469
+ console.log("No API keys found.");
470
+ console.log("Create one with: argus-media-cli keys create --name 'My Key'");
471
+ return;
472
+ }
473
+ console.log(`\x1b[1m${keys.length} API key${keys.length === 1 ? "" : "s"}\x1b[0m\n`);
474
+ for (const k of keys) {
475
+ const status = k.revoked_at ? "\x1b[31mrevoked\x1b[0m" : "\x1b[32mactive\x1b[0m ";
476
+ const lastUsed = k.last_used_at ? `used ${k.last_used_at}` : "never used";
477
+ console.log(` ${status} ${k.key_prefix}… ${k.name}`);
478
+ console.log(` id: ${k.id}`);
479
+ console.log(` created ${k.created_at}, ${lastUsed}`);
480
+ }
481
+ }
482
+ async function cmdKeysCreate(args, flags) {
483
+ const name = flags.name || args[0] || "API Key";
484
+ const config = await loadConfig();
485
+ const data = (await apiRequest(config, "POST", "/keys", { name }));
486
+ if (flags.json) {
487
+ console.log(JSON.stringify(data, null, 2));
488
+ return;
489
+ }
490
+ console.log(`\x1b[1mAPI key created\x1b[0m\n`);
491
+ console.log(` Name: ${data.name}`);
492
+ console.log(` ID: ${data.id}`);
493
+ console.log(` Prefix: ${data.key_prefix}`);
494
+ console.log(`\n\x1b[1m\x1b[33mKey (shown once — store it now):\x1b[0m`);
495
+ console.log(` ${data.key}\n`);
496
+ console.log(`Use it by setting:`);
497
+ console.log(` export ARGUS_API_KEY=${data.key}`);
498
+ }
499
+ async function cmdKeysRevoke(args, flags) {
500
+ const id = args[0];
501
+ if (!id) {
502
+ console.error("Usage: argus-media-cli keys revoke <id>");
503
+ process.exit(1);
504
+ }
505
+ const config = await loadConfig();
506
+ const data = (await apiRequest(config, "DELETE", `/keys/${id}`));
507
+ if (flags.json) {
508
+ console.log(JSON.stringify(data, null, 2));
509
+ return;
510
+ }
511
+ console.log(`Key ${id} revoked.`);
512
+ }
513
+ async function cmdStyleGuide(args, flags) {
514
+ if (args.length < 1) {
515
+ console.error("Usage: argus-media-cli style-guide <asset-id> [<asset-id>...] [--name TEXT] [--guide-id ID]");
516
+ process.exit(1);
517
+ }
518
+ const config = await loadConfig();
519
+ const body = { assetIds: args };
520
+ if (flags.name)
521
+ body.name = flags.name;
522
+ if (flags["guide-id"])
523
+ body.guideId = flags["guide-id"];
524
+ const data = (await apiRequest(config, "POST", "/style-guides", body));
525
+ if (flags.json) {
526
+ console.log(JSON.stringify(data, null, 2));
527
+ return;
528
+ }
529
+ const sg = data.styleGuide;
530
+ console.log(`\x1b[1mStyle Guide: ${sg.name || sg.id}\x1b[0m\n`);
531
+ console.log(` ID: ${sg.id}`);
532
+ console.log(` Assets: ${sg.sourceAssetIds?.length ?? 0}`);
533
+ if (data.googleFontsUrl)
534
+ console.log(` Fonts: ${data.googleFontsUrl}`);
535
+ if (data.rationale)
536
+ console.log(`\n${data.rationale}`);
537
+ }
264
538
  function parseArgs(argv) {
265
539
  const command = argv[0] || "help";
266
540
  const flags = {};
@@ -288,10 +562,10 @@ function parseArgs(argv) {
288
562
  return { command, args, flags };
289
563
  }
290
564
  function printHelp() {
291
- console.log(`\x1b[1margus\x1b[0m — AI-native media asset management
565
+ console.log(`\x1b[1margus-media-cli\x1b[0m — AI-native media asset management
292
566
 
293
567
  \x1b[1mUsage:\x1b[0m
294
- argus <command> [options]
568
+ argus-media-cli <command> [options]
295
569
 
296
570
  \x1b[1mCommands:\x1b[0m
297
571
  login Authenticate with Argus
@@ -300,6 +574,14 @@ function printHelp() {
300
574
  list List all assets
301
575
  get <id> Get asset details and analysis
302
576
  usage Show workspace usage and limits
577
+ creative-direction <id> Generate creative brief for an asset
578
+ typography <id> Suggest typography pairings for an asset
579
+ palette <id> Generate extended color palette from an asset
580
+ cohesion <id> <id> ... Compare visual cohesion across assets
581
+ style-guide <id> ... Generate a style guide from assets
582
+ keys list List API keys in the current workspace
583
+ keys create [--name] Create a new API key (shown once)
584
+ keys revoke <id> Revoke an API key (admin only)
303
585
 
304
586
  \x1b[1mGlobal Options:\x1b[0m
305
587
  --json Output raw JSON
@@ -315,45 +597,110 @@ function printHelp() {
315
597
  --limit N Max results (default 50)
316
598
  --offset N Pagination offset
317
599
 
600
+ \x1b[1mCreative Direction Options:\x1b[0m
601
+ --purpose TEXT Intended use (e.g. 'hero banner')
602
+ --audience TEXT Target audience
603
+ --tone TEXT Desired tone (e.g. 'professional')
604
+ --style TEXT Visual style (e.g. 'minimalist')
605
+
606
+ \x1b[1mTypography Options:\x1b[0m
607
+ --purpose TEXT Intended use context
608
+
609
+ \x1b[1mCohesion Options:\x1b[0m
610
+ --purpose TEXT Comparison context
611
+ --brand TEXT Brand name for context
612
+
613
+ \x1b[1mStyle Guide Options:\x1b[0m
614
+ --name TEXT Name for the style guide
615
+ --guide-id ID Existing guide ID to update
616
+
318
617
  \x1b[1mLogin Options:\x1b[0m
319
618
  --key KEY Set API key non-interactively
320
619
  --url URL Set custom API base URL
321
620
 
621
+ \x1b[1mKeys Options:\x1b[0m
622
+ --name TEXT Name for the new key (keys create)
623
+
322
624
  \x1b[1mEnvironment:\x1b[0m
323
625
  ARGUS_API_KEY API key (overrides saved config)
324
626
  ARGUS_BASE_URL API base URL (default: https://argus.build)
325
627
 
326
628
  \x1b[1mExamples:\x1b[0m
327
- argus login
328
- argus upload photo.jpg --project campaign-q2 --tags hero,banner
329
- argus search "sunset landscape" --json
330
- argus list --project website --limit 20
331
- argus get abc12345-def6-7890-abcd-ef1234567890
629
+ argus-media-cli login
630
+ argus-media-cli upload photo.jpg --project campaign-q2 --tags hero,banner
631
+ argus-media-cli search "sunset landscape" --json
632
+ argus-media-cli list --project website --limit 20
633
+ argus-media-cli get abc12345-def6-7890-abcd-ef1234567890
332
634
  `);
333
635
  }
636
+ // ─── Onboarding ───────────────────────────────────────────────────────────
637
+ function isAuthenticated(config) {
638
+ return !!(process.env.ARGUS_API_KEY || config.apiKey || config.sessionId);
639
+ }
640
+ async function cmdDashboard(_args, flags) {
641
+ const config = await loadConfig();
642
+ const res = await apiRequest(config, "GET", "/usage");
643
+ console.log(`\x1b[1mArgus Dashboard\x1b[0m\n`);
644
+ console.log(` Tier: ${res.tier}`);
645
+ console.log(` Assets: ${res.assets?.used ?? 0} / ${res.assets?.limit ?? "unlimited"}`);
646
+ if (res.storage != null) {
647
+ console.log(` Storage: ${res.storage?.used != null ? formatBytes(res.storage.used) : "0 B"} / ${res.storage?.limit != null ? formatBytes(res.storage.limit) : "unlimited"}`);
648
+ }
649
+ console.log(`\nRun \x1b[1margus-media-cli help\x1b[0m for available commands.`);
650
+ }
334
651
  // ─── Main ──────────────────────────────────────────────────────────────────
335
652
  const COMMANDS = {
653
+ dashboard: cmdDashboard,
336
654
  login: cmdLogin,
337
655
  upload: cmdUpload,
338
656
  search: cmdSearch,
339
657
  list: cmdList,
340
658
  get: cmdGet,
341
659
  usage: cmdUsage,
660
+ "creative-direction": cmdCreativeDirection,
661
+ typography: cmdTypography,
662
+ palette: cmdPalette,
663
+ cohesion: cmdCohesion,
664
+ "style-guide": cmdStyleGuide,
665
+ keys: cmdKeys,
342
666
  };
343
667
  async function main() {
344
- const { command, args, flags } = parseArgs(process.argv.slice(2));
668
+ const rawArgs = process.argv.slice(2);
669
+ // No args: onboarding — show dashboard or prompt login
670
+ if (rawArgs.length === 0) {
671
+ const config = await loadConfig();
672
+ if (isAuthenticated(config)) {
673
+ try {
674
+ await cmdDashboard([], {});
675
+ }
676
+ catch {
677
+ console.log("\x1b[1mArgus Media CLI\x1b[0m\n");
678
+ console.log("Run \x1b[1margus-media-cli help\x1b[0m for available commands.");
679
+ }
680
+ }
681
+ else {
682
+ console.log("\x1b[1mWelcome to Argus!\x1b[0m\n");
683
+ console.log("Get started by signing in:\n");
684
+ console.log(" argus-media-cli login\n");
685
+ console.log("Or set an API key for CI use:\n");
686
+ console.log(" argus-media-cli login --key <your-key>\n");
687
+ console.log("Run \x1b[1margus-media-cli help\x1b[0m for all commands.");
688
+ }
689
+ return;
690
+ }
691
+ const { command, args, flags } = parseArgs(rawArgs);
345
692
  if (command === "help" || command === "--help" || command === "-h") {
346
693
  printHelp();
347
694
  return;
348
695
  }
349
696
  if (command === "version" || command === "--version" || command === "-v") {
350
- console.log("argus-media-cli 0.1.1");
697
+ console.log("argus-media-cli 0.3.0");
351
698
  return;
352
699
  }
353
700
  const handler = COMMANDS[command];
354
701
  if (!handler) {
355
702
  console.error(`Unknown command: ${command}`);
356
- console.error('Run "argus help" for usage.');
703
+ console.error('Run "argus-media-cli help" for usage.');
357
704
  process.exit(1);
358
705
  }
359
706
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "argus-media-cli",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "description": "CLI for Argus — AI-native media asset management. Upload, search, analyze, and manage media assets from the terminal.",
5
5
  "keywords": [
6
6
  "argus",
@@ -21,7 +21,7 @@
21
21
  "homepage": "https://argus.build",
22
22
  "type": "module",
23
23
  "bin": {
24
- "argus": "./dist/index.js"
24
+ "argus-media-cli": "./dist/index.js"
25
25
  },
26
26
  "main": "./dist/index.js",
27
27
  "files": [