carousel — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited carousel (Agent Skill) and scored it 45/100 (orange). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 1 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
A base64 string of 128+ characters appears in a documentation file. Encoded prompt injection hides the hostile instruction in base64 — invisible to keyword filters — and relies on the agent's ability to decode it at runtime. There is no normal authoring reason to embed a multi-hundred-byte base64 blob in skill docs.
*.sig, SIGNATURES) outside the documentation.Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Create professional PPTX slide decks and carousels using python-pptx. 21 layout templates, 6 carousel types, automatic brand integration. Outputs production-ready .pptx files.
Carousel, PPTX, PowerPoint, deck, pitch deck design, slide deck, presentation slides, presentation design, LinkedIn carousel, carousel post, slides, slideshow, pitch presentation, investor deck, product deck, demo deck, case study deck, internal report, slide layout, slide template, python-pptx, presentation builder, content slides, data slides
Before generating any carousel, verify that python-pptx is available:
# Check if python-pptx is installed
try:
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
print("python-pptx is ready")
except ImportError:
print("python-pptx is not installed. Installing...")
# Run: pip install python-pptx PillowIf python-pptx is not installed, run pip install python-pptx Pillow before proceeding. Do NOT attempt to generate slides without the library installed.
Before generating any carousel, check for and apply the brand system:
import json
import os
brand_path = 'brand/brand.json'
colors = None
fonts = None
if os.path.exists(brand_path):
with open(brand_path, 'r') as f:
brand = json.load(f)
# Extract colors (strip '#' prefix if present)
brand_colors = brand.get('colors', {})
colors = {
'primary': brand_colors.get('primary', '1a1a2e').lstrip('#'),
'secondary': brand_colors.get('secondary', '16213e').lstrip('#'),
'accent': brand_colors.get('accent', 'e94560').lstrip('#'),
'text': brand_colors.get('text', 'ffffff').lstrip('#'),
'bg': brand_colors.get('background', '1a1a2e').lstrip('#'),
}
# Extract fonts
brand_fonts = brand.get('fonts', brand.get('typography', {}))
fonts = {
'heading': brand_fonts.get('heading', brand_fonts.get('display', 'Arial Black')),
'body': brand_fonts.get('body', brand_fonts.get('text', 'Arial')),
}
print(f"Brand applied: {brand.get('company_name', 'Custom brand')}")
else:
print("No brand.json found — using professional defaults")# Professional defaults — dark navy theme, clean and modern
if not colors:
colors = {
'primary': '1a1a2e', # Dark navy
'secondary': '16213e', # Darker navy
'accent': 'e94560', # Coral red accent
'text': 'ffffff', # White text
'bg': '1a1a2e', # Dark navy background
}
if not fonts:
fonts = {
'heading': 'Arial Black', # Bold, widely available
'body': 'Arial', # Clean, universal
}Format: 1080x1080px (square), 5-10 slides Purpose: Social media content — educational, promotional, thought leadership
Structure:
title_bold or title_centered.content_single exclusively.cta_slide.Slide size setup:
from pptx import Presentation
from pptx.util import Inches, Emu
prs = Presentation()
# LinkedIn carousel: 1080x1080px = 10 inches x 10 inches at 108 DPI
# python-pptx uses EMU (English Metric Units): 1 inch = 914400 EMU
prs.slide_width = Inches(10)
prs.slide_height = Inches(10)Content rules:
Example flow:
| Slide | Layout | Content |
|---|---|---|
| 1 | title_bold | "5 Things I Wish I Knew Before Raising My Seed Round" |
| 2 | content_single | "1. Your first investor sets the terms for everyone after" |
| 3 | content_single | "2. Warm intros convert 10x better than cold emails" |
| 4 | content_single | "3. Due diligence starts before the first meeting" |
| 5 | content_single | "4. Your cap table is your company's DNA — protect it" |
| 6 | content_single | "5. The best pitch is a story, not a spreadsheet" |
| 7 | cta_slide | "Follow for more startup insights" |
Format: 16:9 (widescreen), 10-15 slides Purpose: Investor presentations, fundraising
Structure:
title_gradient or title_imagecontent_single or content_bulletscontent_bullets or image_leftcontent_stats (TAM/SAM/SOM)image_full or image_rightcontent_two_column or data_tablecontent_stats or data_bar_chartcontent_comparisoncontent_timeline or content_bulletsimage_grid or content_two_columndata_bar_chart or data_tablecta_slideSlide size setup:
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)Content rules:
Format: 16:9, 10-20 slides Purpose: Tutorials, courses, workshops, onboarding
Structure:
title_centeredcontent_bulletsdivider_slidecontent_single, content_bulletsimage_left, image_right, content_two_columncontent_checklistcontent_bulletscta_slideContent rules:
Format: 16:9, 8-12 slides Purpose: Feature showcases, product walkthroughs, sales demos
Structure:
title_boldcontent_singleimage_fullimage_leftimage_rightimage_leftcontent_comparisoncontent_quote or content_statsdata_tablecta_slideContent rules:
image_left and image_right alternating for visual rhythmFormat: 16:9, 6-10 slides Purpose: Customer success stories, portfolio pieces, results showcases
Structure:
title_centered (client name + project)content_bullets or content_two_columncontent_single (the core problem)content_timeline or content_checklistimage_left or image_rightcontent_stats (key metrics)data_bar_chart or data_tablecontent_quotecontent_bulletscta_slideContent rules:
Format: 16:9, 5-15 slides Purpose: Team updates, board reports, quarterly reviews, sprint retrospectives
Structure:
title_centeredcontent_bulletscontent_statsdata_bar_chartdata_pie_chartdata_tablecontent_timelinecontent_checklistcontent_bulletsContent rules:
All layouts are Python functions in the cookbook/ directory. Each function has the signature:
def add_slide(prs, title="", body="", colors=None, fonts=None, **kwargs)| # | Layout | File | Description |
|---|---|---|---|
| 1 | Title Centered | cookbook/title_centered.py | Centered title + subtitle, full background, accent line separator |
| 2 | Title Bold | cookbook/title_bold.py | Large bold left-aligned title with vertical accent bar |
| 3 | Title Image | cookbook/title_image.py | Title over background image with semi-transparent overlay |
| 4 | Title Gradient | cookbook/title_gradient.py | Title with two-color diagonal gradient background |
| # | Layout | File | Description |
|---|---|---|---|
| 5 | Content Single | cookbook/content_single.py | Single key point in large text, maximum whitespace |
| 6 | Content Bullets | cookbook/content_bullets.py | Title + bullet point list with accent underline |
| 7 | Content Two Column | cookbook/content_two_column.py | Two-column text with vertical divider |
| 8 | Content Quote | cookbook/content_quote.py | Large quote with decorative quotation mark and attribution |
| 9 | Content Stats | cookbook/content_stats.py | Big number/metric with context (single or multi-stat) |
| 10 | Content Comparison | cookbook/content_comparison.py | Side-by-side panels with VS circle |
| 11 | Content Timeline | cookbook/content_timeline.py | Horizontal timeline with milestone markers |
| 12 | Content Checklist | cookbook/content_checklist.py | Checklist with checkmark/square icons |
| # | Layout | File | Description |
|---|---|---|---|
| 13 | Image Full | cookbook/image_full.py | Full-bleed image with bottom text overlay strip |
| 14 | Image Left | cookbook/image_left.py | Image left 45%, text right 55% |
| 15 | Image Right | cookbook/image_right.py | Text left 55%, image right 45% |
| 16 | Image Grid | cookbook/image_grid.py | 2x2 image grid with captions |
| # | Layout | File | Description |
|---|---|---|---|
| 17 | Bar Chart | cookbook/data_bar_chart.py | Column chart with categories and values |
| 18 | Pie Chart | cookbook/data_pie_chart.py | Pie chart with percentage labels and legend |
| 19 | Data Table | cookbook/data_table.py | Styled table with colored header and alternating rows |
| # | Layout | File | Description |
|---|---|---|---|
| 20 | CTA Slide | cookbook/cta_slide.py | Call-to-action with button shape and optional handle |
| 21 | Divider Slide | cookbook/divider_slide.py | Section divider with accent background and large text |
Follow this exact workflow when generating a carousel:
Determine:
Create a table mapping each slide to a layout and content:
| Slide # | Layout | Title | Key Content | Notes |
|---------|--------|-------|-------------|-------|
| 1 | title_bold | "Hook headline" | ... | Cover slide |
| 2 | content_single | "TIP #1" | "Key point" | ... |import json, os
colors = None
fonts = None
if os.path.exists('brand/brand.json'):
with open('brand/brand.json') as f:
brand = json.load(f)
brand_colors = brand.get('colors', {})
colors = {
'primary': brand_colors.get('primary', '1a1a2e').lstrip('#'),
'secondary': brand_colors.get('secondary', '16213e').lstrip('#'),
'accent': brand_colors.get('accent', 'e94560').lstrip('#'),
'text': brand_colors.get('text', 'ffffff').lstrip('#'),
'bg': brand_colors.get('background', '1a1a2e').lstrip('#'),
}
brand_fonts = brand.get('fonts', brand.get('typography', {}))
fonts = {
'heading': brand_fonts.get('heading', 'Arial Black'),
'body': brand_fonts.get('body', 'Arial'),
}Write a complete Python script that:
Example script structure:
#!/usr/bin/env python3
"""Generate [carousel type]: [topic]"""
import sys
import os
# Add cookbook to path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from pptx import Presentation
from pptx.util import Inches
# Import layouts
from cookbook import (
title_bold, content_single, cta_slide
)
# Brand colors and fonts
colors = {
'primary': '1a1a2e',
'secondary': '16213e',
'accent': 'e94560',
'text': 'ffffff',
'bg': '1a1a2e',
}
fonts = {'heading': 'Arial Black', 'body': 'Arial'}
# Create presentation
prs = Presentation()
prs.slide_width = Inches(10) # Square for LinkedIn
prs.slide_height = Inches(10)
# --- Slide 1: Cover ---
title_bold(prs, title="Your Hook Here", body="Subtitle", colors=colors, fonts=fonts)
# --- Slide 2: Point 1 ---
content_single(prs, title="TIP #1", body="Your key point here", colors=colors, fonts=fonts)
# ... more slides ...
# --- Final: CTA ---
cta_slide(prs, title="Ready?", body="Take action now",
colors=colors, fonts=fonts, button_text="Follow Me",
handle="@yourhandle")
# Save
output_path = "my-carousel.pptx"
prs.save(output_path)
print(f"Carousel saved: {output_path}")
print(f"Total slides: {len(prs.slides)}")Execute the generated Python script:
python3 generate_carousel.pyAfter successful generation, report:
| Carousel Type | Max Words/Slide | Title Max | Body Max |
|---|---|---|---|
| LinkedIn Carousel | 30 | 10 | 20 |
| Pitch Deck | 50 | 8 | 40 |
| Educational Deck | 60 | 8 | 50 |
| Product Demo | 40 | 8 | 30 |
| Case Study | 50 | 8 | 40 |
| Internal Report | 60 | 8 | 50 |
content_single throughout (this is intentional).All 21 layout functions are in skills/carousel/cookbook/. Each is a standalone Python module with an add_slide() function. See skills/carousel/references/layout-guide.md for detailed documentation of every layout including visual descriptions, use cases, and parameter tables.
To import all layouts:
from cookbook import ALL_LAYOUTS
# Use by name
ALL_LAYOUTS['title_centered'](prs, title="Hello", colors=colors, fonts=fonts)To import specific layouts:
from cookbook import title_bold, content_single, cta_slideAll generated carousels are saved as .pptx files. The default output location is the current working directory. The filename should be descriptive:
linkedin-carousel-[topic].pptxpitch-deck-[company].pptxedu-deck-[topic].pptxdemo-deck-[product].pptxcase-study-[client].pptxreport-[period].pptxIf python-pptx is not installed:
pip install python-pptx PillowIf an image path is invalid:
If brand.json has unexpected format:
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.