test-driven-development
OBobra/superpowers298k近 7 天新增 2,631 个 star
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.
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).
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 closeTen commands run ~45s; there is no hard 30s cap for this flow.
# comments in the visible script. The commands are self-descriptive.| head, no 2>/dev/null on visible commands. Show real output even if
long — it scrolls naturally. (connect ≈ 86 lines incl. an "Available commands"
list, tools-call search-actors ≈ 56, filesystem tools-list --json ≈ 300.)clear between steps. Put a single blank-line
Enter before each command (after the first) so it's separated from the
previous output, like a real terminal session.Type 'export PS1="\[\e[1;38;2;25;230;77m\]$\[\e[0m\] \[\e[1;97m\]"'
Enter
Type "trap 'tput sgr0' DEBUG"
Enter
PS1 is a bold bright-green $, then ends with \[\e[1;97m\] so the typed
input renders bold bright-white.DEBUG trap runs tput sgr0 before every command so the bold-white
input does not bleed into command output.Type 'export MCPC_HOME_DIR="$(mktemp -d)"'
so mcpc shows "No active MCP sessions / No OAuth profiles".export FORCE_COLOR=3
(+ COLORTERM=truecolor for 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 in src/cli/output.ts, RAINBOW_SATURATION,
bumped to 78% for vividness — that's where the demo colors come from.)❯, », ▶) break bash prompt
rendering under VHS and show up as garbage like 92m]. Use $ (or >), styled
with color + bold.Type quoting: use single quotes around any command containing double
quotes. A \" inside a double-quoted Type breaks VHS's parser. e.g.
Type 'mcpc @apify tools-call search-actors keywords:="web scraper" limit:=3'
and Type 'export PS1="\[\e[…m\]$\[\e[0m\] "'.Output 1-foo.gif
fails to parse) and must not be long absolute paths (the parser chokes). Use
short, letter-leading, relative names and run vhs from docs/vhs/.Screenshot is 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.for loop 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.clear after Show, so the
setup spills into frame. Pattern that works: type the connect(s), then one
generous Sleep (7–8s) so they finish, then clear, then another Sleep
(~1.5s) before Show. (Tapes that connect visibly as their first command
don't need this — their hidden setup is just fast exports + clear.)npx-launched stdio servers are too slow here. npx -y <pkg>'s registry
round-trip exceeds mcpc's 60s connect handshake, so connect times out
(MCP error -32001). Fixes: pre-install the server (npm i -g <pkg>) and put
the direct binary in mcp.json (e.g. mcp-server-filesystem, starts in
~0.3s — also a cleaner session header), or use npx --prefer-offline -y <pkg>
once the npm cache is warm (~5s; plain npx -y still does the slow registry
check even when cached).@modelcontextprotocol/server-puppeteer launches Chromium eagerly on startup
and hangs/times out as root in the container. Use
@modelcontextprotocol/server-filesystem instead (14 recognizable tools,
instant). docs/vhs/mcp.json defines the filesystem entry via its global
binary — install it first: npm i -g @modelcontextprotocol/server-filesystem.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.connect auto-names the session: mcp.apify.com → @apify,
mcp.json:filesystem → @filesystem. No @name needed.mcpc connect "https://mcp.apify.com/?tools=search-actors,fetch-actor-details,docs".skills.tape, security.tape)No public server serves the MCP Skills extension yet, so skills.tape records
against the e2e test server (test/e2e/server/index-v2.ts, 2026-07-28, which
serves the git-workflow / refunds / daily skill fixtures) under the name
mcp.example.com. mcpc forces HTTPS for non-localhost hosts, so front it with TLS:
WITH_SKILLS=true PORT=13456 pnpm exec tsx test/e2e/server/index-v2.ts &
echo "127.0.0.1 mcp.example.com" >> /etc/hosts
openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -days 2 \
-subj "/CN=mcp.example.com" -addext "subjectAltName=DNS:mcp.example.com"
# then run any small HTTPS → http://127.0.0.1:13456 reverse proxy on 127.0.0.1:443
export NODE_EXTRA_CA_CERTS="$PWD/cert.pem" NO_PROXY="mcp.example.com,$NO_PROXY"
cd docs/vhs && vhs skills.tape
The connect stays hidden: its output names the test server ("e2e-test-server").
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.
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.)
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.
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.
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. .gitignore ignores only docs/vhs/mcpc-demo.gif (the hero's
raw output, since it's committed under docs/images/).proxy.gif needs a token to record and isn't committed until recorded.| 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) |
skills.tape | MCP Skills extension: skills-list / skills-get / resources-directory-read against the e2e test server served as mcp.example.com |
security.tape | Auto-discovery skipping a checked-in .mcp.json entry that reads ${GITHUB_TOKEN} (fixture: security.mcp.json, copied into a mktemp -d HOME so no real configs are discovered); needs mcp.example.com for the trusted entry |
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).
OBobra/superpowers298k近 7 天新增 2,631 个 star
MAmattpocock/skills288k近 7 天新增 10,178 个 star
AFaffaan-m/ECC278k近 7 天新增 4,046 个 star
AFaffaan-m/ECC278k近 7 天新增 4,046 个 star
FIfirecrawl/firecrawl191k近 7 天新增 2,010 个 star