packages/skills/skills/cmd-art/SKILL.md
Design and render terminal/CMD visual effects and ASCII art from a one-line request via the pluggable `fx` engine (18 hot-swappable, themeable effects plus scripted shows). Effects include donut, matrix rain, plasma, fire, a spinning 3D ball, Game of Life, wireframe cube, 3D text banners, rainbow/lolcat gradient text, starfield, tunnel, fireworks, image-to-ASCII, and more. Use when the request is for a terminal animation, ANSI/CLI art, or a new console effect. Pure Python stdlib; truecolor.
npx skillsauth add mediar-ai/skillhubz cmd-artInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Render and design terminal visual effects with fx, a living-template engine: an Effect ABC + a @register decorator + pkgutil auto-discovery, so effects, themes, and multi-effect shows all compose. Pure Python stdlib (optional pyfiglet for fonts, PIL for real images). Truecolor + ANSI, tuned for Windows Terminal but works on any VT-capable terminal.
fx/effects/).Run python -m fx list for the live catalog. Names + aliases as registered:
| name | kind | what | aliases |
|------|------|------|---------|
| sphere | anim | rotating Lambert-shaded 3D ball ("spinning ball") | |
| donut | anim | THE spinning ASCII torus (Sloane donut.c) | |
| cube | anim | rotating wireframe cube | |
| tunnel | anim | demoscene tunnel fly-through | |
| starfield | anim | perspective starfield warp | |
| plasma | anim | full-screen sine interference field | wave |
| fire | anim | demoscene fire (heat buffer + cooling) | |
| rain | anim | matrix digital rain | |
| life | anim | Conway's Game of Life, toroidal | game_of_life |
| boids | anim | Reynolds flocking | |
| fireworks | anim | rising shells → gravity sparks | |
| sparkle | anim | dim text under bright glints | |
| text3d | anim* | big figlet/block banner, gradient; shimmer animates | banner |
| gradient_text | anim | lolcat rainbow / theme-gradient text | lolcat |
| banner_scroll | anim | scrolling figlet marquee | marquee |
| typewriter | anim | char-by-char reveal with a cursor | |
| decrypt | anim | scramble-to-plaintext reveal | |
| image2ascii | static | image → half-block truecolor / ASCII ramp | img |
*text3d is static unless --set shimmer=true. image2ascii is a StaticEffect (one frame to the normal screen). Everything else animates in the alt-screen.
From skills/cmd-art, run the package:
python -m fx <command> [args]
Or by path from any cwd (a PEP-366 prelude bootstraps the package):
python skills/cmd-art/fx/cli.py <command> [args]
Legacy compat shim (preserves the old surface, translates to fx play):
python skills/cmd-art/scripts/ascii_fx.py [--fps N] [--seconds N] [--once] [--width W] [--height H] <sphere|plasma|wave|rain|text3d> [args]
Prefer the fx CLI for new work; use the shim only for old commands/imports.
list [--tag T] [--json] — every registered effect (kind, tags, description, aliases). --tag filters (e.g. 3d, text, particles, classic, field, matrix). --json emits full param schemas.show <name> — one effect's details: animated?, tags, aliases, preferred theme, and every --set param (kind, default, choices, range, help), plus a ready-to-run example. show also plays scripted shows via --seq/--script (see Compose a show).play <name> [flags] — play one effect. Bounded by default (10s on a TTY when no --seconds/--frames). Flags:
--theme NAME — palette (see Themes). Defaults to the effect's preferred_theme.--seconds N — stop after N seconds.--frames N — stop after N frames.--once — render ONE frame to the normal screen and exit (best for text3d, image2ascii, previews).--forever — explicitly unbounded (until Ctrl-C).--fps N — frame rate (default: the effect's own default_fps).--width W / --height H — 0 = terminal size (height leaves 1 row headroom).--set K=V — override an effect param (repeatable). Unknown keys fail loudly.gallery [--seconds-per N] [--tag T] [--theme NAME] — tour every animated effect back-to-back in one alt-screen (default 3s each).random [play-flags] — play a random animated effect with a random theme (defaults to 8s).Non-TTY safety: play/shows degrade to a single plain frame when stdout is not a terminal, and the play loop always restores the terminal (cursor, wrap, alt-screen) via try/finally. Prefer --seconds/--once in automated contexts so the process always terminates.
--theme names (from fx/theme.py, live via theme_names()):
mono, fire, ocean, synthwave, viridis, pastel, matrix-green, rainbow.
Default theme is synthwave. Effects never bake in hex; they sample the active Theme (color_at(t) gradient, cycle(phase) HSV/lolcat sweep, .primary/.accent/.base), so swapping the theme restyles every effect for free. Unknown --theme on play fails loud; on shows it falls back to default.
python -m fx play sphere --seconds 5 --theme oceanpython -m fx play donut --set speed=2 --seconds 8python -m fx play rain --seconds 8python -m fx play fire --set cool=2python -m fx play life --set fill=0.35 --seconds 10python -m fx play text3d --set text=KIRO --oncepython -m fx play text3d --set text=KIRO --set shimmer=true --seconds 6python -m fx play gradient_text --set text="hello" --theme rainbowpython -m fx play image2ascii --set path=pic.png --oncepython -m fx gallery --seconds-per 3python -m fx randomPlay a timed sequence of segments in ONE alt-screen (no flicker between segments) via show:
--seq grammar effect[:theme[:seconds]],..., with left|right split-screen in the effect slot:
python -m fx show --seq "donut:fire:4,plasma::3,rain:matrix-green:5"
python -m fx show --seq "donut|fire:synthwave:6" # donut left, fire right
--script show.json (list of segment objects):
[
{"effect": "donut", "theme": "fire", "seconds": 4, "params": {"speed": 2}},
{"split": ["donut", "fire"], "themes": ["ocean", "fire"], "seconds": 6}
]
--seconds-per sets the default per-segment duration; --theme is the fallback for segments without one. Each segment gets a local clock (t restarts at 0). Split is a combinator built from two real effects, not a registered effect.
Before inventing or tuning an effect, consult the SmartCLI knowledge graph at
D:/Project/SmartCLI/knowledge/INDEX.md. Its effects/ domain carries exact-formula
notes for most of what ships here — [[donut-torus]], [[plasma]], [[fire-lode]] /
[[fire-doom-psx]], [[matrix-rain]], [[game-of-life]], [[boids]], [[starfield]],
[[tunnel]], [[rotating-cube]], [[ascii-luminance-ramp]] — plus [[color-interpolation]]
and [[hsv-cycling-lolcat]] for theme/lolcat color. The works/ wing ([[donut-c]],
[[lolcat]], [[cmatrix]], [[terminaltexteffects]], ...) is the design brain for a NEW
effect: pick your lane — replica a real effect by measuring its source math, or
compose a new one from documented primitives. Read the relevant note before writing
render code from scratch; references/effects.md is the local techniques sampler, the
graph is the sourced depth.
Drop one module in fx/effects/ — pkgutil auto-imports it, @register wires it into list/show/play/gallery. A module that fails to import is reported (stderr + registry.load_errors()) but never takes the catalog down.
Minimal contract (fx/base.py):
Effect (or StaticEffect for one-shot art). Set class metadata: name (lowercase, unique registry key), description, tags, optional aliases, preferred_theme, default_fps, and a params tuple of Param(...).Param(name, kind, default, help, choices=None, min=None, max=None) — kind ∈ int float str bool color. The CLI lists/parses/validates --set against these; unknown keys and out-of-range values fail loud. color accepts #RRGGBB/RRGGBB (empty = None).render(self, ctx: FrameCtx) -> str: return ONE full frame — ctx.height rows joined by \n, no trailing newline, EVERY cell written. Effects are pure frame producers: never print, sleep, or touch ANSI modes — the play loop owns the terminal.ctx: FrameCtx fields: t (seconds since start), frame_index, width, height, theme (active Theme, never None), params (coerced dict).setup() (allocate buffers/particles before the first frame) and teardown() (release state; also runs on error/Ctrl-C). Override is_animated(cls, params) for effects that are static by default but animate on a flag (see text3d's shimmer, gradient_text).Skeleton:
from fx.base import Effect, FrameCtx, Param
from fx.registry import register
@register
class Swirl(Effect):
name = "swirl"
description = "example: a themed diagonal sweep."
tags = ("field", "demo")
default_fps = 24.0
params = (Param("speed", "float", 1.0, "sweep speed", min=0.0, max=10.0),)
def render(self, ctx: FrameCtx) -> str:
rows = []
for y in range(ctx.height):
cells = []
for x in range(ctx.width):
t = ((x + y) / max(1, ctx.width + ctx.height)
+ ctx.t * ctx.params["speed"] * 0.1) % 1.0
r, g, b = ctx.theme.color_at(t)
cells.append(f"\x1b[38;2;{r};{g};{b}m#")
rows.append("".join(cells) + "\x1b[0m")
return "\n".join(rows)
Then python -m fx play swirl --theme rainbow --seconds 5. Duplicate names raise RegistryError (pass @register(replace=True) to intentionally override a built-in).
ctx.height rows and ctx.width cells; auto-size leaves 1 row headroom so the top doesn't scroll off.plasma and full-field effects are the heaviest (O(width×height) escapes/frame); shrink dimensions or lower --fps if they stutter.pyfiglet powers text3d/banner_scroll/gradient_text --set big=true if importable; otherwise a built-in block font covers A-Z, 0-9, space. image2ascii uses PIL if present, else a PNM/built-in demo fallback.enable_vt()), no action needed.references/effects.md is a techniques sampler — it works a few effects in depth (sphere/block-text projection, plasma field, fire kernel, rain fade), not one section per shipped effect. Read it, plus the per-effect formula notes in knowledge/effects/ (see Knowledge base above), when adding or tuning an effect.The play loop already owns a single alt-screen session, so tmux is never required. For convenience, tmux/ ships two POSIX-sh launchers that drop an effect into a tmux popup or split pane:
tmux/fx-popup.sh <effect|gallery|random> [fx args] — display-popup -E (tmux >= 3.2).tmux/fx-split.sh [-v] EFFECT [EFFECT2] [fx args] — split the current window (one effect in a new pane, or a 2-up of two).Both guard on command -v tmux: with no tmux they print the direct/compositor alternative plus install hints and exit 0. play/random runs get a default --seconds 10 bound. Truecolor through tmux needs set -g default-terminal "tmux-256color" + set -ga terminal-overrides ",*:Tc". See tmux/README.md. For a seamless side-by-side without tmux, use the compositor: python -m fx show --seq "donut|fire:synthwave:6".
tools
Use when the user wants to manage Valet agents, channels, connectors, organizations, or environment variables (secrets and plain config) via the valet CLI. Handles creation, deployment, linking, teardown, and all multi-step workflows. Also use when asked to "create an agent", "deploy an agent", "design an agent", "build me an agent that...", "create a connector", "set up a webhook", or anything involving the Valet platform or any request to create and deploy AI agents. Also use when asked to "learn from this session", "capture this workflow", "save this as an agent", "make this repeatable", or when writing SOUL.md files.
tools
Publish files, folders, and artifacts to the web. Static hosting for HTML sites, images, PDFs, reports, dashboards, and any file type. Use when asked to publish, host, upload, serve, or share work at a live URL. Also use to propose a rendered page when a report, comparison, chart, design document, or status page would work better than terminal text, but do not create or update a remote site until the user asks or agrees. Account publishing gives a permanent, private-by-default URL visible to org members; --anonymous gives a temporary public URL with no account. Use the valet CLI when available and its MCP server when the CLI cannot run. For deploying an AI agent rather than static files, use the `valet` skill instead.
testing
# Faceless.so Turn a script, prompt, Reddit post, or blog into a Remotion short with TTS, captions, and B-roll, then auto-post to YouTube, TikTok, Instagram, X, Facebook, LinkedIn, and Threads. ## Prerequisites - A Faceless.so account (from $24/mo) at https://faceless.so - Source material: script, prompt, Reddit URL, or blog URL - Destination social accounts to auto-post (YouTube, TikTok, Instagram, X, Facebook, LinkedIn, Threads) ## Instructions 1. Open https://faceless.so and start a new
testing
# BIMI SVG Tiny P/S Corpus Validator Use the public makeBIMI SVG Tiny P/S Test Corpus to evaluate an SVG against its evidence-bound fixture rules and to report the result clearly. ## Inputs Accept either an SVG file, an SVG URL, or raw SVG markup. If the source cannot be retrieved or parsed as XML, stop and report that limitation. ## Authoritative corpus 1. Retrieve the current manifest from `https://makebimi.com/public/test-corpus/v1/manifest.json`. 2. Record `schema_version`, `corpus_vers