Record Demo
Create and update terminal demo GIFs for mcpc using VHS scripts.
Installation
- Make sure Claude is on your device and in your terminal.
Skills load from
~/.claude/skills/when Claude Code starts up β so you need it on your machine first. If you don't have it yet, install it once with the command below, then runclaudein any terminal to verify.One-time setupnpm i -g @anthropic-ai/claude-codeAlready have it? Skip ahead.
- Paste into Claude Code or into your terminal.
This copies the whole skill folder into
~/.claude/skills/record-demo-apify/β the SKILL.md plus any scripts, reference docs, or templates the skill ships with. Safe default: works for every skill.Faster alternative (instruction-only skills)
Skips the clone and grabs only the SKILL.md file. Don't use this if the skill ships Python scripts, reference markdowns, or asset templates β they won't be downloaded and the skill will fail when it tries to load them.
Quick install (SKILL.md only)Sign up to copy - Restart Claude Code.
Quit and reopen Claude Code (or any other agent that loads from
~/.claude/skills/). New skills are picked up on startup. - Just ask Claude.
Skills auto-activate when your request matches the skill's description β no slash command needed. Trigger phrases live in the skill's own frontmatter; you can read them in the βWhat this skill doesβ section above.
Prefer to read the source first? Open on GitHub.
When Claude uses it
Record or regenerate the mcpc demo GIFs (the README hero docs/images/mcpc-demo.gif and the focused tapes in docs/vhs/) with VHS. Use whenever asked to create, refresh, restyle, shorten, or fix a terminal demo/animation/GIF of mcpc. The tapes drive real mcpc commands; for the authenticated step this skill ALWAYS prompts for a short-lived, low-permission TEST token first (never production). Captures the VHS + mcpc gotchas learned the hard way β read it fully before editing a tape.
What this skill does
record-demo: VHS demo GIFs for mcpc
The tapes in docs/vhs/*.tape are VHS
scripts that drive a real shell session β VHS types each command, runs it
against a live MCP server, captures the terminal, and renders a GIF. The README
hero is docs/images/mcpc-demo.gif, built from docs/vhs/mcpc-demo.tape.
This file is the accumulated know-how. Read all of it before touching a tape β most rules below were discovered by hitting the wall, and skipping them wastes whole render cycles (~1β2 min each).
The hero flow (mcpc-demo.tape)
A basic-use story across both transports:
mcpcβ empty state (no sessions, no profiles)mcpc connect mcp.json:filesystemβ local stdio server (auto-names@filesystem)mcpcβ session list (now shows the live session)mcpc @filesystem tools-listmcpc @filesystem tools-list --jsonβ JSON output, syntax-highlighted, no jqmcpc connect mcp.apify.com -H "Authorization: Bearer $APIFY_TOKEN"β remote HTTP server (auto-names@apify)mcpc @apify tools-listmcpc @apify tools-get search-actorsβ inspect one tool's input schemamcpc @apify tools-call search-actors keywords:="web scraper" limit:=3mcpc @apify close
Ten commands run ~45s; there is no hard 30s cap for this flow.
Style conventions (the current standard β match these)
- No
# commentsin the visible script. The commands are self-descriptive. - No
| head, no2>/dev/nullon visible commands. Show real output even if long β it scrolls naturally. (connectβ 86 lines incl. an "Available commands" list,tools-call search-actorsβ 56, filesystemtools-list --jsonβ 300.) - Continuous session β never
clearbetween steps. Put a single blank-lineEnterbefore each command (after the first) so it's separated from the previous output, like a real terminal session. - Colored prompt + bold-white typed commands. In the hidden setup block:
Type 'export PS1="\[\e[1;38;2;25;230;77m\]$\[\e[0m\] \[\e[1;97m\]"' Enter Type "trap 'tput sgr0' DEBUG" EnterPS1is a bold bright-green$, then ends with\[\e[1;97m\]so the typed input renders bold bright-white.- The
DEBUGtrap runstput sgr0before every command so the bold-white input does not bleed into command output.
- Empty state needs a clean home β hidden:
Type 'export MCPC_HOME_DIR="$(mktemp -d)"'somcpcshows "No active MCP sessions / No OAuth profiles". - Color is automatic for non-piped commands β mcpc detects the TTY and emits
color (256-color, plenty vivid). You only need
export FORCE_COLOR=3(+COLORTERM=truecolorfor exact hex) when a command is piped (mcpc turns color off when stdout isn't a TTY). The current tapes avoid pipes, so they don't need it. (The CLI palette lives insrc/cli/output.ts,RAINBOW_SATURATION, bumped to 78% for vividness β that's where the demo colors come from.)
VHS gotchas (these will bite you)
- ASCII prompt symbols only. Multibyte glyphs (
β―,Β»,βΆ) break bash prompt rendering under VHS and show up as garbage like92m]. Use$(or>), styled with color + bold. Typequoting: use single quotes around any command containing double quotes. A\"inside a double-quotedTypebreaks VHS's parser. e.g.Type 'mcpc @apify tools-call search-actors keywords:="web scraper" limit:=3'andType 'export PS1="\[\e[β¦m\]$\[\e[0m\] "'.- Output/Screenshot paths: must not start with a digit (
Output 1-foo.giffails to parse) and must not be long absolute paths (the parser chokes). Use short, letter-leading, relative names and runvhsfromdocs/vhs/. Screenshotis unreliable (frequently exits 2 even though the GIF rendered fine). Don't depend on it β pull frames from the finished GIF instead:ffmpeg -y -ss <seconds> -i x.gif -vframes 1 frame.png, then Read the PNG.- Renders are slow (~1β2 min each: real-time timeline + Chromium + ffmpeg
encode). Render tapes one at a time β a
forloop over several blows the 5-minute command timeout. Extracted frames often land mid-typing; sample a few timestamps around when output should be on screen. - Hidden connects leak into the recording if bash falls behind. When a tape
connects in the hidden setup (so the feature commands run against a ready
session, e.g. tools/scripting/grep), a slow connect lets VHS type ahead; bash
then echoes the buffered commands and runs the
clearafterShow, so the setup spills into frame. Pattern that works: type the connect(s), then one generousSleep(7β8s) so they finish, thenclear, then anotherSleep(~1.5s) beforeShow. (Tapes that connect visibly as their first command don't need this β their hidden setup is just fast exports +clear.)
Stdio servers in a headless / proxied box
npx-launched stdio servers are too slow here.npx -y <pkg>'s registry round-trip exceeds mcpc's 60s connect handshake, soconnecttimes out (MCP error -32001). Fixes: pre-install the server (npm i -g <pkg>) and put the direct binary inmcp.json(e.g.mcp-server-filesystem, starts in ~0.3s β also a cleaner session header), or usenpx --prefer-offline -y <pkg>once the npm cache is warm (~5s; plainnpx -ystill does the slow registry check even when cached).- Puppeteer does NOT work for headless recording.
@modelcontextprotocol/server-puppeteerlaunches Chromium eagerly on startup and hangs/times out as root in the container. Use@modelcontextprotocol/server-filesysteminstead (14 recognizable tools, instant).docs/vhs/mcp.jsondefines thefilesystementry via its global binary β install it first:npm i -g @modelcontextprotocol/server-filesystem.
Auth token (the authenticated step)
- Always prompt for the token first. Insist on a short-lived, low-permission token from a TEST / throwaway account β never production. Apify: https://console.apify.com/settings/integrations. Tell the user to revoke it as soon as the recording is done.
- Pass it inline, for the render only:
APIFY_TOKEN=β¦ vhs mcpc-demo.tape. The tape references$APIFY_TOKEN(never the literal), typed inside single quotes so bash expands it at run time β the value is never on screen, never in the GIF, never committed. Always verify a connect frame shows$APIFY_TOKEN, not the value. connectauto-names the session:mcp.apify.com β @apify,mcp.json:filesystem β @filesystem. No@nameneeded.- No-token alternative (public, anonymous):
mcpc connect "https://mcp.apify.com/?tools=search-actors,fetch-actor-details,docs".
Keychain warning (headless only)
On a box with no keyring, the bearer-token connect prints
[keychain] OS keychain unavailable, falling back to file-based credential storage β¦. It is environment-specific (won't appear on a normal desktop
with a keyring) and there is no env var to suppress it β it's a logger.warn
in src/lib/auth/keychain.ts gated only by keychain availability and JSON mode.
A dbus-run-session + gnome-keyring-daemon wrapper does not fix it in this
sandbox (raising the dbus fd limit is blocked). Options: leave it (honest), or add
a targeted 2>/dev/null to just that one connect command.
Prerequisites
mcpc --version # the CLI being demoed (npm i -g @apify/mcpc, or build + pnpm link this repo)
vhs --version # brew install vhs (needs ttyd + ffmpeg on PATH)
mcp-server-filesystem # npm i -g @modelcontextprotocol/server-filesystem (the stdio demo server)
Headless + root: VHS drives a Chromium (go-rod auto-downloads it to
~/.cache/rod) that refuses to start without --no-sandbox. If renders fail to
launch Chromium, wrap the binary once:
CHROME=$(find ~/.cache/rod/browser -name chrome -type f | head -1)
mv "$CHROME" "$CHROME-real"
printf '#!/bin/sh\nexec "$(dirname "$0")/chrome-real" --no-sandbox --disable-gpu --disable-dev-shm-usage "$@"\n' > "$CHROME"
chmod +x "$CHROME"
(Run vhs once first to trigger the Chromium download.)
Render and verify
cd docs/vhs
APIFY_TOKEN=β¦ vhs mcpc-demo.tape # real-time; be patient
ffprobe -v error -show_entries format=duration -of csv=p=0 mcpc-demo.gif # check length
ffmpeg -y -ss 12 -i mcpc-demo.gif -vframes 1 /tmp/f.png # spot-check a frame, then Read it
cp mcpc-demo.gif ../images/mcpc-demo.gif # update the README hero
Check each frame class: empty state, stdio connect + session list, tools-list, JSON, remote connect (token NOT visible), tool-call result, close. Then revoke the token.
Optimize the GIF size (do this before committing)
VHS GIFs are large (the hero is ~5 MB raw). Shrink them losslessly-ish with
gifsicle (kornel.ski/lossygif) β --lossy
drops imperceptible inter-frame detail and cuts ~60% off a text-terminal GIF
with no visible quality loss:
# in place; lossy=200 β 60% smaller, text stays crisp (verified by frame diff)
for f in docs/images/mcpc-demo.gif docs/vhs/*.gif; do
[ "$f" = docs/vhs/mcpc-demo.gif ] && continue # ignored raw hero
gifsicle -O3 --lossy=200 -b "$f"
done
After optimizing, re-extract a colored frame (ffmpeg -ss 12 β¦) and eyeball it β
lossy=200 is the sweet spot; going much higher smears the antialiased text.
When the optimized hero lands on main, bump the README cache-buster
(mcpc-demo.gif?v=N β ?v=N+1): GitHub's camo image proxy caches by full URL,
so a new ?v= is what makes it re-fetch the smaller file instead of serving the
old cached copy.
What's committed
docs/images/mcpc-demo.gifβ the README hero (canonical copy).docs/vhs/*.gifβ the per-feature recordings are committed too, so they're easy to find and reuse..gitignoreignores onlydocs/vhs/mcpc-demo.gif(the hero's raw output, since it's committed underdocs/images/).proxy.gifneeds a token to record and isn't committed until recorded.
The tapes
| Tape | Records |
|---|---|
mcpc-demo.tape | Hero basic-use flow (stdio + remote) β docs/images/mcpc-demo.gif |
quickstart.tape | Minimal connect β list β call |
tools.tape | tools-list / tools-get / tools-call, inline JSON, stdin |
scripting.tape | --json piped through jq (code mode) |
grep.tape | Dynamic tool discovery with mcpc grep across two sessions (Apify + filesystem) |
proxy.tape | MCP proxy / AI sandboxing (keeps a bearer token on purpose) |
All focused tapes follow the same conventions as the hero (bold $ prompt,
bold-white commands, no comments, blank-line separation, mktemp home).
quickstart/tools/scripting/grep are token-free (public ?tools= URL);
grep also connects a local filesystem stdio server so it can search across two
sessions. proxy.tape keeps a bearer token because demonstrating that you can
proxy a credentialed session without leaking the token is its entire point (it's
the one focused tape that needs a token to record).
Related skills
Claude API Helper
anthropics
Build, debug, and optimize Claude API applications with caching and model migration support.
Documentation Co-Authoring
anthropics
Guide structured workflows for writing docs, proposals, and technical specs collaboratively.
PPTX Text Extractor
axoviq-ai
Extract text and speaker notes from PowerPoint presentations.
Memory Search
davila7
Search conversation history and recall previous discussions, decisions, and context.