Pinta Documentation
Pinta is a Chrome extension and companion server that hands visual UI annotations to a coding agent — Claude Code, Cursor, Aider, or any MCP-compatible tool — which edits your source files. This guide covers the mental model, every module, the multi-agent workflow, and a troubleshooting reference.
What is Pinta
Pinta closes the loop between "I see what's wrong on this page" and "the agent edits the right file." You annotate the running app — pick an element, draw on a screenshot, drop a pin, type a comment — and hit Submit. The agent reads your annotation, finds the source file, makes the change, and reports back. No screenshots pasted into chat, no manually grepping for selectors, no copy-paste round trips.
Three pieces work together:
| Component | Role |
|---|---|
| Extension | Chrome side panel + on-page overlay. Where you draw and submit. |
| Companion | Node server on 127.0.0.1:7878+. Receives your submission, persists the session. |
| Agent | Claude Code (or compatible) running the /pinta skill. Reads the session, edits source files. |
The mental model
Pinta is opinionated about the verbs you use to talk to your codebase. Today there are three:
- Act — Annotate, optionally with GitLab Issues. You're asking the agent to do something to your source. This is the original Pinta loop.
- Test — Test Pilot. You're driving an interactive QA spec with the agent's help.
- Inquire — Chat. You're asking before you commit — explanations, what-if questions, "what does this do?"
- Audit — AuditFlow. You're asking the agent to look across the project and surface findings, then route the ones you care about back into Act.
Each verb is a Pinta module. Enable the ones you want in Settings; ignore the rest. The extension's UI is just the surface; the wire protocol and agent skill stay narrow.
Install & first run
1. Install the Chrome extension
Get it from the Chrome Web Store (search for "Pinta"), or load it unpacked from the GitHub repo if you want the unreleased build.
2. Start the companion in your project
npx pinta-companion .
# Or, if you cloned the repo for Pinta dev:
node ~/.claude/skills/pinta/start-companion.js .
The companion binds the first free port in 7878-7898 and
registers itself in ~/.pinta/registry.json so the
extension + agent skill can find it.
3. Install the /pinta skill
The /pinta slash command is a Claude Code skill — it is
not installed by npx pinta-companion.
Install it once (no clone needed), then fully restart Claude
Code (skills load at startup; /clear is not
enough):
npx pinta-companion@0.6.0 install-skill
The @0.5.0 is deliberate — npx may have an
older pinta-companion cached, and the
install-skill subcommand only exists in 0.5.0+. Prefer a
plugin? /plugin marketplace add kevzlou7979/pinta then
/plugin install pinta@pinta (invoked as
/pinta:pinta, auto-updates).
4. Run /pinta in Claude Code
Open a Claude Code terminal in your project root and type
/pinta. The skill discovers the companion via the
registry, opens a long-lived SSE stream, and waits for sessions.
It will say something like:
"Companion is up on port 7878 for /path/to/your/project.
Open the Pinta Chrome extension, annotate the page you want
changed, and hit Submit. I'll wait."
5. Open the side panel
Click the Pinta icon in your Chrome toolbar (or pin it first). The side panel opens on the right; the project picker at the top should say Connected · your-project.
Your first annotation
- Open the page you want to change in any tab.
- In the side panel, click Select (the cursor icon) and click any element on the page. A pink halo appears; the element gets a pin badge.
- Type a comment in the popup: "make this button match the brand color".
- Hit Submit in the panel.
- Your
/pintaterminal lights up: the agent reads the annotation, finds the source file, shows you the plan, and waits for confirmation. - Reply "go" (or just confirm) and the edit happens. Refresh the page to see it — or rely on HMR / auto-reload if your dev server supports it.
Annotate always on
The core verb. Three annotation shapes:
- Select — pick a DOM element. The agent gets the selector, outer HTML, computed styles, and surrounding text.
- Draw — arrow, rectangle, circle, freehand, pin. No DOM target — the agent reads the composited screenshot.
- Image — drop a reference image at a specific spot. The agent sees both the screenshot and your reference.
Inline editor
On select mode, the popup has tabs for Content
(edit text in place), Font / Sizing / Spacing
(CSS pickers populated from getComputedStyle), and
CSS (free-form). Edits apply to the DOM live so
you see the result before submitting. The diff is captured and
shipped to the agent verbatim.
Hotkeys
On the page (the overlay ignores INPUT / TEXTAREA / contenteditable so typing into your app never triggers these):
Alt+S— toggle Select modeAlt+P— toggle Draw mode (Pen)Alt+X— exit to idleEsc— cancel an in-progress annotation or exit the active mode
Inline element editor + comment popover:
Ctrl/Cmd+Enter— submit comment / save editEsc— cancel and close
Chat input (Test Pilot per-row, global, Just Ask):
Enter— send messageAlt+Enter(orShift+Enter) — new line
Settings → Keyboard shortcuts lists the same set inside the side panel for quick reference.
GitLab Issues module
Tick Create GitLab issues in the submit footer and
the agent files one issue per annotation after the source edits land.
Auth is delegated to your glab CLI (run
glab auth login --scopes api,write_repository once);
Pinta never sees the token.
Each issue carries the annotation's selector, source-file pointer,
page URL, the full-page screenshot (uploaded to your project's
uploads endpoint), and a footer linking back to the
Pinta session. Before filing, the agent prompts in chat for batch
metadata (domain label, extra tags, assignees, or later
to defer entirely).
Test Pilot module
Interactive UAT module in its own side-panel tab. Two ways to start:
- Import a hand-written markdown test spec.
- Generate a UAT spec from project context — the agent scans your routes / components / auth flow and writes one.
Either way you get a catalog — sections of test rows. Mark each row Pass, Fail, or leave it untested. Click the ? on any row to ask the agent for step-by-step instructions (toggle Detailed help steps in Settings for deeper technical context).
Editing the catalog (Phase 13)
Right-click the kebab on any section or row for delete / add /
rename / move-up / move-down / "add test below". Drag-and-drop
also works — grab a row's grip handle on the leading edge. Edits
sync to .pinta/test-docs/{docId}.md on disk so the
agent's ? flow works against rows you added
yourself.
Auto-save status to disk
Pass / Fail marks land in a Result column in the on-disk markdown — so if browser storage gets wiped, re-importing the same spec restores your marks. Catalog structure is the source of truth.
Chat module
Inquiry-mode module — one Settings toggle lights up three chat surfaces:
- Global chat — speech-bubble icon in the side-panel header. Ask Pinta-shaped questions ("how do I disable screenshot opt-in?"). Supports pasting images.
- Annotate "Just Ask" — checkbox in the submit footer. When ticked, Submit re-labels to "Ask agent" — the agent answers without editing source. Pivot to a real submit by unticking.
- Test Pilot per-row chat — chat button on each test row. Context auto-attaches (test ID, expected result, current steps).
Replies render with light markdown (inline code, fenced
blocks with syntax highlighting, > Note: callouts).
The Test Pilot tier has a special affordance: when the agent
suggests test scenarios in its reply, a one-click
Add N to spec button appears below the bubble —
adds the suggestions to the current section (or creates a new
section).
Detailed responses toggle
Settings → Chat → Detailed responses. Off (default) = short, tester-friendly. On = deeper technical detail (curl, payloads, env vars, ARIA names). Affects all three chat surfaces.
AuditFlow module 15a + 15b
Lighthouse-style audit surface in its own side-panel tab. Pick categories, run audit, get back per-category scores with actionable findings.
Categories (Phase 15b)
- Security — XSS, CSRF,
eval/{@html}misuse, secret leakage in source, CSRF guards on destructive endpoints,npm auditfor dependency CVEs. - Performance — bundle entry count, production deps count, heavy known offenders (lodash full, moment), sync fetches in render, missing lazy routes, build target sanity, missing
loading="lazy". - Accessibility — alt text, labeled inputs, ARIA misuse, heading hierarchy, click handlers on non-interactive elements, focus-visible, missing
lang. - Mobile — viewport meta, fixed-px containers, touch-target sizing, hover-only interactions, horizontal-overflow risks, mouse-only drag listeners.
- Cross-Browser soon — caniuse-resolved support matrix per finding.
Fix with agent
Every finding has a Fix with agent button that composes a Pinta annotation pre-filled with the check details and switches you to the Annotate tab for review. The audit becomes a source of work; the existing Annotate loop is the sink.
Scoring
Deterministic:
(pass × 1 + warn × 0.5 + fail × 0) / (pass + warn + fail) × 100.
Info checks excluded from the denominator. Rating: 90+ Excellent,
70+ Good, 50+ Needs work, else Poor.
Role flags (Phase 18a) multi-terminal
Run multiple /pinta Claude Code terminals against the
same project and dedicate each to a workload. Each terminal declares
which session kinds it claims; mismatches silently skip to other
terminals.
| Flag | Claims sessions where… |
|---|---|
--annotate | modules[] does NOT contain test-pilot, audit-flow, or chat |
--test-pilot | modules[].id contains test-pilot |
--audit | modules[].id contains audit-flow |
--chat | modules[].id contains chat |
| (no flag) | Claim everything — default, current behavior |
Flags stack: /pinta --test-pilot --audit claims both
kinds. Typical 4-terminal setup:
Terminal 1: /pinta --annotate # source-edit work
Terminal 2: /pinta --test-pilot # UAT runs + per-row chat
Terminal 3: /pinta --audit # audit runs, low traffic
Terminal 4: /pinta --chat # Just-Ask + global chat
/pinta terminal is claiming annotation
sessions. Run /pinta in your project's Claude Code
terminal (or /pinta --annotate)."
Multi-project setup
One companion runs per project. The extension's project picker (top
of side panel) shows every running companion. When you switch tabs,
Pinta auto-routes to the companion whose URL patterns match —
annotations made on localhost:5173 go to one project,
annotations on localhost:3000 go to another, all without
you re-picking.
Add URL patterns by clicking the project name in the picker, or by
editing .pinta.json in your project root:
{
"urlPatterns": [
"http://localhost:5173/**",
"https://staging.example.com/**"
]
}
Settings
Click the gear icon in the side-panel header. Modules are listed; tick to enable. Each enabled module exposes its own settings:
- GitLab Issues — optional
project_idoverride + default labels. - Test Pilot — Detailed help steps (default off).
- Chat — Detailed responses (default off) + Redact PII (default on — strips emails / phones / IDs from page content sent to the agent).
- AuditFlow — no settings in 15a/b; browser-target picker arrives with Cross-Browser.
Visual feedback
Settings → Visual feedback → Processing pulse enables a pulsing colored glow around the page edges while the agent is applying changes. Off by default; cosmetic only.
Standalone mode
Pinta works without a companion. Useful for testers hitting deployed URLs who don't have the project on disk: the side panel falls into Standalone mode, sessions live in browser IndexedDB, and you can Copy (markdown to clipboard) or Download instead of Submit.
Standalone is also useful for trying Pinta before you've installed
the companion — the annotation UX works fully; only the
agent-edit loop is gated on having a companion + /pinta
running.
Share files (.pinta)
Click the download icon in the panel header to export a session as a .pinta file: a self-contained JSON document with the annotations, screenshots inline, and your manifest (title, author, accent color, description). Send it to a teammate; they open Pinta and pick Import .pinta.
Imported sessions are read-only in the viewer. Two follow-up paths:
- Send to agent (connected mode) — files the imported annotations as a brand-new submission against your project. Agent picks up like any other.
- Fork to local (standalone mode) — clones into an editable draft you can extend.
Module settings (e.g. GitLab tokens) are stripped from share files. Each recipient uses their own configured modules.
Troubleshooting
Side panel says "No companion is running"
Start the companion in your project root:
npx pinta-companion .
If it complains about another companion already on the port,
check ~/.pinta/registry.json — stale entries from
crashed companions can linger.
Companion is running but the agent doesn't pick up sessions
Most likely: /pinta isn't running in a Claude Code
terminal for this project. Start one. If you're using role flags,
make sure at least one terminal covers the kind you're submitting
(see Role flags for the matrix).
Agent edited the wrong file
Pinta uses a 3-tier locate strategy: data-source-file
attributes (Phase 6 Vite plugin), then a project-wide grep for
nearby text, then a route-scoped fallback. The Vite plugin gives
the highest accuracy (~95%); without it, you're at grep-accuracy
(~80%). If you keep hitting wrong files, install the plugin or
give the agent more nearby text by typing a verbose comment.
Auto-apply edited a file but I wanted to discuss first
Auto-apply is off by default. If it's on and you want a discussion instead, untick it AND tick Just Ask — the submit button re-labels to "Ask agent" and routes to the chat sheet instead of editing source.
GitLab Issues filed but no screenshot embedded
Your glab token likely lacks api /
write_repository scope. Re-auth:
glab auth logout
glab auth login --scopes api,write_repository
Chat says "Agent returned an empty response"
Usually means the agent had no answer for an image-context prompt
and submitted blank. Try rephrasing with more context (paste a
screenshot into the chat, mention the file path), or restart
/pinta if the agent seems stuck.
Sessions sitting in "Submitted" forever
After 10 seconds, the side panel surfaces a claim-warning telling
you what's likely wrong (no /pinta running, or no
terminal accepting the session's kind under your role flags).
Most fixes: start a /pinta, or unblock a stuck agent
terminal.
Privacy
Pinta sends annotation contents (selectors, comments, optional
screenshots) to the agent you've configured — the
same Claude Code / Cursor / etc. you'd use anyway. Pinta itself
doesn't host servers, store sessions remotely, or send telemetry.
The companion binds 127.0.0.1 only.
See the full Privacy Policy for the per-field breakdown.
What's next
See the Roadmap on the landing page for what's planned. Quick highlights:
- Phase 15c — user-defined custom audits (paste docs → agent generates rules)
- Phase 16 — Test Pilot sign-off (tester exports MD with Pass/Fail; dev imports + reviews)
- Phase 17 — Claude Design (ambient design-system module)
- Phase 18b — companion-enforced role routing (currently trust-model)