Create the first admin
On first boot z4j has no users. It prints a setup URL to stderr inside an ASCII banner:
╔══════════════════════════════════════════════════════════════════════╗║ z4j first-boot setup ║║ ║║ Open this URL in your browser to create the admin: ║║ ║║ http://localhost:7700/setup?token=yAXssHbiYxnJfohZeqOejGA8b14C0mKPEm║║ ║║ Token expires at: 2026-04-23T16:52:27+00:00 (UTC) ║║ Single-use. Restart z4j to generate a new one. ║║ For zero-log-exposure setup, use Z4J_BOOTSTRAP_ADMIN_*. ║╚══════════════════════════════════════════════════════════════════════╝The token is a one-shot urlsafe-random string valid for 15 minutes, stored hashed. Visit the URL.
If the token expired or you closed the terminal, restart z4j serve. Every
start with an empty users table replaces the pending token and prints a fresh
banner. If you specifically need to clear the pending token first, run:
z4j reset-setup --forcereset-setup --force resolves the configured SQLite or PostgreSQL database,
deletes pending setup tokens, preserves existing signed setup audit rows, and
appends a signed setup.tokens_reset audit row. It does not print a URL; start
the brain to mint a replacement token. The command refuses with exit 2 once
any user exists. Without --force, it also exits nonzero without changing the
database.
Setup form
Section titled “Setup form”The setup page asks for:
- Email - becomes the admin username.
- Display name - optional.
- Password - minimum 12 characters by default
(
Z4J_PASSWORD_MIN_LENGTH, configurable down to 8), maximum 256, and checked against the common-password denylist. Passwords under 16 characters must use at least 3 of 4 character classes (lowercase, uppercase, digits, symbols; whitespace is not a symbol). See password policy.
On submit, z4j:
- Creates a global admin user and grants the project role
admin(there is noownerrole). - Creates the first project with the fixed slug
defaultand nameDefault. - Invalidates the setup token (one-shot).
- Signs you in and redirects to the dashboard home.
Bootstrap without the setup URL
Section titled “Bootstrap without the setup URL”For IaC pipelines that cannot read a browser setup URL, set Z4J_BOOTSTRAP_ADMIN_EMAIL + Z4J_BOOTSTRAP_ADMIN_PASSWORD before first boot. z4j provisions the admin automatically and the setup banner is suppressed. See env vars.
Equivalent CLI form for first-boot provisioning:
# In automation, feed stdin from a protected file or secret mount: < /run/secrets/z4j_admin_passwordWhat to do next
Section titled “What to do next”- Mint an agent token - go to
/projects/{slug}/agentsin the dashboard, click new agent, and copy both thetokenandhmac_secretbefore closing. The bearer token cannot be recovered. The HMAC secret is derived per project, so every agent in that project shares it and minting another agent shows the same value again; revoking one agent does not rotate it. - Install the agent - see the install guide and pick the framework + engine combo that matches your app.
- Wire it up - Django quickstart, Flask, FastAPI, or bare Python.
- Invite your team - Settings, Memberships, Invite. The mint dialog always displays the single-use invite link, so copy it before closing. With an active email notification channel z4j also attempts to mail it, but the UI does not report whether that send succeeded. See SMTP presets.
Losing admin access
Section titled “Losing admin access”If an active admin still exists but its password is lost, use the operator-side password reset against the same database as the brain:
This does not require an admin login and invalidates that user's existing
sessions. The Z4J_BOOTSTRAP_ADMIN_* variables and the bootstrap-admin /
createsuperuser commands are first-boot provisioning paths: they run only
while the users table is empty and cannot recover a populated installation.
If no active admin remains, restore a known-good backup or obtain supported
recovery help rather than editing password_hash by hand.
Production deployments should always have at least two admins.