Skip to main content

Running the app

Everything you need to know about running postman-app locally — commands, flags, channels, and config.


The two-terminal workflow​

Running the app always requires two terminals:

# Terminal 1 — start the dev server
yarn run start

# Terminal 2 — open the app (wait for Terminal 1's build to finish first)
yarn run open

yarn run start builds the app and serves it. yarn run open launches the Electron window pointing to that server. Both must stay running while you develop.


Prerequisite: local HTTPS certificate (mkcert)​

The dev server serves the app over HTTPS at https://matrix.postman-beta.co:8777 (and :8778). That hostname is a public DNS record that already resolves to 127.0.0.1, so no /etc/hosts entry is needed.

The certificate is generated per machine via mkcert on yarn start — you just need mkcert installed and its local CA registered once:

# macOS
brew install mkcert nss && mkcert -install

# Windows
choco install mkcert && mkcert -install

# Linux: install libnss3-tools + the mkcert binary, then:
mkcert -install

mkcert -install is required because postman-beta.co uses HSTS — the browser/Electron app won't offer a "proceed anyway" bypass, so the certificate must be trusted (a plain self-signed cert is blocked). If you hit a NET::ERR_CERT_* warning, confirm mkcert -install has run, then delete npm/certs/*.pem and re-run yarn start to regenerate it.


Webpack vs Rspack​

The repo supports two bundlers:

CommandBundlerWhen to use
yarn run start / yarn run openWebpackDefault — most stable, used in CI
yarn start / yarn openRspackFaster builds — the team is moving here

For day-to-day development, either works. Rspack (the shorter command) is faster and is the long-term direction.


Build targets: desktop vs browser​

By default, the app builds for desktop (Electron). To build the web browser version instead:

yarn start --target browser
yarn open --target browser

The browser version runs in Chrome without Electron — useful for testing web-specific behavior or working on features that ship to postman.com.


Channels​

Postman ships as multiple named apps: dev, beta, canary, stage, and prod. The channel controls which environment URLs and app icons are used. Use the -c flag to switch:

yarn run start -c dev # default — dev backend (postman-beta.com)
yarn run start -c stage # staging backend
yarn run start -c beta # beta channel

# Packaging uses the same flag:
yarn run starship-package -c beta # packages the PostmanBeta.app binary
yarn run starship-package -c prod # packages the production Postman.app

Channel configs live in starship/ — one JSON file per channel. They define the app name, icon, URL protocol, and build directory.


Useful start flags​

Skip slow modules​

The console and runner modules add significant build time. If your work doesn't touch them, skip them:

yarn run start -- --skip-bundle="console,runner"

This is one of the most useful flags for fast iteration.

Analyze bundle size​

yarn run start -- --analyze-bundle

Opens a visual bundle analyzer in the browser showing what's in each chunk. Useful for investigating why a PR increased bundle size.

Check duplicate packages​

yarn run start -- --check-duplicates

Prints all duplicate npm packages in the bundle. Enabled by default in non-dev channels.

Disable hot module replacement​

yarn run start -- --disable-hmr

Code still rebuilds on changes, but the app doesn't auto-reload. You'll need to press Cmd/Ctrl+R in DevTools manually. Useful when HMR is causing unexpected state issues.


Opening DevTools​

# Open DevTools for all windows (except loader)
yarn run open -- --dev-tools

# Open DevTools for specific windows only
yarn run open -- --dev-tools=requester,loader
yarn run open -- --dev-tools=loader,shared,console

Available window keys: runner, console, requester, loader, shared.

note

--dev-tools works on the built app, not during dev mode (yarn run start). In dev mode, you can open DevTools manually via the app menu.


The configuration system​

Environment-specific config (API gateway URLs, feature flags, service endpoints) lives in:

config/environments/
├── default/ # Standard Postman builds
│ ├── browser/
│ │ ├── base.json # Shared defaults across all channels
│ │ ├── dev.json # Dev channel overrides
│ │ ├── stage.json
│ │ └── prod.json
│ └── desktop/
├── gw/ # Gateway variant (different service URLs)
│ └── browser/
├── enterprise/ # Enterprise / Postman Black builds
│ └── desktop/
└── local.json # Your local overrides (gitignored — see below)

The three config types are:

  • default — standard postman-app builds
  • gw — gateway-specific service URLs (used by some internal tools)
  • enterprise — enterprise and Postman Black builds

The active config is determined at runtime by domain/app context. The --channel flag selects which channel overlay to apply on top of base.json.

Overriding config locally​

Create config/environments/local.json to override any config value during local development. This file is gitignored — your changes won't be committed:

{
"__WP_CLOUD_AGENT_GATEWAY_WEBSOCKET_URL__": "'ws://localhost:8080/ws'"
}

This is the right way to point the app at a local backend service without modifying tracked files.


Test commands​

# Run everything (lint + unit + system)
yarn run test

# Lint only
yarn run test-lint

# Unit tests with coverage
yarn run test-unit -- --coverage

# Tests for a specific file
yarn run test -- -f testFile.js

# Single Nx package
nx test @postman-app/workspace-data
nx lint @postman-app/workspace-data

Attach Playwright to the local Electron app​

Keep the normal two-terminal development workflow, but launch PostmanDev with a dedicated test profile. Chromium publishes its OS-assigned debugging port in that profile:

# Terminal 1
yarn start

# Terminal 2
yarn open \
--user-data-path "$PWD/tests-v2/e2e-tests/.test-cache/local-app-profile"

# Terminal 3
yarn playwright test-app --attach --spec client-foundation/app-version-fetch

Attach mode owns authentication inside this dedicated profile. At worker start it signs out any existing account, provisions the user requested by the spec, and signs Electron in through a separate persistent Chrome profile at tests-v2/e2e-tests/.test-cache/local-auth-browser-profile. The browser profile retains Cloudflare and Identity cookies between runs; on first use the runner waits up to two minutes so a one-time verification can be completed. During teardown it signs the temporary user out before deleting it.

The Playwright runner discovers the port from DevToolsActivePort, verifies that the endpoint belongs to PostmanDev, and confirms it is rendering the local matrix.postman-beta.co:8777 build — skipping the auth, shell-migrator and proxy support windows — before connecting. It disconnects without terminating the app after the run. While attached, Playwright's default CDP overrides apply to your live window, so its colour scheme and download handling can change until the run ends. Authentication and user-switching specs can change the dedicated profile normally. See the tests-v2/README.md local Electron app section for profile overrides, safety constraints, and process-lifecycle limitations.


Cleanup​

# Remove all node_modules directories and build artifacts (dist/, build/, build-agent/)
yarn run clean

# Remove only local caches (.build-cache, .cachelint, .jest-cache, .nx)
yarn run clean-cache

Run yarn run clean when dependencies feel broken or after major branch switches. Run yarn run clean-cache when builds feel stale but dependencies are fine.


Troubleshooting​

yarn install or yarn open fails with SELF_SIGNED_CERT_IN_CHAIN​

You see one or more native dependencies fail to build, for example skia-canvas, @postman/starship, keytar, node-pty, @parcel/watcher, or macos-export-certificate-and-key, with an error like:

gyp ERR! stack FetchError: request to https://nodejs.org/download/release/v24.14.0/node-v24.14.0-headers.tar.gz failed, reason: self-signed certificate in certificate chain
code: 'SELF_SIGNED_CERT_IN_CHAIN'

This is unrelated to the local dev-server certificate (mkcert). It happens because Cloudflare WARP inspects TLS traffic: during install, some dependencies download native binaries or Node/Electron build headers over HTTPS (from nodejs.org, electronjs.org, S3, or GitHub), and WARP re-signs that traffic with its own root CA. Node ships its own CA bundle and does not read the OS trust store by default, so it rejects the re-signed chain.

WARP already installs its root CA into the macOS keychain and the Windows certificate store, so the simplest fix is to tell Node to use the OS trust store. The app runs on Node 24, where this is built in (NODE_USE_SYSTEM_CA and the equivalent --use-system-ca flag ship in Node 23.8+):

export NODE_USE_SYSTEM_CA=1
yarn install # or yarn open

Add the export line to your ~/.zshrc so it persists across sessions. This is the fix Node itself points to in its certificate-error hint, and it needs no .pem file. On macOS and Windows the WARP cert is already in the system store, so nothing else is required. On Linux, --use-system-ca reads OpenSSL's default CA paths rather than a single unified store, so results are less consistent there; if it does not work, use the fallback below.

Fallback: point Node at the WARP CA file​

If the WARP root CA is not in your OS trust store, point NODE_EXTRA_CA_CERTS at the cert file directly:

export NODE_EXTRA_CA_CERTS="/Library/Application Support/Cloudflare/installed_cert.pem"
yarn install

That path is the macOS WARP cert location; ask in #it-help if you cannot locate it on your platform.

Both options keep Node's normal chain verification intact. Do not use NODE_TLS_REJECT_UNAUTHORIZED=0, which turns verification off entirely.

Scope: these settings only affect Node's own TLS. The app resolves all dependencies from the npm registry and prebuilt native binaries (no git+https dependencies), so the Node setting covers every download in a normal install. A dependency fetched over git+https, or a postinstall script that shells out to curl, git, or python, would use that tool's own CA handling and need separate configuration (for example git config --global http.sslCAInfo).

Why this only appears sometimes

An existing node_modules skips these download and build scripts, so the proxy interception stays invisible. A fresh clone, yarn run clean, or a branch switch that changes dependencies re-runs them, which is why the failure can surface unexpectedly even though the dependencies themselves have not changed.


Quick reference​

What you wantCommand
Start dev serveryarn run start
Open the appyarn run open
Faster buildsyarn start + yarn open
Web versionyarn start --target browser + yarn open --target browser
Skip console & runneryarn run start -- --skip-bundle="console,runner"
Check bundle sizeyarn run start -- --analyze-bundle
Open DevTools on startyarn run open -- --dev-tools=requester
Point to stagingyarn run start -c stage
Package the appyarn run starship-package -c dev
Run all testsyarn run test
Clean everythingyarn run clean