How it works

What runs where, and where your data goes

canvas.review runs on your Mac, or on a box of your own in the cloud. The two pictures below show each part.

The Mac app

Your MacCoding agent sessionin your terminalclaude, codex, …Mac appthe menu bar paneland its helperBrowsera review linkCanvas CLI, one per PRreads the PR, serves the pagemacOS sandboxAgents and diffyduckyour own login and planGitHubyour gh loginAPI, git, commentsModel provideryour own planAnswers and drafts stay on your Mac. Comments live on GitHub.report, sendreview linkstartsrunsgh, git as youagent callsYour MacBrowsera review linkAgent sessionin your terminalMac appthe menu bar panel and its helperCanvas CLI, one per PRreads the PR, serves the pagemacOS sandboxAgents and diffyduckyour own login and planGitHubyour gh loginModel provideryour own planAnswers and drafts stay on your Mac.Comments live on GitHub.review linkreport, sendstartsrunsgh, git as youagent calls
Everything runs on your Mac, and the blue line is the path of a review link.

The web and the cloud

Your computeroptionalyour own agentscanvas.review on Cloudflaresign-in with GitHubaccounts and sealed readingsin D1 and R2Browsera review linkboxd, one box per personYour boxthe canvas CLI, one per PRyour clonesbubblewrapAgents and diffyduckyour own login and planGitHubsigned in as youAPI, git, commentsModel provideryour own plansendreview linkyour requestsrunsgh, git as youagent callsBrowsera review linkYour computeroptionalyour own agentscanvas.review on Cloudflaresign-in with GitHubaccounts and sealed readings in D1, R2boxd, one box per personYour boxthe canvas CLI, one per PRbubblewrapAgents and diffyduckyour own login and planGitHubsigned in as youModel provideryour own planreview linksendyour requestsrunsgh, git as youagent calls
Cloudflare sends your requests to your own box at boxd, and the blue line is the path of a review link.

Where your data goes

What each part keeps, and what leaves your machine.
  • Your code
    Where it lives

    On a Mac, a clone in ~/.cache/canvasreview.

    In the cloud, a clone in your home on your box. Cloudflare keeps no clones and no diffs.

    What leaves your machineThe PR's code goes to your agent's provider when the agent reads the PR. diffyduck also sends the files that it opens, and the git history of the changed files.
    Who can read itYou and your agent's provider. In the cloud, boxd also runs the disk of your box.
  • PR readings
    Where it lives

    The summaries, order and questions that an agent writes.

    On a Mac, in ~/.cache/canvasreview. In the cloud, in R2, sealed with AES-GCM and a key for each team.

    What leaves your machineIn the cloud, the reading goes to the team store. A question can quote a line of code.
    Who can read itYou. In the cloud, a team member whose own GitHub login can open the repo.
  • Your GitHub login
    Where it lives

    On a Mac, in gh's own login. The app asks gh for the token at run time and keeps it in memory.

    In the cloud, the GitHub App's tokens, sealed in D1. Your box gets the access token only.

    What leaves your machineOnly calls to GitHub. Agents never get the token.
    Who can read itYou. In the cloud, also our Worker, which holds the key.
  • Agent calls
    Where it livesYour agent's own login, on your Mac. In the cloud, each agent's own sign-in keeps it in your home on your box. Claude Code, Codex, Gemini CLI, Cursor, opencode and Copilot CLI can sign in there.
    What leaves your machinePrompts with the PR's text and code go to the agent's provider, on your own plan. Claude Code sends to Anthropic, Codex to OpenAI.
    Who can read itThe provider. canvas.review does not read or keep the agent's login.
  • diffyduck's findings and settings
    Where it lives

    Findings: on a Mac in ~/.cache/canvasreview, in the cloud in R2 beside the readings. The team store keeps the duck's findings, which can quote a few lines of code.

    Settings: on a Mac in the app's settings, in the cloud in D1. The Worker sends them to your box with each request.

    What leaves your machineA finding goes to GitHub only when you click Add to review or Post. It can quote a few lines of code.
    Who can read itFindings: you, and in the cloud a team member who can open the repo. Settings: you.
  • Your review skill
    Where it livesThe text that you write for diffyduck, up to 8000 characters. On a Mac in the app's settings, in the cloud in D1.
    What leaves your machineIt goes in diffyduck's prompt to your agent's provider. The agent keeps its read-only tools.
    Who can read itYou and the provider. In the cloud, also our Worker.
  • Canvas state
    Where it livesAnswers, opened questions, widths and drafts, in state.json, in ~/.config/canvasreview on your Mac or in your home on your box. Comments live on GitHub only.
    What leaves your machineNothing. What you post goes to GitHub through gh, after your click.
    Who can read itYou.
  • Connected computers
    Where it livesD1 keeps the name that the computer gave, when it was last used, and a SHA-256 of its token. Messages wait 10 minutes, and stay an hour at most.
    What leaves your machineThe agent's name, the folder's name (not its path), the branch, whether it is busy, the session's PRs, and what your agent tells you. Your code and prompts stay.
    Who can read itYou. Remove in Settings stops the token.
  • Cloudflare runs our Workers, D1, R2 and the Durable Objects. Our Worker holds the keys that open the sealed data.
  • A share link is a secret gist on your own GitHub account. It holds the reading and diffyduck's findings, never the code, except the lines that a finding quotes.
  • A deploy preview walk uses our own headless browser, with none of your logins. The browser sends only reads, opens no sockets and types no text. It walks only public previews, not an address on your Mac or your network. The first walk downloads the e2e tool and its browser.
  • Reads of your PRs, and what you post, go through your own gh. Some things load from GitHub directly, with no token: avatars, images in comments, the gist of a share link, and the first copy of gh, checked against a SHA-256 in the app.
  • To us: the app's check for a new version, and a bug report only when you send one. The app sends no analytics. This website loads no tracker.
  • Reading ahead sends a review request's code to your agent before you open it. Turn it off in Settings, Advanced, Prepare canvases.
  • Each person has a box of their own. Teammates share a PR's reading through the team store, not through a box.

The walls around each agent

What an agent can reach, and what it cannot.
  • On a Mac, each canvas is a local server that answers only its own page. Other websites cannot read a canvas.
  • On a Mac, the helper answers only on that Mac.
  • Your own computer is optional. Its agent token reaches only your messages, never your code, a box or GitHub.
  • On a Mac, each agent runs in a macOS sandbox. It blocks ~/.ssh, ~/.aws, gh's login, your documents and your browsers' data. Codex uses its own sandbox.
  • On a box, each agent runs in bubblewrap, with its own /proc. The gateway sets CANVASREVIEW_WALL=required, so no agent runs without it.
  • Agents get no GitHub token and none of our keys.
  • diffyduck reads a read-only copy of the PR's head, with read tools only and no web tools. Codex runs read-only commands in its own sandbox, with no network. The copy leaves out the PR's agent settings, hooks and .env files.
  • Cursor, opencode and Copilot CLI get a lean diffyduck that sees only the diff. So does Codex on a Mac, on a PR from outside the repo's team.
  • Only our Worker can call a box's gateway. A request without the box's key gets 403.
  • Our Worker keeps each box's key in D1, sealed with AES-GCM under a Worker secret.
  • The menu bar lists your agent sessions from ~/.claude/sessions and ~/.config/canvasreview/sessions. A message reaches a session only when you click Send to terminal, or answer its question.
  • Agents on a box cannot reach the team store's door. Bubblewrap hides its folder, and agents never get its token.
  • Nothing goes to GitHub without your click. A fix works in a separate checkout, and nothing reaches GitHub before you accept it.
  • The limit: text in a stranger's PR can try to steer an agent. canvas.review marks that text as quoted, but a model can still follow it.

Check it yourself

Five commands that check the app you downloaded.

Run these commands on the app that you downloaded, or tell your agent to run them.

  1. 1We sign the app with our Developer ID. The team ID is LPV78GHYTM.
    codesign -dv --verbose=4 /Applications/canvasreview.app
  2. 2Apple notarised the app.
    spctl -a -vv /Applications/canvasreview.app
  3. 3The app asks for no special permissions (entitlements).
    codesign -d --entitlements - /Applications/canvasreview.app
  4. 4See where the app connects. To see its gh, git and agent processes too, use a firewall such as LuLu.
    lsof -a -i -n -P -p $(pgrep -d, -f canvasreview.app)
  5. 5Compare the checksum with the one we publish. Add .sha256 to the end of your download link to get it.
    shasum -a 256 ~/Downloads/*.dmg

The app installs an update only when our team ID signs it.

More about the two parts

Review links, the hook, the Workers and the boxes.

The Mac app

  • Everything runs on your Mac: the canvas CLI, your coding agents and your own gh login.
  • A review link opens a canvas by itself only for a repo that you opened before. For other repos, you click Open first.
  • The hook and the MCP server run one copy of the canvasreview binary, in ~/.local/share/canvasreview/cli. The app puts its copy there at launch, unless a newer copy is there.

The web and the cloud

  • Cloudflare runs our three Workers and their storage. boxd runs one box for each person.
  • The site Worker sends cloud pages, and review links from a signed-in browser, to the cloud Worker. The app Worker answers the rest.
  • A box starts from the snapshot canvasreview-base. It sleeps after 10 idle minutes, and a request wakes it.
  • In the picture, dashed lines are calls from your own computer.