agent-media-cli 1.7.1 → 1.7.3

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/README.md CHANGED
@@ -49,6 +49,15 @@ agent-media ugc -g "A fitness tracker that monitors sleep quality" --actor naomi
49
49
 
50
50
  # PIP mode (talking head + rotating B-roll overlays)
51
51
  agent-media ugc "your script..." --actor adaeze --pip --duration 15 --sync
52
+
53
+ # Product Acting UGC from a product image URL
54
+ agent-media product-acting \
55
+ --product-image https://cdn.example.com/product.png \
56
+ --actor sofia \
57
+ --about "A premium perfume with a warm vanilla dry-down" \
58
+ --template product-in-hand \
59
+ --acting-style honest-review \
60
+ --sync
52
61
  ```
53
62
 
54
63
  ## UGC Flags
@@ -78,6 +87,7 @@ hormozi, minimal, bold, karaoke, clean, tiktok, neon, fire, glow, pop, aesthetic
78
87
 
79
88
  ```bash
80
89
  agent-media ugc "script..." # Generate UGC video
90
+ agent-media product-acting --product-image https://... --actor sofia --about "..." --sync
81
91
  agent-media actor list # Browse 200+ AI actors
82
92
  agent-media subtitle ./video.mp4 # Add subtitles
83
93
  agent-media status <job-id> # Check job status
@@ -88,8 +98,25 @@ agent-media subscribe # Subscribe or buy credits
88
98
  agent-media apikey list # Manage API keys
89
99
  agent-media whoami # Current user info
90
100
  agent-media doctor # Run diagnostics
101
+ agent-media update # Update CLI + Claude Code skill docs
102
+ ```
103
+
104
+ ## Updates
105
+
106
+ ```bash
107
+ # Update the global CLI package and refresh Claude Code skill docs
108
+ agent-media update
109
+
110
+ # Preview what would update without changing anything
111
+ agent-media update --check
112
+
113
+ # Update only one side when needed
114
+ agent-media update --cli-only
115
+ agent-media update --skills-only
91
116
  ```
92
117
 
118
+ Skill docs are refreshed from `gitroomhq/agent-media`, the same repo used by `npx add-skill gitroomhq/agent-media`.
119
+
93
120
  ## Pricing
94
121
 
95
122
  | Plan | Price | Credits/month | ~10s Videos |
@@ -113,7 +140,7 @@ agent-media doctor # Run diagnostics
113
140
  - [Interactive API Docs](https://agent-media.ai/docs/api-reference)
114
141
  - [OpenAPI Spec](https://agent-media.ai/openapi.json)
115
142
  - [Website](https://agent-media.ai)
116
- - [GitHub](https://github.com/gitroomhq/agent-media)
143
+ - [GitHub](https://github.com/yuvalsuede/agent-media)
117
144
 
118
145
  ## License
119
146
 
@@ -0,0 +1,9 @@
1
+ /**
2
+ * `agent-media product-acting` command.
3
+ *
4
+ * Generates a Product Acting UGC video: an AI creator presents or reacts to a
5
+ * product image in a selected real-world scenario.
6
+ */
7
+ import type { Command } from 'commander';
8
+ export declare function registerProductActingCommand(program: Command): void;
9
+ //# sourceMappingURL=product-acting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"product-acting.d.ts","sourceRoot":"","sources":["../../src/commands/product-acting.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgIzC,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoMnE"}
@@ -0,0 +1,276 @@
1
+ // Copyright 2026 agent-media contributors. Apache-2.0 license.
2
+ import chalk from 'chalk';
3
+ import { detectOutputMode, printJson, printQuiet, createSpinner, } from '../lib/output.js';
4
+ import { getApiKey, resolveProfileName } from '../lib/credentials.js';
5
+ import { AgentMediaAPI, } from '../lib/api.js';
6
+ import { CLIError, handleError } from '../lib/errors.js';
7
+ const POLL_INTERVAL_MS = 5_000;
8
+ const TERMINAL_STATUSES = new Set(['completed', 'failed', 'canceled']);
9
+ const VALID_DURATIONS = new Set([5, 10, 15]);
10
+ const VALID_SUBTITLE_STYLES = new Set(['hormozi', 'none']);
11
+ const VALID_TEMPLATES = new Set([
12
+ 'product-in-hand',
13
+ 'mirror-selfie',
14
+ 'bathroom-reaction',
15
+ 'kitchen-counter',
16
+ 'car-selfie',
17
+ 'couch-review',
18
+ 'expert-interview',
19
+ 'product-closeup',
20
+ ]);
21
+ const VALID_ACTING_STYLES = new Set([
22
+ 'raw-selfie',
23
+ 'shocked',
24
+ 'angry',
25
+ 'excited',
26
+ 'dramatic',
27
+ 'weird-hook',
28
+ 'casual-demo',
29
+ 'honest-review',
30
+ ]);
31
+ const WORDS_PER_SECOND = 3;
32
+ const STATUS_COLORS = {
33
+ pending: chalk.yellow,
34
+ submitted: chalk.blue,
35
+ processing: chalk.blue,
36
+ completed: chalk.green,
37
+ failed: chalk.red,
38
+ canceled: chalk.dim,
39
+ };
40
+ function formatStatus(status) {
41
+ const colorize = STATUS_COLORS[status] ?? chalk.white;
42
+ return colorize(status.toUpperCase());
43
+ }
44
+ function formatElapsed(seconds) {
45
+ if (seconds < 60)
46
+ return `${seconds}s`;
47
+ const mins = Math.floor(seconds / 60);
48
+ const secs = seconds % 60;
49
+ return `${mins}m ${secs}s`;
50
+ }
51
+ async function waitForJob(api, jobId, mode) {
52
+ const startTime = Date.now();
53
+ let interrupted = false;
54
+ const onSigint = () => {
55
+ interrupted = true;
56
+ };
57
+ process.on('SIGINT', onSigint);
58
+ const spinner = createSpinner('Building Product Acting UGC video...');
59
+ if (mode === 'human')
60
+ spinner.start();
61
+ try {
62
+ while (!interrupted) {
63
+ const poll = await api.pollProvider(jobId);
64
+ const elapsed = Math.floor((Date.now() - startTime) / 1000);
65
+ const status = poll.status;
66
+ if (mode === 'human') {
67
+ spinner.text = `${formatStatus(status)} elapsed ${formatElapsed(elapsed)} (Ctrl+C to stop)`;
68
+ }
69
+ if (TERMINAL_STATUSES.has(status)) {
70
+ const job = await api.getJob(jobId);
71
+ if (mode === 'human') {
72
+ if (status === 'completed') {
73
+ spinner.succeed(`Product Acting UGC video produced in ${formatElapsed(elapsed)}`);
74
+ }
75
+ else if (status === 'failed') {
76
+ spinner.fail(`Job failed after ${formatElapsed(elapsed)}` + (job.error_message ? `: ${job.error_message}` : ''));
77
+ }
78
+ else {
79
+ spinner.warn(`Job canceled after ${formatElapsed(elapsed)}`);
80
+ }
81
+ }
82
+ return job;
83
+ }
84
+ await new Promise((resolve) => {
85
+ const timer = setTimeout(resolve, POLL_INTERVAL_MS);
86
+ const earlyExit = () => {
87
+ clearTimeout(timer);
88
+ process.removeListener('SIGINT', earlyExit);
89
+ resolve();
90
+ };
91
+ process.once('SIGINT', earlyExit);
92
+ });
93
+ }
94
+ if (mode === 'human') {
95
+ spinner.stop();
96
+ console.log();
97
+ console.log(chalk.dim(' Stopped waiting.'));
98
+ }
99
+ return null;
100
+ }
101
+ finally {
102
+ process.removeListener('SIGINT', onSigint);
103
+ }
104
+ }
105
+ export function registerProductActingCommand(program) {
106
+ program
107
+ .command('product-acting')
108
+ .description('Generate Product Acting UGC — AI creator presents a product image\n\n' +
109
+ 'Examples:\n' +
110
+ ' $ agent-media product-acting \\\n' +
111
+ ' --product-image https://cdn.example.com/perfume.png \\\n' +
112
+ ' --actor sarah \\\n' +
113
+ ' --script "I did not expect this perfume to smell this expensive" \\\n' +
114
+ ' --sync\n\n' +
115
+ ' $ agent-media product-acting \\\n' +
116
+ ' --product-image https://cdn.example.com/bottle.webp \\\n' +
117
+ ' --actor marcus --product-name "Hydra Boost" \\\n' +
118
+ ' --about "Daily electrolyte drink for gym recovery" \\\n' +
119
+ ' --template kitchen-counter --acting-style excited --duration 10 --sync\n\n' +
120
+ 'The product image must be a publicly accessible image URL. If --script is omitted,\n' +
121
+ '--about is required and the API generates a short script.')
122
+ .requiredOption('--product-image <url>', 'Public URL of the product image')
123
+ .requiredOption('--actor <slug>', 'Actor slug from `agent-media actor list`')
124
+ .option('--actor-variant-id <uuid>', 'Optional actor variant UUID')
125
+ .option('--product-name <name>', 'Product name for script/frame context')
126
+ .option('--about <text>', 'Product description/context. Required if --script is omitted')
127
+ .option('--script <text>', 'Exact script the actor should say')
128
+ .option('--template <name>', 'Scenario: product-in-hand, mirror-selfie, bathroom-reaction, kitchen-counter, car-selfie, couch-review, expert-interview, product-closeup', 'product-in-hand')
129
+ .option('--acting-style <name>', 'Acting style: raw-selfie, shocked, angry, excited, dramatic, weird-hook, casual-demo, honest-review', 'raw-selfie')
130
+ .option('--visual-style <text>', 'Extra visual/camera direction')
131
+ .option('--duration <seconds>', 'Video duration: 5, 10, or 15', '5')
132
+ .option('--subtitle-style <style>', 'Subtitle style: hormozi or none', 'hormozi')
133
+ .option('--webhook-url <url>', 'Webhook to call on completion')
134
+ .option('-s, --sync', 'Wait for completion and print the output URL')
135
+ .action(async (cmdOpts) => {
136
+ const globalOpts = program.opts();
137
+ const mode = detectOutputMode(globalOpts);
138
+ const profileName = resolveProfileName(globalOpts.profile);
139
+ const apiKey = getApiKey(profileName);
140
+ if (!apiKey) {
141
+ throw new CLIError('Not logged in.', {
142
+ code: 'NOT_AUTHENTICATED',
143
+ suggestion: "Run 'agent-media login' to authenticate.",
144
+ });
145
+ }
146
+ const duration = Number(cmdOpts.duration);
147
+ if (!VALID_DURATIONS.has(duration)) {
148
+ throw new CLIError(`Invalid --duration: ${cmdOpts.duration}`, {
149
+ code: 'VALIDATION_ERROR',
150
+ suggestion: 'Use 5, 10, or 15.',
151
+ });
152
+ }
153
+ if (!VALID_SUBTITLE_STYLES.has(cmdOpts.subtitleStyle)) {
154
+ throw new CLIError(`Invalid --subtitle-style: ${cmdOpts.subtitleStyle}`, {
155
+ code: 'VALIDATION_ERROR',
156
+ suggestion: 'Use hormozi or none.',
157
+ });
158
+ }
159
+ if (!VALID_TEMPLATES.has(cmdOpts.template)) {
160
+ throw new CLIError(`Invalid --template: ${cmdOpts.template}`, {
161
+ code: 'VALIDATION_ERROR',
162
+ suggestion: `Use one of: ${Array.from(VALID_TEMPLATES).join(', ')}.`,
163
+ });
164
+ }
165
+ if (!VALID_ACTING_STYLES.has(cmdOpts.actingStyle)) {
166
+ throw new CLIError(`Invalid --acting-style: ${cmdOpts.actingStyle}`, {
167
+ code: 'VALIDATION_ERROR',
168
+ suggestion: `Use one of: ${Array.from(VALID_ACTING_STYLES).join(', ')}.`,
169
+ });
170
+ }
171
+ if (!cmdOpts.script && !cmdOpts.about) {
172
+ throw new CLIError('Either --script or --about is required.', {
173
+ code: 'VALIDATION_ERROR',
174
+ suggestion: 'Pass exact words with --script or product context with --about.',
175
+ });
176
+ }
177
+ if (cmdOpts.script) {
178
+ const wordCount = cmdOpts.script.trim().split(/\s+/).filter(Boolean).length;
179
+ const maxWords = duration * WORDS_PER_SECOND;
180
+ if (wordCount > maxWords) {
181
+ throw new CLIError(`Script too long: ${wordCount} words. Max ${maxWords} for ${duration}s.`, {
182
+ code: 'VALIDATION_ERROR',
183
+ suggestion: `Shorten the script to ≤${maxWords} words or increase --duration.`,
184
+ });
185
+ }
186
+ }
187
+ try {
188
+ const api = new AgentMediaAPI(apiKey);
189
+ const submitSpinner = createSpinner('Submitting Product Acting UGC job...');
190
+ if (mode === 'human')
191
+ submitSpinner.start();
192
+ const result = await api.productActingGenerate({
193
+ product_image_url: cmdOpts.productImage,
194
+ actor_slug: cmdOpts.actor,
195
+ actor_variant_id: cmdOpts.actorVariantId,
196
+ product_name: cmdOpts.productName,
197
+ product_description: cmdOpts.about,
198
+ script: cmdOpts.script,
199
+ template: cmdOpts.template,
200
+ acting_style: cmdOpts.actingStyle,
201
+ visual_style: cmdOpts.visualStyle,
202
+ duration,
203
+ subtitles: cmdOpts.subtitleStyle !== 'none',
204
+ subtitle_style: cmdOpts.subtitleStyle,
205
+ webhook_url: cmdOpts.webhookUrl,
206
+ });
207
+ if (mode === 'human')
208
+ submitSpinner.succeed('Product Acting UGC job submitted');
209
+ if (!cmdOpts.sync) {
210
+ switch (mode) {
211
+ case 'json':
212
+ printJson(result);
213
+ break;
214
+ case 'quiet':
215
+ printQuiet(result.job_id);
216
+ break;
217
+ default:
218
+ console.log();
219
+ console.log(` ${chalk.bold('Job ID:')} ${chalk.cyan(result.job_id)}`);
220
+ console.log(` ${chalk.bold('Actor:')} ${result.actor_slug}`);
221
+ console.log(` ${chalk.bold('Subtitles:')} ${result.subtitle_style}`);
222
+ console.log(` ${chalk.bold('Credits:')} ${result.credits_deducted} deducted`);
223
+ console.log();
224
+ console.log(chalk.dim(` Run 'agent-media status ${result.job_id}' to check progress`));
225
+ console.log(chalk.dim(` Or re-run with --sync to wait for completion`));
226
+ console.log();
227
+ }
228
+ return;
229
+ }
230
+ if (mode === 'human') {
231
+ console.log();
232
+ console.log(` ${chalk.bold('Job ID:')} ${chalk.cyan(result.job_id)}`);
233
+ console.log(` ${chalk.bold('Actor:')} ${result.actor_slug}`);
234
+ console.log(` ${chalk.bold('Credits:')} ${result.credits_deducted} deducted`);
235
+ console.log();
236
+ }
237
+ const finishedJob = await waitForJob(api, result.job_id, mode);
238
+ if (!finishedJob)
239
+ return;
240
+ if (mode === 'json') {
241
+ const payload = {
242
+ job_id: finishedJob.id,
243
+ status: finishedJob.status,
244
+ actor_slug: result.actor_slug,
245
+ credits_deducted: result.credits_deducted,
246
+ };
247
+ if (finishedJob.status === 'failed') {
248
+ payload['error'] = finishedJob.error_message ?? 'Unknown error';
249
+ }
250
+ if (finishedJob.output_media_url) {
251
+ payload['output_url'] = finishedJob.output_media_url;
252
+ }
253
+ printJson(payload);
254
+ return;
255
+ }
256
+ if (mode === 'quiet') {
257
+ printQuiet(finishedJob.output_media_url ?? finishedJob.id);
258
+ return;
259
+ }
260
+ if (finishedJob.status === 'completed' && finishedJob.output_media_url) {
261
+ console.log();
262
+ console.log(` ${chalk.bold('URL:')} ${chalk.cyan(finishedJob.output_media_url)}`);
263
+ console.log();
264
+ }
265
+ else if (finishedJob.status !== 'completed') {
266
+ console.log();
267
+ console.log(chalk.yellow(' No output — Product Acting UGC job did not complete successfully.'));
268
+ console.log();
269
+ }
270
+ }
271
+ catch (error) {
272
+ handleError(error);
273
+ }
274
+ });
275
+ }
276
+ //# sourceMappingURL=product-acting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"product-acting.js","sourceRoot":"","sources":["../../src/commands/product-acting.ts"],"names":[],"mappings":"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"}
@@ -3,10 +3,12 @@
3
3
  *
4
4
  * Checks the npm registry for the latest published version of the
5
5
  * agent-media package, compares it against the locally installed version,
6
- * and optionally offers to install the update.
6
+ * installs the update, and refreshes the Claude Code skill docs.
7
7
  *
8
8
  * Flags:
9
9
  * --check Check-only mode (do not prompt or install).
10
+ * --cli-only Update only the CLI package.
11
+ * --skills-only Update only the Claude Code skill docs.
10
12
  */
11
13
  import type { Command } from 'commander';
12
14
  export declare function registerUpdateCommand(program: Command): void;
@@ -1 +1 @@
1
- {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+HzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2H5D"}
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkKzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwK5D"}
@@ -8,8 +8,19 @@ const require = createRequire(import.meta.url);
8
8
  const pkg = require('../../package.json');
9
9
  /** npm registry URL for the package. */
10
10
  const REGISTRY_URL = `https://registry.npmjs.org/${pkg.name}/latest`;
11
+ /** Canonical Claude Code skill repo installed by the public docs. */
12
+ const SKILL_REPO = 'gitroomhq/agent-media';
11
13
  /** Timeout for the registry fetch (5 seconds). */
12
14
  const FETCH_TIMEOUT_MS = 5_000;
15
+ function commandErrorMessage(error) {
16
+ if (error instanceof Error) {
17
+ const maybeExecError = error;
18
+ const stderr = maybeExecError.stderr?.toString().trim();
19
+ const stdout = maybeExecError.stdout?.toString().trim();
20
+ return stderr || stdout || error.message;
21
+ }
22
+ return String(error);
23
+ }
13
24
  /**
14
25
  * Compare two semver strings. Returns:
15
26
  * -1 if a < b, 0 if equal, 1 if a > b.
@@ -110,97 +121,164 @@ function buildInstallCommand(pm, version) {
110
121
  return `npm install -g ${spec}`;
111
122
  }
112
123
  }
124
+ function buildSkillUpdateCommand() {
125
+ return `npx --yes add-skill ${SKILL_REPO}`;
126
+ }
113
127
  export function registerUpdateCommand(program) {
114
128
  program
115
129
  .command('update')
116
- .description('Check for and install CLI updates')
130
+ .description('Update the CLI and Claude Code skill docs')
117
131
  .option('--check', 'Check only, do not install')
132
+ .option('--cli-only', 'Update only the global CLI package')
133
+ .option('--skills-only', 'Update only the Claude Code skill docs')
118
134
  .action(async (cmdOpts) => {
119
135
  const globalOpts = program.opts();
120
136
  const mode = detectOutputMode(globalOpts);
121
137
  const checkOnly = cmdOpts.check ?? false;
138
+ const cliOnly = cmdOpts.cliOnly ?? false;
139
+ const skillsOnly = cmdOpts.skillsOnly ?? false;
140
+ if (cliOnly && skillsOnly) {
141
+ handleError(new CLIError('Choose either --cli-only or --skills-only, not both.', {
142
+ code: 'UPDATE_INVALID_FLAGS',
143
+ suggestion: 'Run either agent-media update --cli-only or agent-media update --skills-only.',
144
+ }));
145
+ }
146
+ const shouldUpdateCli = !skillsOnly;
147
+ const shouldUpdateSkills = !cliOnly;
122
148
  try {
123
- const spinner = createSpinner('Checking for updates...');
124
- if (mode === 'human')
125
- spinner.start();
126
- const latestVersion = await fetchLatestVersion();
127
- const currentVersion = pkg.version;
128
- const comparison = compareSemver(currentVersion, latestVersion);
129
- if (mode === 'human')
130
- spinner.stop();
131
- // Already up to date
132
- if (comparison >= 0) {
133
- switch (mode) {
134
- case 'json':
135
- printJson({
136
- current: currentVersion,
137
- latest: latestVersion,
138
- update_available: false,
149
+ const pm = detectPackageManager();
150
+ const skillUpdateCommand = buildSkillUpdateCommand();
151
+ let cliState = null;
152
+ let skillState = null;
153
+ if (shouldUpdateCli) {
154
+ const spinner = createSpinner('Checking for CLI updates...');
155
+ if (mode === 'human')
156
+ spinner.start();
157
+ const latestVersion = await fetchLatestVersion();
158
+ const currentVersion = pkg.version;
159
+ const comparison = compareSemver(currentVersion, latestVersion);
160
+ if (mode === 'human')
161
+ spinner.stop();
162
+ cliState = {
163
+ current: currentVersion,
164
+ latest: latestVersion,
165
+ update_available: comparison < 0,
166
+ };
167
+ if (comparison < 0) {
168
+ const installCmd = buildInstallCommand(pm, latestVersion);
169
+ cliState.install_command = installCmd;
170
+ if (!checkOnly) {
171
+ if (mode === 'human') {
172
+ console.log();
173
+ console.log(chalk.bold(' CLI update available'));
174
+ console.log(` ${chalk.dim('Current:')} v${currentVersion}`);
175
+ console.log(` ${chalk.green('Latest:')} v${latestVersion}`);
176
+ console.log();
177
+ }
178
+ const installSpinner = createSpinner(`Updating CLI with ${pm}...`);
179
+ if (mode === 'human')
180
+ installSpinner.start();
181
+ try {
182
+ execSync(installCmd, {
183
+ encoding: 'utf-8',
184
+ stdio: 'pipe',
185
+ });
186
+ cliState.updated = true;
187
+ if (mode === 'human') {
188
+ installSpinner.succeed(`Updated agent-media CLI from v${currentVersion} to v${latestVersion}`);
189
+ }
190
+ }
191
+ catch (installError) {
192
+ if (mode === 'human')
193
+ installSpinner.fail('CLI update failed');
194
+ throw new CLIError(`Failed to install CLI update: ${commandErrorMessage(installError)}`, {
195
+ code: 'UPDATE_INSTALL_FAILED',
196
+ suggestion: `Try installing manually:\n ${installCmd}`,
197
+ });
198
+ }
199
+ }
200
+ else {
201
+ cliState.skipped = true;
202
+ }
203
+ }
204
+ else {
205
+ cliState.updated = false;
206
+ }
207
+ }
208
+ if (shouldUpdateSkills) {
209
+ skillState = {
210
+ repository: SKILL_REPO,
211
+ update_command: skillUpdateCommand,
212
+ };
213
+ if (!checkOnly) {
214
+ const skillSpinner = createSpinner('Refreshing Claude Code skill docs...');
215
+ if (mode === 'human')
216
+ skillSpinner.start();
217
+ try {
218
+ execSync(skillUpdateCommand, {
219
+ encoding: 'utf-8',
220
+ stdio: 'pipe',
139
221
  });
140
- break;
141
- case 'quiet':
142
- printQuiet(currentVersion);
143
- break;
144
- default:
145
- console.log();
146
- console.log(` ${chalk.green('Up to date!')} agent-media v${currentVersion} is the latest version.`);
147
- console.log();
148
- break;
222
+ skillState.updated = true;
223
+ if (mode === 'human')
224
+ skillSpinner.succeed(`Refreshed skill docs from ${SKILL_REPO}`);
225
+ }
226
+ catch (skillError) {
227
+ if (mode === 'human')
228
+ skillSpinner.fail('Skill refresh failed');
229
+ throw new CLIError(`Failed to update Claude Code skill docs: ${commandErrorMessage(skillError)}`, {
230
+ code: 'SKILL_UPDATE_FAILED',
231
+ suggestion: `Try running manually:\n ${skillUpdateCommand}`,
232
+ });
233
+ }
234
+ }
235
+ else {
236
+ skillState.skipped = true;
149
237
  }
150
- return;
151
238
  }
152
- // Update available
153
- const pm = detectPackageManager();
154
- const installCmd = buildInstallCommand(pm, latestVersion);
155
239
  switch (mode) {
156
240
  case 'json':
157
241
  printJson({
158
- current: currentVersion,
159
- latest: latestVersion,
160
- update_available: true,
161
- install_command: installCmd,
242
+ cli: cliState,
243
+ skills: skillState,
244
+ check_only: checkOnly,
162
245
  });
163
246
  break;
164
247
  case 'quiet':
165
- printQuiet(latestVersion);
248
+ printQuiet([
249
+ cliState ? `cli:${cliState.latest}` : 'cli:skipped',
250
+ skillState ? `skills:${skillState.repository}` : 'skills:skipped',
251
+ ]);
166
252
  break;
167
- default: {
168
- console.log();
169
- console.log(chalk.bold(' Update available!'));
170
- console.log();
171
- console.log(` ${chalk.dim('Current:')} v${currentVersion}`);
172
- console.log(` ${chalk.green('Latest:')} v${latestVersion}`);
253
+ default:
173
254
  console.log();
174
255
  if (checkOnly) {
175
- console.log(` Run the following to update:`);
176
- console.log();
177
- console.log(` ${chalk.cyan(installCmd)}`);
178
- console.log();
179
- return;
256
+ if (cliState) {
257
+ if (cliState.update_available) {
258
+ console.log(`${chalk.bold('CLI update available')}: v${cliState.current} -> v${cliState.latest}`);
259
+ console.log(` ${chalk.cyan(cliState.install_command)}`);
260
+ }
261
+ else {
262
+ console.log(`${chalk.green('CLI up to date')}: v${cliState.current}`);
263
+ }
264
+ }
265
+ if (skillState) {
266
+ console.log(`${chalk.bold('Skill refresh command')}:`);
267
+ console.log(` ${chalk.cyan(skillState.update_command)}`);
268
+ }
180
269
  }
181
- // Attempt to install the update
182
- console.log(` Installing update via ${pm}...`);
183
- console.log();
184
- const installSpinner = createSpinner(`Running: ${installCmd}`);
185
- installSpinner.start();
186
- try {
187
- execSync(installCmd, {
188
- encoding: 'utf-8',
189
- stdio: 'pipe',
190
- });
191
- installSpinner.succeed(`Updated agent-media from v${currentVersion} to v${latestVersion}`);
270
+ else {
271
+ if (cliState && !cliState.update_available) {
272
+ console.log(`${chalk.green('CLI up to date')}: v${cliState.current}`);
273
+ }
274
+ if (skillState?.updated) {
275
+ console.log(`${chalk.green('Skill docs refreshed')}: ${skillState.repository}`);
276
+ }
192
277
  console.log();
278
+ console.log(chalk.dim('Restart your terminal if the CLI binary was updated.'));
193
279
  }
194
- catch (installError) {
195
- installSpinner.fail('Installation failed');
196
- const msg = installError instanceof Error ? installError.message : String(installError);
197
- throw new CLIError(`Failed to install update: ${msg}`, {
198
- code: 'UPDATE_INSTALL_FAILED',
199
- suggestion: `Try installing manually:\n ${installCmd}`,
200
- });
201
- }
280
+ console.log();
202
281
  break;
203
- }
204
282
  }
205
283
  }
206
284
  catch (error) {