Skip to main content
Demoman runs on your machine. Its browser opens only the pages your agent asks for, in a fresh profile signed in only where you ran npx demoman signin <url> or a demo account signed in. It has no telemetry and calls nothing on demoman.io: the publisher receives nothing from a run.

What is installed

The demoman npm package is the command line, the MCP server your agent talks to, and the Studio. The server speaks over standard input and output only. It opens no port for your agent, and there is no bridge key or approval page as in the browser extension. Setup also downloads Chromium into Playwright’s cache (~/Library/Caches/ms-playwright on macOS). Each run records in a throwaway profile in that browser.

What setup changes in your agents

Setup connects each agent it finds and pre-approves Demoman’s tools, so they run without asking. It says what it did for each agent, and when it could not pre-approve. Setup is the whole approval. Once it has run, any session of an agent it connected can use Demoman on any site. There is no per-agent or per-site grant.

What it keeps on disk

Everything lives under ~/.demoman. DEMOMAN_HOME moves it. Videos you export go to ~/Downloads. An agent started with --out-dir saves to that folder instead. Each take is a version of a video. A run records its repo’s commit in the take too. Old recordings are removed on their own. When a run starts and when the Studio opens, at most once an hour, Demoman removes the frames and preview images of each version over 30 days old. It keeps a video’s current version, any version you edited in the Studio, the version your newest export was made from, and any version that could not be recorded again. The take’s steps, report and list of exports stay, and your exported files are never touched. A version whose recording was removed can be recorded again from its video. status says what the last cleanup did. Every MP4, GIF and PNG Demoman exports carries its video’s id and its take’s id inside the file. Anyone you send the file to can read them; they name nothing else. Your agent uses them to find the video a file came from. Page URLs in a take have query values and token-like path segments replaced by “redacted”. The address a script starts at is kept as given. Text typed into a password field, or a field whose name reads like a password, token, card number or code, is stored as hidden. The command line and the MCP server keep no log file. Their logs go to the terminal, with secrets swept out. The Studio reads no secrets, and its log is not swept. There is no delete command. The Studio’s library can delete a take or a whole video. To remove everything else, delete ~/.demoman (or just its takes/, videos/ or sessions/ folders), your exported files and Playwright’s Chromium cache, and remove Demoman from each agent: uninstall the Demoman plugin in Claude Code and in Codex, and for Cursor delete the demoman entry in ~/.cursor/mcp.json and the ~/.cursor/skills/record-demo/ folder.

Passwords and secrets

  • npx demoman signin <url> opens a visible window and you sign in yourself. Demoman saves the site’s stored state, never the form, and records nothing.
  • A demo account signs in from the steps in .demoman/accounts.json, in a hidden browser that is not recorded. A secret is never typed outside its account’s site, and a session that holds a secret’s value is not saved.
  • Secret values come from the environment, as in CI, or from .demoman/secrets.env. Either way, a secret must name the one site it may be typed on, so an accounts.json someone else wrote cannot send it to theirs.
  • Demoman sweeps every secret value out of written files, tool answers and log lines, replacing it with a placeholder. One gap: a token that merely contains the password is not caught.
  • The video is not masked unless you mask it. It shows what the page shows. A real password input draws dots because Chromium does; a field Demoman treats as a credential only by its name shows its value. A Mask added in the Studio covers part of the picture. A change to a step’s typed text covers that one field, not the same text shown elsewhere on the page.
  • Your agent makes the demo password and writes it to .demoman/secrets.env, so the agent, and the AI service it runs on, already has that value. Demoman only stops it being echoed back.

What your agent sees

Every tool answers with text. No image or video bytes travel over MCP.
  • recipe: how to record with Demoman, the same text for everyone.
  • snapshot: the page’s address, where it landed, its title, the size it was laid out at, and the visible text and position of its interactive elements.
  • run and report: the run’s report, with each step as the agent wrote it (credential text hidden), where each target was found, the size it recorded at, the take id, and the video and version it joined.
  • takes: each take’s id, name, date and step count.
  • videos: each video’s id, name, repo, start page, versions, pages, steps, and where each version’s exports went. Given an exported file, which video and version it came from.
  • derive: a script rebuilt from a take, including the text it typed (credential fields blank).
  • status: versions, the export folder, saved sign-ins (sites and dates, never cookies), demo accounts (names and sites), the secrets file’s path but never a value, the pull-request video setting, the last run’s report, the last cleanup of old recordings and the update check’s answer.
  • export: the saved file’s path and size. An agent with file access can open it.
  • attach: the pull request’s address and the posted video’s address on GitHub.
  • studio: that the Studio window opened.

What leaves your machine

To the publisher: nothing.
  • npm, once a day at most: Demoman asks https://registry.npmjs.org/demoman/latest whether a newer version exists, with no identifiers beyond Node’s default user agent. DEMOMAN_NO_UPDATE_CHECK=1 turns it off; set it where your agent starts Demoman, and see Authentication for why Codex may not pass it on from your shell. npx also asks npm for the newest Demoman each time your agent starts the server.
  • During setup: Playwright downloads Chromium from its CDN, Claude Code and Codex fetch the Demoman plugin from GitHub, and npm’s cache is warmed with the package.
  • GitHub, to update the plugin: Claude Code and Codex check the Demoman plugin’s GitHub repository in the background and install a newer version when there is one.
  • GitHub, only when your agent attaches a video to a pull request: the video goes up through your gh sign-in, to the pull request’s description or a comment, where anyone who can see the pull request can see it. Your agent does this without asking only when the pull-request setting is Attach. It is Ask unless you change it, which offers first. The setting guides your agent and Demoman does not enforce it: setup pre-approves attach with Demoman’s other tools, so no prompt stops an attach your agent decides to make, including one a page it read talked it into.
  • The sites your agent opens, and whatever they load, in Demoman’s browser.
  • Your agent’s AI service, through the agent, for everything under “What your agent sees”. Demoman neither sees nor controls that.

Local network

Nothing listens for your agent. The encode and render steps each start a short-lived server on 127.0.0.1, on a random port, for the length of that step. It does not authenticate: anything on your machine that finds the port can fetch that take’s frames and images while it runs. The Studio serves its pages on 127.0.0.1, on a random port, while it runs. Every request needs a cookie holding a random secret. A window gets that cookie from a link that works once, within a minute, so the secret never appears in an address. The browser’s own control channel also binds to localhost, with an unguessable path as its only credential.