ChatForge
Self-hosted multi-provider LLM chat with per-user history, local/server sync controls, tools and memory, native-client APIs, streaming responses, and server-proxied or browser-direct provider access.
UI tour: Jump to screenshots.
Features
Chat and content
- Multi-provider chat with Anthropic, OpenAI, Gemini, and VertexAI backends, with streaming and non-streaming generation and a Stop action for in-flight responses.
- Per-user conversation storage with URL-addressable chats, folders, pin/collapse state, desktop/mobile drag-and-drop move/reorder, title regeneration, and persistent ordering.
- Local-only chats and folders with global, per-chat, and per-folder sync/unsync controls. Local records are saved in browser storage for that account until explicitly synced or deleted.
- Chat search across titles, IDs, context metadata, folder names, and SQLite FTS5-indexed message content, with folder/unfiled scoping and matching snippets.
- Message editing/regeneration, retry, copy, individual deletion, sent-prompt history navigation, and token-usage/provider/timestamp footers.
- Markdown rendering with sanitized links, syntax highlighting, KaTeX math, source links, collapsible reasoning summaries/steps, and code-block themes, wrapping, line numbers, copy, and fullscreen view.
- Up to six text/audio/video attachments per message, bounded attachment sizes, native media playback, and a playback-disable preference.
- Artifact CRUD with file/folder upload, path filtering, autocomplete for
@pathmentions, and lightweight message references that hydrate current artifact content when displayed or sent to a model. - Slash commands for context control and generation flow (
/compact,/clear,/retry,/restore), plus persistent summaries and configurable rolling context windows. - Sound effects, background-completion browser notifications, configurable stream-completion auto-scroll, Enter-to-send behavior, resizable/left-or-right chat sidebar, light/dark mode, high contrast, preset accents, and arbitrary hex themes.
Providers and generation
- Server-side LLM proxy with provider-specific request shaping and endpoint validation, plus a per-account switch and browser-direct provider fallback when proxying is disabled by the user or server.
- OpenAI Chat Completions and Responses API support, including built-in Responses web search with returned source links and
store: falserequests. - Provider reasoning controls: OpenAI effort/summary/web-search context, Anthropic thinking budget, and Gemini/VertexAI thinking level/budget/include-thoughts.
- Per-user provider/model catalogs with editable labels and per-model capability overrides, server-synced defaults, and a separately selectable provider/model/token budget for automatic chat titles.
- Custom system prompts with runtime
{model},{date}, and{today}interpolation. - Provider-bound conversation turns include their original send timestamps so the model retains temporal context across older messages.
- Client-side encrypted sync for provider endpoints/API keys and local-agent URL/token (PBKDF2-SHA256 + AES-GCM with a password-derived key), including selective fields and login-time unlock.
Tools and memory
- Tool calling with a per-tool allowlist, explicit execution traces, per-call approve/deny decisions, bounded parallel read-only execution, and a configurable consecutive-call limit.
- Workspace-scoped file read/write/list, shell command, SearXNG web search, URL fetch, memory read/write, chat/folder read/manage, appearance/settings control, and current/connected-session inspection tools.
- Local agent process support for filesystem/shell/web tools with workspace confinement, bearer auth, CORS controls, endpoint health, and command timeouts. An agent URL is required to execute these machine-local tools.
- Direct-provider tool definitions and results are withheld until the user grants browser-session consent to disclose them to the external provider.
- Memory CRUD/edit/search with SQLite FTS5 indexing, origin labels (
manual,tool,background), approval context for destructive writes, and admin memory search. - Optional incremental automatic memory consolidation: each user selects a provider/model/endpoint and encrypted API key, then a background worker creates, updates, merges, or retires durable background memories while excluding common credential, payment, and identity data.
Accounts, sync, and portability
- Per-user authentication and RBAC (user/admin), JWT cookie sessions, bcrypt password hashing, TOTP/recovery-code 2FA, passkey (WebAuthn) sign-in, and hardened self-service password rotation.
- Optional verified account e-mail addresses with per-address notifications for new logins, session deletion, blocked refresh-token replay, password changes, and export start/completion.
- E-mail password recovery by username or verified address, with recovery-link proof, required TOTP/recovery-code verification for 2FA accounts, rate limiting, and revocation of existing sessions after reset.
- Connected-device management for web and native sessions: view metadata/IP/activity, rename, revoke, permanently delete, clean stale entries, or revoke every other session.
- Native access/refresh/session tokens with rotating refresh tokens, replay detection, password and passkey login, logout, and browser-approved device-code linking.
- Real-time WebSocket sync with sequence-based delta catch-up, reconnect/reconciliation, backpressure limits, and granular policies/presets for folders, chats, messages, memories, artifacts, UI, settings, catalogs, encrypted secrets, and security state.
- Full user data export as a compressed archive with status/history, expiring downloads, and secrets excluded; server deployments use async jobs while embedded deployments retain a direct-download fallback.
- Resumable, restart-safe paged migration APIs for folders, conversations, messages, memories, artifacts, preferences, client preferences, encrypted provider config, and model catalogs, including conflict remapping and commit/rollback.
- Server mode uses
better-sqlite3with WAL; the embedded Flutter/Android runtime uses an FTS5-enabledsql.jsWASM adapter, a persistent generated secret, and database lock/resume bridge controls.
Administration and hardening
- Admin user management (create/update/delete/reset password), detailed per-user inspection, session revocation/deletion, user and memory search, and last-admin protection.
- Admin background-queue dashboard with stats/history, filters, auto-refresh, requeue/dead-letter handling, filtered cleanup, and managed worker spawn/stop/restart/log controls.
- Admin system operations (optional self-update/build pipeline, dependency-change detection, service restart/status, and manual cleanup of expired auth/export records).
- Admin database operations (state inspector, table previews, VACUUM, message/memory FTS rebuild, and parameterized SQL query runner).
- Hardened API surface with CSRF origin enforcement, CSP/security headers, login/recovery/device-code rate limits, content/count limits, outbound DNS pinning, blocked redirects/embedded credentials, and private/custom endpoint controls.
- Per-user isolation for chats, messages, folders, preferences, client preferences, models, memories, artifacts, sessions, passkeys, exports, migration state, sync events, background jobs, and encrypted payloads.
Quick Start
npm install
cp .env.example .env # edit CHATFORGE_SECRET
npm run user:create -- mattia hunter2 admin
npm run dev # starts both Vite (5173) + Express (3069)
User Management
npm run user:create -- <username> <password> [user|admin]
npm run user:list
npm run user:delete -- <username>
Admin users can open the in-app admin panel to:
- inspect full user profiles (preferences, model catalog, memories, conversations, messages)
- create/update/delete users and reset passwords
- inspect and revoke user device sessions
- search users and memories
- operate the background queue and managed workers
- run maintenance, service, update, and database actions
Production
npm run build # builds React into dist/
NODE_ENV=production CHATFORGE_SECRET=replace-with-at-least-32-random-characters node server/server.js
# Run in a second service/process when using async exports, e-mail, or automatic memory
NODE_ENV=production CHATFORGE_SECRET=replace-with-at-least-32-random-characters npm run worker
The Express server serves the built frontend from dist/ and the API on the same port (3069).
Set NODE_ENV in systemd/OpenRC (or inline as above), not in .env files consumed by Vite.
The background worker leases persistent jobs for e-mail delivery, archive generation, and automatic memory scans. You can run npm run worker as a long-lived process, run one claim/maintenance pass with npm run worker -- --once, or let an admin spawn and manage worker processes from the Background Queue panel. Jobs remain queued across restarts when no worker is running.
Optional: Admin Self-Update Button
You can expose an admin-only update action in the UI that runs:
- fetch and classify local/upstream history
- stash local changes
- fast-forward, or perform guarded rewritten-history recovery
- install/update dependencies
- rebuild
- unstash
- restart service
Enable it with env vars in your runtime service:
CHATFORGE_ENABLE_SELF_UPDATE=true
CHATFORGE_UPDATE_REPO_DIR=/path/to/chatforge
CHATFORGE_UPDATE_BUILD_CMD="npm run build"
CHATFORGE_UPDATE_INSTALL_DEPS=true
CHATFORGE_UPDATE_INSTALL_CMD="npm ci --include=dev"
CHATFORGE_UPDATE_INSTALL_FALLBACK_CMD="npm install --include=dev"
CHATFORGE_UPDATE_INSTALL_POLICY="if-needed"
CHATFORGE_UPDATE_INSTALL_TRIGGER_FILES="package.json,package-lock.json,npm-shrinkwrap.json,yarn.lock,pnpm-lock.yaml,bun.lock,bun.lockb"
CHATFORGE_UPDATE_RECOVER_REWRITTEN_HISTORY=true
CHATFORGE_UPDATE_RESTART_CMD="rc-service chatforge restart"
CHATFORGE_SYSTEM_STATUS_CMD="sudo /usr/bin/systemctl status chatforge.service"
If local and upstream history diverge after a rewrite, the updater only recovers when local HEAD exactly matches one upstream commit by tree, author identity/date, subject, and full message. It creates a refs/chatforge/update-backups/... ref before resetting to upstream, refuses ordinary local commits or ambiguous matches, and rolls back the Git history if dependency installation or the build fails. Set CHATFORGE_UPDATE_RECOVER_REWRITTEN_HISTORY=false to retain strict fast-forward-only behavior.
If any step fails, the process stops and restart is not executed.
Backend via Docker Compose
Use the hardened backend-only compose stack:
# set a strong secret first (or place it in .env)
export CHATFORGE_SECRET='replace-with-a-long-random-secret'
docker compose -f docker-compose.backend.yml up -d --build
docker compose -f docker-compose.backend.yml logs -f --tail=100
Create the first user inside the containerized backend:
docker compose -f docker-compose.backend.yml exec chatforge-backend \
node server/cli.js create-user <username> <password> [user|admin]
Notes:
- Backend binds to
127.0.0.1:3069by default. - SQLite data and tool sandbox are persisted in Docker volumes (
chatforge_data,chatforge_sandbox). - The compose file runs the web/backend service. Start workers from Admin → Background Queue, or add a separately supervised
npm run workerprocess with the same database, secret, export directory, and e-mail/memory environment.
Architecture
- Frontend: React SPA (Vite)
- Backend: Express server runtime plus an optional persistent background-job worker
- Auth: bcrypt passwords + optional TOTP/recovery codes + passkeys (WebAuthn), JWT in an httpOnly cookie for web clients, and rotating access/refresh tokens for native clients
- LLM transport: Validated server-side proxy by default; browser-direct provider requests are available when proxying is disabled. Provider credentials originate in browser-local configuration and may optionally be synced as a client-encrypted blob
- Storage: Adapter-based SQLite:
better-sqlite3+ WAL in server mode, or the bundled FTS5-enabledsql.jsWASM build in embedded mode - Live sync: WebSocket event stream with ordered delta catch-up and REST state reconciliation
- Background work: Lease-based SQLite queue for e-mail, exports, automatic memory, and maintenance
Native Authentication and Device Linking
Native clients can sign in with a password or passkey, rotate refresh tokens, log out, or use a browser-approved device-code flow:
POST /api/auth/native/loginPOST /api/auth/native/refreshPOST /api/auth/native/logoutPOST /api/auth/device/authorize— returns a device code, user code, verification URL, poll interval, and expiryPOST /api/auth/device/token— polls until the signed-in web user approves or denies the user codePOST /api/auth/device/approve— authenticated browser approval used by the/device-linkscreen
Passkey login for Flutter/native clients uses:
POST /api/auth/native/passkeys/authenticate/options- Input: optional
username - Output: WebAuthn authentication options +
challenge_id
- Input: optional
POST /api/auth/native/passkeys/authenticate/verify- Input:
challenge_id, WebAuthnresponse, and nativedevicemetadata (platform,device_name, etc.) - Output: native auth token bundle (
access_token,refresh_token,session) matching/api/auth/native/login
- Input:
Existing authenticated passkey management endpoints (/api/auth/passkeys list/register/delete) also work with Bearer access tokens from native clients.
Authenticated web and native clients can list and manage their session inventory through /api/auth/devices, including rename, revoke, permanent delete, stale cleanup, and revoke-others operations. Refresh tokens rotate on use; detected replay revokes the affected native session.
Live Sync Policy API (Native + Web)
Authenticated clients can control granular live WebSocket synchronization categories:
GET /api/sync/live-policy- Output:
{ policy }
- Output:
PUT /api/sync/live-policy- Input: partial or full
policyobject (can also send the object directly as request body) - Output:
{ ok: true, policy, updated_at }
- Input: partial or full
Policy shape:
enabled: global on/off for live WebSocket updatesfolders.state: synchronize folder open/closed statefolders.order: synchronize folder ordering and pin statefolders.names: synchronize folder rename changesfolders.lifecycle: synchronize folder create/deletechats.order: synchronize chat ordering and pin statechats.names: synchronize chat rename changeschats.lifecycle: synchronize chat create/deletechats.context: synchronize chat context metadata changes (context_summary,context_cutoff_count)chats.messages: synchronize chat message create/update/delete eventsdata.memories: synchronize memory create/update/deletedata.artifacts: synchronize artifact create/update/deleteapp.ui: synchronize UI preference changesapp.settings: synchronize non-UI settings changesapp.modelCatalog: synchronize model catalog changesapp.encryptedSecrets: synchronize encrypted provider/agent sync metadata changesapp.security: synchronize account security state changes (auth devices, passkeys, TOTP)
The web client consumes /api/sync/ws, resumes from its last sequence number through /api/sync/changes, ignores its own actor-session events, and periodically reconciles state. The Settings presets can enable everything, disable everything, sync only UI/settings, or omit chat content. Separately, sidebar arrows can move individual chats/folders between server sync and browser-local storage, while Unsync all chats switches new chat creation to local-only mode.
Per-User Model Catalogs
- Each account has its own provider/model catalog (Anthropic, OpenAI, Gemini, VertexAI).
- Default model lists are preloaded with current model families and can be customized in Settings.
- Add, edit, or remove model IDs and labels in the UI; changes are persisted server-side for that user.
- Per-model capability toggles gate sampling, reasoning, thought, and OpenAI web-search controls; suggested values are inferred from provider/model families and can be overridden.
- Each account can also save a default provider and default model, applied automatically at login.
- Automatic title generation can use its own provider/model and output-token limit instead of the active chat model.
Provider Reasoning Controls
- OpenAI: configurable reasoning effort (used for Chat Completions / Responses where supported).
- OpenAI Responses API: configurable reasoning summary mode (
auto,concise,detailed) and request-levelstore: falseto avoid provider-side response storage. - OpenAI Responses API: optional built-in web search, configurable search context size, and rendered source links.
- Anthropic: configurable thinking token budget (
thinking.budget_tokens). - Gemini / VertexAI: configurable thinking level and thinking budget (
generationConfig.thinkingConfig). - Conversation UI: optional reasoning-step visibility for providers that return reasoning/thought traces.
When server proxying is disabled globally or for an account, the browser uses the same provider converters to call the configured endpoint directly; the endpoint must permit browser CORS. Direct-provider tools require explicit consent once per browser session before tool definitions or approved results are disclosed to that provider.
Encrypted Provider Config Sync
- API keys, provider endpoints, the local-agent URL, and the agent bearer token can be selectively synced to the server as a client-side encrypted blob.
- Encryption/decryption uses PBKDF2 (password-derived key) + AES-GCM in the browser.
- On interactive login, ChatForge attempts to load and decrypt synced provider values with the entered password and hydrate local storage.
- In Settings, use
Sync Values To ServerandLoad Values From Serverto push/pull while already logged in. - Passwordless passkey login prompts for the account password only if the user chooses to unlock encrypted values; a password change prompts the user to re-encrypt them.
Account E-mail and Password Recovery
Set CHATFORGE_EMAIL_ENABLED=true, configure a transport, and run a background worker to enable account e-mail features. Users can add multiple addresses, verify them through the SPA verification route, and independently subscribe each verified address to new-login, deleted-session, blocked-token-replay, password-change, and export notifications.
The sign-in screen accepts password-recovery requests by username or verified e-mail address. Recovery links are single-account proofs; accounts with 2FA must additionally supply a live TOTP or recovery code. Completing recovery rotates the password and revokes existing sessions. Add/update/delete e-mail operations also require current-password proof and, when enabled, a second factor.
For real links, set CHATFORGE_PUBLIC_BASE_URL to the externally reachable ChatForge origin. The log transport is useful for development; production can use SMTP or a sendmail-compatible command.
Data Export and Migration
Settings → Data Export creates a .tar.gz archive containing account metadata, security summaries, chats, folders, messages, memories, artifacts, preferences, per-client preferences, encrypted provider configuration, and the model catalog. Password hashes, refresh tokens, raw TOTP secrets, recovery codes, automatic-memory credentials, and memory-processing cursors are excluded.
Server-mode exports are persistent async jobs with paged history, status polling, expiring authenticated downloads, optional start/completion e-mails, and scanner-safe public download confirmation pages. They require a background worker. Embedded mode exposes the direct archive fallback instead.
The authenticated /api/migration API provides resumable paged export/import sessions that survive server restarts:
GET /api/migration/capabilitiesPOST /api/migration/export/start, then status/manifest/paged-resource readsPOST /api/migration/import/start, then chunked resource uploads and status readsPOST /api/migration/import/:id/commitor/rollback
Imports validate record sizes/counts and ownership, reject gaps/out-of-bounds chunks, remap conflicting IDs, preserve artifact path identity, and emit sync events after commit.
Automatic Memory Consolidation
In Settings → Memories, server-mode users can enable background analysis, choose a provider/model/endpoint, save a dedicated API key encrypted at rest, inspect last/next run and errors, and queue an immediate run. The scheduler incrementally scans completed conversations from per-conversation cursors and can backfill a bounded number of existing chats.
The model may create, update, merge, or retire only background-origin memories; manual and tool-created memories are protected. Candidate output is bounded and screened for common credentials, bearer/API tokens, private keys, payment-card numbers, and government identity data. Automatic memory is disabled in embedded mode and requires a running background worker.
Embedded Backend and Migration
server/embedded-entry.js runs the backend inside a Flutter Android bridge. It selects the bundled FTS5-enabled sql.js WASM storage adapter, persists a generated secret beside the database, creates a local sandbox, and handles prepare_lock / resume_after_unlock control messages so the host can safely close and reopen local storage around its lock lifecycle.
POST /api/auth/embedded-bootstrap creates the single local-owner admin on first use and returns the same native token/session bundle used by remote clients. Embedded mode disables e-mail, async workers, automatic memory, self-update, and system-status commands; it keeps the core chat/storage APIs, resumable migration import/export, local sync endpoints, and direct archive export. See Flutter embedded integration for packaging and bridge details.
nginx Reverse Proxy
server {
listen 443 ssl;
server_name chat.n9x.co;
location / {
proxy_pass http://127.0.0.1:3069;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_buffering off; # important for SSE streaming
proxy_cache off;
}
}
OpenRC Service (Alpine/Gentoo)
Service files are provided under deploy/openrc/.
# install chatforge service + config
sudo cp deploy/openrc/chatforge /etc/init.d/chatforge
sudo chmod +x /etc/init.d/chatforge
sudo cp deploy/openrc/chatforge.confd.example /etc/conf.d/chatforge
# edit /etc/conf.d/chatforge and set CHATFORGE_SECRET
sudo rc-service chatforge start
sudo rc-update add chatforge default
Agent service (optional, if you use local tool execution):
sudo cp deploy/openrc/chatforge-agent /etc/init.d/chatforge-agent
sudo chmod +x /etc/init.d/chatforge-agent
sudo cp deploy/openrc/chatforge-agent.confd.example /etc/conf.d/chatforge-agent
# edit /etc/conf.d/chatforge-agent (set CHATFORGE_AGENT_TOKEN and allowed CHATFORGE_AGENT_CORS origins;
# include your hosted ChatForge origin, for example https://chat.example.com, if the UI is not served from localhost)
# optional: set CHATFORGE_AGENT_EXTRA_ARGS="--allow-private-fetch true" only if you explicitly need local/private URL fetching
sudo rc-service chatforge-agent start
sudo rc-update add chatforge-agent default
SearXNG via Docker Compose
Compose files are under deploy/searxng/.
cd deploy/searxng
# set a strong server.secret_key in settings.yml first
docker compose up -d
docker compose logs -f --tail=100
By default it binds to 127.0.0.1:8888 and matches CHATFORGE_SEARXNG=http://127.0.0.1:8888.
Environment Variables
Runtime, authentication, and sync
| Variable | Default | Description |
|---|---|---|
CHATFORGE_PORT |
3069 |
Server port |
CHATFORGE_DB |
./data/chatforge.db |
SQLite path |
CHATFORGE_BACKEND_MODE |
server |
Runtime mode; embedded selects the WASM adapter and disables server-only operations |
CHATFORGE_EMBEDDED_DATA_DIR |
database directory | Embedded secret and default sandbox directory |
CHATFORGE_SECRET |
unset | Token/signing and default memory-credential key; production requires at least 32 characters, while development generates an ephemeral secret if unset |
CHATFORGE_JWT_EXPIRY |
7d |
JWT lifetime |
CHATFORGE_ACCESS_TOKEN_EXPIRY |
15m |
Native Bearer access-token lifetime |
CHATFORGE_REFRESH_TOKEN_EXPIRY_DAYS |
90 |
Native rotating refresh-token lifetime in days (1–365) |
CHATFORGE_DEVICE_CODE_EXPIRY_MIN |
10 |
Native device-link code lifetime in minutes |
CHATFORGE_DEVICE_CODE_POLL_INTERVAL_SEC |
5 |
Minimum device-token polling interval |
CHATFORGE_DEVICE_VERIFICATION_URI |
inferred /device-link URL |
Public device-link approval URL returned to native clients |
CHATFORGE_TOTP_ISSUER |
ChatForge |
Display name used in authenticator apps during TOTP setup |
CHATFORGE_PASSKEY_RP_NAME |
ChatForge |
Relying Party display name shown in passkey prompts |
CHATFORGE_PASSKEY_RP_ID |
empty | Optional RP ID override for passkey ceremonies (defaults to request host without port) |
CHATFORGE_PASSKEY_ALLOWED_ORIGINS |
empty | Optional comma-separated allowed origins for passkey ceremonies (defaults to inferred same-origin values; can include native origins like android:apk-key-hash:...) |
CHATFORGE_PASSKEY_ANDROID_PACKAGE_NAME |
empty | Optional Android package name used to publish /.well-known/assetlinks.json for native passkey providers |
CHATFORGE_PASSKEY_ANDROID_SHA256_CERT_FINGERPRINTS |
empty | Optional comma-separated Android cert SHA-256 fingerprints (AA:BB:...). When set with package name, ChatForge publishes Digital Asset Links and auto-adds matching android:apk-key-hash:... passkey origins |
CHATFORGE_PASSKEY_CHALLENGE_TTL_SEC |
300 |
Passkey challenge lifetime in seconds |
CHATFORGE_PASSKEY_CHALLENGE_PURGE_AGE_SEC |
86400 |
Age after which used/expired passkey challenges are purged |
CHATFORGE_TRUST_PROXY |
false |
Express trust proxy setting (1, true, or trusted proxy keyword) |
CHATFORGE_ALLOWED_ORIGINS |
empty | Optional comma-separated origins allowed for mutating /api requests. Empty means same-origin only. |
CHATFORGE_ALLOW_WS_QUERY_TOKEN_AUTH |
false |
Allow Bearer auth via WebSocket query params (access_token/token) on /api/sync/ws. Keep disabled to avoid token leakage in URL logs/history. |
NODE_ENV |
unset | Set to production in the runtime service env (not in .env) for secure cookies |
E-mail, exports, and background work
| Variable | Default | Description |
|---|---|---|
CHATFORGE_EMAIL_ENABLED |
false |
Enable account e-mail, verification, recovery, and notification routes; always off in embedded mode |
CHATFORGE_PUBLIC_BASE_URL |
empty | External origin used in e-mail verification, recovery, and export links |
CHATFORGE_EMAIL_FROM |
ChatForge <no-reply@localhost> |
Outbound From header |
CHATFORGE_EMAIL_TRANSPORT |
log |
Worker delivery transport: log, sendmail, or smtp |
CHATFORGE_EMAIL_SENDMAIL_CMD |
sendmail -t -i |
Command used by the sendmail transport |
CHATFORGE_EMAIL_SMTP_HOST |
empty | SMTP hostname; required for the smtp transport |
CHATFORGE_EMAIL_SMTP_PORT |
587 |
SMTP port |
CHATFORGE_EMAIL_SMTP_SECURE |
false |
Use implicit TLS for SMTP |
CHATFORGE_EMAIL_SMTP_USER |
empty | Optional SMTP username |
CHATFORGE_EMAIL_SMTP_PASS |
empty | Optional SMTP password |
CHATFORGE_EMAIL_SMTP_REQUIRE_TLS |
false |
Require STARTTLS for SMTP |
CHATFORGE_EMAIL_SMTP_IGNORE_TLS |
false |
Disable STARTTLS negotiation for SMTP |
CHATFORGE_EMAIL_VERIFY_TTL_SEC |
86400 |
E-mail verification-token lifetime |
CHATFORGE_PASSWORD_RECOVERY_TTL_SEC |
3600 |
Password-recovery request lifetime |
CHATFORGE_BACKGROUND_JOB_LEASE_SEC |
60 |
Queue lease duration; active workers renew leases during long jobs |
CHATFORGE_BACKGROUND_JOB_POLL_INTERVAL_MS |
1000 |
Worker idle polling interval |
CHATFORGE_DAILY_MAINTENANCE_INTERVAL_SEC |
86400 |
Full expired-token/export cleanup interval |
CHATFORGE_EXPORT_STORAGE_DIR |
./data/exports |
Async archive output directory; must be shared by server and workers |
CHATFORGE_EXPORT_TTL_HOURS |
24 |
Completed archive and download-token lifetime |
CHATFORGE_AUTO_MEMORY_ENABLED |
true in server mode |
Globally enable automatic-memory scheduling |
CHATFORGE_AUTO_MEMORY_INTERVAL_SEC |
86400 |
Per-user automatic-memory scan interval |
CHATFORGE_AUTO_MEMORY_BACKFILL_CONVERSATIONS |
100 |
Maximum existing conversations considered when initializing cursors; 0 disables backfill |
CHATFORGE_AUTO_MEMORY_MAX_MESSAGES_PER_CONVERSATION |
50 |
Maximum messages read from each conversation per scan |
CHATFORGE_AUTO_MEMORY_MAX_INPUT_CHARS_PER_RUN |
120000 |
Aggregate conversation-input character budget per scan |
CHATFORGE_MEMORY_CREDENTIAL_KEY |
CHATFORGE_SECRET |
Optional independent key material for AES-256-GCM automatic-memory API-key encryption |
Providers and tools
| Variable | Default | Description |
|---|---|---|
CHATFORGE_ENABLE_LLM_PROXY |
true |
Enable /api/stream; when false, the web client falls back to direct provider requests instead of using the server proxy |
CHATFORGE_ALLOW_PRIVATE_ENDPOINTS |
true outside production, false in production |
Allow proxying LLM traffic to localhost/private IPs |
CHATFORGE_ALLOWED_CUSTOM_LLM_HOSTS |
empty | Optional comma-separated public hostnames allowed for custom LLM endpoints while keeping arbitrary endpoints blocked |
CHATFORGE_ALLOW_CUSTOM_LLM_ENDPOINTS |
false |
Allow arbitrary public LLM endpoint hosts in /api/stream. Prefer CHATFORGE_ALLOWED_CUSTOM_LLM_HOSTS when possible |
CHATFORGE_SANDBOX |
./sandbox |
Default workspace reported by server tool configuration and used by legacy server-side tool executors |
CHATFORGE_SEARXNG |
http://localhost:8888 |
SearXNG base URL for web_search |
CHATFORGE_ALLOW_PRIVATE_FETCH_URLS |
false |
Allow fetch_url tool requests to localhost/private IPs |
CHATFORGE_CMD_TIMEOUT |
30000 |
Default run_command timeout in ms (can be overridden per-user at runtime in Tools settings) |
Admin operations
| Variable | Default | Description |
|---|---|---|
CHATFORGE_ENABLE_SELF_UPDATE |
false |
Allow admin UI to run self-update pipeline |
CHATFORGE_UPDATE_REPO_DIR |
current working dir | Repository directory for update commands |
CHATFORGE_UPDATE_BUILD_CMD |
npm run build |
Build command run during admin update |
CHATFORGE_UPDATE_INSTALL_DEPS |
true |
Install dependencies before build during admin update |
CHATFORGE_UPDATE_INSTALL_CMD |
npm ci --include=dev |
Primary dependency-install command run during admin update |
CHATFORGE_UPDATE_INSTALL_FALLBACK_CMD |
npm install --include=dev |
Fallback install command if primary install fails |
CHATFORGE_UPDATE_INSTALL_POLICY |
if-needed |
if-needed skips install unless dependency trigger files changed in pulled commits; always installs every update |
CHATFORGE_UPDATE_INSTALL_TRIGGER_FILES |
package.json,package-lock.json,npm-shrinkwrap.json,yarn.lock,pnpm-lock.yaml,bun.lock,bun.lockb |
Comma-separated files that trigger dependency install in if-needed mode |
CHATFORGE_UPDATE_RECOVER_REWRITTEN_HISTORY |
true |
Allow guarded divergence recovery when local HEAD exactly matches one rewritten upstream commit; a backup ref is created before reset |
CHATFORGE_UPDATE_RESTART_CMD |
empty | Service restart command (required if self-update enabled) |
CHATFORGE_SYSTEM_STATUS_CMD |
empty | Command for admin service-status display |
UI Tour (Screenshots)
Authentication
Login
Username/password sign-in before loading synced user preferences and chats.
Core Chat
Main Chat (Light Theme)
Primary conversation surface with model/provider controls, streaming responses, and message actions.
Conversation Example
Longer back-and-forth conversation showing grouped turns in one thread.
Markdown Rendering (1)
Markdown Rendering (2)
Markdown Rendering (3)
Formatted markdown output across lists, blocks, and rich response content.
Inline LaTeX
Math rendering in chat responses.
High-Contrast Chat
High-contrast chat mode for improved visual accessibility.
Search
Search With Content Match
Search inside chats to quickly jump to conversations/messages containing the query.
Search With No Content Match
Empty/no-match state behavior when no messages match the query.
Productivity Features
Commands
Built-in command palette/view for quick in-chat actions and workflow shortcuts.
Sidebar and Organization
Sidebar Folders (Drag and Drop)
Conversation sidebar for organizing chats and folders. Supports collapsing folders, drag-and-drop reordering for folders and threads, and server-side persistence of folder state and order.
Settings and Configuration
Settings (Collapsed)
Main settings entry point for providers, defaults, preferences, and account-level options.
General Settings
Provider Settings
Model Catalog Settings
Per-user provider/model catalogs can be customized directly in Settings.
Default Model Selector
Reasoning Settings
Sampling Settings
System Prompt Settings
Tools Settings
Memories Settings
Encrypted Provider Sync
Artifacts Settings
Self Password Change
Admin and Operations
Admin Panel Overview
Top-level admin panel with user, database, and service controls.
Admin Controls
Operational actions for service status, update, and restart workflows.
Admin User Management
User list with role management, password reset, and account lifecycle actions.
Admin User Detail
Full per-user snapshot including preferences, memories, conversations, and messages.
Admin SQL Query Runner
In-app SQL runner for read/admin queries with typed parameter input.
Admin Query Runner Example
Example query execution and result rendering in the admin database panel.
Default Themes
Blue Theme
Green Theme
Purple Theme
Yellow Theme
Theme customization note:
- You are not limited to presets. Any valid hex color is supported (for example
#1f6feb,#22c55e,#f59e0b).


































