CLI

Configuration & authentication

How the CLI authenticates — Deploy Tokens vs. dashboard JWTs, browser and CI login, the sankofa.yaml project file, environment variables, and credential resolution order.

The CLI needs two things before it can publish: who you are (authentication) and which project + environment you are shipping to. This page covers both, plus the sankofa.yaml file that Flutter Deploy reads at runtime.

Two credential types

Sankofa uses two different tokens for two different classes of command. Using the wrong one is the single most common auth error.

Deploy Tokensk_deploy_…
Publishing credential. Used by release, patch, deploy, status, preview, dist, submit. Scoped to one project. Mint one from the dashboard's Deploy tokens panel, or let sankofa login create one for you.
Dashboard JWTsession token
Full user session with project-role RBAC. Used by flags, config, catch, and demo — commands that read and write dashboard resources, not just deploy artifacts.

Log in

Browser login (interactive)

The default flow opens your browser, authenticates against your Sankofa account, lets you pick an organization + project, and mints a local Deploy Token bound to that project.

bash
sankofa login

It prompts for the API endpoint (default https://api.sankofa.dev), opens a login page, and waits for the callback. On success it caches your credentials locally and, if the current directory is a Sankofa project, backfills the empty app_id / api_key fields in sankofa.yaml.

bash
sankofa login --project    # save to .sankofa.json in this project instead of global config
sankofa login --endpoint https://api.sankofa.dev

Deploy Token login (CI/CD)

For headless environments, authenticate directly with a pre-minted Deploy Token and a project ID — no browser round-trip.

bash
sankofa login --deploy-token sk_deploy_xxxxxxxx --project-id proj_xxxxxxxx

The token must start with sk_deploy_. The project ID can also come from the SANKOFA_PROJECT_ID environment variable. The CLI validates the token against the deploy API and records whether it belongs to the live or test environment.

Log out and switch projects

bash
sankofa logout             # clear both project + global scopes
sankofa logout --project   # clear the project-scoped credentials only
sankofa switch             # change the active project / environment without re-auth

sankofa switch reuses your existing sign-in, so it can list your projects and switch without another browser trip.

Credential resolution order

Every authenticated command resolves credentials from the following sources, highest priority first:

  1. Environment variables

    SANKOFA_DEPLOY_TOKEN (deploy auth), SANKOFA_JWT (dashboard auth), SANKOFA_PROJECT_ID, SANKOFA_ENDPOINT, SANKOFA_ENVIRONMENT. SANKOFA_API_KEY is accepted as an alias for SANKOFA_DEPLOY_TOKEN.

  2. Project config

    Per-project settings written by sankofa init / sankofa login — project ID, endpoint, environment. Never holds a login token.

  3. Global login

    Your saved account sign-in from sankofa login.

If nothing resolves, the command exits with a prompt to run sankofa login. The endpoint defaults to https://api.sankofa.dev and the environment defaults to live when unset.

Environment variables

VariablePurpose
SANKOFA_DEPLOY_TOKENDeploy auth token for release / patch / status / preview / dist / submit.
SANKOFA_JWTDashboard JWT for flags / config / catch / demo.
SANKOFA_PROJECT_IDProject ID (proj_…).
SANKOFA_ENDPOINTAPI base URL. Defaults to https://api.sankofa.dev.
SANKOFA_ENVIRONMENTlive or test. Defaults to live.
SANKOFA_ENGINE_VERSIONOverride the Sankofa Flutter engine version the build resolves.
SANKOFA_HOMEOverride the cache root (default ~/.sankofa). Useful to isolate CI caches.
SANKOFA_NO_UPDATE_CHECKSet to 1 to silence post-command update notices.

The sankofa.yaml project file (Flutter)

Flutter Deploy projects carry a sankofa.yaml at the project root. It is bundled as a Flutter asset and read at runtime by the SDK, so the app knows which project it belongs to and which server to talk to. sankofa init --deploy creates it; sankofa login fills the identity fields.

YAML
# sankofa.yaml — read at runtime from the asset bundle.
app_id: proj_xxxxxxxx        # your Sankofa project ID
api_key: sk_live_xxxxxxxx    # publishable runtime key (sent as x-api-key by the app)
# base_url: https://api.sankofa.dev   # only when self-hosting a non-default endpoint
engine_version: 3.44.1+sankofa-2      # written by 'sankofa engine install' / 'upgrade'
# signing_pubkey: <base64>            # paste the key printed by 'sankofa keys generate'
app_idstringRequired
Your Sankofa project ID (proj_…). sankofa login fills this from the project you select.
api_keystringRequired
The project's publishable runtime key (sk_live_… or sk_test_…). The app sends it to the API as the x-api-key header. It is a client-embedded key by design, like a Firebase or Stripe publishable key.
base_urlstring?default https://api.sankofa.dev
Only written when your endpoint differs from the default (self-hosted / regional). Omitted for the standard cloud.
engine_versionstring?
The pinned Sankofa Flutter engine version (e.g. 3.44.1+sankofa-2). Written by sankofa engine install and re-written by sankofa engine upgrade.
signing_pubkeystring?
The base64 Ed25519 public key patches are signed with. sankofa keys generate prints it; you paste it here (or pass it to Sankofa.initialize(deploySigningPubkey:)). The SDK verifies every patch against it before applying.

The engine pin is also mirrored to .sankofa/flutter-version. sankofa release, sankofa patch, and sankofa preview read the pin automatically, so every build uses the engine your project is locked to.

What's safe to commit — and what to protect

  • Safe to commit: .sankofa.json and sankofa.yaml carry your project ID, endpoint, and the publishable runtime key (api_key, sent as x-api-key — a client-embedded key by design, like a Firebase or Stripe publishable key). Neither file holds a login token.
  • Never commit: your account login (created by sankofa login) and your patch-signing private key (created by sankofa keys generate). Losing the signing key means you can't sign future patches; leaking it means someone else could — back it up somewhere safe and manage it with sankofa keys.
  • Engine binaries and other CLI state live under a local cache root you can relocate with SANKOFA_HOME (handy for isolating CI caches). | ~/.sankofa/flutter/<version>/ | Bundled Sankofa Flutter SDK per engine version. |

Next steps

Edit this page on GitHub