bama
BAMA: Build Any Mac App. Agent skills to research, clone, design, build, optimize, and test native macOS apps with Swift and SwiftUI.
Create high-converting video ads that boost your ROAS. Write a script, pick an actor, get professional content ready for any platform. Get started.
SkillsMarkdown · PythonGitHub @novoadsOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
AI video and image ads for marketers, built in Claude Code or Cursor and priced by a live estimate first.
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
Novoads AI Video & Image Ad Skill Pack (agent-skills)
AI video and image ads for marketers, built in Claude Code or Cursor and priced by a live estimate first.
Every image and video in this README was generated by the skills in this repo, through the API, with
the asks shown beside them.
Make AI video ads and static image ads from Claude Code or Cursor, against your own
Novoads
account. The agent does the mechanical part — upload, price, generate, poll, download — and the
skills carry the part that decides whether the render is any good: the prompt.Read the full README ↗Novoads (novoads.ai) is an AI UGC video ad generator; this pack drives the Novoads REST API from Claude Code or Cursor.
AI video and image ads for marketers, built in Claude Code or Cursor and priced by a live estimate first.
Every image and video in this README was generated by the skills in this repo, through the API, with the asks shown beside them.
Make AI video ads and static image ads from Claude Code or Cursor, against your own Novoads account. The agent does the mechanical part — upload, price, generate, poll, download — and the skills carry the part that decides whether the render is any good: the prompt.
In Claude Code or Cursor, open a new empty folder and paste:
https://github.com/novoads/agent-skills help me set this up
The agent clones this repo, runs ./scripts/setup.sh, and stops at the one step only you
can do: pasting your Novoads API key.
Need an account? Plans start at $15/month (Starter, 200 credits), and every plan can generate through the API. Current prices: novoads.ai/en/pricing (as of 2026-10-08).
See what it makes · Get started · What you can make · Models · Costs · Security · Support · License
Twelve skills, plus the shared steps they call, make the ad and the things around it. The generated
creative runs on the models GET /v1/models lists, video and stills alike: UGC video,
static Meta creatives, Pixar and claymation storyboards, and YouTube thumbnails. The narrator
voice-over, a replacement voice for an ad already made, a music bed, burned-in captions, a
competitor swipe file and a paused Meta ad come from their own endpoints and APIs instead.
Two rules run through the whole pack, and they are the reason it is safe to point an agent at a billing API:
POST /v1/estimates call in the session that is about to spend, shown to you and approved first.
That call charges nothing, and there is no rate table anywhere in this repo to fall back on.Two more things worth knowing before your first render. The prompt formulas build on the model vendors' own published guides from ByteDance, Google DeepMind, Google Cloud and OpenAI, scoped to what this API actually exposes (vendor prompting guides). And every Meta ad this pack publishes is created PAUSED, so nothing goes live without you (security).
Claude and Claude Code are products of Anthropic. This is an independent skill pack built by Novoads for Claude Code; it is not affiliated with or endorsed by Anthropic.
You need a POSIX shell (macOS or Linux; WSL2 or Git Bash on Windows), plus curl, jq and
a Novoads API key. Everything else is per-workflow.
A Novoads API key, and a shell. The key is not optional and nothing in this
repo substitutes for it: every skill here runs one executable path, curl
against https://api.novoads.ai/v1 with NOVOADS_API_KEY from .env. Create
one at novoads.ai/dashboard/settings?tab=api.
Beyond the key, the core workflow (upload a photo, price it, generate a
video or an image, poll, download) is plain HTTP driven by your agent.
curl and jq are enough, and both are already on most machines. Your
first ad needs nothing from the optional table.
| Tool | Needed for | Install (macOS) |
|---|---|---|
curl + jq | Everything on the API: uploads, estimates, generation, polling, download | preinstalled / brew install jq |
| Python 3.10+ | The Python-driven steps, including the image-ad callers (chatgpt-image-ad, nano-banana-image-ad, clone-image-ad) and the competitor sweep (spy-competitor-ads). Stdlib only, nothing to pip install | preinstalled or brew install [email protected] |
ffmpeg | Only the steps that assemble or edit video on your machine: the storyboard ads (pixar-ad, claymation-ad, both of which assemble locally at every length), the local post steps (music-mix, broll-overlay), and frame extraction in analyze-video. Every core API workflow needs nothing | brew install ffmpeg |
Captions, transcripts and music are generated server-side and need no local
tools: POST /v1/captions burns captions in (30 presets), POST /v1/transcripts
returns text, word timings and an SRT, and POST /v1/music generates the
soundtrack. Only laying that soundtrack under a finished cut is local, and that
is the music-mix step in the ffmpeg row above.
Optional, per workflow. Each skill tells you when it needs one; nothing here blocks your first ad:
| Tool | Only if you | Install |
|---|---|---|
| Meta publishing deps | publish finished creatives to the Meta Marketing API (meta-ad-builder) | pip install -r shared/skills/meta-ad-builder/scripts/requirements.txt |
Node.js + whisper | use the manual caption path instead of POST /v1/captions: a style outside the 30 presets, or hand-editing the wording before burn-in | brew install node; pip install openai-whisper plus a model download (the binary alone returns an EMPTY transcript, not an error) |
Linux: apt install curl jq ffmpeg python3. Windows: WSL2 or Git Bash;
the skills here are shell scripts and curl calls, so they need a POSIX shell.
No shell at all? See Environments that cannot run this repo at the bottom.
Fastest path: in Claude Code or Cursor, open a new empty folder and paste this, and the agent clones the repo, runs setup, and stops at your API key.
https://github.com/novoads/agent-skills help me set this up
Prefer the terminal? The same setup the pasted prompt above runs, by hand:
git clone https://github.com/novoads/agent-skills.git
cd agent-skills
./scripts/setup.sh
It creates .env (chmod 600), asks for your API key, and validates the key against
GET /v1/models before writing it to disk — a key that has never been probed is the most
expensive thing to debug later. It then copies MASTER_CONTEXT.template.md to your personal
MASTER_CONTEXT.md, syncs the skills, and runs the connectivity check.
Your key looks like novo_ followed by 64 hex characters. Create one at
novoads.ai/dashboard/settings?tab=api — it is
shown once, at creation, and cannot be retrieved afterwards.
Setup never hangs an agent: with no TTY (or with --non-interactive) it prompts for nothing,
prepares the workspace, prints the one step left for a human, and exits 0.
Re-check connectivity any time with ./scripts/check-novoads-env.sh. It tells you which failure
you have: a 401 is a bad or revoked key, a 403 with plan_required is a good key on an account
without API access. Different problems, different fixes.
Steps 3 and 4 are the same whichever way you installed, pasted prompt or terminal.
Claude Code: open the folder. A SessionStart hook syncs the skills and prints a banner —
which skills are installed, whether .env and MASTER_CONTEXT.md are set up, and the reminder
that prices come from /v1/estimates.
Cursor: open the folder. The same skills are exposed at .cursor/skills/.
Drop a product photo into references/products/ and say what you want. The agent picks the route,
reads the matching prompt formula, prices it, confirms the dialogue, and generates. The first time
you ask for an ad it asks what your product is and saves the answer to MASTER_CONTEXT.md, so no
later session asks again — setup itself never asks; the only thing setup needs from you is the key.
Everything below was made by this pack in one run on 2026-08-11/12, through the same skills a customer installs. Each item shows the exact ask typed to the agent and the prompt the skill wrote from it. The prompt panels are wrapped for width, and the long ones stop after their opening blocks and name their full length.
Demonstration creative for a real product; not commissioned by or affiliated with the brand.
| What | Watch | The ask, and the prompt the skill wrote |
|---|---|---|
| Pixar-style storyboard ad. A cast sheet, four beat stills, one clip per beat, voice-over into the gaps, a music bed and captions, assembled locally.Made with pixar-ad.Rendered 2026-08-12 UTC. Demo creative. | You type: Make a Pixar-style animated ad for Liquid Death — the villain is a sad crumpled plastic bottle. Play it as dark comedy, not eco-preaching.The prompt the skill wrote3D animated film look, vertical 9:16, animating the character in thereference image. crushed unlabeled bottle, a clear plastic water bottlestamped flat and concertinaed along its length, lying on its side inhard ribbed folds, cap gone, two oversized half-lidded eyes and a smalldownturned mouth set into the rounded end, wrecked and never intact, nolabel and no printed text anywhere on it, lying in a shallow gutterpuddle of black rainwater on wet asphalt at night under one amber streetlamp.From zero to one and a half seconds the bottle sags deeper into thepuddle and its eyes blink once, slowly. From one and a half to fourseconds the eyes lift to camera and the bottle says, flat and defeated:"I've been in a cupholder since March." Small mouth shapes match thesyllables and the eyebrows lift on the last word.Camera: locked extreme close-up macro, very subtle handheld micro-drift,no zoom, no pan.Stylized 3D animated feature film look, hard directional light with deepfalloff, cold palette of wet asphalt grey, gunmetal blue, bone white andtarnished gold, painterly soft-focus background, desaturated colourgrade with crushed blacks, every character caught mid-emotion.Audio: a small flat defeated male voice, close-mic and hollow, faintrain behind it. No other speech in this shot.The bottle is unchanged from the reference image: same crush creases,same eye placement. Exactly one bottle in frame. no live-action footage,no photorealistic humans, no uncanny faces, no dead eyes, no animestyle, no 2D cel-shaded look, no named or copyrighted animated filmcharacters, no morphing between frames, no on-screen text, no subtitles,no captions[beat 1 clip prompt, one of five. 1,677 characters, shown whole.] | |
Static ad to motion. One finished still, one call: the coin scratches the foil and the reveal happens while every printed word stays frozen.Made with image-to-motion.Rendered 2026-08-12 UTC. Demo creative.Rendered on seedance-2.0: on this run seedance-2.5 refused every start image it was sent, six calls, each charged and then refunded, while the same still went through on . |
Five templates from the 40-template library, plus a thumbnail, on one sheet: scratch ticket, desk-kit flatlay, 9:16 story hero, sticky-note flatlay, before/after split, and a reaction thumbnail from generate-youtube-thumbnail.
The pair demonstrates the edit endpoint: the same image sent back with sourceAssetId, one new
headline, and nothing else moved.
The pack prices before it spends: POST /v1/estimates first, the number shown, the render only
after that number is approved. This is what one of those moments looks like, captured on 2026-08-11
before the UGC row's 720p render. A dated capture, not a rate table.
{
"capturedAt": "2026-08-11",
"endpoint": "POST https://api.novoads.ai/v1/estimates",
"apiSpecVersion": "2.19.0",
"httpStatus": 200,
"request": {
"kind": "video",
"model": "seedance-2.0",
"durationSeconds": 15,
"resolution": "720p",
"language": "en",
"prompt": "15 seconds UGC style honest review video, filmed on smartphone, grey morning light through the kitchen window blinds, casual handheld selfie angle. … (2,646 characters)"
},
"response": {
"credits": 7,
"balance": 243.2,
"sufficient": true
},
"responseHeaders": {
"x-request-id": "f8f1379240ff64680b8263fa8d5559b3"
}
}
credits and balance are display credits, the same unit POST /v1/videos reports back as
creditsCharged. The prompt is abridged here for width; the call carried it in full.
Any integer duration from 4 to 15 seconds, six aspect ratios, native audio and lip-sync
rendered in the same call. Start from one photo (startImageAssetId animates it as the first
frame) or composite up to nine reference images (referenceAssetIds, addressed in the prompt
as @Image1…@ImageN). Those are two separate modes — a request carrying both is rejected.
Five prompt formulas ship, each with a worked example that has been priced live:
| Formula | For | File |
|---|---|---|
| UGC selfie review | A person talking to camera about the product | seedance-2-ugc.md |
| Premium reveal | Dark void, text narrative, no person | seedance-2-premium-reveal.md |
| Product hero | Splash, mist, light rays, slow rotation | seedance-2-product-hero.md |
| Studio lookbook | Polished multi-look editorial with voiceover | seedance-2-studio-lookbook.md |
| Feature walkthrough | Fast-paced demo cuts, one person held across clips | seedance-2-feature-walkthrough.md |
"Make a 12-second Seedance UGC video — woman in a kitchen holding the product, says she stopped buying the drugstore version"
The platform guide — grids, the two reference modes, prompt length by shot count, the mini-draft tier — is seedance-2.md.
Draft on Mini first. seedance-2.0-mini takes the same grid and the same formulas at half the
price and comes back in 2–3 minutes. Upload once, draft on Mini, re-price naming the final tier,
render once. The agent asks which tier you want before the first Seedance call of a workflow.
Any integer duration from 4 to 30 seconds, which makes it the only model here that renders past
15 in a single call. Everything else is 2.0's shape: the same six aspect ratios, the same nine
referenceAssetIds, the same audioEnabled toggle, the same 4,000-character prompt ceiling — so
the five Seedance formulas apply unchanged.
Two differences worth knowing before you pick it. It renders 480p and 720p only — no
1080p, no 4k, on either provider — so a resolution carried over from a 2.0 workflow is a
rejected request rather than a downgrade. And it is the dearest model on the API at the same
length; thirty seconds of it is the most expensive single call this API takes. Price it, like
everything else, at POST /v1/estimates.
"Make a 30-second Seedance 2.5 ad — the founder walks through the workshop and explains why they built it"
A longer clip wants more beats, not slower delivery. If the script only fills 15 seconds, render
15 seconds on seedance-2.0, which is cheaper at that length.
"Give me a fast 8-second vertical clip of the product on a kitchen counter, no dialogue"
omni-flash carries a 20,000-character prompt ceiling, the roomiest of any video model here
against 4,000 everywhere else, which is what makes long structured briefs possible. Its grids are narrower than Seedance's — durations 4/6/8/10,
aspect ratios 9:16 or 16:9 only — and it takes no reference images. Prompt craft in
shared/skills/gemini-omni-flash/prompting/guide.md,
which is Google DeepMind's own guide with the parts this API cannot reach marked as such.
POST /v1/images usually hands the finished images back in the response body. A render still
going after about 105 seconds answers running with no images instead (API 2.39.0): the skills
poll GET /v1/generations/{jobId} for it and never resubmit. Up to 4 images per call; reference
images are capped per model: 4 on each of the three GPT models, 14 on nano-banana-pro, 8 on
reve-2.1, 10 on each Seedream 5 model (seedream-5-lite, seedream-5-pro, API 2.39.0).
gpt-image-2.5-sunburst: the API default when model is omitted. Slower than Flare, and
it keeps fine detail and labels exact.gpt-image-2.5-flare: fast, for most images.gpt-image-2: heavy typography and mimicked UI. Still live, still offered, unchanged.nano-banana-pro — photoreal people and products in a scene; holds a character's identity
tightest across a reference batch.reve-2.1 — a different look on the same still, or a second opinion.The three GPT models share one grid: the same six aspect ratios, the same 32,000-character prompt
ceiling, the same cap of 4 reference images, the same sourceAssetId edit arm, and the same price
per image. What differs is speed against fidelity, so switching between them changes nothing in a
request body but the model value.
"Create a new AI influencer — 22-year-old with freckles, golden-hour kitchen lighting" · "UGC selfie of Sofia holding the product in her bedroom" · "Recreate this influencer's look from this photo"
Character sheets, influencer recreation, UGC product selfies and product-showcase stills live in skills/novoads-api/prompting/prompt-library/. The standard flow is still-first: generate the still, get it approved, then animate the approved frame on Seedance. Stills are cheap to iterate; video is not.
Every returned image gets a QA look — hands, fingers, faces, merged objects, garbled text. A defect is regenerated with a corrected prompt, capped at 2 retries, and the extra credits are reported at the end.
"Make me an Apple Notes-style ad for my product" · "Generate a Forbes editorial ad" · "Clone this comparison-table ad as a template"
A three-skill family over a shared library of 40 validated prompt templates — Apple Notes lists, editorial hero, fake Google search, comparison tables, sticky-note flatlays, Slack threads, ChatGPT-conversation ads, iMessage screenshots, magazine covers, billboards, museum exhibits, weather UI, scratch-off tickets, founder letters, dating-app cards, and more.
chatgpt-image-ad — typography / UI mimicry, on gpt-image-2nano-banana-image-ad — photoreal / lifestyle / multi-reference, on nano-banana-proclone-image-ad — reverse-engineer an existing ad into a new library entry; asks which backend to validate against at Phase 1 (gpt-image-2, nano-banana-pro or reve-2.1) and can cross-validate against another at Phase 8Read shared/skills/image-ad-prompting/OVERVIEW.md
first — it holds the decision tree, the per-backend aspect-ratio matrix, and the standard
generate / clone workflows. Output is image files; publishing is the separate meta-ad-builder
skill.
| Pipeline | Shape | Guide |
|---|---|---|
| Pixar-style 3D animated ad | The storyboard flow, and the only one: a researched product read → cast sheet → per-beat gpt-image-2 stills, each chaining the previous one's assetId to hold the character → seedance-2.0 per beat → POST /v1/voiceovers into the gaps → music bed → captions → local ffmpeg assembly. Carries the genre's beat formulas: an anthropomorphized problem character that speaks the pain in first person, a protagonist reveal, a mascot mechanism-of-action scene, a composited end card. Gated: the board is reviewed before the clips are paid for. Every animated ask routes here, a 15-second one included — there is no single-call tier, so ffmpeg is required | pixar-ad · formulas in references/formulas.md |
| Claymation / stop-motion clay ad | The 8-beat narrative arc (setup → inciting moment → social validation → quiet despair → clay infographic → discovery → transformation → resolution), a 5-beat short, hand-sculpted clay style lock, per-beat material detail, and a local ffmpeg + Whisper read of a reference video as a second entry for recreating a clay ad you were shown | claymation-ad · formulas in references/formulas.md |
| Still → motion graphic | One seedance-2.5 call off startImageAssetId, where the image you hand over is the shot rather than a reference: motion vocabulary for seven image classes (UI, hero, flat-lay, key art, collage, product, character), a timed-beat prompt template, and the clauses that hold text pixel-identical and pin regions still. The judgement is what moves, in what order, and what is absent at 0.0s | image-to-motion |
| YouTube thumbnails |
"Reverse-engineer this video into a reusable Seedance template" · "Clone this video ad for our product" · "Pull the ads our competitor is running into a swipe file"
clone-image-ad.
A sweep that finds nothing is a result, not an apology.seedance-2.5 reaches 30s in one call, so some sources that
used to need two clips now need one."Publish this approved creative as a paused Meta ad"
meta-ad-builder takes a finished file and uploads it
through the Meta Marketing API. Every ad is created PAUSED — you launch it yourself in Ads
Manager. It can also pull your top-spending ads and competitor ads to inform copy. Auth via the
META_* rows in .env.
Need an account? Plans start at $15/month (Starter, 200 credits), and every plan can generate through the API. Current prices: novoads.ai/en/pricing (as of 2026-10-08).
There is no price list in this repo, on purpose. A stored rate goes stale silently, and a quote that disagrees with the invoice is worse than no quote at all.
Instead, before anything is generated, the agent calls POST /v1/estimates and shows you what came
back: the credits for that exact configuration, your balance, and — when the batch would exceed the
balance — how short you are and where to top up. You approve the number, then it generates.
The estimate charges nothing, and what it does not do is worth stating:
warnings array of craft notes
({rule, message}) — verified live 2026-08-04. POST /v1/videos and POST /v1/images do not
run these rules and return no such field. Nothing in it can refuse or reprice a call, so a
weak prompt is still priced, charged and rendered exactly like a strong one, and the warnings
are substring matches that do false-positive. Read them, judge each against your prompt,
and never paste in a suggested fix that does not fit. The prompt libraries in this repo remain
the real quality gate — which is why the skills treat them as mandatory reading rather than
reference material.content_policy. Nothing is charged when it is.GET /v1/models carries each model's live grid and its price for a representative output if you
want to compare models yourself.
Every model below is live on api.novoads.ai/v1, and GET /v1/models is the list of record. Grids below come from GET /v1/models. That endpoint
is the current answer, this table is a map.
| Model | Kind | Duration | Aspect ratios | Prompt cap | Notes |
|---|---|---|---|---|---|
seedance-2.0 | Video | 4–15s, any integer | 16:9 9:16 1:1 4:3 3:4 21:9 | 4,000 chars | The flagship. Native audio + lip-sync, mutable with audioEnabled: false. startImageAssetId or up to 9 referenceAssetIds, never both. Fleet range 3–8 min; one render here came back in ~171s. |
seedance-2.5 | Video | 4–30s, any integer | same as above | 4,000 chars | The only model here that renders past 15s. Otherwise 2.0's shape — audio toggle, 9 reference images, six ratios. 480p / 720p only, no 1080p or 4k. Dearest per second; nothing has timed one, so quote the wait as unknown. |
seedance-2.0-mini | Video | 4–15s, any integer | same as above | 4,000 chars | Same grid, same formulas, half the price, back in 2–3 min. The drafting tier. |
omni-flash | Video | 4 6 8 10 | 9:16 16:9 | 20,000 chars | Reference images and one reference video (API 2.30.0 on). Defaults to 9:16 and 8s. Best for long structured briefs and silent b-roll. |
veo-3.1 | Video | 4 6 8 | 9:16 16:9 | 4,000 chars | Start frame only, no reference images. Defaults to 8s — the one model that defaults to its own ceiling. Shot-evolution prompting. Unmeasured here: no render time on record. |
sora-2 | Video | 4 8 12 | 9:16 16:9 |
Image calls take numImages 1–4. Two of their limits are per model and neither is one
number across the set. The referenceAssetIds cap is 14 on nano-banana-pro, 8 on
reve-2.1, 4 on each of the three GPT models, 10 on each Seedream 5 model. The prompt ceiling is 50,000, 4,000 and 32,000 in
that same order, split apart by deployed spec 2.16.0 from what used to be 4,000 everywhere. So a
prompt written for one image model may be too long for another, and switching to reve-2.1 for a
second opinion is the case that hits it. The three GPT models are the case that does not, because
they share one grid. Images have no start-frame concept. Videos are
asynchronous (202 + jobId, poll to a terminal status); images come back in the response body,
or answer running and are polled the same way.
audioEnabled (default true) is on the three Seedance variants and, since API 2.38.0,
kling-v3-pro; send false for a clip meant to run silent. omni-flash, veo-3.1 and sora-2 are
strict and 400 on it, as does POST /v1/estimates for every model: it does not move the price.
resolution is on seedance-2.0, seedance-2.5, and omni-flash where GET /v1/models lists
more than one tier for it, and it is the one output-shape field
that moves the price: each tier is its own credit schedule, not a surcharge on the one below it.
Since 2026-08-07 480p costs roughly half of 720p rather than the same, which makes it a real
draft tier on both Seedance models. seedance-2.5 stops at 720p. omni-flash may list 360p,
720p and 1080p, plus 4k where the server publishes it: read the live list, never assume 4k.
Kling 3.0 is on this API as kling-v3-pro since API 2.38.0, where GET /v1/models lists it:
any integer 3 to 15 seconds, 16:9, 9:16 or 1:1, audio on or off, text or a start frame, and
since 2.44.0 an end frame beside the start frame. Its
prompt library in skills/novoads-api/prompting/prompt-library/ is vendor craft; the request body
comes from the skill's reference.md. There is no b-roll or scene endpoint: a silent omni-flash
or Seedance clip is the b-roll path.
Also on the API since 2.40.0 to 2.44.0: the dashboard's image to ad, product to ad and upscale
tools on one photo (preset on POST /v1/images), background removal on a video up to 30 seconds
(POST /v1/background-removals), your product in a library actor's hands on the Seedance family
(productSwap), and a library actor moved by a clip you upload (POST /v1/videos/animate-actor:
MP4 or MOV, with or without the clip's own sound).
Each is quoted by POST /v1/estimates before anything is spent.
| Path | What it does |
|---|---|
skills/novoads-api/ | The spine. SKILL.md is the router: decision tree, the two gates, the full call sequence, error branching. reference.md is every endpoint, field, limit and status code, plus the dated discrepancy list. Carries the Seedance formulas, the image/character libraries, and the analyze-video + clone-video-ad sub-workflows. |
skills/chatgpt-image-ad/ | Static Meta image-ad creatives on gpt-image-2 (typography / UI mimicry). |
skills/nano-banana-image-ad/ | Static Meta image-ad creatives on nano-banana-pro (photoreal / lifestyle). |
skills/clone-image-ad/ | Turn an existing ad image into a reusable library entry. Backend chosen at Phase 1. |
skills/generate-youtube-thumbnail/ | 5 CTR-tested thumbnail formulas with bounded batch generation. |
skills/spy-competitor-ads/ | Sweep a competitor's live Meta ads into a local swipe folder, one priced sweep per competitor, ranked by how long each creative has run and how many audiences it runs against. fans the sweeps out and downloads the media before the CDN links die; and write the delivery and the contact sheet. It files ads rather than rebuilding them. |
Drop images into references/ and the agent finds them before asking you for anything:
references/influencers/ — faces and bodies to recreate, plus saved character sheetsreferences/products/ — product photos for showcase and UGC workflowsreferences/aesthetics/ — mood boards, lighting and style referencesThe folder is gitignored, so the files stay on your machine. Uploads are minted through
POST /v1/uploads and the resulting assetId is durable and reusable forever — upload the
product shot once and reuse it across every iteration and every model, which is what makes drafting
on Mini cheap. (The presigned upload URL expires in 900 seconds; the assetId does not.)
MASTER_CONTEXT.md is your workspace's living memory — created by setup, gitignored, read at the
start of every session and written back to. It holds:
meta-ad-builderIt holds no prices, deliberately. See what it costs.
Canonical sources live under skills/ and shared/skills/. After editing any file there:
./scripts/sync-skill.sh
That copies changes into .claude/skills/ and .cursor/skills/, which are generated and
gitignored. The SessionStart hook runs it automatically when Claude Code opens the folder.
At session start, the banner hook runs git fetch origin (10 second ceiling, never blocks). If
your clone is behind it lists the pending commits and points at the update command. The banner only
notifies. Applying anything is opt-in, and by default nothing lands on your clone unless you say so.
To update, run ./scripts/update.sh. Not git pull, and the difference is not cosmetic. A
plain pull silently deletes a gitignored .env the moment upstream starts tracking that path, and
git pull --autostash can exit 0 having left <<<<<<< conflict markers inside a skill file,
which your agent then reads as instructions. update.sh copies .env aside before it touches the
tree and restores it afterwards, including when you interrupt it; decides whether to stash by
reading git status --porcelain, so an untracked collision counts too; fast-forwards only; and if
restoring your work conflicts, rolls the tree back and leaves that work in a stash it names for you.
It never leaves a conflict marker behind.
Three more things it does that a pull does not:
main is
the least reviewed code in the repo, and this pack runs shell scripts on your machine. --fresh
takes the tip instead, and says so when it does..claude/skills/ and .cursor/skills/ match what just landed. Neither of those failing undoes
the update.STATUS= line. Exit 0 means the clone is in a usable state.
A blocked status exits 1 and leaves the clone exactly as it was found, with the decision
yours. An interrupted run can exit nonzero too, and promises something narrower: .env restored
and no merge half-applied. The full vocabulary is in AGENTS.md, for the agent
reading it.If an update goes wrong, ./scripts/update.sh --rollback puts the clone back on the commit it
was on, .env and all. It refuses on a dirty worktree rather than steamrolling what you were doing.
The novoads-update skill is the same update with a conversation around it. Ask your agent to
run it and it offers four answers: update now, always keep me up to date, not now, or never ask
again. "Not now" snoozes the banner on an escalating ladder (a day, then two, then a week), and a
genuinely new version resets it. Snoozing quiets the nag only: the skill and
./scripts/update.sh both still run whenever you ask them to.
Auto-apply is opt-in and stays that way. "Always keep me up to date" is a standing grant to run
upstream code on your machine, so it is never on by default and no agent may switch it on for you.
Your answer to that question is what writes auto_apply=on. Once it is on, the hook applies updates
at session start without holding the session up, never takes the tip, tries at most once an hour,
and asks the session to reload its skills when something lands, where the harness supports that.
Turning the whole thing off. .update-state/config takes update_check=off, which silences the
banner's fetch and the auto-updater together, and NOVOADS_PACK_NO_UPDATE_CHECK=1 does the same
from the environment. ./scripts/update.sh still runs when you ask it to, because a kill switch
that strands the manual path is not a kill switch. auto_apply defaults to off.
What survives an update. Everything your sessions write is gitignored and left alone: .env,
MASTER_CONTEXT.md, references/, outputs/, generated/, prompts/, iterations/, and
logs/*.jsonl (latency and failure history across sessions is worth keeping, which is exactly why
the log never records keys, presigned URLs, or prompt text). .env gets belt and braces on top of
that, backed up and restored around every merge, because being gitignored is precisely the
protection that failed.
Customizing a shipped skill file is the one thing that collides. Those files are tracked, so
your edits are real diffs and every update has to stash and restore them. If a customization is
meant to last, keep the customized copy in local-skills/ at the repo root and point your agent at
it there, rather than editing under skills/. That directory is gitignored, so nothing you keep in
it is ever a diff to stash. One caveat if you would rather install your copy into .claude/skills/
directly: give it a different name from the pack skill. The session sync deletes and re-copies
every live pack skill name each time it runs, so a copy sitting under the same name is overwritten.
Everything above assumes you cloned the repo. If you installed through the skills CLI instead:
npx skills add novoads/agent-skills#v1.0.0, naming the
latest release tag (v1.0.0 today). Tags work. 40-character commit SHAs do not, because the CLI
installs by cloning a branch or a tag. A pinned install moves only when you point it at a newer
tag. Releases are tagged vX.Y.Z and written up in CHANGELOG.md.npx skills update, and read this before you do. The reinstall is rm -rf on
the skill folder followed by a fresh copy: no backup, no prompt, no diff. A file you added
inside the skill folder is deleted, and an edit you made to SKILL.md is reverted. Copy anything
you customized out of the folder first. The command is also undocumented on skills.sh and has no
notifier, so nothing will tell you an update exists.broll-overlay, caption-video,
meta-ad-builder and music-mix live under shared/skills/, which the CLI does not walk, so
they are invisible to it. That is a known limitation, deliberately unchanged for now: clone the
repo if you want them.X-Novoads-Pack-Version header the API returns on /v1
calls. If a newer pack exists it mentions it once. It never blocks a call and never nags..env is gitignored and written chmod 600. Never commit it.MASTER_CONTEXT.md is gitignored — it holds your product IDs and workspace data.MASTER_CONTEXT.md. If you
paste a key into a chat, rotate it — transcripts get shared.404, not 403: "not found" and "not yours" are deliberately
indistinguishable.meta-ad-builder is PAUSED. Nothing goes live without you.GET /v1/openapi.json — the machine-readable spec.
Public, no key needed, and the authority whenever a file in this repo disagrees with it.Everything above needs a POSIX shell, curl, and a key in .env. If you have none of that
(claude.ai on the web, or Windows with no WSL and no Git Bash), Novoads also runs a hosted
connector at novoads.ai/mcp. It is a separate surface, not a
way to run this pack: it carries none of the skills, prompt libraries or formulas in this repo,
and it quotes costs in different units. The skills in this repo never use it. They stop and
ask for the API key instead, even in a session where the connector is already connected.
| Model | Guide |
|---|---|
| Seedance 2.0 | ByteDance's published Seedance prompting platform, summarized in seedance-2.md |
| Omni Flash | Google DeepMind — Gemini Omni prompt guide, scoped for this API in gemini-omni-flash |
| Nano Banana | Google Cloud — Nano Banana |
| ChatGPT Image 2 | OpenAI image guidance, summarized with model-specific limits in chatgpt-image-ad |
Point your assistant at AGENTS.md — it carries the auth shape, the async-video / sync-image distinction, the cost policy, and the skill map.
Need an account? Plans start at $15/month (Starter, 200 credits), and every plan can generate through the API. Current prices: novoads.ai/en/pricing (as of 2026-10-08).
GET /v1/openapi.json when a file here disagrees with it.MIT. Copyright (c) 2026 NOVO SpA. Copyright (c) 2026 Caleb Kruse / Kruse Media LLC.
seedance-2.0You type: Animate this scratch-off ticket ad — a coin scratches the foil and the reveal happens. Every word stays frozen.The prompt the skill wroteLocked-off overhead flat-lay of a printed Liquid Death scratch-offticket on grey painted concrete, a US quarter resting flat beside itslower-right corner. Photographic, not illustrated. A silent motiongraphic with no spoken dialogue, no voice-over and no music.CAMERA: the camera is locked off and never moves: no pan, no tilt, nozoom, no push-in, no orbit, no drift. Lighting is constant: same softkey, same soft shadows, no light sweep, no flicker, no exposure change.The reference image is the exact composed state: every colour, shadow,layout position and printed glyph matches it precisely. Framing keepsthe ticket and coin at their exact positions and relative sizes; nothingon the ticket is cropped or re-laid out. The ticket never moves, shifts,rotates, bends or lifts.TEXT: all printed text stays perfectly intact and pixel-identical to thereference at every frame, same faces, weights, sizes, navy and goldcolours and positions, correctly spelled: "LIQUID DEATH PRESENTS", "No.012777 / STILL ARTESIAN", "SCRATCH TO MURDER YOUR THIRST", "COLD","MOUNTAIN", "ARTESIAN", "TALLBOY", "WIN", "MATCH ALL FIVE = ONE COLDCAN", "NO LOSING TICKETS. EVERY CAN IS A WINNER.", "liquiddeath.com",and on the small can photograph "Liquid Death" and "MOUNTAIN WATER".Text is never redrawn, re-lettered, re-spaced or re-coloured, and neverfades, scales, slides or animates. The gold skull, the five navy iconsand the can photograph are likewise pixel-identical and never redrawn.… 3,962 characters total |
| Claymation ad. A five-beat clay short: cast sheet, per-beat stills, per-beat clips, voice-over, music bed, a composited end card, captions burned locally.Made with claymation-ad.Rendered 2026-08-12 UTC. Demo creative. | You type: Make a claymation ad for Liquid Death — a bored office worker's grey day until the can shows up. No eco talk.The prompt the skill wroteHand-sculpted stop-motion clay look. Plasticine characters with visiblefingerprint impressions and sculpting-tool marks, matte clay surfaceswith subtle micro-bumps, slightly asymmetric features, painted-on orsculpted eyebrows. Real knit-fabric clothing with visible wool weave andstitch lines, wooden and ceramic miniature-set props with hand-paintedfinishes. Practical miniature-set interior lighting, shallow macro depthof field, soft photographic bokeh. Subtle imperfection in every surface.Vertical 9:16 composition.Vertical 9:16, animating the character in the reference image. grey woolcardigan Frank, a man in his late 50s with thinning side-parted slate-grey plasticine hair in carved ribbon-strands and an oversized sculptednose, stands in a miniature clay office cubicle set with grey feltpartition walls in visible fibre texture, a hand-painted wooden desk inflat grey, a chunky beige clay desktop computer, a wire tray of hand-cutpaper, a hand-thrown ceramic mug and a small clay desk lamp facingcamera, the set behind him in saturated hand-painted colour.From zero to six seconds a small closed-mouth smile arrives on his faceand he lifts the tall Liquid Death can to chest height with the labeltoward camera, one unhurried gesture.Camera: locked medium shot at chest height, very subtle handheld micro-drift, no pan, no zoom. The desk surface fills the lower third of theframe and stays clear of props throughout, fully rendered to the bottomedge of the frame.… beat 5 clip prompt, one of five. 3,807 characters total |
| UGC selfie ad. One 15-second Seedance call: four jump cuts, and the spoken script and its lip-sync rendered in the same call as the picture.Made with novoads-api.Rendered 2026-08-12 UTC. Demo creative. | You type: Make a 15-second UGC video ad for Liquid Death — a woman in her kitchen explains why she switched. Match Liquid Death's brand voice.The prompt the skill wrote15 seconds UGC style honest review video, filmed on smartphone at arm'slength, grey morning light through the kitchen window blinds, casualhandheld selfie angle framed tight from the chest up. Grey hoodie woman:late 20s, dark hair in a messy claw clip, natural skin with visiblepores across her nose and slight undereye shadows, wearing a plainunprinted grey hoodie with no writing or graphic on it. Her smallapartment kitchen, close behind her and mostly out of focus — a plainwhite coffee mug, a wooden cutting board with a cut lime, a dish rack ofclean plates. The setting stays the same throughout: the same kitchencounter, the window blinds as the only light source, the same plain greyhoodie and the same claw clip. Only the framing changes between cuts,and every cut stays close — her head and shoulders fill the frame andthe can is never further from the lens than her own face.The video opens on a tight chest-up selfie framing — grey hoodie womanlooking flatly into the lens, holding the @Image1 tall white and navyLiquid Death mountain water can up beside her chin, close to the camera:"I switched to water. My family staged an intervention."Quick jump cut — grey hoodie woman closer still, the @Image1 can fillinghalf the frame height with its front face square to the lens: "It'scalled Liquid Death. It's water. Terrifying."Quick jump cut to a tight framing — grey hoodie woman takes one flatunimpressed sip from the @Image1 can, the can still large in frame:"Tastes like water. That's the whole review."Quick jump cut — grey hoodie woman holds the @Image1 can up beside herface, both filling the frame: "Murder your thirst. Or don't. Whatever."… 3,404 characters total |
| Clone of an existing ad. One of our own skincare ads read locally with ffmpeg and Whisper, then rebuilt for a different product. The clip plays source left, clone right.Made with clone-video-ad.Rendered 2026-08-12 UTC. Demo creative. | You type: Clone this video ad for Liquid Death: references/sources/our-own-ugc-ad-source.mp4The prompt the skill wroteHandheld selfie take on a phone in one hand, one unbroken take, no cuts,framing drifting as her arm moves. A woman in her late twenties, dampdark hair half pulled back, bare face, visible pores, freckles acrossher nose, white waffle bathrobe, bright bathroom, mirror behind her,blown-out window at camera-left.[00:00] Chest-up, she looks into the lens, flat little smile, and says:"Okay, my thirst has genuinely never been this dead."[00:04] She raises the @Image1 tallboy can into frame beside her jaw andsays: "Just finished my morning water and I'm kind of obsessed."[00:07] She slowly turns the can toward the lens, front label to camera,and says: "Nothing sweet, nothing added, just water and aluminum."[00:10] She takes one slow sip and lowers the can to her collarbone,saying: "Honestly, it's the only thing in my routine that isn't lying tome."[00:13] Back to chest-up, the can still at her collarbone, deadpan half-smile, she says: "All right, ready to murder some thirst."The can from @Image1 stays visually unchanged in every shot, its labelsharp and identical to the reference image, its text unchanged and fullylegible, with no extra words, numbers or lettering anywhere on the can.Robe and damp hair unchanged throughout. The tone is dry, warm and flat;she talks quickly, running sentences together like a voice note, everyword landing clearly. Documentary handheld, photorealistic, naturalphone quality, no colour grading, one side of her face in shadow, sounddirect from the phone mic, room echo. Vertical 9:16.[1,555 characters, shown whole.] |
5 CTR formulas (peace-sign branding, real-vs-AI, terminal flow, reaction shock, before/after split) on nano-banana-pro, likeness locked with face references |
| generate-youtube-thumbnail |
| Burn captions onto an MP4 | Whisper transcript → reading phrases → captions-only HTML on a transparent background → ffmpeg alpha overlay. The manual caption path, for a style outside the 30 presets or wording you need to hand-correct. Out of band: no API call, no credits | caption-video |
| Overlay b-roll cutaways on a finished MP4 | Whisper transcript → EDL of overlay windows (file, start, end, covers) → validate → ffmpeg overlay → verify duration, audio and every window. Base audio runs untouched, duration never changes. Local ffmpeg, no credits (the cutaway clips themselves are generated first, and those are charged) | broll-overlay |
| Lay a music bed under a finished MP4 | Track trimmed and faded to the exact cut length, ducked under the voice, picture stream-copied so burned captions survive bit-exact. Mixing is local ffmpeg and free; generating a track is one priced API call on the same key (two tracks per request), or bring your own file | music-mix |
| 4,000 chars |
| Start frame only, no reference images. Measured with no leading silence where Seedance front-loads 3–5s, and ~123s to render. Coarse grid: no 6s, no 10s. |
kling-v3-pro | Video | 3–15s, grid in GET /v1/models | 16:9 9:16 1:1 | read GET /v1/models | Kling 3.0 (API 2.38.0). One resolution; audio on or off with audioEnabled. Text, or startImageAssetId as the first frame and, since API 2.44.0, lastFrameAssetId as the last. No referenceAssetIds. |
gpt-image-2.5-sunburst | Image | — | 1:1 4:5 2:3 9:16 16:9 21:9 | 32,000 chars | The API default: omit model and this renders. Slower, keeps fine detail and labels exact. Can answer running: poll it. |
gpt-image-2.5-flare | Image | — | same six | 32,000 chars | Fast, for most images. Can answer running: poll it. |
gpt-image-2 | Image | — | same six | 32,000 chars | Typography and UI mimicry. Unchanged by the 2.5 arrivals. Can answer running: poll it. |
nano-banana-pro | Image | — | 10 ratios incl. 3:2 4:3 5:4 | 50,000 chars | Photoreal people and products; strongest identity lock across references. The most prompt room on the API. |
reve-2.1 | Image | — | same 10 ratios | 4,000 chars | Third look / second opinion on a still. The one image model still on the old tight budget. |
seedream-5-lite | Image | n/a | read GET /v1/models | read GET /v1/models | Seedream 5 Lite (API 2.39.0). Up to 10 referenceAssetIds. Can answer running: poll it. |
seedream-5-pro | Image | n/a | read GET /v1/models | read GET /v1/models | Seedream 5 Pro (API 2.39.0). Up to 10 referenceAssetIds. Can answer running: poll it. |
scripts/sweep.pyskills/analyze-video/ | Deconstruct a reference video into a reusable Seedance 2.0 formula file, written into the prompt library: structure, pacing, camera work, edit style and tone, as variables anyone can plug a new product into. Frames come from ffmpeg and the transcript from Whisper, both local. The output is a formula, not a single prompt. |
skills/clone-video-ad/ | Clone a video ad end to end for a different product: reads the source's style, pacing, dialogue and tone, adapts it into a Seedance 2.0 prompt, prices it, renders it, and diffs each clip's transcript against the approved script. The deliverable is the whole ad, not its opening and not a template. |
skills/change-voice/ | Replace the voice in a finished ad with one from the catalog, keeping the timing so the lips still match. Casts by measuring the source voice against auditioned candidates instead of reading labels, refuses a source with no speech before anything is charged, and fences the sound effects so they survive from the original track. scripts/ holds the three local steps — the speech check, the acoustic match and the assembly with its loudness verification; evals.md records the acceptance run that reproduced a hand-approved re-voice from the public API alone. |
skills/image-to-motion/ | Animate a finished still as-is. Motion vocabulary for UI, marketing hero, flat-lay, key art, collage, product and character images, plus the prompt clauses that pin camera, timing, frozen regions and text fidelity, so printed words stay legible instead of being redrawn. |
skills/pixar-ad/ | A product URL or photo → a finished stylized 3D animated ad, built as a reviewed storyboard: one clip per beat, narrator voice-over layered into the gaps, then local assembly. Stills chain by assetId, so holding one character across separately-rendered beats needs no re-upload. Every Pixar-style ask lands here, at any length. references/formulas.md holds the four genre roles with a variable table and a worked still and clip prompt for each; evals.md the scored cases; references/NOTICE.md the upstream MIT notice for the craft it adapts. |
skills/claymation-ad/ | The clay sibling. Same pipeline as the Pixar skill; what it owns is the hand-sculpted clay look and a longer, quieter arc built on a named protagonist. references/formulas.md holds the eight beats, the subject-lock fragments and the clay QA checklists; evals.md the clay-specific cases on top of the Pixar skill's; references/NOTICE.md the upstream MIT notice. |
shared/skills/image-ad-prompting/ | Shared brain for the image-ad family: OVERVIEW.md, the 40-template library, safety suffixes, entry format. |
shared/skills/gemini-omni-flash/ | Prompting guide for omni-flash, scoped to what this API actually exposes. |
shared/skills/caption-video/ | Out-of-band caption burn-in for any finished MP4, and the manual fallback to POST /v1/captions. SKILL.md routes; prompting/guide.md carries the recipe. |
shared/skills/broll-overlay/ | Overlay b-roll cutaways on a finished MP4 — local ffmpeg, no credits. Validates the EDL, renders atomically, and verifies duration, audio and every window. |
shared/skills/music-mix/ | The last step of the video pack: a ducked music bed under a finished cut. Mixing is local ffmpeg and costs nothing; the track itself comes from POST /v1/music on your Novoads key, or from your own file. evals.md holds the six scenarios, scripts/test_music_mix.py implements the five mixing ones in 15 executable cases. |
shared/skills/meta-ad-builder/ | Publish finished creatives as paused Meta ads. |
scripts/setup.sh | One-time setup. Validates the key before writing it. |
scripts/check-novoads-env.sh | Connectivity check that names the failure. |
scripts/sync-skill.sh | Copies skill edits into .claude/skills/ and .cursor/skills/. |
shared/scripts/check-context.sh | The SessionStart banner. |
MASTER_CONTEXT.template.md | Template for your workspace memory. Setup copies it to MASTER_CONTEXT.md (gitignored). |
references/ | Your reference images — gitignored, local only. |
logs/ | Per-call audit log. Latency, config, creditsCharged after the fact. Observability, never a pricing source. |
AGENTS.md | Entry point for non-Claude assistants. |