# PinAppAI: full documentation
> The change-request layer for AI-built sites. Reviewers drop a pin on any element of a live site and say what should change in text or voice; the AI dev agent (Claude Code, Codex, Cursor, or a custom pipeline) receives a structured, locator-precise change request instead of a Slack screenshot.
This file inlines every PinAppAI documentation page in one place for LLM ingestion. For the curated link map, see https://pinappai.com/llms.txt. The human docs live at https://pinappai.com/docs/.
## What PinAppAI is
AI builds your site: static, fast, deployed in seconds. PinAppAI is the layer on top for *changing* it. A reviewer points at what should change on the live page; the AI dev agent receives a precise, actionable change request. No more screenshots pasted into chat with "make this bit bigger".
## Four ways to capture intent
- **Free-form pins**: drop a pin anywhere on the page and describe the change.
- **Element pins**: pick a specific element; the change request carries a precise locator to it.
- **Screenshot pins**: capture a region of the page as an image attached to the request.
- **Text-selection pins**: select copy and request an edit to exactly that text.
Each supports **voice dictation** in five languages, persists across page reloads, and outputs to Claude Code, Codex, Cursor, or your own pipeline.
## The review loop
Change requests collect into an **Inbox**. The AI agent drains it with a single apply command, turning each request into an edit. An optional **AI-diff review page** (the /changes/ workflow) lets reviewers approve, reject, or rewrite each change individually, on the review page or on the actual page where it lives. Every surface (widget, review page, editor) shares the same short **#N** identity for each change request.
## Four ways for reviewers to reach a site
- **Review link**: share one URL; reviewers annotate the live site with zero setup, through review.pinappai.com. No embed, no account gymnastics.
- **Site-wide widget**: embed a single script tag so any page of your own site carries the review tools.
- **Reviewer Chrome extension**: reviewers review the real site in their own logged-in tab, including pages behind logins, in-app flows, and strict security policies. Sign in once.
- **Native macOS desktop app**: pick a project and the app opens that project's site, with pinning, screenshot capture and dictation built in. Nothing is embedded on the site, and the site can be a local dev server.
## What a pin looks like once work starts on it
A pin is not just red or green. Its state is decided on the server and shared by all four surfaces, so they cannot disagree about the same change.
- **Open**: still needs work.
- **Applied here**: solid green, shown only on the build that actually contains the change. On a build without it, the same pin stays neutral rather than claiming a fix that is not there.
- **Applied elsewhere**: hollow green. The change landed, just not on the page being looked at.
- **Settled**: muted, for a change that has been decided but is still part of the round.
- **Retired**: gone. Once a finished change request drops out of the current round, its pin stops rendering entirely, so a project on its tenth round does not carry the first round's markers.
## MCP-first
PinAppAI is driven over the Model Context Protocol. An AI agent installs the MCP server in two commands and runs the entire loop (setup, apply, generate the review page, uninstall) without leaving the editor. Every non-MCP step also has an admin-UI + copy-paste fallback.
## Pricing (summary)
- **Free**: $0 forever. 1 workspace, 3 projects, unlimited pins and sign-off decisions, 50 screenshot pins/month, 14-day pin history, unlimited invited reviewers.
- **Pro**: $9/month ($7 annual). Unlimited projects, unlimited screenshot pins, forever pin history, no PinAppAI branding.
- **Team**: $15/seat/month ($12 annual). Multi-seat with viewer / editor / admin roles, custom AI prompt template per workspace.
Full pricing: https://pinappai.com/pricing/
## Security & data (summary)
EU data residency, two-factor authentication on every plan, and export-and-delete of your data with a 7-day undo window. Details: https://pinappai.com/security/
---
# Getting started
> Sign up, connect your AI agent over MCP, and let one workflow, setup-project, take you from zero to collecting structured feedback in about 5 minutes.
Source: https://pinappai.com/docs/getting-started/
PinAppAI is the change-request layer for AI-built sites. AI builds the page; reviewers point at what should change; your AI dev agent gets a structured, locator-precise change request, not a Slack screenshot. This page walks you through the first session end-to-end.
PinAppAI is **MCP-first**: the fastest path through every step below is a PinAppAI **workflow**, run inside Claude Code, Codex, Cursor, Continue, or any MCP-aware agent. Each step also has a no-MCP alternative (admin UI + copy-paste prompts). Those are the fallback, not the main road.
## 1. Create an account
Sign up at [app.pinappai.com](https://app.pinappai.com). The free tier covers 3 projects with unlimited reviewers, enough to evaluate the full flow.
### The dashboard walks you through the rest
After sign-up, your dashboard shows a **setup checklist**: create a project, open your site to reviewers, connect your coding agent, watch the first change request land, run your first apply. You don't tick anything off yourself; each step completes on its own when the product sees it happen (your project exists, your review link was opened, a pin arrived). Finish the last step and the card retires for good.
The checklist mirrors this guide: its five steps are sections 2 to 5 below. Follow either; they meet at the same place.
## 2. Connect your AI agent and run setup
Two commands work for any AI client (Claude Code, Codex CLI, Cursor, Claude Desktop, Continue):
```sh
npx @pinappai/mcp install # registers the MCP entry in every detected AI client config
npx @pinappai/mcp login # opens browser for sign-in, mints a per-machine key, saves it locally
```
Restart your AI client, then run the **setup-project** workflow. How you invoke it depends on your client:
| Your client | Run it |
|---|---|
| **Claude Code** | Type `/pinappai:setup-project` |
| **Codex** | Ask: *"run the pinappai setup-project workflow"* |
| **Continue** (agent mode) | Type `/setup-project` |
| **Cursor** | Type `/` and pick it from the menu |
| **Claude Desktop** | **+** menu, then pinappai, then setup-project |
| **Anything else** | Ask in plain language, the same as Codex |
Every workflow below is invoked the same way: swap the name. The full table lives in [Run a workflow](/docs/mcp/#run-a-workflow); examples from here on use Claude Code's syntax.
That one workflow walks the whole setup: creates the workspace + project, sets allowed origins, embeds the widget snippet in the most idiomatic place for your framework (Astro, Next.js, SvelteKit, Eleventy, Hugo, WordPress, plain HTML), offers the zero-install [review link](/docs/review-link/), invites your reviewers, and bootstraps the `.pinappai/` directory that makes later rounds iteration-aware. Nothing is ever committed without your explicit say-so: every run ends with an a/b/c/d landing chooser.
> **CI / headless?** Skip `login` and set `PINAPPAI_API_KEY=ppk_…` in the environment that spawns the MCP. Mint the key at [app.pinappai.com/api-keys](https://app.pinappai.com/api-keys). Name it after the machine so you can revoke cleanly.
### No MCP? The manual path
In the admin, click **+ New project** and enter a **slug** (URL identity, e.g. `acme-marketing`), a **name**, and your **allowed origins** (start with `http://localhost:3000`, add staging / production later). Then click **Add to your site → Show snippet, embed & remove prompts** and copy the one-line `
```
Prefer an AI to place it but don't want the MCP? Click **Copy embed prompt for AI** in the same modal and paste it into any agent with repo access.
Either way: reload your dev server, open any page, and you should see three floating buttons in the bottom-right corner. That's the widget.
## 3. Decide who can leave feedback
By default, only **invited reviewers** + workspace members can submit. The widget shows an email-OTP modal on the first comment; the email must be on the allowlist. The `setup-project` workflow asks for reviewer emails during the walkthrough; you can always add more later.
Two options:
- **Add reviewers explicitly:** Projects → **Reviewers** on the project's row → **Add reviewer** → enter email. Repeat for each invitee.
- **Flip Open access ON:** Projects → **Settings** on the project's row → tick **Open access**. Anyone who can reach the page can verify and submit. Recommended for public beta tests, off for production.
If you set a **Site origin**, reviewers don't even need the widget on your site: they annotate through `review.pinappai.com/p//` with zero setup ([how the review link works](/docs/review-link/)). Reviewers who prefer their own logged-in tab can use the [reviewer Chrome extension](/docs/extension/) instead; same pins, same stream.
Test it yourself: open your dev page, click a floating button, type your own email, paste the 6-digit code from your inbox, leave a comment. The pin should appear in your admin dashboard within a few seconds.
## 4. Run an AI-diff review
After a content rewrite or redesign, you don't want reviewers skimming a 4,000-word diff. You want them to decide on every change individually.
Run:
```
/pinappai:generate-changes-page
```
The agent reads your recent commits, summarizes meaningful changes, writes a single self-contained `/changes/` HTML file at the right path for your framework, and registers its items with the API. You only need this for the first page (or a standalone rewrite review). From then on, **the `apply` workflow refreshes `/changes/` automatically** after every round.
*No-MCP fallback:* open the **Add to your site** modal and click **Copy AI diff prompt**, or copy the ready prompt from the dashboard's InReview tab (**Copy /changes/ prompt**), and paste it into your agent.
Commit, deploy, and visit `/changes/`. You'll see Before / After cards for every change with **✓ Approve / ✗ Reject / ↻ Request change** buttons, plus a running decision tally bottom-right:
Reviewers can also visit any source page (`/pricing/`, `/features/...`) and see a chip bottom-right offering to review changes that target that page in context, each applied change highlighted in place with its numbered pin:
Clicking the chip opens the on-page review panel: it frames each change on the page and walks through them one by one, with the same verdict buttons and the pin's original comment a click away:
The full walkthrough, including cross-page navigation, deep links, and how decisions feed back into the next AI iteration, is in [AI-diff review (the /changes/ workflow)](/docs/changes-review/).
## 5. Close the loop with Apply
From here the rhythm is simple: reviewers pin change requests on the live site, each one lands in your dashboard **Inbox** as a numbered CR (#41, #42, …), and one command drains it:
```
/pinappai:apply
```
The agent edits your source (new applies, reverts for rejections, rewrites for change requests), regenerates `/changes/`, and records the round: every applied CR moves to **InReview** for verdicts. Same command, every round. The full state model is in [the iteration loop](/docs/iteration-loop/), and the other workflows (`analyze`, `summarize`, `audit-review`, `auth-help`, `reset-project`) are in the [MCP reference](/docs/mcp/).
## 6. Prefer the desktop client?
If you want reviewers to leave feedback without keeping a browser tab open (useful for designers reviewing a deployed site over hours, or for PMs who want a Notion-like dock for review), install the [native reviewer client](/download/) for macOS. Same API, same projects, same comments; just outside the browser.
## What to do next
- [Site-wide feedback widget](/docs/widget/): what reviewers see on every page (FABs, voice dictation, screenshot capture).
- [AI-diff review (the /changes/ workflow)](/docs/changes-review/): the headline flow for structured per-item review.
- [Reviewer access & permissions](/docs/reviewers/): open access, allowlist, two-stage Remove, what 403 errors mean.
- [MCP server for AI agents](/docs/mcp/): the full 10-workflow / 38-tool reference, and how to run a workflow in your client.
When you're ready to ship to production, two paths to clean removal:
- **MCP-native:** run the `remove` workflow in your AI client.
- **No-MCP fallback:** open the **Add to your site** modal once more and click **Copy remove prompt for AI**.
Either path strips the widget script, deletes `/changes/`, and verifies with four `git grep` commands before commit. Both **preserve `.pinappai/`** so re-installing later drops you back into the same baseline.
---
# The review link (no-install reviews)
> Share one URL and reviewers annotate your live site with zero setup. The review tools load automatically, no widget embed, no account gymnastics.
Source: https://pinappai.com/docs/review-link/
The fastest way to get feedback: **share a link**. `review.pinappai.com/p//` serves your live site with the PinAppAI review tools pre-loaded. Reviewers pin, comment, and verdict without your site embedding anything and without installing anything themselves.
## Enable it
Set **Site origin (review link)** in your project's Settings (or accept the offer your AI agent makes during the `setup-project` workflow). That's it:
```
https://review.pinappai.com/p//
```
Reviewers browse your site through that URL exactly as it is in production. Navigation stays on the review link; every pin and decision records against your **real** page URLs, so nothing forks from the widget-embedded experience.
The reviewer invitation email includes this link ready to click when it's configured.
## Reviewing a page
Every page served through the review link carries the same review tools in the bottom-right: **pin an element**, leave a **comment**, or grab a **screenshot**. Reviewers work directly on your live site as it looks on their screen: no desktop app, no browser extension, nothing embedded on your end.
To raise a change: pick the element, optionally suggest the exact rewrite, add a note, and **Submit**. It lands on your change-request stream with the element locator, the real page URL, and who asked.
## The preview variant
Review rounds usually live on a branch deploy before they reach production. Add a **Preview origin** in Settings (your AI agent offers to wire the deploy URL after each apply run) and the same link gains a preview twin:
```
https://review.pinappai.com/p/~preview/
```
Decisions made there still record against your canonical URLs. A verdict is a verdict, regardless of which deploy it was judged on.
PinAppAI routes reviewers to the right surface automatically:
- Review entries (the chip, green pins, dashboard links, `/changes/` icons) open on the **preview** when that's where the applied round lives.
- If a page exists on one deploy but not the other, the 404 carries a one-click banner to the deploy that has it.
## Review as a device
The desktop view above is the default, but reviewers aren't limited to it. The same review link can also render your page as a **phone**, with its real mobile layout. Open the account menu (the initials chip under the review buttons) and turn on **Device view**:
The page reloads as the chosen device, with its real mobile layout. A slim control gutter sits beside it:
- **Pick a device** and **Rotate** between portrait and landscape; **Fit** scales the frame to your window.
- The same review actions (pin, comment, screenshot) work right there, and a screenshot captures just the device frame, not your whole screen.
Every pin and decision is tagged with the device it was made on, so "only broken on mobile" lands on the change request as a fact, not a guess.
## Security posture
- The proxy only ever fetches your project's **stored** origins: a URL can't be smuggled in.
- Reviewer identity works the same as everywhere else: email verification, allowlist by default ([reviewer docs](/docs/reviewers/)).
- Your site is served as-is; the review tools live in an isolated layer that can't collide with your CSS or scripts.
## When to use another surface
The [widget embed](/docs/widget/), the review link, and the [reviewer Chrome extension](/docs/extension/) produce identical data. Pick per project, or mix them. Embed when you want reviewers on your real domain (e.g. dogfooding in production); share the link for zero-touch onboarding, agency-style client reviews, or feedback on a site you can't modify; reach for the extension when the pages live behind a login or strict security policies.
---
# The reviewer Chrome extension
> Review the real site in your own tab: pages behind logins, in-app flows, and strict security policies included. Sign in once; no email codes on any page.
Source: https://pinappai.com/docs/extension/
The [review link](/docs/review-link/) covers most reviews with zero install. The **reviewer Chrome extension** exists for everything a link structurally can't reach: pages behind a login, in-app flows, client-side routed apps, sites with strict security policies. Install it once and every site you review gets the same PinAppAI tools, in your own logged-in tab.
## What it does
Open a site you've been invited to review, click the extension, and the familiar review tools appear: pins, comments, screenshots, verdicts. Everything records against the **real** page URLs, exactly like the widget embed and the review link. Your team and your AI agent see one change-request stream no matter which surface the feedback came from.
## Using it
1. **Sign in once.** The extension connects to your PinAppAI account with a browser approval: no password typed into a popup, and from then on no email codes on any page you review.
2. **Click the extension on the site.** When the site matches one of your projects, **Review this page** brings up the review tools right there.
3. **Optional: open automatically.** Tick **Open automatically on this site** and the tools load on every page of that site by themselves. The browser asks once for access to that site; you can turn it off any time.
**Turn off on this page** hides the tools for a site and is remembered. Reviewing is always your choice, per site.
## When to use which surface
- **Review link**: the zero-install default; send it to anyone.
- **Extension**: the same review in your own logged-in tab: behind logins, in-app flows, strict security policies.
- **Widget embed**: for your own team, always on, on your own domain.
All three produce identical change requests, so you can mix them freely per project.
## Privacy and permissions
The extension ships with **no standing site access**. It touches a page only when you click it, or on sites where you opted into automatic opening (one browser prompt, revocable). Your project list and per-site preferences stay in your browser. It collects no browsing data.
## Availability
Live on the Chrome Web Store: [install PinAppAI](https://chromewebstore.google.com/detail/kkcdekejgchiddinkkidfdfihadbolfc).
---
# Site-wide feedback widget
> Embed a single script tag and reviewers can pin a comment, pick an element, or capture a region from any page of your site.
Source: https://pinappai.com/docs/widget/
The PinAppAI widget is a one-line `
```
No MCP but still want an AI to place it? The admin UI has a **Copy embed prompt for AI** button. Paste the prompt into any AI coding agent with repo access.
## What reviewers see
Three floating action buttons render bottom-right:
- **🎯 Inspect**: pick a specific element on the page and comment on it. The widget records a precise CSS selector so the next AI iteration can find the exact element without grepping.
- **💬 Comment**: drop a free-form pin anywhere on the page. Useful for layout-level feedback that doesn't map to a single element.
- **📷 Screenshot**: drag-select a region of the page and attach the captured image to the comment. Useful for visual issues that text can't describe.
Each pin survives reload (stored on the PinAppAI server, scoped to the project) and shows up in your admin dashboard with the page URL, selector, screenshot, and reviewer name.
### Pins change as the work does
A pin is not simply red or green. Its state is decided on the server, so every surface a reviewer might use shows the same thing about the same change.
- **Still open**: the pin stays red.
- **Applied on this build**: solid green, and only here. Looking at a build that does not contain the change yet leaves the pin neutral instead of promising a fix that is not on the page.
- **Applied somewhere else**: hollow green, so "done, just not here" reads at a glance.
- **Decided**: muted, because a change someone has already ruled on should stop competing for attention.
- **Finished**: gone. Once a change request closes and drops out of the current round, its pin stops rendering. A project on its tenth round shows the tenth round's work, not ten rounds of markers stacked on one page.
An open pin never disappears on its own, however old it is. Only finished work retires.
## Voice dictation
Every comment input has a 🎙️ microphone button. Click and hold to dictate (uses the browser's built-in speech recognition, no extra API). The recognized text streams in live; release to stop. Language defaults to the browser's, but you can pin it via:
```html
```
`data-lang` sets the default; `data-langs` overrides the picker's options. The same can be done at runtime from your own JS:
```js
window.PinAppAI.setDictationLang('tr-TR');
window.PinAppAI.setDictationLangs(['en-US', 'tr-TR']);
```
## Permissions
The widget asks each reviewer to verify their email via a one-time 6-digit code before they can submit. That gates spam and ties every comment to a real address. Once verified, an initials chip joins the floating buttons. Open it to see who's signed in, and to **Sign out** (the session ends properly, not just in that browser tab).
Two modes for the project:
- **Allowlist** (default): only invited reviewers + workspace members can submit.
- **Open access**: anyone who can reach the page can verify and submit. Useful for public beta testing; recommended off for production.
Both flip from the project's **Settings** in the admin UI (Projects → Settings on the project's row). See [Reviewer access](/docs/reviewers/) for the full breakdown.
## What's NOT in the widget
The widget does not send analytics, track non-reviewer visitors, or alter your site's layout/styles. It mounts an isolated stack of elements with `pp-*`-prefixed class names and a high z-index, so host CSS doesn't conflict.
---
# The iteration loop
> How PinAppAI organizes review rounds: an Inbox of change requests, one Apply command that hands them to your AI agent, and per-item reviewer verdicts.
Source: https://pinappai.com/docs/iteration-loop/
PinAppAI's backbone is a simple loop: reviewers request changes, your AI agent applies them, reviewers verify the result. The dashboard has exactly three tabs (**Inbox**, **InReview**, **Closed**) and every change request (CR) is always in exactly one of them.
## The loop
```
reviewers pin change requests on the live site
│
▼
Inbox ← every new CR lands here (#N number assigned)
│
│ apply workflow: your AI agent edits source,
│ regenerates /changes/, registers the round
▼
InReview ← applied, awaiting verdicts
│
├── Approve → Closed (done)
├── Reject → back to Inbox (next Apply reverts the edit)
└── Request change → back to Inbox (next Apply applies the new wording)
```
That's the whole model. There is no separate triage ceremony: anything in the Inbox is Apply-eligible, and one `apply` run drains it.
## Inbox
New pins arrive as CRs with a per-project short number (**#41**, **#42**): the same number you'll see inside the pin marker on the page, on the `/changes/` review card, in commit messages, and on the dashboard row. One identity everywhere.
Inbox rows carry a substate badge so you can see *why* something is here: 🆕 new, ↩ rejected (needs a revert), 🔄 change requested (needs new wording), ⏸ deferred. **Defer** parks a CR you're not ready to act on. It's skipped by Apply until you undefer it.
## Apply
The **Apply** button (or running the `apply` workflow directly in Claude Code, Codex, Cursor, or any MCP-aware agent, see [Run a workflow](/docs/mcp/#run-a-workflow)) hands every non-deferred Inbox CR to your AI agent. The agent:
1. Edits your source files: new applies, reverts for rejected CRs, rewrites for change requests. It asks before doing anything it isn't sure about, and nothing is ever committed without your explicit say-so.
2. Regenerates the `/changes/` review page to match.
3. Records the round with PinAppAI, moving every applied CR to **InReview**.
Each Apply run is recorded as an *iteration*: the project's apply history, visible per CR ("From iter #3").
## InReview
Applied CRs wait here for verdicts. Reviewers decide from the live page (green pin / review panel) or from `/changes/`; admins can also decide from this tab. First action wins: whoever verdicts first owns the decision.
Owning it does not mean being stuck with it. That reviewer can revise their own verdict until the change request is applied again, so a misclicked Reject is a two-second fix rather than an admin ticket. Another reviewer cannot overwrite the decision, but their verdict is not thrown away either: it is recorded in the change request's history, so a disagreement stays visible instead of vanishing.
- **Approve** closes the CR.
- **Reject** or **Request change** sends it back to the Inbox with the matching substate, and the next Apply handles the revert or the new wording. Same CR, same #N. Nothing forks.
## Closed
Terminal CRs: ✓ done or ✗ wontfix. **Reopen** sends one back to the Inbox if it turns out the work isn't finished after all.
## Where the AI fits
Everything the dashboard does is also available to your AI agent through [the MCP server](/docs/mcp/): `apply` is the loop's engine, and companion workflows cover setup, `/changes/` generation, analysis, and project reset.
---
# AI-diff review (the /changes/ workflow)
> Generate a /changes/ page from your latest changes and let reviewers approve, reject, or rewrite each one, on the review page or the page where it lives.
Source: https://pinappai.com/docs/changes-review/
After a content rewrite, redesign, or major copy refresh, you want reviewers to decide on every change individually, not skim a giant diff. The PinAppAI **AI-diff review workflow** turns your work into a per-item review surface: a `/changes/` page with Before/After cards, plus in-page review on the very pages the changes live on.
## How it fits together
```
your AI agent applies changes (apply workflow)
│
├── edits source
├── writes/refreshes the /changes/ page
└── registers every item with PinAppAI
│
│ Reviewer visits /changes/ OR any source page
▼
• /changes/ → per-item Approve/Reject/Request-change cards + summary
• source page → review chip + decision panel + cross-page navigation
```
Registration happens automatically as part of the apply/generate run: there is nothing to warm up and the page itself never writes anything.
## 1. Generate /changes/
Most of the time you don't generate it by hand: **the `apply` workflow refreshes `/changes/` automatically** after every round. For a first-time page (or a standalone rewrite review), run the `generate-changes-page` workflow in your AI client ([how](/docs/mcp/#run-a-workflow)), or copy the ready prompt from the dashboard's InReview tab (**Copy /changes/ prompt**).
The generated page is a single self-contained file:
- One card per atomic change: reviewers decide each one independently
- Each card carries the CR's **#N** number, the same identity the dashboard and the on-page pin show
- BEFORE / AFTER text rows, byte-faithful to your source
- All CSS inlined; no site chrome: one file to deploy, one file to delete
> The AI generator never modifies your source files while generating. `/changes/` is the only artifact it writes.
## 2. Deploy + decide
Commit and deploy `/changes/` like any other page. Reviewers see a summary header, and per card:
- **✓ Approve**: accept the applied wording
- **✗ Reject**: the next Apply run reverts this change
- **↻ Request change**: type the wording you actually want; the next Apply applies it
Two small icons next to each card heading open the change *in context*: one on the site itself, one through the [no-install review link](/docs/review-link/). The latter works even on pages without the widget embedded.
Decisions persist on PinAppAI's servers, scoped to the reviewer's verified email.
## 3. Review on the actual page (in-page mode)
When a reviewer visits a source page that has pending changes, a chip appears bottom-right:
> **16** changes to review on this page
Click → a draggable panel opens with the changed text highlighted in place, BEFORE/AFTER rows, the verdict buttons, and ◀ ▶ navigation that walks every pending item, even across pages. Applied-but-undecided changes glow green on the page; deciding removes the glow.
If the round you're reviewing lives on a preview deploy (branch preview), review entries take you there automatically: you always verdict on the content that actually contains the change.
On pages without their own items, the chip shows the project-wide count and jumps you to the first pending item anywhere on the site.
## 4. Apply the verdicts
Run the `apply` workflow again. Rejected items are reverted to their original wording, change requests get the reviewer's literal text, and `/changes/` regenerates to match. Approved items close. The full state model is documented in [the iteration loop](/docs/iteration-loop/).
## 5. The iteration boundary marker
Every apply run writes `.pinappai/last-applied.json` with the run's timestamp. The next `/changes/` generation reads it and scopes the diff to "what changed since the last apply": reviewers only ever see the new round, not cumulative history.
If you decline the `/changes/` page offer during an apply run, the marker records that the batch is still waiting for a review page. Running the `generate-changes-page` workflow later picks that batch up automatically, so nothing you applied goes unreviewed.
**Commit `.pinappai/last-applied.json`** together with the source changes of each run (your AI agent stages it for you and asks before committing). `.pinappai/context.json` (project binding) lives next to it. Both are tiny, commit them.
## Preparing for production
When you ship and want all review markup gone from the customer-facing build, run the `remove` workflow in your AI client: it strips the widget tag, deletes `/changes/`, verifies with `git grep`, offers to disable the review link, and asks before committing. The `.pinappai/` directory is preserved by design so a later re-install lands on the same baseline.
---
# MCP server for AI agents
> Drive the PinAppAI iteration loop from Claude Code, Codex, Cursor, Continue, or any MCP agent: install, drain the Inbox with apply, and generate /changes/.
Source: https://pinappai.com/docs/mcp/
The **PinAppAI MCP server** is the AI-native interface to your project. Instead of pasting decision dumps into your editor, your agent runs the **apply** workflow and walks the full iteration loop end-to-end: read live state, propose code edits, write a marker so the next regeneration knows where the boundary is, and ASK before committing anything.
The MCP server is published as `@pinappai/mcp` on npm and runs as a stdio server next to the agent. It's also reachable as a hosted HTTP endpoint, no install required.
## Two ways to connect
| Way | What it takes | Best for |
|---|---|---|
| **[Hosted connector](#hosted-connector)** | One URL, then sign in through your browser (or paste an API key) | any client that speaks MCP over HTTP, zero install |
| **[npm package](#npm-package)** | Two commands: `npx @pinappai/mcp install`, then `login` | CI/headless installs, pinning a version, working offline |
Both reach the same server: the same 38 tools, the same 10 workflows. Neither is a reduced surface.
## Three surfaces, and who uses them
Worth getting straight up front, because they are easy to confuse:
| Surface | Who uses it | Example |
|---|---|---|
| **10 workflows** | **You** invoke them | The apply workflow. How you invoke one depends on your client, see [Run a workflow](#run-a-workflow). |
| **38 tools** | **Your agent** calls them over the protocol | `list_projects`. You never type these. |
| **6 CLI commands** | **You**, in a terminal | `npx @pinappai/mcp login` |
The one mistake worth avoiding: a workflow is **not** a shell command. Typing `pinappai-mcp apply` in your terminal will not work. Workflows are invoked inside your AI client.
## Hosted connector
For clients that speak MCP over HTTP, connect straight to a hosted endpoint instead of running `npx @pinappai/mcp` locally.
Endpoint: `https://mcp.pinappai.com/mcp` (Streamable HTTP).
Two ways to authenticate:
- **Browser sign-in, no key to paste.** If your client supports MCP browser sign-in (Claude Code does), add the endpoint with no credentials. Your client opens your browser to approve access and pick the workspace the agent works in, then connects. Nothing to copy, nothing to store by hand.
- **API key.** For clients that authenticate with a static header, pass a bearer key: `Authorization: Bearer ppk_...`. Mint one from [app.pinappai.com/api-keys](https://app.pinappai.com/api-keys) (see [npm package](#npm-package) below for what a `ppk_` key scopes to).
Either way, a client with no credentials can still discover the server: list tools, read workflows. Running a tool is the part that needs authentication.
### Claude Code, browser sign-in
```sh
claude mcp add --transport http pinappai https://mcp.pinappai.com/mcp
```
No key in the command. Your client opens the browser to approve access on first use.
### Claude Code, API key
```sh
claude mcp add --transport http pinappai https://mcp.pinappai.com/mcp --header "Authorization: Bearer ppk_YOUR_KEY"
```
### Any client with a JSON config (Cursor and similar)
```json
{ "url": "https://mcp.pinappai.com/mcp", "headers": { "Authorization": "Bearer ppk_YOUR_KEY" } }
```
The npm package (`npx @pinappai/mcp`) stays fully supported: it's the right choice for CI/headless installs, pinning a version, or working offline. The hosted endpoint is a second way to connect, not a replacement.
## npm package
Two commands work for any AI client (Claude Code, Codex CLI, Cursor, Claude Desktop, Continue):
```sh
npx @pinappai/mcp install # registers the MCP entry in every detected AI client config
npx @pinappai/mcp login # opens browser for sign-in, mints a per-machine key, saves it locally
```
`install` writes the MCP server entry into every AI client config it finds on your machine (`~/.claude.json`, `~/.cursor/mcp.json`, `~/.codex/config.toml`, `~/.continue/config.yaml`, `~/Library/Application Support/Claude/claude_desktop_config.json`). No credential is written at this step.
`login` runs a browser sign-in flow: prints a URL + a short approval code, opens your browser, lets you pick a workspace if you have multiple, and saves the freshly minted API key locally on your machine. The MCP server picks it up automatically on next launch.
The `ppk_…` API key is **separate from the widget's `pk_*` key**: it's a workspace-scoped machine credential, and every call it makes runs with the workspace role of the member who approved the login.
The six CLI commands:
| Command | Purpose |
|---|---|
| `npx @pinappai/mcp install` | Register MCP entry in every detected AI client config |
| `npx @pinappai/mcp login` | Browser sign-in; mint + save a per-machine key |
| `npx @pinappai/mcp logout` | Revoke the key server-side and delete the stored credentials file |
| `npx @pinappai/mcp uninstall` | Remove MCP entry from AI client configs, and sign out (revoke + delete key) |
| `npx @pinappai/mcp --help` | Print every workflow and tool this version exposes |
| `npx @pinappai/mcp --version` | Print the installed version |
`--help` reads the live server, so it always describes the version you actually have. It is the one answer to "what can this thing do?" that works identically in every client and every terminal.
### Verify the install
Restart your AI client, then ask it, in plain language:
> list my PinAppAI projects
If it answers with your projects, the server is connected and authenticated. That check works in **every** client, because it exercises the tools every client implements.
Do not verify by typing a slash command. Whether workflows appear as slash commands depends entirely on your client, so a slash command that does not autocomplete tells you nothing about whether the install worked. See [Run a workflow](#run-a-workflow).
### CI / headless installs
The browser-based `login` doesn't fit non-interactive contexts. Set `PINAPPAI_API_KEY=ppk_…` in the environment that spawns the MCP: the MCP server reads env first, then the credentials file. Mint the key from [app.pinappai.com/api-keys](https://app.pinappai.com/api-keys); name it after the machine / pipeline so you can revoke cleanly later.
### Manual install
If you'd rather wire up a single client by hand, or you need to pin a specific version, these are the per-client config snippets the new `install` writes for you:
#### Claude Code
```sh
claude mcp add-json pinappai '{"type":"stdio","command":"npx","args":["-y","@pinappai/mcp"],"env":{"PINAPPAI_API_KEY":"ppk_..."}}'
```
#### Cursor: `~/.cursor/mcp.json`
```json
{ "mcpServers": { "pinappai": { "command": "npx", "args": ["-y", "@pinappai/mcp"], "env": { "PINAPPAI_API_KEY": "ppk_..." } } } }
```
#### Claude Desktop: `~/Library/Application Support/Claude/claude_desktop_config.json`
```json
{ "mcpServers": { "pinappai": { "command": "npx", "args": ["-y", "@pinappai/mcp"], "env": { "PINAPPAI_API_KEY": "ppk_..." } } } }
```
#### Codex CLI: `~/.codex/config.toml`
```toml
[mcp_servers.pinappai]
command = "npx"
args = ["-y", "@pinappai/mcp"]
[mcp_servers.pinappai.env]
PINAPPAI_API_KEY = "ppk_..."
```
#### Continue: `~/.continue/config.yaml`
```yaml
mcpServers:
- name: pinappai
command: npx
args: ["-y", "@pinappai/mcp"]
env:
PINAPPAI_API_KEY: ppk_...
```
`PINAPPAI_API_BASE` is optional and defaults to `https://api.pinappai.com`.
## Run a workflow
Workflows ship inside the MCP server. No extra setup.
**How you invoke one depends on your client.** The MCP spec deliberately leaves that to each client, so there is no single syntax that works everywhere. Find your client:
| Your client | Run the apply workflow |
|---|---|
| **Claude Code** | Type `/pinappai:apply`. Typing `/pinappai:` autocompletes the menu. |
| **Codex** | Ask it: *"run the pinappai apply workflow"*. Codex fetches the procedure and follows it. |
| **Continue** (VS Code / JetBrains, agent mode) | Type `/apply`. Continue lists workflows without a server prefix. |
| **Cursor** | Type `/` and pick from the menu. |
| **Claude Desktop** | Use the **+** menu, then pinappai, then apply. |
| **Any other MCP agent** | Ask in plain language, the same as Codex. |
Swap `apply` for any workflow name below.
Two notes worth knowing. **Codex does not show workflows as slash commands** at all: typing `/pinappai:` there answers `Unrecognized command`. Asking in plain language is the supported path, and it runs the same procedure. **Continue does not namespace workflows**, so ours arrive as `/apply`, `/remove` and friends, sharing one menu with any prompt files of your own. Continue also surfaces workflows only in the editor extension in agent mode, not in its `cn` CLI.
If you are unsure what your client supports, ask it in plain language. That path works everywhere.
### The 10 workflows
| Workflow | Purpose |
|---|---|
| `setup-project` | Create a new project from scratch: workspace, project, widget snippet, reviewers. Offers the no-install [review link](/docs/review-link/) and bootstraps the iteration boundary marker. |
| `embed-widget` | Embed the widget snippet into an **existing** project's site and bootstrap the marker, the MCP-native equivalent of "Copy embed prompt for AI". |
| `apply` | The loop's engine. Drain the Inbox: new applies, reverts for rejected items, rewrites for change requests, then mark the whole round applied in one atomic batch, refreshing `/changes/` on the way. |
| `generate-changes-page` | Generate the `/changes/` review page for a multi-page batch of edits and register its items: for the first page of a big rewrite, or whenever you want one outside an apply run. |
| `remove` | Strip widget + `/changes/` + helpers when you're shipping. Preserves `.pinappai/` for re-install, and offers to switch off the review link too. |
| `analyze` | Read-only triage report on the current CR pile (no edits made). |
| `summarize` | Generate a PR description, changelog, or customer email from completed work, citing the original CRs. |
| `audit-review` | Summarize recent audit-log activity for the workspace (Business tier; owner role). |
| `auth-help` | Diagnose API key / role / scope issues if a tool returns 401 or 403. |
| `reset-project` | Wipe a project's review data back to zero: CRs, decisions, pins, screenshots on the server, optionally the repo's `/changes/` + marker. Not recoverable; asks twice. |
`npx @pinappai/mcp --help` prints this same list from your installed version.
The five featured on [/mcp/](/mcp/) (`setup-project`, `embed-widget`, `apply`, `generate-changes-page`, `remove`) map to the iteration-loop arc: set up (or embed into an existing site), apply the Inbox, generate the review page, remove when you ship. The other five are utilities you'll reach for less often.
## The iteration loop, at a glance
```
reviewers pin change requests (#N assigned)
│
▼
Inbox ──── apply workflow ────▶ InReview
▲ │
│ Reject / Request change ├── Approve → Closed
└─────────────────────────────────┘
```
Every pin lands in the dashboard **Inbox** as a numbered change request. One `apply` run drains it: the agent edits your source, regenerates `/changes/`, and records the round: every applied CR moves to **InReview**. Reviewer verdicts either close a CR or bounce it back to the Inbox for the next round, same CR, same #N. There is no separate triage ceremony.
The full state model (substates, defer, reopen, first-action-wins) lives in [the iteration loop](/docs/iteration-loop/).
## The `.pinappai/` directory
A small folder at the root of your repo. It's load-bearing for the iteration loop: **commit it**, don't gitignore it.
| File | Purpose |
|---|---|
| `.pinappai/last-applied.json` | The iteration boundary marker. ISO timestamp written at end of every apply run. The next `/changes/` regen scopes to "git log --since=". |
| `.pinappai/context.json` | Project shape cache: detected stack (Astro / Next / Hugo / etc.), build / lint commands, source dir, route convention, localization shape, and `text_lives_in` (`pages-inline` / `component-props` / `i18n-files` / `content-files` / `mixed`). Saved once, then every prompt reads it instead of re-detecting. |
Both files are tiny (a few hundred bytes each). Committing them means a teammate's first MCP run already knows your project's shape: no second round of "what stack are you on?" questions per machine.
If `.pinappai/` is gitignored or the working tree is read-only, the prompts fall back to in-memory detection: the loop still works, just less efficiently.
## Landing-chooser: the AI never auto-commits
Every workflow that touches your repo (`setup-project`, `embed-widget`, `apply`, `remove`, `reset-project`) ends with this verbatim block:
```
✅
Affected files:
How do you want to land this? Pick one:
(a) New feature branch — suggested name: pinappai/-YYYY-MM-DD-HHMM
I'll create the branch from your current HEAD, commit ALL the
affected files, and either push or stay local — your call.
(b) Commit on the current branch — same commit, no branch switch.
(c) Stage only — leave it uncommitted so you can review the diff first.
(d) Skip — don't touch git, you'll handle it manually.
Suggested commit message: ():
Tell me which option (a / b / c / d), whether to push, and any
commit-message tweaks. I'll wait.
```
The agent stops there until you pick. That's the contract: no `git add`, no `git commit`, no `git push` until you say which option. Branch protection is respected; `--no-verify` is never used. If you say "your call, just do it," the default is (b) commit on current branch + don't push.
Pre-flight is also covered: every applies-to-source prompt runs `git status` + `git branch --show-current` before editing. Dirty working tree → it surfaces the diff and asks instead of silently stashing.
## Tools the server exposes
38 tools across read + write surfaces. Your agent calls these; you never type them. Here are the 6 read tools you'll touch most often:
| Tool | What it returns |
|---|---|
| `list_projects` | All projects the API key can see |
| `list_change_requests` | Recent feedback rows (pins, comments, decisions) with filtering by status / kind / page / cursor pagination |
| `get_change_request` | Full detail for one feedback row by id: page URL, selector, before/after text, reviewer, decision, screenshot URL |
| `get_review_summary` | Aggregate counts: pending vs decided, approved/rejected/change-requested split, per-page breakdown |
| `get_screenshot` | The PNG bytes for an attached screenshot, base64-encoded for the agent |
| `analyze_patterns` | Across decisions, what wording patterns are reviewers consistently rejecting? Returns clusters with examples |
One tool carries the workflows themselves:
| Tool | What it does |
|---|---|
| `pinappai_get_workflow` | Returns a workflow's full procedure as text. This is how clients that don't show workflows as slash commands still run the real thing: the agent fetches the exact procedure and follows it, rather than improvising from the name. It's what makes *"run the pinappai apply workflow"* work in Codex. Read-only. |
Four tools drive the apply loop (they're what the `apply` and `generate-changes-page` workflows call under the hood):
| Tool | What it does |
|---|---|
| `pinappai_list_apply_inbox` | Everything Apply-eligible right now: new, rejected (needs a revert), and change-requested (needs new wording), with the fields the agent needs to edit source |
| `pinappai_apply_change_requests` | Atomic end-of-round call: takes the per-CR before/after pairs, records one iteration, moves every CR to InReview in a single batch |
| `pinappai_register_change_items` | Registers a freshly written `/changes/` page's items with the API so decision bars, the in-page chip, and verdicts light up |
| `pinappai_reset_review_data` | The nuclear option behind the `reset-project` workflow: wipes a project's CRs, decisions, pins, and screenshots |
Two more expose apply history: `pinappai_list_iterations` (past rounds with their frozen manifests) and `pinappai_get_iteration_coverage` (how complete is this round: decided vs outstanding, per reviewer).
The remaining 25 cover the full admin lifecycle, and this completes the list of all 38:
| Area | Tools |
|---|---|
| Account & GDPR | `get_me`, `update_me_profile`, `export_my_data` (Art. 15 export) |
| API keys | `list_api_keys`, `get_api_key`, `revoke_api_key`, `restore_api_key` |
| Workspaces | `list_workspaces`, `get_workspace`, `create_workspace`, `update_workspace`, `delete_workspace` |
| Projects | `get_project`, `create_project`, `update_project`, `archive_project`, `unarchive_project` |
| Members | `list_members`, `invite_member`, `update_member_role`, `remove_member` |
| Reviewers | `list_reviewers`, `invite_reviewer`, `revoke_reviewer` |
| Audit log | `list_audit_events` (Business tier) |
Every write is gated by the caller's role: `editor` can drive the apply loop and register `/changes/` items but not invite members; `admin` can do everything except permanent-delete (which stays admin-UI-only by design).
## Auth model
`ppk_` keys are scoped to a **workspace**, not a single project: one key reaches every project in the workspace. Each key is minted by a workspace member, and every call runs with that member's *current* role (`viewer` / `editor` / `admin` / `owner`): a `viewer`'s key sees reads only; an `admin`'s key drives the full lifecycle. Change the member's role and the key's reach changes with it; remove the member and the key stops working.
To plug an agent into a second workspace, mint a key there and add the server again under a different name (e.g. `pinappai-staging`). Multiple servers can coexist; the agent picks based on natural-language context.
Keys can be revoked from admin at any time. The next MCP call from that key returns `401`. The agent should treat that as "I lost access, please surface a new key."
## Source
The server source and changelog live at `@pinappai/mcp` on npm. Bug reports and issues go to the project's GitHub repo.
---
# Reviewer access & permissions
> Who can leave feedback on your project: open access vs allowlist, inviting reviewers, removing them, and what 403 errors mean.
Source: https://pinappai.com/docs/reviewers/
Two questions decide who can post feedback on your project: **is this project open to anyone, or invite-only?** and **is this email on the allowlist?** This page walks through both.
## Open access vs allowlist
Each project has a single toggle, **Open access**, that flips its access mode.
- **Open access OFF** (default): only invited reviewers + workspace members can submit. The widget's email-OTP modal accepts a code only for emails on the project's reviewer list.
- **Open access ON**: anyone who can reach the page can verify their email and submit. The widget auto-creates a reviewer record on first OTP.
Toggle it from the project's **Settings** (Projects → Settings on the project's row). The recommendation:
> **Off for production:** keeps your dashboard signal-to-noise high. **On for public beta tests:** you want unsolicited feedback from real visitors.
You can flip it any time. Existing reviewer rows survive either direction; the toggle only changes who CAN newly verify.
## Inviting reviewers
From the project's row in Projects, click **Reviewers**, then **Add reviewer** → enter email → save. Repeat for each invitee. Each invitee receives an invitation email; when the project has a review link configured (Site origin in Settings), the email includes a ready-to-click link to start reviewing, no install needed. Reviewers who prefer working in their own logged-in tab can use the [reviewer Chrome extension](/docs/extension/) instead: they sign in once and never type email codes on pages.
Workspace members (anyone you've added to your PinAppAI workspace) are implicitly allowed without needing a per-project reviewer entry. Useful for internal teams.
## Removing reviewers (two-stage)
The Remove button on a reviewer row is a two-stage action that mirrors a Trash → Empty Trash pattern:
1. **First click on an active reviewer** → soft-revokes. The row stays in the list with a REVOKED badge so you can see who used to have access. Already-submitted feedback survives untouched.
2. **Second click on a revoked reviewer** → hard-deletes the row. The row is gone from the list entirely.
The two stages are explicit because revocation is reversible-in-spirit (audit trail of "who was once a reviewer") whereas hard-deletion isn't. Submitted feedback always survives both stages: it belongs to the reviewer's account, not to their access entry.
## Reviewer sessions: signing in and out
A reviewer verifies their email once per site and stays signed in on that browser until the sign-in expires, which takes about half a day. While signed in, an initials chip sits beneath the widget's floating buttons. Open it to see the name and email their feedback will carry, and to **Sign out**.
When a sign-in expires the widget says so and signs the reviewer out on the spot: the chip disappears and their own pins stop showing. Nothing is lost. One more email code brings the session and every pin back.
Sign-out is real: the session ends on our side, not just in that browser tab. On the review link, signing out ends the session for every project served through `review.pinappai.com` in that browser. Reviewers using the [Chrome extension](/docs/extension/) sign in and out from the extension itself instead.
## What 403 errors mean for reviewers
The OTP modal surfaces specific 403 messages so you can self-diagnose if a reviewer can't get in:
| Modal text | What it means | What to fix |
|---|---|---|
| "This site isn't on the project's allowed-origins list…" | The page's origin (e.g., `https://staging.your.site`) isn't in `allowed_origins` for the project | Add the origin in Projects → Settings → Allowed origins |
| "This email isn't on the project's reviewer allowlist…" | The reviewer's email isn't on the allowlist AND open access is off | Either add the email as a reviewer, or flip Open access on |
| Anything else | The API returned the literal message (usually a stale `data-project` key) | Verify the script tag matches your current project's API key |
These granular messages replaced an older "you don't have permission, contact the project owner" generic message that left owners debugging blind.
## API key vs reviewer
Two separate concepts:
- **`pk_*` (widget key)**: embedded in your widget script tag. Public, scoped to one project, intended to be in your customer-facing HTML. Cannot post feedback by itself; it only identifies which project the widget belongs to.
- **Reviewer credential**: minted when a reviewer verifies their email, scoped to that reviewer and that browser, and required on every feedback submission. Never appears in your HTML; you never handle it.
Revoking a reviewer takes effect on their next submission attempt: the submission is rejected and they see the granular 403 in the modal.
## Workspace roles (advanced)
Workspaces have four roles: **owner** > **admin** > **editor** > **viewer**. Project access flows through workspace membership: any workspace member can submit feedback on any project in the workspace. Only owners + admins can manage API keys and project settings. Viewers and editors can submit but not configure.
Workspace member changes propagate to project access immediately. No per-project sync.