agentleFS
indranilbanerjeeindranilbanerjee/socialforge/skills/compose-creative/SKILL.md

compose-creative

Skill43 starsChanged 4 months agoMITView on GitHub

Compose just the creative (image or video) for a calendar post, in four modes. \"make the visual for this post\"

The file

We split this skill into the rules it gives an agent

12 rules. About 0 are common, 9 are distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈9

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Remove background from brand asset (rembg)

    line 23
  2. Distinctive:

    Add shadow/reflection for natural placement

    line 26
  3. Distinctive:

    Add text overlay + logo

    line 27
  4. Distinctive:

    Verify core subject preservation

    line 34
  5. Distinctive:

    No brand asset composited.

    line 38
  6. Very specific:

    Read from scripts/generate_image.py, scripts/edit_image.py and scripts/generate_video.py.

    line 54
  7. Very specific:

    If any prerequisite is missing: "Run /socialforge:match-assets first — creative production needs asset matching results."

    line 74
  8. Distinctive:

    No image generation happens here.

    line 114
  9. Distinctive:

    After the user selects their preferred image:

    line 133
  10. Distinctive:

    After the user picks the final video, post-processing runs before saving:

    line 172
  11. Distinctive:

    Background music: If the video has no audio (sound=False in the clip request), user is asked whether to add background music (optional).

    line 175
  12. Very specific:

    When processing all posts via /socialforge:generate-all, the staged approval flow uses group-based approval to avoid per-post bottlenecks:

    line 185

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

/socialforge:compose-creative — Creative Production Engine

Script location. If your host does not set ${CLAUDE_PLUGIN_ROOT}, the scripts are in this plugin's scripts/ folder, next to skills/. Run them with Python 3.10 or newer: python, or python3 where python is not found (macOS, many Linux systems).

The core production skill. Takes asset matching results and produces visual and video assets for each post according to its assigned creative mode, using a staged human-in-the-loop approval flow.

Context efficiency

Asset-heavy skill. Grep before Read the asset catalog (${CLAUDE_PLUGIN_DATA}/socialforge/brands/<brand>/asset-index.json) — never list the asset directory. Reference generated images / videos by path, not by loading metadata. Brand profile loads once per session.

The 4 Creative Modes

MODE 1: ANCHOR_COMPOSE

Brand asset is the untouchable center. AI generates scene around it.

  1. Remove background from brand asset (rembg)
  2. Generate surrounding scene via AI using brand style references
  3. Composite asset onto generated scene (Pillow)
  4. Add shadow/reflection for natural placement
  5. Add text overlay + logo
  6. Resize per platform

MODE 2: ENHANCE_EXTEND

Brand asset is the foundation. AI modifies periphery only.

  1. Feed real image to AI edit endpoint
  2. AI extends/enhances while preserving core subject
  3. Verify core subject preservation
  4. Add overlay + resize

MODE 3: STYLE_REFERENCED

No brand asset composited. Style reference photos guide AI generation.

  1. Load 2-8 brand style reference images
  2. Construct 5-layer prompt (brand identity, post context, creative direction, image rules, technical)
  3. Feed references + prompt to AI generation
  4. Quality review — does output match brand DNA?
  5. Add overlay + resize

MODE 4: PURE_CREATIVE

Full AI generation with only text prompt + brand colors/mood.

  1. Construct prompt from brief + brand-config visual style
  2. Generate (text-only, no reference images)
  3. Quality review
  4. Add overlay + resize

Reference images and keyframes — what the scripts actually do

Read from scripts/generate_image.py, scripts/edit_image.py and scripts/generate_video.py. This skill promises only what those scripts implement.

InputHow to pass itWhat is true today
Style references for a new image (STYLE_REFERENCED)generate_image.py --references <path> [<path> ...] — the first 14 are readSent to the primary image provider only. The fallback providers receive the prompt and aspect ratio, not the references: when the result carries fallback_from and references were supplied, it also carries references_used: 0, references_dropped: <n> and a references_note — the image is not style-referenced. Tell the user, and fix the primary provider's credentials rather than accepting a reference-less image as a style-referenced one.
References alongside an image being edited (ENHANCE_EXTEND)edit_image.py --image <src> --instruction "..." --references <path> ... — first 14Supported. There is no fallback chain for edits. (generate_image.py --edit takes no references.)
First frame for videogenerate_video.py --image <path>Supported by every video provider in the chain; one of them requires it. See /socialforge:generate-video.
Last frame for videogenerate_video.py --last-image <path> (with --generate-video)Sent to the kling rung as the clip's end image; no other rung takes one. The result's video.last_frame_used says whether it was sent — false (with a last_frame_note) means the clip was not steered to the approved last frame. See /socialforge:generate-video.
Reference images for videononeNot wired through generate_video.py — no flag exists. See /socialforge:generate-video.

Two caveats from the code: file type is set from the extension (.jpg/.jpeg as JPEG, everything else as PNG), so pass JPEG or PNG and convert WebP first; and references_used is the number of files actually read and sent, not the number of paths passed. When it is lower than what you passed, the result says why: references_missing lists the paths that do not exist (they are not sent, and there is no error), references_over_limit counts the paths past the 14-file limit, and references_dropped plus references_note mean a fallback provider made the image. Read those fields before treating an image as style-referenced.

Prerequisites

  • asset-matches.json must exist (generated by /socialforge:match-assets -> match_assets.py)
  • calendar-data.json must exist (generated by /socialforge:parse-calendar)
  • brand-config.json must exist for active brand
  • cost-log.json initialized (via status_manager.py --action init-month)
  • Valid credentials for the image provider (Vertex AI or a Gemini API key, alias latest-image-balanced-google) and the video provider (WaveSpeed, alias latest-video-wavespeed; or Vertex AI for Veo) via credential_manager.py. Which model each alias resolves to today: python "${CLAUDE_PLUGIN_ROOT}/scripts/generate_video.py" --list-models.

If any prerequisite is missing: "Run /socialforge:match-assets first — creative production needs asset matching results."

Quote, then go (before any paid call)

Generation spends provider credits, so the first paid call waits for a quote and an explicit go. This skill states no price and the model registry stores none: price_book.py is the only source, and it refuses rather than guesses.

  1. List what is about to be generated: for each paid call, the registry alias (resolve_model.py --alias <alias> gives the current model id), the provider, and the units (images, or seconds of video, plus any option that changes the price, such as synchronised audio). For an image post that is the 2-3 variants of Stage 3; for a video post it is both keyframe rounds and the clip.
  2. Quote it:
python "${CLAUDE_PLUGIN_ROOT}/scripts/price_book.py" --action quote-batch --items '[{"model":"<resolved model id>","provider":"<provider>","units":<n>,"label":"<post id and stage>"}]'

A single item can use --action quote --model <id> --provider <provider> --units <n>. If the quote exits non-zero or lists a blocked item, stop: run /socialforge:price-check to look the missing price up, then quote again. 3. Show the user the total, each line, its source URL, and how old the price is (a price older than 24 hours is stale and is refused; it must be looked up again):

Estimated cost: <total_usd> USD for <n> generations. Prices from <source>, <age_hours> h old (valid for 24 h).
Type "go" to generate. Anything else cancels.
  1. Continue only on an explicit go for exactly this list. Anything else, including silence, cancels and nothing is generated. If the list changes (more posts, another model, an added option), quote again and ask again. A quote is never approval (approved_to_run is always false).
  2. Quote only providers that can run here (generate_video.py without --generate-video prints routing.unavailable; Veo needs Vertex AI, a Gemini API key alone covers images only), and pass exactly the quoted providers to the script: --quoted-providers <names> on generate_image.py (gemini, wavespeed, higgsfield) and on generate_video.py (kling, veo, higgsfield). A provider that was not quoted never runs: the result is NEEDS_REQUOTE with nothing spent on it, so quote the new line and ask for a new go.

Process (For Each IMAGE Post) — 4-Stage Approval Flow

Stage 1: Creative Direction (No API Call)

Present 2-3 creative direction options to the user. Each option includes:

  • A description of the visual concept
  • Mood, color palette, and composition approach
  • How the brand asset will be used (per the assigned creative mode)
  • Rough reference to style/tone
  • Overlay text, written against the pairing rule: the overlay and the caption do different jobs and never echo each other. The overlay stops the scroll — a promise, a number, a tension in a few words. The caption (written later by adapt-copy) pays it off with context and the CTA. If the proposed overlay reads like the caption's first line, it is the wrong overlay — the quality reviewer flags this pairing as a Copy Quality failure downstream, so catch it here before credits are spent.

No image generation happens here. The user picks a direction before any credits are spent.

Stage 2: Confirm Details

Once the user selects a direction, confirm the specifics before generating:

  • Final prompt details and any refinements the user wants
  • Aspect ratio and platform targets
  • Text overlay copy and placement preferences
  • Any special instructions (e.g., "warmer tones", "more negative space")

User explicitly approves to proceed to generation.

Stage 3: Generate and Select (image provider, Vertex AI)

  • First: Quote, then go (the section above). Nothing is generated until the user types go.
  • Generate 2-3 image versions based on the confirmed direction
  • Show all versions inline via the Read tool so the user can compare
  • User picks their preferred version (or requests another round with adjustments)
  • Max 3 generation rounds per post before escalating

Stage 4: Post-Process and Save

After the user selects their preferred image:

  1. Apply text overlay via compose_text_overlay.py
  2. Apply logo per brand-config.json (position, opacity, size, platform exclusions)
  3. Resize per platform via resize_image.py
  4. Save final assets to the post-specific folder: {post_folder}/final/
  5. Update status-tracker.json
  6. Log prompt to shared/prompt-logs/
  7. Track API cost in cost-log.json

Process (For Each VIDEO Post) — 5-Stage Approval Flow

Stage 1: Video Concept (No API Call)

Present 2-3 video concept ideas to the user. Each option includes:

  • A narrative arc or visual concept for the short-form video
  • Description of the opening frame, motion/transition, and closing frame
  • Mood, pacing, and style notes
  • How brand assets or style references will be incorporated

User picks a concept before any generation begins.

Stage 2: First Frame Generation (image provider, Vertex AI)

  • First: Quote, then go for the whole video post (both keyframe rounds and the clip), as above. Nothing is generated until the user types go.
  • Generate 2 first-frame options based on the selected concept
  • Show both inline via the Read tool
  • User picks their preferred first frame (or requests adjustments)

Stage 3: Last Frame Generation (image provider, Vertex AI)

  • Generate 2 last-frame options that complement the approved first frame
  • Show both inline via the Read tool
  • User picks their preferred last frame (or requests adjustments)

Stage 4: Video Generation (WaveSpeed, latest-video-wavespeed)

  • Generate 2 video versions from the approved frames (generate_video.py --generate-video --image <first-frame> --last-image <last-frame> --quoted-providers <quoted>). The last frame reaches the video model only on the kling rung — pass --provider kling when the clip must end on it, and read video.last_frame_used in the result before presenting a clip as landing on it (see "Reference images and keyframes" above).
  • Use the video provider chain via generate_video.py. If a result carries provider_notice (or fallback_from), tell the user which provider made it and why the first did not; a rung listed in skipped_unavailable never started (no credentials, or Veo without Vertex AI) and cost nothing, so do not report it as a failure.
  • Show both versions for user review
  • User picks their preferred video (or requests another round)
  • Max 3 generation rounds before escalating

Stage 5: Post-Process + Save

After the user picks the final video, post-processing runs before saving:

  1. Watermark: Logo overlay is automatically added to the video via video_postprocess.py
  2. Subtitles: User is asked whether to burn subtitles into the video (optional). SRT was already generated from the script and is saved separately regardless.
  3. Background music: If the video has no audio (sound=False in the clip request), user is asked whether to add background music (optional).
  4. Platform resize: Video is automatically resized for each target platform (letterbox/pillarbox with black padding, no stretching)
  5. Save all platform versions to {post_folder}/final/
  6. Save alternatives to {post_folder}/versions/
  7. Update status-tracker.json
  8. Log prompt and generation parameters to shared/prompt-logs/
  9. Track API cost in cost-log.json

Batch Mode (/socialforge:generate-all)

When processing all posts via /socialforge:generate-all, the staged approval flow uses group-based approval to avoid per-post bottlenecks:

  1. Group posts by creative mode — all ANCHOR_COMPOSE posts together, all PURE_CREATIVE together, etc.
  2. Stage 1 in bulk — present creative direction options for each post in the group at once. User reviews and selects directions for the entire group before generation begins.
  3. Stage 2 confirmation — confirm details for the group. User can adjust individual posts or approve the batch.
  4. Stage 3 generation — generate images/videos for the group sequentially. After each post's variants are generated, show them inline. User can approve, request regeneration, or skip.
  5. Stage 4/5 post-processing — all approved posts are post-processed together (logo, resize, save).

Progress indicator during batch:

[GROUP 1: ANCHOR_COMPOSE — 8 posts]
  Presenting directions... awaiting approval

[GROUP 2: STYLE_REFERENCED — 12 posts]
  Queued — waiting for Group 1

[GROUP 3: VIDEO — 4 posts]
  Queued — waiting for Group 2

Posts that are skipped or fail after 3 rounds are collected into a "needs attention" list presented at the end of the batch.

Rules

  • Brand assets are SACRED — never modify the core subject in ANCHOR_COMPOSE
  • No text in AI-generated images — text is always added via compose_text_overlay.py
  • Logo overlay per brand-config.json (position, opacity, size, platform exclusions)
  • Every generated image/video requires user approval at each stage before proceeding
  • No API calls before Stage 1 approval — creative direction is confirmed before spending credits
  • Max 3 generation rounds per post before escalating to user
  • Show all variants inline via the Read tool so the user can visually compare

Progress Indicators

[3/28] Post P03 — IMAGE — ANCHOR_COMPOSE
  Stage 1: Presenting 3 creative directions...
  [User selects Direction B]
  Stage 2: Confirming details...
  [User approves]
  Stage 3: Generating 3 variants (image provider, Vertex AI)...
    Variant A... done
    Variant B... done
    Variant C... done
  [Images shown inline — user selects Variant B]
  Stage 4: Post-processing...
    Text overlay... done
    Logo... done
    Resize (IG, FB, LinkedIn)... done
    Saved. done

[4/28] Post P04 — VIDEO — STYLE_REFERENCED
  Stage 1: Presenting 2 video concepts...
  [User selects Concept A]
  Stage 2: Generating 2 first frames (image provider, Vertex AI)...
  [User selects Frame 1]
  Stage 3: Generating 2 last frames (image provider, Vertex AI)...
  [User selects Frame 2]
  Stage 4: Generating 2 video versions (WaveSpeed)...
  [User selects Video A]
  Stage 5: Saving final...
    Saved. done

Scripts Used

  • generate_image.py | compose_image.py | edit_image.py
  • generate_video.py | credential_manager.py
  • resize_image.py | compose_text_overlay.py | verify_brand_colors.py

Timeout & Fallback

  • Image generation (image provider, Vertex AI): 60-second timeout per image. Retry once with simplified prompt.
  • Video generation (WaveSpeed): 300-second timeout per video, matching generate_video.py. Retry once with reduced parameters.
  • Background removal: 30-second timeout. If fails, flag for manual masking.
  • Compositing: 15-second timeout. If Pillow fails, save components for manual assembly.
  • Total per image post: 5-minute cap. If exceeded, mark as production_timeout and move to next.
  • Total per video post: 8-minute cap. If exceeded, mark as production_timeout and move to next.
  • Staged approval pauses do not count against timeout — the clock runs only during active generation and processing.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.