present
Skill40 starsChanged 9 days agoMITView on GitHub
Quickly turns a design doc, a pull request, a website, or anything the agent has in its context into a watchable presentation at a shareable URL. Use when asked to make a presentation, slides, a video, a deck, a slideshow, a narrated briefing, or a talk — or when stacked after another skill's report, as in /retro /present.
- Pipes a download into a shell
- Reads credentials
12 other projects use a version of this.
Adopted by
Most recently taken up by
- pietz/skillstheir own version, first seen Nov 8, 2026
- StasPotapov/presenttheir own version, first seen Nov 3, 2026
- grainulation/grainulatortheir own version, first seen Nov 3, 2026
- sassarini-marco/track-to-demotheir own version, first seen Nov 1, 2026
- qwwiwi/agentos-skills-publictheir own version, first seen Nov 1, 2026
- NguyenHuy190303/EEPtheir own version, first seen Oct 17, 2026
Used with
Projects with it also use tdd.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
GoogleSkilltdd
Test-driven development. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration tests.
Also in 3 projects that use this
Other versions12 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 12
- glebis/claude-skills★ 410same name
- grainulation/grainulator★ 86same name
- StasPotapov/present★ 16same name
- qwwiwi/agentos-skills-public★ 4same name
- michaelengland/deckwright★ 2same name
- NguyenHuy190303/EEP★ 2same name
- pietz/skills★ 2same name
- godmarch33/power-presentation★ 1same name
- OHOKAYYEAH/claude-skills★ 1same name
- GerardoRdz96/claude-skills★ 0same name
2 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
The file
Show its rules and text
We split this skill into the rules it gives an agent
22 rules. 0 are common, 7 are distinctive, and 15 are very specific to this project.
0
Common
Most of the 10 edited versions we read keep these.
7
Distinctive
This author's own choices. Worth a look.
15
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 115
Read spec.md and follow it exactly.
- Very specific: line 132
Use the command rather than curl.
- Very specific: line 140
Write index.html per the spec, in its own directory.
- Very specific: line 187
Read each respelled value against how the word should sound.
- Distinctive: line 211
When you publish, list the words you marked, in one line.
- Very specific: line 215
When you stop before publish and a later step publishes the folder (a CI job, inside anthropics/claude-code-action), narrate it yourself …
- Very specific: line 223
Use the voice the task names, else kokoro:af_heart.
- Very specific: line 242
If the user asks to publish for their team or company, add --org <slug> (their organization's slug on bisque.team).
- Very specific: line 273
Add --engine/--align when more than one is installed, --speed (default 1.0, valid range 0.7–1.2), --handle, --slug, --design, …
- Very specific: line 287
When the engine to synthesize with is not installed on this machine — typically because it was picked in the welcome flow on bisque.cloud — …
- Distinctive: line 321
Don't rebuild the slides from the transcript or from memory:
- Distinctive: line 340
Don't re-narrate: the audio is already published and the renderer downloads it.
- Distinctive: line 358
Keep it; every later command names it.
- Very specific: line 383
Not every account can put a question on a slide yet.
- Very specific: line 404
If your session has to end while a question is still open, leave the presentation open.
- Distinctive: line 408
When the work is done, end the session.
- Distinctive: line 415
If you are asked to continue a live presentation that another session started and never finished, resume it by its id.
- Very specific: line 423
If all you have is the watch URL, because the first publish stopped before it printed the id, pass the URL in place of the id.
- Very specific: line 440
If the server has no live presentation API yet, publish --keep-open says so and stops.
- Distinctive: line 448
Never silently move a user from free local narration to billed cloud narration.
- Very specific: line 453
Don't inline the format spec, and don't hand-edit presentation.json — the server assembles it so every producer computes cues the same way.
- Very specific: line 455
Never finish a live presentation while a wait is still open or the person is still answering.
“Common” is measured: kept by at least 6 in 10 of the 10 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Present
You author one index.html, bisque-voice narrates it on this machine, and
Bisque publishes it. Free, unlimited, identical on macOS, Linux and Windows.
scripts/present.mjs in this skill directory does the mechanical half — narration
extraction, synthesis, publish, upload, complete. Run it with node (18+) or
bun; below, present.mjs means that file's absolute path.
1. Check the machine
node present.mjs doctorIt prints the bisque-voice path, which engines/aligners are installed,
whether credentials resolve, the account behind them (username, tier, and any
account settings from bisque.cloud), and — when an engine is installed — runs a
one-word smoke synthesis that also checks the audio is audible, so a broken
or silent engine is caught here rather than at publish time. Fix whatever it
reports, in this order:
No bisque-voice. It lives at ~/.bisque/bin/bisque-voice
(%USERPROFILE%\.bisque\bin\bisque-voice.exe), which is usually not on
PATH — never probe with command -v/where. Tell the user you are about to
download it (~13 MB, ~30 MB installed) and what it is, then:
curl -fsSL https://download.bisque.today/bisque-voice/install.sh | sh # macOS, Linuxirm https://download.bisque.today/bisque-voice/install.ps1 | iex # WindowsNo engine installed. There is deliberately no default speech model and no
default voice — the user picks. Run ~/.bisque/bin/bisque-voice engines --json
and present each entry's real trade-offs (summary, downloadBytes,
languages, voiceCount, parameters) in a sentence each, then ask which to
install; more than one is fine. An entry carrying an unsupported field
cannot run in this build (kokoro on Intel Macs, for example) — relay its
message and offer the rest. bisque-voice install <id> installs. Then pick
a voice: if doctor printed a settings line with a voice, that saved
setting is the default and publish uses it automatically — only ask the user
when there is none. A channel can carry its own voice, in which case that line
says which channel it came from and publish narrates in it whenever it
targets that channel (--handle, or the account's default handle). When asking, use the engine's own quality metadata: each
entry in engines --json may carry a voices array (id, grade,
recommended — recommended first). Offer the recommended voices with
their grades, suggesting kokoro:af_heart (grade A) as the default. Only if
the user wants more options show the rest, grades attached — "not
recommended" means the voice has audible quality issues (upstream trained
it on very little data), not a licensing matter. The Studio named voices
(qwen3-voices-*: serena, vivian, uncle_fu, ryan, aiden, ono_anna, sohee,
eric, dylan) exist alongside cloning — nine ready-made voices, no recording
needed, ten languages; they carry no upstream grades (grade is "—") and
all nine are recommended, with the accent field flagging the two Chinese
dialect voices (eric, dylan — best in Chinese) and the Japanese/Korean-leaning
ones. Any voice the user names explicitly with --voice works regardless.
doctor lists installed voice ids where the pack exposes them, otherwise any
wrong --voice prints the engine's speaker list.
Smoke synthesis fails or is silent. doctor prints the remediation with
the failure: retry with --device cpu (on macOS the GPU path is the usual
culprit), and if that fixes it, pass --device cpu to publish too. A SILENT
result means the engine ran but produced inaudible audio — publishing would
ship silent narration, so fix it first (CPU retry, or reinstall the engine).
--no-smoke skips the check.
Aligners come with the Studio engines, not separately. A forced aligner
measures where each word lands instead of inferring it. Every qwen3-*
engine declares one as its companion, so bisque-voice install <engine> fetches
it too — a 1.05 GB download shared by all of them, on top of the engine's own
size. Say both numbers when you offer a Studio engine. Kokoro produces exact
timings natively and has no companion. --align none makes synthesis fall back
to the engine's own timings; it does not avoid the download, and it is a
real downgrade — these engines emit frames rather than word boundaries, so
without the aligner cues drift, and the clip can open with untrimmed
non-speech that measured timings would have cut. Only pass it if the user
accepts that. The publish response says which slides were approximate.
No credentials. node present.mjs login prints a URL and a pairing code;
have the user open the URL and approve, and it saves the key to
~/.bisque/config.json under the profile present. (BISQUE_API_KEY +
BISQUE_USER_ID in the environment win over the file.)
Ambiguous credentials. With several accounts configured, resolution refuses
to guess rather than publish to the wrong one — ask the user which, then pass
--profile <name> to whichever command reported it. Every command takes it:
doctor, plan, publish, claim-username, and login, where it names the
profile to write so a second account can be added without displacing the first.
No username. A presentation is published under one, and doctor reports
when the account has none. Handle it now, not at publish time: ask the user
what handle they want (3–30 chars, lowercase letters/digits/hyphens), then
node present.mjs claim-username <handle>publish makes the same check itself and stops before synthesizing
anything when the username is missing, so nothing is wasted either way.
2. Fetch the format spec — never write it from memory
node present.mjs spec --out spec.mdRead spec.md and follow it exactly; it is the renderer's own contract, which
is why it is fetched rather than repeated here.
What you fetched is the core spec. Its "Capability modules" index names the deep modules — design, charts, tables, dither, motion, code-walkthrough, cues-advanced — and the condition under which each is needed. Once you know what the presentation contains, fetch every module it calls for and read it before composing any slide that uses the capability:
node present.mjs spec --part charts --out spec-charts.mdA module you have not read is a capability you must not use. When unsure
whether a module applies, fetch it — one module is cheap. --part format
fetches the whole spec with every module inlined, if you prefer one file.
Use the command rather than curl. The endpoint is public and a plain fetch
still returns a correct spec — but the command sends the credentials this
account already has, and the spec can carry sections that only some accounts
are entitled to. Fetched without them, those sections are simply absent and
you would never know the capability existed.
3. Author
Write index.html per the spec, in its own directory. Each slide's narration is
its <aside class="notes">; a slide without one is silent. Optionally write:
context.md— what the presentation can answer viewer questions from. It ships at the presentation's visibility, so nothing more private than the presentation goes in it.design.md— theme tokens in frontmatter.assets/— every font, image, and other file the slides reference, as the spec requires.publishwalks this directory and uploads it with the presentation, so a page that renders locally renders the same once published.
node present.mjs plan --html index.html shows exactly what will be spoken, per
slide. Read it before synthesizing.
When the input is another skill's report
Skills stack. Many skills end with a report in the terminal — gstack's
/retro, /qa, /autoplan, /cso, and /ship all do — and a user can put
/present on the same line: /retro /present presents the retrospective the
moment it is written. Invoked this way, your material is the report already in
the conversation, not the repository around it. Build the slides from the
report; there is nothing extra to gather.
A report like this names its finding somewhere inside it: the ship of the week, the bug that blocks release, the highest-severity issue, the verdict on the plan. Open on that finding, wherever it sits in the report — the first slide states the report's single most important conclusion, named specifically, never the file list, the metrics table, or a description of what was run. Then the reasoning, then the evidence. A viewer who stops after the first slide still leaves with the finding.
Check pronunciations before synthesizing
A presentation narrated by a Kokoro voice MUST run this report before
publish, on the final narration, and again after any narration edit.
plan is not a substitute: plan shows the words, only the report shows the
sounds. If the report cannot run, say so in your reply rather than publishing
as if it had.
node present.mjs pronunciation-report --html index.html --voice <engine:voice>It emits, per slide and per word, what the voice will say: phonemes, a
respelled form in ordinary letters, inLexicon, and readings. The report
is facts only — it flags nothing, and you judge every word:
- Read each
respelledvalue against how the word should sound. Watch names and product words (inLexicon: falsemeans the pronunciation was guessed from the spelling) and words withreadingsabove 1 (a reading was chosen for that occurrence; check it is the one the sentence means). Short capitals read as a word. Kokoro resolves a two- or three-letter all-caps word through its lowercase entry, soUSrespells asUHS("us"),IDasIHD("id"),ITasIHT("it"), and the report calls eachinLexicon: truewith one reading. Every such word is a decision you make: letters ([US](U-S),[ID](eye dee),[IT](eye tee)), a name ([HN](Hacker News)), or a word that happens to be capitalised. Only the last stays unmarked. - For a word said wrong, write a marker with your best IPA into the slide's
narration —
[Kokoro](/kˈOkOɹO/)— and run the report again. The reportedrespelledfor that word is the verdict. The engine's notation differs from standard IPA (Ois the "oh" diphthong,əis schwa), so a first proposal is often wrong and only the re-run confirms it. - Repeat until the respelling matches the intended sound, at most three report runs per word. If three runs do not land it, remove the marker, leave the word as written, and tell the user which word you could not fix.
inspectable: false means the voice has no letters-to-sounds stage to read;
the reason field says why. That is not a pass — tell the user no automated
check ran for that voice. Markers still work there, judged by ear.
When you publish, list the words you marked, in one line.
Narrate before someone else publishes
When you stop before publish and a later step publishes the folder (a CI
job, inside anthropics/claude-code-action), narrate it yourself first, so the
narration you judged is the narration that ships. It needs no account:
node present.mjs narrate --html index.html --voice <engine:voice>Use the voice the task names, else kokoro:af_heart. bisque-cloud/presenter's
presentation: input publishes in the voice and speed you narrated in; any
other publish narrates again unless it names the same ones. It writes audio/ beside index.html and prints, per
slide, what the voice actually produced: durationMs, every word with its
start and end in seconds, pronunciationWarnings the engine raised while
speaking, and exact (false means the timings are estimates). Judge it:
- Any
pronunciationWarningsentry is a word to fix with a marker, as above. - A word whose time is out of line with its length — a short word held long, a long name rushed — is one the voice stumbled on. Look it up in the pronunciation report and mark it if it is wrong.
- A slide that runs much longer than what it shows needs shorter narration.
Edit, then run pronunciation-report and narrate again; only the slides
whose narration changed are synthesized again. Leave audio/ in the folder:
a publish of it in the same voice and speed uploads that audio as it is.
Publishing into a company (bisque.team)
If the user asks to publish for their team or company, add --org <slug>
(their organization's slug on bisque.team). The presentation then belongs
to the company — it lives at bisque.team/{org}/{slug}, only members can
open it, and it defaults to members-only visibility. A repository that
always publishes to one company can pin it once with {"org": "<slug>"}
in .bisque.json. Do not pass --handle with --org.
4. Publish
With a Kokoro voice, publish only after the pronunciation report has run on this exact narration and you have read it.
node present.mjs publish --html index.html \
--title "Q3 Review" \
--visibility unlisted \
--made-with "Claude Opus 5" \
--context context.mdPass --made-with with the model you are running as, named the way a
person says it ("Claude Opus 5", "GPT-5.4 mini", "Gemini 3 Pro"), not an API
id. The narrating voice is added for you. Viewers can see the list in the watch
page's ⋯ menu; it is never the focus of the page. If you genuinely do not know
what model you are, leave the flag off rather than guessing.
Pass --description description.txt to set the text under the player: a line
or two on what the presentation covers, then the links behind it, one per line.
Web URLs in it become links, so sources belong there and in context.md, not
on a slide. A republish without the flag keeps the description already there.
Add --engine/--align when more than one is installed, --speed (default
1.0, valid range 0.7–1.2), --handle, --slug, --design,
--presentation-id, --device. It
prints the webUrl — give that to the user. Report any staleSlides or
warnings it prints rather than hiding them.
Pass --voice only when the user picked a voice in this conversation (step 1
or by naming one). Otherwise leave it off: publish preflights the account, and
when --voice/--engine are omitted the channel's saved voice, else the
account's, on bisque.cloud fills them in — it says so when it does. A --voice
you add yourself outranks the voice the owner saved, so never pass one by
habit. A missing username stops the run before any synthesis (see "No
username" above).
When the engine to synthesize with is not installed on this machine —
typically because it was picked in the welcome flow on bisque.cloud — publish
says what it is about to download and how large (from bisque-voice engines
--json), then runs bisque-voice install itself before synthesizing. Relay
that message to the user in plain language; there is nothing else to do.
For a clone engine (qwen3-clone-*), publish also makes sure the voice
itself exists: if this machine has no cloned voice for that engine, it fetches
the account's reference recording (made in the browser during the welcome
flow) and runs bisque-voice clone locally, once. If the account has no
recording, it stops and says to record one at bisque.cloud/welcome — relay
that; never ask the user to produce a recording in the terminal.
5. Edits are cheap — never re-narrate everything
Editing a slide and re-running the same publish command is the whole point:
- It publishes without audio first, purely to ask the server what changed.
Unchanged slides carry their audio forward; the response's
staleSlidesnames the ones that actually need synthesizing. - It synthesizes only those, then publishes for real.
So a one-slide fix costs one slide of synthesis, not the whole presentation, and
an HTML-only edit (layout, colors, a cue marker moved) costs none at all. Pass
the same --title/--slug/--presentation-id/--speed as before, or it is a
different presentation. A different voice re-narrates every slide on its own:
audio is carried forward only in the voice it was spoken in. Audio published
before slides recorded their voice is narrated again once, on the next publish,
and carried forward after that. Use --all only to deliberately re-synthesize
everything.
A presentation from an earlier session
To change a presentation you no longer have the files for, pull its source. Don't rebuild the slides from the transcript or from memory:
node present.mjs pull --presentation https://bisque.today/p/<handle>/<slug> --dir <empty directory>It takes the watch URL or the id, works only for an account that may republish
the presentation, and writes index.html as published, context.md and
assets/ into that directory. It prints a republish command with the same
id, slug, visibility, voice and speed. Change what you were asked to change and
nothing else, then run that command from the directory. The URL stays, the
slides you left alone keep their audio, and the replaced version stays in the
history. A presentation still being added to is resume, not pull.
6. A video, if they want one
publish prints a watch URL, and that URL is all a video needs. If the user
asks for an MP4, a YouTube upload, a Short or a Reel, hand off to the video
skill — bisque-video renders any published presentation from its watch URL.
Don't re-narrate: the audio is already published and the renderer downloads it.
Rendering is macOS-only. On Linux or Windows, say so and offer the watch URL.
7. An interactive presentation, while the work is still running
A presentation can ask the person watching it a question and hand you the answer. Use this when what you are presenting still has decisions in it: a workflow that stops to ask (an office-hours session, a plan review, a one-question-at-a-time grilling), rather than a finished report. A finished report has nothing left to decide, so present it the ordinary way. You tell the two apart from the material, not from the request. The order of skill names on a line carries no meaning, and "run office hours on this idea, as a presentation" is enough.
Publish what you have so far with --keep-open. The presentation stays open
instead of being finished. Its presentationId is printed as soon as the
slides are up, before narration starts, and again in the output at the end.
Keep it; every later command names it.
node present.mjs publish --html index.html --keep-open --title "Office hours: …"To add slides, append new sections to the end of index.html and re-run the
same command with the id. Never remove, reorder or rewrite an earlier section;
the person may already be watching it, and the server refuses the append
(LIVE_APPEND_ONLY).
node present.mjs publish --html index.html --keep-open --presentation-id <id>To ask, put the question on a slide as a bp-survey. Fetch
node present.mjs spec --part surveys first and follow it: the same spec in
both layout blocks, and a <<fire handoff target=… for=hold>> cue on the last
word of the narration that asks the question, so playback stops for the
answer. Publish that slide, then wait:
node present.mjs wait --presentation <id> --survey <survey id> --timeout 1500Not every account can put a question on a slide yet. When that fetch answers
Unknown spec part, this account can't: ask the question in the conversation
instead, and say what the person chose on the next slide. Resuming changes
nothing here. resume prints the answers already given either way; the spec
is only for writing a new question.
wait blocks until the person presses Continue under the questions (or
play on that slide), prints the answer as JSON
(answers, keyed by question id), and exits 0. Use the answer, then keep
going: the next slide can say what they chose. Ask one question at a time:
publish the next question only after the last one is answered. A person who
skips past an unanswered question leaves you waiting on it while they answer
the next.
People answer when they get to it, which can be hours later. Your harness
probably stops long commands before then (Claude Code stops a background
command after two hours at most), so give wait a --timeout shorter than
that limit. Exit 2 means the time passed with no answer yet, not that the
session is over: run the same wait again. A timeout is never a reason to
finish.
If your session has to end while a question is still open, leave the
presentation open. Tell the person its id and that any later session can
pick it up with resume (below); their answer will be waiting for it.
When the work is done, end the session. That claims the version, and from then on it is an ordinary presentation.
node present.mjs finish --presentation <id>If you are asked to continue a live presentation that another session started and never finished, resume it by its id. Don't start a new one, and don't rebuild its slides from memory:
node present.mjs resume --presentation <id> --dir <empty directory>If all you have is the watch URL, because the first publish stopped before it
printed the id, pass the URL in place of the id. That works for a presentation
published without --presentation-id, from the account that published it.
node present.mjs resume --presentation https://bisque.today/p/<handle>/<slug> --dir <empty directory>resume writes the slides published so far into that directory as
index.html, prints every answer the person has already given, and records
where the presentation stands. Don't ask a question again that already has an
answer. Add new sections after the last one and continue with
publish --keep-open --presentation-id <id> from that directory. If another
session appended first, the publish stops and changes nothing; resume again
into a new directory and add your sections after theirs. A finished
presentation can't be resumed.
If the server has no live presentation API yet, publish --keep-open says so and
stops. Ask the questions in the conversation instead, and present the result
the ordinary way when the work is done.
Rules
- Absolute path for
bisque-voice.command -vreports "missing" on machines where it is installed. - Never silently move a user from free local narration to billed cloud narration.
- A Kokoro voice is never published without
pronunciation-reportrun on the final narration and read word by word. Short all-caps words (US,ID,IT) read as words unless marked. - Don't inline the format spec, and don't hand-edit
presentation.json— the server assembles it so every producer computes cues the same way. - Never
finisha live presentation while awaitis still open or the person is still answering. Finish once the work is done and the last slide is published.
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
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.

