hermoso 0.1.253 → 0.1.254
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
|
@@ -30,6 +30,51 @@ ad-build tool accepts); build and read campaigns on your own ad accounts with yo
|
|
|
30
30
|
competitors with no brand drafted and no channel connected; or generate a file with nothing connected at all and
|
|
31
31
|
just download it. Use the one piece you need, or all of it together.
|
|
32
32
|
|
|
33
|
+
## Install in one command
|
|
34
|
+
|
|
35
|
+
This repo is a plugin marketplace, a Gemini CLI extension and a skills package at once, so a coding agent takes
|
|
36
|
+
Hermoso in one line. Every install brings the same four skills (`hermoso-research`, `hermoso-generate`,
|
|
37
|
+
`hermoso-ad-from-brand`, `hermoso-product-photoshoot`), and the skills drive the `hermoso` CLI through `npx`. No
|
|
38
|
+
tool list is loaded into your session: a CLI command costs nothing until it runs, and it reaches every tool.
|
|
39
|
+
The first time, your agent runs `npx -y hermoso auth login`, which opens a browser to sign in.
|
|
40
|
+
|
|
41
|
+
**Claude Code:**
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
claude plugin marketplace add hermoso-ai/hermoso && claude plugin install hermoso@hermoso
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Inside a session the same thing is `/plugin marketplace add hermoso-ai/hermoso` then `/plugin install hermoso@hermoso`.
|
|
48
|
+
|
|
49
|
+
**Codex CLI** (it reads the same marketplace file):
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
codex plugin marketplace add hermoso-ai/hermoso && codex plugin add hermoso@hermoso
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Gemini CLI:**
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
gemini extensions install https://github.com/hermoso-ai/hermoso
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Cursor, OpenCode, GitHub Copilot, Windsurf and about 75 more agents**, through the open skills installer:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npx skills add hermoso-ai/hermoso
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
It asks which agents to install into; `-a opencode` (or `cursor`, `github-copilot`, `windsurf`) picks one, and
|
|
68
|
+
`--skill hermoso-research` installs a single skill. VS Code agent plugins can also take this repo whole: run
|
|
69
|
+
**Chat: Install Plugin From Source** and paste `https://github.com/hermoso-ai/hermoso`.
|
|
70
|
+
|
|
71
|
+
**ChatGPT and Claude.ai** run in a browser and cannot run a CLI, so they use the hosted connector instead (see
|
|
72
|
+
below). The ChatGPT desktop app and ChatGPT workspace admins can also read this repo's
|
|
73
|
+
`.claude-plugin/marketplace.json`, which installs the skills.
|
|
74
|
+
|
|
75
|
+
No browser on the machine? Create a key in the app under **MCP & CLI** and run
|
|
76
|
+
`npx -y hermoso auth login --token <key>`.
|
|
77
|
+
|
|
33
78
|
## Which surface should your agent use?
|
|
34
79
|
|
|
35
80
|
Two shapes, and the right one is decided by **what your client can do**, not by which we prefer.
|
|
@@ -315,6 +360,8 @@ the package, so they need no key, no network and no sign-in.
|
|
|
315
360
|
`skills/` holds four installable skills: `hermoso-generate`, `hermoso-ad-from-brand`,
|
|
316
361
|
`hermoso-product-photoshoot`, `hermoso-research`.
|
|
317
362
|
|
|
363
|
+
The quickest way in is the one-command install at the top of this page. From a clone, copying works too:
|
|
364
|
+
|
|
318
365
|
```bash
|
|
319
366
|
cp -r skills/* ~/.claude/skills/
|
|
320
367
|
```
|
package/mcp/tools.mjs
CHANGED
|
@@ -3419,7 +3419,10 @@ function buildTools(rawServer, opts = {}, sink = null) {
|
|
|
3419
3419
|
const _pickLine = 'NAMING A MODEL IS HOW YOU GET ONE: a render that passes no `model` is routed by the server\'s own auto-pool, which is deliberately NARROWER than this catalog — the `best` flag and the longest-clip row do NOT decide it. If you need a particular model\'s length, resolution, audio or reference-count capability, pass its id in `model`; that is a deliberate pick and the server will not swap it without telling you.';
|
|
3420
3420
|
// RESOLUTION IS PER MODEL, and asking outside the list is not an error — it is a quiet downgrade.
|
|
3421
3421
|
const _resLine = 'RESOLUTION: each model\'s `resolutions` list is its REAL enum (and `creditsByRes` prices every tier). Ask for a tier a model does not list and the render is delivered at that model\'s best available tier instead — the reply does not say so — so read `resolutions` here before promising anyone 1080p or 4k.';
|
|
3422
|
-
|
|
3422
|
+
// recast_motion's two tiers, priced off the same live quote the app's costs page reads (toolExamples), never a number here.
|
|
3423
|
+
const _mq = (q) => (q ? Object.entries(q).map(([s, c]) => `${s}s=${c}cr`).join(' ') : null);
|
|
3424
|
+
const _motionLine = _mq(d.toolExamples?.motion) ? `\nRecast motion (recast_motion, billed per output second): tier pro (default) ${_mq(d.toolExamples.motion)}${_mq(d.toolExamples.motionStandard) ? `; tier standard ${_mq(d.toolExamples.motionStandard)}` : ''}` : '';
|
|
3425
|
+
const text = `Image: ${d.image ? img : 'unavailable'}\nVideo: ${d.video ? vid : 'unavailable'}\n${_lenLine}\n${_pickLine}\n${_resLine}${_motionLine}\nVoice engines (generate_voice): ${voice}\nWriting models (generate_text): ${llm}\ncanEdit:${d.canEdit} canAvatar:${d.canAvatar}\nRecipes (${(d.recipes || []).length}): ${(d.recipes || []).slice(0, 20).map(r => r.id).join(', ')}…\n\n${CAPABILITY_MAP}`;
|
|
3423
3426
|
return ok(text + connLine, d);
|
|
3424
3427
|
}));
|
|
3425
3428
|
|
|
@@ -19152,17 +19155,18 @@ function memoryNoteVerdict(text) {
|
|
|
19152
19155
|
|
|
19153
19156
|
server.registerTool('recast_motion', {
|
|
19154
19157
|
title: 'Recast motion',
|
|
19155
|
-
description: "Motion transfer: re-perform a reference video's motion with a different person/character (supply their image). The reference clip drives the movement; the image supplies the identity. Paid render.",
|
|
19158
|
+
description: "Motion transfer: re-perform a reference video's motion with a different person/character (supply their image). The reference clip drives the movement; the image supplies the identity. Paid render, billed per output second (the output is as long as the reference clip, 3-30s); a 5s clip takes about 5 minutes. Runs on the Pro tier by default: 1080p, and the person really handles the object the reference performer handles.",
|
|
19156
19159
|
inputSchema: {
|
|
19157
19160
|
image: z.string().describe("the actor/character image URL (who should appear)"),
|
|
19158
19161
|
video: z.string().describe('the reference video whose motion to re-perform'),
|
|
19159
19162
|
prompt: z.string().optional().describe('optional scene/style guidance'),
|
|
19160
19163
|
orientation: z.enum(['video', 'image']).optional().describe("which aspect to keep: the video's (default) or the image's"),
|
|
19164
|
+
tier: z.enum(['pro', 'standard']).optional().describe("'pro' (default): 1080p and real hand-object interaction. 'standard': about 25% fewer credits and faster, but 720p, and it tends to mime a held object with empty hands. hermoso_capabilities lists the exact credits for both"),
|
|
19161
19165
|
},
|
|
19162
19166
|
outputSchema: { ...JOB_OUT },
|
|
19163
19167
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
19164
|
-
}, wrap(async ({ image, video, prompt = '', orientation = 'video' }) => {
|
|
19165
|
-
const r = await renderJob('motion', { image, video, prompt, orientation }, 'Motion recast');
|
|
19168
|
+
}, wrap(async ({ image, video, prompt = '', orientation = 'video', tier }) => {
|
|
19169
|
+
const r = await renderJob('motion', { image, video, prompt, orientation, ...(tier ? { tier } : {}) }, 'Motion recast');
|
|
19166
19170
|
return okVideo(`Recast video: ${r.url}`, r);
|
|
19167
19171
|
}));
|
|
19168
19172
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hermoso",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.254",
|
|
4
4
|
"mcpName": "io.github.hermoso-ai/hermoso",
|
|
5
5
|
"description": "Marketing on autopilot, run from your own AI agent. 841 tools. Publishing, scheduling, ad campaign management, comments, DMs and analytics cost no credits on every plan; credits are only for generating creative and for Ad Spy research. AD PLATFORMS: Meta, Google Ads, TikTok Ads, LinkedIn Ads, Reddit Ads, X Ads, Pinterest Ads, Snapchat Ads, Microsoft Advertising, Apple Search Ads and ChatGPT Ads, plus product feeds in Google Merchant Center. PUBLISHING AND SCHEDULING: Facebook, Instagram, Threads, TikTok, YouTube, X, LinkedIn, Pinterest, Bluesky and Telegram. AD RESEARCH: the Meta, Google and LinkedIn ad libraries plus organic TikTok, Instagram, YouTube, Threads and Reddit. ANALYTICS: Google Analytics 4, Google Search Console and every connected platform's own post and campaign insights. Also brand onboarding, 50+ image and video generation models, ad scoring, competitor teardowns, Google Drive and OneDrive, a CLI and installable Claude skills.",
|
|
6
6
|
"type": "module",
|
|
@@ -5,16 +5,18 @@ description: >-
|
|
|
5
5
|
copy, then render the image or video. Use when the user says "make an ad for <company/website>", "build a
|
|
6
6
|
launch ad for my brand", or gives a domain/brand and wants a complete ad, not just research. NOT for: just
|
|
7
7
|
pulling competitor ads (use hermoso-research) or rendering from a prompt you already have (use hermoso-generate).
|
|
8
|
-
argument-hint: "[brand or website + what to advertise
|
|
8
|
+
argument-hint: "[brand or website + what to advertise, e.g. 'an ad for yourbrand.com, our best-selling olive oil']"
|
|
9
9
|
allowed-tools: Bash
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
-
# Hermoso
|
|
12
|
+
# Hermoso: full ad from a brand
|
|
13
13
|
|
|
14
14
|
Drive the **Hermoso CLI** to go from a brand to a finished ad in three steps. Report the final media URL.
|
|
15
15
|
|
|
16
|
-
## Setup
|
|
17
|
-
-
|
|
16
|
+
## Setup (once)
|
|
17
|
+
- Run the CLI through npx: `npx -y hermoso <command>`. The commands below are written `hermoso …`; if `hermoso` is not on PATH (`npm install -g hermoso` puts it there), prefix them with `npx -y`. No MCP server is needed.
|
|
18
|
+
- Sign in once: `npx -y hermoso auth login` (opens a browser; nothing to paste). On a machine with no browser: `npx -y hermoso auth login --token <your key>`, using a key from app.hermoso.ai under **MCP & CLI**. No account at all? An agent can sign itself up on a paid plan with `POST /v1/signup` at app.hermoso.ai; see the Hermoso README.
|
|
19
|
+
- For anything these steps do not cover: `hermoso tools --search <what you want>` finds the tool, `hermoso tools <name>` prints its arguments, `hermoso call <name> --json '{...}'` runs it. The CLI reaches every tool and costs no context until it runs.
|
|
18
20
|
|
|
19
21
|
## Procedure
|
|
20
22
|
1. **Onboard the brand** (skip if the user already gave full brand details):
|
|
@@ -25,11 +27,11 @@ Drive the **Hermoso CLI** to go from a brand to a finished ad in three steps. Re
|
|
|
25
27
|
2. **Plan the concept + copy:** `hermoso create --brand "<name>" --product "<what to advertise + angle>" --format <auto|image|video> --json`
|
|
26
28
|
- Read the result: it has the `concept`, `copy[]` (headline/primary/cta), and the resolved **render model id** (`imodel` for images, `vmodel` for video). Tell the user the concept + headline.
|
|
27
29
|
3. **Render**, using the model the create step resolved (or run `hermoso capabilities` for options):
|
|
28
|
-
- Image: `hermoso generate image --prompt "<image_concept.prompt from step 2
|
|
30
|
+
- Image: `hermoso generate image --prompt "<image_concept.prompt from step 2, it already bakes in the copy>" --model <imodel> --aspect 1:1`
|
|
29
31
|
- Video: `hermoso generate video --prompt "<from the storyboard>" --model <vmodel> --aspect 9:16 --duration 8 --wait`
|
|
30
32
|
4. **Report the served URL.** Offer one concrete next step (a punchier hook, a different aspect ratio, or a variation).
|
|
31
33
|
|
|
32
34
|
## Notes
|
|
33
35
|
- If the brand has a real product photo and the ad features that product, pass it with `--ref ./product.png` on the image step so the packaging is accurate.
|
|
34
36
|
- Quality over cost: prefer the resolved/best model unless the user asks for cheap/fast.
|
|
35
|
-
-
|
|
37
|
+
- Renders run on Hermoso's hosted API and come back as served URLs; `hermoso fetch <url> --out <file>` saves one to disk.
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: hermoso-generate
|
|
3
3
|
description: >-
|
|
4
|
-
Generate on-brand ad creative with Hermoso
|
|
5
|
-
stitched videos
|
|
4
|
+
Generate on-brand ad creative with Hermoso (images, videos, talking-avatar clips, and multi-scene
|
|
5
|
+
stitched videos) from a prompt, returning a served media URL. Use when the user asks to "generate /
|
|
6
6
|
make / render an image or video ad", "create an ad", "make a product shot", "make a UGC video", or to
|
|
7
7
|
turn a concept into finished creative with Hermoso. NOT for: pure research/competitor lookups (use
|
|
8
8
|
hermoso-research), or editing an existing local image with a non-Hermoso tool.
|
|
9
|
-
argument-hint: "[what to generate
|
|
9
|
+
argument-hint: "[what to generate, e.g. 'a 9:16 video ad for our protein pancakes']"
|
|
10
10
|
allowed-tools: Bash
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
# Hermoso
|
|
13
|
+
# Hermoso: generate ad creative
|
|
14
14
|
|
|
15
15
|
You drive the **Hermoso CLI** (`hermoso`) to render images and videos. Always report the final **media URL**.
|
|
16
16
|
|
|
17
17
|
## Setup (once)
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
- Run the CLI through npx: `npx -y hermoso <command>`. The commands below are written `hermoso …`; if `hermoso` is not on PATH (`npm install -g hermoso` puts it there), prefix them with `npx -y`. No MCP server is needed.
|
|
19
|
+
- Sign in once: `npx -y hermoso auth login` (opens a browser; nothing to paste). On a machine with no browser: `npx -y hermoso auth login --token <your key>`, using a key from app.hermoso.ai under **MCP & CLI**. No account at all? An agent can sign itself up on a paid plan with `POST /v1/signup` at app.hermoso.ai; see the Hermoso README.
|
|
20
|
+
- For anything these steps do not cover: `hermoso tools --search <what you want>` finds the tool, `hermoso tools <name>` prints its arguments, `hermoso call <name> --json '{...}'` runs it. The CLI reaches every tool and costs no context until it runs.
|
|
20
21
|
|
|
21
22
|
## Procedure
|
|
22
23
|
1. **Always run `hermoso capabilities` first.** It lists the valid image/video **model ids**, their credit costs, aspect ratios, video durations, and the recipe ids. Never guess a model id.
|
|
@@ -26,7 +27,7 @@ You drive the **Hermoso CLI** (`hermoso`) to render images and videos. Always re
|
|
|
26
27
|
- Video: `hermoso generate video --prompt "<shot description>" [--ref ./frame.png] [--duration 8] [--aspect 9:16] [--model <id>] [--tts "<voiceover>"] [--voice Rachel] --wait`
|
|
27
28
|
- Avatar (lip-sync): `hermoso generate avatar --image ./face.png --script "<words>" [--voice George] --wait`
|
|
28
29
|
- Stitch (≥2 scenes): `hermoso generate stitch --scenes scenes.json --wait`
|
|
29
|
-
4. Video/avatar/stitch are **job-based
|
|
30
|
+
4. Video/avatar/stitch are **job-based**: keep `--wait` (default) so the command blocks and prints the final URL. If you don't wait, poll with `hermoso jobs get <id> --wait`.
|
|
30
31
|
5. **Report the served URL** (e.g. `https://assets.hermoso.ai/…`), never a raw job id. If the user wants the file, `hermoso fetch <url> --out name.png`.
|
|
31
32
|
|
|
32
33
|
## Notes
|
|
@@ -5,31 +5,33 @@ description: >-
|
|
|
5
5
|
scenes via reference-image compositing, so the packaging/label stays accurate. Use when the user wants
|
|
6
6
|
"product shots", "a photoshoot for my product", "lifestyle images of <product>", "hero banner", or "a pack of
|
|
7
7
|
ad images" from a real product image. NOT for: video (use hermoso-generate) or research (use hermoso-research).
|
|
8
|
-
argument-hint: "[product image + scene
|
|
8
|
+
argument-hint: "[product image + scene, e.g. './bag.png as a sunlit kitchen hero shot']"
|
|
9
9
|
allowed-tools: Bash
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
-
# Hermoso
|
|
12
|
+
# Hermoso: product photoshoot
|
|
13
13
|
|
|
14
14
|
Use Hermoso's reference-image compositing so the real product (label, colours, shape) is preserved while the
|
|
15
15
|
scene around it is generated. Drive the **Hermoso CLI**.
|
|
16
16
|
|
|
17
|
-
## Setup
|
|
18
|
-
-
|
|
17
|
+
## Setup (once)
|
|
18
|
+
- Run the CLI through npx: `npx -y hermoso <command>`. The commands below are written `hermoso …`; if `hermoso` is not on PATH (`npm install -g hermoso` puts it there), prefix them with `npx -y`. No MCP server is needed.
|
|
19
|
+
- Sign in once: `npx -y hermoso auth login` (opens a browser; nothing to paste). On a machine with no browser: `npx -y hermoso auth login --token <your key>`, using a key from app.hermoso.ai under **MCP & CLI**. No account at all? An agent can sign itself up on a paid plan with `POST /v1/signup` at app.hermoso.ai; see the Hermoso README.
|
|
20
|
+
- Run `hermoso capabilities` once to see image model ids and recipes. For anything these steps do not cover: `hermoso tools --search <what you want>` finds the tool, `hermoso tools <name>` prints its arguments, `hermoso call <name> --json '{...}'` runs it.
|
|
19
21
|
|
|
20
22
|
## Procedure
|
|
21
|
-
1. Get the **product image** path/URL from the user. This is the `--ref
|
|
22
|
-
2. Pick a **mode** and write the prompt accordingly (compose for ads
|
|
23
|
-
- `product_shot
|
|
24
|
-
- `lifestyle_scene
|
|
25
|
-
- `hero_banner
|
|
26
|
-
- `social_carousel
|
|
27
|
-
- `ad_creative_pack
|
|
23
|
+
1. Get the **product image** path/URL from the user. This is the `--ref`, it forces product-accurate compositing.
|
|
24
|
+
2. Pick a **mode** and write the prompt accordingly (compose for ads: off-center hero, depth, directional light, negative space for copy):
|
|
25
|
+
- `product_shot`: clean studio packshot on a seamless backdrop.
|
|
26
|
+
- `lifestyle_scene`: the product in a real in-use setting (kitchen, desk, outdoors).
|
|
27
|
+
- `hero_banner`: wide banner composition with room for a headline.
|
|
28
|
+
- `social_carousel`: several angles/scenes of the same product (run the command N times with varied prompts).
|
|
29
|
+
- `ad_creative_pack`: a few finished ad images with on-image copy.
|
|
28
30
|
3. Render: `hermoso generate image --prompt "<scene + composition + any on-image text>" --ref <product image> [--model <id>] [--aspect 1:1|4:5|16:9]`
|
|
29
31
|
- Prefer the `★best` image model for hero work; a faster model is fine for bulk variations.
|
|
30
32
|
4. For a **pack**, loop: vary the scene/angle/aspect per call, collect the URLs, and present them together.
|
|
31
33
|
5. Report each served image URL; offer to `hermoso fetch` them to disk or to tweak a scene.
|
|
32
34
|
|
|
33
35
|
## Notes
|
|
34
|
-
- Keep the product as the hero; never let generated text garble the real label
|
|
36
|
+
- Keep the product as the hero; never let generated text garble the real label, describe the product as "the exact product in the reference, label unchanged."
|
|
35
37
|
- `--ref` takes a local path (read + sent) or a URL.
|
|
@@ -5,16 +5,18 @@ description: >-
|
|
|
5
5
|
across Meta/Google/LinkedIn, and surface the winning hooks/angles worth copying. Use when the user asks to
|
|
6
6
|
"find my competitors", "pull <brand>'s ads", "what ads are working in my niche", "research the longest-running
|
|
7
7
|
ads", or wants proven creative to remix. NOT for: generating creative (use hermoso-generate / hermoso-ad-from-brand).
|
|
8
|
-
argument-hint: "[a brand/domain or a research question
|
|
8
|
+
argument-hint: "[a brand/domain or a research question, e.g. 'longest-running protein-pancake ads']"
|
|
9
9
|
allowed-tools: Bash
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
-
# Hermoso
|
|
12
|
+
# Hermoso: competitor & ad research
|
|
13
13
|
|
|
14
14
|
This is Hermoso's discovery half (which most generators don't have). Drive the **Hermoso CLI**.
|
|
15
15
|
|
|
16
|
-
## Setup
|
|
17
|
-
-
|
|
16
|
+
## Setup (once)
|
|
17
|
+
- Run the CLI through npx: `npx -y hermoso <command>`. The commands below are written `hermoso …`; if `hermoso` is not on PATH (`npm install -g hermoso` puts it there), prefix them with `npx -y`. No MCP server is needed.
|
|
18
|
+
- Sign in once: `npx -y hermoso auth login` (opens a browser; nothing to paste). On a machine with no browser: `npx -y hermoso auth login --token <your key>`, using a key from app.hermoso.ai under **MCP & CLI**. No account at all? An agent can sign itself up on a paid plan with `POST /v1/signup` at app.hermoso.ai; see the Hermoso README.
|
|
19
|
+
- For anything these steps do not cover (organic search on TikTok, Instagram, YouTube, Reddit or Threads, creator search, a competitor teardown): `hermoso tools --search <what you want>` finds the tool, `hermoso tools <name>` prints its arguments, `hermoso call <name> --json '{...}'` runs it.
|
|
18
20
|
|
|
19
21
|
## Procedure
|
|
20
22
|
Pick the tool that fits the ask:
|
|
@@ -24,7 +26,7 @@ Pick the tool that fits the ask:
|
|
|
24
26
|
- Defaults to Meta (richest library). Add google/linkedin only if asked (Google detailed pulls cost more).
|
|
25
27
|
3. **Natural-language research** (Claude tool-use over ad libraries + organic TikTok): `hermoso research "<request>"`
|
|
26
28
|
- e.g. `hermoso research "the longest-running protein-pancake ads on Meta and what hooks they use"`. Prints a summary + the found ads with their URLs.
|
|
27
|
-
4. **Synthesize**: report the strongest hooks, angles, formats, and what's worth copying
|
|
29
|
+
4. **Synthesize**: report the strongest hooks, angles, formats, and what's worth copying, be specific (quote the actual headlines/angles). If the user then wants to build one, hand off to `hermoso-ad-from-brand` / `hermoso-generate`.
|
|
28
30
|
|
|
29
31
|
## Notes
|
|
30
32
|
- Research spends credits (ad-library calls); keep platform scope to what's asked.
|