Every release
The release loop: one editable take becomes the demo, the listing and the social cuts, and the next version re-renders it.
The release loop: one editable take becomes the demo, the listing and the social cuts, and the next version re-renders it.
A release needs video: the demo, a cut for the feed, a vertical cut, a loop for the README. vosso treats that set as one editable document rendered to many destinations, so shipping the video becomes part of shipping the release, and the next version is mostly a re-render.
The loop, once per release:
Keep the script in the repo
actions.json is the recording script: the click path through your
product, written once and committed next to the code it demonstrates. It
is the next release's script too.
Re-record, keep the cut
vos record --actions actions.json --out take --strict
vos plan take --reuseRecord the same script into the same take directory: the footage is
replaced and the cut survives (doc.prev.json). --reuse then re-times
that cut onto the new recording. The recorder wrote down when every step
ran, so a zoom you placed on the checkout button follows the checkout
button, even when a new banner shifted everything down; the look copies
over; the automatic camera re-plans. Whatever could not follow, a moved
step or a control that left the UI, is named in the report rather than
guessed at, and you fix just those.
Cut it, deliver it
Cut by exception over what the planner proposed, then render the whole destination set in one pass:
vos deliver take-v2 --to youtube,x,shorts-linkedin,github --release "v2.1"The verb renders and verifies, and composes nothing: the demo, the feed
cut, the vertical cut and the README loop each play what vos plan
proposed into the document in one animation vocabulary: the card's enter,
the templates the recipe names (an end card from your shelf, or the
official End card template from vos.so when the recipe leaves endCard
on), a caption per step, a music bed and click sounds where the channel
plays sound. Each destination applies only its mechanics: the README loop
drops the motion, the words and the sound so it loops seamlessly, and the
vertical cut is a reframe whose crop follows the camera. Every cut is
verified against its channel's spec and kit.json records the set;
vos validate kit/kit.json --picture then reads each video's first and
last frames and says it with a code and a fix when one opens or ends on
nothing. The demo is also the promo video the Chrome Web Store and Product
Hunt link to, since both take a YouTube URL.
Push it, labelled for the release
vos push take-v2 --label "v2.1 launch" --note "what shipped, one line"The push creates a version named for the release, and the watch page always plays the latest one, so a shared link never goes stale. The take, the script and the kit are the release's video source, kept.
Keep the release's video source next to the code it demonstrates:
media/
actions.json the recording script (steps carry ids and captions)
doc.json the signed-off cut of the last release
BRAND.md the brand kit: colours, faces, the look (vos brand writes it)
LAUNCH.md per-channel house rules and the release's words (headline, kicker, music)
kit.json what the last release shipped, verifiedThe platform mirrors it: vos push versions the take on your shelf,
vos pull brings studio edits back, and media/vos.json tracks which
vos the pushes land on. After a release, commit the updated doc.json
so the next re-record has the cut to carry.
The whole loop is headless, so CI can produce the release's video, and a pull request can carry it the way a preview deployment carries a site: one comment with the watch page and the kit, updated in place on every push, so reviewers, QA and marketing sign off on a link. The vosjs/action action does the loop:
name: release media
on:
pull_request:
push:
tags: ['v*']
permissions:
contents: read
pull-requests: write
jobs:
media:
runs-on: ubuntu-latest # ships Google Chrome, which mp4 renders need
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22 }
- uses: vosjs/action@v1
with:
key: ${{ secrets.VOS_API_KEY }} # mint a content key at /app/apiIt records media/actions.json, carries media/doc.json onto the new
footage, renders the release's cuts (channels: picks them), re-measures
the kit with vos validate,
pushes the take labelled for the release, attaches the kit to the run, and
keeps the comment. Without the key nothing is pushed and the comment says
so. The same run on a tag is the release.
The steps the action runs, if you would rather own them (the same
VOS_API_KEY secret):
name: release media
on:
push:
tags: ['v*']
jobs:
media:
runs-on: ubuntu-latest # ships Google Chrome, which mp4 renders need
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22 }
- run: npm i -D @vosjs/cli
- name: record the shipped product
run: npx vos record --actions media/actions.json --out /tmp/take --strict --json
- name: carry the committed cut onto the new footage
run: npx vos plan /tmp/take --reuse --from media/doc.json --json
- name: render the destination set
run: npx vos deliver /tmp/take --to youtube,github --release "${{ github.ref_name }}" --json
- name: push the take, labelled for the release
env:
VOS_API_KEY: ${{ secrets.VOS_API_KEY }}
run: |
cp media/vos.json /tmp/take/vos.json || true
npx vos push /tmp/take --label "${{ github.ref_name }} launch" --note "CI release media" --yes --json
- uses: actions/upload-artifact@v4
with: { name: release-kit, path: /tmp/take/kit }--strict fails the job on a broken selector instead of shipping around
it, and a push against a stale base fails with the changelog of what
changed on the shelf, so a human race never resolves silently. The
flagged list from --reuse prints in the job log; anything named there
is the release's real to-do.
The whole loop is agent-shaped. npx skills add vosjs/skills installs the
launch-kit skill, and a message like "we're shipping v2.1 on Friday, make
the demo and the social cuts" is enough: the agent records,
cuts, delivers and pushes, and you fine-tune the result in the studio.