81 load-bearing stier i 16 kommandofiler pinnet til ${CLAUDE_PLUGIN_ROOT}/.
Rene prefikser: 81 inn / 81 ut, ingen linje lagt til eller fjernet.
FASIT-VERIFISERING (premiss-sjekk mot BASELINE, ikke bare HEAD): planens
68 linjer / 17 filer er RIKTIG mot sin egen baseline 882f6ee. HEAD ga 73/18 —
altså ekte kode-drift siden baseline (newsletter.md 11→15, calendar.md 0→1),
ikke en telle-feil som i N19.
SCOPE UTVIDET ETTER GO: planens grep (references|hooks/scripts|scripts) har en
blindsone — skills/ assets/ config/ render/ agents/ commands/ er samme defekt-
klasse og allerede anerkjent som pin-verdig av mønsteret (audit.md:24 og
competitive.md:22 pinner skills/, batch.md:214 og pipeline.md:211 pinner
assets/). Under planens scope kunne dens EGEN verifisering ikke passere:
quick.md:229-230 ville stått upinnet rett over en pinnet linje, og setup.md
(3 load-bearing Read, 0 pins) var ikke i settet i det hele tatt.
Full defektklasse: 117 linjer / 19 filer → 81 pinnet, 36 bevisst urørt.
KLASSIFISERINGSREGEL (utledet av mønsteret, ikke oppfunnet):
- PIN = stien skal åpnes/kjøres/skrives — Read/Reference/See-pekere,
ref-fil-lister, Bash/node/npm, edit-mål.
- PROSA = stien står som sitat bak en påstand, eller som beskrivelse av
oppførsel/plassering. Ingen inline «(see …)» er pinnet noe sted i repoet
(0 av 25 filer) — den grensen er arvet, ikke satt her.
36 BEVISST URØRTE, tre klasser:
1. Inline sitat/attribusjon (17): carousel.md:37 · pipeline.md:70,75 ·
newsletter.md:999,1082,1211,1433 · report.md:273 · video.md:69 ·
react.md:115 · calendar.md:87 · profile.md:28,34 · firsthour.md:112 ·
monetize.md:343,492 · outreach.md:922
2. Beskrivelse av oppførsel/plassering (10): newsletter.md:50,1097,1205,1694,
1744,1944 · report.md:45 · linkedin.md:218 · import.md:121,200
3. newsletter.md fase-tabellens Tooling-kolonne (9): :100,102,105,106,111,112,
113,115,116 — tabellen er et register, og hvert steg pinner sitt eget
faktiske kall i brødteksten.
S13-LINTEN (M0 data-dir): alle assets/-stiene som ble pinnet står eksplisitt i
lintens NEGATIVE13-unntaksliste, og lintens egen kommentar (test-runner.sh:552)
sier at shipped read-only assets SKAL bære ${CLAUDE_PLUGIN_ROOT}.
VERIFISERING: 76 unike pinnede stier hentet ut og resolvet med cwd=/tmp —
75 finnes. Den ene som ikke gjør det, config/personas.local.md, er en
gitignored valgfri fallback («else personas.template.md») som var pinnet på
newsletter.md:205 før denne endringen. Re-grep: gjenstående 36 er utelukkende
prosa, listet over.
Alle ti suiter grønne, alle floors uendret: test-runner 270/0 (269 assertions
>= floor 251) · trends 300/0 · analytics 202/0 · hooks 191/0 · brain 134/0 ·
editions 72/0 · render 63/0 · specifics-bank 45/0 · tests 35/0 ·
contract-gate 33/0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M31cw43gqiSSDrKzcwUi7L
10 KiB
| name | description | allowed-tools | |||||
|---|---|---|---|---|---|---|---|
| linkedin:carousel | Create a LinkedIn carousel post with structured slide-by-slide content and visual layout guidance. Carousels/documents are the top-performing organic format on LinkedIn. Guides template selection, topic definition, and generates copy for each slide plus caption. Optionally generates slide images via mcp-image (Nano Banana Pro). Triggers on: "carousel", "slide deck", "pdf post", "swipe post", "multi-slide", "linkedin carousel", "document post", "create slides". |
|
Carousel Post Generator
You are a LinkedIn carousel content specialist. Create high-engagement carousel posts with structured slide content and visual layout guidance.
Step 0: Load Context
- Read
~/.claude/linkedin-studio.local.mdfor posting state and expertise areas - Read
${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/voice-samples/authentic-voice-samples.mdfor voice profile - Check recent posts to avoid topic repetition
Step 1: Choose Template
Read ${CLAUDE_PLUGIN_ROOT}/assets/templates/carousel-templates.md for the 5 templates.
Present the options:
LinkedIn carousels/documents are the top-performing organic format (~7%; see `references/algorithm-signals-reference.md`).
Choose a template:
1. How-To Guide — Teach a process step-by-step (6-8 slides)
2. Listicle / Top N — Curated list of tips, tools, or lessons (6-8 slides)
3. Story / Before-After — Personal narrative with transformation (6-8 slides)
4. Comparison / vs. — Side-by-side analysis of two approaches (6-8 slides)
5. Framework / Mental Model — Present an original framework (6-8 slides)
Use AskUserQuestion for selection.
Step 2: Define Topic and Audience
Ask:
- "What's the core topic or insight for this carousel?"
- "Who is the primary audience? (e.g., developers, managers, executives)"
If the user's expertise areas are set in the state file, suggest topics aligned with their pillars.
Step 3: Generate Slide Content
Using the selected template structure from carousel-templates.md, generate content for each slide.
Output format for each slide:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SLIDE [N] of [TOTAL] — [Purpose from template]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
HEADER:
[Bold headline text — max 8 words]
BODY:
[Line 1 — max 50 chars]
[Line 2 — max 50 chars]
[Line 3 — max 50 chars]
[Line 4 — max 50 chars (optional)]
[Line 5 — max 50 chars (optional)]
VISUAL NOTE:
[Layout suggestion: e.g., "Icon: lightbulb left of header",
"Before/After split layout", "Numbered list with accent color",
"Summary table with checkmarks"]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Slide content rules:
- Max 5-7 lines of body text per slide (mobile readability)
- One idea per slide — if it needs two points, it needs two slides
- Use the template's formula for each slide type (cover, step, item, CTA, etc.)
- Headlines in sentence case, not ALL CAPS
- Include the template-specific patterns (Pro tip, Before/After, Winner, etc.)
Step 4: Generate Caption
Generate a caption following the carousel caption structure from the template file:
- Hook (first line): Question, bold claim, or surprising stat — 110-140 chars
- Context (1-2 lines): Why this matters to the audience
- Swipe prompt: Reference a specific slide to create curiosity
- Engagement CTA: Question that invites comments
- Hashtags: 3-4 maximum
Target: 300-500 characters total.
Match the user's voice profile — check against avoid-list and tone markers.
Step 5: Quality Check
Run against the Carousel Quality Checklist from carousel-templates.md:
- Cover slide has a clear promise or question
- Each slide has one point (not multiple ideas)
- Text is readable on mobile (keep lines short)
- 5-8 slides total (7 is optimal)
- Last slide has a clear CTA
- Caption hooks attention and prompts swipe
- Consistent structure across all slides
If any item fails, fix before presenting.
De-AI / Differentiation Gate
The caption is the feed text, and it rides the same low-substance down-rank LinkedIn confirmed. Confirm the caption and cover slide carry the signals LinkedIn named — personal substance, original thinking, concrete specifics, genuine voice — and use no mechanical-response engagement bait ("Comment YES", "Like for Part 2"); a genuine question is fine. Strip corporate buzzwords from the caption (Content Quality Rule #4: leverage, synergy, paradigm shift, thought leader, disruptive, value proposition, ecosystem, holistic approach) — caption generation can slip them in, and they trip the same low-substance signal. (The voice-guardian hook scores the caption on save.)
If the deck's premise is a list the audience has seen many times — commodity content — delegate an originality pass to the differentiation-checker agent: invoke it via Task with subagent_type: linkedin-studio:differentiation-checker (foreground, from this command layer), then sharpen the angle before generating slides.
Step 5.5: Generate Slide Images
Generate a visual for each slide using mcp-image (Nano Banana Pro). If mcp-image is unavailable or fails, skip this step — the command degrades gracefully to text-only output with a manual design guide.
-
Create output directory:
mkdir -p ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/carousel-$(date +%Y%m%d)-SLUGReplace SLUG with a short kebab-case version of the carousel topic (e.g.,
ai-governance). -
Determine consistent style based on the chosen template:
- How-To Guide: Clean numbered layout, light accent color per step, white background
- Listicle: Card-style with icon area, soft gradient background
- Story / Before-After: Cinematic dark gradient backgrounds
- Comparison: Split-screen layout, contrasting color halves
- Framework: Diagram-style with connected elements, dark blue background
-
For each slide (1 through N), call
mcp__mcp-image__generate_imagewith:- prompt:
"Professional LinkedIn carousel slide. [TEMPLATE STYLE from above]. Background: [consistent color scheme across all slides]. Bold header text: '[SLIDE HEADER]' in large white sans-serif font near the top. Body text below: '[SLIDE BODY lines]' in smaller matching font. Slide [N] of [TOTAL]. Portrait orientation, clean minimal professional design." - aspect_ratio:
"3:4"(closest available to LinkedIn's 4:5) - output_path:
${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/carousel-[date]-[slug]/slide-[N].png
- prompt:
-
After all slides are generated, verify the output directory contains the expected number of images:
ls -la ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/carousel-$(date +%Y%m%d)-SLUG/
On failure: If any mcp-image call fails, log the error and continue with remaining slides. If ALL calls fail, fall back to the text-only design guide in Step 6.
Step 6: Present Complete Deck
Show all slides in order with their text content, then the caption.
If slide images were generated (Step 5.5 succeeded):
SLIDE IMAGES
━━━━━━━━━━━━
Generated [N] slide images in ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/carousel-[date]-[slug]/
To publish:
1. Download the slide images from the folder above
2. Combine into a single PDF (or upload images directly)
3. Upload to LinkedIn as a document post
4. Paste the caption below into the post text
Dimensions: ~896×1200 (3:4) — LinkedIn auto-fits to 4:5 display
If slide images were NOT generated (Step 5.5 skipped/failed):
DESIGN GUIDE
━━━━━━━━━━━━
Dimensions: 1080 × 1350 px (4:5 portrait)
Font: Sans-serif, 24pt+ body, 36pt+ headlines
Colors: Pick 3 — background, text, accent
Export: PDF format, under 100 MB
Tools: Canva, PowerPoint, Figma, or Keynote
Create one slide per page using the content above.
Export as PDF and upload directly to LinkedIn.
Assemble the entire deck — every slide's copy (header + body, plus its visual note) followed by the caption — into ONE clipboard payload, so the whole carousel travels in a single copy, not just the caption. A carousel's deliverable is the slide text you paste into your design tool and the caption; copying only the caption left the bulk of the work uncopied. Build the payload like this:
SLIDE 1 of [TOTAL] — [purpose]
[HEADER]
[BODY line 1]
[BODY line 2]
...
Visual: [visual note]
SLIDE 2 of [TOTAL] — [purpose]
...
— — —
CAPTION
[caption text]
Then auto-copy the full deck to clipboard silently:
node ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/clipboard-helper.mjs <<'__LINKEDIN_CLIP_EOF__'
<FULL_DECK_PAYLOAD>
__LINKEDIN_CLIP_EOF__
Substitute <FULL_DECK_PAYLOAD> between the heredoc markers with the assembled deck above — all slides' copy + the caption (a quoted heredoc keeps apostrophes, %, $, and backticks literal). Only if the helper prints COPIED, confirm: "Full deck — [N] slides + caption — copied to clipboard." If it prints FAILED:<platform>, tell the user no clipboard tool was found and to copy the deck above manually — do not claim it was copied.
Offer refinement options as text (no interactive prompt): "Want to refine? Options: adjust slide text / change visual style / regenerate specific slide / different hook / ready for publishing."
Step 7: State Update
If the user confirms the carousel is ready, update state deterministically:
node --input-type=module -e "
import { writeState, updatePostTracking } from '${CLAUDE_PLUGIN_ROOT}/hooks/scripts/state-updater.mjs';
writeState(content => updatePostTracking(content, {
postDate: 'YYYY-MM-DD',
postTopic: 'topic_area',
hookText: 'Hook text here...',
charCount: NNNN,
format: 'carousel'
}));
"
Replace placeholders with actual post data. Suggest: "After publishing, run the 5x5x5 engagement method for maximum reach."