reins Hands and eyes inside your app for coding agents. Built for Lucid Coding.

  • < 5 KB min+gzip
  • Zero bytes in prod
  • Web + Expo
  • MCP + WebMCP

Stop making agents click by pixels and guess what happened. Register named actions, expose redacted state, and mark the panels worth snapping—all in one package (npm i -D reins) with an agent skill that wires it for you.

DEVELOPMENT & AGENT VERIFICATION Your Web or Expo App (dev) reins (< 5 KB, 0 browser deps) • Actions: login-as-tester, set-locale • State: Zustand / Redux / React Query • Network & error ring buffers (redacted) • <ReinsPanel id="checkout"> + WebMCP 127.0.0.1:7357 192-bit token Localhost Bridge npx reins bridge • Writes .reins/token (rotated) • Checks Origin header allowlist • Appends .reins/audit.log • Captures panel PNGs (CDP / adb) stdio MCP 9 tools Coding Agent & Coordinator Claude Code · Codex · Cursor • Calls reins_list_actions first • Drives flows via reins_run_action • Reads reins_state & reins_network • Blind critic snaps panels as evidence PRODUCTION BUILD GATE reins/vite · reins/next · reins/metro → aliases reins to reins/stub (0 dev code) → verified by reins verify dist ✓ CLEAN BUNDLE
  1. Inside the app, not outside. The agent calls your app's real functions and reads its real stores instead of scraping DOM nodes.
  2. Inert until paired. Nothing is patched and no listener is added until the app presents the one-time token from .reins/token.
  3. Guaranteed out of production. Build plugins swap reins for a no-op stub, and reins verify fails the build if __REINS_DEV_ONLY__ leaks.

Why not just let the agent click by pixels?

Browser automation tools see the DOM from the outside. reins lets your app declare a small, stable contract from the inside—and pairs cleanly with Playwright when you want both.

Capability Pixel clicking / Raw DevTools MCP Browser WebMCP alone reins
Reaching a screen state (e.g. Arabic + logged in + 3 cart items) Clicks through 6 screens, types passwords, waits on spinners, breaks when copy changes. Runs registered page tools if the browser supports navigator.modelContext. One reins_run_action call with schema-validated JSON input. Also registers on WebMCP automatically.
Reading app state & network Dumps raw DOM or unredacted network traffic, including auth cookies and tokens. No built-in state snapshots, network ring buffer or error log. Named snapshots (zustand, redux, reactQuery) + network & error buffers, redacted by default.
Visual panel snapshots & DOM/CSS layout Full-page screenshots or brittle CSS selector crops; guesses clipping from pixels. Not supported. <ReinsPanel id="checkout"> gives pixel-exact PNG snaps + reins_dom computed CSS and automatic horizontal-clip / vertical-clip / zero-size flags.
Performance & lifecycle timeline Manual trace files or wall-clock guesses. Not supported. reins_perf reports TTFB, FCP, DOM interactive/load, component mount times & render counts, API latency stats, and a unified millisecond timeline.
React Native & Expo Requires separate native UI hierarchy scrapers. Browser only. First-class reins/expo and reins/metro over 127.0.0.1:7357.
Production safety Test hooks or globals often ship to production by accident. Up to you to strip. Build plugins swap reins for a stub + reins verify fails CI if any dev marker remains.

One package. Or let your agent wire it in one command.

Everything—core, React & Expo hooks, state adapters, Vite/Next/Metro plugins, the MCP bridge, and the bundle verifier—ships in a single dev dependency: npm i -D reins.

Recommended Let the agent set it up

Install the reins plugin in Claude Code (or add the skill folder to Codex / Cursor / Antigravity) and run /reins:setup. The agent inspects your stack, installs reins, wires the bundler plugin, connects dev mode, wraps key screens in <ReinsPanel>, and registers the MCP server.

/plugin marketplace add mindmakr/reins
/plugin install reins@reins
/reins:setup

On Claude Code 2.1.275+: /plugin install reins --marketplace mindmakr/reins

Install the single npm package + MCP server

Prefer to wire it by hand? Install reins once and add npx reins bridge to your project's .mcp.json:

npm i -D reins
{
  "mcpServers": {
    "reins": { "command": "npx", "args": ["reins", "bridge"] }
  }
}

1. Bundler plugin & dev connect vite.config.ts + src/main.tsx

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

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

// src/main.tsx
import { reins } from 'reins';
import { zustand } from 'reins/adapters';
import { useAppStore } from './store';

if (import.meta.env.DEV) {
  reins.state('app', zustand(useAppStore));
  reins.connect();
}

Build script gate: "build": "vite build && reins verify dist"

2. Register actions & panels src/Settings.tsx

import { useReinsAction, ReinsPanel } from 'reins/react';

export function Settings() {
  const { setLocale } = useI18n();
  useReinsAction({
    name: 'set-locale',
    description: 'Switch the UI language',
    input: {
      type: 'object',
      properties: { locale: { type: 'string', enum: ['en', 'ar', 'fr'] } },
      required: ['locale'],
    },
    run: ({ locale }) => setLocale(locale),
  });
  return <ReinsPanel id="settings">…</ReinsPanel>;
}

Also exposes window.__reins__ in browser DevTools and registers WebMCP tools when paired.

1. Next config & token route next.config.mjs + route.ts

// next.config.mjs
import { withReins } from 'reins/next';
export default withReins({ /* your Next config */ });

// app/api/reins-token/route.ts
export { GET } from 'reins/next/token-route';
export const dynamic = 'force-dynamic';

Works with both Webpack and Turbopack. Build gate: "build": "next build && reins verify .next/static"

2. Client bootstrap app/Reins.tsx

'use client';
import { useEffect } from 'react';
import { reins } from 'reins';

export function Reins() {
  useEffect(() => {
    if (process.env.NODE_ENV !== 'production') {
      reins.connect({ tokenUrl: '/api/reins-token' });
    }
  }, []);
  return null;
}

In components, import useReinsAction, useReinsState and ReinsPanel from reins/react.

1. Metro config metro.config.js

const { getDefaultConfig } = require('expo/metro-config');
const { withReins } = require('reins/metro');

module.exports = withReins(getDefaultConfig(__dirname));

For Android emulators or USB devices: adb reverse tcp:7357 tcp:7357. Export gate: npx expo export && npx reins verify dist.

2. Connect & wrap views App.tsx

import { connectExpo, ReinsPanel, useReinsAction } from 'reins/expo';

if (__DEV__) connectExpo();

export default function App() {
  useReinsAction({
    name: 'open-cart',
    description: 'Open the cart screen',
    run: () => navigation.navigate('Cart'),
  });
  return <ReinsPanel id="home">…</ReinsPanel>;
}

<ReinsPanel> renders a native View with testID={id} and measures window coordinates in device pixels.

Nine MCP tools. Seven hard security limits.

Give agents instruments, not just screenshots—with boundaries enforced in code, not just prompts.

The 9 MCP tools

  • reins_list_actionsReturns the paired app, its registered actions with JSON schemas, state sources and mounted panels. Always call this first.
  • reins_run_actionRuns one named action: { name, input, confirm? }. Also records a [reins] <name> performance measure.
  • reins_stateReads a redacted snapshot of one state source (Zustand, Redux, React Query, route, storage) or all of them.
  • reins_networkRecent fetch calls: method, URL, status, startMs, duration in ms, and redacted headers/bodies.
  • reins_errorsRecent console.error calls, uncaught exceptions and unhandled promise rejections.
  • reins_panel_boxBounding box of a <ReinsPanel id> in CSS pixels with devicePixelRatio and viewport dimensions.
  • reins_snapSaves a pixel-exact PNG of a panel to .reins/snaps/ (via Playwright CDP in browsers or adb screencap on Android).
  • reins_perfPage lifecycle timings (TTFB, FCP, DOM interactive, load), component/panel mount times and render counts, API call latency stats, and a unified millisecond timeline.
  • reins_domInspects a panel or CSS selector's DOM subtree, bounding boxes, computed CSS styles (direction, display, flexDirection, overflowX), and automatic layout issue flags (horizontal-clip, vertical-clip, zero-size).

Security model (enforced in code)

  1. Kept out of production. Core turns on only in dev builds. Bundler plugins alias reins to reins/stub, and reins verify fails the build if __REINS_DEV_ONLY__ is found.
  2. Off until paired. Before the bridge accepts its 192-bit token from .reins/token, reins patches nothing and adds no listeners.
  3. Loopback & origin locked. The bridge binds to 127.0.0.1 only (no host flag) and refuses non-localhost WebSocket Origin headers.
  4. Redacted by default. Request/response bodies, Authorization/Cookie headers, storage values and sensitive state keys (token, password, secret, session) become [redacted] unless allowlisted.
  5. Consequential actions require confirmation. Any action marked consequential: true is refused unless called with confirm: true.
  6. Full audit log. Every pairing, refusal, MCP call, DevTools call and WebMCP call is written to .reins/audit.log with redacted arguments.
  7. Lazy & no eval. Waits for load + idle before pairing, and can only run functions explicitly registered by the app.
Built for Lucid Coding

The companion to Coordinator

Coordinator (mindmakr/coordinator) runs multi-step engineering work through builders and independent blind critics until every behaviour meets a hard bar. reins gives those builders and blind visual critics hands and eyes inside your running app.

  • 1. Agree the bar before the build (Principle #3). Coordinator writes each unit's bar as testable given / when / then behaviours referencing your app's reins actions and <ReinsPanel id> names.
  • 2. Give agents instruments, not just screenshots (Principle #2). The builder and critic read reins_state, reins_network, reins_perf (lifecycle, component mounts & render counts, API latency timeline), and reins_dom (computed CSS & overflow clipping flags) alongside reins_snap PNGs.
  • 3. Blind critic & measurement on the record (Principles #4, #5 & #8). A separate visual critic—who never sees the builder's reasoning—drives your app across locales (e.g. en and ar RTL), verifies zero layout clipping and fast paint/mount timings, and attaches durable proof on the Coordinator dashboard.

Install both skills in Claude Code

/plugin marketplace add mindmakr/coordinator
/plugin install coordinator@coordinator
/plugin marketplace add mindmakr/reins
/plugin install reins@reins

Then in any web or Expo project

# 1. Wire reins into the app automatically
/reins:setup

# 2. Initialize Coordinator on the repo
/coordinator:init

# 3. Build & verify with builders + blind critics
/coordinator:run Add Arabic RTL checkout flow