CtrlK
BlogDocsLog inGet started
Tessl Logo

jbaruch/speaker-toolkit

Seven-skill presentation system: ingest talks into a rhetoric vault, run interactive clarification, generate a speaker profile, create presentations that match your documented patterns, produce the deck illustrations + thumbnail visual layer, create and publish talk-content Agent Skills with talk pages to a Jekyll shownotes site, and verify a recorded screencast against its storyboard. Includes a 113-entry Presentation Patterns taxonomy (83 observable: 64 patterns + 19 antipatterns; 30 unobservable: 21 patterns + 9 antipatterns) for scoring, brainstorming, and go-live preparation.

75

Quality

94%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

Overview
Quality
Evals
Security
Files

export-pdf.pyskills/presentation-creator/scripts/

#!/usr/bin/env python3
"""Export a PowerPoint deck to PDF via AppleScript (macOS + Microsoft PowerPoint).

Falls back to LibreOffice CLI if PowerPoint is not available.

Usage:
    export-pdf.py <deck.pptx> [<output.pdf>]

    If output.pdf is omitted, uses the same name with .pdf extension.

Examples:
    export-pdf.py presentation.pptx
    export-pdf.py presentation.pptx ~/exports/presentation.pdf
"""

import os
import shutil
import subprocess
import sys


def try_powerpoint_applescript(pptx_path, pdf_path):
    """Export via Microsoft PowerPoint AppleScript (macOS only)."""
    script = f'''
tell application "Microsoft PowerPoint"
    open POSIX file "{pptx_path}"
    delay 2
    save active presentation in POSIX file "{pdf_path}" as save as PDF
    close active presentation saving no
end tell
'''
    result = subprocess.run(
        ["osascript", "-e", script], capture_output=True, text=True, timeout=30
    )
    return result.returncode == 0


def try_libreoffice(pptx_path, pdf_path):
    """Export via LibreOffice CLI."""
    output_dir = os.path.dirname(pdf_path) or "."
    result = subprocess.run(
        [
            "libreoffice",
            "--headless",
            "--convert-to",
            "pdf",
            "--outdir",
            output_dir,
            pptx_path,
        ],
        capture_output=True,
        text=True,
        timeout=60,
    )
    if result.returncode == 0:
        # LibreOffice names output after the input file
        lo_output = os.path.join(
            output_dir, os.path.splitext(os.path.basename(pptx_path))[0] + ".pdf"
        )
        if lo_output != pdf_path and os.path.exists(lo_output):
            shutil.move(lo_output, pdf_path)
    return result.returncode == 0


def main():
    if len(sys.argv) < 2:
        print(f"Usage: {sys.argv[0]} <deck.pptx> [<output.pdf>]", file=sys.stderr)
        sys.exit(1)

    pptx_path = os.path.abspath(sys.argv[1])
    if len(sys.argv) >= 3:
        pdf_path = os.path.abspath(sys.argv[2])
    else:
        pdf_path = os.path.splitext(pptx_path)[0] + ".pdf"

    # Try PowerPoint first (macOS), then LibreOffice
    if sys.platform == "darwin" and shutil.which("osascript"):
        if try_powerpoint_applescript(pptx_path, pdf_path):
            print(f"Exported via PowerPoint: {pdf_path}")
            sys.exit(0)
        print("PowerPoint export failed, trying LibreOffice...", file=sys.stderr)

    if shutil.which("libreoffice"):
        if try_libreoffice(pptx_path, pdf_path):
            print(f"Exported via LibreOffice: {pdf_path}")
            sys.exit(0)

    print(
        "ERROR: Neither PowerPoint nor LibreOffice available for PDF export",
        file=sys.stderr,
    )
    sys.exit(1)


if __name__ == "__main__":
    main()

skills

presentation-creator

SKILL.md

README.md

tile.json