VIXENTIO / Developers
Build the visual loop into your stack.
Overview
VIXENTIO connects what you see in a running app to the code behind it and to the coding agent that changes it. Five parts work together:
- The Mac app captures, annotates and reviews, runs agent tasks and publishes pull requests.
- A dev-server integration (
@vixentio/vite-pluginor@vixentio/next) tags each host JSX element with its source location in development builds only. - The browser runtime (
@vixentio/dev-runtime) lets you Option-click an element, then reports the component, its source and a style summary. - The local bridge connects the runtime, the dev server and the VS Code extension to the app over a Unix socket and a loopback WebSocket. Nothing goes over the network.
- Your coding agent, Claude Code, Codex or Cursor, receives the request under your own account. Agent tasks run Claude Code headless with a VIXENTIO MCP server.
Production builds contain no source tags, no runtime and no VIXENTIO module.
Quickstart
- Install VIXENTIO for Mac (macOS 14 or later) and open it once.
- Add the integration for your framework as a development dependency. The packages come with Developer Platform onboarding.
- Register the plugin in your Vite or Next.js config, as shown below.
- Start your dev server, hold Option and click any element in the page.
- Choose Open in VIXENTIO, add your instruction and send it to your agent, or start an agent task.
Vite
React 18 or 19 on Vite 6 or later. Put the plugin first:
// vite.config.ts
import { defineConfig } from "vite"
import react from "@vitejs/plugin-react"
import vixentio from "@vixentio/vite-plugin"
export default defineConfig({
plugins: [vixentio(), react()],
})
The plugin applies to the dev server only (apply: "serve") and tags .jsx, .tsx, and .js or .mjs files that contain JSX.
Next.js
Next.js 15.3 or later with the App Router, on Turbopack or webpack:
// next.config.ts
import type { NextConfig } from "next"
import { withVixentio } from "@vixentio/next"
const nextConfig: NextConfig = {
// your existing configuration
}
export default withVixentio(nextConfig)
Outside the development server, withVixentio returns your config unchanged. In development it adds the source transform for Turbopack (*.tsx, *.jsx, *.js, excluding node_modules) or webpack, and mounts the runtime as the first child of <body> in app/layout. The Pages Router gets source tags but no runtime.
Integrations
| Package | Purpose | Requires |
|---|---|---|
@vixentio/vite-plugin | Source tagging and the runtime for Vite dev servers | vite 6 or later |
@vixentio/next | Source tagging and the runtime for Next.js development | next 15.3 or later |
@vixentio/dev-runtime | The in-page inspector: selection, overlay, Workbench rendering | Added by the plugins |
@vixentio/dev-transform | Tags host JSX elements with their source location | Used by the plugins |
@vixentio/dev-bridge | Finds VIXENTIO on this Mac and registers the running project | Used by the plugins |
The packages are distributed to teams during onboarding rather than through the public npm registry. All are version 0.1.0.
Plugin options
Both integrations take the same options:
interface VixentioOptions {
instance?: "release" | "development" // which VIXENTIO app to talk to; default "release" or VIXENTIO_INSTANCE
modifier?: "alt" | "alt+shift" // the key you hold to select; default "alt"
include?: RegExp // Vite only: files to tag
workbench?: { wrapper?: string } // providers for the Component Workbench, as "file#export"
}
// Use Option and Shift to select, and wrap Workbench renders in your providers
vixentio({ modifier: "alt+shift", workbench: { wrapper: "./src/providers.tsx#Providers" } })
withVixentio(nextConfig, { workbench: { wrapper: "./src/app/providers.tsx#Providers" } })
Component Workbench
The Workbench renders one component on its own through your dev server, with its props, states, widths from 320 to 2560 pixels, and light and dark themes. Vite serves it at /__vixentio/workbench. On Next.js, add a page that only exists in development:
// app/vixentio-workbench/page.vixentio.tsx
export default function VixentioWorkbench() {
return null
}
To render components inside your providers, export a wrapper from vixentio.workbench.tsx at the project root:
// vixentio.workbench.tsx
import type { ReactNode } from "react"
import { ThemeProvider } from "./src/theme"
export function Wrapper({ children }: { children?: ReactNode }) {
return <ThemeProvider>{children}</ThemeProvider>
}
Files listed in .vixentioignore (gitignore syntax) are left out of the index.
Selecting elements
Hold Option and move the pointer to outline an element with its component name and file. Option-click selects the nearest tagged element and opens a menu: Open in VIXENTIO, Open in Workbench, Select Parent and Copy Source Location. Copy Source Location puts the source id on the clipboard, for example src/components/pricing/PricingCard.tsx:14:7.
Each selection reports:
- the route, a redacted URL, the component name, its file and range, and its call site
- bounds, viewport and device pixel ratio, up to 40 classes and the owner chain
- a style summary: display, position, flex and grid, gap, size, padding, margin, font, color, background, border, radius, shadow, opacity and z-index
- safe props and the CSS variables in use, and how exactly the selection maps to source (
exact,approximateornone)
Safe props. Props whose names match password, secret, token, key, auth, session, cookie, email, phone, card or credential are dropped, along with ref. At most 20 props are kept; strings only up to 120 characters; functions, objects and elements are reported by kind only.
Never captured. Page text, form values, cookies and storage. Debug capture never reads request or response headers or bodies, drops query values, credentials and fragments from URLs, and masks bearer tokens and JWTs.
Agent hand-offs
From the Mac app, a request goes to the agent you choose, opened in your project. The capture is exported to ~/Library/Caches/<bundle id>/AgentExports/, and export folders are removed after 7 days.
| Agent | How it receives the request |
|---|---|
| Claude Code | claude --add-dir <exports> -- <prompt> in a new Terminal session, or the claude-cli://open deep link |
| Claude Code, running | Typed into an open session in Terminal or iTerm2, or pasted into a tmux pane |
| Codex | codex --cd <project> --image <capture.png> -- <prompt> |
| Cursor | Opens the project with the prompt filled in; the capture is placed on the clipboard |
The prompt your agent receives:
Make this the primary action and keep its label readable on phones.
Annotated screenshot from VIXENTIO: "Pricing page" (1440 × 900 px, 3 annotations)
Image: ~/Library/Caches/<bundle id>/AgentExports/20261013-101500-a1b2c3/Pricing page.png
Project: ~/Projects/harbor-web
Context files
- Board Context.md is written next to the image when you send a Board. It starts with the Board and page titles and lists Frames, Nodes, Connections, Text, Sticky notes, Charts, Equations (as LaTeX), Graphs, Entities, Embedded items, Web links and Files.
- Context packs are Markdown: a title, Task, the sections the AI writes, Requested outcome, Open questions and the attached material, with code and errors fenced.
- Implementation packages for Claude Code open in plan mode (
--permission-mode plan) and cover project context, existing architecture, requirements, API contracts, data models, files and modules, security, implementation phases, tests, acceptance criteria and checked source references.
Agent tasks and MCP
An agent task runs Claude Code headless inside your repository, under your Claude account. VIXENTIO starts it with a restricted, explicit configuration:
claude -p --output-format stream-json --verbose --input-format stream-json --include-hook-events \
--restricted --strict-mcp-config --mcp-config <run>/mcp.json --settings <run>/claude-settings.json \
--permission-mode default --permission-prompt-tool mcp__vixentio__permission --permission-prompts host \
--disable-slash-commands --tools <phase tools> --session-id <uuid> \
--max-budget-usd 2.00 --max-turns 40
| Phase | Tools |
|---|---|
| Analyze | Read, Grep, Glob |
| Execute and refine | Read, Grep, Glob, Edit, MultiEdit, Write, Bash, TodoWrite; web tools only if your project enables them |
| Publish | Read, Grep, Glob, Bash and the publish tools below |
Each run is limited to a spending cap (2 US dollars by default, 0 for none), 40 turns and 30 minutes. You can leave the model on Auto or choose Haiku, Sonnet or Opus.
MCP tools
The task's MCP server is named vixentio and runs over stdio for that task only.
| Tool | What it returns | Input |
|---|---|---|
vixentio_find_component | Where a React component is defined, and the routes that render it | name |
vixentio_component_usages | Where a component is used, grouped by route (up to 50) | name |
vixentio_design_tokens | The project's design tokens: colors, radii, spacing, typography, shadows | kind (optional) |
vixentio_routes_for_file | The routes affected by a file | path |
vixentio_capture_regions | The task's capture regions and their source locations | capture (optional) |
permission | Answers Claude Code's permission prompts; not for direct use | tool_name, input |
Publishing adds vixentio_git_status, vixentio_git_commit, vixentio_git_push, vixentio_pr_create, vixentio_pr_view, vixentio_pr_merge (merge, squash or rebase) and vixentio_git_revert. Every tool schema rejects unknown properties.
Permissions and safety
| Action | Always Ask | Auto | Bypass Permissions |
|---|---|---|---|
| Edits inside the project | Ask each time | Allow | Allow |
| Read-only shell commands | Ask | Allow | Allow |
| Safe project scripts (test, lint, typecheck, build) | Ask each time | Allow | Allow |
| Other shell writes | Ask | Ask | Allow |
| Installs and other commands | Ask | Ask | Allow inside the sandbox, otherwise deny |
| Sensitive files, commands that can't be parsed | Ask | Ask | Deny |
When VIXENTIO asks, you can allow once, always allow in this project, or deny. In every mode, these are refused:
- git and
ghwrites through the shell; publishing goes through the publish tools - recursive or wildcard deletion, such as
rm -randfind -delete - destructive database commands, such as
DROP,TRUNCATE,prisma migrate resetandsupabase db reset sudo,su,dd,launchctl,defaults write,security,osascript,chmod -R, and writes to~/.sshor~/.claude- piping remote code into a shell,
npm publish,vercel --prodandterraform apply - paths outside the project, inside
.git, or reached through links, and overwriting files you edited during the task
Sandbox. On by default, through sandbox-exec. Writes are allowed only to the project, the temporary folder, caches and ~/.claude; never to .git or your Claude settings. Reads of .env*, private keys and certificates, ~/.ssh, ~/.aws, ~/.gnupg, ~/.config/gh, ~/.netrc and ~/.git-credentials are blocked.
Visual review
After a task, VIXENTIO renders the affected routes at your project's breakpoints, or at 375, 768, 1280 and 1440 pixels (900 pixels tall, 812 below 768), and runs your project's test, lint, typecheck and build scripts as checks. You then:
- Accept the change; its snapshot is kept for 7 days.
- Refine it with a follow-up instruction in the same session.
- Undo it: a file-by-file revert of that task's patch only. VIXENTIO never runs
git reset,checkout,restoreorstash.
GitHub publishing
Accepted changes are committed on their own branch, built with a temporary index so your HEAD, index and working tree never move.
| Step | Command | Always Ask | Auto | Bypass |
|---|---|---|---|---|
| Status, view pull request | gh pr view | Allow | Allow | Allow |
| Commit, push branch, open pull request, revert | git push --porcelain origin refs/heads/<branch>:refs/heads/<branch>, gh pr create | Ask | Allow | Allow |
| Push to the default branch, merge | gh pr merge <n> --<method> --match-head-commit <sha> | Ask | Ask | Allow |
- Branches are named
vixentio/<instruction slug>-<task id>. - Pushes never use
--force,--deleteor-u; merges never use--admin,--delete-branchor--auto. - The pull request body lists the summary, changed files, tests and commands, visual validation, before and after, and notes.
- VIXENTIO uses your git credential helper and GitHub CLI sign-in, and never reads or stores tokens.
Project memory
Memory entries carry decisions your agent should follow: a scope (you, the workspace or the project), a category (architecture, design, coding, decision, workflow or domain), text up to 1,000 characters, a rationale, and the paths, components or routes they apply to. Export and import them as JSON:
{
"format": "peeknote.memory",
"version": 1,
"origin": "project",
"exportedAt": "2026-10-13T09:00:00Z",
"entries": []
}
Exports hold up to 2,000 entries (1 MB). The format name predates VIXENTIO and stays the same so that older exports keep importing. Design memory is derived from your project's index and stays on your Mac. Team memory is shared explicitly by an owner, and changes go through proposals that approvers decide.
Local bridge
The bridge connects the dev server, the browser runtime and VS Code to the app on the same Mac.
- Socket:
~/Library/Application Support/Vixentio/Local/Bridge/bridge-vixentio.sock(folder 0700, socket 0600), discovered throughbridge-vixentio.jsonin the same folder. - Runtime: a WebSocket at
ws://127.0.0.1:<port>/runtime. TheHostmust be exactly127.0.0.1:<port>and theOrigina loopback origin (localhost,127.0.0.1,[::1],*.localhost) or one you approved. The first message must beruntime.hellowith a valid ticket. - Tickets:
runtime.registerreturns a 256-bit runtime token that ends when the plugin disconnects or re-registers, or after 12 hours. - Pairing: VS Code pairs with a six-digit code shown in the app; three wrong codes or two minutes end the attempt. The credential is 256 random bits in VS Code's secret storage, VIXENTIO keeps only its SHA-256, and sessions expire after 24 hours.
- Limits: 20 messages a second, 5 runtime sessions per project, 64 connections, 256 KB per runtime message and 1 MB per socket message.
Every message uses one envelope:
{ "v": 1, "id": "7f3c…", "kind": "request", "op": "runtime.register", "payload": { "root": "/Users/you/harbor-web", "framework": "vite", "bundler": "vite", "pluginVersion": "0.1.0" } }
| Client | Operations |
|---|---|
| Handshake | hello, pair.request, pair.confirm |
| Dev server | runtime.register, runtime.unregister, devserver.status |
| Browser runtime | runtime.selection, runtime.open, runtime.console, runtime.network, runtime.hmr, runtime.located, runtime.workbench, runtime.page |
| VS Code | project.list, project.connect, open.file, open.component, inspect.request, send.selection, send.error, open.review, memory.show, task.open, workbench.open |
Errors are one of bad_request, unauthorized, not_paired, expired, forbidden_op, wrong_project, not_registered, too_large, rate_limited, unsupported_version, unavailable and internal. The protocol is version 1; fields are only added within a version, and a previous version stays supported for at least one release after a new one. The JSON Schema is https://vixentio.ai/schemas/bridge/v1.json.
Runtime API
In development builds, each host element carries its source as data-pn-src="<path>:<line>:<column>" (1-based, UTF-16 columns). The runtime exposes a small, versioned API for tools and tests:
window.__VIXENTIO__ // { version: 1, snapshot(), locate(), locateRange(), highlight(), hmrStatus() }
window.__VIXENTIO_WORKBENCH__ // { version: 1, status(), render(), bounds(), targets() }
snapshot() returns geometry, names and hashes only: no text content, form values, cookies or storage.
VS Code extension
The extension talks to VIXENTIO over the local socket and never over the network, and it never runs anything itself. It requires VS Code 1.95 or later.
| Command | What it does |
|---|---|
vixentio.connectProject | Pair with the app and connect the open folder |
vixentio.openCurrentFile | Open the current file in VIXENTIO |
vixentio.openCurrentComponent | Open the component under the cursor |
vixentio.inspectRunningComponent | Highlight the component in the running app |
vixentio.openInWorkbench | Render the component on its own |
vixentio.sendSelection | Send the selected code as context |
vixentio.sendError | Send an error with its location |
vixentio.openVisualReview | Open the current task's visual review |
vixentio.showProjectMemory | Show the project's memory |
vixentio.openCurrentTask | Open the current agent task |
Set vixentio.instance to development to work with a development build of the app.
AI service
AI features call VIXENTIO's AI service, which picks the model: Claude Haiku 5.5 for questions, Sonnet 5.5 for actions and Opus 5.5 for deep work. Each account can make 12 requests a minute and 3 at once, and up to 400 requests, 2 million tokens and 150 images a day. Before a request leaves the Mac, and again on the server, high-confidence secrets are replaced with [REDACTED <kind>]: private keys, Anthropic, OpenAI, Stripe, Supabase, GitHub, AWS, Google, Slack and npm keys, JWTs and bearer tokens. The service stores usage records, never prompts, answers, images or code.
Requirements
| Component | Requirement |
|---|---|
| Mac app | macOS 14 Sonoma or later, Apple silicon or Intel |
| Vite projects | React 18 or 19, Vite 6 or later |
| Next.js projects | Next.js 15.3 or later, App Router, Turbopack or webpack |
| Agent tasks | Claude Code installed and signed in to your account |
| Pull requests | Git and the GitHub CLI, signed in |
| Editor | VS Code 1.95 or later, optional |