Repository navigation
Configuration reference
This page lists every environment variable and every setting, with its default. For the steps, see Self-hosting and AI.
Contrack needs no configuration to start. Most settings live in the app. Environment variables cover what the app cannot set for itself, such as the port, the data folder and sign-in, and setups that never open the app.
-
Where variables come from. The server reads
.envfrom the folder it starts in. A variable that the environment already sets wins over the file..env.exampleholds the common ones:cp .env.example .env. -
Docker.
docker run -e NAME=valuesets a variable. Compose reads.envbesidedocker-compose.ymland passes the variables that itsenvironment:block lists. - Which one wins. A variable and an app setting can name the same thing:
| App setting | Variable | Which one wins |
|---|---|---|
| A provider key |
GEMINI_API_KEY, OPENAI_API_KEY, ANTHROPIC_API_KEY
|
The variable. The provider row says which, such as Set by GEMINI_API_KEY |
| A model: Fast, Strong, web search or embedding |
AI_QUICK_MODEL, AI_DEEP_MODEL, AI_RESEARCH_MODEL, AI_EMBEDDINGS_MODEL
|
A model pinned in the app. With none, the variable, and the select says From AI_QUICK_MODEL or its own variable |
| SearXNG address | SEARXNG_URL |
The variable. The field is locked |
| Use AI on this instance | AI_DISABLED |
The variable holds AI off, and the switch is locked |
| Look up addresses for the map | GEOCODING_DISABLED |
The variable holds lookups off, and the switch is locked |
| Outgoing mail |
SMTP_URL, with MAIL_FROM and MAIL_REPLY_TO
|
The variable. The page shows its values read only |
| Google OAuth client |
GOOGLE_OAUTH_CLIENT_ID and GOOGLE_OAUTH_CLIENT_SECRET
|
The variables, when both are set. The field is locked |
| Trash, Backups, Snapshots to keep |
TRASH_RETENTION_DAYS, BACKUP_INTERVAL_HOURS, BACKUP_KEEP
|
A value saved in the app, then the variable, then the default. While the variable is set, the app cannot change the field |
For the last row, set the variable before anyone saves a value in the app. A value saved earlier keeps winning.
| Variable | What it does | Default |
|---|---|---|
AUTH_REQUIRED |
true makes everyone sign in with an account. The first visit creates the first account |
false |
HOST |
The interface that the server listens on. 0.0.0.0 listens on every interface. Development mode takes a loopback address only |
127.0.0.1 (image: 0.0.0.0) |
PORT |
The port that the server listens on | 3210 |
PUBLIC_URL |
The address people open, such as https://crm.example.com, with no path. Mail sends no sign-in, reset or invitation link without it. With sign-in on, an https address, or http on localhost or 127.0.0.1, turns on OAuth sign-in for MCP clients. A bad value stops the start |
Taken from each request |
TRUST_PROXY_HOPS |
How many reverse proxies are in front, from 0 to 10. 0 believes no X-Forwarded-* header. Set 1 behind one proxy. Another value stops the start |
0 |
ALLOWED_HOSTS |
While sign-in is off, and until the first account exists, the server answers only local names: an IP address, localhost, a name with no dot, or one under .localhost, .local, .lan, .home, .corp, .localdomain, .home.arpa or .internal, plus the PUBLIC_URL host. Other names get 403 HOST_NOT_ALLOWED. List them here, comma-separated, such as a Tailscale .ts.net name. .example.com allows every name under it, * allows all. A reverse proxy must pass the original Host on (nginx proxy_set_header Host $host, Apache ProxyPreserveHost On) |
Local names only |
CORS_ORIGIN |
Allows cross-origin requests from this one origin. The app itself needs none | Off |
DATA_DIR |
The folder for the database, uploads, backups, model files and secret.key
|
The working folder (image: /app/data) |
CONTRACK_SECRET_KEY |
64 hex characters that encrypt the credentials the database stores. A bad value stops the start | A key in DATA_DIR/secret.key
|
AI_PROVIDER |
The provider that Automatic tries first: gemini, openai or anthropic. A bare model name in an AI_*_MODEL pin also goes to it |
gemini |
GEMINI_API_KEY |
Google Gemini API key. It wins over a key saved in the app | None |
OPENAI_API_KEY |
OpenAI API key. It always calls OpenAI itself: a local model server is an OpenAI-compatible server | None |
ANTHROPIC_API_KEY |
Anthropic API key | None |
AI_DISABLED |
true or 1 turns AI off for the whole instance. Use AI on this instance cannot turn it back on. Local search keeps working |
false |
AI_QUICK_MODEL |
Pins the Fast model, as model or provider:model, such as anthropic:claude-sonnet-5. A model pinned in the app wins |
Automatic |
AI_DEEP_MODEL |
Pins the Strong model, in the same form | Automatic |
AI_RESEARCH_MODEL |
Pins the Web search model, in the same form | Automatic |
AI_EMBEDDINGS_MODEL |
Pins a hosted embedding model, in the same form. A change rebuilds both vector indexes | The built-in local model |
SEARCH_RERANK_MODEL |
The local model that reorders the top of Ask Contrack's local list. off turns it off. Another model downloads once, which needs MODEL_DOWNLOADS=true
|
Xenova/ms-marco-TinyBERT-L-2-v2 |
SEARCH_RERANK_BUDGET_MS |
The most milliseconds that model may add to a question. Later scores are dropped, and the list keeps its order | 25 |
MODEL_DIR |
The folder of model files that the server reads before it downloads anything, as <folder>/<model id>/<file>. npm run models:fetch fills it |
DATA_DIR/models (image: /app/models) |
MODEL_DOWNLOADS |
false, 0, off or no stops model downloads from huggingface.co. A model that is not on disk then fails to load, and the log says how to fetch it |
true (image: false) |
TRANSFORMERS_CACHE |
The folder that the server writes downloaded model files to |
DATA_DIR/.cache when DATA_DIR is set |
SEARXNG_URL |
The base URL of your SearXNG, for contact research. It wins over an address saved in the app | None |
SMTP_URL |
The mail server, as smtp://user:pass@host:587 or smtps://user:pass@host:465. It wins over Outgoing mail
|
None |
MAIL_FROM |
The sender address, such as Contrack <noreply@example.com>. Read only with SMTP_URL
|
The SMTP user name, when it is an email address |
MAIL_REPLY_TO |
The Reply-To address. Read only with SMTP_URL
|
None |
GOOGLE_OAUTH_CLIENT_ID |
The OAuth client ID for the Google Workspace connector. Read only when GOOGLE_OAUTH_CLIENT_SECRET is set too |
None |
GOOGLE_OAUTH_CLIENT_SECRET |
The OAuth client secret for the Google Workspace connector | None |
CONNECTOR_SYNC_CONCURRENCY |
The most connector syncs that run at once | 2 |
JOB_CONCURRENCY |
The most background jobs that run at once, such as a backup or the daily sweep. An integer of at least 1. Another value logs a warning and runs the default | 2 |
LOG_LEVEL |
The lowest level that the server log writes: error, warn, info or debug. Each request is one info line. Another value logs a warning and runs at info
|
info |
CONNECTORS_ALLOW_PRIVATE_HOSTS |
true lets the Calendar and Mailbox (IMAP) connectors reach private network addresses. The server logs a warning at start |
false |
MAP_STYLE_LIGHT |
The basemap style for the light palette: an https:// URL or a root-relative path such as /map/style.json
|
OpenFreeMap positron
|
MAP_STYLE_DARK |
The basemap style for the dark palette, with the same rule | OpenFreeMap dark
|
NOMINATIM_URL |
The base URL of your own Nominatim, such as http://nominatim:8080. Address lookups go there instead of nominatim.openstreetmap.org. A value that is not an http or https URL turns lookups off |
https://nominatim.openstreetmap.org |
GEOCODING_DISABLED |
true or 1 turns address lookups off for the whole instance. Look up addresses for the map cannot turn them back on. No address leaves the server |
false |
TRASH_RETENTION_DAYS |
Days a deleted contact stays in Trash, from 1 to 365 | 30 |
BACKUP_INTERVAL_HOURS |
Hours between snapshots, from 0 to 168. 0, or a value that is not a number, turns the schedule off |
24 |
BACKUP_KEEP |
How many snapshots to keep, from 1 to 100 | 7 |
NODE_ENV |
production serves the built app from dist/ with the strict Content-Security-Policy. Anything else runs the Vite dev server, and the policy also allows its inline script and reload socket |
Development (image: production) |
DISABLE_BACKGROUND_JOBS |
true skips the model load, the backfills, backups, the trash purge and every schedule. For tests and throwaway instances |
false |
DISABLE_CPU_WORKER |
true runs the embedding model on the request thread, not on a worker thread. Only for a Node build that cannot start threads. Ask Contrack then skips its local reranker |
false |
Development and test switches. These change one process. A deployment does not need them.
| Variable | What it does | Default |
|---|---|---|
DISABLE_HMR |
true turns off Vite hot reload. Each dev server keeps its reload socket on its own port |
false |
VITEST |
Vitest sets it, never a person. Under it, the server refuses to open ./curator.db unless DATA_DIR is set |
None |
IMPORT_SETTLE_MS |
How long an import that does not stream waits before its duplicate check, in milliseconds. Tests shorten it | 3000 |
AI_GATEWAY_TIMEOUT_OVERRIDE |
Replaces the time limit of every AI call, in milliseconds. Tests and evals use it | None |
Docker. docker-compose.yml passes every variable in the first table to
the container, except seven. The image sets HOST, PORT, DATA_DIR and
NODE_ENV itself, and a value meant for a local run would break it.
DISABLE_BACKGROUND_JOBS and DISABLE_CPU_WORKER are switches for one
process, and a value meant for development would stop backups or the
embedding worker in the container. TRANSFORMERS_CACHE follows DATA_DIR
there. Compose passes MODEL_DIR and
MODEL_DOWNLOADS with the image's own values as defaults (/app/models and
false), because an empty value would point the server away from the models
that the image ships. tests/unit/repo/envDocs.test.ts fails when this table,
.env.example, the compose file and the code disagree.
The steps are in AI. This section lists the parts and the rules.
| Model in the app | What uses it | Variable | OpenAI-compatible server |
|---|---|---|---|
| Fast model | Ask Contrack planning and checks, the group brief, briefings, the daily insight, Add from text, people named in notes, mail summaries, and the fields that research fills | AI_QUICK_MODEL |
Yes |
| Strong model | Email file summaries, AI duplicate checks, and the pages that SearXNG finds | AI_DEEP_MODEL |
Yes |
| Web search model | The provider's own web search in contact research | AI_RESEARCH_MODEL |
No |
| Embedding model | Search by meaning and duplicate matching | AI_EMBEDDINGS_MODEL |
Yes |
Each model is found in this order:
- A model pinned in Settings → Administration → AI.
- The variable, when it names a connected provider. The select then says From AI_QUICK_MODEL, or the variable that is set.
-
Automatic: the provider in
AI_PROVIDER, then a fixed order, then any other connected provider. The Fast model tries Gemini, OpenAI, Anthropic. The Strong model and the Web search model try Gemini, Anthropic, OpenAI. The web search model skips OpenAI-compatible servers.
The embedding model has no Automatic: with no pin, it is the built-in
model. A pin written as model goes to the AI_PROVIDER provider. A pin
written as provider:model names gemini, openai or anthropic. To pin a
model on an OpenAI-compatible server, use the app.
The Reranker row is read-only. Only SEARCH_RERANK_MODEL changes it.
| Model | Gemini | OpenAI | Anthropic |
|---|---|---|---|
| Fast model | gemini-3.5-flash-lite |
gpt-6-luna |
claude-haiku-4-5 |
| Strong model and Web search model | gemini-3.8-flash |
gpt-6-sol |
claude-sonnet-5 |
These are the fallbacks before a model list loads. Once it loads, each provider
takes the newest model of the same family. Gemini also skips a model that
Google paused with a 429 answer, until the pause ends. An OpenAI-compatible
server uses the first chat model in its list, for both the Fast model and
the Strong model.
Contrack loads each provider's model list when a key or a server is saved, at start, and once a day. Refresh the model list loads it at once. The list leaves out models that do not chat, deprecated models, and chat models more than a year old when the provider dates them. (?) after a model name marks a guess from the name, because OpenAI and OpenAI-compatible servers report bare model names. A pin to Gemini, OpenAI or Anthropic gets one small test request before it saves.
| Field | Rule |
|---|---|
| ID | Letters, numbers and hyphens. The provider's ID becomes custom:<ID>
|
| Name | The label in the app |
| Base URL | An http or https URL that ends in /v1, such as http://alpha:11434/v1
|
| API key (optional) | Stored encrypted. A local server needs none |
Contrack asks an OpenAI-compatible server for a strict JSON schema first. When the server refuses it, Contrack falls back to JSON mode, then to instructions in the prompt, and remembers what each model accepts.
- One model serves both vector indexes: search and duplicates.
- The built-in model is
Xenova/all-MiniLM-L6-v2, with 384 dimensions. It runs on a worker thread on the CPU. - A hosted model is an embedding model that Gemini, OpenAI or an OpenAI-compatible server lists. Anthropic has none. Contrack embeds a short text first to learn the vector width, and refuses a model that returns nothing.
- Gemini embeds a question, a contact and a duplicate check each with its own task type, which ranks better than one type for all three.
- A change rebuilds both indexes and embeds every contact again, in the background. Keyword search keeps working meanwhile.
- While AI is off for the instance, the built-in model serves, whatever is pinned.
- With a hosted model, the search index embeds new and changed contacts only after someone confirms on the Search by meaning card, under the embedding model.
- A hosted model embeds no contact of an account with Use AI for my account off, for search or for duplicates.
Two small models run on the CPU:
| Model | Use | Size |
|---|---|---|
Xenova/all-MiniLM-L6-v2 |
The built-in embedding model | About 24 MB |
Xenova/ms-marco-TinyBERT-L-2-v2 |
The local reranker for Ask Contrack | About 5 MB |
The server looks for each file in this order:
- the download cache,
TRANSFORMERS_CACHE(DATA_DIR/.cachewhenDATA_DIRis set, else a folder insidenode_modules) - the model folder,
MODEL_DIR(defaultDATA_DIR/models) - huggingface.co, when
MODEL_DOWNLOADSallows it
A download needs no Hugging Face account and sends no contact data. Hugging Face sees the server's address and the model names.
-
Docker. The image downloads both models at build time into
/app/models, and setsMODEL_DOWNLOADS=false. A container never reaches huggingface.co. -
Without Docker.
npm run models:fetchdownloads the files, pinned to one upstream commit, intoMODEL_DIR. It checks each file's SHA-256 and skips a file that is already there. Then setMODEL_DOWNLOADS=false. -
Script options.
npm run models:fetch -- --checkchecks the folder and downloads nothing.npm run models:fetch -- <folder>fills another folder.HF_ENDPOINTpoints the script at a mirror. The script reads.envin the working directory, as the server does, so it fills the folder thatDATA_DIRorMODEL_DIRnames there. -
Another model. A
SEARCH_RERANK_MODELor embedding model outside the pinned list is not in the image. SetMODEL_DOWNLOADS=trueto let the server download it once, or copy its files intoMODEL_DIR/<model id>/.
With MODEL_DOWNLOADS=false and a file missing, the model does not load. The
log names the folder and the command that fixes it, and search keeps working
on keywords.
The map draws OpenFreeMap styles. They need no API key and no sign-up. Two variables point each palette at another style:
MAP_STYLE_LIGHT="https://tiles.openfreemap.org/styles/positron"
MAP_STYLE_DARK="https://tiles.openfreemap.org/styles/dark"These two values are the defaults. A value is an https:// URL with no user
name or password, or a root-relative path such as /map/style.json. A value
the server cannot read writes one warning to the log, and the default style
loads.
The Content-Security-Policy allows the origin of each style URL. A root-relative style adds nothing, because it is on the same origin. A style cannot load tiles, glyphs or sprites from a third host. Serve them from the style's host, or from Contrack.
Contrack can serve its own basemap, with no tile server. The map reads tiles
from one .pmtiles archive with pmtiles://, and the server answers the
range requests.
-
The tiles. Get a planet build from Protomaps, and cut it to your area with the
pmtilestool. The box is west, south, east, north:pmtiles extract https://build.protomaps.com/20260901.pmtiles \ public/map/area.pmtiles --bbox=-0.6,51.2,0.4,51.8
-
The glyphs and the sprite. Copy the
fonts/andsprites/folders of protomaps/basemaps-assets intopublic/map/. -
The style, at
public/map/style.json. The source names the archive with a root-relative path. The@protomaps/basemapspackage writes the layers for a named theme.{ "version": 8, "glyphs": "/map/fonts/{fontstack}/{range}.pbf", "sprite": "/map/sprites/v4/light", "sources": { "protomaps": { "type": "vector", "url": "pmtiles:///map/area.pmtiles", "attribution": "© OpenStreetMap" } }, "layers": [ { "id": "background", "type": "background", "paint": { "background-color": "#f4f2ee" } }, { "id": "water", "type": "fill", "source": "protomaps", "source-layer": "water", "paint": { "fill-color": "#cfe0f0" } } ] } -
The setting. Set
MAP_STYLE_LIGHT="/map/style.json", and a dark style inMAP_STYLE_DARK, then restart.
The build copies public/ into dist/. On a running production instance, put
the files under dist/map/. With Docker, mount the folder at /app/dist/map.
Contrack places addresses on the map with Nominatim (OpenStreetMap). It needs no key and no setting.
- The server sends each address to
nominatim.openstreetmap.orgin the background, one request a second.NOMINATIM_URLsends them to your own Nominatim instead. - An admin turns lookups off with Look up addresses for the map in
Settings → Administration → General, or with
GEOCODING_DISABLED=true. Then no address leaves the server. A pin comes from an earlier lookup or by hand, and the map's place search answers only from the cache. - When an address finds nothing, the server tries a broader one: it drops the first part before a comma, up to four tries.
- Answers are cached for every account. An address that found nothing is tried again after 7 days. A daily job deletes the answers that no contact uses.
- The log names the contact, never the address.
- At start, the server queues contacts that have an address and no pin.
- The geocoder never moves a pin that a person placed (see Move a pin by hand).
Set the mail server in Settings → Administration → Outgoing mail, or with
SMTP_URL.
- The page's fields are Host, Port, Use TLS, Username, Password, From address and Reply-to. The password is stored encrypted.
-
SMTP_URLusessmtp://(plain or STARTTLS, port 587 by default) orsmtps://(TLS from the start, port 465 by default). Percent-encode special characters in the user name and the password. - With
SMTP_URLset, the page shows its values read only, andMAIL_FROMandMAIL_REPLY_TOapply. - Mail counts as set up only with a host and a sender address. Without
MAIL_FROM, the sender is the SMTP user name, when it is an email address. - Links in mail need
PUBLIC_URL(see Outgoing mail).
Contrack encrypts every credential that the database stores, with AES-256-GCM: AI provider keys and OpenAI-compatible server keys saved in the app, the SMTP password, connector credentials, and the Google OAuth client secret. Keys given as variables are not stored.
-
CONTRACK_SECRET_KEYholds the key as 64 hex characters (32 bytes). Make one withopenssl rand -hex 32. - Without it, Contrack writes a key to
DATA_DIR/secret.key, with mode0600, the first time it stores a credential. - A value that the key cannot open reads as missing. An AI provider then shows as not connected, and the log says that the saved key "cannot be decrypted". Enter the credential again.
- There is no key rotation. A new key means entering every stored credential again.
- Snapshots hold the encrypted values, so keep the key with them. The rest of the database is not encrypted.
| What | Kept for | Setting |
|---|---|---|
| Deleted contacts in Trash | 30 days, then deleted at the daily cleanup |
Trash in General, TRASH_RETENTION_DAYS
|
| Snapshots | The newest 7 |
Snapshots to keep in General, BACKUP_KEEP
|
| Audit log entries | 90 days | None |
| Connector run history | 90 days | None |
| AI usage activity | 30 days | None |
| Finished imports and their rows | 30 days | None |
| Revoked API tokens | 30 days after the revoke | None |
| Revoked or expired invitations | 30 days | None |
| Sign-in and reset link records | 30 days | None |
| Weekly score snapshots | 26 weeks | None |
| Merge history | 90 days, the time a merge can be undone | None |
| Cached address lookups | While a contact uses the address | None |
| Uploaded files that no row uses | 2 days, 31 for a link preview | None |
| Events, the record of each write | 30 days, once every reaction has read them | None |
| Finished background jobs | 1 day, 30 for a failed job. The newest run of each job stays | None |
| OAuth sign-in requests | 1 day after they expire | None |
| OAuth access and refresh tokens | Until they expire | None |
| OAuth app registrations | While no grant uses one: 1 day with no sign-in, or 30 days unused | None |
The trash cleanup runs at start and every 24 hours. A daily sweep removes the other rows and expired sessions, and checkpoints the database's write-ahead log. Daily jobs also delete a merged-away contact once its merge can no longer be undone, the cached address lookups that no contact uses, and the uploaded files that no row uses. An hourly sweep removes the OAuth rows. Privacy lists what each delete removes. The snapshot schedule is in Backups and restore.
Each account keeps its own settings on the server. They follow the person to
another device, and two accounts in one browser never share them. A settings
page with a changed value ends with Reset to defaults. Scripts read and
change them with GET and PATCH /api/auth/preferences (see
Authentication).
| Setting | Page | Choices | Default | Key |
|---|---|---|---|---|
| Theme | Appearance | Light, Dark, System | System | theme |
| Accent color | Appearance | Any color | #006a91 |
accent |
| Text size | Appearance | Default, Large | Default | textScale |
| Motion | Appearance | System, Reduced | System | motion |
| Corvid motion | Appearance | Full, Subtle, Off | Full | mascotMotion |
| List density | Appearance | Comfortable, Compact | Comfortable | listDensity |
| Where Contrack opens | Network and contacts | Network, Pulse | Network | startPage |
| Default sort | Network and contacts | Name, Recent | Name | listSort |
| Recent contacts | Network and contacts | 0 to 10. 0 hides the row | 3 | recentLimit |
| Default cadence | Network and contacts | Weekly, Monthly, Quarterly, Yearly | Quarterly | defaultCadenceDays |
| Track new contacts | Network and contacts | On, Off | Off | trackNewContacts |
| Week starts on | Network and contacts | Monday, Sunday | Monday | weekStart |
| Weather | Network and contacts | On, Off | Off | showWeather |
| Temperature unit | Network and contacts | °C, °F | °C | tempUnit |
| Single-key shortcuts | Keyboard | On, Off | On | singleKeyShortcuts |
| Use AI for my account | Privacy and AI | On, Off | On | aiAssist |
| Auto-merge sensitivity | Duplicates | Cautious, Balanced, Eager | Balanced | dedupePreset |
| Check new contacts automatically | Duplicates | On, Off | On | dedupeOnCreate |
| Check imports automatically | Duplicates | On, Off | On | dedupeOnImport |
| Enrich new contacts automatically | Contact enrichment | On, Off | Off | autoEnrich |
| Web search engine | Contact enrichment | Instance default, or an engine | Instance default | webSearchEngine |
- Default cadence stores days: 7, 30, 90 or 365. A value of 60 or 180 still loads, and the select shows it as a fifth choice.
-
Auto-merge sensitivity stores
conservative,defaultoraggressive. -
Use AI for my account shows as one Use AI switch on an instance
with one account. That switch is the instance's switch, and turning it on
also turns
aiAssistback on. -
Web search engine stores
default,provider,searxngorcombined.defaultfollows the engine that an admin sets for the instance. On an instance with one account, the page shows and changes the instance's engine, so this staysdefault. - Search history on Privacy and AI is not a preference. Contrack keeps each question that you ask in Ask Contrack and the command palette, and Clear history deletes them all (see History).
- The app also remembers four choices outside Settings: the Pulse layout
(
pulseLayout), whether the Ask Contrack history panel is open (askHistoryOpen, open by default), whether Map insights is open (mapPaneOpen, open by default), and the map layer (mapLayer, Pins or Heat, Pins by default).
An admin sets these for every account. They are in Settings → Administration.
| Setting | Page | Default | Range or form | Variable |
|---|---|---|---|---|
| Instance name | General | None (Contrack) | Up to 60 characters | None |
| Anyone can create an account | General | Off | On, Off | None |
| Sign in by emailed link | General | Off | Needs Outgoing mail | None |
| Session length | General | 30 days | 1 to 365 days, for new sign-ins | None |
| Trash | General | 30 days | 1 to 365 days | TRASH_RETENTION_DAYS |
| Backups | General | 24 hours | 0 to 168 hours. Off is 0 | BACKUP_INTERVAL_HOURS |
| Snapshots to keep | General | 7 | 1 to 50 in the app, 1 to 100 by variable | BACKUP_KEEP |
| Look up addresses for the map | General | On | On, Off | GEOCODING_DISABLED |
| Google OAuth client | General | None | A client ID and a client secret |
GOOGLE_OAUTH_CLIENT_ID, GOOGLE_OAUTH_CLIENT_SECRET
|
| Mail server | Outgoing mail | None | Host, port, TLS, user, password, sender, Reply-To |
SMTP_URL, MAIL_FROM, MAIL_REPLY_TO
|
| Use AI on this instance | AI | On | On, Off | AI_DISABLED |
| Provider keys and OpenAI-compatible servers | AI | None | One key per provider, any number of servers |
GEMINI_API_KEY, OPENAI_API_KEY, ANTHROPIC_API_KEY
|
| Fast model, Strong model | AI | Automatic | A model |
AI_QUICK_MODEL, AI_DEEP_MODEL
|
| Embedding model | AI | Built-in | A model | AI_EMBEDDINGS_MODEL |
| Allow web search | AI | On | On, Off | None |
| Web search model | AI | Automatic | A Gemini, OpenAI or Anthropic model | AI_RESEARCH_MODEL |
| SearXNG address | AI | None | An http or https URL, not a cloud metadata or link-local address |
SEARXNG_URL |
| Web search engine | AI | The provider's own search | The provider, SearXNG, or both | None |
The Trash, Backups and Snapshots to keep rows offer set choices. A value set another way shows as it is, with a note. A change to Backups restarts the schedule at once.
These pages are written from docs/ in arvarik/contrack. Change the source, then run npm run docs:wiki again.
Start here
Use Contrack
- Contacts
- Pulse and tracking
- Search and Ask Contrack
- Map
- Duplicates
- Import, sync, and export
- AI
- Keyboard shortcuts
- Accessibility
Run Contrack
Comparisons
- Contrack vs Monica
- Contrack vs Clay
- Contrack vs Folk
- Contrack vs Twenty
- Contrack vs Huly
- Contrack vs EspoCRM
- Contrack vs Nextcloud Contacts
Build on Contrack