Setting up AI features
What lawlint init does, which providers are supported, and where API keys are stored.
Linting is deterministic and offline. Two features are not — the soft-rule AI
judge and lawlint learn — and
neither does anything until you configure a model.
lawlint init
The walkthrough covers AI-model choice, whether the judge runs on every lint,
Markdown handling for stdin, and custom rule directories. It writes
.lawlint/config.json, plus an optional starter rules package under
.lawlint/rules/.
Hosted providers
The recommended path: better quality, no multi-gigabyte download.
| Provider | Model spec | Key |
|---|---|---|
| Anthropic (recommended) | anthropic:<model> |
ANTHROPIC_API_KEY |
| OpenAI-compatible | openai:<base-url>#<model> |
OPENAI_API_KEY |
| Azure AI Foundry | foundry:<deployment> |
AZURE_FOUNDRY_API_KEY |
API keys go to a user-level credential file — ~/.lawlint/credentials, mode
0600 — or to the environment. The environment wins. Keys are never
written into your project, so .lawlint/config.json is safe to commit.
Once a key and a model are configured, the soft rules run on every lint,
including in directories with no project config. --no-ai skips them for a
run; "judge": { "enabled": false } turns them off for good.
Before 0.8 the credential file lived at ~/.config/lawlint/credentials. It is
still read from there, and the next lawlint init moves it to ~/.lawlint/
and reports the move.
Keeping text on your machine
lawlint has no built-in model. If the document must not leave your machine — privileged material, a client matter under an engagement term that forbids it — run an OpenAI-compatible server yourself and point lawlint at it:
ollama serve && ollama pull qwen3:30b
lawlint init --ai openai:http://localhost:11434/v1#qwen3:30b
That spec needs no API key, and nothing but your own server ever sees the text. Ollama, vLLM, llama.cpp and LM Studio all speak this protocol.
Non-interactive setup
lawlint init --yes # accept defaults (hosted)
lawlint init --ai anthropic:claude-haiku-4-5-20251001
lawlint init --ai openai:http://localhost:11434/v1#qwen3:30b # self-hosted
lawlint init --force # overwrite an existing config
--yes?flag
Accept the default answer for every prompt.
flag--force?flag
Overwrite an existing .lawlint/config.json.
flag--ai?string
Model spec, skipping the catalog prompt (anthropic:<model>, openai:<base-url>#<model>, foundry:<deployment>).
stringWhat it writes
// .lawlint/config.json — every field optional, camelCase
{
"ai": {
"model": "anthropic:claude-haiku-4-5-20251001",
"features": { "judge": "...", "learn": "..." },
},
"judge": { "enabled": false },
"markdown": false,
"ruleDirs": [".lawlint/rules"]
}
ai.model is the default for every AI feature; ai.features overrides it per
feature. The full schema is in
Configuration.
Where config is found
The CLI walks up from the current directory looking for .lawlint/config.json,
falling back to the legacy lawlint.config.json at each level. The first
directory containing either is the project root, and relative ruleDirs
resolve against it.
A config file that exists but does not parse is a configuration error — exit
2 — never a silent skip.