Rive Animation Viewer
September 2, 2026 · View on GitHub
A local and desktop viewer for .riv files with runtime controls, JavaScript configuration editing, ViewModelInstance debugging tools, standalone export, a bundled native MCP sidecar, and desktop auto-update support.
Release
- Prepared release candidate:
2.5.4(awaiting signed GitHub build and updater acceptance). - Until 2.5.4 is published, public downloads and the normal public
latest.jsonupdater feed continue to deliver 2.5.3. - Release source will be the exact
chore(release): v2.5.4commit onmain. - macOS downloads and updater apps are Developer ID signed, notarized, and stapled; updater payloads retain their separate update signatures.
Regression Gates
The repo now has explicit prebuild guards for the surfaces that were regressing during the 2.1.x window-chrome and export hardening work:
npm run check:architectureenforces file-size and folder-shape budgetsnpm run check:depsenforces dependency-cruiser import boundariestests/smoke/ui-regressions.smoke.test.jsprotects the shared scrollbar contract, custom window-chrome structure, Tauri window config, and exported demo chrome contracttests/unit/ui/window-chrome.test.jsprotects desktop window-control wiring and Tauri/non-Tauri behavior splitnpm run testruns the full Vitest suite before every package buildcargo check --manifest-path src-tauri/Cargo.tomlvalidates the native Tauri layer
These gates materially reduce regression risk, but they are still code- and DOM-contract tests, not full visual snapshot coverage. If we want pixel-level guarantees from this point forward, the next step is adding screenshot-based desktop smoke tests for the packaged app window.
2.5.4 Web 2.41.1 / runtime-v0.1.344 and MCP Authority
- Exact Web 2.41.1 playback: The candidate is bound to released Web 2.41.1 / runtime-v0.1.344. A single state machine uses the released singular
stateMachineoption. Multiple machines, mixed animation/state-machine playback, older runtimes, and existing plural editor configs retain the 2.x path. - Complete compatibility surfaces: The live viewer, reset flow, generated CDN/local snippets, and standalone demos share the same runtime-version boundary while retaining no-target behavior, state-machine inputs, callbacks, text runs, ViewModel-first binding, and global ViewModels.
- Authoritative evaluation:
rav_evaldefaults to the active isolated playback child, supports strictplaybackand diagnostichosttargets, labels the surface/session used, and never replays arbitrary eval into a replacement child. - Explicit console limits: MCP console tools continue to operate on the host UI transcript; they do not claim isolated-child
console.*or live Luau-output authority. - Current dependency locks: Compatible JavaScript, MCP, website, and Rust updates remove current npm advisories without taking speculative framework/tooling majors.
- Purpose-built timeline transport: Linear animations get a row above the status bar with frame/second modes, duration-aware ticks, a large unclipped playhead, drag-to-seek, and a current-time indicator that advances on every rendered animation frame. State machines keep the row hidden.
- Lean snippets, complete standalone exports: CDN/local snippets contain animation setup plus only the selected typed accessors on
window.riveProperties; standalone HTML remains the self-contained output with the runtime, embedded file, UI chrome, controls, and selected-value restoration. - Compact property controls: Color properties use square swatches, while numeric fields reserve enough width for values and native spinner controls.
- One-click
.rivownership: On macOS, MAKE DEFAULT assigns the effective extension association in one action while RAV dynamically discovers registered.rividentifiers for diagnostics and extension-level icon compatibility. - Centered file metadata: Intrinsically sized file metadata sits in equal flexible title-bar columns, keeping its visible center aligned to the real window center while long paths still truncate.
2.5.3 Global VM and Canvas Capture
- Global VM controls: A collapsed
GLOBAL VMsection sits aboveROOT VM. Every file-level global ViewModel used by the animation has its own independently expandable tree, so global and artboard-bound controls can be inspected and changed together. - Complete MCP discovery: Fresh MCP activation advertises 49 unique tools. Six named global-VM operations inspect, read, write, fire, set images, and clear images without colliding with the root VM.
- Rendered-canvas screenshots:
rav_capture_canvasreturns the authoritative RAV canvas as PNG image content with exact byte length, dimensions, renderer, surface, background, and bounded-downscale metadata. - Stable RAV chrome: Native flyouts clip their dark backgrounds to the rounded yellow frame. Console warning and error rows use the RAV palette, and first-open JS-console virtualization no longer flickers between painted and blank rows.
2.5.2 Reliability Update
- Switch without flicker: File, artboard, playback-target, and ViewModel-instance changes keep the last confirmed frame visible until the replacement is ready. Rapid changes discard stale work instead of surfacing blank frames or first-frame errors.
- Controls match the canvas: Scalars, booleans, images, authored instances, and runtime-generated list instances remain synchronized in both directions. Image slots stay independent, and Reset plus Properties
DEFAULTupdate playback and controls together. - Timeline progress: Timeline playback shows current and total frames or seconds in a compact meter that stays hidden for state machines.
- Reliable warm opens: Opening another
.rivwhile RAV is already running queues the request and replaces the active file without racing playback activation. - Stable overlays: Settings, MCP Setup, About, and export remain above playback without stopping it, close from any outside click, and keep consistent RAV chrome, focus, corners, and scrollbars.
- macOS
.rivownership: Settings names the actual current handler and provides deliberate Make Default and Repair Icon actions without silently taking ownership. Quick Look remains separate. - Private-by-design opt-out: Disabling Anonymous Usage sends one final anonymous off status, then stops reporting. No Rive files, paths, hardware identifiers, accounts, or license information are sent.
2.5.1 Hotfix
- Playback controls stay connected: The dedicated playback surface continues to receive Settings, toolbar, and Properties changes after loading, including background color, fit, alignment, canvas size, playback, and ViewModel controls. Main-interface overlays stay accessible above playback.
- Fixed canvas remains predictable: Fixed uses logical CSS pixels, centers while it fits in the viewer, and scrolls from its authored origin when it is larger than the available space.
- Reset without a visible restart: Toolbar Reset and Properties
DEFAULTrestore the current playback in place, without rebuilding the playback surface, flashing its readiness state, or moving adjacent controls.
Canvas size, fit, and alignment
Fixed sets the size of the playback canvas viewport; it does not resize the authored Rive artboard. Contain scales the artboard until one dimension touches the canvas edge. As a result, alignment can only visibly move along the other axis—the axis that still has unused canvas space.
For example, a 16:9 artboard inside a taller 500 × 409 canvas fills the full 500-pixel width, leaving vertical space. Top, Center, and Bottom visibly move the artboard; Left, Center, and Right do not, because there is no horizontal space left to move into. To test horizontal alignment with that artboard, use a canvas that is wider than 16:9 or choose a fit mode that leaves horizontal space.
2.5.0 Highlights
- Dedicated desktop playback surface: Packaged desktop builds place visible Rive playback in a child WebView while the main WebView keeps the controls, drawers, code editor, export, MCP, and diagnostics. The playback surface receives synchronized state, separating its visible render loop from most interface DOM and control work.
- Recorded transition comparison: In two 60 FPS recordings of the same large Rive asset with 999 live control paths and 10 embedded runtime script assets, observed transition holds were 4–16 captured frames in the earlier single-WebView run and 1–2 in the later dedicated-surface run. The worst observed hold was approximately 8× shorter and the median per-transition maximum was approximately 3× shorter. Build profiles, runtime and viewport settings, transition sequences, and capture setups differed, so these are observed results rather than a controlled or universal performance guarantee.
- Bounded interface updates: Visible scalar controls update on a separate interface cadence, list controls rebuild only when membership changes, hidden or collapsed controls skip scalar syncing, and closed consoles stop rebuilding invisible rows.
- Automatic runtime selection: Fresh or unset runtime preferences use
Latest (auto), while existing explicit runtime choices remain unchanged. - Accurate export counts: Export summaries report the actual number of serialized controls, including controls generated from repeated lists.
- Drawer reveal controls: The left and right drawer buttons now live in the main interface strip so they remain accessible beside the separate playback surface.
- Anonymous Usage controls: Official releases can report anonymous installation and monthly usage counts. A first-run notice, a Settings toggle, and Privacy Policy links were added with the feature.
- macOS
.rivownership and icon repair: MAKE DEFAULT is one action for the effective.rivassociation, regardless of how many compatible identifiers are registered. RAV discovers those aliases internally and includes an extension-level fallback with its document icon, but Settings does not expose them as separate ownership chores. REPAIR ICON re-registers the document metadata after RAV is the default; installation never silently takes over, and Quick Look remains a separate macOS provider.
Anonymous installation counting
Anonymous counting is on by default in official releases. A first-run notice appears before the first report, and the feature can be disabled at any time under Settings → Anonymous Usage.
RAV reports only anonymous installation and monthly usage tokens with the release number. Turning Anonymous Usage off sends one final anonymous disable status, then reporting stops. If that final status cannot be delivered, it remains pending locally and receives at most one retry per later launch until acknowledged, without resuming any other reporting. RAV does not send Rive data, files, paths, hardware identifiers, accounts, or license information. The website displays only an aggregate total; updates usually appear within a few minutes. More information is available in the RAV website's Privacy Policy.
2.4.3 Highlights
- Exact ViewModel list labels: A row uses its direct authored instance name when available. When the Web wrapper exposes only the ViewModel definition name, RAV accepts a unique match between the definition's canonical instance-name set and a readable string property; ambiguous or missing matches become
Row N. It never presentsviewModelNameas an authored row label. - Embedded image controls: Each image property now uses one full-width select containing every embedded raster asset followed by
Open file…andClear;Open file…invokes a hidden file input, with no separate folder or clear button and noEmbedded image…placeholder. Entries useuniqueFilenameidentity, magic-byte MIME detection, and numbered labels when display names repeat. Non-raster embedded resources stay out of the image catalog. The same catalog and control carry into standalone exports, while decoded image objects remain excluded from JSON snapshots. - Standalone editor-config preservation: Applied editor configuration and lifecycle callbacks are preserved and run in standalone exports; unsaved drafts remain inactive.
- Fixed-canvas centering and overflow: A fixed canvas uses overflow-safe auto margins: it remains centered while it fits, then the margins collapse safely and scrolling begins at the authored top-left origin when it exceeds the viewport. The central scroller uses the shared styled 10px track, thumb, and corner.
- Clean build provenance: Release builds capture Git status before generating their build identifier, so clean signed artifacts do not report a false
dirtysuffix while genuinely modified builds remain labeled. - macOS
.rivopening and file identity: Double-click/open-with and warm single-instance opens route through the native queue andopen-filebridge. The bundle declares both the officialapp.rive.editor.rive-fileUTI and the pre-2.4.3app.rive.animation.viewer.rivcompatibility UTI as Viewer types and includes the dedicatedRiveFileIcon.icnsdocument resource. A version-and-schema-gated post-update launch refreshes the installed bundle registration without restarting Finder or taking over the default handler. - Windows
.rivdocument icon: NSIS and MSI packages ship a dedicated ten-resolutionRiveFileIcon.icoderived mechanically from the supplied 1024 px master. NSIS repairs Tauri's generatedRive File\\DefaultIconafter every install/update and refreshes Explorer; MSI owns the correspondingRive Animation Viewer.riv\\DefaultIconregistry value as an upgrade-aware component that is removed on uninstall. - Runtime compatibility: RAV protects authored layouts when a selected runtime has known compatibility problems and keeps explicit runtime choices available.
2.4.2 Highlights
- MCP sidecar startup restored: Packaged RAV builds resolve
rav-mcpbeside the running application executable, so the app-owned bridge starts automatically again. - Updater migration repair: Existing stable MCP launcher symlinks are refreshed during startup after an app replacement.
- Regression coverage: Rust and smoke tests now enforce the sibling-binary layout instead of relying on Tauri's unrelated generic executable-directory API.
2.4.1 Highlights
- Trusted macOS installs: Apple Silicon and Intel builds are Developer ID signed with hardened runtime and secure timestamps, then notarized and stapled for normal Gatekeeper-approved launch.
- Notarized auto-updates: Tauri creates each macOS
.app.tar.gzfrom the already-notarized app. CI verifies that it has the same code-signing hash as the app inside the notarized DMG before publishing. - Two independent signature layers: Apple signing and notarization establish macOS platform trust; the existing Tauri
.sigfiles authenticate updater downloads before installation. - Single signed MCP binary: RAV now packages one
rav-mcpbeside the main executable, where Tauri signs it inside-out with the app. The redundant unsigned Resources copy is gone. - Atomic, bounded releases: Complete platform inventory, signing checks, job timeouts, concurrency protection, and a final draft gate prevent partial or runaway releases from becoming public.
MCP startup regression resolved in 2.4.2
RAV 2.4.1 includes the signed sidecar at
Rive Animation Viewer.app/Contents/MacOS/rav-mcp, but its packaged macOS
startup path can report that the sidecar is missing. The bundle has not moved:
the failure is in resolving the directory that contains the running app
executable. Update to 2.4.2 or later; reinstalling 2.4.1 does not repair the
path-resolution failure.
2.4.0 Highlights
- Dynamic ViewModel lists: List instances populate as soon as a file opens and rebuild when their controlling count changes, with readable
Row 1,Row 2, … labels instead of an arbitrary ten-item ceiling. - Export parity: Standalone HTML exports and generated snippets preserve the live player's list count and reactive behavior, while controls excluded from export remain absent from the Properties panel and serialized snapshot.
- Reliable VM instance selection: The VM Instance selector stays populated even when the file exposes only one default or unnamed instance.
- Playback and trigger parity: Loaded state machines remain active, triggers continue to fire, and explicit ViewModel instance choices reload with the binding mode required by the runtime.
- Selected-instance export parity: CDN/local snippets and standalone demos bind the selected ViewModel instance before applying the exported control snapshot.
- Truthful MCP activity state: The MCP indicator is green while healthy and ready, blue for 30 seconds after an agent command, yellow while connecting, red after a failure, and muted when disabled.
- Release toolchain alignment: Tauri, its plugins, the Rust graph, Vite, and Vitest are aligned on compatible security-patched versions, and dirty local builds are identified in their build stamp.
2.2.3 Highlights
- Status-strip lifecycle hardening: Temporary notices like canvas sizing, refresh, restart, runtime, layout, and export confirmations now restore the last structured artboard/playback/ViewModel/instance summary automatically instead of getting stuck in the strip.
- Website-matched status icon colors: The artboard, animation, state-machine, ViewModel, and instance glyphs in the runtime strip now use the RAV green/yellow palette instead of the old purple fallback tint.
2.2.2 Highlights
- Windows window-mode cleanup: Windows now uses a single window contract instead of mixing decorated config with a runtime undecorated override, so the custom header and native rounded-corner hint are no longer fighting each other.
- Shared layout mapping: The live viewer, canonical snippet export, and standalone demo now all map fit/alignment through the runtime enums instead of passing raw strings into
new Layout(...). - Fixed-size export centering hardening: Explicit pixel-size canvases now keep the selected alignment behavior while staying centered in exported demos and snippets, including on macOS.
- Status-strip iconography: Structured playback status now renders with dedicated artboard / animation / state-machine / instance / ViewModel icons instead of text abbreviations.
2.2.1 Highlights
- Scrollbar regression fix: Shared app/demo scrollbars on macOS are styled again, and the smoke suite now fails prebuild if shared scrollbar owners mix incompatible WebKit and standardized scrollbar styling paths.
- Fixed-size canvas centering: Explicit pixel-size canvases now stay centered in both the live app and exported demos instead of snapping to the upper-left corner.
- Windows rounded-corner hint: Desktop startup now applies the Windows 11 DWM rounded-corner preference for the custom RAV window so Windows can match the macOS chrome treatment more closely.
2.2.0 Highlights
- Explicit canvas sizing: You can now pin the viewer to an exact pixel size from Settings, carry that same size through the editor via
canvasSize, and keep width/height locked to a chosen aspect ratio while editing. - Canvas sizing through MCP: Agents can now call
rav_set_canvas_size, andrav_statusreports the active canvas sizing mode so remote workflows can inspect and control explicit pixel dimensions. - Snippet/demo parity: Generated snippets and exported demos now preserve the active canvas sizing mode. Fixed-size exports emit explicit
canvas.width,canvas.height, and CSS dimensions instead of silently falling back to fluid layout. - Updater reliability on Windows: The app-owned MCP bridge is now shut down before updater installation begins, preventing
rive-mcp.exefrom holding the old install open during Windows update handoff.
2.1.1 Highlights
- Desktop chrome stabilization: macOS now uses a supported overlay-titlebar path with the custom RAV header, rounded outer corners, corrected window controls, and centered file metadata that keeps the filename visible while truncating long directories.
- Runtime strip cleanup: The bottom strip is slimmer and clearer, with compact runtime labeling, a simpler open/close console affordance, and an MCP chip that now distinguishes disabled, connected-idle, and actively-in-use states.
- Console hardening: The JavaScript console keeps full Eruda inspection, no longer freezes when toggled, and its
FOLLOWbehavior stays pinned to the real visible transcript. - Snippet/export hardening: Generated snippets now stay lean when no controls are selected, preserve falsy VM values correctly, keep triggers manual by default, and avoid the demo bootstrap/runtime helper regressions found during the template audit.
- Desktop polish: About layout, dialog scrollbars, and shared scrollbar theming were tightened so the app no longer exposes stray native scrollbars across its desktop surfaces.
2.1.0 Highlights
- Architecture sweep: Root runtime drift is gone. App boot now starts from
src/app/main-entry.js, the frontend MCP bridge lives undersrc/app/platform/mcp, injected snippets are source-backed, and architecture rules now enforce modular growth. - Custom desktop About: RAV now ships a proper in-app About window with runtime/build metadata, credits, dependency inventory, product links, and native Help-menu integration.
- Console mode cleanup: The runtime strip console control is now open/close only, the console header toggles
Events/JS, and JSFOLLOWnow tracks the real visible transcript correctly. - Indicator and logging fixes: Runtime and MCP status chips again reflect the real live state, and cyclic MCP payloads no longer crash the event console renderer.
- Windows polish: Dark-mode menu chrome remains visible and the bundled MCP sidecar no longer opens a stray PowerShell window on launch.
- Windows release workflow fix: The architecture-budget checker now resolves its config path correctly on Windows runners, fixing the
D:\\D:\\...path error that blocked the original2.1.0Windows packaging step.
2.0.5 Highlights
- Windows release fix: The stable MCP launcher-path helper now compiles on Windows, fixing the cross-platform release failure that blocked the
2.0.4tag from publishing a complete updater set.
2.0.4 Highlights
- Claude-ready native sidecar:
rav-mcpnow speaks both normal MCPContent-Lengthframing and Claude's newline-delimited JSON probe format, so Claude health checks no longer fail before the first real tool call. - Real MCP-ready startup: Packaged builds now load the frontend bridge correctly on launch, so
MCP readyactually corresponds to a live RAV app bridge and not just a listening sidecar process. - Stable launcher path: MCP client setup now targets a stable launcher path (
rav-mcp-rav) instead of the app-bundle-internal binary, which survives app replacements and keeps Claude/Codex registrations valid. - Workspace control tool: Agents can now call
rav_configure_workspaceto open/close sidebars, switch between internal/editor live source modes, and inject/remove the VM Explorer snippet. - Updater retry self-heal:
UPDATE RETRYno longer waits for a manual click forever; the app retries checks automatically on focus, visibility return, online events, and a short timer.
2.0.3 Highlights
- Consistent JS console chrome: Command, result, warning, error, and app log rows now share the same timestamp-and-badge presentation instead of mixing Eruda chevrons with plain text tags.
- Working JS console filters: Level/search filters now act on the actual visible transcript, so REPL input/output rows no longer punch through warning/error filters.
- Copy mirrors the screen: The JS console copy action now copies the current visible transcript exactly as shown, in newest-first order.
- Native object inspection preserved:
riveInstand other live objects still use Eruda's lazy inspector instead of being collapsed into fake summary objects. - Docs/site sync: README, docs, changelog, and feature cards now explicitly describe the normalized console behavior.
2.0.2 Highlights
- Exact playback names: State machine and animation names are shown exactly as authored in the
.rivfile, without injected display prefixes. - Refined startup layout: RAV now opens with the right properties panel visible while the editor and console stay closed by default.
- Icon-based console actions: Event and JS consoles now use outlined SVG controls for
FOLLOW,COPY, andCLEAR, with clearer active-state styling. - Primary toolbar polish:
OPENstays bright green, auto-fits its icon-plus-label width, and the runtime renderer selector now lives with the main playback/layout controls. - MCP setup responsiveness: The MCP dialog opens immediately and refreshes install-state data asynchronously instead of blocking the UI.
- Release workflow compatibility: The release pipeline now points at the real published
tauri-actiontag and uses Node 24-compatible JavaScript action settings for future releases.
2.0.0 Highlights
- Bundled native MCP sidecar: Packaged builds no longer require Node.js to expose MCP. RAV ships with a native
rav-mcpbinary and an always-on bridge. - One-click MCP setup: The MCP dialog detects Codex, Claude Code, and Claude Desktop, shows whether
rav-mcpis already configured, and offersADD,REINSTALL, andREMOVE. - Script Access permission: MCP scripting tools are gated behind an explicit
Script Accesstoggle so you can keep MCP in read-only control mode when needed. - Snippet & Export Controls:
EXPORTopens a dialog that previews the generated web snippet, lets you choose CDN vs local package output, and serializes only the selected or changed controls. - Readable integration snippets: Generated snippets contain only runtime setup plus the selected typed property accessors on
window.riveProperties; standalone HTML export separately includes the viewer UI and selected-value restoration. - Unified consoles: Event Console and JavaScript Console now share the same newest-first transcript model, timestamps, search/filter workflow, and
FOLLOWbehavior. - Live-source-aware editor: The editor title itself indicates whether the live runtime is being driven by internal RAV wiring or the applied editor config.
- Background app updates: The desktop app checks for Tauri-signed updater payloads on launch and exposes an update chip for install/relaunch flow.
- Cross-architecture updater feed: Tauri-signed release feeds publish Apple Silicon, Intel macOS, and Windows updater entries together so one release can serve all supported desktop targets.
Quick Start
npm install
npm start # Opens the browser DEV viewer at http://localhost:1420; MCP uses isolated port 9278
Browser preview and packaged DEV sessions may share port 9278, but the bridge
always routes agent commands to the packaged desktop app while it is connected.
The browser remains a fallback only when no desktop RAV peer is present.
Features
Core Viewer
- File Loading: Open button plus drag/drop file loading for
.rivfiles - Desktop Open With: Double-click / open-with / single-instance handoff for
.rivfiles - Runtime Selection: Toggle between Canvas and WebGL2 renderers
- Runtime Version Selection: Pick runtime semver (
Latest (auto), the latest 4 concrete versions, orCustom) from Settings - Layout Options: Fit and alignment are surfaced directly in the main toolbar next to playback controls
- Background Color: Color picker with
No BGreset for transparent canvas backgrounds - Explicit Canvas Size: Settings can pin the canvas to a specific width/height in pixels and optionally lock the aspect ratio
- Playback Controls: Play, pause, and reset/restart (reset restarts playback in place with autoplay and restores control values)
- Autoplay on Open: Fresh file opens, drag/drop loads, open-with events, and MCP file opens all autoplay by default
- Event Console: Source toggles (
Native,Rive User,UI,MCP), text search, timestamps, newest-first ordering, andFOLLOW - Console Actions: Shared outlined SVG buttons for
FOLLOW,COPY, andCLEARacross Event Console and JavaScript Console - Artboard Switcher: Auto-populating dropdowns for artboards and playback targets (state machines + animations), VM instance selector, reset-to-default button
- Exact Playback Labels: Playback dropdown labels preserve authored capitalization and formatting exactly as they appear in the Rive file
- State Machine Detection: Automatically detects and initializes available state machines
- Auto Update Chip: Desktop app checks for updates on launch and exposes
UPDATE <version>,UPDATING,RESTARTING, orUPDATE RETRY
Code Editor Panel
- CodeMirror 6 Editor: JavaScript syntax highlighting with One Dark theme
- JavaScript Configuration: Write JavaScript objects (NOT JSON) for Rive initialization
- Live Source Indicator: The
EDITORtitle block itself indicates the current live source. Neutral gray means internal wiring is live. Green pulsing state means the applied editor config is live. - Apply & Reload:
APPLYevaluates the current editor code, switches the live source to the editor, and refreshes the current view without throwing away the active artboard/playback state - Editor Canvas Sizing: Applied editor configs can include a
canvasSizeblock so the live runtime, snippets, and exports all use the same explicit pixel size - Internal Wiring Toggle: You can switch back to internal RAV wiring without deleting editor content
- Tab Support: Tab inserts 2 spaces, Shift+Tab removes indentation
- Error Display: Shows errors in red banner when configuration fails
- Resizable Panel: Drag to resize panel to any width for comfortable editing
- VM Explorer Injection: Injects helper APIs for console-driven VM inspection and mutation
JavaScript Console
- Integrated JS Console: Executable REPL panel styled to match RAV
- Console Capture: Captures
console.log/info/warn/error/debugoutput from the running app/runtime - REPL Execution: Execute live JavaScript against the active browser/runtime context
- Shared Console UX: Same transcript layout as the Event Console, with timestamps, newest-first ordering, filters/search, and
FOLLOW - Unified Console Chrome: Command, result, warning, error, and application log rows share the same timestamp-and-badge styling while keeping Eruda's native lazy object inspection
- Visible Transcript Copy:
COPYserializes the currently visible JS console rows in the same order and with the same badges you see on screen - MCP Console Tools: Open, close, read, and execute console commands remotely through MCP
Important: The editor accepts JavaScript code, not JSON. You can use JavaScript features like comments, trailing commas, and unquoted keys:
{
// This is a valid comment
artboard: "MyArtboard",
stateMachine: "StateMachine1",
autoplay: true,
}
ViewModelInstance Explorer
Developer tool for debugging Rive files with ViewModelInstances.
How to Use
- Load a Rive file
- Click "Inject VM Explorer" button in toolbar
- Open browser console (F12 or Cmd+Option+I)
- Use the following commands:
vmExplore() // Show root properties
vmExplore("path/to/prop") // Navigate to specific path
vmGet("settings/volume") // Get value
vmSet("settings/volume", 0.5) // Set value
vmTree // View full hierarchy
vmPaths // List all property paths
The explorer displays a comprehensive usage guide in the console when injected.
MCP Integration
RAV includes a built-in MCP (Model Context Protocol) sidecar that lets Claude Code, Claude Desktop, Codex, or any MCP client control the viewer remotely — open files, inspect ViewModels, drive playback, manipulate inputs, run JS, generate web snippets, export demos, and configure the workspace layout/state.
Architecture
Runtime source structure is now enforced by an architecture budget:
- ARCHITECTURE.md defines module and folder rules
- architecture-budget.json locks current oversized files so they cannot keep growing
.dependency-cruiser.cjsenforces layer boundaries and cycle bansnpm run check:architectureandnpm run check:depsrun automatically as part ofnpm run test
The key rule is simple: new hand-written source files may not exceed 400 lines, and folders must subgroup before they turn into flat dumping grounds.
MCP Client ←(stdio)→ rav-mcp sidecar ←(WebSocket :9274)→ RAV Frontend
The desktop app bundles one native rav-mcp sidecar beside the main application executable and exposes a stable launcher path for external clients. On macOS, the exact location is Rive Animation Viewer.app/Contents/MacOS/rav-mcp; RAV derives it from the running executable's parent directory. Tauri applies the same Developer ID, hardened-runtime, and timestamp requirements to the sidecar before signing the outer app. The frontend MCP bridge client starts automatically when RAV launches, attaches to the configured port, and keeps retrying until a client attaches.
Setup (one-time)
Open the desktop app, click the cable icon, and use the MCP Setup dialog:
- Launcher path: Copy the stable
rav-mcp-ravlauncher path generated for your machine - Client detection: Detect whether Codex, Claude Code, and Claude Desktop are present and whether
rav-mcpis already configured - One-click installs: Add RAV to Codex, Claude Code, or Claude Desktop directly from the dialog when those clients are detected
- Reinstall / remove: Already-configured clients show
REINSTALLandREMOVE - Responsive setup refresh: The MCP dialog paints immediately, then hydrates install status in the background to avoid blocking the UI
- Configurable port: Change the MCP bridge port from inside the MCP dialog and all generated snippets update to match
- Script Access: Keep MCP in read-only mode, or explicitly allow JavaScript execution (
rav_eval,rav_console_exec,rav_apply_code) - Copy/paste snippets: Ready-to-paste snippets are shown for Codex, Claude Code, Claude Desktop, and a generic MCP client
Representative snippets:
claude mcp add-json -s user rav-mcp '{"type":"stdio","command":"/Users/you/.local/bin/rav-mcp-rav","args":["--stdio-only","--port","9274"]}'
[mcp_servers."rav-mcp"]
command = "/Users/you/.local/bin/rav-mcp-rav"
args = ["--stdio-only", "--port", "9274"]
Open the RAV desktop app and enable the MCP bridge. The MCP chip is muted and crossed out when disabled, yellow while connecting, red after a bridge failure, green when healthy and ready, and blue for 30 seconds after an agent command arrives. From then on, your MCP client can control RAV whenever both are running.
Available Tools (49)
| Tool | Description |
|---|---|
rav_status | App status: file, runtime, playback, ViewModel summary |
rav_set_anonymous_usage | Enable or disable anonymous version reporting through the Settings preference controller |
rav_open_file | Open a .riv file by absolute path |
rav_play / rav_pause / rav_reset | Playback controls |
rav_get_artboards | List artboard names |
rav_get_state_machines | List state machine names |
rav_switch_artboard / rav_reset_artboard | Switch artboard/animation, reset to default |
rav_switch_vm_instance | Bind a specific authored or runtime/list ViewModel instance key |
rav_get_vm_tree | Full ViewModel hierarchy |
rav_vm_get / rav_vm_set / rav_vm_fire | Read, write, and fire ViewModel properties |
rav_vm_set_image / rav_vm_clear_image | Set or clear an image on the authoritative root ViewModel |
rav_get_global_vm_tree | List every named file-level global ViewModel and its hierarchy |
rav_global_vm_get / rav_global_vm_set / rav_global_vm_fire | Read, write, or fire a property in a specifically named global ViewModel |
rav_global_vm_set_image / rav_global_vm_clear_image | Set or clear a named global ViewModel image through authoritative playback |
rav_get_event_log | Recent event log entries (filterable by source) |
rav_get_editor_code / rav_set_editor_code | Read/write the script editor |
rav_apply_code | Apply editor code and reload animation (Script Access required) |
rav_set_runtime | Switch runtime (webgl2/canvas) |
rav_set_layout / rav_set_alignment | Set layout fit mode and nine-way canvas alignment |
rav_set_canvas_color | Set background color or transparent |
rav_set_canvas_size | Set canvas sizing mode (auto or explicit pixels) and optional aspect lock |
rav_capture_canvas | Capture the authoritative rendered canvas as PNG image content with render metadata |
rav_open_isolated_playback | Open the current animation in an ordinary isolated diagnostic WebView |
rav_export_demo | Export standalone HTML demo |
rav_export_demo_visual | Drive the visible export dialog with exact control selection, package source, snippet mode, and output path |
generate_web_instantiation_code | Generate the canonical live web-instantiation snippet (local npm package or cdn) with selected typed accessors on window.riveProperties. Preferred over hand-writing snippets from scratch. |
rav_toggle_instantiation_controls_dialog | Open/close the in-app Snippet & Export Controls dialog so a human can choose which controls are serialized |
rav_configure_workspace | Open/close sidebars, switch live source mode (internal / editor), and inject/remove the VM Explorer snippet idempotently |
rav_get_sm_inputs / rav_set_sm_input | State machine input access |
rav_eval | Evaluate JS with `target: auto |
rav_console_open / rav_console_close | Toggle the JS console remotely |
rav_console_set_mode / rav_console_set_filter / rav_console_clear | Switch console mode, mirror visible filters, and clear the active transcript |
rav_console_read / rav_console_exec | Read the JS console transcript or run REPL code (rav_console_exec requires Script Access). Transcript includes REPL input/result rows plus captured console.* output. |
Editor and Export Semantics
rav_evaldefaults to the active authoritative playback child and otherwise uses the host WebView. Settarget: "playback"to require the child ortarget: "host"for a deliberate UI-WebView diagnostic; results identify the resolved surface and child session.- The console tools read and execute only in the host UI WebView. They do not forward isolated-child
console.*calls or claim live Luau-output authority. - The live runtime can run in either internal mode or editor-driven mode.
rav_apply_codeswitches the live runtime to the last applied editor config.- Unsaved editor draft changes do not change the running animation until applied.
rav_statusreports the active instantiation source and whether the editor draft is dirty.rav_statusalso reports the active canvas sizing mode and explicit pixel size when the canvas is fixed.- ViewModel paths are slash-separated. Dynamic list items use a zero-based live index such as
rows/0/playerName; callrav_get_vm_treeagain after the controlling count changes before addressing newly added or removed rows. - Global ViewModel tools require both the file-level ViewModel name and its property path, preventing collisions when multiple globals expose the same path.
generate_web_instantiation_codealways reflects what is actually running.generate_web_instantiation_codedefaults to the CDN form unless you explicitly requestpackage_source: "local".- Compact snippets expose only checked ViewModel/state-machine accessors on
window.riveProperties; scaffold snippets list all accessors with unchecked lines commented out. They do not replay captured values. - Fixed-size snippets and exported demos preserve explicit
width × heightsizing instead of collapsing back to host-driven layout. - The Snippet & Export Controls dialog chooses which accessors appear in snippets and which current values a standalone HTML export restores. Branch checkboxes select nested properties; individual rows affect one property only.
- If you never open the dialog, RAV defaults to the controls that differ from the load-time baseline.
- Exported demos mirror the active live source, keep fit/alignment in the main toolbar, and include a Copy Instantiation Code button in the demo toolbar.
Event Console
All MCP commands, responses, and connection events appear in the event console with the MCP source tag. Messages are formatted as human-readable summaries with elapsed time — no raw JSON. Use the MCP filter toggle to show/hide MCP traffic.
Configuration
| Environment Variable | Default | Description |
|---|---|---|
RAV_MCP_PORT | 9274 | WebSocket bridge port |
Desktop Features (Tauri)
- Native App: Runs as a desktop application on macOS/Windows/Linux
- Demo Bundle Export: Create self-contained HTML files with embedded animations and copyable instantiation snippets
- Canvas Background Parity: Exported demos preserve the selected solid or transparent canvas background
- Offline Support: Caches runtime scripts for offline use
- Dev Tools Access: Programmatic DevTools opening via inject button to access console
- Background App Updates: Check, authenticate with the Tauri updater signature, install, and relaunch updates from GitHub Releases
- Safe Updater Bridge Shutdown: Desktop installs now stop the app-owned MCP bridge before updater installation starts, preventing Windows file-lock stalls
- Trusted macOS distribution: Developer ID signing, notarization, stapling, and parity checks cover both direct-download DMGs and macOS updater apps
- Merged updater publishing: Release automation publishes a combined
latest.jsononly after macOS Apple Silicon, macOS Intel, MSI, and NSIS updater payloads are all present
Project Structure
rive-local/
├── index.html # Main UI shell
├── styles/ # Split UI stylesheets
├── mcp-server/
│ ├── index.js # Reference JS MCP server
│ └── README.md # MCP protocol/setup guide
├── src/app/
│ ├── main-entry.js # Frontend composition root / bootstrap
│ ├── bootstrap/ # App wiring stacks
│ ├── core/ # Constants + DOM element registry
│ ├── platform/ # Runtime, export, updater, session, MCP helpers
│ ├── rive/ # Instance, playback, VM, artboard controllers
│ ├── snippets/ # Source-backed and generated injected snippets
│ └── ui/ # Editor, consoles, dialogs, shell/status controllers
├── vendor/
│ └── codemirror-bundle.js # Bundled CodeMirror
├── scripts/
│ ├── build-dist.mjs # Production build
│ ├── build-mcp-sidecar.mjs # Debug rav-mcp builder used before tauri dev
│ ├── check-release-version.mjs # Verifies synchronized release metadata
│ ├── generate-updater-manifest.mjs # Merges complete multi-platform updater assets
│ ├── verify-macos-distribution.sh # Verifies Developer ID/notary parity
│ └── verify-updater-signatures.mjs # Verifies exact Tauri-signed payload bytes
└── src-tauri/ # Rust/Tauri desktop wrapper + native rav-mcp
Desktop Development
Prerequisites
- Rust toolchain (
rustup) - Node.js 22.13+ (the release pipeline is pinned to Node.js 24.20.0)
- Xcode Command Line Tools (macOS)
Build Commands
npm run tauri dev # Development mode
npm run tauri build # Production build
Export behavior must be tested in a packaged desktop build. The web build deliberately disables or cannot provide the native export path, so browser-only testing cannot accept an export change. Keep the exported artifact and identify the exact packaged build in the test receipt.
Test Build Numbering
npm run build now stamps builds as bNNNN-YYYYMMDD-HHMM-<gitsha>:
bNNNNauto-increments on every local build via.cache/build-counter.txt- Timestamp uses local system time
- Tail is short git SHA
Override the test build number when needed:
npm run build -- --build-number=172
APP_BUILD_NUMBER=172 npm run tauri build
Technical Details
Configuration Format
The editor uses eval() to evaluate JavaScript code, allowing full JavaScript syntax:
{
artboard: "Main",
stateMachine: "State Machine 1",
autoplay: true,
canvasSize: {
mode: "fixed",
width: 1600,
height: 900,
lockAspectRatio: true,
},
layout: {
fit: "contain",
alignment: "center"
},
// Custom onLoad callback
onLoad: () => {
console.log("Animation loaded!");
riveInst.resizeDrawingSurfaceToCanvas();
}
}
Runtime API compatibility
Use stateMachine: "name" for one state machine. RAV accepts both this spelling and existing stateMachines configurations, then chooses the runtime API for the loaded version: singular on Rive 2.41+, plural on older runtimes. Standalone demos and generated snippets use the same version boundary. For LOCAL snippets, install the runtime version reported with the snippet so the emitted API matches your package.
Explicit timeline playback, multiple simultaneous state machines, legacy state-machine inputs, and user-supplied event callbacks remain supported. These can still emit upstream deprecation warnings on 2.41+. The active viewer/demo also retains StateChange and RiveEvent listeners for its event log; generated snippets do not subscribe unless user code requests them. RAV does not rewrite authored state machines or bindings inside a compiled .riv file, and it does not suppress runtime warnings.
Error Handling
- Configuration errors display in a red error banner
- Errors auto-dismiss after 5 seconds
- Invalid JavaScript shows syntax errors
- File loading errors display detailed messages
Tab Key Implementation
The editor intercepts Tab key events when focused:
- Captures keydown events in capture phase
- Prevents default browser tab behavior
- Manually inserts/removes spaces at cursor position
VM Explorer Architecture
- Loaded from the source-backed snippet pipeline under
src/app/snippets/source/vm-explorer.jsand emitted into the generated snippet bundle at build time - Usage guide displayed when injecting, not in the snippet itself
- Walks ViewModelInstance property trees recursively
- Builds path references for direct access
- Uses Rive runtime's path resolution for get/set operations
Known Issues
CSP Warnings (Desktop)
The desktop app shows harmless CSP warnings about blob:// URLs. These are WebKit quirks and don't affect functionality.
DMG Creation
DMG bundling may fail on some systems. The .app bundle in src-tauri/target/release/bundle/macos/ works regardless.
Tab Key
Tab indentation only works when the editor has focus. Click in the editor area before using Tab.
Troubleshooting
Animation won't load
- Check browser console for errors
- Verify the .riv file is valid
- Try a different runtime (Canvas vs WebGL2)
Configuration won't apply
- Ensure you're writing valid JavaScript (not JSON)
- Check for syntax errors in the code
- Look for error messages in the red banner
VM Explorer not working
- Verify your Rive file has ViewModelInstances
- Check console for injection confirmation
- Try reloading after injection
Desktop build fails
- Run
rustup updateto ensure latest Rust - Check
npm run tauri infofor missing dependencies - Verify Xcode Command Line Tools installed (macOS)
License
MIT License - Copyright © 2025 IVG Design
Rive runtimes are provided by Rive under their own licensing terms.