@cross-deck/cli — CLI reference
@cross-deck/cli is one binary — crossdeck — with two families. Sign in with your browser and you provision projects and apps, mint keys, and read revenue, analytics, and errors straight from your terminal, across web, iOS, and Android. Or drop the key-based source-map upload into CI, no login, no browser. Same binary, one keychain, honest command names. This page is the full reference.
The launcher
Run crossdeck with no command on an interactive terminal and it opens a session — a working environment, like claude. Inside it you type bare commands with no crossdeck prefix (whoami, init, revenue, use prolend, help, exit), and your active project persists across the session and shows in the prompt. The session opens with the splash — the brand's first impression in your terminal, in two states: logged out shows exactly one path (sign in); logged in reveals the two hats — stand up the engine, then read the facts. The tagline is the honest moat, not a slogan: Crossdeck joins revenue, errors, and identity by identity.
The session is for humans at a keyboard. Everything is also a one-shot command — crossdeck revenue, crossdeck init … — so scripts and CI compose exactly as you'd expect. When Crossdeck detects it isn't attached to an interactive terminal (a pipe, a CI runner), it never opens a session; it runs the command and exits.
It shows raw facts and the paths to them — never revenue-at-risk, churn queues, or "the cross" as a headline. Interpretation lives in Prism and the dashboard, never in the binary.
Zero to a running account
The whole journey, word for word — from a machine with nothing installed to a live Crossdeck project with identity wired, a payment rail connected, and the numbers flowing. Follow it top to bottom; every command is exactly what you type and every result is what you'll see. You don't need to be an engineer — where a step happens in your app's code or in the dashboard instead of the terminal, it says so.
Install & open the session Terminal
One package. Then type crossdeck to open the session — the working environment.
npm install -g @cross-deck/cli
crossdeck
You'll see the splash with ○ Not signed in and one instruction: sign in.
Sign in In the session
Type login. Your browser opens, you approve on the Crossdeck screen, and the terminal confirms — signed in as you. No password is ever typed into the terminal.
prolend ❯ login
Stand up the project In the session
One command creates the project, creates the app, mints your publishable keys, and prints the snippet to paste. This is the moment you go from nothing to a real project.
prolend ❯ init --name "ProLend" --platform web --domain app.prolend.com
It prints your proj_… id, your app_… id, a live and a test key, and the exact code to paste next. Your new project is now the active one (it shows in the prompt).
Turn on identity in your app Your app's code
Paste the snippet init gave you into your web app, and wire identify() to your own login. This is the moat: from here, every event, error, and dollar joins to the real person, not an anonymous blob.
import { Crossdeck } from "@cross-deck/web";
Crossdeck.init({ publishableKey: "cd_pub_live_…" });
// after your user signs in, tell Crossdeck who they are:
await Crossdeck.identify(currentUser.id);
Deploy your app as normal. The first page load self-registers your domain — you don't hand-configure any allowlist. Watch it arrive live with analytics back in the session.
Connect a payment rail Dashboard
Payment rails connect through a one-time secure handshake in the dashboard — not a terminal command, because it grants long-lived access that belongs behind an explicit click. Open app.cross-deck.com, go to Payment rails (bottom bar) or Settings → Connected accounts, choose your rail (e.g. Stripe), and approve. Revenue now flows in — and because identity is already wired, it joins to the same people.
See it all working In the session
Back in the terminal session, read the facts. These are the same REST APIs your own code can call — here they're one word each.
prolend ❯ revenue # cash coming in, by person
prolend ❯ people # who you're identifying + their journeys
prolend ❯ analytics # traffic & where signups come from
Make production errors readable CI / build
Optional but recommended. So a crash in production shows the original file:line:function instead of minified soup, upload your source maps from CI — the key-based family, no login needed. This is what the dashboard's Errors tab means by "install the CLI."
crossdeck sourcemaps upload --release v1.0.0 \
--url-prefix https://app.prolend.com/static/js/ ./dist
Lock it down Dashboard + session
Every machine you sign in appears in Settings → Developer → Connected apps, revocable in one click — the answer to a lost laptop. From the terminal, logout revokes this machine's session server-side.
That's the whole arc. You just touched several parts of Crossdeck at once — here's what each did:
identify() joins every event and dollar to the real person — step 4. The moat.Every step above is also a plain command, no session needed — crossdeck login, crossdeck init …, crossdeck revenue. Use the session when you're working by hand; use one-shot commands in scripts and CI. Same engine, either way.
Two families, one binary
There are two ways to authenticate, for two different callers. Keeping them distinct is deliberate — a human at a keyboard and a CI runner have opposite needs.
| Family | Who it's for | Credential | Commands |
|---|---|---|---|
| Account (OAuth) | You, at a terminal | Browser sign-in → a short-lived workspace token (cd_wk_live_…), stored in your keychain file. No secret ever pasted. |
login, whoami, logout, init, projects, apps, use, revenue, analytics, errors |
| CI / source maps | Build pipelines (no browser) | A project secret key (cd_sk_live_…) in an env var. No login step. |
sourcemaps upload (alias upload-sourcemaps), doctor |
The Errors tab in the dashboard tells you to install the CLI to resolve minified stack traces. That's this same binary — the CI / source-maps family. It's key-based and never signs in, so it's independent of your interactive account session. See Source maps (CI).
Install
A normal npm package. Install it globally for interactive use; use npx in CI so the runner never depends on a pre-installed binary.
Global install
npm install -g @cross-deck/cli
Provides a crossdeck binary on your PATH. Verify with crossdeck --version (prints 1.4.0).
One-shot via npx
npx @cross-deck/cli sourcemaps upload --release v1.2.3 --url-prefix https://app.example.com/static/js/ ./dist
Requirements
- Node.js ≥ 18. Uses the native
fetch; nonode-fetchdependency. - One runtime dependency.
commanderfor argument parsing.
@cross-deck with a hyphen.
Not @crossdeck. If npm install errors with "package not found," the scope is the cause.
Sign in
crossdeck login runs the standard OAuth flow: it opens your browser, you approve on the Crossdeck consent screen, and the CLI receives a short-lived workspace token. Under the hood it's RFC 8252 loopback + PKCE (S256) — the CLI binds a one-shot listener on 127.0.0.1, never sees your password, and never receives a long-lived secret.
crossdeck login
| Flag | Description |
|---|---|
--read-only | Request read-only scope — no project / app / key creation. Good for a machine that should only ever read the facts. |
--scope <scope> | Override the exact space-separated OAuth scope to request (advanced). |
--no-browser | Print the sign-in URL instead of launching a browser — for headless / remote machines. Paste it into any browser and the loopback still completes. |
--base-url <url> | Crossdeck API base URL. Defaults to https://api.cross-deck.com. |
The rotating refresh token is written to ~/.crossdeck/credentials.json with 0600 permissions (owner read/write only). The 1-hour access token is never persisted — every command trades the refresh token for a fresh one and rotates it. See Sessions & sign-out.
login.
A pipeline has no browser. For CI, use the key-based source-maps family with a cd_sk_live_… secret key in an env var. The account family is for humans.
Zero to installed — crossdeck init
One command takes a signed-in account from nothing to a working install: it creates a project, creates an app, mints the app's publishable keys, seeds origins (or lets them self-learn), and prints the SDK snippet to paste.
crossdeck init --name "ProLend" --platform web --domain app.prolend.com
| Flag | Description |
|---|---|
-n, --name <name> | Project name. |
-P, --platform <platform> | App platform: web, ios, or android. Default web. |
--domain <domain> | Web app domain. Optional — web origins self-learn from the first heartbeat (see below). |
--bundle-id <id> | iOS bundle id (for --platform ios). |
--package-name <name> | Android package name (for --platform android). |
--env-file [path] | Write the publishable keys to an env file (default .env). |
--base-url <url> | Crossdeck API base URL. |
A new web app starts with an empty origin allowlist. The first heartbeat the SDK sends learns the calling origin and registers the correct registrable-domain wildcard (*.prolend.com, not the exact tenant subdomain), then admits that first beat. Pass --domain / --origin only if you want it seeded up front.
Projects & apps
The pieces init orchestrates are also available directly, for adding a second project or a second app to an existing one. All writes go through the audited provisioning gate — the workspace token's scope is the boundary, and every create is recorded.
crossdeck projects
| Command | Description |
|---|---|
projects create -n <name> | Create a project. Options: --business-model <model> (e.g. subscription), --activate to make it the active project, --json. |
projects list | List the projects you own. --json for the raw envelope. |
crossdeck apps
| Command | Description |
|---|---|
apps create -P <platform> | Create an app and mint its first publishable keys. Options: -p, --project <id> (defaults to active), --domain, --bundle-id, --package-name, --origin <origin...> to seed web origins now, --json. |
apps list | List apps — all, or one project's with -p, --project <id>. --json supported. |
crossdeck use
Set — or, with no argument, show — the active project. Every command that takes -p, --project falls back to this, so you set it once and stop repeating yourself.
crossdeck use proj_prolend # make it active
crossdeck use # show the current one
Monitor the REST APIs
The read hat. These call the same /v1 REST APIs your own code would, and print the facts. Every number is self-describing — it carries what it measures and how much it covers — so a count of actors is never quietly reported as a count of customers. Pass --json to get the raw envelope for scripting; omit it for the rendered readout.
| Command | Reads | Notes |
|---|---|---|
crossdeck revenue |
GET /v1/revenue |
Recognised cash for the project. -p, --project, --json. |
crossdeck analytics |
GET /v1/acquisition |
Signup acquisition sources. -p, --project, --json. |
crossdeck errors -i <fingerprint> |
GET /v1/errors |
One error issue stitched to the moat — who it hit, how many of them pay. --issue is the fingerprint from the Errors tab. -p, --project, --json. |
The account family reads your live workspace; it cannot change anything. Where a metric isn't instrumented yet, the CLI says so — it never prints 0 for a blind spot. Payment rails (Stripe and the rest) connect through a separate OAuth flow in the dashboard, not a CLI command.
Source maps (CI)
The CI family — key-based, no login. Upload .map files from a production build so the dashboard resolves minified frames back to original file:line:function. This is what the Errors tab means by "install the CLI."
crossdeck sourcemaps upload --release v1.2.3 \
--url-prefix https://app.example.com/static/js/ ./dist
Authenticate with a secret key in an env var — the same CROSSDECK_SECRET_KEY every Crossdeck server SDK reads (or pass -t, --auth-token). The environment (sandbox vs production) is inferred from the key prefix.
| Command | Description |
|---|---|
sourcemaps upload <dist-dir> | Walk a build dir, pair .js with .map, POST in batches of ≤100 to /v1/releases/sourcemaps. Requires -r, --release and -u, --url-prefix. Options: -e, --environment, -t, --auth-token, -p, --project, --base-url, -v, --verbose. |
upload-sourcemaps <dist-dir> | Permanent alias for sourcemaps upload — the name already shipped in the Errors tab instructions. Identical behaviour. |
doctor | Validate auth token, environment, and API reachability without uploading anything. CI-friendly exit codes. |
The full source-map workflow — bundler config, URL-prefix schemes, running alongside Sentry — lives in the Source maps reference.
Platforms & environments
Crossdeck is multi-platform. The CLI provisions and reads across every runtime the platform supports, and every app carries both a live and a test publishable key so you never mix production and sandbox traffic.
Web
Livecrossdeck init -P web. Origins self-learn from the first heartbeat; seed with --domain / --origin.
iOS
Livecrossdeck init -P ios --bundle-id com.you.app. Device UID is keychain-anchored by the SDK.
Android
Soon-P android --package-name com.you.app provisions today; the Android SDK follows.
| Environment | Publishable key prefix | Used for |
|---|---|---|
production | cd_pub_live_… | Real traffic. Minted alongside every app. |
sandbox | cd_pub_test_… | Test traffic. Minted alongside every app. |
Crossdeck supports many payment rails (Stripe, and more). You connect a rail once, through its own OAuth handshake in the dashboard — the CLI reads the revenue that flows from it, but it does not connect rails. That boundary is deliberate: connecting a rail grants long-lived access, which belongs behind the dashboard's explicit consent, not a terminal flag.
Sessions & sign-out
crossdeck whoami shows the active session — the API it targets, the scopes you were granted, and your portfolio size. crossdeck logout ends the session on this machine.
crossdeck whoami
crossdeck logout
Sign-out is a real revocation, not just a local wipe. crossdeck logout revokes this machine's refresh token server-side (RFC 7009) and then removes the local credential file — so a stolen ~/.crossdeck/credentials.json is dead the moment you log out, not merely absent from your disk.
Every CLI sign-in appears in Settings → Developer → Connected apps in the dashboard, with its device, granted scopes, and last-used time. Revoke one there and that machine's next command fails cleanly with "session revoked — run crossdeck login." This is the answer to a lost laptop.
Help & the command tree
crossdeck help prints the full command tree, grouped by the two hats, in the same premium style as the launcher. crossdeck help <command> (or crossdeck <command> --help) drills into one command's flags.
crossdeck help # the whole tree
crossdeck help init # one command's flags
crossdeck init --help # the same, commander-native
| Group | Commands |
|---|---|
| Account | login, whoami, logout |
| Stand up the engine | init, projects create, projects list, apps create, apps list, use |
| Read the facts | revenue, analytics, errors |
| Source maps (CI) | sourcemaps upload, upload-sourcemaps, doctor |
Security
- The key is the boundary. A workspace token carries an explicit scope map. Reads are allowed by scope; every write (create project / app / key) is authorised and audited separately. The CLI never re-implements the gate or widens a token silently.
- No secret ever transits your clipboard.
loginis browser-based PKCE; the CLI receives a rotating refresh token, never your password and never a long-lived secret. - Least privilege on disk. The credential file is
0600; the 1-hour access token is never written to disk. - Revocable everywhere.
logoutrevokes server-side; the dashboard revokes any machine. A lost device is one click from dead. - CI keys stay scoped. Source-map upload needs only a
cd_sk_*secret key; publishablecd_pub_*keys are client-only and are rejected for upload at config-resolve time.
Related
- Web SDK reference — the SDK the CLI provisions keys for.
- Source maps — the full CI upload workflow and bundler config.
- API keys & authentication — publishable vs secret vs workspace tokens, scope, and rotation.
- Create a project — the dashboard equivalent of
crossdeck init. - Source on GitHub — the CLI lives under
sdks/cli/.
Last updated when @cross-deck/cli@1.4.0 shipped (Aug 3, 2026). Two families — account (OAuth) and CI (source maps) — one binary.
Using an AI assistant? Read this page as clean markdown — index.md — or the whole docs index at /docs/llms.txt.