Docs

Reference

Troubleshooting

The Passback button does not appear

  • Start your dev server. The plugin is active under vite serve and in the build modes you list in stagingModes; other builds do not include the widget.
  • Check that your Vite config contains passback() in its plugins list. If you ran npx passback init without --apply, run npx passback init --apply: the first run only prints the changes. If npx passback init --apply could not edit the config safely, add the lines it printed.
  • Restart your dev server after running npx passback init --apply if 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 /passback in Claude Code or Cursor, $passback in Codex.
  • Approve the passback server in your agent when it asks.
  • Your comment is saved in .passback/inbox in 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 --apply from the project root you want to use, and add --agents if you limited it: the agent you use must be in the list.
  • Restart that agent in the same project folder.
  • Type /passback in Claude Code or Cursor, $passback in Codex.
  • Check that the project's passback MCP server is listed in the agent and approved. Approve it if the agent asks.
  • If init printed that it left .mcp.json, .cursor/mcp.json or the Passback block in AGENTS.md as 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 /passback or $passback.
  • Check that the passback server 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.

Next: Export and delete your data