Configuration
Maina works with zero configuration. Everything below is optional and lets you customize behavior as your needs grow.
Config File
Section titled “Config File”Create maina.config.ts in your project root:
import { defineConfig } from 'maina';
export default defineConfig({ models: { mechanical: 'google/gemini-2.5-flash', standard: 'anthropic/claude-sonnet-4', architectural: 'anthropic/claude-sonnet-4', local: 'ollama/qwen3-coder-8b', }, provider: 'openrouter', budget: { daily: 5.00, perTask: 0.50, alertAt: 0.80, },});Model Tiers
Section titled “Model Tiers”Every AI call uses a specific tier. You choose which model fills each tier.
| Tier | Used for | Default example |
|---|---|---|
| mechanical | Tests, commit messages, slop detection, context compression | google/gemini-2.5-flash |
| standard | Reviews, plans, design docs, explanations | anthropic/claude-sonnet-4 |
| architectural | Design review, architecture decisions, prompt evolution | anthropic/claude-sonnet-4 |
| local | Offline use via Ollama — slop detection, commit messages | ollama/qwen3-coder-8b |
Models are specified as provider/model-name strings. Maina uses OpenRouter by default, giving access to 300+ models through a unified interface.
Free tier
Section titled “Free tier”With no API key, Maina still works:
- Deterministic verification (Biome, Semgrep, Trivy, etc.) runs normally
- Point the
localtier to Ollama for offline AI features - AI-dependent features gracefully degrade
Constitution
Section titled “Constitution”The constitution is your project’s non-negotiable rules. Generated by maina init and stored at .maina/constitution.md.
# Project Constitution
## Stack- Runtime: Bun- Language: TypeScript strict- Lint/Format: Biome 2.x (NOT ESLint/Prettier)- Test: bun:test (NOT Jest)- Error handling: Result<T, E> pattern. Never throw.
## Architecture- All DB access through repository layer- API responses: { data, error, meta } envelope- Feature modules are self-contained packages
## Verification- All commits pass: biome check + tsc --noEmit + bun test- PR reviews require spec compliance before code quality- Mutation testing score > 80% on changed code- No console.log in production codeThe constitution is:
- Injected as preamble into every AI call
- Stable DNA — not subject to A/B testing or prompt evolution
- Editable — update it directly when your project fundamentals change
- Per-project — different repos have different constitutions
Custom Prompts
Section titled “Custom Prompts”Drop markdown files in .maina/prompts/ to control AI behavior per task:
.maina/prompts/ review.md # What to focus on during code reviews tests.md # How your team writes tests commit.md # Commit message style and conventions plan.md # Planning document structureEdit prompts with the CLI:
maina prompt edit review # Opens .maina/prompts/review.md in $EDITORmaina prompt list # Shows all prompts with version hashes and accept ratesCustom prompts:
- Override defaults — Maina ships built-in prompts for each task; your custom prompts take priority
- Are versioned — every prompt is hashed, with usage and accept rates tracked per version
- Evolve from feedback —
maina learnanalyzes accept/reject patterns and proposes improvements - Support A/B testing — improved prompts are tested at 80/20 split against the previous version
Environment Variables
Section titled “Environment Variables”| Variable | Description | Required |
|---|---|---|
MAINA_API_KEY | OpenRouter API key for AI features | No (deterministic verification works without it) |
OPENROUTER_API_KEY | Alternative name for the API key | No |
MAINA_MODEL_MECHANICAL | Override the mechanical model tier | No |
MAINA_MODEL_STANDARD | Override the standard model tier | No |
MAINA_MODEL_ARCHITECTURAL | Override the architectural model tier | No |
MAINA_MODEL_LOCAL | Override the local model tier | No |
EDITOR | Editor used by maina prompt edit | No (defaults to vi) |
Environment variables override config file values. This is useful for CI or per-developer overrides.
Lifecycle Hooks
Section titled “Lifecycle Hooks”Shell scripts in .maina/hooks/ execute at lifecycle boundaries:
.maina/hooks/ pre-commit.sh # Before verification gates post-commit.sh # After successful commit pre-verify.sh # Before verification pipeline post-verify.sh # After verification completes pre-review.sh # Before AI review post-learn.sh # After prompt evolutionHooks receive JSON on stdin with event context. An exit code of 2 blocks the action. This enables custom integrations without a plugin API.