Author a teleprompter deck
Turn raw source material into a finished, well-timed teleprompter deck. You (the
agent) do the soft work — interview, ingest, write the prose, place rhetorical
pauses. A deterministic committed tool (tools/deck.js) does the hard contract
work — parse, count words, estimate exact duration, assemble the JSON, stamp a
stable id. Never hand-write the deck JSON; always compile it through the tool so
the contract and the duration report are machine-guaranteed.
Read references/format.md for the exact .deck.md authoring format and the
pptx-extraction recipe before you start writing.
Workflow
1. Gather the source
Ask what the source is, then ingest it:
- Pasted text / notes — use it directly.
- Images / screenshots — read the image files yourself (vision). No script.
- PDF — read it yourself with the Read tool (native PDF support). No script.
- PowerPoint (.pptx) — convert the deck to text whatever way works best on the
user's machine (see
references/format.md→ "Extracting a .pptx"): capture per-slide text and speaker notes, then check the output looks right before drafting from it. Treat the file as untrusted; don't commit any throwaway extraction script you write.
Speaker notes are the best raw material for narration — prefer them over the on-slide bullets when both exist.
2. Confirm intent and metadata (ask, do not assume)
Propose a per-slide skeleton from the source — number, title, type
(e.g. content, section-divider), the on-screen cue (what the audience sees),
and a rough target minutes per slide — and confirm it. Also ask:
- Total target duration for the talk (drives per-slide targets).
- Audience / purpose (tunes register and depth).
- Content mode — full narration (write the spoken prose) or cue notes
(short talking-point bullets the presenter expands in their own words, with a
pause after each point for speaking room). See
references/format.md→ "Content modes". If the user already asked for cues / talking points / a summarised or notes-style deck, skip this question and author in cue mode; otherwise ask. - Speaking style / voice. Offer the user's own
blacktree-voiceskill if they want it in their personal blog voice, or a register: conversational, formal, energetic, or neutral. Apply that voice when you draft. (In cue mode the voice shapes the few words you do write; the presenter supplies the rest live.) - Language (default en-GB to match the repo's existing decks).
Use AskUserQuestion for these branching choices rather than guessing.
3. Draft the narration
Write the spoken script per slide in the chosen voice. Place pause beats where
the rhetoric calls for them — after a reveal, before a list, at a hard topic
change — using [[pause]] (1s) or [[pause:1.5]] (custom). This semantic
placement is your job; the tool only validates and reports.
In cue mode, don't write full sentences: write one short talking-point bullet
per paragraph and end each with a speaking-budget pause ([[pause:20]]–
[[pause:30]] for a substantive point, less for minor ones), sizing the pauses to
sum to the slide's target. The few bullet words read in seconds, so the pauses
are what hits the target. See references/format.md → "Content modes" for the
convention and the note that the report's pace flag is expected and ignored here.
Write it all to decks/<slug>.deck.md in the format from references/format.md.
Keep each paragraph as one logical beat (the tool collapses soft wrapping).
4. Compile
node tools/deck.js decks/<slug>.deck.md --wpm 130
This writes decks/<slug>.json and prints a duration report: per slide the
words, pause count and added seconds, estimated m:ss at the reference pace, the
implied wpm vs the 60–220 range, and the delta against each slide's target; plus
the deck total. Use --wpm <n> to report at the pace the user actually reads at.
Optional: --fill-beats inserts a structural [[pause]] at paragraph ends that
lack one (never the last paragraph of a slide, never duplicating an existing
beat). Off by default — only use it if the user wants automatic breathing room
on top of your authored beats.
5. Confirm duration and iterate
Show the user the report. If a slide runs over or under its target, revise the
prose (tighten or expand) or adjust pauses, then recompile. Repeat until the
timing fits. The deck id is stable (seeded from the title / meta.id), so
recompiling updates the same deck in place rather than spawning duplicates.
6. Hand off
Confirm the final deck and tell the user:
- The compiled deck is at
decks/<slug>.json; the editable source isdecks/<slug>.deck.md(re-runnable any time). - To use it: open the app → menu (bottom-right) → choose file and pick the
JSON, or drag the
.jsononto the drop zone.decks/is not auto-listed, so it must be loaded once; thereafter it persists on that device and remembers its position.
Guardrails
- The deck JSON is always produced by
tools/deck.js, never typed by hand. - All deck text reaches the app via
textContent/.value; still, keep scripts free of control characters (the tool andSchemasanitise, but stay clean). - Don't commit any throwaway pptx extraction script; extract, verify, clean up.
- Pause beats are absolute time (not pace-scaled); spend them deliberately.