Flow recorder for Vite + React

Record a flow. Replay it with an agent.

A small dev-only overlay for your Vite + React app. Click Record, use the app, then export the journey as JSON and a Claude Code prompt you can commit and replay in a real browser.

View on GitHub
  • record
  • export
  • prompts/<slug>.md
  • session history
  • redaction
  • local-first

How it works

Record, export, then replay

flowtape records the journey inside your running app. There is no browser extension and nothing to script by hand.

  1. 01

    Record

    Click Record in the overlay. flowtape logs the current page, then every click, field value, form submit and client-side navigation.

  2. 02

    Stop and name

    Click Stop and type a name, such as Login and add note. The name becomes the file slug.

  3. 03

    Export

    flowtape writes flows/<slug>.json, a FlowDocument validated with Zod, and prompts/<slug>.md, a Claude Code prompt.

  4. 04

    Replay with Claude Code

    Start your dev server, give Claude Code a browser tool such as Playwright MCP, and hand it the prompt.

.flowtape/prompts/login-and-add-note.mdExcerpt
# Flow: Login and add note

## Goal
Replay the recorded journey in a real browser
and confirm each step works as recorded.

## Preconditions
- Redacted fields read their values from
  environment variables: `FLOWTAPE_PASSWORD`.

## Steps
1. Open `/`.
2. Type `ada@example.test` into the field "Email".
3. Fill the password field with `$FLOWTAPE_PASSWORD`.

## Assertions
## Fuzz hints
## Out of bounds
## Report back
Excerpt from the sample prompt committed in the flowtape demo app.

Commit flows and prompts

Flows and prompts are meant to be committed. They act as living, reviewable test journeys. Export under the same name to overwrite them.

Fill in the TODOs

Assertions and fuzz hints are heuristics. Fill in the TODO lines, such as seed data and final-state checks, before you rely on them.

Terminal
# Interactive
claude "Follow @.flowtape/prompts/login-and-add-note.md against the running app"

# Headless
claude -p "$(cat .flowtape/prompts/login-and-add-note.md)"

Session history

A quiet log of what you did

In development, flowtape keeps an always-on, redacted log for each browser tab. It records navigations, clicks, field values (type-only for masked fields), form submits, and uncaught errors and unhandled rejections. Error lines keep a scrubbed message, never a stack.

Record flow vs session history
Record flowSession history
StartsWhen you click RecordAutomatically in development
EndsWhen you click StopWhen you switch it off or close the tab
Outputflows/<slug>.json and prompts/<slug>.mdhistory/<date>-<sessionId>.jsonl
GitCommittedIgnored
.gitignore
**/.flowtape/history/

Toggle it in the overlay

Use the Session history switch at the bottom of the overlay. While it is on, the overlay shows the session id, event count and file path. The choice survives reloads.

One file per tab

Reloading appends to the same file. A new tab starts a new one. History is never turned into a named flow; use Record for that.

Terminal
# Ask Claude Code to review it
claude "Read the latest files in .flowtape/history/ and summarise what I did in the app and any errors I hit"

# List history files, newest first
npx flowtape history

Redaction and local-first

Secrets are scrubbed three times

Redaction runs in the browser as events are recorded, on the server before files are written, and over the final Markdown. Session history gets the first two.

  1. 01

    In the browser

    Values are redacted as each event is captured, before anything leaves the page.

  2. 02

    On the server

    The dev middleware validates and redacts again before it writes a flow or appends to history.

  3. 03

    Over the prompt

    The final Markdown is scrubbed once more before it is saved.

  • Password fields never store a value. The event keeps only that it was redacted and the value's length.
  • data-flowtape-mask on a field or any ancestor records every field inside type-only.
  • Secret-looking field names, such as token, API key, OTP or card number, are masked automatically.
  • Pattern scrub replaces secret shapes in every stored string, such as bearer tokens, JWTs, API keys and PEM private keys, with [REDACTED].

The pattern scrub is a safety net, not a guarantee. Mask sensitive fields explicitly and review a flow before you commit it.

Test credentials, by name

Redacted fields name an environment variable, such as $FLOWTAPE_PASSWORD. Set it to a test credential in the shell that runs Claude Code. The prompt tells the agent never to print, log or screenshot it.

Everything stays on your machine

The middleware serves /__flowtape/* during vite dev only. The overlay renders only outside production builds.

  • no account
  • no cloud
  • no extension
  • no network capture

Setup

Three steps into any Vite app

To keep the overlay out of your production bundle entirely, render it behind import.meta.env.DEV.

1. Install the package.

Terminal
npm install -D @vedantb/flowtape

2. Add the plugin.

vite.config.ts
import react from '@vitejs/plugin-react';
import { flowtape } from '@vedantb/flowtape/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [flowtape(), react()],
});

3. Mount the overlay once.

main.tsx
import { FlowtapeOverlay } from '@vedantb/flowtape';

createRoot(root).render(
  <>
    <App />
    <FlowtapeOverlay />
  </>,
);