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:

ComponentRole
ExtensionChrome side panel + on-page overlay. Where you draw and submit.
CompanionNode server on 127.0.0.1:7878+. Receives your submission, persists the session.
AgentClaude 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:

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.

Why does this matter? Every module reuses the same session lifecycle — discover companion, claim, edit / answer, done. Once you understand one, you understand them all. The differences live in the agent's instructions per module, not in new infrastructure.

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

  1. Open the page you want to change in any tab.
  2. 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.
  3. Type a comment in the popup: "make this button match the brand color".
  4. Hit Submit in the panel.
  5. Your /pinta terminal lights up: the agent reads the annotation, finds the source file, shows you the plan, and waits for confirmation.
  6. 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.
Tip: If you tick Auto-apply (no agent confirmation) in the submit footer, the agent skips the wait-for-go step and applies directly. The plan is still shown briefly so you can see what's happening.

Annotate always on

The core verb. Three annotation shapes:

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):

Inline element editor + comment popover:

Chat input (Test Pilot per-row, global, Just Ask):

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).

If you only tick GitLab Issues without Auto-apply (file-only mode): no source edits happen. The agent just files the tickets. Useful when you want a backlog item but don't want code touched yet.

Test Pilot module

Interactive UAT module in its own side-panel tab. Two ways to start:

  1. Import a hand-written markdown test spec.
  2. 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:

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)

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.

FlagClaims sessions where…
--annotatemodules[] does NOT contain test-pilot, audit-flow, or chat
--test-pilotmodules[].id contains test-pilot
--auditmodules[].id contains audit-flow
--chatmodules[].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
Coverage matters. At least one terminal in the project must accept each kind in use. If you start all 4 specialized terminals but submit a regular annotation, the session sits unclaimed — the side panel will warn you after 10s: "No /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:

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:

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: