Skip to content

Configuration reference

Reference · Configuration

AskDB resolves config from two sources: an askdb.config.* file (TypeScript or JavaScript) and environment variables. Both are loaded by @askdb/config at startup into an in-memory runtime snapshot.

askdb init scaffolds this file. It uses defineConfig for type safety:

import { defineConfig, env } from "@askdb/config";
export default defineConfig({
ai: {
provider: "openai",
providerConfig: {
openai: {
apiKey: env("OPENAI_API_KEY"),
model: env("OPENAI_MODEL"),
},
},
},
introspection: {
provider: "postgres",
providerConfig: {
postgres: { databaseUrl: env("DATABASE_URL") },
},
outputDir: "./my-app.schema",
},
rag: {
embedder: "openai",
store: "pgvector",
storeConfig: {
pgvector: { databaseUrl: env("PGVECTOR_URL") },
},
},
logging: {
level: "info",
},
});

Use the env() helper (rather than process.env) so AskDB can capture which environment variables your config depends on and apply its defaults pass.

defineConfig returns the object unchanged at runtime — it exists only for type inference. The full type is AskDbConfig.

bootstrapAskDbEnv() looks for config in the current working directory only (no upward walk), trying two locations in order:

  1. askdb.config.<ext> — extension precedence ts → mts → cts → js → mjs → cjs
  2. .config/askdb.<ext> — same extension precedence

The first match wins. JSON config files are not supported. If nothing is found, bootstrapAskDbEnv() throws — run your process from the directory that holds the config (or pass cwd in its options).

AskDB reads .env next to your process via dotenv, then evaluates your askdb.config.*. You choose the variable names — they’re whatever you pass to env("…") in your config. The scaffolded config uses these common names; rename any of them in your config and .env together:

VariableReads into (config field)Notes
OPENAI_API_KEYai.providerConfig.openai.apiKeyStandard OpenAI key.
OPENAI_MODELai.providerConfig.openai.modelOptional model override. Default: gpt-4o-mini.
ANTHROPIC_API_KEYai.providerConfig.anthropic.apiKeyWhen ai.provider = "anthropic". Default model: claude-sonnet-4-6.
AZURE_API_KEY, AZURE_RESOURCE_NAMEai.providerConfig.azure.*Azure OpenAI.
DATABASE_URLintrospection.providerConfig.postgres.databaseUrlPostgres introspection connection.

Everything else AskDB needs — output directory, mode, log level, Studio query connection, the vector-store URL — is set the same way: a field in askdb.config.ts, bound to a name you choose with env("…"). You don’t set any AskDB-prefixed variables yourself; AskDB derives its internal runtime values from your config.

ai.provider accepts any string — not just the first-party literals. When an unknown provider string is used, AskDB applies a generic branch: you supply ai.providerConfig.custom.{apiKey, baseUrl, model} (each bound to a name you choose with env("…")), and AskDB hands them to whatever adapter is registered under that provider name.

import { defineConfig, env } from "@askdb/config";
export default defineConfig({
ai: {
provider: "mistral", // any string
providerConfig: {
custom: {
apiKey: env("MISTRAL_API_KEY"),
model: "mistral-large-latest",
},
},
},
// ...
});

This works end to end only when the consuming registry has an adapter registered under that provider name. First-party apps (@askdb/http-api, the CLI) register openai, azure, foundry, google, and anthropic. For any other provider you have two options:

  1. Embed AskDB and register your own adapter via createAiRegistry — about 40 lines of code.
  2. Use the openai provider with a custom baseUrl for any OpenAI-compatible endpoint (vLLM, OpenRouter, Together, Ollama, …).

See Bring your own model for the embedding walkthrough.

In code that uses the AskDB libraries directly, call bootstrapAskDbEnv() at startup and then read settings via getAskDbRuntimeConfig():

import { bootstrapAskDbEnv, getAskDbRuntimeConfig } from "@askdb/config";
bootstrapAskDbEnv({ cwd: process.cwd() });
const rt = getAskDbRuntimeConfig();
const aiEnv = rt.ai.aiEnv; // provider + key/model env map
const outputDir = rt.introspection.outputDir; // resolved artifact directory

AskDB does not copy the full config into process.env. The runtime snapshot is the source of truth — use getAskDbRuntimeConfig rather than process.env for anything AskDB-specific.

For any given setting, the precedence (highest wins) is:

  1. Per-call arguments — CLI flags (--mode, --schema, …) and ask() options.
  2. The askdb.config.* file — the single source of truth for the runtime snapshot.
  3. Built-in defaults applied for optional fields (e.g. outputDir./askdb/).

Environment variables don’t override the config file from the outside — they flow through it: every env("VAR") call in the config reads the environment when the file loads. .env is loaded first (without overwriting variables already set in the real environment), so the per-environment override story is: system env beats .env, and whatever env() reads lands in the snapshot. This still lets you ship one config file and vary it per environment — just route each tunable through env().