What's new in PandaStudio. Every release is signed and notarized — download and run, no extra steps.
Latest
v1.26.9
Organise projects into folders. The Home page now groups projects under user-defined folder labels (Tutorials, Client X, Lacrosse drills, whatever). A filter row sits above the grid showing All / Unsorted plus every folder you've created, each with its project count. Right-click any project's three-dot menu, pick 'Move to folder', and either choose an existing folder or type a new one inline. Folders are flat (no nesting), workspace-scoped, and the field lives on the project file itself so the organisation survives across machines if you sync the recordings dir. Also fully reachable by the agent via the new `project.setFolder` verb and `project_set_folder` MCP tool, so 'put these in a Tutorials folder' just works.
Projects now carry an optional `folder` label that groups them on the Home page. A pill row above the grid renders one chip per folder plus All / Unsorted, each annotated with the project count. Clicking a chip filters the grid; search continues to work within the active folder. The chip row only appears once at least one folder exists, so the new-user view stays clean. Folder list is derived live from the projects array (no separate folder-management screen needed) and sorted alphabetically. Move action lives in the existing three-dot card menu under 'Move to folder', which opens a submenu listing every existing folder with the current one marked, plus '+ New folder…' that flips inline into a text input. Optimistic local state update means the chip counts and grid reflow the moment the IPC resolves.
Folder support is plumbed end-to-end
Folder string lives on the `.pandastudio` project file as a top-level field, so it survives sync / copy / restore the same way `name` and `id` do. The SQLite project index gets a `folder` column via ALTER TABLE migration on first launch; the index is a denormalised cache that the Home page reads to avoid re-parsing every project file on each render. New `set-project-folder` IPC validates the path, writes the project file through `persistProjectFile` (same chokepoint as every other project mutation), then patches the index row inline so the Home page sees the new grouping without a full reconcile. Pure primitive `setProjectFolder(project, folder)` lives in `electron/automation/projectEdit.ts` for both the IPC and the automation handler to share.
The folder field is reachable by the embedded agent (and by external Claude / Cursor / Codex via MCP), so a user can say 'put all my tutorials in a Tutorials folder' and the agent walks `project.list`, filters by name pattern, and runs `project.setFolder` per match. Every `project.list` row now carries `folder: string | null`. The new `project.setFolder` verb takes `id` (preferred) or `path` plus `folder` (empty string = move to Unsorted) and returns the canonical `{id, path, folder}` shape. SKILL.md documents the verb with a worked example for bulk moves via `jq` pipe. MCP package and CLI bumped to 1.34.0; SKILL.md to 2.41.0.
Previous releases
v1.26.8
Recover gracefully when a recording file goes missing. If the source video has been moved, renamed, offloaded by OneDrive, or sits on a disconnected drive, the Transcript panel now shows a 'Locate file' button that opens a file picker. Pick the moved file once and the editor rewrites the active project file, the session.json sidecar, and the in-memory clips array in lockstep — no more being stuck on a Retry button that keeps re-hitting the same dead path. Also clearer error messages and proper logging so the next field report is debuggable on first read.
• Locate file recovery for missing recordings
• Clearer user-visible read errors
• Diagnostic logging on every read failure
v1.26.7
Long recordings no longer crash on stop. v1.26.6 added live-streaming-to-disk for crash recovery, but the normal stop path still assembled the full recording as an in-memory blob and shipped it across the renderer-to-main IPC boundary as one ArrayBuffer. V8's structured-clone serializer crashed mid-transfer on a 1.65 GB recording (1.3 GB webcam + 347 MB screen), leaving the editor un-opened. v1.26.7 collapses that into one path: MediaRecorder chunks go straight to disk via append IPCs as they arrive, and on stop the main process promotes the on-disk file in place. No blob, no ArrayBuffer copy, no structured-clone serialization. A 2-hour recording now uses the same memory profile as a 2-second one.
• Single converged finalize path for normal stop and crash recovery
• MediaRecorder chunks no longer buffer in renderer memory
• FFmpeg owns duration metadata; `fix-webm-duration` is gone
v1.26.6
Long recordings now survive crashes. Every MediaRecorder chunk is streamed to disk as it arrives, instead of accumulating ~950 MB of in-memory buffer for a 21-minute session that vanishes on any crash, force-quit, or OOM kill before `recorder.onstop`. We saw this twice in the field with 21+ minute recordings that produced no file on disk at all. A new Home-page recovery banner surfaces any unfinished recordings on next launch — one click remuxes and opens them in the editor. Codec-aware remux on top: H.264-in-WebM (Chrome's default on macOS for MediaRecorder) is now finalized as `.mp4` instead of failing FFmpeg's webm muxer with 'Only VP8 or VP9 or AV1 video … supported for WebM' and leaving the duration metadata broken.
• Recordings stream to disk live — no more lost long recordings
• Home-screen recovery banner for unfinished recordings
• Codec-aware remux finally fixes H.264-in-WebM
v1.26.5
Four export + editor fixes that hit phone-recorded content hardest. (1) Mobile clips with rotation metadata now export upright — the container's rotation tag was being ignored by the WebCodecs decoder, so portrait phone footage exported as a small landscape strip with the wallpaper showing through. Detection now happens in the decoder preflight; rotated sources are routed through the bundled FFmpeg's `-autorotate` to bake the orientation into pixels. (2) Audio survives the rotation-preprocess round-trip — the preprocessed MP4 has `-an` (audio stripped), so the audio-mux step was concluding `hasAudio: false` for every clip and substituting silence. Fixed by tracking the original source URL on `audioSourceUrl` and pointing audio-mux at the untouched file. (3) Color-grade LUTs now apply to the export — the preview renders LUTs via a CSS filter on the screen layer, but the Tier-3 frame renderer was never wired to apply them. Now applied via `ctx.filter` on the screen-layer drawImage, scoped the same way preview does (not background, not webcam). (4) Remove-silences now catches dead air past the last spoken word — added an ffmpeg `silencedetect` pass that unions audio-level silences with the existing transcript-gap regions, so Whisper-hallucinated phantom words on long silent stretches no longer block detection. (5) Playback auto-advances past a trimmed clip tail — the trim-EOF handler was paused-but-not-handed-off because the pause-listener ordering flipped `isPlayingRef` before the boundary-advance read it; fixed by calling advance directly from the trim handler.
• Phone clips export upright (container rotation tag is honored)
• Audio survives rotation preprocessing
• Color-grade LUTs apply on export
• Remove-silences catches dead air past the last spoken word
v1.26.4
Auto-preprocess unsupported codecs via the bundled FFmpeg. A handful of Windows users still hit 'VideoDecoder Error, Unknown or Ambiguous...' on v1.26.3 — that error is a synchronous throw from WebCodecs' decoder.configure() when the source codec_string is incomplete or non-standard, a different path from the mid-stream decoder errors v1.26.1's retry handles. v1.26.4 preflights every source through VideoDecoder.isConfigSupported, and when it returns false (or throws on ambiguous codecs), routes the file through the bundled FFmpeg to produce a CFR H.264 MP4 that WebCodecs is guaranteed to decode on every platform. The preprocessor module has existed in the codebase since v1.x but was never wired in — this release finally connects it.
USB cameras no longer get squished in the recording preview. The camera-preview window was asking getUserMedia for an aspect that doesn't match the camera's native sensor — 640×640 (square) for the bubble preview, 1080×1920 (portrait) for the fullscreen 9:16 camera-only mode. Built-in Mac cameras (FaceTime HD, Continuity Camera) negotiate that gracefully by cropping the sensor and reporting the actual delivered resolution, so their preview always looked right. Many cheap USB cameras instead 'satisfy' the constraint by horizontally squeezing their native 16:9 sensor output into the asked-for aspect; CSS object-cover then rendered the already-squeezed frames and the bubble looked stretched. v1.26.3 asks the camera for its native landscape mode and lets CSS handle the framing into the bubble circle / 9:16 rect on the display side. Built-in cameras keep working, USB cameras stop squishing.
• Camera-preview MediaStream now requests native landscape
v1.26.2
Cropped or zoomed video now fills the canvas on export. v1.26.0 shipped in-canvas drag handles for cropping the screen recording and webcam directly on the preview, but a clamp in the layout solver was capping the rendered rect at the cropped pixel dimensions instead of scaling it up to fill the canvas. Preview looked correct because the editor's viewport is itself shrunk to fit — but at full 1080p export, the cropped region rendered as a small box centered with black bars on every side. Removed the upscale clamp; cropped content now zooms in the way the user expects on both preview and export. Re-export to pick up the fix.
• Cropped content fills the canvas at export resolution
v1.26.1
Two field-reported regressions fixed. (1) Windows exports were failing with a generic 'Video Decoder Error' on VP9/VP8/HEVC screen recordings because WebCodecs VideoDecoder was attempting hardware decode by default and many Intel UHD / older NVIDIA driver builds reject those mid-stream. v1.26.1 prefers software decode upfront for those codecs on Windows and adds an automatic retry-with-software fallback on any decoder error. Software 1080p decode runs at 20–30% of realtime instead of 5% — a slower export beats a failed one. (2) Mac motion graphics failed with 'spawn ffmpeg ENOENT' because the third-party HyperFrames producer spawns ffmpeg by bare name, and packaged Mac apps launched from Finder don't include our cached ffmpeg directory on PATH. v1.26.1 prepends the bundled ffmpeg's directory to process.env.PATH before the producer runs.
• Robust video decode on Windows
• Motion graphics work on packaged Mac apps
v1.26.0
Unified in-canvas crop UX across screen recording, camera, and overlays. Click any source in the preview to select it, drag the corner handles to zoom (aspect-locked), or drag the edge handles to crop a single side. Same gesture, same affordances, three sources. Per-overlay source crop also lands — drop a 16:9 b-roll into a 9:16 short and pick which part of the source survives instead of letting object-fit silently cut your sides off. Plus fixes for cursor-telemetry auto-zooms re-suggesting after deletion, drag-handle edits not making it into single-clip exports, the camera crop being invisible in vertical-stack / side-by-side preview, and the Export Library copy buttons silently failing because navigator.clipboard is unreliable in Electron.
• One crop gesture across screen, camera, and overlays
• Per-overlay source crop (CLI + MCP + UI)
• Drag-handle crops now survive the export
• Camera crop actually visible in non-PiP layouts
v1.25.4
In-app AI agent finds the bundled pandastudio CLI now. The agent was saying "the PandaStudio CLI isn't accessible" and running shell commands like `ls /Applications | grep panda` to look for it — even though the CLI ships inside the app bundle. Root cause: Electron apps launched from Finder on macOS inherit a minimal PATH (`/usr/bin:/bin:/usr/sbin:/sbin`) that doesn't include the app's own `Resources/cli` directory, so the agent's spawned shell genuinely couldn't see it. v1.25.4 prepends the bundled CLI directory to PATH when spawning the opencode agent host, so `command -v pandastudio` succeeds immediately. SKILL.md also flipped to lead with the CLI path (one bash tool covers ~150 verbs vs. one MCP tool schema per verb — significantly more token-efficient) and document MCP as the explicit fallback when the CLI isn't on PATH.
• Bundled CLI is on PATH for the embedded agent
• SKILL.md: CLI is preferred, MCP is fallback
v1.25.3
YouTube title overflow fix + thumbnail prompt rebuild. The Publish-to-YouTube dialog was silently passing AI-generated titles over the 100-char limit to the API, which rejected the upload with a confusing "invalid or empty video title" 400 — fixed in three layers (initial-state clamp, onChange clamp, IPC backstop) plus live character counters on Title (100) and Description (5000). The thumbnail prompt builder was rewritten to produce thumbnails that follow the actual YouTube formula — close-up REACTION FACE filling 50–60% of the frame, literal topic visible alongside, bold 2–4 word text overlay in the opposite corner — instead of decorative images with text bolted on. Compaction tuned for the small local LLM (Qwen3.5-2B) so it doesn't degenerate into repetition loops, plus a defensive post-processor that strips preambles, removes hallucinated 8K/60fps noise, and truncates if the model loops anyway.
• YouTube title length fixed in three layers
• Thumbnail prompt rebuilt around the actual YouTube formula
Caption drift fix — side-effect of v1.25.1's region-coordinate fix that surfaced in any project with trim regions. The animated caption renderer was reading from the same accumulator the overlay/audio path uses, which v1.25.1 changed from source-summed-time to output-time to make overlay activation match audio adelay. The merged transcript still stores word startMs in source-summed-time (sum of clip sourceDurationMs from project start), so captions and transcript words ended up in different coord systems and progressively drifted as the export advanced through clips. v1.25.2 tracks a separate source-summed prefix accumulator that the caption path uses, leaving the overlay/audio path on output-time. Two coordinates for two consumers, each correctly aligned with the data it reads.
• Captions stay in sync from start to end of multi-clip exports
v1.25.1
Two preview-vs-export divergences fixed for any project with trim/speed regions. (1) Region timestamps were treated as output-time by the export pipeline when they're actually stored in source-summed-time (sum of clip source durations from project start, ignoring trims). Preview's playhead is in the same source-summed space, so overlays activated correctly there; the export's renderer and audio mux were using the raw values as if they were post-trim output time. Result: an overlay placed at original-recording 27 s on a clip with 22 s of leading trim showed at output 5 s in preview but at output 27 s in export. v1.25.1 maps every region's startMs/endMs through a clip-segment-aware translator before the renderer activation check and before FFmpeg's adelay= — same arithmetic as the audio mux's atrim+concat, so visual and audio land on the same output instant by construction. (2) Audio drift compounding to ~920 ms by end of long multi-clip exports. The video decoder emits Math.ceil(srcDur/speed × fps) frames per kept segment (rounded up), but the audio mux was using precise atrim bounds — each segment's audio ended ~17 ms shorter than the corresponding video; across ~55 segments × 4 clips that compounded to nearly a second of lipsync slip by the end. Audio mux now pads each segment with apad+atrim to exactly frameCount/fps seconds, matching the video frame count by construction. Lip-sync stays tight from start to end.
• Overlay timestamps respect trims by mapping source-summed → output-time
• Frame-quantised audio segments eliminate lipsync drift in long exports
• renderer-debug-log IPC bridge for export observability
v1.25.0
Export pipeline collapsed from three tiers to one — preview parity is now guaranteed by construction. The export path used to fan out into three different code paths depending on what edits a project had: a stream-copy fast path for trim-only projects, an FFmpeg-filter-graph path for trim+speed, and the full PixiJS-rendered path for anything with visual effects. The first two were faster, but they bypassed the PixiJS composite — meaning preview showed one thing and export shipped a slightly different thing. Every "preview shows X but export shows Y" bug fixed during 1.24.x was a tier-divergence bug. v1.25.0 deletes the legacy tiers entirely; every export, including unedited screen recordings, now goes through the same PixiJS frame-by-frame pipeline that preview uses. Cost: a small speed regression on trivial exports (re-encoding a 5-min unedited screen recording is now ~25 s instead of ~3 s, hardware-accelerated on M-series). Benefit: a whole class of bugs cannot happen again. Also lands the audio-mux precision fix from the in-progress 1.24.9 patch — atrim/apad/anullsrc bounds now use microsecond precision (toFixed(6)) instead of millisecond (toFixed(3)), and the single-clip path normalises cleaned WAVs the same way the multi-clip path does. Multi-clip exports with cleaned audio + trims should now have zero perceptible lipsync drift, even across 100+ trim/speed segments. Plus: agent skill cache now hot-reloads from the public skills repo on every app launch, so SKILL.md edits propagate within minutes instead of waiting for an app rebuild — and the in-progress Anthropic Claude.ai OAuth integration was removed after testing showed Pro/Max subscription tokens hit aggressive rate limits in third-party clients. Anthropic models continue to work via API key.
• One export path, guaranteed preview parity
• Single source of truth for timeline-segment math
• AI working principles document — effort estimation
v1.24.8
Multi-clip projects finally export with full parity to preview, and background music actually plays. Three multi-clip export bugs caught at once: camera was missing because the renderer initialised webcam dimensions from the first clip only (so any later clip whose webcam loaded first had nothing to size against), layout drifted between clips because per-clip source dimensions weren't being updated on the renderer between clips, and lipsync was off in export because DeepFilterNet's cleaned WAV is quantised to 10 ms frames so its duration didn't quite match the source video's. All three fixed: renderer scans all clips for webcam dims at init, source/webcam dims update per clip in the export loop, and the cleaned WAV is length-normalised at the boundary plus padded/trimmed in the mux filter. Background music now plays across clip boundaries (the sync code was reading per-clip source time from `<video>` instead of cumulative edited time), inserts at the playhead instead of the timeline start, and no longer crashes when the volume slider goes above 100% (HTMLAudioElement throws above 1.0 — clamped). Plus drag-and-drop clip reorder with full region migration, right-click motion graphic → promote to intro/outro clip, agent chat persists per project with image attachments, the roundness slider works in screenCover layouts, and a new 3D Title Card template via three.js.
• Multi-clip export now matches preview — camera, layout, lipsync
• Background music plays across clips, at the playhead, without crashing
• Cleaned-audio preview no longer crackles
• Drag-and-drop clip reorder with full region migration
v1.24.7
The AI agent gets its tools back, and your conversation with it now sticks to the project. v1.24.6 shipped the agent with no MCP tool access — it could chat but couldn't actually read your project, transcripts, or regions, because the bundled MCP server was being spawned via Electron's binary without `ELECTRON_RUN_AS_NODE=1` and silently launched a second copy of the desktop app instead of running as Node. Symptom in the field: the agent fell back to shelling out to `which pandastudio` and `npx @writepanda/cli` — neither of which exists in production — and reported "PandaStudio MCP server is running?" Fixed by setting the right env on the spawn. And alongside that, agent chats now persist per project: open a project tomorrow and the conversation is right where you left it, same thread, same model. The opencode server already kept full transcripts in its own database — the only missing piece was remembering which session belonged to which project. A new "+ New session" button in the chat header drops the persisted thread when you want a clean start.
• AI agent has tool access in production again
• Per-project agent chat persistence + "+ New session" button
v1.24.6
Two production bugs caught by users on v1.24.5 and fixed the same day. The bundled AI agent (opencode) silently failed to launch in installed Mac builds — the wrapper script under node_modules has shebang `#!/usr/bin/env node`, and Electron apps started from Finder inherit a minimal PATH with no `node` on it, so `exec` died with code 127 before the script even ran. The agent tab showed `opencode server exited before binding (code=127, signal=null). stdout:` with empty stdout because the interpreter never started. PandaStudio now spawns the cached self-contained native opencode binary directly and bypasses the wrapper. Auto-transcribe also got stuck in a loop on clips that legitimately yielded zero recognised words (true silence, music-only clips, unrecognised speech) — the 'needs transcription' check matched any clip with a missing or empty transcript, so the same clip was picked again every time the empty result was saved. Empty transcripts are now treated as terminal; the user can manually re-run from the transcript panel if they suspect the result was wrong.
Three real bugs caught and fixed in a tight cycle. Recording was producing empty files on Electron 39 / Chrome 132 because MediaRecorder kept selecting AV1 codec — `isTypeSupported('video/webm;codecs=av1')` returned true but the encoder silently emitted no frames. Every Stop button click resolved to a 0-byte Blob, the finalizer's empty-blob guard returned early, and nothing saved. AV1 dropped from the preferred codec list. The aspect-ratio picker on the Home screen wasn't actually constraining the camera — it only flowed to the preview window, not the recorder, so iPhone Continuity Camera and capture-card setups silently delivered portrait video even when 16:9 was selected. Now the picked aspect builds proper getUserMedia constraints. And the floating preview no longer goes black during recording when you use a built-in webcam — only virtual cams (EOS Webcam Utility, OBS Virtual Cam, Camo, iPhone Continuity, NVIDIA Broadcast, Snap, mmhmm, Loopback) trigger the pause-preview workaround they need, and they show a clear 'Preview is not available for virtual webcams during recording' placeholder instead of just black.
• Recording works again — AV1 codec dropped
• Camera aspect ratio actually applies now
• Floating preview stays live during recording for built-in webcams
v1.24.4
The architectural fix that v1.24.3 set up but couldn't fully deliver. v1.24.3 made virtual-cam recordings stop capturing the placeholder frame, but it had to pause the floating preview during recording — DSLR / iPhone Continuity Camera users who specifically want to see themselves while recording were left with a black preview window. Wrong tradeoff. v1.24.4 inverts the architecture entirely: the camera preview window is now the SOLE getUserMedia consumer for the physical device, and live VideoFrames flow to the recorder via an Electron MessageChannel using MediaStreamTrackProcessor + MediaStreamTrackGenerator. One physical consumer, two windows seeing live frames. Result: preview stays live during recording for ALL cameras (built-in + every virtual cam — EOS Webcam Utility, OBS Virtual Cam, Camo, iPhone Continuity Camera, NVIDIA Broadcast, Snap Camera, mmhmm), recordings capture the live feed correctly, no 250 ms pause on Record click.
• Single getUserMedia consumer + cross-window VideoFrame relay
• Removed: pause/resume cycle, 250 ms Record-click latency, Recording-overlay UI
v1.24.3
Patch for v1.24.2. Two camera bugs that surfaced when a creator connected a Canon DSLR through EOS Webcam Utility — and almost certainly affected anyone using OBS Virtual Camera, Camo, or iPhone-as-webcam too. First: switching cameras in the recorder dropdown silently kept showing the old camera; the workaround was to disable webcam, then re-enable it. Second, the worse one: recordings made with virtual cameras came out with the cam's static placeholder image instead of the live feed, even though the preview window had been showing live frames seconds before clicking Record. Both fixed at the IPC layer.
• Live camera switching — no more disable + re-enable
• Virtual-cam recordings stop capturing the placeholder frame
v1.24.2
Tiny but satisfying patch: stale agent processes that used to accumulate across PandaStudio launches now get swept automatically. The bundled AI agent harness (opencode) was leaking child processes whenever the parent app shut down dirty — a force-quit, a kernel panic, killing the dev server with Ctrl+C, anything that didn't fire the normal before-quit hook. The orphaned process got reparented to launchd and sat there forever, holding a port and ~100MB of RAM. Over a few weeks of force-quits you'd accumulate 10+ stragglers. Now every spawned opencode PID is recorded to a per-user pidfile; on the next app launch we read that file and SIGTERM → SIGKILL anything still alive that we recorded as ours, then rewrite the file empty. stopOpencodeServer also escalates SIGTERM → SIGKILL after a 2-second grace so a wedged child can't survive a normal shutdown either. Net effect: even after a dirty exit, the next launch leaves you with exactly one opencode process. No accumulation across launches — ever.
• Orphaned agent-server cleanup, the right way
v1.24.1
Patch for v1.24.0. Three bugs that surfaced once people started actually publishing the videos they exported: AI-generated thumbnails were saved as WebP, but YouTube's thumbnails.set endpoint rejects image/webp ("invalid image") — so every fresh thumbnail was failing on upload. Fixed: gpt-image-2 now outputs PNG, the FFmpeg crop pipeline writes PNG, and the YouTube uploader transparently transcodes any leftover .webp file to PNG via FFmpeg before sending. Also: clicking the description field in the export-library content tab was throwing a ReferenceError and breaking the panel layout (the keyboard-hint span referenced process.platform, which doesn't exist in the renderer) — fixed with a navigator-based platform check. And the thumbnail buttons now show an inline spinner while generating instead of just going disabled, plus a new "Download" button copies the canonical thumbnail to a user-chosen location.
• Thumbnails generated as PNG (not WebP) — Publish to YouTube works
• Description field stops crashing on click
• Thumbnail buttons show a spinner while working
• Download button — save the thumbnail to your computer
v1.24.0
The convergence release. PandaStudio used to ship two parallel render pipelines: a Tier-3 PixiJS path that drove the live preview and the in-app Export Video button, and a separate Rust + Skia native render-helper that served agent-driven exports. Same project, two pipelines, two sets of bugs. The Skia path was slower by an order of magnitude on large projects and had a recurring audio-drift bug where SFX trailed the visuals they were attached to. v1.24.0 deletes the Skia path entirely — the Rust crate, the native binary, the IPC handler, the electron-builder packaging — and routes agent exports through the same Tier-3 pipeline the UI button uses, via a hidden BrowserWindow when no editor is open. One render path. Identical output regardless of who initiated the export. Plus a critical fix to the source-vs-edited time accounting in the Tier-3 exporter that was causing video overlays + zooms to render at the wrong encoded frame when trim regions were present, making SFX appear to lag the visuals in export while preview stayed in sync.
• One export pipeline — Tier-3 PixiJS for everyone
• Agent-export dispatcher — reuses your editor or spawns a hidden one
• Source-vs-edited time fix — overlays + SFX now stay in sync in export
Patch for v1.23.2. The agent's chat panel was disappearing mid-conversation: every time the agent finished an edit and called preview.show (the canonical "show me what you did" verb), the editor BrowserWindow was destroyed and recreated, which wiped the renderer process and took the chat transcript with it. v1.23.2 patched the same hazard in project.open but missed the three sibling verbs (preview.show, window.preview, window.editor) that have identical behaviour. v1.23.3 extracts the soft-open logic into a shared helper and applies it everywhere — when the editor is already showing the target project, the verb refreshes from disk + focuses the existing window instead of recreating it. AgentChatPanel keeps its chatId, transcript, and OAuth state across edits.
• Agent chat survives across the agent's own "preview" calls
v1.23.2
The frosted-glass release. Motion graphics now ship with proper backdrop-blur — when you add a glass card, the camera behind the graphic's exact alpha shape gets blurred, like every modern editor (Premiere, CapCut, DaVinci) does. Implemented end-to-end across all three render paths (preview, Skia exporter, Tier-3 PixiJS) with alpha-driven masking, so the blur follows the graphic's content shape — no rectangular halo. Plus: a new "Remix with AI" button on every motion-graphic template hands the template's HTML to the embedded agent as a visual reference and lets you describe what to change in plain English. The agent re-authors a custom variant that matches the template's look while restaging timing, content, and layout for your specific narrative. Templates stop being slot-fill containers; they start being inspirational examples. Several agent-side polish fixes too — the chat panel finally streams narration around tool calls (was dropping post-tool text), the live template preview actually animates instead of showing literal {{title}} placeholders, and the clip-transform inspector lives inside the sidebar instead of pushing it below the viewport.
• Frosted-glass backdrop blur — first-class effect on any overlay
• Glass mode for motion-graphic templates
• Remix with AI — templates as inspirational examples, not rigid slot-fills
• Live template preview actually animates
v1.23.1
Patch for v1.23.0. The bundled opencode agent binary was missing from the production Mac/Windows packages — the AI tab crashed with ENOENT on the first prompt because the package that contains the binary was in devDependencies and electron-builder strips those from the shipped app. Moved to dependencies and rebuilt; the 103 MB native binary is now baked into both architectures and the AI tab works on first launch. If you installed v1.23.0, the in-app updater will pull this patch automatically.
• Agent binary actually ships now
v1.23.0
AI agent chat lands in PandaStudio — opencode-backed multi-provider chat (ChatGPT subscription via OAuth, OpenAI API, Anthropic, Moonshot Kimi, Google, and more) with full editor context, friendly tool labels, and persistent state across tab switches. Plus three smaller fixes that have been bugging us: clip-transform regions now keep the camera on top of media overlays in every render path, music overlays default to a polite 5% volume, and export quality is finally a proper option in the Export dialog instead of an always-visible strip in the sidebar footer. Intel-Mac users also get Clean Audio back — the deep-filter binary was silently missing from the Intel dmg since v1.8.2 and is now baked in.
• AI agent chat panel
• Editor context, never in the transcript
• First-run notice + persistent chat
• Clip-transform layering: main camera stays on top
v1.22.0
Three releases worth of work consolidated. The headline: clip-transform regions — a new way to compose talking-head and explainer videos where the camera shrinks during a motion-graphic beat (camera in the bottom half of a 9:16 Short while the graphic plays up top, or camera as a right-portrait card on a 16:9 explainer in the Ali-Abdaal style) and slides back to full-frame when the beat ends. Shipped end-to-end across preview, export, automation, and the editor UI. Plus: B-roll image generation via your Replicate API key, agency-grade workspace context for cross-workspace safety, default zoom softened to 1.5× with a swoosh, FX timeline regions can now be drag-resized, and the export pipeline matches the preview frame-for-frame on every code path.
• Clip-transform regions — the explainer-beat layout
• Manual UI for clip-transform — timeline track + inspector
• Export bug fix: clip-transform applies on every code path
• FX timeline regions: drag-to-resize is back
v1.19.1
Quality release. Three timeline-editor bugs fixed (timeline zoom no longer resets when you split a clip, zooms now apply on second-and-beyond clips in multi-clip projects, individual sub-tile selection + drag-to-resize are back in multi-clip mode). YouTube-publish polish: external links open in your default browser so your real YouTube session is used; thumbnail upload failures surface the actual reason instead of silently succeeding. And the big one for agent users: motion-graphics quality is now governed by an aesthetic contract (11 Laws + visual vocabulary + 3-mode delivery playbook) so agent-authored motion graphics aim for HyperFrames-demo quality instead of template-filled defaults.
• Timeline zoom survives splits
• Zooms apply on all clips in multi-clip projects
• Individual sub-tile selection + drag-to-resize in multi-clip mode
• External links open in your real browser
v1.19.0
Two big additions: Workspaces (multi-client isolation for agencies and consultants — every project, export, and integration scoped to its workspace) and YouTube publishing (OAuth-connect your Google account, upload directly from the Export Library with custom thumbnails, metadata, and privacy settings). The YouTube refresh token stays encrypted on your machine via the OS keychain — it never leaves the device.
• Workspaces — keep clients separate
• Publish to YouTube from PandaStudio
• Local-only YouTube auth — no backend, no data leaves
• External links open in your real browser
v1.17.1
Agent-authored motion graphics are now frame-perfect. The in-house Puppeteer+FFmpeg render path has been replaced with HyperFrames (HeyGen's open-source Apache-2.0 engine) for deterministic capture via Chrome's BeginFrame API — every frame lands at its exact composition time, no more "text flew past in the first 200ms" bugs. The installer is ~40% smaller than it would have been by bundling only the headless Chromium variant both render paths can share.
• Frame-perfect motion.render-html via HyperFrames
• Concrete authoring contract + pacing rules for agents
• Installer ~40% smaller — one Chromium, two render paths
• Common-mistakes list + non-GSAP escape hatch
v1.16.0
Audio overlays are now first-class timeline regions — drag, trim, see a real waveform. Fixed a long-standing preview bug where music didn't play (export was always correct). Music panel now previews each bundled track before adding. Agents get a full SaaS-promo playbook, image-tilt rule, and a no-static-scene motion rule.
• Music + VO on the timeline, not in a sidebar
• Preview music finally plays in preview
• Music-preview button in the Audio tab
• Richer music library with agent-routing tags
v1.15.1
Anchored zooms (survive trims + speed edits), preview plays cleaned audio + music immediately, agent exports match manual exports, and the Settings modal now shows your version + an Update button on every platform.
• Zooms anchor to source-time landmarks
• New project.add-zoom argument: anchorSourceMs
• Anchor types and behavior
• Cleaned audio plays in preview without a restart
v1.14.1
Three agent-workflow fixes — live editor refresh when an agent writes, reliable Copy Project ID, and motion graphics rendering in preview.
• Editor auto-refreshes when an agent edits
• Copy Project ID actually copies
• Agent-added motion graphics render in preview
v1.14.0
Sound effects for zooms and motion graphics, fast project lookup via SQLite index, and a clutch of editor + export fixes.
• Zoom + motion-graphic sound effects
• Agent API for SFX
• project.current — target what's open
• Fast project lookup (SQLite index)
v1.13.0
Transparent overlay motion graphics — agents and the export pipeline now fully support WebM/VP9 alpha overlays composited over video.
• motion.screenshot — validate layout in under a second
• motion.concat — assemble multi-scene promos into one MP4
• project.add-audio / project.remove-audio — background music for projects
• motion.render-html: bake audio into rendered clips
v1.9.5
Arbitrary motion-graphic HTML rendering — no template wall for Claude Code.
• motion.render-html — author the animation, we'll render it
• Why the escape hatch exists
• Locked-down render window
• MCP tool + Skill docs updated
v1.9.4
preview.show now opens the editor focused on the project — same one-call UX from the agent's POV, but using the editor's battle-tested preview pane instead of a parallel chromeless window.
• Simpler 'show me' surface
• Why the change
• @writepanda/cli@1.9.4 + @writepanda/mcp@1.9.4 on npm
v1.9.3
MCP server + npm-distributed CLI. Cursor, Continue, Cline, Claude Desktop — every MCP-compliant agent can now drive PandaStudio.
• @writepanda/mcp — Model Context Protocol server on npm
• @writepanda/cli — CLI on npm too
• Three install paths, one underlying surface
• pandastudio_call escape hatch
v1.9.2
PandaStudio is now agent-editable. Full CLI surface, transcript-based editing, headless export, and a floating preview overlay AI agents can pop up at will.
• Local CLI — drive PandaStudio from the command line
• Claude Skill bundle — one-click install for AI agents
• Transcript-based editing from the CLI
• Floating preview overlay — agents show their work
v1.8.7
Lower thirds, FX overlays, bundled sound library, and end-to-end multi-clip polish.