Configuration reference
Piwi is configured entirely through environment variables. It runs with zero configuration out of the box — SQLite and local file storage are created automatically under .data/. Set variables only to change a default.
Variables can go in apps/application/.env (see apps/application/.env.example) or be passed to the container/process. Where a value can also be set in the Settings UI, the environment variable always wins and the UI shows that field read-only.
Prefer a guided setup? The configuration generator builds a ready-to-paste .env, Docker, Kubernetes or systemd configuration from the same registry as this page — entirely in your browser.
Settings UI tooltips
In the dashboard, every overridable setting shows a help icon next to its label. Hover it to see which PIWI_* env var backs the field, a one-line description, and a link back to this page. Fields that are currently pinned by the environment show a lock badge with the variable name, and the Settings nav marks env-managed pages with a lock icon. This page is generated from the typed registry in apps/application/shared/piwi-env-vars.ts (version 0.25.0), the same source those tooltips use.
General
| Variable | Default | Description |
|---|---|---|
PIWI_SITE_URL | — | Public base URL of the instance (e.g. https://piwi.example.com). Used to build links in emails. When unset, links in emails point to http://localhost:3000 and OAuth callback URLs are inferred from the request host — set it when running behind a reverse proxy. |
PIWI_SECRET_KEY | — | Master key for AES-256-GCM encryption of secrets stored in the database (AI API keys, webhook/SCM secrets). Strongly recommended in production. Falls back to an insecure built-in development key (with a startup warning in production). Generate one with node -e "console.log(require('node:crypto').randomBytes(32).toString('hex'))". |
Database
Piwi uses SQLite by default. Setting PIWI_DATABASE_URL switches it to PostgreSQL; migrations run automatically on startup.
| Variable | Default | Description |
|---|---|---|
PIWI_DATABASE_PATH | .data/piwi.db | Path to the SQLite database file (used when PIWI_DATABASE_URL is not set). |
PIWI_DATABASE_URL | — | PostgreSQL connection string. When set, PostgreSQL is used instead of SQLite and migrations run automatically on startup. See details. |
PIWI_RETENTION_DAYS | — | Days of test-run history the nightly retention sweep keeps. Unset or 0 disables automatic run pruning (the default — pruning is opt-in). See details. |
PIWI_RETENTION_NOTIFICATION_DAYS | 30 | Days to keep sent/failed notification outbox rows before the nightly sweep prunes them (default 30; 0 keeps them forever). |
PIWI_RETENTION_DIAGNOSIS_VERSIONS | 20 | AI-diagnosis history versions kept per diagnosis by the nightly sweep (default 20; 0 disables capping). |
See Database for SQLite versus PostgreSQL and Storage → Data retention for how the nightly sweep works.
Storage
Controls where test artifacts (HTML reports, traces, attachments) are stored.
| Variable | Default | Description |
|---|---|---|
PIWI_STORAGE_TYPE | local | Storage backend for test artifacts (HTML reports, traces, attachments): "local" or "s3". Only the exact value s3 selects S3; any other value falls back to local storage. |
PIWI_STORAGE_PATH | .data/storage | Directory for local file storage (when PIWI_STORAGE_TYPE is "local"). |
PIWI_S3_BUCKET | — | S3 bucket name for artifact storage (when PIWI_STORAGE_TYPE is "s3"). See details. |
PIWI_S3_REGION | — | S3 bucket region (when PIWI_STORAGE_TYPE is "s3"). |
PIWI_S3_ACCESS_KEY_ID | — | S3 access key id with write access to the bucket. |
PIWI_S3_SECRET_ACCESS_KEY | — | S3 secret access key. |
PIWI_S3_ENDPOINT | — | Custom endpoint for S3-compatible services (MinIO, R2, Spaces). |
PIWI_S3_FORCE_PATH_STYLE | — | Use path-style addressing (required by some S3-compatible services). Defaults to on when a custom endpoint is set, off otherwise; only the exact value false turns it off explicitly. |
Full details and IAM examples: Storage configuration.
Authentication
Authentication is optional and off by default. When disabled, all endpoints behave as a single virtual administrator.
| Variable | Default | Description |
|---|---|---|
PIWI_AUTH_ENABLED | false | Set to "true" to enable role-based access control and API keys. Off by default. |
PIWI_AUTH_SECRET | — | Secret used to sign/encrypt session cookies. Required when PIWI_AUTH_ENABLED is true. The server refuses to start when auth is enabled and this is unset. |
PIWI_SHARE_LINKS_ENABLED | false | Set to "true" to allow minting read-only public share links for executions and failure clusters. Off by default; turning it off again immediately dead-ends every outstanding link without deleting anything. Added in 0.26.0. |
PIWI_SHARE_LINK_MAX_TTL_DAYS | 30 | Longest allowed share-link lifetime, in days. The creation dialog offers expiries up to this; 0 lifts the cap and allows links with no expiry. Added in 0.26.0. |
PIWI_TRUST_PROXY | false | Set to "true" when a reverse proxy sits in front of Piwi, so per-IP rate limits on the auth endpoints key on the client address your proxy appends to X-Forwarded-For instead of on the proxy's own address (which would pool every client into one bucket). Leave off when clients connect directly: the header is client-controlled then, and trusting it would let a caller choose its own bucket. Added in 0.26.0. |
PIWI_OAUTH_GOOGLE_CLIENT_ID | — | Google OAuth client id (optional single sign-on). See details. |
PIWI_OAUTH_GOOGLE_CLIENT_SECRET | — | Google OAuth client secret. |
PIWI_OAUTH_GITHUB_CLIENT_ID | — | GitHub OAuth client id (optional single sign-on). See details. |
PIWI_OAUTH_GITHUB_CLIENT_SECRET | — | GitHub OAuth client secret. |
PIWI_OAUTH_ALLOWED_DOMAINS | — | Comma-separated verified email domains allowed to sign in via OAuth (all providers). Only verified emails in these domains are accepted. Empty means no domain restriction. |
PIWI_OAUTH_GITHUB_ALLOWED_ORGS | — | Comma-separated GitHub org logins a user must belong to (requests read:org scope). |
Behind a reverse proxy, set
PIWI_SITE_URLso the OAuthredirect_uriis built from your public URL and matches what you registered with the provider (instead of being inferred from the requestHost).
See Authentication for roles, API keys, and project assignments.
Wasted time
Controls which Playwright wait steps are counted as "wasted time" on the run timeline and in per-test/run totals. Classification happens when a run is viewed, so changing it re-classifies historical runs immediately.
| Variable | Default | Description |
|---|---|---|
PIWI_WASTED_WAIT_PATTERNS | Wait for timeout*,*waitForTimeout* | Glob patterns (comma or newline separated) defining which wait steps count as wasted time. Locks the UI when set. Case-insensitive globs (* and ?) matched against a wait step’s title or source location. Use * to count every wait. |
When unset, configure the patterns from Settings → Wasted time (administrator only). The default counts only explicit waitForTimeout sleeps, since framework-injected waits (load-state, wait-for-function) are usually unavoidable.
AI diagnosis
PIWI_AI_PROVIDER is the master switch: when it is set, AI configuration is environment-managed (the Settings UI shows the fields read-only) and the other PIWI_AI_* variables apply. When it is unset, AI diagnosis is configured from Settings → AI instead and the variables below are ignored.
| Variable | Default | Description |
|---|---|---|
PIWI_AI_PROVIDER | — | AI provider for failure diagnosis: "anthropic" or "openai" (OpenAI-compatible). |
PIWI_AI_API_KEY | — | API key for the diagnosis provider. Takes precedence over the DB-stored key. Optional for OpenAI-compatible providers that need no key (e.g. a local model). |
PIWI_AI_MODEL | — | Diagnosis model name (default: claude-opus-4-8 for Anthropic). |
PIWI_AI_BASE_URL | — | Base URL for OpenAI-compatible providers (e.g. http://localhost:11434/v1). |
PIWI_AI_AUTO_DIAGNOSE | false | Set to "true" to auto-diagnose new failure clusters when a run finishes. |
PIWI_AI_AUTO_DIAGNOSE_MAX | 3 | Max clusters auto-diagnosed per finished run (budget cap; default 3). |
PIWI_AI_RESEARCH_PROVIDER | — | Provider for the optional research (pre-analysis) stage. Falls back to PIWI_AI_PROVIDER. |
PIWI_AI_RESEARCH_MODEL | — | Cheaper/faster model for the research stage. Empty disables the two-stage pipeline. |
PIWI_AI_RESEARCH_BASE_URL | — | Base URL for the research-stage provider. Falls back to PIWI_AI_BASE_URL. |
PIWI_AI_RESEARCH_API_KEY | — | API key for the research-stage provider. Falls back to PIWI_AI_API_KEY. |
PIWI_AI_EMBEDDING_PROVIDER | — | Provider for embeddings (semantic failure clustering). Falls back to PIWI_AI_PROVIDER. Must resolve to an OpenAI-compatible provider — Anthropic has no embeddings API — so the fallback only helps when the main provider is "openai". |
PIWI_AI_EMBEDDING_MODEL | — | Embedding model name (e.g. text-embedding-3-small). Empty disables semantic clustering (and the embedding fallbacks). |
PIWI_AI_EMBEDDING_BASE_URL | — | Base URL for the embedding provider. Falls back to PIWI_AI_BASE_URL. |
PIWI_AI_EMBEDDING_API_KEY | — | API key for the embedding provider. Falls back to PIWI_AI_API_KEY. |
See AI diagnosis for how diagnosis, the research stage, and semantic clustering work.
AI context limits
Cap how much evidence (and how many tokens) go into each AI diagnosis. Resolution order: defaults ← values stored from Settings → AI ← environment; the environment wins and locks the field in the UI. Values are clamped to the min–max range; a 0 disables a section only where the minimum is 0.
| Variable | Default | Description |
|---|---|---|
PIWI_AI_MAX_SAMPLE_ERROR_CHARS | 10000 | Max characters of raw error text (per error block). |
PIWI_AI_MAX_SCM_PATCH_BUDGET | 15000 | Total characters of diff patches across changed files. |
PIWI_AI_MAX_AFFECTED_TESTS | 30 | Max affected tests listed in the diagnosis context. |
PIWI_AI_MAX_STEPS | 50 | Max recent test steps included. |
PIWI_AI_MAX_CONSOLE_ENTRIES | 30 | Max console error/warning entries included. |
PIWI_AI_MAX_CONSOLE_ENTRY_CHARS | 1000 | Max characters per console entry. |
PIWI_AI_MAX_NETWORK_REQUESTS | 25 | Max failed network requests included. |
PIWI_AI_MAX_ARIA_SNAPSHOT_CHARS | 12000 | Max characters of the page ARIA snapshot. |
PIWI_AI_MAX_TEST_SOURCE_CHARS | 8000 | Max characters of the test source snippet. |
PIWI_AI_MAX_SOURCE_FILES | 4 | Max full source files fetched from SCM to ground patches (0 disables). |
PIWI_AI_MAX_SOURCE_FILE_CHARS | 12000 | Max characters per fetched full source file. |
PIWI_AI_MAX_SERVER_LOG_ENTRIES | 50 | Max backend server log entries (from X-Piwi-Logs header) included. |
PIWI_AI_MAX_SERVER_LOG_ENTRY_CHARS | 1000 | Max characters per backend server log entry. |
PIWI_AI_MAX_SERVER_TRACE_SPANS | 40 | Max backend server spans (from X-Piwi-Trace header) included in AI diagnosis (0 disables). Added in 0.16.0. |
PIWI_AI_MAX_STEP_INTENTS | 20 | Max AI-step intent mappings (natural-language prompt → compiled locator) included in a diagnosis (0 disables the section). Added in 0.24.0. |
PIWI_AI_MAX_IMAGES | 5 | Max screenshots auto-included in the diagnosis context. |
PIWI_AI_MAX_PASSED_PEERS | 20 | Max peer tests in the same file listed when they passed. |
PIWI_AI_MAX_CONSOLE_WINDOW | 50 | Max console entries of any type in the window before failure. |
PIWI_AI_SLOW_REQUEST_MS | 1500 | Network request duration (ms) threshold for flagging as slow. |
PIWI_AI_MAX_TRACE_ACTIONS | 10 | Max actions extracted from trace ZIP for failing-action context (0 disables). |
PIWI_AI_TRACE_DOM_CHARS | 6000 | Max characters for the trace-derived DOM/ARIA excerpt in failing-action context. |
PIWI_AI_MAX_TRACE_STACK_FRAMES | 10 | Max call-stack frames (with source windows) from the trace call-stack section (0 disables). |
PIWI_AI_MAX_TRACE_NETWORK_REQUESTS | 20 | Max requests included from the trace network stream (0 disables). |
PIWI_AI_MAX_DOM_SNAPSHOT_CHARS | 8000 | Max characters of the failure-time DOM snapshot rendered from the trace (0 disables). |
PIWI_AI_IMAGE_MAX_EDGE | 1920 | Screenshots are downscaled to at most this many pixels on the long edge before being sent. |
See AI diagnosis → Context limits for section-by-section guidance.
AI steps
Bounds on the reporter's AI-step authoring pass (page.piwiLocator(...) / page.piwiRun(...) in resolve/heal mode), which calls the model through this server. They cap how much of the page snapshot and how many output tokens go into each authoring iteration. They never apply during normal replay runs, which make no model calls. Values are clamped to the min–max range.
| Variable | Default | Description |
|---|---|---|
PIWI_AI_STEP_MAX_SNAPSHOT_CHARS | 24000 | Max characters of the page ARIA snapshot the reporter sends per AI-step authoring iteration. Added in 0.24.0. |
PIWI_AI_STEP_MAX_OUTPUT_TOKENS | 1024 | Max output tokens the model may return per AI-step authoring iteration. Reasoning models count hidden chain-of-thought against this, so raise it (up to 8192) when authoring with one. Added in 0.24.0. |
Reasoning models spend output tokens on hidden chain-of-thought, so raise PIWI_AI_STEP_MAX_OUTPUT_TOKENS for them. See AI steps for the full authoring/replay model and the reporter-side PIWI_AI* options.
Ingest limits
Caps applied to per-execution payloads (console output, steps, ARIA snapshots, error text, source snippets) before they are stored. They bound database growth against verbose or hostile submitters; values above each limit are truncated with a visible marker. Distinct from the PIWI_AI_MAX_* limits, which bound what enters an AI diagnosis prompt — the storage defaults sit at or above the AI maxima so the AI limits stay the binding constraint for prompts. Environment-only (no settings UI).
| Variable | Default | Description |
|---|---|---|
PIWI_INGEST_MAX_CONSOLE_ENTRIES | 200 | Max console entries stored per test execution. |
PIWI_IMPORT_MAX_BYTES | 524288000 | Max size of a single multipart upload (report upload or blob-report import), in bytes. Lower it to match a reverse proxy that rejects large bodies, so the import page rejects an oversized archive before uploading it. Added in 0.19.0. |
PIWI_INGEST_MAX_CONSOLE_ENTRY_CHARS | 2000 | Max characters stored per console entry. |
PIWI_INGEST_MAX_STEPS | 500 | Max test steps stored per execution. |
PIWI_INGEST_MAX_STEP_EVENTS | 1000 | Max step events stored per execution. |
PIWI_INGEST_MAX_ARIA_CHARS | 100000 | Max characters of the ARIA snapshot stored per failing execution. |
PIWI_INGEST_MAX_ERROR_CHARS | 20000 | Max characters of error text stored per execution (head and tail are kept). |
PIWI_INGEST_MAX_SAMPLE_ERROR_CHARS | 50000 | Max characters of the sample error stored per failure cluster. |
PIWI_INGEST_MAX_TEST_SOURCE_CHARS | 50000 | Max characters of the test source snippet stored per failing execution. |
PIWI_INGEST_MAX_SOURCE_FRAMES | 8 | Max source stack frames stored per failing execution. |
PIWI_INGEST_MAX_SOURCE_FRAME_CHARS | 4000 | Max characters per stored source frame snippet. |
Offline export
Bounds on the offline export of a test execution or a failure cluster (HTML, ZIP, PDF). Evidence that does not fit is listed in the report as omitted rather than dropped silently. The total cap is also the memory an export costs to build, since the archive is assembled before it is sent.
| Variable | Default | Description |
|---|---|---|
PIWI_EXPORT_MAX_INLINE_BYTES | 8388608 | Max size of a single evidence file embedded as a data: URI in an HTML export, in bytes. Larger files are left out of the single-file HTML (and listed as omitted); the ZIP export still carries them at full size. Added in 0.19.0. |
PIWI_EXPORT_MAX_BYTES | 524288000 | Max total size of one export, in bytes. Evidence is added largest-last until the budget is reached; the rest is listed as omitted. The archive is built in memory, so this also bounds what a single export costs the server. Added in 0.19.0. |
PIWI_EXPORT_MAX_CASES | 25 | Max member executions carrying full evidence in a failure-cluster export. Remaining affected tests are listed by name without their evidence. Added in 0.19.0. |
Timeline markers
| Variable | Default | Description |
|---|---|---|
PIWI_AUTO_MARKERS | true | Automatically create a timeline marker when a run’s environment, Playwright version, or reporter version changes from the previous run (default: enabled). Set to false to disable. Only the exact value false disables auto-markers. See details. |
Email (SMTP)
Required for email notifications and account flows (verification, password reset, invites). Set via environment only.
| Variable | Default | Description |
|---|---|---|
PIWI_SMTP_HOST | — | SMTP server hostname for outbound email. |
PIWI_SMTP_PORT | 587 | SMTP port (default 587; 465 for implicit TLS). |
PIWI_SMTP_USER | — | SMTP username. Optional — only when the server requires authentication. |
PIWI_SMTP_PASS | — | SMTP password. Optional — only when the server requires authentication. Never returned by the API. |
PIWI_SMTP_FROM | — | From address for outbound email (e.g. noreply@example.com). |
PIWI_SMTP_FROM_NAME | Piwi Dashboard | Display name for the from address (optional). |
PIWI_SMTP_SECURE | — | Set to "true" for implicit TLS on port 465 (default false → STARTTLS/plain). Defaults to on when the port is 465, off otherwise. |
Email sending activates once PIWI_SMTP_HOST and PIWI_SMTP_FROM are set; add PIWI_SMTP_USER/PIWI_SMTP_PASS when the server requires authentication. See Notifications for channels and subscriptions.
Failure clustering
Tunes the similarity thresholds used when grouping failures into clusters by their error fingerprint (and optional embeddings). Only used when an embedding model is configured.
| Variable | Default | Description |
|---|---|---|
PIWI_CLUSTER_SIMILARITY_THRESHOLD | 0.92 | Cosine similarity (0–1) above which two failure embeddings merge into one cluster. Must be greater than 0 and at most 1; invalid values fall back to the default. |
PIWI_CLUSTER_SUGGEST_THRESHOLD | 0.80 | Similarity at which a failure is suggested (not auto-merged) as related to a cluster. Capped at the merge threshold. |
See AI diagnosis → Failure clustering.
Backend logs
Controls the X-Piwi-Logs response-header capture that attaches backend logs to test failures. See Backend logs.
| Variable | Default | Description |
|---|---|---|
PIWI_TEST_LOGS_DISABLED | — | Disable X-Piwi-Logs response header emission (default: auto-disabled in production, enabled in development). Unset: capture is on in development and off in production builds; true forces it off everywhere, false forces it on even in production. See details. |
Build-time
These affect how the app is built rather than how a running instance behaves, and are mostly for contributors.
| Variable | Default | Description |
|---|---|---|
PIWI_BUILD_DIR | — | Overrides the Nuxt build output directory. Used by the test harness to isolate parallel builds. |
PIWI_BUILD_SHA | — | Commit SHA baked into the build for provenance. Shown on Settings → About. Set as a build-time arg. |
PIWI_DEMO_MODE | — | Set to "true" to build the standalone client-side demo SPA (no server). |
TIP
PIWI_BASE_URL, PIWI_POSTGRES_TEST_URL, PIWI_S3_TEST_BUCKET, PIWI_S3_TEST_REGION, PIWI_S3_TEST_ACCESS_KEY_ID, PIWI_S3_TEST_SECRET_ACCESS_KEY, PIWI_S3_TEST_ENDPOINT, PIWI_MAILPIT_URL, PIWI_MAILPIT_SMTP_PORT, PIWI_EMAIL_SERVER_URL, PIWI_TEST_CLEANUP_ENABLED, PIWI_DESKTOP_TOKEN exist only for the functional test harness and are not used by a normal deployment.