margo

Pin comments on your live app.
AI implements them.

A shared annotation layer for AI-coding teams. PMs, designers, and devs leave comments on the running UI. Claude Code reads those comments as live context and makes the change. Solo or team β€” both modes self-hosted, no SaaS, no extension to install, your project repo stays clean.

npm install -D margo-dev
npx margo init
npm run dev
localhost:5173
Alice
Bob

Pricing

~/acme β€” claude
Claude Code
β€Ί
2 open comments:
A c-001 alice β€” Make the CTA green
B c-002 bob β€” Highlight SAML 2.0
Edit src/components/Pricing.tsx
-className="cta cta-blue"
+className="cta cta-green"
-<li>SSO + audit log</li>
+<li>SSO (SAML 2.0) + audit log</li>
Commit margo: 2 ai-replies (ready-for-review)

1. Pin it

Click any element on the running app, type a comment. The overlay captures a hybrid anchor (selector + text + role + coords) so the pin survives refactors. Network calls can be pinned too.

2. AI works it

Each comment is a markdown file under ~/.margo/. Claude Code reads them via the /margo skill, makes the code change, replies in-thread, bumps status to ready-for-review. The plugin auto-syncs the file change to teammates β€” no margo push step.

3. Humans review

Approve, reply, or mark resolved β€” from the overlay on the live app, or from the host's dashboard at /projects/<slug>/comments. Either surface propagates instantly via SSE. Your project repo's git history stays untouched.

Two storage modes

Solo? Standalone. Team? Server. Switch by editing one line in margo.config.json.

Default Β· zero infra

Standalone

Solo workspace β€” "me + AI on my machine." No host, no sign-in.

  • Each workspace has its own UUID. Comments land under ~/.margo/standalone/<id>/comments/ β€” not in the project tree, not in git.
  • Identity comes from git config user.name/email; no separate account.
  • One person + Claude Code gets value in under a minute.
npm install -D margo-dev
npx margo init
npm run dev
Self-hostable Β· team collab

Server

Team collaboration via a self-hostable host. Web dashboard + offline-first sync.

  • Drop-in Docker image: margolabs/margo-host. First signup at /setup becomes superuser.
  • Per-project member roster (read / write / admin). Plugin caches to ~/.margo/cache/<host>/<project>/.
  • Web dashboard at <host>/projects/<slug>/comments: browse, filter, change status, reply, delete β€” every action broadcasts SSE so connected overlays update in real time.
  • Pins work even when the host's unreachable β€” writes queue locally and drain when it's back. Overlay shows a "syncing" pill while pending.
docker run -d -p 7331:7331 margolabs/margo-host
npx margo init --server http://<host>:7331 --project <slug>
npm run dev   # click "Sign in to margo" in the overlay

Works with your stack

Two integration modes β€” same overlay, same workflow.

Native plugin

Vite (vanilla, Vue, React, Svelte, Astro), Next.js App Router

One line in vite.config.* or next.config.*.

Sidecar + proxy

Angular, webpack-dev-server, Vue CLI, Create React App, SvelteKit (non-Vite), Remix-classic

Run margo serve next to your dev server; proxy /__margo/* to it.

Full setup for each framework is in the README. Demos for each integration ship in the repo.

Why this exists

Common questions

Real issues reported by users. Most are resolved by upgrading to the latest margo-dev.

Why am I seeing 404 /__margo/bootstrap.js?

The README's sidecar setup mentions adding <script src="/__margo/bootstrap.js"> to your HTML. Through 0.4.4, only the sidecar served that URL β€” Vite + Next plugins 404'd it. Fixed in 0.4.5: all three integration modes now serve bootstrap.js.

npm install -D margo-dev@latest
rm -rf node_modules/.vite .next
npm run dev
I keep seeing a "Set up your margo identity" dialog instead of the Sign in pill.

That dialog was a v0 leftover from when comments lived in your repo's git history and needed a real git config user.name/email. Removed entirely in 0.4.4. Server mode now always shows the blue Sign in to margo pill when there are no credentials; standalone mode falls back to you@local as the author if git isn't configured.

If you still see the dialog after upgrading, clear your dev server's overlay cache:

rm -rf node_modules/.vite .next
My Next.js app uses basePath: '/ui' and the overlay 404s every request.

Through 0.4.5, withMargo()'s rewrite was naive β€” Next auto-prefixed the basePath onto both sides, so the source ended up at /ui/__margo/* while the overlay always calls origin-root /__margo/*. Fixed in 0.4.6: withMargo() detects basePath and emits a rewrite with basePath: false + an absolute destination URL automatically.

// next.config.ts
import { withMargo } from 'margo-dev/next-config';
const nextConfig = { basePath: '/ui' /* whatever */ };
export default withMargo(nextConfig);
My CSP blocks margo's inline script ("script-src strict-dynamic without nonce").

Different per integration mode:

  • Next.js β€” 0.4.6+ <MargoScript /> auto-reads the nonce from next/headers's x-nonce request header. Existing users get the fix on npm install -D margo-dev@latest; no layout change needed.
  • Vite β€” pass a static nonce in your config (Vite's HTML transform runs before per-request headers exist): margo({ nonce: process.env.CSP_NONCE }). Strict CSP in Vite dev is rare; most setups don't need this.
  • Sidecar β€” you control the <script> tag in your HTML; add the nonce there yourself.
Do I need to run npx margo push after AI edits a comment?

No. Since 0.4.1, the dev plugin watches the cache directory with chokidar and pushes any change to the host through the offline-tolerant outbox. AI can edit ~/.margo/cache/<host>/<project>/comments/<id>.md directly and teammates see it via SSE. Don't invoke margo push manually inside an AI session β€” it duplicates work and can race with the watcher.

Is margo-dev getting pulled into my Next.js production bundle?

The route template generated by margo init in 0.4.6+ uses a production-gated dynamic import β€” chokidar and the rest of margo-dev's runtime never resolve in prod. If you initialized on an older version, replace the static import { handlers } from 'margo-dev/next-server' in app/margo-runtime/[[...path]]/route.ts with the dynamic pattern (full template in our repo README), or re-run npx margo init --server <url> --project <slug> with the overwrite flag.

I'm in server mode but my teammate sees a 404 instead of the Sign in pill.

Almost always an older margo-dev version that doesn't emit the data-margo-storage attribute on the bootstrap script tag β€” the overlay falls back to a stale code path. Have them upgrade and bust caches:

npm install -D margo-dev@latest
rm -rf node_modules/.vite .next
npm run dev

If the problem persists, check the dev server's terminal β€” the plugin logs [margo] host rejected bearer token when a token's been revoked from the dashboard. Sign-out + sign-in via the avatar popover fixes it.

My team can't reach our host (firewall / VPN / wrong IP). Are pins lost?

No. Server mode is offline-first since 0.4.x: writes land in ~/.margo/cache/<host>/<project>/.outbox/ when the host is unreachable, and a background drainer retries every 30 seconds. The overlay shows a small "N comments syncing…" banner while pending. Once the host is back, the queue drains automatically.