agentsclimarketplace

Demo recording

Skill kc0506/ntucool/.claude/skills/demo-recording

Record or regenerate terminal demos for the ntucool project — the CLI demo (VHS, scripted in demo/cli.tape) and the MCP / agent demo (asciinema recording an interactive Claude Code session, rendered via agg), with personal data masked through the project's redact pipeline. Use this whenever the user asks to update, record, regenerate, tweak, restyle, or speed up a demo GIF/video for this project, or mentions VHS .tape files, asciinema .cast files, agg flags, redact.py, or PII masking for terminal recordings — even if they don't explicitly name the tools.From its SKILL.md

Install
npx -y skills add kc0506/ntucool --skill demo-recording

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 10 stars10 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

7.6 KB, as published. Nobody here has run it

Demo recording

The demo/ directory has two independent recipes. Both produce a GIF and optionally a .cast for sharing on asciinema.org.

DemoToolDriverOutput
CLIVHSScripted tapedemo/cli.gif
MCP / agentasciinema + aggInteractive — user drives Claude Codedemo/mcp.cast + demo/mcp.gif

Pick VHS when the content is fully scriptable and you want a deterministic artifact that re-runs cleanly after every change. Pick asciinema when authenticity matters — real timing, real agent reasoning, real tool calls — which scripting would flatten.

CLI demo (VHS)

demo/
├── cli.tape       VHS script: command sequence + styling
├── record.sh      Entry point — sets PATH, runs vhs
├── bin/cool       Masking wrapper around the real `cool` binary
├── redact.py      Masks personal data on stdout
└── cli.gif        Output

Regenerate: ./demo/record.sh

The script puts demo/bin first on PATH so cool in the tape resolves to the masking wrapper. The wrapper finds the real cool by scanning PATH minus its own directory, then pipes stdout through redact.py.

Tweaking commands shown. Edit the Type "cool ..." blocks in cli.tape. Each follows the pattern Type / Sleep / Enter / Sleep — the first sleep lets viewers register the command, the second lets them read the output.

Tweaking styling. The Set block at the top of cli.tape controls FontSize, Theme, WindowBar, BorderRadius, Margin, etc. The current theme is Catppuccin Mocha; vhs themes lists alternatives.

MCP demo (asciinema + agg)

demo/
├── record-mcp.sh    Entry point — prints prompts, records, redacts, renders
├── redact_cast.py   Applies redact.py to each output event of a .cast
├── mcp.raw.cast     Pre-redaction recording (review then delete)
├── mcp.cast         Redacted recording (shareable)
└── mcp.gif          Rendered GIF

Record: ./demo/record-mcp.sh

The script:

  1. Prints three suggested prompts and pauses for confirmation.
  2. Launches asciinema rec --command "claude --dangerously-skip-permissions" so the recording IS the Claude Code session — when the user /exits, recording stops.
  3. Pipes the raw cast through redact_cast.py.
  4. Greps the redacted cast for residual PII and warns if anything leaked across event chunks.
  5. Runs agg to render the GIF.

The suggested prompts intentionally avoid asking about grades — grade numbers in raw MCP JSON output ("current_score": 88.6) need different regex than the CLI's current: 88.6 (A-) shape. If a new prompt would expose grades, extend redact.py first with a JSON-shaped rule.

Why --dangerously-skip-permissions. Smooth recording. The demo only exercises read-only ntucool MCP tools. If a prompt could trigger a write tool (e.g., assignments_submit), remove the flag and approve interactively.

Rendering knobs (agg flags currently in record-mcp.sh):

FlagValueEffect
--font-size22Larger = sharper at README scale
--text-font-familyDejaVu Sans Mono,Noto Sans Mono CJK TCDejaVu for ASCII, Noto for CJK fallback (agg's default chain has no CJK and will drop chars like 哪, 內)
--speed2Whole recording plays 2× faster
--idle-time-limit1Caps any single idle gap to 1 s

--speed and --idle-time-limit are the two speedup knobs — --speed scales everything, --idle-time-limit cuts dead air. Start with --speed 2 --idle-time-limit 1; go gentler (1.5 / 0.75) if tool-call animations look choppy.

Re-render without re-recording — once a .cast exists, render variants are cheap:

agg --speed 2 --idle-time-limit 1 --font-size 22 \
    --text-font-family "DejaVu Sans Mono,Noto Sans Mono CJK TC" \
    demo/mcp.cast demo/mcp.gif

PII masking philosophy

Both demos share redact.py. The rule (also persisted in user memory):

Mask, don't fake. Sensitive values become █ bars of the same display width — not plausible fake names or grades. A fake reads as real and is misleading; a █ bar unambiguously says "redacted".

What's masked:

FieldRuleExample
Chinese nameKeep first character, mask the rest洪愷希 → 洪████
Romanized nameKeep first letter, mask the restHONG, CASEY → H██████████
Student IDKeep b104010 prefix, mask trailing digitsb10401006 → b104010██
Grade valuesMask current: X (Y) / final: X (Y) shape88.6 (A-) → ████ (██)
Submission scoresMask earned numerator, keep the assignment total93/100 → ██/100
"No grade" markersKept as-is — — (—) is not sensitiveunchanged

To re-target a different account, edit only the IDENTITY dict at the top of redact.py. Grade and submission rules are shape-matched and work for any course / assignment automatically.

CLI demo: rules apply to stdout, line-oriented — clean. MCP demo (redact_cast.py): each .cast output event is redacted independently, so if a sensitive substring is split across two events (rare, but possible for streamed agent text), it can leak. The verification grep in record-mcp.sh catches that — fix by hand by editing the .cast directly.

Dependencies

All installed without sudo on this machine:

ToolPurposeInstalled via
vhs, ttyd, ffmpegCLI demo recording + renderingStatic binaries → ~/.local/bin
asciinemaTUI session recordinguv tool install asciinema
agg.cast → GIFcargo install --git https://github.com/asciinema/agg --tag v1.8.1
Noto Sans Mono CJK TCCJK font for aggapt install fonts-noto-cjk

A couple of gotchas to remember when reproducing on a fresh machine:

  • The prebuilt agg binary from GitHub releases needs GLIBC 2.38; older systems have to build from source as above. mise use -g ubi:asciinema/agg will hit this on Ubuntu 22.04.
  • The agg crate on crates.io is a different project (a 2D graphics engine); cargo install agg installs the wrong thing — always use the git URL.

Both entry scripts command -v-check each dependency at the top, so a missing tool fails fast with a clear message.

Common tasks

Add a command to the CLI demo. Insert another Type "..." / Sleep / Enter / Sleep block in cli.tape. Re-run ./demo/record.sh.

Change which prompts the MCP demo suggests. Edit the heredoc near the top of record-mcp.sh.

Mask a new field. Add a substring entry to IDENTITY in redact.py, or for structural fields (e.g. a JSON key with a sensitive value), add a re.sub(...) call near the bottom of redact(). Both demos pick it up automatically — redact_cast.py calls redact() per event.

Just regenerate the GIFs after pulling new code. ./demo/record.sh for the CLI demo (always deterministic). For the MCP demo, if you don't want to re-record, just re-run agg on the existing demo/mcp.cast (see the "Re-render without re-recording" snippet above).

Keep looking

Skills are one crate of 628,853. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.