The Salesprompter app code is not in this repository, but the CLI makes its expectations very clear. This page documents the app-side contract that the rest of the universe depends on.
The app is the identity source of truth
The app should own:
- user identity
- session initiation
- CLI device login
- fallback direct CLI token issuance
- token verification for
auth:whoami --verify
The CLI and Chrome extension should not create separate credential systems. A single user should have one coherent identity across the app, CLI, and extension.
Required backend endpoints
The CLI expects these backend routes:
| Method | Path | Purpose |
|---|---|---|
POST |
/api/cli/auth/device/start |
Start device login and return the verification details |
POST |
/api/cli/auth/device/poll |
Poll for authorization state until the user completes login |
GET |
/api/cli/auth/me |
Verify the active token and return the normalized user |
The app should also support direct token issuance as a fallback for humans or internal tooling:
| Method | Path | Purpose |
|---|---|---|
POST |
/api/cli/auth/token |
Issue an app-approved CLI bearer token for auth:login --token |
Expected response shapes
Device start
POST /api/cli/auth/device/start should return fields compatible with:
{
"deviceCode": "device-code",
"userCode": "ABCD-EFGH",
"verificationUrl": "https://salesprompter.ai/cli/device?user_code=ABCD-EFGH",
"intervalSeconds": 3,
"expiresInSeconds": 180
}
The CLI also accepts verificationUri in place of verificationUrl.
Device poll
POST /api/cli/auth/device/poll should return one of three states:
Pending:
{
"status": "pending"
}
Denied or expired:
{
"status": "denied"
}
Authorized:
{
"status": "authorized",
"accessToken": "token",
"refreshToken": "optional-refresh-token",
"expiresAt": "2026-03-10T12:00:00.000Z",
"user": {
"id": "usr_123",
"email": "user@example.com",
"name": "Example User"
}
}
Who am I
The CLI normalizes three variants for GET /api/cli/auth/me:
Top-level user:
{
"user": {
"id": "usr_123",
"email": "user@example.com",
"name": "Example User"
},
"expiresAt": "2026-03-10T12:00:00.000Z"
}
Flat user object:
{
"id": "usr_123",
"email": "user@example.com",
"name": "Example User",
"expiresAt": "2026-03-10T12:00:00.000Z"
}
Wrapped in data:
{
"data": {
"user": {
"id": "usr_123",
"email": "user@example.com",
"name": "Example User"
},
"expiresAt": "2026-03-10T12:00:00.000Z"
}
}
App-level invariants
The app should preserve these invariants:
- The same person should resolve to the same identity in app, CLI, and extension.
- CLI verification should always go through
/api/cli/auth/me. - Device flow failure should degrade cleanly to token-based login instead of blocking CLI usage entirely.
- App-issued tokens should be safe to store locally in the CLI session file.
What the app does not currently proxy
This repo does not expect the app to proxy:
- BigQuery queries
- domain-finder candidate selection
- Instantly sync
Those are local CLI responsibilities today. The app may surface or observe those workflows, but the CLI is the execution engine defined in this repository.