HARVEY.md
Project-specific guidance for the harvey coding agent (Go).
Agent execution model
Harvey automatically executes certain structured outputs from your replies:
Tagged code blocks trigger a write proposal — if you include a fenced code block whose opening fence names a target file, Harvey proposes writing that file and asks the user to confirm (Y/n) before touching the filesystem. Parent directories are created as needed.
Two fence formats are recognized — pick whichever reads more naturally:
#!/bin/bash
echo "Hello World"typescript libguides/auth.ts export async function authenticate(clientId: string): Promise<string> { // ... }
The file path must be on the opening fence line
(after the language tag). A path in a comment inside the block
(// libguides/auth.ts) is not picked up —
Harvey only reads the fence tag.
Use this format whenever you want to create or update a file.
Session recording produces a .spmd
screenplay script when active (-r flag at startup or
/record start). Turns appear as USER / HARVEY dialogue
blocks; actions and stats appear as Fountain notes ([[…]]).
Safe mode applies to all auto-executed commands.
When safe mode is on (the default, shown as harvey > in
the prompt), only commands in the configured allowlist will execute —
others are blocked. When safe mode is off (shown as
harvey [unsafe] > in red), all commands are permitted.
Do not instruct the user to disable safe mode.
File reading capabilities
When asked to read a file, Harvey handles these formats automatically:
- Plain text, Markdown, source code — returned as-is.
- PDF (.pdf) — text is extracted using the poppler
utilities (pdfinfo, pdftotext). No user conversion is needed. Use the
optional
pagesparameter to read a subset (e.g."1-10"or"5"). - Images (.png, .jpg, .jpeg, .gif, .webp) — injected directly when the active model supports vision input.
Never ask the user to convert a PDF to text before reading it. Call
read_file with the .pdf path directly.
Documentation conventions
All exported functions, structs/types, interfaces, and constants must
be documented with a /** ... */ block comment. Each comment
must include:
- A description of what the symbol is or does
- Parameters — name, type, and purpose for each
- Return values — type and meaning
- An embedded usage example
/** Greet returns a greeting string for the given name.
*
* Parameters:
* name (string) — the person to greet
*
* Returns:
* string — a greeting message
*
* Example:
* msg := Greet("Alice")
* fmt.Println(msg) // "Hello, Alice!"
*/
func Greet(name string) string {
return "Hello, " + name + "!"
}Apply to every exported symbol — functions, structs, interfaces, type aliases, and constants. Do not omit the example section even for simple symbols.
Build & test
All commands should be run from inside harvey/.
# Build all programs
make build
# Run tests
go test
# Build a single program
go build -o bin/<name> cmd/<name>/*.go
# Generate version.go from codemeta.json
cmt codemeta.json version.go
# Build website (HTML from Markdown via pandoc)
make website
# Clean build artifacts
make cleanProvenance
When you use content that came from a RAG retrieval, attribute the source at the point you use it — not in a trailing bibliography or footnote block. The reader needs to know which claim comes from which source as they read, not after the fact.
Inline attribution pattern:
The WAL-mode pragma improves concurrent read throughput (source:
docs/sqlite-wal.md).
SHA-256 content hashing on ingest prevents duplicate chunks (from: Harvey S1 design notes,
rag_support.go).
If the chunk has a DOI or URL, prefer the identifier over the file path:
Cosine similarity is the standard measure for dense vector retrieval (source: doi:10.1234/ir-survey).
Workflow when recording observations:
- Ask your question — RAG fires automatically when relevant chunks exist.
- After answering, run
/kb observe finding Your insight here. - Harvey will list the RAG sources it used. Link them immediately:
/kb cite SOURCE_ID [SOURCE_ID …] - Use
/kb show OBS_IDto review the linked sources and check for retraction warnings before acting on the observation.
Do not skip /kb cite with the intention of linking
“later” — the association between an observation and its evidence
degrades quickly once the context moves on.
Key conventions
version.gois generated bycmt— do not edit by hand.bin/,dist/,man/,testout/are gitignored build artifacts.- Source lives at the package level (
harvey/*.go); CLI entry points go undercmd/<program>/. - See the root
CLAUDE.mdfor full toolchain dependencies and release targets.