Skip to Content
We are live but in Staging 🎉
CLI GuidePools & Configuration

Pools & configuration

pool

# create — --with-local enables email+password sign-in in the same call dodil appid pool create my-app --display-name "My App" --with-local dodil appid pool list dodil appid pool get my-app # includes live migration status when one is running # partial update: only the documents you pass change; "{}" clears one dodil appid pool update my-app --display-name "My App (EU)" \ --policies '{"cors_allowed_origins":["https://app.example.com"]}' dodil appid pool rotate-keys my-app # new signing key; old key stays in JWKS for cached verifiers dodil appid pool delete my-app --yes # keeps bucket data if the store is a K3 bucket dodil appid pool delete my-app --yes --wipe-bucket-data

pool update takes any of --display-name, --policies, --settings, --branding, --role-catalog (inline JSON, @file, or -). The dedicated settings / branding / roles commands below are ergonomic wrappers over the same documents.

pool test-flow — the headless smoke test

Drives the full authorization-code + PKCE flow — authorize, credential submit, code exchange — without a browser, and prints the resulting tokens:

dodil appid pool test-flow my-app [email protected] 'S3curePass!' \ --redirect-uri https://app.example.com/callback

Use it after every configuration change; it exercises exactly what your app will.

settings

The pool’s behavioral knobs:

dodil appid settings get my-app dodil appid settings set my-app \ --allow-signup=true \ --require-email-verification=true \ --password-min-length 10 \ --access-ttl-secs 900 \ --refresh-ttl-secs 2592000 \ --refresh-reuse-grace-secs 10 \ --redirect-uris "https://app.example.com/callback,http://localhost:5173/callback"
FlagDefaultMeaning
--allow-signuptrueSelf-service signup on the hosted page and /signup endpoint
--require-email-verificationfalseBlock sign-in until the email link is clicked
--password-min-length88–128; the only password rule
--access-ttl-secs900Access-token lifetime
--refresh-ttl-secs30 daysRefresh-family lifetime
--refresh-reuse-grace-secs10Double-submit forgiveness window (0 = strict, max 60)
--redirect-urisThe /authorize allowlist — required for the code flow

branding

One JSON document that themes the hosted login/reset/verify pages and the transactional emails:

dodil appid branding get my-app dodil appid branding set my-app @branding.json
{ "logo_url": "https://cdn.example.com/logo.svg", "colors": { "primary": "#4f46e5", "background": "#ffffff" }, "dark": { "colors": { "background": "#0b0b12" } }, "layout": "card", "copy": { "title": "Sign in to My App" }, "links": { "terms": "https://example.com/terms", "privacy": "https://example.com/privacy" }, "email": { "from_name": "My App", "accent": "#4f46e5" } }

All keys are optional; colors accept #hex / rgb() / hsl(), image URLs must be https. The hosted page picks branding up immediately (it’s served pre-auth from {issuer}/branding). Full schema in the hosted login recipe.

roles

The role → permission catalog, expanded into every token’s permissions[] claim:

dodil appid roles get my-app dodil appid roles set my-app admin=users.write,billing.read editor=posts.write viewer=posts.read dodil appid roles set my-app --file roles.json

Renaming or re-scoping a role here re-shapes future tokens without touching any user.

connection

How users sign in. local (email + password) is the implemented kind:

dodil appid connection add my-app local --enabled dodil appid connection list my-app dodil appid connection remove my-app local --yes

connection add accepts a --config JSON for kinds that take configuration; other kinds (oauth:google, oidc, saml, anonymous) are reserved but not implemented yet — adding them today does not enable a new sign-in method.