Operate

Configuration

Configuration

clickclack serve resolves config in this order. Later sources override earlier ones for any given key:

  1. Hard-coded defaults (Addr=":8080", Data="./data").
  2. Environment variables.
  3. JSON config file passed via --config.
  4. CLI flags that were explicitly set.

Source: apps/api/internal/config/config.go and the applyFlagOverrides hook in cmd/clickclack/main.go.

#Flags and env vars

FlagEnvDefaultNotes
--addrCLICKCLACK_ADDR:8080HTTP listen address.
--dataCLICKCLACK_DATA./dataData root for DB, uploads, logs.
--dbCLICKCLACK_DBderivedDB URL. Defaults to sqlite://<data>/clickclack.db.
--uploadsCLICKCLACK_UPLOADSderivedUpload storage URL. Defaults to file://<data>/uploads; use r2://bucket/prefix for Cloudflare R2.
--configunsetJSON config file.
--dev-bootstrapCLICKCLACK_DEV_BOOTSTRAPfalseserve only. Creates a default user/workspace/channel and enables local dev auth fallbacks when explicitly set to true.
CLICKCLACK_PUBLIC_URLunsetExternal URL. Used to build the GitHub OAuth callback.
CLICKCLACK_GITHUB_CLIENT_IDunsetGitHub OAuth app client ID.
CLICKCLACK_GITHUB_CLIENT_SECRETunsetGitHub OAuth app client secret.
CLICKCLACK_GITHUB_ALLOWED_ORGunsetOptional GitHub org login gate. Requires read:org scope.
CLICKCLACK_GITHUB_MODERATOR_ORGunsetOptional GitHub org whose members become guest-workspace moderators. Requires read:org scope.
CLICKCLACK_PUSHOVER_API_TOKENunsetPushover application API token. Users still opt in with their own Pushover user key in account settings.
CLICKCLACK_R2_ACCOUNT_IDunsetCloudflare account ID for r2:// uploads.
CLICKCLACK_R2_ACCESS_KEY_IDunsetR2 API token access key ID.
CLICKCLACK_R2_SECRET_ACCESS_KEYunsetR2 API token secret access key.
CLICKCLACK_R2_ENDPOINTderivedOptional S3-compatible endpoint override for tests or non-standard R2 endpoints.

#Config file

{
  "addr": ":8080",
  "data": "./data",
  "db": "sqlite:
   "file:///var/lib/clickclack/uploads",
  "dev_bootstrap": false,
  "public_url": "https:
   "Iv1.xxxxxxxxxxxx",
   "...",
   "openclaw",
   "openclaw",
   "azGDORePK8gMaC0QOYAMyEEuzJnyUi",
   "91b59577e757131d68d55a471fe32aca",
   "...",
   "..."
}

Pass with --config /etc/clickclack/config.json. Values from the file override env vars; CLI flags override the file if explicitly set.

#DB URL

SQLite forms:

sqlite://./data/clickclack.db
./data/clickclack.db

Both end up at the same place — the sqlite:// prefix is stripped. The parent directory is created on open.

Postgres forms:

postgres://user:pass@host:5432/clickclack?sslmode=require
postgresql://user:pass@host:5432/clickclack?sslmode=require

serve, migrate, and admin commands all accept --db or CLICKCLACK_DB. Postgres stores durable chat state in the external database.

#Upload storage

Local disk is the default:

CLICKCLACK_UPLOADS=file:///var/lib/clickclack/uploads

Cloudflare R2 uses the S3-compatible API:

CLICKCLACK_UPLOADS=r2://clickclack-uploads/prod
CLICKCLACK_R2_ACCOUNT_ID=91b59577e757131d68d55a471fe32aca
CLICKCLACK_R2_ACCESS_KEY_ID=...
CLICKCLACK_R2_SECRET_ACCESS_KEY=...

The database still stores upload metadata and auth visibility. The upload backend stores the bytes and streams them back through /api/uploads/{id} after the normal ClickClack permission checks.

#Disabling dev fallbacks

For non-local deployments:

clickclack serve \
  --dev-bootstrap=false \
  --config /etc/clickclack/config.json

Combine with real auth (CLI-created magic links or GitHub OAuth) so the "first-user-in-DB" dev auth fallback never kicks in. In containers, this is already the default; CLICKCLACK_DEV_BOOTSTRAP=false is only an explicit guard.