Screenshot the app or the CLI

SkillMedia

Take a screenshot of the running Mycelium app, or of CLI output rendered as a terminal card, or record a short video of a flow with a visible cursor and click/zoom animations. Use when you need to SEE the UI — verifying a frontend change, checking a layout at phone/tablet/desktop widths, driving a multi-step flow and looking at each step, producing an image of a `mycelium` command's output for a doc or PR, or showing a flow in motion. Triggers on "screenshot", "show me the app", "what does it look like", "check the layout", "responsive", "capture the terminal", "record a video", "screen recording", "demo clip", "show it in motion".

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Screenshot the app or the CLI skill

What this skill tells your AI

The instructions your AI receives, as published by mycelium-io/mycelium in .claude/skills/screenshot/SKILL.md and read by ahel’s review.

shotkit/ is this repo's camera. It holds a browser open in a background daemon, so the first shot costs ~2s and every later one ~150ms.

Run it from the repo root:

node shotkit/bin/shot.mjs <command> [flags]

The absolute PNG path is the only thing on stdout — read that file back to see the result. Timings and warnings go to stderr.

First run on a machine

node shotkit/bin/shot.mjs doctor

It reports the browser, script(1), whether the frontend's deps are installed, whether an app is already listening, and whether webfonts load here. Fix anything it marks before capturing. Terminal and code cards need no app at all.

If the webfont check warns, add --offline to every app capture and don't publish shots taken on this machine — they will render in fallback fonts. A capture that takes more than a few seconds prints the same hint.

Screenshot the app

# boot the mock frontend (no backend, SLIM or LLM needed) and shoot a route
node shotkit/bin/shot.mjs app /room/atlas-migration --mock

# against an app you already have running
node shotkit/bin/shot.mjs app / --base-url http://localhost:3000

--mock boots pnpm dev:mock inside the daemon, so it stays warm across shots — pass it on the first capture and omit it afterwards. An already-running dev server is found automatically, whatever port it is on.

Add --offline when a capture takes more than a few seconds. The frontend links Google Fonts; where those are unreachable, each navigation waits ~13s on them. --offline resolves nothing but localhost and the app renders with fallback fonts.

Check a layout across breakpoints

node shotkit/bin/shot.mjs app / --responsive --sheet --offline

Four frames — phone, tablet, laptop, wide — plus one contact sheet composing them at their true relative widths. Read the sheet: it answers "is this responsive" in a single look. --viewports phone,wide picks a subset; --viewport 1280x800@2 takes an exact size.

Drive a flow, then look

For a state behind a click, either pass ordered steps to one capture:

node shotkit/bin/shot.mjs app /room/atlas-migration --offline \
  --do click:Negotiate --do wait:.offer-grid

…or hold the page open and work against it, which is what you want when you need to see each step before deciding the next:

node shotkit/bin/shot.mjs open /room/atlas-migration --session r --offline
node shotkit/bin/shot.mjs do click:Negotiate --session r
node shotkit/bin/shot.mjs shoot --session r --name negotiate   # ~250ms
node shotkit/bin/shot.mjs close --session r

Anything without CSS punctuation is matched by accessible name, then visible text — click:Negotiate, and phrases too: click:Install CLI is a button, not a descendant selector. Words that are also tag names are no exception, so click:table finds a button labeled "table" before it considers a <table>. For a selector use #id, .class, role=button[name="Save"], text=Save, or css= when it is only tag names and spaces. shot help shoot lists every verb.

Record a short video

When the thing to show is a flow rather than a state — a demo clip for a PR or a doc, or checking that an interaction feels right:

node shotkit/bin/shot.mjs video /room/atlas-migration --mock --offline \
  --do click:Negotiate --do wait:.offer-grid --auto-zoom

Same --do verbs as a screenshot. The recording adds what a still does not need: the pointer travels to each target (moving the real mouse, so hover states fire), a ring marks each click, and --auto-zoom pushes the camera in on what is being pressed and back out after. zoom:<sel>, zoom:<sel>@2.2 and zoomout place the camera by hand.

The output path on stdout is an .mp4 where the machine has a full ffmpeg, and a .webm otherwise — Playwright's bundled build is webm-only. shot doctor says which. You cannot watch it: hand the path to the user, or pull a frame out of it to look at. Keep takes short (a few actions); --max-seconds caps one.

Screenshot CLI output

Runs the command under a pty, so Rich keeps its colors and box drawing:

node shotkit/bin/shot.mjs term --cols 84 -- mycelium memory --help

# run one command, label it as another (the CLI often needs `uv run` locally)
node shotkit/bin/shot.mjs term --cwd mycelium-cli --command "mycelium doctor" \
  -- uv run mycelium doctor

Flags must come before the command; everything after the first plain word belongs to the child. shot text <file> renders an ANSI log you already have, and shot code <file> --range 40:80 makes a syntax-highlighted code card.

Framing for a PR or doc

node shotkit/bin/shot.mjs app /room/atlas --chrome --offline          # browser window frame
node shotkit/bin/shot.mjs app / --chrome --theme light --backdrop dusk
node shotkit/bin/shot.mjs app / --chrome --backdrop mycelial --padding 90

--theme switches the app itself, not just the browser's media query.

--backdrop mycelial is the desktop behind the window: the docs site's own mycelial network, the same one docs/banner.png is cut from. Give it padding to show — and prefer a quiet backdrop (mycelium, ink, paper) when the screen itself is busy.

Rules

  • Never commit anything from .shotkit/. It is gitignored scratch. The committed docs screenshots have their own pipeline — pnpm screenshots in mycelium-frontend/, publishing per screenshots/targets.ts. Run that, and commit its output, only when asked to update the docs assets.
  • Don't hand-roll Playwright for a screenshot. If shotkit is missing a capability, add it there; capture() in shotkit/src/api.mjs is importable.
  • Leave the daemon running. It idles out after 15 minutes. shot stop only if you need a clean slate.

Signals

GitHub stars
118
Forks
12
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
screenshot-mycelium-io
Source
github.com/mycelium-io/mycelium