Repository navigation
Releases: airiclenz/photon
Releases · airiclenz/photon
Release list
v0.2.0
photon — v0.2.0 — 2026-10-22
This release adds photon tune, a timing editor that runs in your browser, and gives storyboards a camera that aims and zooms, plus captions drawn over the GIF.
Breaking changes
- A beat no longer takes a
zoom— a storyboard written for v0.1.0 that setszoomon a beat is now refused when it loads, withbeat <id>: zoom: removed; zoom with camera.zooms and aim with camera.positions. What to do: move each beat zoom into an entry of the storyboard'scamera.zoomslist, and aim it with an entry incamera.positions. frame.font_sizemust lie between 6 and 72 — a storyboard whose font size is outside that range now fails to load, andphoton lintreportsframe.font_size: want in [6, 72], got …. What to do: setframe.font_sizeto a value from 6 to 72.
New
photon tune, a timing editor in the browser —photon tune <storyboard> [<take>]serves an editor on 127.0.0.1 (any free port, or the one you give--port), prints its address and previews the take until you press Ctrl-C. You can edit each beat'sduration,holdandcutand the clip's framewidth,fps,font_size,line_height,paddingandscalewith undo, redo and revert, and saving writes back only the values you changed.- A camera that aims and zooms — a storyboard can declare a top-level
camerawithpositions(where the camera aims: acellor a text target, withat,holdandease) andzooms(tofrom 1 to 3, withat,overandease), whereatis a clip time or a beat plus an offset.photon renderholds each position, glides to the next and keeps the crop inside the frame, andphoton lintreports camera mistakes such as a position naming an undeclaredarea. - Captions — a storyboard can declare a top-level
captionslist of text shown on the clip's clock (at, thenfororuntil) with a font size and weight, a place, alignment, offset or explicitposition, colours, a background box and fades.photon renderandphoton tunedraw captions on top of everything, cursor included, so zooming or aiming the camera never moves or scales them, andphoton lintreports bad captions. - Caption fonts — captions use the built-in Source Sans 3 Regular and Bold, or the font files you name with
caption_font.regularandcaption_font.boldinphoton.yaml; acaption_fontentry that names a directory is refused when the config loads. Release archives now include the font's licence,SourceSans3-OFL.txt. - Smooth preview while playing or scrubbing —
photon tune's preview shows quick draft frames while it plays or while you scrub, fetching up to 4 frames ahead, and settles on the exact framephoton renderwould produce once it stops. - Editing the camera in
photon tune— you can change, add and remove camera positions (at,hold,ease, acellor a text target) and zooms (at,over,ease,to), and move the edges of the transition between two positions, with only those keys written back. An edit that would make two positions or two zooms overlap is refused with a message naming both, and removing a list's last entry removes the list, andcamera:too once it is empty. - Position lane —
photon tune's timeline shows each camera position as a bar (or a point when it has no hold) with a transition bar between it and the next, each opening a panel to edit it; bars and their edge grips drag in 50ms steps, each drag one undoable edit. The lane's+adds a point at the playhead on the cell the camera is already centred on, so adding it does not move the camera. - Zoom lane —
photon tune's timeline shows one bar per zoom, labelled with its zoom factor:+adds a zoom at the playhead and dragging a bar moves it while keeping its beat. Clicking a bar opens a panel that editsat,over,toandease, shows the zoom's errors and removes it. - Aiming on the full frame — selecting a camera position in
photon tunejumps the playhead to it, and while paused the preview shows the whole frame with the camera's crop dashed and a marker you drag onto the cell the position should aim at. A pick's Set as position target sets the selected position's text target instead, and stays disabled until a position is selected. - Captions lane —
photon tuneshows captions as bars on their own lane:+adds one at the playhead, dragging moves it in 50ms steps, and its panel editstext,at,fororuntil,placeandalign, moves it up or down the list or removes it. A caption's rendering error, such as a box bigger than the frame, shows on its own panel, and the Inspect list marks captions that have one. - Caption style and timing in
photon tune— the caption panel edits font size and weight, text and box colours, box opacity, fade in and out, an offset and an explicit position, and sets start and end by beat or clip time plus an offset in milliseconds. Choosing "none" for the end turns anuntilinto aforof the same length. - Target picker — press ⌖ Pick in
photon tuneand drag across one row of the paused frame to get a target photon has checked against the screen, ready to copy as click, seen, drag-from or drag-to YAML. A target'snth: lastis kept when it is set or copied. - A page that fits the window — in a short window
photon tuneshrinks the preview (keeping its shape, never below 120px tall) so the transport bar and timeline stay on screen. The transport bar also shows which photon build serves the page, and why a lane's add button was refused, until the next accepted edit.
Improved
photon versionshows the build —photon versionandphoton --versionnow print the version with the commit it was built from, such asphoton 0.1.0 (a1b2c3d), adding, dirtywhen the tree had uncommitted changes; a build without that information prints justphoton 0.1.0.- Takes recorded out of order are refused —
photon check,photon renderandphoton tunerefuse a take that started its beats in a different order from the storyboard, naming both orders so you know to re-record it, and report a beat that started twice. photon lintchecks caption sizes — once the storyboard and config load cleanly,photon lintlays the captions out with the config's fonts and reports any caption box larger than the frame, instead of leaving it forphoton renderto fail on.- All-cut storyboards caught early — a storyboard in which every beat is cut is now refused when it loads (
beats: every beat is cut), sophoton lintreports it.
Fixed
- Stopped services free their port — when photon stops a project service it now waits for every process of that service to exit, so the service no longer keeps holding its port afterwards (Windows ends those processes with a delay); a process that survives being killed is reported.
Docs & install
- README rewritten — the README is reorganised with Contents, Why, Features, FAQ and License sections, and Install now leads with Homebrew (
brew install airiclenz/tap/photon) and Scoop, thengo installand release archives, without the pre-release caveat. - Camera and captions documented — the README gains Camera (positions, transitions, zooms, eases) and Captions reference sections, and its
photon tunesection,photon tune --help,photon render --helpand the glossary describe camera positions and zooms.
v0.1.0
photon — v0.1.0 — 2026-10-17
photon's first release. You describe a demo once as a storyboard, photon performs it against your real terminal app, checks the result and renders the GIF you ship, so a demo that goes stale after a UI change is re-recorded with one command.
New
- Record a demo from a storyboard —
photon record <storyboard>starts your app in a terminal at the storyboard's frame size, performs every beat (typing, keys, clicks, drags, waits) and saves what the screen showed as a take,<work>/<clip>.take, ready to check and render. On Windows,recordandsetuprefuse to run with the message that recording needs a unix pty. - Check a take, and retake until it passes —
photon check <storyboard> [<take>]compares a take (by default the onephoton recordsaved) with the storyboard's expects and prints a PASS/FAIL table.photon recordchecks each take whose beats all succeeded and exits 0 only when every beat and expect passed, sountil photon record ...; do :; doneis the whole retake loop. - Render the finished GIF —
photon render <storyboard> [<take>]turns a take into the GIF, giving each beat exactly itsduration(played at normal speed, held, or sped up to fit) and leaving out beats markedcut. Memory stays flat however long the clip, the file is shrunk further whengifsicleis installed, and--dry-runprints the ffmpeg commands instead of running them. - Lint before you record —
photon lint <storyboard>reads the storyboard and its config without recording anything and lists every problem by the field it sits in, or prints a one-lineoksummary; it exits 1 when anything is wrong. - Project config in
photon.yaml— onephoton.yaml, given with--configor found at or above the storyboard, names the program tolaunch(its directory, extraenv, andstrippatterns that keep your own environment variables out), thesetupandresetcommands, aworkdirectory,services,profiles, namedareas, anendblock (keys, idle wait,settle_timeout,kill_after), athemeof foreground, background and 16 ANSI colours, and afontsdirectory. Unknown keys are rejected. - The storyboard format — a storyboard file describes one clip: where its GIF ships, the terminal frame (columns, rows, font size, line height, padding, width, fps, palette size), then beats that each run actions —
typewith human-like typing,keywith 27 named keys and repeats,click,waitfor text to appear or be gone,pause— and set their duration, hold, cut and zoom. Each beat lists expects that some text isseen(optionally within an area) or that aruncommand succeeds, and unknown fields or bad values are rejected. - Aim at text, not coordinates — clicks, drags and zooms find their target by a regular expression on the screen's text, picking the first, last or Nth match, optionally inside a named area: a band of rows bounded by text anchors and found afresh on every screen, so the storyboard keeps working as the layout shifts.
- Drag with the mouse — a beat can
dragfrom one piece of text to another (or by a cell offset) in a set number of steps; photon presses, moves and releases the button as a real mouse would, and the rendered cursor and zoom follow the drag. - Services and profiles —
photon.yamlcan start helper processes, such as a fake backend, before your app, wait until each is ready by a port accepting connections or a line of output, pass their ports along asPHOTON_PORTandPHOTON_PORT_<NAME>, log their output in the work directory and stop them after the take.photon record --profile <name>swaps their commands or environment and runs anon_successcommand after a passing take. - Zoom and a drawn cursor — a beat's
zoompushes in on its target (by a factor from 1 to 3, or sized automatically) and eases back out within the beat, and a drawn cursor fades in, glides to each click and drag, rings on the press and fades away. - Fonts built in — frames are drawn with Source Code Pro, with Noto Sans Symbols 2, Math and Symbols as fallbacks, all bundled in the binary so a clip renders the same on every machine; point the config's
fontsdirectory at all six files to use your own faces. - One-time setup —
photon setup <storyboard>creates the work directory and runs the config'ssetupcommand once, for building whatever your app needs before the first recording. - Clear exit statuses — every command exits 0 on success, 1 when a run started and failed, and 2 for a bad command line, and errors go to stderr prefixed with
photon:. - Version —
photon versionandphoton --versionprint photon's version number.
Docs & install
- Install with Homebrew, Scoop or a download — besides
go install, photon installs withbrew install airiclenz/tap/photon, withscoop install airiclenz/photon, or from the release archives for Linux, macOS and Windows on amd64 and arm64; a guide to cutting a release ships alongside. - ffmpeg comes with the package — installing through Homebrew or Scoop also installs ffmpeg, so
photon renderworks straight away. - A full user guide in the README — the README now covers installing, a quick start, every command and exit status, the take and retake loop, the
photon.yamland storyboard references, targets and areas, expects, services and profiles, zoom and cursor, the environment variables your commands see, the key names and the fonts. - Font licences in every archive — each release archive carries the SIL Open Font License texts of the bundled fonts beside
LICENSEandREADME.md, with aSHA256SUMSfile to verify the downloads.