Skip to content

Add a release-media capture tool for changelog screenshots and clips - #15010

Merged
teamleaderleo merged 4 commits into
mainfrom
feat/release-media-capture
Sep 27, 2026
Merged

teamleaderleo merged 4 commits into
mainfrom
feat/release-media-capture

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Sep 27, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Release notes can show a screenshot or a looping clip per feature (#14869), but producing them meant a person recording their own screen. scripts/release-media/release_media.py now captures one feature from a scene file on a fleet Mac and writes it straight into the site:

scripts/release-media/release_media.py scripts/release-media/scenes/0.64.25/light-mode-terminals.json --host <capture-mac> --allow-1x
  • Host agent (host_agent.py, piped to ssh <host> python3 -, system Python 3.9): downloads the latest cmux-nightly-macos-<arch>.dmg on the host itself, copies the app to ~/release-media/nightly/<arch>/<build>/, launches it on a private socket (CMUX_SOCKET_MODE=allowAll) with a clean zsh, merges the scene's cmux.json settings (restored afterwards), opens a window at the scene size, runs the scene's cmux CLI steps, and captures that window by its CGWindowID. It quits only the copy it launched, and refuses to start when another cmux NIGHTLY or a soak is running (a second copy of the nightly bundle terminates the first; I hit that while prototyping).
  • Capture backends: screencapture -l / -v -V <secs> -l when the SSH session has Screen Recording; otherwise the already-approved CuaSshScreenCapture.app helper from cua-ssh, one window-only frame per launch (about 6 fps, retimed to 30 fps). Both capture the window alone, so the stale system prompts sitting on the minis never show up.
  • Local side: copies the raw frames back, encodes H.264 + VP9 WebM each under 2 MB plus a poster PNG (under nice), writes web/public/changelog/<version>/, and patches the feature's video or image in changelog-media.ts.
  • Degrading: with no Screen Recording, or a 1x display without --allow-1x, it stops and prints the matching operator step (approve the capture helper, or give the host a HiDPI display).
  • Safety on a shared host: one capture per host (lock file), cmux.json read as JSONC and restored byte for byte (also on SIGHUP/SIGTERM and failed captures), only the exact scratch executable is ever signalled.

Scene format, backends, and host requirements are in scripts/release-media/README.md.

Proof: 0.64.25 Light Mode Terminals

Captured end to end on a fleet Mac mini (reserved for the run) from nightly 0.64.25-nightly.3631791700601, helper backend, at 1x. The scene starts in Dark and switches Settings > App > Appearance to Light at 3 s. It flips the cmux setting rather than macOS appearance, which would need an Automation grant on the host.

Dark at 1.5 s, Light poster at 6 s

File Size Dimensions
light-mode-terminals.mp4 67 KB 1200x674, 8 s, 30 fps
light-mode-terminals.webm 91 KB 1200x674
light-mode-terminals-poster.png 56 KB 1200x674

Limits of this capture: it is 1x (every mini drives 1920x1080 at 1x, so this is half the resolution the convention asks for) and the helper backend's ~6 fps, which is fine for an instant repaint but would look choppy for motion. Recapturing on a HiDPI host is the same command without --allow-1x.

Host receipt from the run:

[host +1s] capture backend: helper
[host +1s] nightly 0.64.25-nightly.3631791700601
[host +3s] running the scene
[host +8s] capturing window 366
warning: captured at 1x: the display is not HiDPI

Testing

  • tests/test_release_media.py (15 tests incl. JSONC settings parsing, registered on the linux-guard lane): scene validation, the changelog-media.ts patcher (right version and feature, replaces existing media, idempotent, keeps the real file balanced), ffconcat timing, no upscaling, settings restore, and step handle substitution. The first 14 ran locally on Python 3.14 and the system 3.9; CI (guards preflight) runs the file from here.
  • Live: three dry runs and two real runs on the mini, plus a host-only run of the review fixes (b983620); after each, cmux.json matched its backup, no nightly process or /tmp/rm-* file remained, and the host run directory was removed.
  • Degrade path: without --allow-1x the run stops with the not-HiDPI ask. The no-Screen-Recording path was checked by hand (screencapture over SSH fails on the minis) but not end to end, since the capture host has the helper.
  • Not exercised: the native backend. The only fleet host whose SSH session has Screen Recording was running a soak, so I left it alone. Its clip crop now refuses any size other than window or full display rather than guessing.
  • The existing web/tests/changelog-pages.test.tsx check (every referenced media file exists, clips at most 2 MB) covers the new entry; CI runs it.

Changelog

none

🤖 Generated with Claude Code

scripts/release-media/release_media.py runs a scene file on a fleet Mac:
the host agent installs the latest nightly there, launches it on a private
socket with a clean zsh, builds the scene with the nightly's cmux CLI, and
captures the window (native screencapture when SSH has Screen Recording,
otherwise the approved CuaSshScreenCapture helper). The local side encodes
to the changelog convention (2 MB H.264 + WebM + poster PNG), writes
web/public/changelog/<version>/, and patches changelog-media.ts. Hosts
without Screen Recording or a HiDPI display stop with the hq#771 ask.

First capture: the 0.64.25 Light Mode Terminals clip, taken at 1x on
cmux-austin-mini-0 from nightly 0.64.25-nightly.3631791700601.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cursor

cursor Bot commented Sep 27, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 9 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: c804e2cb-23a5-48ed-b59f-983f8c87ede8

📥 Commits

Reviewing files that changed from the base of the PR and between da291df and bec37fe.

⛔ Files ignored due to path filters (3)
  • web/public/changelog/0.64.25/light-mode-terminals-poster.png is excluded by !**/*.png
  • web/public/changelog/0.64.25/light-mode-terminals.mp4 is excluded by !**/*.mp4
  • web/public/changelog/0.64.25/light-mode-terminals.webm is excluded by !**/*.webm
📒 Files selected for processing (9)
  • .github/workflows/ci-guards.yml
  • scripts/release-media/README.md
  • scripts/release-media/host_agent.py
  • scripts/release-media/release_media.py
  • scripts/release-media/scenes/0.64.25/light-mode-terminals.json
  • scripts/release-media/window_probe.swift
  • tests/test-execution.toml
  • tests/test_release_media.py
  • web/app/[locale]/(landing)/docs/changelog/changelog-media.ts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Read cmux.json as JSONC (cmux writes a commented template), and turn any
  unexpected exception into a RESULT line instead of a bare traceback.
- Stop and join the clip timeline thread before cleanup, so a failed
  capture can no longer rewrite cmux.json after it was restored.
- Hold a per-host lock for the whole run; restore settings and quit the
  scratch app on SIGHUP/SIGTERM too.
- Match the scratch app by exact executable path from ps, tolerate exit
  races, and download the DMG through a .partial file.
- Crop a native clip only when it is exactly display-sized.
- Keep private tracker and fleet host names out of the public text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cursor

cursor Bot commented Sep 27, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

cmux's default template ends `"schemaVersion": N,` followed only by
commented-out sections, so removing trailing commas before comments left
that comma in place and every host with a generated cmux.json failed with
bad-settings. Strip a BOM, then comments, then trailing commas (the
JSONCParser order), and write cmux.json by temp file and rename so an
interrupted restore never truncates it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cursor

cursor Bot commented Sep 27, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@teamleaderleo
teamleaderleo merged commit 12ec99b into main Sep 27, 2026
70 checks passed
@teamleaderleo
teamleaderleo deleted the feat/release-media-capture branch September 27, 2026 14:51
@github-actions

Copy link
Copy Markdown
Contributor

Merge receipt for bec37fe5f3: every check was green at merge (25 verified; 18 skipped by policy). Full suite runs on main after merge.

rustybret pushed a commit to rustybret/bmux that referenced this pull request Sep 27, 2026
648d5c1 Add a Paste Last Screenshot action with an unbound shortcut (manaflow-ai#14955)
ff61677 ci: avoid partial blobs in catch-up merges (manaflow-ai#15023)
4d0d112 ci: retry transient catch-up GraphQL failures (manaflow-ai#15021)
212e808 ci: attribution scores a lone suspect and reports app-host crashes apart (manaflow-ai#14952)
4cabdf4 test: settle the window before measuring the unread sidebar-row invalidation (manaflow-ai#14568)
12ec99b Add a release-media capture tool for changelog screenshots and clips (manaflow-ai#15010)
ee2cda0 Backfill Unreleased changelog and draft next release cards (manaflow-ai#14999)
be4adf8 Show a brief notice when Cmd+V fails on an oversized image or a timeout (manaflow-ai#14953)
23d22d7 ci: an owned pool the run starts on now beats an earlier one it queues on (manaflow-ai#14993)
05d0190 ci: catch-up posts once per head, says less, and merges inserted declarations (manaflow-ai#15018)
4ee4b21 ci: fail stalled Swift package tests instead of waiting out the job timeout (manaflow-ai#14997)
9ce512a merge-main: run local guards only when asked (manaflow-ai#15016)
d60108a ci: clear test-e2e's fixed DerivedData with clear-dirs.sh (manaflow-ai#14994)
1d7895e ci: run the shell and CLI no-socket lanes in parallel (manaflow-ai#14990)
6e7d25f Honor macOS Differentiate Without Color, Increase Contrast and Reduce Transparency (manaflow-ai#14991)
966b355 Stop interrupting focused work: sidebar jumps, Computer Use focus steal, quit dialog on logout (manaflow-ai#14961)
e1f1cb2 Strip control characters from feedback attachment filenames (manaflow-ai#14783)
0758c9f test: find the onboarding window the test presented, not a leftover (manaflow-ai#15015)
b35c540 fix(spm): resolve GhosttyKit/GhosttyRuntimeTestStubs target name collisions (manaflow-ai#10569)
ef33bed Map .purs artifacts to the Haskell highlight.js grammar (manaflow-ai#14202)
e2a167a Highlight Elixir and Erlang files in the file editor (manaflow-ai#13732)
972c449 fix: wrap Linux browser download card label (manaflow-ai#11157)
f563884 Add Aside to browser data import detection (manaflow-ai#13379)
091d0ea Add cmux send --paste and hint at it for large multi-line sends (manaflow-ai#14937)
3ffcdbb test(ios): keep folder-tap stat tests off the real 2 s deadline (manaflow-ai#15017)
68d3936 test: keep CmuxTerminal pasteboard tests off the cooperative pool (manaflow-ai#15006)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant