@conceptcraft/mindframes 0.1.8 → 0.1.10

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/dist/index.js CHANGED
@@ -1,17 +1,46 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'module'; const require = createRequire(import.meta.url);
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __esm = (fn, res) => function __init() {
6
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
7
- };
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
3
+
4
+ // src/index.ts
5
+ import { Command as Command20 } from "commander";
6
+ import chalk13 from "chalk";
12
7
 
13
8
  // src/lib/brand.ts
14
9
  import path from "path";
10
+ var BRANDS = {
11
+ conceptcraft: {
12
+ id: "conceptcraft",
13
+ name: "conceptcraft",
14
+ displayName: "ConceptCraft",
15
+ description: "CLI tool for ConceptCraft presentation generation",
16
+ commands: ["cc", "conceptcraft"],
17
+ apiUrl: "https://conceptcraft.ai",
18
+ docsUrl: "https://docs.conceptcraft.ai",
19
+ packageName: "@conceptcraft/cli",
20
+ configDir: ".conceptcraft",
21
+ apiKeyEnvVar: "CONCEPTCRAFT_API_KEY",
22
+ apiUrlEnvVar: "CONCEPTCRAFT_API_URL"
23
+ },
24
+ mindframes: {
25
+ id: "mindframes",
26
+ name: "mindframes",
27
+ displayName: "Mindframes",
28
+ description: "CLI tool for Mindframes presentation generation",
29
+ commands: ["mf", "mindframes"],
30
+ apiUrl: "https://mindframes.app",
31
+ docsUrl: "https://docs.mindframes.app",
32
+ packageName: "@conceptcraft/mindframes",
33
+ configDir: ".mindframes",
34
+ apiKeyEnvVar: "MINDFRAMES_API_KEY",
35
+ apiUrlEnvVar: "MINDFRAMES_API_URL"
36
+ }
37
+ };
38
+ var COMMAND_TO_BRAND = {
39
+ cc: "conceptcraft",
40
+ conceptcraft: "conceptcraft",
41
+ mf: "mindframes",
42
+ mindframes: "mindframes"
43
+ };
15
44
  function detectBrand() {
16
45
  const binaryPath = process.argv[1] || "";
17
46
  const binaryName = path.basename(binaryPath).replace(/\.(js|ts)$/, "");
@@ -26,50 +55,52 @@ function detectBrand() {
26
55
  }
27
56
  return BRANDS.mindframes;
28
57
  }
29
- var BRANDS, COMMAND_TO_BRAND, brand;
30
- var init_brand = __esm({
31
- "src/lib/brand.ts"() {
32
- "use strict";
33
- BRANDS = {
34
- conceptcraft: {
35
- id: "conceptcraft",
36
- name: "conceptcraft",
37
- displayName: "ConceptCraft",
38
- description: "CLI tool for ConceptCraft presentation generation",
39
- commands: ["cc", "conceptcraft"],
40
- apiUrl: "https://conceptcraft.ai",
41
- docsUrl: "https://docs.conceptcraft.ai",
42
- packageName: "@conceptcraft/cli",
43
- configDir: ".conceptcraft",
44
- apiKeyEnvVar: "CONCEPTCRAFT_API_KEY",
45
- apiUrlEnvVar: "CONCEPTCRAFT_API_URL"
46
- },
47
- mindframes: {
48
- id: "mindframes",
49
- name: "mindframes",
50
- displayName: "Mindframes",
51
- description: "CLI tool for Mindframes presentation generation",
52
- commands: ["mf", "mindframes"],
53
- apiUrl: "https://mindframes.app",
54
- docsUrl: "https://docs.mindframes.app",
55
- packageName: "@conceptcraft/mindframes",
56
- configDir: ".mindframes",
57
- apiKeyEnvVar: "MINDFRAMES_API_KEY",
58
- apiUrlEnvVar: "MINDFRAMES_API_URL"
59
- }
60
- };
61
- COMMAND_TO_BRAND = {
62
- cc: "conceptcraft",
63
- conceptcraft: "conceptcraft",
64
- mf: "mindframes",
65
- mindframes: "mindframes"
66
- };
67
- brand = detectBrand();
68
- }
69
- });
58
+ var brand = detectBrand();
59
+
60
+ // src/commands/login.ts
61
+ import { Command } from "commander";
62
+ import chalk3 from "chalk";
63
+ import ora from "ora";
64
+ import http from "http";
65
+ import { randomBytes, createHash } from "crypto";
66
+ import open from "open";
70
67
 
71
68
  // src/lib/config.ts
72
69
  import Conf from "conf";
70
+ var DEFAULT_API_URL = "https://www.mindframes.app";
71
+ var schema = {
72
+ apiKey: {
73
+ type: "string"
74
+ },
75
+ apiUrl: {
76
+ type: "string",
77
+ default: DEFAULT_API_URL
78
+ },
79
+ defaultTeamId: {
80
+ type: "string"
81
+ },
82
+ // OAuth tokens (preferred over API key)
83
+ accessToken: {
84
+ type: "string"
85
+ },
86
+ refreshToken: {
87
+ type: "string"
88
+ },
89
+ tokenExpiresAt: {
90
+ type: "number"
91
+ },
92
+ // OAuth client registration (cached per-server)
93
+ clientId: {
94
+ type: "string"
95
+ },
96
+ clientSecret: {
97
+ type: "string"
98
+ }
99
+ };
100
+ var config = new Conf({
101
+ projectName: brand.name,
102
+ schema
103
+ });
73
104
  function getConfig() {
74
105
  return {
75
106
  apiKey: getApiKey(),
@@ -151,47 +182,6 @@ function setOAuthClient(clientId, clientSecret) {
151
182
  config.set("clientId", clientId);
152
183
  config.set("clientSecret", clientSecret);
153
184
  }
154
- var DEFAULT_API_URL, schema, config;
155
- var init_config = __esm({
156
- "src/lib/config.ts"() {
157
- "use strict";
158
- init_brand();
159
- DEFAULT_API_URL = "https://www.mindframes.app";
160
- schema = {
161
- apiKey: {
162
- type: "string"
163
- },
164
- apiUrl: {
165
- type: "string",
166
- default: DEFAULT_API_URL
167
- },
168
- defaultTeamId: {
169
- type: "string"
170
- },
171
- // OAuth tokens (preferred over API key)
172
- accessToken: {
173
- type: "string"
174
- },
175
- refreshToken: {
176
- type: "string"
177
- },
178
- tokenExpiresAt: {
179
- type: "number"
180
- },
181
- // OAuth client registration (cached per-server)
182
- clientId: {
183
- type: "string"
184
- },
185
- clientSecret: {
186
- type: "string"
187
- }
188
- };
189
- config = new Conf({
190
- projectName: brand.name,
191
- schema
192
- });
193
- }
194
- });
195
185
 
196
186
  // src/lib/output.ts
197
187
  import chalk from "chalk";
@@ -358,40 +348,25 @@ function formatJson(data) {
358
348
  function printJson(data) {
359
349
  console.log(formatJson(data));
360
350
  }
361
- var init_output = __esm({
362
- "src/lib/output.ts"() {
363
- "use strict";
364
- init_config();
365
- }
366
- });
367
351
 
368
- // src/types/media.ts
369
- var init_media = __esm({
370
- "src/types/media.ts"() {
371
- "use strict";
372
- }
373
- });
352
+ // src/lib/feature-cache.ts
353
+ import Conf2 from "conf";
354
+
355
+ // src/lib/auth.ts
356
+ import chalk2 from "chalk";
374
357
 
375
358
  // src/types/index.ts
376
- var EXIT_CODES;
377
- var init_types = __esm({
378
- "src/types/index.ts"() {
379
- "use strict";
380
- init_media();
381
- EXIT_CODES = {
382
- SUCCESS: 0,
383
- GENERAL_ERROR: 1,
384
- AUTH_ERROR: 2,
385
- NOT_FOUND: 3,
386
- RATE_LIMIT: 4,
387
- NETWORK_ERROR: 5,
388
- INVALID_INPUT: 6
389
- };
390
- }
391
- });
359
+ var EXIT_CODES = {
360
+ SUCCESS: 0,
361
+ GENERAL_ERROR: 1,
362
+ AUTH_ERROR: 2,
363
+ NOT_FOUND: 3,
364
+ RATE_LIMIT: 4,
365
+ NETWORK_ERROR: 5,
366
+ INVALID_INPUT: 6
367
+ };
392
368
 
393
369
  // src/lib/auth.ts
394
- import chalk2 from "chalk";
395
370
  async function refreshAccessToken() {
396
371
  const refreshToken = getRefreshToken();
397
372
  const clientId = getClientId();
@@ -440,21 +415,15 @@ function hasAuth() {
440
415
  }
441
416
  async function requireAuth() {
442
417
  if (!hasAuth()) {
443
- const { confirm: confirm4 } = await import("@inquirer/prompts");
444
- try {
445
- const shouldLogin = await confirm4({
446
- message: chalk2.red("Not authenticated.") + " Log in now?",
447
- default: true
448
- });
449
- if (!shouldLogin) {
450
- console.log(chalk2.gray("\nTip: You can also set CC_MINDFRAMES_API_KEY environment variable."));
451
- process.exit(EXIT_CODES.AUTH_ERROR);
452
- }
453
- const { runLoginFlow: runLoginFlow2 } = await Promise.resolve().then(() => (init_login(), login_exports));
454
- await runLoginFlow2({ browser: true });
455
- } catch {
456
- process.exit(EXIT_CODES.AUTH_ERROR);
457
- }
418
+ const cmd2 = brand.commands[0];
419
+ const envVar = brand.apiKeyEnvVar;
420
+ console.error(chalk2.red("\u2717 Not authenticated."));
421
+ console.error();
422
+ console.error(chalk2.bold("To authenticate, run:"));
423
+ console.error(chalk2.cyan(` ${cmd2} login`));
424
+ console.error();
425
+ console.error(chalk2.gray(`Or set ${envVar} environment variable.`));
426
+ process.exit(EXIT_CODES.AUTH_ERROR);
458
427
  }
459
428
  }
460
429
  function maskApiKey(key) {
@@ -472,13 +441,6 @@ function isValidApiKeyFormat(key) {
472
441
  const validPrefixes = ["cc_slides_", "mcp_", "cc_sk_", "sk_"];
473
442
  return validPrefixes.some((prefix) => key.startsWith(prefix));
474
443
  }
475
- var init_auth = __esm({
476
- "src/lib/auth.ts"() {
477
- "use strict";
478
- init_config();
479
- init_types();
480
- }
481
- });
482
444
 
483
445
  // src/lib/api.ts
484
446
  import { readFileSync, statSync } from "fs";
@@ -495,6 +457,14 @@ async function getAuthHeaders() {
495
457
  }
496
458
  return {};
497
459
  }
460
+ var ApiError = class extends Error {
461
+ constructor(message, statusCode, exitCode = 1) {
462
+ super(message);
463
+ this.statusCode = statusCode;
464
+ this.exitCode = exitCode;
465
+ this.name = "ApiError";
466
+ }
467
+ };
498
468
  async function request(endpoint, options = {}) {
499
469
  const apiUrl = getApiUrl();
500
470
  if (!hasAuth()) {
@@ -1088,26 +1058,14 @@ async function pollForCompletion(checkFn, maxAttempts = 60, intervalMs = 2e3) {
1088
1058
  }
1089
1059
  throw new ApiError("Operation timed out", 408, 1);
1090
1060
  }
1091
- var ApiError;
1092
- var init_api = __esm({
1093
- "src/lib/api.ts"() {
1094
- "use strict";
1095
- init_config();
1096
- init_auth();
1097
- init_brand();
1098
- ApiError = class extends Error {
1099
- constructor(message, statusCode, exitCode = 1) {
1100
- super(message);
1101
- this.statusCode = statusCode;
1102
- this.exitCode = exitCode;
1103
- this.name = "ApiError";
1104
- }
1105
- };
1106
- }
1107
- });
1108
1061
 
1109
1062
  // src/lib/feature-cache.ts
1110
- import Conf2 from "conf";
1063
+ var cache = new Conf2({
1064
+ projectName: "conceptcraft",
1065
+ configName: "feature-cache"
1066
+ });
1067
+ var FRESH_TTL = 60 * 60 * 1e3;
1068
+ var STALE_TTL = 24 * 60 * 60 * 1e3;
1111
1069
  function hashApiKey(key) {
1112
1070
  let hash = 0;
1113
1071
  for (let i = 0; i < key.length; i++) {
@@ -1153,33 +1111,11 @@ function invalidateCache() {
1153
1111
  function getCachePath() {
1154
1112
  return cache.path;
1155
1113
  }
1156
- var cache, FRESH_TTL, STALE_TTL;
1157
- var init_feature_cache = __esm({
1158
- "src/lib/feature-cache.ts"() {
1159
- "use strict";
1160
- init_api();
1161
- init_config();
1162
- cache = new Conf2({
1163
- projectName: "conceptcraft",
1164
- configName: "feature-cache"
1165
- });
1166
- FRESH_TTL = 60 * 60 * 1e3;
1167
- STALE_TTL = 24 * 60 * 60 * 1e3;
1168
- }
1169
- });
1170
1114
 
1171
1115
  // src/commands/login.ts
1172
- var login_exports = {};
1173
- __export(login_exports, {
1174
- loginCommand: () => loginCommand,
1175
- runLoginFlow: () => runLoginFlow
1176
- });
1177
- import { Command } from "commander";
1178
- import chalk3 from "chalk";
1179
- import ora from "ora";
1180
- import http from "http";
1181
- import { randomBytes, createHash } from "crypto";
1182
- import open from "open";
1116
+ var CLI_CLIENT_NAME = "ConceptCraft CLI";
1117
+ var CALLBACK_PORT_START = 8765;
1118
+ var CALLBACK_PORT_END = 8775;
1183
1119
  function generateCodeVerifier() {
1184
1120
  return randomBytes(32).toString("base64url");
1185
1121
  }
@@ -1427,43 +1363,22 @@ async function runLoginFlow(options) {
1427
1363
  throw err;
1428
1364
  }
1429
1365
  }
1430
- var CLI_CLIENT_NAME, CALLBACK_PORT_START, CALLBACK_PORT_END, loginCommand;
1431
- var init_login = __esm({
1432
- "src/commands/login.ts"() {
1433
- "use strict";
1434
- init_config();
1435
- init_output();
1436
- init_feature_cache();
1437
- CLI_CLIENT_NAME = "ConceptCraft CLI";
1438
- CALLBACK_PORT_START = 8765;
1439
- CALLBACK_PORT_END = 8775;
1440
- loginCommand = new Command("login").description("Authenticate with ConceptCraft (opens browser)").option("--no-browser", "Print URL instead of opening browser").action(async (options) => {
1441
- console.log();
1442
- if (hasOAuthTokens()) {
1443
- warn("You are already logged in.");
1444
- info("Run 'conceptcraft logout' to log out first, or continue to re-authenticate.");
1445
- console.log();
1446
- }
1447
- try {
1448
- await runLoginFlow(options);
1449
- process.exit(0);
1450
- } catch {
1451
- process.exit(1);
1452
- }
1453
- });
1366
+ var loginCommand = new Command("login").description("Authenticate with ConceptCraft (opens browser)").option("--no-browser", "Print URL instead of opening browser").action(async (options) => {
1367
+ console.log();
1368
+ if (hasOAuthTokens()) {
1369
+ warn("You are already logged in.");
1370
+ info("Run 'conceptcraft logout' to log out first, or continue to re-authenticate.");
1371
+ console.log();
1372
+ }
1373
+ try {
1374
+ await runLoginFlow(options);
1375
+ process.exit(0);
1376
+ } catch {
1377
+ process.exit(1);
1454
1378
  }
1455
1379
  });
1456
1380
 
1457
- // src/index.ts
1458
- init_brand();
1459
- init_login();
1460
- import { Command as Command20 } from "commander";
1461
- import chalk13 from "chalk";
1462
-
1463
1381
  // src/commands/logout.ts
1464
- init_config();
1465
- init_feature_cache();
1466
- init_output();
1467
1382
  import { Command as Command2 } from "commander";
1468
1383
  import { confirm } from "@inquirer/prompts";
1469
1384
  var logoutCommand = new Command2("logout").description("Log out and clear authentication").option("--all", "Clear all config including API key").action(async (options) => {
@@ -1503,11 +1418,6 @@ var logoutCommand = new Command2("logout").description("Log out and clear authen
1503
1418
  });
1504
1419
 
1505
1420
  // src/commands/config.ts
1506
- init_config();
1507
- init_auth();
1508
- init_api();
1509
- init_feature_cache();
1510
- init_output();
1511
1421
  import { Command as Command3 } from "commander";
1512
1422
  import chalk4 from "chalk";
1513
1423
  import { input, password, confirm as confirm2, select } from "@inquirer/prompts";
@@ -1711,13 +1621,10 @@ var configCommand = new Command3("config").description("Manage CLI configuration
1711
1621
  );
1712
1622
 
1713
1623
  // src/commands/create.ts
1714
- init_api();
1715
- init_auth();
1716
1624
  import { Command as Command4 } from "commander";
1717
1625
  import chalk6 from "chalk";
1718
1626
 
1719
1627
  // src/lib/streaming.ts
1720
- init_output();
1721
1628
  import { createParser } from "eventsource-parser";
1722
1629
  import chalk5 from "chalk";
1723
1630
  import ora3 from "ora";
@@ -1979,7 +1886,6 @@ async function streamTextContent(response, options = {}) {
1979
1886
  }
1980
1887
 
1981
1888
  // src/commands/create.ts
1982
- init_output();
1983
1889
  import { readFileSync as readFileSync2, existsSync } from "fs";
1984
1890
  import { resolve } from "path";
1985
1891
  var VALID_GOALS = [
@@ -2461,10 +2367,6 @@ function isUrl(str) {
2461
2367
  }
2462
2368
 
2463
2369
  // src/commands/list.ts
2464
- init_api();
2465
- init_auth();
2466
- init_config();
2467
- init_output();
2468
2370
  import { Command as Command5 } from "commander";
2469
2371
  var listCommand = new Command5("list").description("List presentations").option("-n, --limit <count>", "Number of results to return", "20").option(
2470
2372
  "-f, --format <format>",
@@ -2528,9 +2430,6 @@ var listCommand = new Command5("list").description("List presentations").option(
2528
2430
  });
2529
2431
 
2530
2432
  // src/commands/get.ts
2531
- init_api();
2532
- init_auth();
2533
- init_output();
2534
2433
  import { Command as Command6 } from "commander";
2535
2434
  import chalk7 from "chalk";
2536
2435
  var getCommand = new Command6("get").description("Get presentation details").argument("<slug>", "Presentation slug (e.g., my-presentation-v1-abc123)").option(
@@ -2573,9 +2472,6 @@ var getCommand = new Command6("get").description("Get presentation details").arg
2573
2472
  });
2574
2473
 
2575
2474
  // src/commands/delete.ts
2576
- init_api();
2577
- init_auth();
2578
- init_output();
2579
2475
  import { Command as Command7 } from "commander";
2580
2476
  import { confirm as confirm3 } from "@inquirer/prompts";
2581
2477
  var deleteCommand = new Command7("delete").description("Delete a presentation").argument("<slug>", "Presentation slug (e.g., my-presentation-v1-abc123)").option("-f, --force", "Skip confirmation prompt").option("-q, --quiet", "Suppress output").action(async (slug, options) => {
@@ -2611,9 +2507,6 @@ var deleteCommand = new Command7("delete").description("Delete a presentation").
2611
2507
  });
2612
2508
 
2613
2509
  // src/commands/export.ts
2614
- init_api();
2615
- init_auth();
2616
- init_output();
2617
2510
  import { Command as Command8 } from "commander";
2618
2511
  import { writeFile } from "fs/promises";
2619
2512
  import { resolve as resolve2 } from "path";
@@ -2655,10 +2548,6 @@ function formatBytes(bytes) {
2655
2548
  }
2656
2549
 
2657
2550
  // src/commands/import.ts
2658
- init_api();
2659
- init_auth();
2660
- init_output();
2661
- init_config();
2662
2551
  import { Command as Command9 } from "commander";
2663
2552
  import { readFile } from "fs/promises";
2664
2553
  import { resolve as resolve3, basename as basename2 } from "path";
@@ -2748,10 +2637,6 @@ var importCommand = cmd.option("--dry-run", "Validate without importing").option
2748
2637
  });
2749
2638
 
2750
2639
  // src/commands/branding.ts
2751
- init_api();
2752
- init_auth();
2753
- init_config();
2754
- init_output();
2755
2640
  import { Command as Command10 } from "commander";
2756
2641
  import chalk8 from "chalk";
2757
2642
  import ora6 from "ora";
@@ -2925,13 +2810,9 @@ var brandingCommand = new Command10("branding").description("Manage brand profil
2925
2810
  );
2926
2811
 
2927
2812
  // src/commands/derive.ts
2928
- init_api();
2929
- init_auth();
2930
- init_feature_cache();
2931
2813
  import { Command as Command11 } from "commander";
2932
2814
  import chalk9 from "chalk";
2933
2815
  import ora7 from "ora";
2934
- init_output();
2935
2816
  function createBlogCommand() {
2936
2817
  return new Command11("blog").description("Generate a blog post from a presentation").argument("<slug>", "Presentation slug").option("--words <count>", "Target word count (50-2000)", "300").option(
2937
2818
  "--tone <tone>",
@@ -3055,8 +2936,6 @@ function buildDeriveCommand() {
3055
2936
  }
3056
2937
 
3057
2938
  // src/commands/ideas.ts
3058
- init_auth();
3059
- init_output();
3060
2939
  import { Command as Command12 } from "commander";
3061
2940
  import chalk10 from "chalk";
3062
2941
  var ideasCommand = new Command12("ideas").description("Generate presentation topic ideas").option("--context <text>", "Custom context for idea generation").option("--count <n>", "Number of ideas to generate", "5").option("-f, --format <format>", "Output format (human, json)", "human").action(async (options) => {
@@ -3080,10 +2959,6 @@ var ideasCommand = new Command12("ideas").description("Generate presentation top
3080
2959
  });
3081
2960
 
3082
2961
  // src/commands/whoami.ts
3083
- init_api();
3084
- init_auth();
3085
- init_feature_cache();
3086
- init_output();
3087
2962
  import { Command as Command13 } from "commander";
3088
2963
  import chalk11 from "chalk";
3089
2964
  var whoamiCommand = new Command13("whoami").description("Show current user and team information").option("-f, --format <format>", "Output format (human, json)", "human").action(async (options) => {
@@ -3139,11 +3014,430 @@ var whoamiCommand = new Command13("whoami").description("Show current user and t
3139
3014
  });
3140
3015
 
3141
3016
  // src/commands/skill/index.ts
3142
- init_output();
3143
- init_brand();
3144
3017
  import { Command as Command14 } from "commander";
3145
3018
  import chalk12 from "chalk";
3146
3019
 
3020
+ // src/commands/skill/generate-main-skill.ts
3021
+ function generateMainSkillContent(context) {
3022
+ const { name, cmd: cmd2, displayName } = context;
3023
+ const envPrefix = name.toUpperCase().replace(/-/g, "_");
3024
+ return `---
3025
+ name: ${name}
3026
+ description: ${displayName} CLI for AI-powered content creation. Use when user needs to create presentations, generate video assets (voiceover, music, images, stock videos), use text-to-speech, mix audio, search stock media, or manage branding. This is the main entry point - load specialized skills (${name}-video, ${name}-presentation) for detailed workflows.
3027
+ ---
3028
+
3029
+ # ${displayName} CLI
3030
+
3031
+ A comprehensive CLI for AI-powered content creation. Generate presentations, video assets, voiceovers, music, and search stock media - all from your terminal.
3032
+
3033
+ **Install:** \`npm install -g @${name}/cli\` or \`pnpm add -g @${name}/cli\`
3034
+
3035
+ ---
3036
+
3037
+ ## Quick Reference
3038
+
3039
+ | Task | Command |
3040
+ |------|---------|
3041
+ | Create presentation | \`${cmd2} create "Topic"\` |
3042
+ | Generate video assets | \`${cmd2} video create < scenes.json\` |
3043
+ | Text-to-speech | \`${cmd2} tts generate -t "Text" -o voice.mp3\` |
3044
+ | Generate music | \`${cmd2} music generate -p "upbeat corporate"\` |
3045
+ | Search images | \`${cmd2} image search -q "mountain landscape"\` |
3046
+ | Search videos | \`${cmd2} video search "ocean waves"\` |
3047
+ | Mix audio tracks | \`${cmd2} mix create --video v.mp4 --music m.mp3\` |
3048
+
3049
+ ---
3050
+
3051
+ ## Authentication
3052
+
3053
+ **IMPORTANT:** Most commands require authentication. If a command fails with "Not authenticated", run:
3054
+
3055
+ \`\`\`bash
3056
+ ${cmd2} login
3057
+ \`\`\`
3058
+
3059
+ This opens a browser for OAuth login. Alternatively, set an API key:
3060
+
3061
+ \`\`\`bash
3062
+ export ${envPrefix}_API_KEY="your-key-here"
3063
+ \`\`\`
3064
+
3065
+ **Verify authentication:**
3066
+ \`\`\`bash
3067
+ ${cmd2} whoami
3068
+ \`\`\`
3069
+
3070
+ ---
3071
+
3072
+ ## 1. Presentations
3073
+
3074
+ Create AI-powered presentations from text, files, URLs, or piped content.
3075
+
3076
+ \`\`\`bash
3077
+ # From topic
3078
+ ${cmd2} create "AI-powered analytics platform"
3079
+
3080
+ # From file (PDF, PPTX, DOCX, Markdown)
3081
+ ${cmd2} create "Quarterly Report" --file report.pdf
3082
+
3083
+ # From URL
3084
+ ${cmd2} create "Product Overview" --sources https://company.com/product
3085
+
3086
+ # From piped content
3087
+ cat notes.md | ${cmd2} create "Meeting Summary"
3088
+
3089
+ # With options
3090
+ ${cmd2} create "Pitch Deck" \\
3091
+ --slides 10 \\
3092
+ --mode balanced \\
3093
+ --tone professional \\
3094
+ --audience "Investors" \\
3095
+ --brand my-company \\
3096
+ --open
3097
+ \`\`\`
3098
+
3099
+ **Key Options:**
3100
+ - \`--slides <1-20>\` - Number of slides (default: 10)
3101
+ - \`--mode <instant|ultrafast|fast|balanced|best>\` - Quality/speed tradeoff
3102
+ - \`--tone <creative|professional|educational|formal|casual>\`
3103
+ - \`--file <paths...>\` - Extract content from files
3104
+ - \`--sources <urls...>\` - Scrape URLs for context
3105
+ - \`--brand <id|url>\` - Apply branding
3106
+ - \`--open\` - Open in browser when done
3107
+
3108
+ **Manage presentations:**
3109
+ \`\`\`bash
3110
+ ${cmd2} list # List all presentations
3111
+ ${cmd2} get <slug> # Get details
3112
+ ${cmd2} export <slug> -o p.zip # Export to ZIP
3113
+ ${cmd2} delete <slug> # Delete
3114
+ \`\`\`
3115
+
3116
+ ---
3117
+
3118
+ ## 2. Video Asset Generation
3119
+
3120
+ Generate voiceovers, music, and find stock media for video production. Works with Remotion or any video framework.
3121
+
3122
+ ### Generate All Assets at Once
3123
+
3124
+ \`\`\`bash
3125
+ cat <<'EOF' | ${cmd2} video create --output ./public
3126
+ {
3127
+ "scenes": [
3128
+ {
3129
+ "name": "Hook",
3130
+ "script": "Watch how we transformed complex workflows into a single click.",
3131
+ "imageQuery": "modern dashboard dark theme",
3132
+ "videoQuery": "abstract tech particles"
3133
+ },
3134
+ {
3135
+ "name": "Demo",
3136
+ "script": "Our AI analyzes data in real-time, surfacing insights that matter.",
3137
+ "imageQuery": "data visualization charts"
3138
+ },
3139
+ {
3140
+ "name": "CTA",
3141
+ "script": "Start your free trial today.",
3142
+ "imageQuery": "call to action button"
3143
+ }
3144
+ ],
3145
+ "voice": "Kore",
3146
+ "voiceSettings": {
3147
+ "speed": 0.95,
3148
+ "stability": 0.4,
3149
+ "style": 0.6
3150
+ },
3151
+ "musicPrompt": "upbeat corporate, positive energy, modern synth"
3152
+ }
3153
+ EOF
3154
+ \`\`\`
3155
+
3156
+ **Output:** Per-scene voiceovers, background music, stock images/videos, and \`video-manifest.json\` with timing data.
3157
+
3158
+ ### Initialize Remotion Project
3159
+
3160
+ \`\`\`bash
3161
+ ${cmd2} video init my-video # 16:9 landscape
3162
+ ${cmd2} video init my-video --type tiktok # 9:16 vertical
3163
+ \`\`\`
3164
+
3165
+ ### Embed Thumbnail
3166
+
3167
+ \`\`\`bash
3168
+ ${cmd2} video thumbnail video.mp4 --frame 60
3169
+ \`\`\`
3170
+
3171
+ ---
3172
+
3173
+ ## 3. Text-to-Speech (TTS)
3174
+
3175
+ Convert text to natural speech with multiple providers and voices.
3176
+
3177
+ \`\`\`bash
3178
+ # Basic usage
3179
+ ${cmd2} tts generate -t "Hello world" -o output.mp3
3180
+
3181
+ # With voice selection
3182
+ ${cmd2} tts generate -t "Welcome to the demo" -v Rachel -o welcome.mp3
3183
+
3184
+ # With provider and settings
3185
+ ${cmd2} tts generate \\
3186
+ -t "Professional narration" \\
3187
+ -v Kore \\
3188
+ -p gemini \\
3189
+ -s 0.9 \\
3190
+ -o narration.mp3
3191
+
3192
+ # List available voices
3193
+ ${cmd2} tts voices
3194
+ ${cmd2} tts voices --provider elevenlabs
3195
+ \`\`\`
3196
+
3197
+ **Providers:** \`gemini\`, \`elevenlabs\`, \`openai\`
3198
+ **Popular voices:** \`Kore\`, \`Puck\`, \`Rachel\`, \`alloy\`
3199
+ **Speed range:** 0.25 - 4.0 (default: 1.0)
3200
+
3201
+ ---
3202
+
3203
+ ## 4. Music Generation
3204
+
3205
+ Generate AI music from text descriptions.
3206
+
3207
+ \`\`\`bash
3208
+ # Generate music
3209
+ ${cmd2} music generate -p "upbeat corporate, modern synth" --duration 30
3210
+
3211
+ # Save to file
3212
+ ${cmd2} music generate -p "calm ambient background" -o music.mp3
3213
+
3214
+ # Check generation status (for async operations)
3215
+ ${cmd2} music status <request-id>
3216
+ \`\`\`
3217
+
3218
+ **Duration:** 3-30 seconds
3219
+ **Providers:** \`elevenlabs\`, \`suno\`
3220
+
3221
+ ---
3222
+
3223
+ ## 5. Image Search
3224
+
3225
+ Search for stock images from multiple sources.
3226
+
3227
+ \`\`\`bash
3228
+ # Basic search
3229
+ ${cmd2} image search -q "mountain landscape"
3230
+
3231
+ # With options
3232
+ ${cmd2} image search -q "business team meeting" \\
3233
+ --max-results 20 \\
3234
+ --size large \\
3235
+ --format json
3236
+
3237
+ # Download for video project
3238
+ ${cmd2} image search -q "tech abstract" -n 5 --format json > images.json
3239
+ \`\`\`
3240
+
3241
+ **Options:**
3242
+ - \`--max-results <n>\` - Number of results (default: 10)
3243
+ - \`--size <small|medium|large|any>\` - Image size
3244
+ - \`--safe-search / --no-safe-search\` - Filter adult content
3245
+
3246
+ ---
3247
+
3248
+ ## 6. Video Search
3249
+
3250
+ Search for stock video clips.
3251
+
3252
+ \`\`\`bash
3253
+ # Basic search
3254
+ ${cmd2} video search "ocean waves"
3255
+
3256
+ # With filters
3257
+ ${cmd2} video search "city timelapse" \\
3258
+ --max-results 5 \\
3259
+ --orientation landscape \\
3260
+ --license free
3261
+ \`\`\`
3262
+
3263
+ **Options:**
3264
+ - \`--orientation <landscape|portrait|square|any>\`
3265
+ - \`--license <free|premium|any>\`
3266
+
3267
+ ---
3268
+
3269
+ ## 7. Audio Mixing
3270
+
3271
+ Mix video with voiceover and background music.
3272
+
3273
+ \`\`\`bash
3274
+ # Mix audio tracks
3275
+ ${cmd2} mix create \\
3276
+ --video input.mp4 \\
3277
+ --voice voiceover.mp3 \\
3278
+ --music background.mp3 \\
3279
+ --music-volume 30 \\
3280
+ --voice-volume 100 \\
3281
+ -o final.mp4
3282
+
3283
+ # Check mixing status
3284
+ ${cmd2} mix status <request-id>
3285
+ \`\`\`
3286
+
3287
+ Music automatically loops to match video duration.
3288
+
3289
+ ---
3290
+
3291
+ ## 8. Branding
3292
+
3293
+ Manage brand profiles for consistent styling.
3294
+
3295
+ \`\`\`bash
3296
+ # List saved brands
3297
+ ${cmd2} branding list
3298
+
3299
+ # Extract branding from website
3300
+ ${cmd2} branding extract https://company.com
3301
+
3302
+ # Get brand details
3303
+ ${cmd2} branding get <brand-id>
3304
+
3305
+ # Set default brand
3306
+ ${cmd2} branding set-default <brand-id>
3307
+
3308
+ # Use in presentations
3309
+ ${cmd2} create "Topic" --brand my-company
3310
+ \`\`\`
3311
+
3312
+ ---
3313
+
3314
+ ## 9. Configuration
3315
+
3316
+ \`\`\`bash
3317
+ # Interactive setup
3318
+ ${cmd2} config init
3319
+
3320
+ # Show current config
3321
+ ${cmd2} config show
3322
+ ${cmd2} config show --verify # Verify API key
3323
+
3324
+ # Set values
3325
+ ${cmd2} config set api-key <key>
3326
+ ${cmd2} config set team-id <id>
3327
+
3328
+ # Clear config
3329
+ ${cmd2} config clear
3330
+
3331
+ # Show config file location
3332
+ ${cmd2} config path
3333
+ \`\`\`
3334
+
3335
+ ---
3336
+
3337
+ ## Output Formats
3338
+
3339
+ All commands support multiple output formats:
3340
+
3341
+ \`\`\`bash
3342
+ ${cmd2} <command> --format human # Default, colored terminal output
3343
+ ${cmd2} <command> --format json # Machine-readable JSON
3344
+ ${cmd2} <command> --format quiet # Minimal output, errors only
3345
+ \`\`\`
3346
+
3347
+ ---
3348
+
3349
+ ## Environment Variables
3350
+
3351
+ \`\`\`bash
3352
+ ${envPrefix}_API_KEY # API key for authentication
3353
+ ${envPrefix}_API_URL # Custom API URL (optional)
3354
+ \`\`\`
3355
+
3356
+ ---
3357
+
3358
+ ## Specialized Skills
3359
+
3360
+ For detailed workflows, load these skills:
3361
+
3362
+ - **\`${name}-video\`** - Detailed video creation workflow, Remotion integration, composition rules, R3F/Three.js patterns
3363
+ - **\`${name}-presentation\`** - Detailed presentation creation, styling options, export formats
3364
+
3365
+ ---
3366
+
3367
+ ## Common Workflows
3368
+
3369
+ ### Video Production Pipeline
3370
+
3371
+ \`\`\`bash
3372
+ # 1. Initialize project
3373
+ ${cmd2} video init product-demo
3374
+
3375
+ # 2. Generate assets
3376
+ cat scenes.json | ${cmd2} video create -o product-demo/public
3377
+
3378
+ # 3. Implement in Remotion (see ${name}-video skill)
3379
+
3380
+ # 4. Render and add thumbnail
3381
+ cd product-demo
3382
+ pnpm exec remotion render FullVideo
3383
+ ${cmd2} video thumbnail out/FullVideo.mp4 --frame 60
3384
+ \`\`\`
3385
+
3386
+ ### Presentation from Research
3387
+
3388
+ \`\`\`bash
3389
+ # Gather content from multiple sources
3390
+ ${cmd2} create "Market Analysis" \\
3391
+ --file research.pdf \\
3392
+ --sources https://industry-report.com \\
3393
+ --context "Focus on Q4 trends" \\
3394
+ --slides 15 \\
3395
+ --tone professional \\
3396
+ --brand company \\
3397
+ --open
3398
+ \`\`\`
3399
+
3400
+ ### Batch Image Collection
3401
+
3402
+ \`\`\`bash
3403
+ # Get images for video scenes
3404
+ for query in "hero shot" "team photo" "product showcase"; do
3405
+ ${cmd2} image search -q "$query" -n 3 --format json
3406
+ done
3407
+ \`\`\`
3408
+
3409
+ ---
3410
+
3411
+ ## Troubleshooting
3412
+
3413
+ **Authentication issues:**
3414
+ \`\`\`bash
3415
+ ${cmd2} whoami # Check current user
3416
+ ${cmd2} logout && ${cmd2} login # Re-authenticate
3417
+ \`\`\`
3418
+
3419
+ **Check API status:**
3420
+ \`\`\`bash
3421
+ ${cmd2} config show --verify
3422
+ \`\`\`
3423
+
3424
+ **Debug mode:**
3425
+ \`\`\`bash
3426
+ ${cmd2} <command> --debug
3427
+ \`\`\`
3428
+
3429
+ ---
3430
+
3431
+ ## Help
3432
+
3433
+ \`\`\`bash
3434
+ ${cmd2} --help # General help
3435
+ ${cmd2} <command> --help # Command-specific help
3436
+ ${cmd2} --version # Version info
3437
+ \`\`\`
3438
+ `;
3439
+ }
3440
+
3147
3441
  // src/commands/skill/rules/video/content.ts
3148
3442
  var VIDEO_RULE_CONTENTS = [
3149
3443
  {
@@ -4405,6 +4699,7 @@ function getSupportedEditorNames() {
4405
4699
  }
4406
4700
 
4407
4701
  // src/commands/skill/index.ts
4702
+ var SKILL_TYPES = ["main", "video", "presentation"];
4408
4703
  var skillContext = {
4409
4704
  name: brand.name,
4410
4705
  cmd: brand.commands[0],
@@ -4413,25 +4708,39 @@ var skillContext = {
4413
4708
  var skillCommand = new Command14("skill").description(`Manage ${brand.displayName} skills for AI coding assistants`).addHelpText(
4414
4709
  "after",
4415
4710
  `
4711
+ ${chalk12.bold("Skill Types:")}
4712
+ ${chalk12.cyan("main")} Main CLI skill with all capabilities (TTS, music, images, videos, presentations)
4713
+ ${chalk12.cyan("video")} Detailed video creation workflow with Remotion/R3F patterns
4714
+ ${chalk12.cyan("presentation")} Detailed presentation creation workflow
4715
+
4416
4716
  ${chalk12.bold("Examples:")}
4717
+ ${chalk12.gray("# Install main CLI skill (comprehensive overview)")}
4718
+ $ ${brand.commands[0]} skill install main
4719
+
4417
4720
  ${chalk12.gray("# Install video skill")}
4418
4721
  $ ${brand.commands[0]} skill install video
4419
4722
 
4420
4723
  ${chalk12.gray("# Install presentation skill")}
4421
4724
  $ ${brand.commands[0]} skill install presentation
4422
4725
 
4423
- ${chalk12.gray("# Install both skills")}
4726
+ ${chalk12.gray("# Install all skills")}
4424
4727
  $ ${brand.commands[0]} skill install
4425
4728
 
4426
4729
  ${chalk12.gray("# Install to specific directory")}
4427
- $ ${brand.commands[0]} skill install video --dir ~/.claude
4730
+ $ ${brand.commands[0]} skill install main --dir ~/.claude
4428
4731
 
4429
4732
  ${chalk12.gray("# Show skill content")}
4430
- $ ${brand.commands[0]} skill show video
4733
+ $ ${brand.commands[0]} skill show main
4431
4734
  `
4432
4735
  );
4433
- skillCommand.command("install").description(`Install ${brand.displayName} skills for AI coding assistants`).argument("[type]", "Skill type: video, presentation, or omit for both").option("-d, --dir <path>", "Install to specific directory").option("-g, --global", "Install globally (to home directory)", true).option("-l, --local", "Install locally (to current directory)").option("-f, --force", "Overwrite existing skill files").action(async (type, options) => {
4736
+ skillCommand.command("install").description(`Install ${brand.displayName} skills for AI coding assistants`).argument("[type]", "Skill type: main, video, presentation, or omit for all").option("-d, --dir <path>", "Install to specific directory").option("-g, --global", "Install globally (to home directory)", true).option("-l, --local", "Install locally (to current directory)").option("-f, --force", "Overwrite existing skill files").action(async (type, options) => {
4434
4737
  const skillsToInstall = [];
4738
+ if (!type || type === "main") {
4739
+ skillsToInstall.push({
4740
+ name: brand.name,
4741
+ content: generateMainSkillContent(skillContext)
4742
+ });
4743
+ }
4435
4744
  if (!type || type === "video") {
4436
4745
  skillsToInstall.push({
4437
4746
  name: `${brand.name}-video`,
@@ -4444,8 +4753,8 @@ skillCommand.command("install").description(`Install ${brand.displayName} skills
4444
4753
  content: generatePresentationSkillContent(skillContext)
4445
4754
  });
4446
4755
  }
4447
- if (type && type !== "video" && type !== "presentation") {
4448
- error(`Invalid skill type: ${type}. Must be "video" or "presentation"`);
4756
+ if (type && !SKILL_TYPES.includes(type)) {
4757
+ error(`Invalid skill type: ${type}. Must be one of: ${SKILL_TYPES.join(", ")}`);
4449
4758
  process.exit(1);
4450
4759
  }
4451
4760
  console.log();
@@ -4477,26 +4786,31 @@ skillCommand.command("install").description(`Install ${brand.displayName} skills
4477
4786
  console.log();
4478
4787
  }
4479
4788
  });
4480
- skillCommand.command("show").description("Display skill content").argument("[type]", "Skill type: video or presentation (default: video)").action((type = "video") => {
4481
- if (type === "video") {
4789
+ skillCommand.command("show").description("Display skill content").argument("[type]", "Skill type: main, video, or presentation (default: main)").action((type = "main") => {
4790
+ if (type === "main") {
4791
+ console.log(generateMainSkillContent(skillContext));
4792
+ } else if (type === "video") {
4482
4793
  console.log(generateVideoSkillContent(skillContext));
4483
4794
  } else if (type === "presentation") {
4484
4795
  console.log(generatePresentationSkillContent(skillContext));
4485
4796
  } else {
4486
- error(`Invalid skill type: ${type}. Must be "video" or "presentation"`);
4797
+ error(`Invalid skill type: ${type}. Must be one of: ${SKILL_TYPES.join(", ")}`);
4487
4798
  process.exit(1);
4488
4799
  }
4489
4800
  });
4490
- skillCommand.command("uninstall").description(`Remove ${brand.displayName} skills from AI coding assistants`).argument("[type]", "Skill type: video, presentation, or omit for both").option("-g, --global", "Uninstall globally (from home directory)", true).option("-l, --local", "Uninstall locally (from current directory)").action(async (type, options) => {
4801
+ skillCommand.command("uninstall").description(`Remove ${brand.displayName} skills from AI coding assistants`).argument("[type]", "Skill type: main, video, presentation, or omit for all").option("-g, --global", "Uninstall globally (from home directory)", true).option("-l, --local", "Uninstall locally (from current directory)").action(async (type, options) => {
4491
4802
  const skillsToRemove = [];
4803
+ if (!type || type === "main") {
4804
+ skillsToRemove.push(brand.name);
4805
+ }
4492
4806
  if (!type || type === "video") {
4493
4807
  skillsToRemove.push(`${brand.name}-video`);
4494
4808
  }
4495
4809
  if (!type || type === "presentation") {
4496
4810
  skillsToRemove.push(`${brand.name}-presentation`);
4497
4811
  }
4498
- if (type && type !== "video" && type !== "presentation") {
4499
- error(`Invalid skill type: ${type}. Must be "video" or "presentation"`);
4812
+ if (type && !SKILL_TYPES.includes(type)) {
4813
+ error(`Invalid skill type: ${type}. Must be one of: ${SKILL_TYPES.join(", ")}`);
4500
4814
  process.exit(1);
4501
4815
  }
4502
4816
  console.log();
@@ -4518,9 +4832,6 @@ skillCommand.command("uninstall").description(`Remove ${brand.displayName} skill
4518
4832
  });
4519
4833
 
4520
4834
  // src/commands/tts.ts
4521
- init_api();
4522
- init_output();
4523
- init_types();
4524
4835
  import { Command as Command15 } from "commander";
4525
4836
  import ora8 from "ora";
4526
4837
  import { writeFile as writeFile2 } from "fs/promises";
@@ -4609,9 +4920,6 @@ var voicesCommand = new Command15("voices").description("List available voices")
4609
4920
  var ttsCommand = new Command15("tts").description("Text-to-speech commands").addCommand(generateCommand).addCommand(voicesCommand);
4610
4921
 
4611
4922
  // src/commands/music.ts
4612
- init_api();
4613
- init_output();
4614
- init_types();
4615
4923
  import { Command as Command16 } from "commander";
4616
4924
  import ora9 from "ora";
4617
4925
  import { writeFile as writeFile3 } from "fs/promises";
@@ -4731,9 +5039,6 @@ var statusCommand = new Command16("status").description("Check status of a music
4731
5039
  var musicCommand = new Command16("music").description("Music generation commands").addCommand(generateCommand2).addCommand(statusCommand);
4732
5040
 
4733
5041
  // src/commands/mix.ts
4734
- init_api();
4735
- init_output();
4736
- init_types();
4737
5042
  import { Command as Command17 } from "commander";
4738
5043
  import ora10 from "ora";
4739
5044
  import { writeFile as writeFile4 } from "fs/promises";
@@ -4857,9 +5162,6 @@ var statusCommand2 = new Command17("status").description("Check status of an aud
4857
5162
  var mixAudioCommand = new Command17("mix").description("Audio mixing commands").addCommand(mixCommand).addCommand(statusCommand2);
4858
5163
 
4859
5164
  // src/commands/image.ts
4860
- init_api();
4861
- init_output();
4862
- init_types();
4863
5165
  import { Command as Command18 } from "commander";
4864
5166
  import ora11 from "ora";
4865
5167
  var searchCommand = new Command18("search").description("Search for images").requiredOption("-q, --query <query>", "Search query").option("-n, --max-results <number>", "Maximum number of results (default: 10)").option("-s, --size <size>", "Image size: small, medium, large, any", "large").option("--safe-search", "Enable safe search (default: true)", true).option("--no-safe-search", "Disable safe search").option("-f, --format <format>", "Output format: human, json, quiet", "human").action(async (options) => {
@@ -4937,9 +5239,6 @@ var searchCommand = new Command18("search").description("Search for images").req
4937
5239
  var imageCommand = new Command18("image").description("Image search commands").addCommand(searchCommand);
4938
5240
 
4939
5241
  // src/commands/video.ts
4940
- init_api();
4941
- init_output();
4942
- init_types();
4943
5242
  import { Command as Command19 } from "commander";
4944
5243
  import ora12 from "ora";
4945
5244
  import { mkdir, writeFile as writeFile5, readFile as readFile2, access, rm, cp } from "fs/promises";
@@ -5686,7 +5985,7 @@ var thumbnailCommand = new Command19("thumbnail").description("Embed a thumbnail
5686
5985
  var videoCommand = new Command19("video").description("Video asset generation commands").addCommand(initCommand).addCommand(createCommand2).addCommand(searchCommand2).addCommand(thumbnailCommand);
5687
5986
 
5688
5987
  // src/index.ts
5689
- var VERSION = "0.1.8";
5988
+ var VERSION = "0.1.10";
5690
5989
  var program = new Command20();
5691
5990
  var cmdName = brand.commands[0];
5692
5991
  program.name(cmdName).description(brand.description).version(VERSION, "-v, --version", "Show version number").option("--debug", "Enable debug logging").option("--no-color", "Disable colored output").configureOutput({