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.json updater feed continue to deliver 2.5.3.
  • Release source will be the exact chore(release): v2.5.4 commit on main.
  • 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:architecture enforces file-size and folder-shape budgets
  • npm run check:deps enforces dependency-cruiser import boundaries
  • tests/smoke/ui-regressions.smoke.test.js protects the shared scrollbar contract, custom window-chrome structure, Tauri window config, and exported demo chrome contract
  • tests/unit/ui/window-chrome.test.js protects desktop window-control wiring and Tauri/non-Tauri behavior split
  • npm run test runs the full Vitest suite before every package build
  • cargo check --manifest-path src-tauri/Cargo.toml validates 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 stateMachine option. 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_eval defaults to the active isolated playback child, supports strict playback and diagnostic host targets, 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 .riv ownership: On macOS, MAKE DEFAULT assigns the effective extension association in one action while RAV dynamically discovers registered .riv identifiers 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 VM section sits above ROOT 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_canvas returns 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 DEFAULT update 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 .riv while 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 .riv ownership: 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 DEFAULT restore 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 .riv ownership and icon repair: MAKE DEFAULT is one action for the effective .riv association, 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 presents viewModelName as 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… and Clear; Open file… invokes a hidden file input, with no separate folder or clear button and no Embedded image… placeholder. Entries use uniqueFilename identity, 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 dirty suffix while genuinely modified builds remain labeled.
  • macOS .riv opening and file identity: Double-click/open-with and warm single-instance opens route through the native queue and open-file bridge. The bundle declares both the official app.rive.editor.rive-file UTI and the pre-2.4.3 app.rive.animation.viewer.riv compatibility UTI as Viewer types and includes the dedicated RiveFileIcon.icns document resource. A version-and-schema-gated post-update launch refreshes the installed bundle registration without restarting Finder or taking over the default handler.
  • Windows .riv document icon: NSIS and MSI packages ship a dedicated ten-resolution RiveFileIcon.ico derived mechanically from the supplied 1024 px master. NSIS repairs Tauri's generated Rive File\\DefaultIcon after every install/update and refreshes Explorer; MSI owns the corresponding Rive Animation Viewer.riv\\DefaultIcon registry 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-mcp beside 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.gz from 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 .sig files authenticate updater downloads before installation.
  • Single signed MCP binary: RAV now packages one rav-mcp beside 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, and rav_status reports 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.exe from 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 FOLLOW behavior 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 under src/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 JS FOLLOW now 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 original 2.1.0 Windows 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.4 tag from publishing a complete updater set.

2.0.4 Highlights

  • Claude-ready native sidecar: rav-mcp now speaks both normal MCP Content-Length framing 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 ready actually 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_workspace to open/close sidebars, switch between internal/editor live source modes, and inject/remove the VM Explorer snippet.
  • Updater retry self-heal: UPDATE RETRY no 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: riveInst and 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 .riv file, 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, and CLEAR, with clearer active-state styling.
  • Primary toolbar polish: OPEN stays 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-action tag 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-mcp binary and an always-on bridge.
  • One-click MCP setup: The MCP dialog detects Codex, Claude Code, and Claude Desktop, shows whether rav-mcp is already configured, and offers ADD, REINSTALL, and REMOVE.
  • Script Access permission: MCP scripting tools are gated behind an explicit Script Access toggle so you can keep MCP in read-only control mode when needed.
  • Snippet & Export Controls: EXPORT opens 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 FOLLOW behavior.
  • 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 .riv files
  • Desktop Open With: Double-click / open-with / single-instance handoff for .riv files
  • Runtime Selection: Toggle between Canvas and WebGL2 renderers
  • Runtime Version Selection: Pick runtime semver (Latest (auto), the latest 4 concrete versions, or Custom) from Settings
  • Layout Options: Fit and alignment are surfaced directly in the main toolbar next to playback controls
  • Background Color: Color picker with No BG reset 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, and FOLLOW
  • Console Actions: Shared outlined SVG buttons for FOLLOW, COPY, and CLEAR across 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, or UPDATE 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 EDITOR title 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: APPLY evaluates 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 canvasSize block 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/debug output 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: COPY serializes 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

  1. Load a Rive file
  2. Click "Inject VM Explorer" button in toolbar
  3. Open browser console (F12 or Cmd+Option+I)
  4. 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.cjs enforces layer boundaries and cycle bans
  • npm run check:architecture and npm run check:deps run automatically as part of npm 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-rav launcher path generated for your machine
  • Client detection: Detect whether Codex, Claude Code, and Claude Desktop are present and whether rav-mcp is 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 REINSTALL and REMOVE
  • 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)

ToolDescription
rav_statusApp status: file, runtime, playback, ViewModel summary
rav_set_anonymous_usageEnable or disable anonymous version reporting through the Settings preference controller
rav_open_fileOpen a .riv file by absolute path
rav_play / rav_pause / rav_resetPlayback controls
rav_get_artboardsList artboard names
rav_get_state_machinesList state machine names
rav_switch_artboard / rav_reset_artboardSwitch artboard/animation, reset to default
rav_switch_vm_instanceBind a specific authored or runtime/list ViewModel instance key
rav_get_vm_treeFull ViewModel hierarchy
rav_vm_get / rav_vm_set / rav_vm_fireRead, write, and fire ViewModel properties
rav_vm_set_image / rav_vm_clear_imageSet or clear an image on the authoritative root ViewModel
rav_get_global_vm_treeList every named file-level global ViewModel and its hierarchy
rav_global_vm_get / rav_global_vm_set / rav_global_vm_fireRead, write, or fire a property in a specifically named global ViewModel
rav_global_vm_set_image / rav_global_vm_clear_imageSet or clear a named global ViewModel image through authoritative playback
rav_get_event_logRecent event log entries (filterable by source)
rav_get_editor_code / rav_set_editor_codeRead/write the script editor
rav_apply_codeApply editor code and reload animation (Script Access required)
rav_set_runtimeSwitch runtime (webgl2/canvas)
rav_set_layout / rav_set_alignmentSet layout fit mode and nine-way canvas alignment
rav_set_canvas_colorSet background color or transparent
rav_set_canvas_sizeSet canvas sizing mode (auto or explicit pixels) and optional aspect lock
rav_capture_canvasCapture the authoritative rendered canvas as PNG image content with render metadata
rav_open_isolated_playbackOpen the current animation in an ordinary isolated diagnostic WebView
rav_export_demoExport standalone HTML demo
rav_export_demo_visualDrive the visible export dialog with exact control selection, package source, snippet mode, and output path
generate_web_instantiation_codeGenerate 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_dialogOpen/close the in-app Snippet & Export Controls dialog so a human can choose which controls are serialized
rav_configure_workspaceOpen/close sidebars, switch live source mode (internal / editor), and inject/remove the VM Explorer snippet idempotently
rav_get_sm_inputs / rav_set_sm_inputState machine input access
rav_evalEvaluate JS with `target: auto
rav_console_open / rav_console_closeToggle the JS console remotely
rav_console_set_mode / rav_console_set_filter / rav_console_clearSwitch console mode, mirror visible filters, and clear the active transcript
rav_console_read / rav_console_execRead 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_eval defaults to the active authoritative playback child and otherwise uses the host WebView. Set target: "playback" to require the child or target: "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_code switches the live runtime to the last applied editor config.
  • Unsaved editor draft changes do not change the running animation until applied.
  • rav_status reports the active instantiation source and whether the editor draft is dirty.
  • rav_status also 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; call rav_get_vm_tree again 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_code always reflects what is actually running.
  • generate_web_instantiation_code defaults to the CDN form unless you explicitly request package_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 × height sizing 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 VariableDefaultDescription
RAV_MCP_PORT9274WebSocket 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.json only 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>:

  • bNNNN auto-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.js and 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 update to ensure latest Rust
  • Check npm run tauri info for 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.