Crossdeck Docs
Dashboard

@cross-deck/cli — CLI reference

Reference Current version: 1.4.0 · ~11 min read · Updated Aug 3, 2026

@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.

Session, or one-shot — both work.

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.

State 1 — logged out. One action.
State 2 — logged in. The two hats.
The launcher never computes or advises.

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:

The CLIProvisioned the project, app, and keys, and read the facts — steps 1-3, 6.
Identity (the SDK)identify() joins every event and dollar to the real person — step 4. The moat.
Payment railsStripe (and more) connected once in the dashboard; revenue flows by identity — step 5.
Errors & source mapsThe key-based CI family makes production stack traces readable — step 7.
Prefer one-shot?

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.

FamilyWho it's forCredentialCommands
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
"Install the errors CLI" points here.

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

The npm scope is @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
FlagDescription
--read-onlyRequest 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-browserPrint 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.

CI never runs 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
FlagDescription
-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.
Origins self-seed — you don't hand-configure the allowlist.

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

CommandDescription
projects create -n <name>Create a project. Options: --business-model <model> (e.g. subscription), --activate to make it the active project, --json.
projects listList the projects you own. --json for the raw envelope.

crossdeck apps

CommandDescription
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 listList 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.

CommandReadsNotes
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.
Read-only, and honest about coverage.

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.

CommandDescription
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.
doctorValidate 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

Live

crossdeck init -P web. Origins self-learn from the first heartbeat; seed with --domain / --origin.

iOS

Live

crossdeck 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.

EnvironmentPublishable key prefixUsed for
productioncd_pub_live_Real traffic. Minted alongside every app.
sandboxcd_pub_test_Test traffic. Minted alongside every app.
Payment rails are a connect flow, not a CLI command.

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.

Revoke any machine from the dashboard.

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
GroupCommands
Accountlogin, whoami, logout
Stand up the engineinit, projects create, projects list, apps create, apps list, use
Read the factsrevenue, analytics, errors
Source maps (CI)sourcemaps upload, upload-sourcemaps, doctor

Security


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.