What has been shipping

Newest first. Latest is 0.22.0, 24 Oct 2026. A ring is a ship day. GitHub ↗ · RSS

515 commits over 90 days, 9 days with a release.

Shipping activity

LessMoreRelease

0.22.0

GitHub ↗
  • #157 88481f0 Crops can be set by hand on top of what framing decides. Right-click the picture in the editor (or a section on the timeline, or the Crop… button on a section) for Set crop…, which fixes the pane under the pointer to an exact part of the source: a box to drag, resize or draw over the whole source frame, with the numbers beside it, starting from what shows now; a split's two panes, a stack's screen and speaker, and a fitted frame each take their own. A crop shaped like the pane fills it, any other shape is fitted over a blurred copy like a webcam tile, and dragging the picture moves a fixed crop. Over MCP, update_clip sections take crop, crop2 and contentCrop. The hook on the preview has the same right-click menu as a text layer: edit it in place (or double-click it), centre it, reset its position, or hide it.
  • #157 c1501c1 One clip's framing for the whole project. For a recording whose layout never changes (a slide deck with a webcam tile, a fixed camera), set the framing on one clip and pick "Use for all N clips…" on its Framing tab: the section's mode and its nudge, subject or crop become the project's framing (reframe and the new reframeAdjust setting), every clip's own sections are cleared, the finished clips re-render, and clips added later get it too. A clip without framing of its own now shows and renders the project's framing; editing it makes the clip's own, and "Use the project framing" takes it back. Over MCP apply_framing does the same from a clip id, reframeAdjust is a project setting like the others, and the CLI has apply-framing.
  • #157 6735b9a Screen + speaker framing finds the webcam tile (the picture-in-picture box of a Zoom, Teams, Meet or OBS recording) around the speaker's face and shows just that tile in the speaker pane, instead of a face-sized crop that reached into the slides, the black column or the name plate. A tile in a flat band along a frame edge drops that band from the top pane, so the speaker is not shown twice, and a webcam too small for the face detector most of the time is still framed as a stack when its tile stands steady. A forced Screen + speaker section gets the same tile, and a drag on the speaker pane still nudges it. The framing eval gained tile cases for a webinar recording and a corner-webcam screencast.
  • #157 d75a456 A re-rendered clip plays at once. The clip's video and thumbnail are served at a URL that never changes, with an hour-long cache, so after a re-render the project page and the clip preview could replay the previous render for up to an hour (a moved caption or a new crop looked as if it had not been applied). The clip media now carries an ETag and asks the browser to check before replaying, so an unchanged file still costs one small request and a re-rendered one is fetched anew.

0.21.0

GitHub ↗
  • #155 1a5a370 Changelog at reelsaw.com/releases (GitHub feed, 90-day commit heatmap). The app's What's new, version line and update banner link there; list_releases and reelsaw releases read the same feed.

0.20.0

GitHub ↗
  • #153 90ef339 Layers on the editor's 9:16 preview have a right-click menu (edit text, centre, show for the whole clip, bring to front / send to back, copy, duplicate, remove) and a text layer can be retyped in place with a double-click. The Layers lane's right-click menu gained Template…, and applying a template keeps a clip's existing layers unless Replace is chosen.
  • #153 d64e671 Layer templates: save a look once (a logo pop in the first seconds, a follow card at the end, a watermark or a music bed) and put it on any clip whatever its length. Template layers are timed from the start, from the end, over the whole clip or as a share of the clip, so they stretch and contract with each clip. Build one from a clip's layers or in the template editor, apply it to selected clips (replacing or adding to their layers, with an optional re-render) or set it on a project so every new clip gets it. Also available as the list_layer_templates, save_layer_template, update_layer_template, remove_layer_template, restore_layer_template and apply_layer_template MCP tools and the reelsaw templates command.

0.19.1

GitHub ↗
  • #151 d579380 Giphy GIFs play in the library and land on a clip as a small looping sticker you can drag and resize. Adding a catalog or provider item no longer shows it as removed from the library.

0.19.0

GitHub ↗
  • #147 d08a8e5 Operators can set a forgotten password from the shell without email: reelsaw set-password you@example.com. --must-change signs them in with that temporary password and then a blocking page asks for a new one (no current-password field). Other devices are signed out; API keys keep working.
  • #147 d08a8e5 Sign-in has Forgot password. When email is on, it sends a 24-hour reset link, and choosing a new password signs out other devices.
  • #150 31a78a1 Catalog and provider items are no longer saved into your library. Search them from the library or editor and add them to a clip; they stay on the instance while a clip uses them.
  • #149 99e57c4 Searching the library no longer calls Iconify (or other remote providers) with an empty query, which used to return an error as you started typing.
  • #149 99e57c4 After a deploy, a tab that still has the old page reloads itself when nothing is unsaved. If you are in the middle of editing a clip, a header chip asks you to save first, then refresh.

0.18.2

GitHub ↗
  • #135 ba237ac Dependency updates across the app: AI SDK providers and ai 7.0.150, AWS S3 SDK 3.1156, better-auth 1.7.12, posthog, react 19.3.1, react-router 8.5, react-query, lucide icons, vite 8.3.5. OpenTelemetry stays on the 2.12 / 0.223 line and API 1.9 until the SDK moves to 3.0 as a set.
  • #117 1f2cdbe Dependency fix: body-parser 2.4.0 (GHSA-27r3-jxmh-p828, a denial of service through trailing bytes after a compressed request, reachable through the MCP endpoint's Express layer). The image's base layers are now pinned by digest and Dependabot keeps them, the npm packages and the workflow actions current.
  • #111 ff53ef5 Reelsaw is published to the official MCP registry as io.github.osbytes/reelsaw on every release, and the Docker image carries the registry's server-name label, so registry-aware clients can install the reelsaw mcp bridge straight from the image.
  • #124 2a50493 The image is back on Node 22 LTS (an automated bump had moved it to Node 25, which is not an LTS line and was never built by CI). Automated base-image updates now stay within the major.
  • #131 4cc0fb7 Dependency fixes: nodemailer 10.2.1 (three address-parser advisories, GHSA-8c8m-p3m8-cjg8, GHSA-m943-m63m-w62w, GHSA-85x2-q946-cp5h) and fast-uri 3.1.9 (four URI parsing advisories reached through the MCP SDK's ajv). Each release's install folder now ships with a provenance attestation next to the zip.

0.18.1

GitHub ↗
  • #105 b8f29a7 The arm64 image starts again: SVG rasterising uses resvg compiled to WebAssembly instead of a native package that only existed for the build host's architecture.

0.17.2

GitHub ↗
  • #100 4f94838 On a phone, the selected-clips action bar stays on screen while the browser URL bar is showing. Full-height shells now follow the visible viewport (100dvh) instead of 100vh, which is taller than the screen with chrome visible.

0.17.1

GitHub ↗
  • #97 11c78d7 Project failures show a short plain-language message instead of a wall of yt-dlp stderr. Admins see operator hints (env keys) and optional technical details; everyone else gets a generic line with no platform details. Download errors from a broken proxy are explained clearly.
  • #99 bd478e4 App and transactional emails link to the source on GitHub (github.com/osbytes/reelsaw): login and pending pages, the account menu, Settings next to the version, and the email footer (HTML and plain text).

0.17.0

GitHub ↗
  • #95 2c67f49 Library: "used by" now counts every role an item plays (intro, outro, overlay, music track) and the usage list says which, per project and clip; items can be renamed from the card or the viewer; music plays in place on the card and in the viewer. list_bumpers adds usedByClips and url (the file), bumper_usage returns the roles per clip with overlay and music counts.

0.16.0

GitHub ↗
  • Background music from the library plays under a clip: several tracks per clip on their own lane, each with window, offset, level, fade and loop, loudness-normalised and ducked while someone speaks. Captions and transcripts export as SRT/VTT (routes, zip, MCP, CLI), and an SRT/VTT file can be imported as a project's transcript. Text overlays take a font from the image (DejaVu, Liberation, Roboto, Open Sans, Lato, Inter, Bebas Neue), and ⌘C/⌘V copy and paste overlays and tracks in the editor. New: clips.audio, clips.captions, update_clip { audio }, get_clip_captions, get_project_transcript_file, import_transcript, reelsaw clip-audio, captions, transcript-file, import-transcript, GET /api/fonts/:family.
  • #92 0f3a7dd Keyboard shortcuts go through one binding helper (react-hotkeys-hook) instead of hand-rolled listeners, so the typing rule and the platform modifier are the same on every screen. ⌘K no longer splits framing in the clip editor; it only opens the command palette (⌘B splits, as the ? sheet says).

0.15.0

GitHub ↗
  • #89 43ecc28 Clip editor: per-pane focus in split framing with follow awareness (drag either speaker; drop a pane on someone else to follow them), an Overlays lane for library images, videos and lines of text, intro/outro as blocks on the clip track, and one action bar with the preview's controls in a canvas header. The watermark is now the logo with the site name under it, top-left outside the platforms' dead zones. New: clips.overlays, update_clip { overlays }, reelsaw clip-overlays, WATERMARK_LOGO_PATH.

0.14.0

GitHub ↗
  • #83 65c0b7e When OpenTelemetry points at Sentry, traces and logs go to Sentry's OTLP endpoint, and metrics go through the Sentry SDK. Sentry does not accept OTLP metrics. Logs are the same pino lines as the local log, with prompts, transcripts and secret values left out. The browser records traces on the same rate (OTEL_TRACES_SAMPLE_RATE, default all of them) and its API calls, including live subscriptions, stay on the server's trace.
  • #85 dd23f2b Signing in to an account that is waiting for approval shows that waiting message instead of "Email not verified". The sign-in form asks for the current password, so a password manager does not generate a new one that was never stored. A repeat sign-up for an existing email is refused instead of looking successful.

0.13.0

GitHub ↗
  • #80 8ba227c Show each API and worker process under Settings → System → Workers, and a Queue section for live job depth, failed work, and bulk retry after a platform fix. A failed-work row opens the recorded reason (Retry, Copy, Open project); #queue&fail=kind:id deep-links it. Admins get the same from list_workers / get_queue / list_failures / get_failure / retry_failures and reelsaw workers / reelsaw queue / reelsaw failure / reelsaw retry-failures.
  • #80 8ba227c Admins can tick **Instance-wide diagnostics** on Report an issue to include unfinished work, failed jobs, usage and error logs across every account — not only their own projects. reelsaw report --instance and the report_issue MCP tool do the same.

0.12.0

GitHub ↗
  • #77 16f9d5b YTDLP_PROXY accepts one URL or an operator-ranked pool. Priority is what you set; a circuit breaker skips a candidate after consecutive faults and never lets a more reliable expensive proxy overtake a healthy cheaper one. reelsaw ytdlp-proxies shows the pool without URLs.
  • #76 c3b33b4 Ingest fails immediately when the worker disk cannot hold MIN_FREE_DISK_MB plus the source (instead of waiting 900 s and retrying). Uploads reserve their actual size, and the UI says Preparing rather than Downloading.

0.11.6

GitHub ↗
  • #74 eb5ee1f Admins can turn the watermark off (or on) for one account from Users → Limits. Follow / Always / Never saves and applies on the next render; reelsaw limits <email> --watermark always|never|follow does the same.

0.11.5

GitHub ↗
  • #73 31561b7 Clips are picked throughout the video instead of clustering in the first couple of minutes. Each map pass now looks at a short overlapping window, and a second pass only runs when the first picks leave a long uncovered stretch. Existing projects pick this up on re-analyze.

0.11.4

GitHub ↗
  • #69 f841d61 OpenTelemetry is clearer to wire and works in the browser too: the server exports traces with explicit OTLP URLs/headers (Sentry destinations skip metrics), and when OTEL is on the web app gets the same public endpoint from system.status and sends browser traces. SENTRY_DSN stays separate from OTEL — set OTEL_EXPORTER_OTLP_* yourself.

0.11.3

GitHub ↗
  • #67 4ca10a5 On hosted instances with Sentry or PostHog, "Report an issue" sends feedback through those channels instead of a zip download. Instance system info and recent errors stay available only for self-host and admins, so a hosted account cannot export another user's diagnostics.

0.11.2

GitHub ↗
  • #64 c093611 Transactional emails (verify, reset password, approved, waiting for approval) now send branded HTML with a clear button, plus the same links in plain text. No tracking.
  • #65 bbbae38 pnpm stripe:setup rebuilds @reelsaw/shared first so a stale shared build cannot miss exports like billingPath.

0.11.1

GitHub ↗
  • #62 673bd6d The image entrypoint now chowns a volume-mounted DATA_DIR (e.g. Railway) before dropping to node, so boot no longer fails with EACCES on /data/uploads.
  • #60 df7d4ab A budgeted batch loop (retention sweeps, purges) always makes one batch of progress before honouring its deadline, so a budget that is already spent when the loop starts cannot leave the cursor in place forever. Also fixes the timing-sensitive unit test that failed on a slow CI runner.

0.11.0

GitHub ↗
  • #53 1ac8156 Plans and billing for hosted instances (enterprise edition), a monthly minutes quota, and a watermark for accounts that are not admins.
  • MAX_SOURCE_MINUTES_PER_MONTH joins the quotas: minutes of source video per billing period (or UTC calendar month), with the usual refusal sentence and per-user override.
  • WATERMARK_NON_ADMINS (default on) burns WATERMARK_TEXT into the clips of non-admin accounts through the caption file; admins switch it per user on the Users page (Limits), a paid plan removes it, and each clip records whether it was rendered with it. **Upgrade:** multi-user installs that do not want this set WATERMARK_NON_ADMINS=false (Settings → System → Limits works without a restart).
  • REELSAW_EE=true with STRIPE_SECRET_KEY / STRIPE_WEBHOOK_SECRET loads apps/server/src/ee (its own licence, see LICENSING.md): Free / Starter / Creator / Pro plans (priced like OpenShorts Cloud) whose limits sit between the instance setting and the admin's per-user override, Stripe Checkout and Billing Portal from Settings → Billing, get_billing / billing_checkout_url over MCP, reelsaw billing on the CLI. Webhooks are recorded and queued in one transaction and the account's row is rewritten from Stripe by a job, so late, duplicate or reordered events converge; a daily reconcile and reelsaw billing sync repair lost ones. pnpm stripe:setup creates the Stripe objects; pnpm stripe:mock stands in for Stripe in development. Self-hosted installs are unchanged apart from the two settings above.
  • Free-tier abuse guards, off unless set: MAX_SIGNUPS_PER_IP_PER_DAY, BLOCK_DISPOSABLE_EMAILS, one account per real mailbox (user.email_key, backfilled by the migration), MAX_REQUESTS_PER_MINUTE / _HOUR on changes per account, and hourly abuse flags on the Users page (reelsaw abuse). TRUST_PROXY (default on) names which headers carry the client address.
  • Optional Sentry (SENTRY_DSN) and PostHog (POSTHOG_KEY, POSTHOG_HOST) across server and web: errors from boot, 5xx API calls, final job failures and render crashes; product events for sign-ups, projects, billing and abuse flags; page views and a few actions in the browser. Off unless set.
  • #51 defa355 Refine after transcription (name fixes, filler removal, the filler model pass, and scene cuts) is opt-in: turn steps on per project or in Project defaults, with instance ceilings under Settings → System → Pipeline.
  • #57 57528f2 CTC forced alignment no longer treats adjacent repeated letters without a blank as a valid path, so words like "hello" get legal letter spans at cut seams.

0.10.2

GitHub ↗
  • #47 8dfaeae Add local-qwen14-cpu / local-qwen14-gpu bench profiles and bench:e2e --gpu (NVENC for the isolated bench app). Fix the e2e driver on Windows (fileURLToPath for the repo root cwd, resolve docker.exe via where.exe).

0.10.1

GitHub ↗
  • #45 eeb1933 Link downloads now report progress ("Downloading 42% of 1.57GiB at 5.00MiB/s"): yt-dlp's --print-json silenced its progress lines, and they were read from the wrong stream. "Download finished in …" shows the download's wall clock instead of the video's length, and processing-time estimates no longer learn from the bad ingest samples.

0.10.0

GitHub ↗
  • #41 c48aeb5 Use the GPU where it pays. docker-compose.gpu.yml hands an NVIDIA card to Speaches (SPEACHES_IMAGE=ghcr.io/speaches-ai/speaches:latest-cuda, so faster-whisper-large-v3 transcribes faster than small did on the CPU), to Ollama in a container, and to the app, where ffmpeg now encodes clips, intros and outros with h264_nvenc when FFMPEG_ENCODER=auto finds it at boot (VideoToolbox on a Mac outside Docker); a hardware encoder that fails mid-render falls back to libx264 for that clip. ONNX_EXECUTION_PROVIDER moves the face, text and alignment models to CUDA, CoreML or DirectML with a CPU fallback (CPU stays the default: measured faster on Apple silicon). Settings → System → Overview and the new reelsaw machine command show the GPU the process sees, the encoder in use and why, and where each on-device model runs.
  • #41 9324f80 The one-command installers (install.sh, install.ps1) now look at the machine before doing anything: RAM, an NVIDIA GPU and its VRAM, Docker's memory, free disk, an Ollama already running and the models it has, and the port. They print a plan and ask three questions (local Ollama or a hosted provider, which model, go ahead), install Ollama when it is missing and you chose local, reuse a good model Ollama already has, pick the model by VRAM when a GPU serves it, move a busy port, and put Ollama, Speaches and the app on the GPU when the NVIDIA Container Toolkit is present. Hosted providers (OpenAI, Anthropic, Google, Groq, Vercel AI Gateway) are a choice in the same prompt. REELSAW_YES=1 takes the proposed answers, REELSAW_DRY_RUN=1 prints the plan and stops; re-running upgrades an existing install.
  • #44 9ba8669 Detect the GPU on Docker Desktop (WSL2) via /dev/dxg when nvidia-smi and /dev/nvidia0 are missing, document that Windows .env must use ; in COMPOSE_FILE (a colon is the drive-letter separator), and keep pnpm docs:gen defaults as POSIX paths on Windows.

0.9.0

GitHub ↗
  • #35 21cc500 Admins can change instance settings without a restart: sign-up mode, email verification, captcha, legal links, per-account quotas, upload limits, retention, the stall watchdog, the update check and whether /api/health shows machine numbers. The environment stays the default; what an admin saves under Settings → System, with reelsaw settings or the set_instance_settings MCP tool overrides it for every process within seconds, is validated as a whole and audited. The Settings page is split into Account and System tabs, and project cards keep one height whatever the title length.