hermoso 0.1.528 → 0.1.530
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 +9 -8
- package/mcp/chatgpt-roster.mjs +2 -1
- package/mcp/client.mjs +4 -1
- package/mcp/prod-gate-flags.json +1 -0
- package/mcp/roster-scope.mjs +8 -2
- package/mcp/tool-hints.mjs +3 -3
- package/mcp/tools.mjs +716 -116
- package/package.json +2 -2
- package/skills/hermoso-edit-timeline/SKILL.md +34 -0
- package/skills/hermoso-marketing/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -67,7 +67,7 @@ Ask in your own words. The agent picks the tools:
|
|
|
67
67
|
- "Compare last week's Google Ads and Meta Ads results and tell me what to pause."
|
|
68
68
|
- "Schedule this video to TikTok, Instagram Reels and YouTube Shorts for Tuesday at 9am."
|
|
69
69
|
|
|
70
|
-
**
|
|
70
|
+
**1195 tools.** `tools/list` is always the authoritative set; `hermoso_capabilities` (free) returns the live model
|
|
71
71
|
catalog with exact per-render credit costs plus the full capability map.
|
|
72
72
|
|
|
73
73
|
**No markup on models** on Starter, Pro and Studio. Stop overpaying markups on AI models. Plans: [hermoso.ai/pricing](https://hermoso.ai/pricing).
|
|
@@ -78,7 +78,7 @@ website.
|
|
|
78
78
|
|
|
79
79
|
**Most of it costs nothing.** Publishing and scheduling posts, building and managing paid campaigns, analytics
|
|
80
80
|
and insights, comments and DMs, connectors, profiles and team seats cost **no credits on any plan**, with no
|
|
81
|
-
per-post fee and no seat pricing. The Free plan includes
|
|
81
|
+
per-post fee and no seat pricing. The Free plan includes 5 posts a month on up to 3 platforms; every paid plan posts without a limit and runs autopilot. Basic ($19.99 a month) is unlimited posting and Autopilot with no monthly credits: it includes the same 160 free credits as the Free plan, and monthly credits start on Starter. Credits are spent only on running an AI model (image, video,
|
|
82
82
|
voice, text, planning, post-production) and on Ad Spy research, and posting an ad you already rendered is never a
|
|
83
83
|
second charge. The one exception is X (Twitter), where posting and reads bill credits per call because X
|
|
84
84
|
charges per API request (`hermoso_credits` prints the exact credits per X post).
|
|
@@ -102,8 +102,8 @@ just download it. Use the one piece you need, or all of it together.
|
|
|
102
102
|
## Install in one command
|
|
103
103
|
|
|
104
104
|
This repo is a plugin marketplace, a Gemini CLI extension and a skills package at once, so a coding agent takes
|
|
105
|
-
Hermoso in one line. Every install brings the same
|
|
106
|
-
`hermoso-ad-from-brand`, `hermoso-product-photoshoot`, `hermoso-marketing`), and the skills drive the `hermoso`
|
|
105
|
+
Hermoso in one line. Every install brings the same six skills (`hermoso-research`, `hermoso-generate`,
|
|
106
|
+
`hermoso-ad-from-brand`, `hermoso-product-photoshoot`, `hermoso-marketing`, `hermoso-edit-timeline`), and the skills drive the `hermoso`
|
|
107
107
|
CLI through `npx`. No
|
|
108
108
|
tool list is loaded into your session: a CLI command costs nothing until it runs, and it reaches every tool.
|
|
109
109
|
The first time, your agent runs `npx -y hermoso auth login`, which opens a browser to sign in.
|
|
@@ -252,7 +252,7 @@ Connect, approve with your Hermoso account, and you are done: the full toolset w
|
|
|
252
252
|
1. **Get an account** at [app.hermoso.ai](https://app.hermoso.ai). The free tier is included; plans and credits
|
|
253
253
|
are the same ones the web Studio uses. Or skip the browser entirely and let your agent sign itself up on a paid
|
|
254
254
|
plan with `POST /v1/signup` (above).
|
|
255
|
-
2. **Install the plugin.** It adds the
|
|
255
|
+
2. **Install the plugin.** It adds the six Hermoso skills, which drive the `hermoso` CLI through `npx`:
|
|
256
256
|
|
|
257
257
|
```bash
|
|
258
258
|
claude plugin marketplace add hermoso-ai/hermoso && claude plugin install hermoso@hermoso
|
|
@@ -276,7 +276,7 @@ your browser (`--no-browser` prints the link on a headless machine). Measured ag
|
|
|
276
276
|
|
|
277
277
|
Your agent now has the full studio **with your profile's context**: the brand details, products, logos and
|
|
278
278
|
learned memory you set up in the web app apply automatically (`get_brand` shows what's saved; omit `brand` in
|
|
279
|
-
`plan_ad`/`plan_variations` to use it). Renders bill your Hermoso credits, at the same prices as the Studio. Only AI model runs and Ad Spy research spend credits; publishing, scheduling, ads management and analytics cost no credits on any plan (posting to X and reading X data are the one per-call exception, managing X ads is free). The Free plan includes
|
|
279
|
+
`plan_ad`/`plan_variations` to use it). Renders bill your Hermoso credits, at the same prices as the Studio. Only AI model runs and Ad Spy research spend credits; publishing, scheduling, ads management and analytics cost no credits on any plan (posting to X and reading X data are the one per-call exception, managing X ads is free). The Free plan includes 5 posts a month on up to 3 platforms; every paid plan posts without a limit and runs autopilot. Basic ($19.99 a month) is unlimited posting and Autopilot with no monthly credits: it includes the same 160 free credits as the Free plan, and monthly credits start on Starter.
|
|
280
280
|
|
|
281
281
|
## 1. MCP server (stdio), optional in a coding agent
|
|
282
282
|
|
|
@@ -304,7 +304,7 @@ block entirely if you signed in above; it is there for CI, where the process can
|
|
|
304
304
|
|
|
305
305
|
Then ask your agent: *“Generate an image ad with Hermoso.”*
|
|
306
306
|
|
|
307
|
-
### What the
|
|
307
|
+
### What the 1195 tools cover
|
|
308
308
|
|
|
309
309
|
**Ad spy / research** — `find_competitors`, `competitor_teardown`, `pull_competitor_ads`, `research_ads`; the
|
|
310
310
|
Meta / Google / LinkedIn ad libraries (`search_meta_ads`, `search_google_ads`, `search_linkedin_ads`); organic
|
|
@@ -480,7 +480,7 @@ the package, so they need no key, no network and no sign-in.
|
|
|
480
480
|
|
|
481
481
|
## 3. Skills: what a coding agent installs
|
|
482
482
|
|
|
483
|
-
`skills/` holds
|
|
483
|
+
`skills/` holds six installable skills:
|
|
484
484
|
|
|
485
485
|
| Skill | What it does |
|
|
486
486
|
| --- | --- |
|
|
@@ -489,6 +489,7 @@ the package, so they need no key, no network and no sign-in.
|
|
|
489
489
|
| `hermoso-ad-from-brand` | A brand or domain to one on-brand ad, concept and copy included |
|
|
490
490
|
| `hermoso-product-photoshoot` | A real product photo composited into studio, lifestyle or hero scenes |
|
|
491
491
|
| `hermoso-marketing` | The whole loop: research, create, publish and schedule, paid campaigns, measure |
|
|
492
|
+
| `hermoso-edit-timeline` | The manual for composing any video edit or transition with `edit_timeline` |
|
|
492
493
|
|
|
493
494
|
They are what every one-command install at the top of this page adds, in Claude Code, Codex, Gemini CLI and
|
|
494
495
|
through `npx skills add`. From a clone, copying works too:
|
package/mcp/chatgpt-roster.mjs
CHANGED
|
@@ -24,11 +24,11 @@ export const CHATGPT_ROSTER_FAMILIES = Object.freeze([
|
|
|
24
24
|
'bluesky', // publishing
|
|
25
25
|
'openai_ads', // big-platform ads
|
|
26
26
|
'reddit_ads', // long tail
|
|
27
|
-
'bing_webmaster', // analytics
|
|
28
27
|
]);
|
|
29
28
|
// Left out to stay under the cap, in rank order (the first one is the next to get in when room appears).
|
|
30
29
|
export const CHATGPT_ROSTER_LEFT_OUT = Object.freeze([
|
|
31
30
|
'x_ads', // long tail
|
|
31
|
+
'bing_webmaster', // analytics
|
|
32
32
|
'mixpanel', // analytics
|
|
33
33
|
'apple_ads', // long tail
|
|
34
34
|
'pinterest_ads', // long tail
|
|
@@ -42,6 +42,7 @@ export const CHATGPT_ROSTER_LEFT_OUT = Object.freeze([
|
|
|
42
42
|
'mailchimp', // analytics
|
|
43
43
|
'posthog', // analytics
|
|
44
44
|
'stripe', // analytics
|
|
45
|
+
'amazon_ads', // long tail
|
|
45
46
|
'applovin_ads', // long tail
|
|
46
47
|
'canva', // long tail
|
|
47
48
|
'notion', // long tail
|
package/mcp/client.mjs
CHANGED
|
@@ -460,7 +460,10 @@ export async function connectedProviders() {
|
|
|
460
460
|
const shopifyStore = r?.shopifyStore === true ? true : r?.shopifyStore === false ? false : null;
|
|
461
461
|
// flagsOn (2026-11-03): tools that ship dark and are switched ON on this server (roster-scope.mjs FLAGGED_OFF_TOOLS).
|
|
462
462
|
const flagsOn = new Set((Array.isArray(r?.flagsOn) ? r.flagsOn : []).filter((n) => typeof n === 'string' && n));
|
|
463
|
-
|
|
463
|
+
// brand (2026-11-08): which brand this connection resolved to, so a "not connected" refusal can name it and the
|
|
464
|
+
// switch. Absent on an older server or a session login; never invented.
|
|
465
|
+
const brand = r?.brand && typeof r.brand === 'object' && typeof r.brand.profileId === 'string' ? { profileId: r.brand.profileId, name: typeof r.brand.name === 'string' ? r.brand.name : null, shared: !!r.brand.shared, source: String(r.brand.source || '') } : null;
|
|
466
|
+
return { connected: new Set(list.filter((p) => typeof p === 'string' && p)), readOk: true, offered, gated, connectLink, withheld, flagsOn, shopifyStore, brand };
|
|
464
467
|
} catch { return { connected: new Set(), readOk: false }; }
|
|
465
468
|
}
|
|
466
469
|
// Upload raw file BYTES to /api/upload (150MB, persists → returns {url,kind,bytes}). Overrides the JSON content-type so
|
package/mcp/prod-gate-flags.json
CHANGED
package/mcp/roster-scope.mjs
CHANGED
|
@@ -74,6 +74,7 @@ export const TOOL_PROVIDER_RULES = [
|
|
|
74
74
|
[/_microsoft_ads_|^microsoft_ads_|_microsoft_merchant_/, 'microsoft_ads'],
|
|
75
75
|
[/_apple_ads_|^apple_ads_/, 'apple_ads'],
|
|
76
76
|
[/_openai_ads_|^openai_ads_/, 'openai_ads'],
|
|
77
|
+
[/_amazon_ads_|^amazon_ads_/, 'amazon_ads'], // Amazon Ads (2026-11-07): Sponsored Products through Login with Amazon
|
|
77
78
|
[/applovin/, 'applovin_ads'], // AppLovin Ads (2026-10-04) has no posting sibling, so the bare name is unambiguous
|
|
78
79
|
// Google Ads owns Merchant Center + the Ads↔Analytics link (both are Google Ads API surfaces, not GA4 ones).
|
|
79
80
|
[/_google_ads_|^google_ads_|_merchant_|^merchant_|^list_merchant_|link_google_ads_to_analytics/, 'google_ads'],
|
|
@@ -255,13 +256,18 @@ export const WHOP_DARK_TOOLS = Object.freeze(['post_to_whop', 'list_whop_destina
|
|
|
255
256
|
// Whop they are lit PER CALLER: server.js flagsOnNow(connected, req) names them in `flagsOn` for a workspace that already
|
|
256
257
|
// holds a Canva connection (ours and Canva's reviewer's), so an existing connection keeps its tools while the gate is shut.
|
|
257
258
|
export const CANVA_DARK_TOOLS = Object.freeze(['save_to_canva', 'list_canva_designs', 'export_canva_design', 'list_canva_brand_templates', 'autofill_canva_template', 'list_canva_folder', 'create_canva_folder']);
|
|
258
|
-
|
|
259
|
+
// THE AMAZON ADS TOOLS SHIP DARK WITH AMAZON'S API-ACCESS APPROVAL (2026-11-07). The connector is built, but Amazon has not
|
|
260
|
+
// approved Hermoso's Amazon Ads API access, so CONNECTOR_GATES.amazon_ads is shut (AMAZON_ADS_API_APPROVED unset) and these
|
|
261
|
+
// are no capability for a customer yet: not counted, not documented, not on a roster. Lit PER CALLER exactly like Canva:
|
|
262
|
+
// server.js flagsOnNow names them for a workspace already holding an Amazon Ads connection and for the gate's team pass.
|
|
263
|
+
export const AMAZON_ADS_DARK_TOOLS = Object.freeze(['list_amazon_ads_profiles', 'list_amazon_ads_campaigns', 'create_amazon_ads_campaign', 'create_amazon_ads_ad_group', 'add_amazon_ads_keywords', 'create_amazon_ads_product_ads', 'set_amazon_ads_status', 'set_amazon_ads_budget', 'update_amazon_ads_object', 'delete_amazon_ads_object', 'amazon_ads_report']);
|
|
264
|
+
export const FLAGGED_OFF_TOOLS = new Set(['reangle_video', ...WHOP_DARK_TOOLS, ...CANVA_DARK_TOOLS, ...AMAZON_ADS_DARK_TOOLS]);
|
|
259
265
|
// THE PRODUCTION FLAG THAT LIFTS A DARK TOOL (2026-11-03, owner: count and document the Whop tools whenever their gate
|
|
260
266
|
// is open in prod, keep the automatic gate). A tool named here is dark only while that CONNECTOR_GATES flag is off in
|
|
261
267
|
// production, as recorded in docs-site/prod-gate-flags.json, the file the docs build already reads. The counts and the
|
|
262
268
|
// docs reference read it through darkToolsUnder(); the per-caller roster still follows `flagsOn` from the server.
|
|
263
269
|
// reangle_video has no entry: it follows its own REANGLE_VIDEO switch, which no production record carries.
|
|
264
|
-
export const DARK_TOOL_GATE_FLAG = Object.freeze(Object.fromEntries([...WHOP_DARK_TOOLS.map((n) => [n, 'WHOP_API_KEY']), ...CANVA_DARK_TOOLS.map((n) => [n, 'CANVA_APP_APPROVED'])]));
|
|
270
|
+
export const DARK_TOOL_GATE_FLAG = Object.freeze(Object.fromEntries([...WHOP_DARK_TOOLS.map((n) => [n, 'WHOP_API_KEY']), ...CANVA_DARK_TOOLS.map((n) => [n, 'CANVA_APP_APPROVED']), ...AMAZON_ADS_DARK_TOOLS.map((n) => [n, 'AMAZON_ADS_API_APPROVED'])]));
|
|
265
271
|
export function darkToolsUnder(flags) {
|
|
266
272
|
const f = flags && typeof flags === 'object' ? flags : {};
|
|
267
273
|
return new Set([...FLAGGED_OFF_TOOLS].filter((n) => !(DARK_TOOL_GATE_FLAG[n] && f[DARK_TOOL_GATE_FLAG[n]] === true)));
|
package/mcp/tool-hints.mjs
CHANGED
|
@@ -161,10 +161,10 @@ export const CREDITS_LOW_NOTE = `The Hermoso account's credit balance is too low
|
|
|
161
161
|
const UPSELL_SENTENCE_RE = /\s*(?:please\s+)?(?:upgrade(?:\s+your\s+plan)?\s+or\s+top\s+up|top\s+up|add\s+credits|buy\s+(?:more\s+)?credits|monthly\s+plans\s+have\s+no\s+markup\s+on\s+models)\b[^.!\n]*[.!]?/gi; // the monthly-plan upsell (2026-10-20) is a promotion too: a widget host (ChatGPT) never hears it
|
|
162
162
|
// ── FREE CREDITS NOT CLAIMED YET (2026-10-25, ChatGPT funnel) ─────────────────────────────────────────────────────
|
|
163
163
|
// An account whose welcome credits were never added (the one-time check that a person is behind it did not pass
|
|
164
|
-
// silently at sign-in) reads 0 credits. Its fix is opening
|
|
164
|
+
// silently at sign-in) reads 0 credits. Its fix is opening a one-click link once (2026-11-10: signed for the account, no sign-in), which is not a purchase, so it is
|
|
165
165
|
// said on every host, ChatGPT included. The server marks the refusal (meta.welcomeClaim = {credits, url}).
|
|
166
|
-
export const welcomeClaimSentence = (w) => `This account has not received its ${Number(w?.credits) || 0} free credits yet. The user opens ${w?.url} once in a browser,
|
|
167
|
-
export const welcomeClaimHint = (w) => ({ do: `ask the user to open ${w?.url} once in a browser,
|
|
166
|
+
export const welcomeClaimSentence = (w) => `This account has not received its ${Number(w?.credits) || 0} free credits yet. The user opens ${w?.url} once in a browser (one click, no sign-in and no card) and they arrive in a few seconds after a quick check that a person is there.`;
|
|
167
|
+
export const welcomeClaimHint = (w) => ({ do: `ask the user to open ${w?.url} once in a browser (one click, no sign-in) to receive the ${Number(w?.credits) || 0} free credits; then run the same call again`, why: 'the account never received its free credits: they wait behind a one-time check that a person is behind the account, which runs in the browser' });
|
|
168
168
|
export function neutralCreditsText(msg) {
|
|
169
169
|
const base = String(msg ?? '').replace(UPSELL_SENTENCE_RE, '').replace(/[ \t]+$/gm, '').replace(/\s*[—–,:-]\s*$/gm, '.').trim();
|
|
170
170
|
return `${base}${base ? '\n' : ''}${CREDITS_LOW_NOTE}`;
|