Install the CLI

For a container demo, a bigger build, a terminal or Claude Code: pitch on your machine.

On this page

pitch is the command-line tool that checks, rehearses and publishes a demo from the folder it lives in. This page covers when you need it, what it needs on your machine, how to run it, how it signs in as you, and where it keeps the credential it signs in with.

When you need it

You may not. The connector deploys a static demo from a chat with Claude, with nothing to install, and most people start there. Install pitch when:

  • the demo has a server. A container demo deploys only from your machine.
  • the build is bigger than a chat carries, more than 200 files or 3 MB. pitch takes a static build of at most 5,000 files, 32 MB per file and 256 MiB unpacked.
  • you work on the demo in its repository with Claude Code, through the plugin.
  • you want links and pages from a terminal, or a deploy from a script.

When one of those applies, the connector says so. In Claude Code, Claude offers to run the install for you, and runs it only on your yes; in a chat, it gives you the commands. Either way, pitch login is yours to approve in your browser.

Run it

pitch is published on npm as @pitch-product/cli. Run it without installing anything:

npx @pitch-product/cli --help

or install it once, which gives you the command pitch:

npm install -g @pitch-product/cli
pitch --help

These docs write the command as pitch throughout, so pitch login means npx @pitch-product/cli login if you did not install it. It talks to Roomi, https://api.getroomi.com, with nothing to configure.

Requirements

What Why
Node 24 pitch requires Node 24 or later (node --version); npm warns if yours is older. It is also the Node every container demo runs on.
gitleaks Every rehearsal scans the project, and the build it makes, for secrets. If gitleaks cannot run, the deploy stops rather than calling an unscanned build clean. On a Mac: brew install gitleaks.
Docker, running Only for a container demo. pitch deploy builds your Dockerfile and runs the result on the platform's own runner, locally. A static demo does not need Docker.
macOS pitch login keeps its token in the macOS Keychain. pitch login, pitch open and pitch dev open your browser with the Mac's open command (xdg-open on Linux, start on Windows). See Other systems.
Your package manager For a static demo with a build script, pitch deploy runs it with the package manager your lockfile names: pnpm, yarn, bun, or npm if there is no lockfile.

If gitleaks is installed somewhere that is not on your PATH, set PP_GITLEAKS to its full path.

Create an account

Sign in at app.getroomi.com with Continue with GitHub. There is no separate sign-up: the first time you sign in, your account is made, with a workspace of your own on the Free plan. Continue with Google works the same way, but is open only to invited testers for now. Once you are in, you can add a passkey in Settings and sign in with it from then on. There is no sign-in by email.

Sign in

pitch login

pitch asks the platform for a one-time code, prints where to enter it, and opens that page in your browser:

  Open https://app.getroomi.com/device and enter the code K7QXDRPM
  (or go straight to https://app.getroomi.com/device?user_code=K7QXDRPM)
  Opened it in your browser.
  Waiting for you to confirm…

If the browser did not open, open the address yourself. If you are not signed in to the app there, it asks you to sign in first and brings you back. Enter the code, or check the one already filled in against your terminal, and choose Yes, connect pitch. Only approve a code your own pitch login printed, moments ago: approving someone else's code signs their machine in as you.

The terminal then says:

  Signed in. The token is in the macOS Keychain.

A code lasts 30 minutes. If it runs out before you approve it, pitch says the code expired and stores nothing; run pitch login again for a new one. If you choose No, deny it in the browser, it says Sign-in was denied in the browser. and stores nothing.

This is the OAuth device authorization flow (RFC 8628): the terminal never sees your password or your GitHub or Google sign-in, only the session token the platform grants once you approve.

Check who you are

pitch whoami
  Priya Shah <priya@example.com> on https://api.getroomi.com

It names the account and the platform the token is for. If there is no token it says you are not signed in, and if the stored token has expired, or its session was ended, it says the stored token is no longer valid. Either way, pitch login signs you in again.

Sign out

pitch logout

This ends the session on the platform, so the token stops working wherever a copy of it is, and then deletes it from the Keychain. If the platform cannot be reached, pitch says so and removes the token from your machine anyway.

Where the token lives

The token is kept in the macOS Keychain under the service name pitch-product-cli, and nowhere else: never in a file, never in your project, never printed. It reaches the Keychain on standard input rather than as a command-line argument, so no other process can read it from the process list.

There is one Keychain entry per platform address. A token for one platform never stands in for another, so signing in to a local platform while developing does not touch the token for the hosted one.

Scripts and CI

For a script, set PP_TOKEN:

PP_TOKEN=... pitch deploy --commit

pitch uses PP_TOKEN instead of the Keychain for that one run, and never writes it anywhere. While it is set, pitch login and pitch logout refuse, with PP_TOKEN is set, so the Keychain is not in use. Unset it to sign in or out., so the Keychain is never bypassed without you knowing.

The header for other programs

pitch auth header

This prints the one line a program needs to call the platform as you, and nothing else:

{"Authorization":"Bearer ..."}

It is how the Claude Code plugin signs its connection in to a platform running on your own machine (Deploying from Claude). Because it prints your token, it refuses when its output is a terminal a person is looking at, with This prints your token. It is meant to be read by a program; pass --print to see it here. Pass --print only if you mean to see it.

Choosing the platform

pitch talks to https://api.getroomi.com. pitch whoami says which platform it is using, and where that came from:

  API https://api.getroomi.com (the default)

You only change it to work on Roomi itself, against a platform running on your own machine. pitch config set api <url> keeps the address for you, and pitch config unset api goes back to production; PP_API overrides both for one shell or script. CLI has the details.

pitch config set api http://127.0.0.1:8200

Environment variables

Variable What it does
PP_API The platform's address, for this run, ahead of pitch config. Unset, pitch uses https://api.getroomi.com.
PP_CONFIG A settings file to use instead of ~/.config/pitch/config.json.
PP_TOKEN A token to use for this run instead of the Keychain. Never stored.
PP_GITLEAKS The path to gitleaks, when it is not on your PATH.
PP_KEYCHAIN A keychain file to keep the token in, instead of your default keychain.
PP_HEALTH_TIMEOUT_MS How long a container rehearsal waits for the platform's runner to open, in milliseconds. The default is 60000.

Other systems

Today pitch stores its token with the macOS security tool, so pitch login works only on a Mac. On Linux or Windows, sign-in fails because there is no Keychain to store the token in; PP_TOKEN works there, and so does everything that does not need a token: pitch init, pitch validate, pitch dev, and pitch deploy without --commit.

pitch login, pitch open and pitch dev print the address they open as well as opening it, so where the browser cannot be opened you can copy the address from the terminal.

Next