Command-line tool for dashboard user administration and ad hoc D1 queries against the Legaciti monorepo.
The Legaciti CLI (legaciti) lives in the monorepo directory cli/ (package @legaciti/cli). It targets the dashboard worker (for example https://my.legaciti.org) for user operations and optional direct D1 access.
Running the CLI
Section titled “Running the CLI”From the repository root:
pnpm cli -- --helpThat runs the CLI in development mode via tsx. To use the compiled binary after a build:
pnpm -C cli buildpnpm -C cli exec legaciti --helpGlobal options:
| Option | Description |
|---|---|
-h, --help | Show help for the program or a subcommand |
-V, --version | Print the CLI version |
Configuration
Section titled “Configuration”Environment variables are read from, in order: the repository root .env, the current working directory .env, and cli/.env (if present). Copy cli/.env.example to cli/.env (or merge into the root .env) as a starting point.
| Variable | Required for | Description |
|---|---|---|
BASE_URL | User API commands | Dashboard origin (default http://localhost:5173). Example: https://my.legaciti.org. Alias: LEGACITI_BASE_URL. |
ADMIN_CLI_SECRET | users list, users create, users edit, users delete | Bearer token shared with the Worker (ADMIN_CLI_SECRET secret / .dev.vars). |
RESET_PASSWORD_REDIRECT_TO | Optional for users reset-password | Default redirect URL embedded in the reset email. Must match a Better Auth trustedOrigins entry on the dashboard (for example https://my.legaciti.org/reset-password). |
CLOUDFLARE_ACCOUNT_ID | d1 query --http | Cloudflare account ID |
CLOUDFLARE_API_TOKEN | d1 query --http | Cloudflare API token with D1 (and any other) permissions — same name as Worker / Drizzle. |
D1_DATABASE_ID | d1 query --http | UUID for DB_0 (publications-db-0); see apps/dashboard/wrangler.jsonc |
D1_DATABASE_NAME | d1 query (wrangler mode) | Database name passed to wrangler d1 execute (default publications-db-0) |
Set the Worker secret from apps/dashboard:
pnpm exec wrangler secret put ADMIN_CLI_SECRETFor local development, add the same name and value to apps/dashboard/.dev.vars.
Command: users
Section titled “Command: users”Parent command:
legaciti users --helpAll users subcommands except reset-password require ADMIN_CLI_SECRET and call the dashboard JSON API at /api/cli/users with Authorization: Bearer <ADMIN_CLI_SECRET>.
users list
Section titled “users list”Prints every row from app_users (email, display name, superadmin flag, id) as a table.
pnpm cli -- users listAPI: GET /api/cli/users → response body { "users": [ … ] }.
users create
Section titled “users create”Interactive prompts: email, then whether the user should be a superadmin. Inserts into app_users (same semantics as the dashboard admin flow).
pnpm cli -- users createAPI: POST /api/cli/users with JSON body { "email": "<email>", "is_superadmin": <boolean> } (validated with AdminUserSchema).
users edit
Section titled “users edit”Interactive prompts: user email to update, then new superadmin yes/no. Updates is_superadmin (and updated_at) for that primary_email.
pnpm cli -- users editAPI: PATCH /api/cli/users with JSON body { "email": "<email>", "is_superadmin": <boolean> } (email required; is_superadmin optional in the schema but the CLI always sends a value).
users delete
Section titled “users delete”Interactive prompts: user email, then confirmation. Removes workspace_memberships for that app user and deletes the app_users row.
pnpm cli -- users deleteAPI: DELETE /api/cli/users?email=<url-encoded-email>.
users reset-password
Section titled “users reset-password”Interactive prompts: account email, then reset redirect URL (defaults to RESET_PASSWORD_REDIRECT_TO or <BASE_URL>/reset-password). Does not use ADMIN_CLI_SECRET; it calls Better Auth’s HTTP handler.
pnpm cli -- users reset-passwordAPI: POST /api/auth/request-password-reset with JSON { "email": "<email>", "redirectTo": "<absolute-url>" }. The redirectTo URL must be allowed by the dashboard’s Better Auth trustedOrigins configuration.
Command: d1
Section titled “Command: d1”Run raw SQL against the dashboard’s DB_0 database (auth and app metadata shard). Use read-only queries when possible; writes can affect production data.
Parent help:
legaciti d1 --helpd1 query
Section titled “d1 query”legaciti d1 query "<sql>" [options]| Option | Description |
|---|---|
--http | Use Cloudflare’s D1 HTTP API instead of Wrangler. Requires CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_API_TOKEN, and D1_DATABASE_ID. |
--local | With the default Wrangler mode, run against local D1 (omit --remote). |
--cwd <dir> | Working directory for pnpm exec wrangler (defaults to the current directory). Run from the monorepo root so wrangler resolves via the workspace. |
Default mode (no --http): runs:
pnpm exec wrangler d1 execute <D1_DATABASE_NAME> --remote --json --command "<sql>"
Examples:
# Remote D1 via wrangler (from repo root)pnpm cli -- d1 query "SELECT COUNT(*) AS n FROM app_users"
# Cloudflare HTTP APIpnpm cli -- d1 query "SELECT name FROM sqlite_schema WHERE type='table'" --httpHTTP API summary (/api/cli/users)
Section titled “HTTP API summary (/api/cli/users)”These routes are implemented on the dashboard worker and are intended for operator automation (including this CLI).
| Method | Path | Auth | Description |
|---|---|---|---|
GET | /api/cli/users | Bearer ADMIN_CLI_SECRET | List app_users |
POST | /api/cli/users | Bearer | Create user |
PATCH | /api/cli/users | Bearer | Update superadmin flag |
DELETE | /api/cli/users?email= | Bearer | Delete user and memberships |
If ADMIN_CLI_SECRET is not configured on the Worker, these endpoints respond with 503 and a JSON error body.
See also
Section titled “See also”- Authentication — session and API patterns for the dashboard
- Operations runbook — related operational procedures
- Deploy workers — shipping the dashboard worker that serves
/api/cli/users