Harvey uses a workspace-local configuration system. All configuration files live inside the workspace — the directory where Harvey is launched. A HARVEY.md file in the workspace root provides the system prompt, and environment variables supply cloud provider API keys.
┌─────────────────────────────────────────────────────────────┐
│ CONFIGURATION SOURCES │
├─────────────────────────────────────────────────────────────┤
│ 1. Workspace Config <workspace>/agents/harvey.yaml │
│ 2. System Prompt <workspace>/HARVEY.md │
│ 3. Environment Variables Shell environment │
└─────────────────────────────────────────────────────────────┘
Precedence: Workspace config > System prompt > Environment variables
<workspace>/agents/harvey.yaml)Purpose: Workspace-level configuration for Harvey’s subsystems: knowledge base, sessions, skills, RAG stores, and model cache.
Locations: Workspace:
<workspace>/agents/harvey.yaml
Format: YAML
Example:
# Knowledge base
knowledge_db: "agents/knowledge.db"
# Session recordings
sessions_dir: "agents/sessions"
# Skills/agents directory
agents_dir: "agents"
# Auto-record setting (null = use default)
auto_record: true
# Model capability cache
model_cache_db: "agents/model_cache.db"
# RAG configuration
rag:
enabled: true
active: "default"
stores:
- name: "default"
db_path: "agents/rag/default.db"
embedding_model: "nomic-embed-text"
model_map:
"llama3.1:latest": "nomic-embed-text"
"granite-code:3b": "nomic-embed-text"
"mistral:latest": "nomic-embed-text"
- name: "deno_typescript"
db_path: "agents/rag/deno_typescript.db"
embedding_model: "nomic-embed-text"
model_map:
"llama3.1:latest": "nomic-embed-text"Top-Level Fields:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
knowledge_db |
string | No | "agents/knowledge.db" |
Path to knowledge base SQLite file |
sessions_dir |
string | No | "agents/sessions" |
Directory for session recordings |
agents_dir |
string | No | "agents" |
Directory for skills/agents tree |
auto_record |
boolean/null | No | true |
Auto-record sessions (null = keep default) |
model_cache_db |
string | No | "agents/model_cache.db" |
Path to model capability cache |
rag |
object | No | See below | RAG configuration |
RAG Configuration (rag:):
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
enabled |
boolean | No | false |
Whether RAG is enabled |
active |
string | No | "" |
Name of active RAG store |
stores |
array | No | [] |
Array of named RAG stores |
RAG Store Fields:
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Unique store identifier |
db_path |
string | Yes | Path to SQLite database file |
embedding_model |
string | Yes | Embedding model name (e.g., nomic-embed-text) |
model_map |
object | No | Mapping of generation model → embedding model |
embedder_kind |
string | No | "ollama" |
embedder_url |
string | No | Base URL for encoderfile embedder |
Important Notes: - Paths are relative to the
workspace root - The model_map ensures each generation
model uses the correct embedding model - Embedding model binding is
enforced: you cannot mix embeddings from different models in the same
store
Security Configuration:
The following fields control Harvey’s security features and are also
persisted in harvey.yaml by the /safemode,
/permissions, and related commands.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
safe_mode |
boolean | No | false |
Enable command allowlist (see /safemode) |
allowed_commands |
string list | No | See below | Commands permitted when safe_mode is true |
permissions |
object | No | Full access | Path-prefix permission map (see below) |
run_timeout |
string | No | "5m" |
Timeout for shell commands run via ! or
/run |
ollama_timeout |
string | No | "" (none) |
HTTP timeout for local LLM providers; empty or "0"
means no timeout |
Default allowed_commands:
ls, cat, grep, head,
tail, wc, find,
stat, jq, htmlq,
bat, batcat
Timeout format (run_timeout,
ollama_timeout): Go duration string or plain integer
seconds. Examples: "5m", "300",
"1m30s", "300s". ollama_timeout
should be left unset (no timeout) for local hardware where inference can
take several minutes.
permissions map — keys are path
prefixes relative to the workspace root; values are lists of allowed
actions (read, write, exec,
delete). Harvey checks the most specific matching prefix.
Default is full access to ..
permissions:
".": [read, write, exec, delete] # workspace root — full access
"docs/": [read] # docs tree — read-only
"scripts/": [read, exec] # scripts — run but not modifyPermission rules: - Prefix "." matches all paths (used
as the catch-all default). - A more specific prefix (longer string)
takes priority over a shorter one. - If no prefix matches, access is
denied (secure by default). - The
/permissions REPL command updates these settings and
persists them.
Example harvey.yaml with security settings:
safe_mode: true
allowed_commands:
- ls
- cat
- grep
- git
run_timeout: "5m"
ollama_timeout: "" # no timeout for local Ollama
permissions:
".": [read, write, exec, delete]
"docs/": [read]<workspace>/agents/routes.json)Purpose: Persists routing endpoints and routing state across Harvey sessions.
Location:
<workspace>/agents/routes.json
Format: JSON
Example:
{
"enabled": true,
"endpoints": [
{
"name": "pi2",
"url": "ollama://192.168.1.12:11434",
"model": "llama3.1:8b",
"kind": "ollama"
},
{
"name": "claude",
"url": "anthropic://",
"model": "claude-3-haiku",
"kind": "anthropic"
},
{
"name": "pi3",
"url": "ollama://192.168.1.13:11434",
"model": "mistral:latest",
"kind": "ollama"
}
]
}Fields:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
enabled |
boolean | No | false |
Whether routing is enabled globally |
endpoints |
array | No | [] |
List of registered remote endpoints |
Endpoint Fields:
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Unique identifier for the endpoint |
url |
string | Yes | URL including scheme (e.g., ollama://host:port) |
model |
string | No | Default model to use with this endpoint |
kind |
string | No | Inferred from URL scheme |
URL Schemes:
| Scheme | Kind | Backend Type | Notes |
|---|---|---|---|
ollama://host:port |
ollama | Ollama server | Local or remote |
http://host:port |
ollama | Ollama server | HTTP (insecure) |
https://host:port |
ollama | Ollama server | HTTPS (secure) |
llamafile://host:port |
llamafile | Llamafile server | OpenAI-compatible |
llamacpp://host:port |
llamacpp | llama.cpp server | OpenAI-compatible |
anthropic:// |
anthropic | Anthropic Claude | Uses ANTHROPIC_API_KEY |
deepseek:// |
deepseek | DeepSeek API | Uses DEEPSEEK_API_KEY |
gemini:// |
gemini | Google Gemini | Uses GEMINI_API_KEY or GOOGLE_API_KEY |
mistral:// |
mistral | Mistral API | Uses MISTRAL_API_KEY |
openai:// |
openai | OpenAI API | Uses OPENAI_API_KEY |
Commands: - /route add NAME URL [MODEL]
— Register a new endpoint - /route rm NAME — Remove an
endpoint - /route list — List all endpoints with status -
/route on — Enable routing globally -
/route off — Disable routing globally -
/route status — Show routing state
<workspace>/HARVEY.md)Purpose: Provides the system prompt for Harvey’s LLM interactions. This is the primary way to give the model context about your project, conventions, and guidelines.
Location: <workspace>/HARVEY.md
(loaded from the workspace root at startup)
Format: Markdown with optional dynamic markers
Example:
You are Harvey, a terminal coding agent. You are working in a Go project
located at /home/user/myproject.
## Project Context
Today: <!-- @date -->
Current git status:
<!-- @git-status -->
Workspace files:
<!-- @files -->
## Conventions
- Use Go 1.26+ features
- Prefer stdlib over third-party packages
- All exported symbols need doc comments
- Use `t.TempDir()` in tests
## Available Tools
You have access to the following slash commands: /read, /write, /run, /search,
/git, /apply, /clear, /summarize, /context, /kb, /rag, /ollama, /route, /skill.
## Rules
1. Tag code blocks with file paths for auto-apply
2. Use /run to suggest shell commands
3. Never narrate fake command outputDynamic Markers: Harvey expands these before injecting the system prompt:
| Marker | Replaced With | Example |
|---|---|---|
<!-- @date --> |
Current date (YYYY-MM-DD) | 2026-05-04 |
<!-- @files --> |
Workspace file tree (hidden dirs excluded) | Tree listing |
<!-- @git-status --> |
Output of git status --short |
M README.md |
Notes: - The prompt is re-injected after
/clear - Pinned context (from /context add) is
injected after the system prompt - Skills catalog can be injected into
the prompt via configuration
Harvey reads environment variables for cloud provider API keys. These are optional and only needed when using the corresponding route types.
| Variable | Provider | Route Scheme | Purpose |
|---|---|---|---|
ANTHROPIC_API_KEY |
Anthropic | anthropic:// |
Claude API key |
DEEPSEEK_API_KEY |
DeepSeek | deepseek:// |
DeepSeek API key |
GEMINI_API_KEY |
gemini:// |
Gemini API key (primary) | |
GOOGLE_API_KEY |
gemini:// |
Gemini API key (fallback) | |
MISTRAL_API_KEY |
Mistral | mistral:// |
Mistral API key |
OPENAI_API_KEY |
OpenAI | openai:// |
OpenAI API key |
OLLAMA_HOST |
Ollama | ollama:// |
Ollama server host (default: localhost) |
OLLAMA_ORIGINS |
Ollama | ollama:// |
CORS origins for Ollama |
OLLAMA_KEEP_ALIVE |
Ollama | ollama:// |
Keep-alive interval (default: 24h) |
Note: For local Ollama, Harvey uses the
ollama command-line tool’s configuration by default. The
OLLAMA_HOST environment variable can override the default
http://localhost:11434.
# 1. Start Harvey for the first time (creates defaults)
harvey
# 2. Register remote endpoints
harvey
> /route add pi2 ollama://192.168.1.12:11434 llama3.1:8b
harvey
> /route on
# 3. Configure RAG (optional)
harvey
> /rag new golang
harvey
> /rag switch golang
harvey
> /rag on
# 4. Create workspace-specific config
mkdir -p myproject/agents
echo 'knowledge_db: myproject/agents/knowledge.db' > myproject/agents/harvey.yaml
# 5. Run Harvey in the project
harvey -w myprojectWorkspace (myproject/agents/harvey.yaml):
rag:
enabled: true
active: golang
stores:
- name: golang
db_path: myproject/agents/rag/golang.db
embedding_model: nomic-embed-text
Result: In myproject/, the golang store is active.
“No routes configured” - Run
/route add NAME URL to register endpoints - Run
/route on to enable routing - Check
<workspace>/agents/routes.json exists
“Knowledge base not found” - Harvey creates it
automatically at first use - Check agents/knowledge.db
exists - Verify path in harvey.yaml or create the
directory
“Model cache not found” - Harvey creates it
automatically - Check agents/model_cache.db exists - Run
/ollama probe to populate it
“RAG store not found” - Run
/rag new NAME to create a store - Run
/rag switch NAME to activate it - Verify the database file
exists at the specified path
# Check workspace routes
harvey --help routing # or: cat agents/routes.json
# Check workspace config
cat agents/harvey.yaml
# Check knowledge base
sqlite3 agents/knowledge.db ".tables"
# Check model cache
sqlite3 agents/model_cache.db "SELECT count(*) FROM models;"
# Check RAG stores
ls -la agents/rag/*.db<workspace>/agents/routes.json){
"enabled": true/false,
"endpoints": [
{
"name": "string (required)",
"url": "string (required)",
"model": "string (optional)",
"kind": "string (optional, auto-detected)"
}
]
}<workspace>/agents/harvey.yaml)# Paths
knowledge_db: "string (optional, default: agents/knowledge.db)"
sessions_dir: "string (optional, default: agents/sessions)"
agents_dir: "string (optional, default: agents)"
model_cache_db: "string (optional, default: agents/model_cache.db)"
# Behavior
auto_record: true/false/null # null = use default (true)
# RAG Configuration
rag:
enabled: true/false
active: "string (store name)"
stores:
- name: "string"
db_path: "string"
embedding_model: "string"
model_map:
"generation-model": "embedding-model"
embedder_kind: "ollama" # or "encoderfile"
embedder_url: "http://host:port"For more details on specific subsystems, see: - ROUTING.md — Remote endpoint routing - KNOWLEDGE_BASE.md — Knowledge base schema - RAG_Support_Design.md — RAG implementation details - SESSIONS.md — Session recording format