Tourwright

Official registry Search and web

Turn a script into a narrated product tour video: real browser, captions, voice, MP4.

Install

Add this to your client's MCP configuration (Claude Desktop: claude_desktop_config.json; Cursor: .cursor/mcp.json; VS Code and others use the same "mcpServers" shape).

NPM package tourwright
Claude Code
claude mcp add tourwright -e 'TOURWRIGHT_API_URL=<TOURWRIGHT_API_URL>' -e 'TOURWRIGHT_API_TOKEN=<your tourwright_api_token>' -- npx -y tourwright@2.1.0 mcp
JSON configuration (Claude Desktop, Cursor, VS Code)
{
    "mcpServers": {
        "tourwright": {
            "command": "npx",
            "args": [
                "-y",
                "tourwright@2.1.0",
                "mcp"
            ],
            "env": {
                "TOURWRIGHT_API_URL": "<TOURWRIGHT_API_URL>",
                "TOURWRIGHT_API_TOKEN": "<your tourwright_api_token>"
            }
        }
    }
}

Environment variables

  • TOURWRIGHT_API_URL Send jobs to a Tourwright API instead of rendering on this machine
  • TOURWRIGHT_API_TOKEN secret Token for TOURWRIGHT_API_URL

Documentation

From the project's README on GitHub, refreshed weekly. Links open on GitHub.

Contents
  1. Why Tourwright
  2. What you get
  3. Install
  4. Use it
  5. Scaling
  6. Security
  7. License

Scripted, narrated product tours. Write what should happen on screen and what should be said; Tourwright films a real browser (or builds slides), guides the eye to each element, synthesizes the voice, and delivers an .mp4 with captions, chapters, subtitles and a thumbnail. Built for people and AI agents, on any server, from a laptop to a cluster.

Leer en español

Made by Tourwright from examples/app.yaml, with nobody at the keyboard. ▶ Watch it with sound (52 s)

# tour.yaml
title: Your first invoice
voice: lessac
baseUrl: https://app.example.com
steps:
  - goto: /invoices/new
  - title: { text: Your first invoice, subtitle: Step by step }
  - say: Pick the <b>customer</b> first.
  - click: { role: combobox, name: Customer }
  - say: Then save. That's it.
  - click: { role: button, name: Save }
tourwright render tour.yaml        # → videos/tour.mp4 (+ .srt .vtt .jpg .json)

Why Tourwright

Screen recorders (Loom) and click-through demo tools (Arcade, Supademo, Scribe) need a person to record, and every redesign means recording again. Tourwright videos are code:

Screen recorderDemo SaaSTourwright
Re-record after a UI changeby handby handtourwright render
Knows when a video went stalenonotourwright check in CI names the broken step and the fix
Narrationyour voice, retakesnone or extratext-to-speech in many voices, offline or online
Same tour for 50 customers or languages50 recordings50 demosone script with {{variables}}
Personal data on screenedit it outedit it outmask replaces it with invented data
Lives ina vendor's clouda vendor's cloudyour git repo, your servers; MIT
AI agents can make onenonoMCP server and a Claude Code plugin

What you get

  • Browser walkthroughs: real Chromium, a smooth animated cursor, click ripples, highlights, spotlights, callout bubbles, camera zoom, drag and drop, blurred personal data, title cards and captions in your colors and logo.
  • Guided focus: the tour an app shows the first time you open it. Everything dims but the element, a ring marks it, a bubble with a 2/4 badge explains it and the camera pushes in, right on the word the voice is saying.
  • Narrated slides: title cards, images (with slow pan/zoom), HTML, crossfades. No website needed.
  • Voices, your choice: Pocket TTS (offline, open, natural: tourwright install --pocket), Piper (offline, open source, light), Microsoft Edge neural voices, any OpenAI-compatible TTS server (OpenAI, Kokoro, LocalAI…), or your own command. Every sentence is cached: re-rendering never re-synthesizes.
  • A cast, and how each line is said: several voices per video, speed, pitch and volume per line on any engine, exact pauses ([[1s]]), a pronunciation dictionary, sound presets (warm, radio, podcast…), click, typing and other sound effects, music with fades.
  • Scripts that scale with you: variables ({{name}}, also from the CLI or the API), reusable blocks, repeats, conditions and steps that may fail. One script, many videos.
  • Plugins: new actions, TTS engines and voices as small modules (docs/PLUGINS.md).
  • Tight edits, automatically: page loads, slow waits and voice synthesis are cut out; narration never overlaps; background music ducks under the voice.
  • Deliverables: H.264/AAC .mp4 with soft subtitles and chapters, .srt, .vtt, thumbnail and a JSON manifest (duration, chapters, captions) for automation.
  • Four ways in: CLI, HTTP API with job queue and webhooks, MCP server for AI agents, Node library.
  • Scales out: stateless API replicas, any number of workers on any number of servers, Redis/BullMQ queue, S3-compatible storage. Or a single process with a folder, on a Raspberry Pi.

Install

docker run --rm -v "$PWD:/work" -w /work ghcr.io/cxmiloxx/tourwright render examples/slides.yaml --out videos/

A full service (API + 2 workers + Redis):

cp .env.example .env    # set TOURWRIGHT_API_TOKENS
docker compose up -d --build
docker compose up -d --scale worker=6
From npm (quickest to try)

Node.js 22+, on Linux, macOS or Windows:

npm install -g tourwright
tourwright install                    # ffmpeg, Piper + voices, edge-tts, Chromium (no root)
tourwright install --plan             # only show what it would use from this PC and what it would download
tourwright config set quality fullhd  # your own defaults: quality, voice, fps… (tourwright config lists them)
tourwright record https://app.example.com --out tour.yaml   # do the tour by hand: it writes the script
tourwright guide tour.yaml --open     # the same tour as a step-by-step guide with screenshots (HTML, PDF, Markdown)
tourwright narrate tour.yaml --write  # your AI (Claude, OpenAI, Ollama) rewrites the narration from the screens
tourwright check videos/*.yaml        # which videos broke after a deploy, at which step, and the fix
tourwright fix tour.yaml --write      # puts the new targets in the script
tourwright render tour.yaml --step 7  # film one step with its voice, without the whole video
tourwright install --pocket           # + Pocket TTS: natural offline voices (about 1 GB)
tourwright clean                      # what each part takes on disk; removes downloads and leftovers
tourwright doctor                     # what works on this machine

Without installing anything globally: npx tourwright <command>. With pnpm: pnpm add -g tourwright (on 2.0.0, add --no-optional).

The Redis queue and Claude for narrate are optional: install bullmq ioredis or @anthropic-ai/sdk next to Tourwright when you use them (npm install -g bullmq ioredis). The Docker image already has them.

Without Docker (Linux, macOS, Windows)

Node.js 22+. tourwright install puts ffmpeg, Piper, voices, edge-tts and Chromium in TOURWRIGHT_HOME, with no root or admin rights; what the system already has is kept.

git clone https://github.com/CXmiloxx/tourwright && cd tourwright
./scripts/install.sh           # Linux / macOS (Windows: powershell -ExecutionPolicy Bypass -File scripts\install.ps1)
node bin/tourwright.js doctor  # what works on this machine
npm link                       # optional: the `tourwright` command

Each piece is looked for on the PC first and only downloaded when it is missing:

Linux (x64, arm64)macOS (Intel, Apple Silicon)Windows 10/11 (x64, ARM)
ChromiumChrome, Edge or Chromium (apt, dnf, pacman, Raspberry Pi OS), else downloadedChrome, Edge or Chromium, else downloadedChrome or Edge, else downloaded
ffmpegPATH, Homebrew, Nix, else downloadedHomebrew, MacPorts, Nix, else brew install ffmpegPATH, winget, scoop, Chocolatey, C: fmpeg, else downloaded
Piper (offline voices)PATH, pip, pipx, conda, else downloadedPATH, pip, pipx, conda, else piper-ttsPATH, pip, pipx, conda, else downloaded
Piper voicesHugging Face cache, TOURWRIGHT_PIPER_VOICE_DIRS, else downloadedsamesame
edge-tts (Microsoft voices)PATH, pip, pipx, conda, else installedsamesame
Python (for edge-tts, Pocket, Whisper)the system's 3.10–3.13, else 3.12 is downloadedsamesame (not the Microsoft Store stub)
Capturescreen with Xvfb (sharpest), else screencastscreencastscreencast

Also reused: a Chromium left by another Playwright or Puppeteer version, and CHROME_PATH, CHROME_BIN or PUPPETEER_EXECUTABLE_PATH. Snap and Flatpak browsers are skipped (their sandbox blocks Playwright). TOURWRIGHT_SYSTEM_BROWSER=0 always uses Playwright's own Chromium. tourwright doctor shows what was found.

Nothing is installed on the system: what is downloaded lives in one folder (TOURWRIGHT_HOME), and the Python packages run in a virtual environment, so yours is never changed. To uninstall, delete that folder.

Xvfb (apt install xvfb, Linux only) gives the sharpest capture; without it Tourwright records headless (screencast), which works everywhere Chromium runs. Clients of the HTTP API or MCP can be on any system.

Use it

From a site to a video, without writing selectors by hand:

tourwright explore https://app.example.com/login --draft app.yaml   # asks for the login, writes the script
tourwright render app.yaml --dry-run                               # checks every step in seconds
tourwright render app.yaml --open                                  # the video, in ./videos/app/

The draft goes through every section of the site with narration taken from its pages; edit it in your words. Credentials are asked for once, never shown and never written in the script (tourwright secret list; tourwright forget deletes them).

tourwright init video.yaml                  # an example script
tourwright validate video.yaml
tourwright render video.yaml --dry-run      # runs every step fast: tests selectors, no voice/video
tourwright render video.yaml --quality fullhd --voice salome --out out/
tourwright voices                           # voices available here
tourwright install-voice en_GB-alba-medium  # any voice from huggingface.co/rhasspy/piper-voices
tourwright say "Hello there" --voice lessac --out hello.wav

The script format, every action and the voices: docs/SCRIPTS.md. JSON Schema for editors and agents: schema/script.schema.json.

HTTP API
TOURWRIGHT_API_TOKENS=secret tourwright serve --worker --port 4700
curl -X POST localhost:4700/v1/jobs -H 'authorization: Bearer secret' -H 'content-type: application/json' \
  -d '{"script": {"type": "slides", "slides": [{"title": "Hello", "say": "Hello from the API."}]}}'
curl localhost:4700/v1/jobs/<id> -H 'authorization: Bearer secret'   # → status, result, download links

Endpoints, assets, webhooks: docs/API.md.

AI agents (MCP)

Claude Code, as a plugin (the MCP server plus a skill that writes, checks and renders the script):

/plugin marketplace add CXmiloxx/tourwright
/plugin install tourwright@tourwright

Any other MCP client (Claude Desktop, Cursor, VS Code…):

{ "mcpServers": { "tourwright": { "command": "tourwright", "args": ["mcp"] } } }

Tools: tourwright_guide, tourwright_voices, tourwright_validate, tourwright_render, tourwright_job (and tourwright_render_file with TOURWRIGHT_MCP_ALLOW_FILES=true). Point it at a remote API with TOURWRIGHT_API_URL and TOURWRIGHT_API_TOKEN. Details: docs/AGENTS.md.

GitHub Action

Re-render your tours on every release, or fail the build when a deploy broke one:

- uses: CXmiloxx/tourwright@v2
  with:
    scripts: videos/*.yaml
    command: check            # or render: the videos become a workflow artifact
  env:
    TOURWRIGHT_SECRET_APP_PASSWORD: ${{ secrets.APP_PASSWORD }}

Inputs: scripts, command, out, voice, quality, voices, version, upload (action.yml).

Node library
import { loadFile, render } from 'tourwright'
const result = await render(await loadFile('tour.yaml'), { out: 'videos/', quality: 'hd' })
console.log(result.paths.video, result.duration, result.chapters)

Scaling

SizeSetup
One machinetourwright serve --worker — local folder queue, files on disk
One big machinedocker compose up --scale worker=N — Redis queue, shared volume
Many machinesAPI replicas behind a load balancer, workers anywhere, same Redis + S3 bucket
Kubernetesdeploy/kubernetes/tourwright.yaml, workers autoscaled

Each worker renders TOURWRIGHT_CONCURRENCY videos at a time (one Chromium + ffmpeg each: plan ~1–2 CPU and ~1 GB RAM per video at 720p). Workers run at low CPU and disk priority so a shared server stays responsive. More: docs/DEPLOYMENT.md · configuration: docs/CONFIGURATION.md.

Security

API jobs run in a sandbox: data-only scripts (no JavaScript), files limited to the job's assets, optional host allowlist and private-network blocking, secrets off by default, per-token job isolation, signed download links. Read SECURITY.md before exposing the API to untrusted clients.

License

MIT. Piper voices have their own licenses (see each voice's model card); Edge voices are a Microsoft online service, check its terms for your use.

Frequently asked questions

What is Tourwright?

Turn a script into a narrated product tour video: real browser, captions, voice, MP4.

How do I install Tourwright?

It runs on your machine. In Claude Code: claude mcp add tourwright -e 'TOURWRIGHT_API_URL=<TOURWRIGHT_API_URL>' -e 'TOURWRIGHT_API_TOKEN=<your tourwright_api_token>' -- npx -y tourwright@2.1.0 mcp. For other clients, paste the JSON configuration from this page into their MCP settings.

Does Tourwright need an API key?

Yes. It expects TOURWRIGHT_API_TOKEN, which you set in its configuration.

Is Tourwright open source?

Yes. Its code is on GitHub under the MIT license.

Who maintains Tourwright?

It is published by CXmiloxx. AI.tn lists it but does not maintain or endorse it.

From the official MCP Registry. Listing is not an endorsement: review a server's code and permissions before giving it access to your data.