Skip to content

Auth (OTP signup & login)

codika-os authenticates via a two-step OTP flow from the terminal. No browser round-trip required.

There are two forks: signup (new email) and login (existing account on a new machine). Both forks have the same shape: a *-request command that emails a 6-digit code, then a *-complete command that consumes the code and mints a cos_… key.

Terminal window
codika-os auth signup-request --email you@codika.io

Output:

✓ OTP sent
Email: you@codika.io
Expires: in 10 minutes
Resend: not before 30 seconds

A 6-digit code arrives at you@codika.io. Then:

Terminal window
codika-os auth signup-complete --email you@codika.io --code 123456

Output:

✓ Signup complete
Email: you@codika.io
Profile: you (now active)
API key: cos_xxxx... (scopes: all)
Try it: codika-os whoami

codika-os has no organization concept. The API key is owned by the worker email — there’s no --company, --brand-*, or --tone to pass.

The cos_… key is now stored in ~/.codika-os/config.json (mode 0600) as the active profile.

Same two steps, different commands:

Terminal window
codika-os auth login-request --email you@codika.io
codika-os auth login-complete --email you@codika.io --code 123456

The /codika-os:setup-codika-os skill handles this automatically. If you’re running the CLI by hand:

  • Never used codika-os? → signup-request / signup-complete.
  • Used it before, just on a different machine? → login-request / login-complete.
  • Not sure? → Try signup first; if the email already has dashboard access, the signup endpoint still works and reports isNewUser: false. Use login when you only need a fresh key.

Auth always reads PROD. OTPs, API keys, and dashboard_access rows all live in PROD regardless of which mode the CLI is syncing tracking data to. Admins grant access via PROD’s dashboard_access table.

no_dashboard_access on login? Your email doesn’t have a row in PROD’s dashboard_access table. Ask an admin to invite you, then re-run login-request.

Every auth … error returns a JSON shape (with --json) like:

{
"success": false,
"error": {
"code": "OTP_EXPIRED",
"message": "The code expired. Request a new one.",
"nextAction": "codika-os auth signup-request --email you@codika.io"
}
}
CodeWhat it meansnextAction
OTP_NOT_FOUNDNo active OTP for that emailRun *-request again
OTP_EXPIREDThe code’s 10-minute window passedRun *-request again
OTP_CONSUMEDThe code was already usedRun *-request again
OTP_MISMATCHWrong codeRe-enter — counts against the 5-attempt lockout
OTP_LOCKED5 failed attemptsWait, then *-request again
OTP_RESEND_COOLDOWNLess than 30s since last *-requestWait, then retry
no_dashboard_accessLogin attempted, but no dashboard_access row exists for this email in PRODAsk an admin to invite the email, then re-run login-request
domain_not_allowedNon-@codika.io emailUse a Codika email
internal_errorServer-side failureSurface the message and retry

The nextAction string is designed to be acted on programmatically. Pass it through to the user verbatim — it tells them (or the agent) exactly what to run next.

After auth, sanity-check the active key:

Terminal window
codika-os whoami
codika-os verify

whoami reads the local config. verify round-trips the key against /api/auth/cli/verify on the app, confirming it’s still valid server-side.

Sign in to a second org or a dev environment without overwriting the active key:

Terminal window
codika-os auth login-request --email you@codika.io --profile dev-local
codika-os auth login-complete --email you@codika.io --code 123456 --profile dev-local
codika-os use dev-local

See configuration for the profile resolution chain.

Implementation: codika-os-cli/src/cli/commands/auth/. Server endpoints: codika-os-app/src/lib/server/cli-auth.ts.