Reference
Troubleshooting
The Passback button does not appear
- Start your dev server. The plugin is active under
vite serveand in the build modes you list instagingModes; other builds do not include the widget. - Check that your Vite config contains
passback()in itspluginslist. If you rannpx passback initwithout--apply, runnpx passback init --apply: the first run only prints the changes. Ifnpx passback init --applycould not edit the config safely, add the lines it printed. - Restart your dev server after running
npx passback init --applyif it was already running. - Press Alt+Shift+R (Option+Shift+R on a Mac) to do the same as clicking the button.
A comment stays at "Sent. Waiting for the agent."
- Open a Passback session in your agent: type
/passbackin Claude Code or Cursor,$passbackin Codex. - Approve the
passbackserver in your agent when it asks. - Your comment is saved in
.passback/inboxin your project. It is safe there while you wait for the agent to pick it up.
The box says "Not sent."
- Your comment did not reach your project. Your text is kept: click Retry.
- In local development, your comment travels through the dev server's own connection into
.passback/inbox. Keep your dev server running so the plugin can receive it.
The tag is on the page and nothing appears
- The page address is not in Allowed origins in the Install section. The relay answers 403
origin_not_allowed. - Your Content Security Policy blocks a file. The browser console names it; see Content Security Policy in Install with a script tag.
- The site is paused. The widget removes itself.
Next: the route does not answer
Init writes an optional catch-all route at app/api/passback/[[...path]]/route.ts, or under src/app if your code lives there. It must contain exactly what init generated:
export { GET, POST } from '@passback/next/route';
export const runtime = 'nodejs';
export const dynamic = 'force-dynamic';Receiving and saving a comment works only under next dev with your config wrapped in withPassback. Without both, the route refuses requests that are not for the public widget assets. Those assets can still be served outside development. Check that the file is in place, that the config is wrapped (see the next entry), run next dev and restart it after any edit.
Next: the button or source location is missing
Init does not rewrite a config or layout it does not recognise. It leaves the file as it is and prints one of these messages, and you make the edit by hand:
next.config left as it is (…); wrap its export by hand: withPassback(config, { root: '…' })<layout> left as it is (…); add <Passback /> inside <head> by hand: import { Passback } from '@passback/next'
In your Next config, import withPassback and wrap the existing config:
import { withPassback } from '@passback/next';
export default withPassback(nextConfig, { root: '.' });In the layout that renders <html>, import Passback and put the tag inside <head>:
import { Passback } from '@passback/next';
// inside the layout's <html>:
<head>
<Passback />
</head>;Restart next dev after the edits. Both webpack and Turbopack have development instrumentation, so you do not need to switch bundlers, and Next has no stagingModes setting. See Install with Next.
The agent has no Passback command
- Run
npx passback init --applyfrom the project root you want to use, and add--agentsif you limited it: the agent you use must be in the list. - Restart that agent in the same project folder.
- Type
/passbackin Claude Code or Cursor,$passbackin Codex. - Check that the project's
passbackMCP server is listed in the agent and approved. Approve it if the agent asks. - If init printed that it left
.mcp.json,.cursor/mcp.jsonor the Passback block inAGENTS.mdas it is, follow the repair instructions it printed, then restart the agent. - Do not start a second MCP server by hand. The agent starts the one from the project configuration.
Every wait asks for permission
This is your agent's tool approval policy, not Passback. The session waits by calling the passback_wait tool, so an agent that asks every time asks on every wait. Approve the discovered passback_wait tool and choose the remembered approval option of your agent if it has one. Init does not set up a permanent permission. Do not turn off all tool approvals to fix this; if your agent has no remembered approval, ask whoever administers it.
A sent comment never reaches running
"Sent" means the comment was saved in .passback/inbox. It does not mean the agent picked it up. The agent picks it up while it waits through passback_wait, and reports running through passback_status.
- Check that a session is active: start one with
/passbackor$passback. - Check that the
passbackserver is approved in the agent. - Check that the agent and the dev server use the same project root (see the monorepo entry below).
- A wait that returns nothing is normal: the agent waits again until a comment arrives.
- A tool error stops the session. Read the error, repair the failure it reports, then restart the session.
Do not edit the fields in the inbox files yourself.
Windows switches keyboard layouts instead of opening Passback
On Windows, Alt+Shift usually switches the keyboard layout, but only when the two keys are released with nothing pressed between them. The Passback shortcut adds a third key, so the switch does not fire and the shortcut works. If it still collides with something on your computer, set a different key with hotkey as described in Widget settings, for example alt+shift+p, or off. That is a setting you choose, and another shortcut can collide with something on your computer too.
The app is in a monorepo subfolder
Your agent reads the inbox of the folder it was started in. If the app is in a subfolder, the dev server can write the inbox somewhere else, and the agent never sees the comment. Point both at the same root.
For an app at apps/web and an agent started at the repository root, keep your existing config and add the root option.
In Vite, a relative root is resolved against the Vite root, the folder of the app:
passback({ root: '../..' });In Next, an explicit root is resolved against the folder where next dev starts. Start it in apps/web and use:
withPassback(config, { root: '../..' });If PASSBACK_ROOT is already set, it overrides the Next root option. Restart the dev server and the agent, each started from its intended folder. The comments already in the inbox stay there and the agent reads them.
For setup and the full comment flow, see Install with Vite and Your first comment.