Coraline Documentation
Coraline is a local-first code intelligence engine that builds a semantic graph of your codebase and exposes high-precision tools over CLI and MCP.
This book is published from the repository and combines practical guides with full reference docs.
What You Can Do With Coraline
- Index and incrementally sync large codebases.
- Query symbols, call graphs, and impact radius.
- Build context for AI workflows.
- Use semantic search with local embeddings.
- Integrate with MCP clients.
Read Next
Start with Getting Started, then move to the CLI Reference and MCP Tools.
Getting Started
Install
Install from crates.io:
cargo install coraline
Initialize and Index
coraline init
coraline index
Optional: Semantic Search Model
coraline model download
coraline embed
By default, embedding runs a freshness check and auto-syncs stale indexed state before generating embeddings.
Start MCP Server
coraline serve --mcp
Next Steps
CLI Reference
Coraline CLI Reference
Coraline is invoked as coraline [COMMAND] [OPTIONS] [PATH].
When [PATH] is omitted, the current working directory is used as the project root.
Commands at a Glance
| Command | Description |
|---|---|
init | Initialize a new project |
index | Full reindex of the project |
sync | Incremental update (git-diff based) |
status | Show project status and paths |
stats | Show index statistics |
query | Search symbols by name |
context | Build AI context for a task |
callers | Find what calls a node |
callees | Find what a node calls |
impact | Analyze change impact radius |
config | Read or update configuration |
hooks | Manage git hooks |
serve | Start the MCP server |
update | Check for available updates on crates.io |
embed | Generate vector embeddings for indexed nodes |
model | Manage the ONNX embedding model |
coraline init [PATH]
Initialize Coraline in a project directory. Creates .coraline/ with a SQLite database, default config.toml, and initial memory templates.
When stdin is a TTY, prompts to download the embedding model (~137 MB) after initialization. Decline to skip — all non-embedding tools remain fully functional and you can download later with coraline model download.
If .coraline/ already exists and --index is passed without --force, init skips the overwrite and runs indexing directly on the existing project.
Options:
| Flag | Description |
|---|---|
-i, --index | Run a full index immediately after initialization |
-f, --force | Overwrite an existing .coraline/ directory without prompting |
--no-hooks | Skip automatic git hook installation |
Examples:
coraline init # Initialize current directory
coraline init /path/to/my-app # Initialize a specific path
coraline init -i # Initialize, prompt for model, then index
coraline init -i --no-hooks # Initialize and index, skip git hooks
coraline init --force # Wipe and reinitialize existing project
On success, creates:
.coraline/coraline.db— SQLite knowledge graph.coraline/config.toml— Annotated config template.coraline/memories/— Initial memory files.coraline/.gitignore— Excludes local data files from git.git/hooks/post-commit— Auto-sync hook (unless--no-hooks)
coraline index [PATH]
Perform a full reindex of the project. Parses all matching source files, extracts symbols and edges, resolves cross-file references, and stores results in the knowledge graph.
Options:
| Flag | Description |
|---|---|
-f, --force | Force re-parse all files, even unchanged ones |
-q, --quiet | Suppress progress output |
Examples:
coraline index # Index current directory
coraline index /path/to/project # Index a specific path
coraline index -f # Force full re-parse
coraline index -q # Silent (useful in scripts)
coraline sync [PATH]
Perform an incremental update using git-diff to identify changed files. Faster than a full index for routine updates.
Options:
| Flag | Description |
|---|---|
-q, --quiet | Suppress progress output |
Examples:
coraline sync # Sync current directory
coraline sync -q # Silent sync (used by git hook)
coraline status [PATH]
Show the current project status: initialization state, paths to config and database, database size, and git hook status.
Examples:
coraline status
Sample output:
Coraline Status
Project: /home/user/my-app
Config: /home/user/my-app/.coraline/config.toml
Database: /home/user/my-app/.coraline/coraline.db (1048576 bytes)
Git hooks: installed
coraline stats [PATH]
Show index statistics: file count, node count, edge count, and unresolved reference count.
Options:
| Flag | Description |
|---|---|
-j, --json | Output as JSON |
Examples:
coraline stats
coraline stats --json
Sample output:
Coraline Statistics
Files: 128
Nodes: 4201
Edges: 9872
Unresolved refs: 153
coraline query <SEARCH> [PATH]
Search for symbols in the knowledge graph by name. Uses SQLite full-text search (FTS5) for fast, fuzzy matching.
Arguments:
| Argument | Description |
|---|---|
SEARCH | Symbol name or search pattern |
Options:
| Flag | Description |
|---|---|
-p, --path PATH | Project root path |
-l, --limit N | Maximum results (default: 10) |
-k, --kind KIND | Filter by node kind (see below) |
-j, --json | Output as JSON |
Valid KIND values:
file, module, class, struct, interface, trait, protocol, function, method, property, field, variable, constant, enum, enum_member, type_alias, namespace, parameter, import, export, route, component
Examples:
coraline query resolve_unresolved
coraline query "index" --kind function --limit 5
coraline query Auth --json
coraline context <TASK> [PATH]
Build structured context for an AI task description. Searches the graph, traverses relationships, and returns relevant code snippets.
Arguments:
| Argument | Description |
|---|---|
TASK | Natural language task description |
Options:
| Flag | Description |
|---|---|
-p, --path PATH | Project root path |
-n, --max-nodes N | Max graph nodes (default: 50) |
-c, --max-code N | Max code blocks (default: 10) |
--no-code | Omit source code snippets |
-f, --format FMT | markdown (default) or json |
Examples:
coraline context "add authentication middleware"
coraline context "how does indexing work" --format json
coraline context "refactor database layer" --max-nodes 30 --max-code 5
coraline callers <NODE_ID> [PATH]
Find all nodes that call the specified node (incoming calls edges).
Arguments:
| Argument | Description |
|---|---|
NODE_ID | Node ID (from query or stats --json output) |
Options:
| Flag | Description |
|---|---|
-p, --path PATH | Project root path |
-l, --limit N | Maximum results (default: 20) |
-j, --json | Output as JSON |
Examples:
coraline callers abc123
coraline callers abc123 --limit 50 --json
coraline callees <NODE_ID> [PATH]
Find all nodes that the specified node calls (outgoing calls edges).
Same flags as callers.
coraline impact <NODE_ID> [PATH]
Analyze the impact radius of a symbol — what would be affected if it changed. Performs a BFS over incoming edges up to --depth hops.
Arguments:
| Argument | Description |
|---|---|
NODE_ID | Node ID to analyze |
Options:
| Flag | Description |
|---|---|
-p, --path PATH | Project root path |
-d, --depth N | BFS depth (default: 3) |
-j, --json | Output as JSON |
Examples:
coraline impact abc123
coraline impact abc123 --depth 5 --json
coraline config [PATH]
Read or update the project configuration at .coraline/config.toml.
Options:
| Flag | Description |
|---|---|
-p, --path PATH | Project root path |
-j, --json | Print config as JSON |
-s, --section SEC | Print only a section (indexing, context, sync, vectors) |
--set KEY=VALUE | Set a value: section.key=value |
Examples:
coraline config # Print full config (TOML)
coraline config --section context # Print one section
coraline config --json # Print as JSON
coraline config --set context.max_nodes=30 # Update a value
coraline config --set indexing.batch_size=50
coraline config --set vectors.enabled=true
coraline hooks <ACTION> [PATH]
Manage the git post-commit hook that runs coraline sync automatically after each commit.
Actions:
| Action | Description |
|---|---|
install | Install the hook (backs up existing hook) |
remove | Remove the hook (restores backup if present) |
status | Show whether the hook is installed |
Options:
| Flag | Description |
|---|---|
-p, --path PATH | Project root path |
Examples:
coraline hooks install
coraline hooks status
coraline hooks remove
coraline serve [PATH]
Start the MCP server. With --mcp, communicates over stdio using the Model Context Protocol.
Options:
| Flag | Description |
|---|---|
-p, --path PATH | Project root path |
--mcp | Start MCP stdio server (required) |
Examples:
coraline serve --mcp
coraline serve --mcp --path /path/to/project
Typically invoked by an MCP client (Claude Desktop, Claude Code, etc.) rather than directly.
coraline update
Check whether a newer version of Coraline is published on crates.io. Compares the running binary version against the latest release and prints upgrade instructions when an update is available.
Options: None.
Examples:
coraline update
Output (when up to date):
✓ coraline is up to date (v0.3.0)
Output (when update available):
Update available: v0.3.0 → v0.4.0
Run `cargo install coraline` to upgrade.
Environment Variables
| Variable | Description |
|---|---|
CORALINE_LOG | Log level filter (default: coraline=info). Examples: debug, coraline=trace, warn |
Examples:
CORALINE_LOG=debug coraline index
CORALINE_LOG=coraline=trace coraline serve --mcp
Logs are written to .coraline/logs/coraline.log (daily rotating) and to stderr at the configured level.
coraline embed [PATH]
Generate vector embeddings for all indexed nodes using the local ONNX model. Embeddings enable the coraline_semantic_search MCP tool.
By default, embed performs a lightweight freshness check and runs incremental sync first when indexed state is stale. This keeps embeddings aligned with current source files without requiring a manual coraline sync step.
Options:
| Flag | Description |
|---|---|
--download | Download the model automatically before embedding |
--variant FILENAME | ONNX variant to download (default: model_int8.onnx) |
--skip-sync | Skip automatic pre-embed sync check (embeddings may be stale) |
--batch-size N | Nodes per progress batch (default: 50) |
-q, --quiet | Suppress progress output |
Examples:
coraline embed # Embed using already-downloaded model
coraline embed --skip-sync # Skip auto-sync and embed current index state
coraline embed --download # Download model_int8.onnx then embed
coraline embed --download --variant model_fp16.onnx
Run coraline index first. Models are stored in .coraline/models/nomic-embed-text-v1.5/.
coraline model [PATH]
Manage the ONNX embedding model files.
coraline model download
Download model files from HuggingFace (nomic-ai/nomic-embed-text-v1.5).
| Flag | Description |
|---|---|
--variant FILENAME | ONNX variant to download (default: model_int8.onnx) |
-f, --force | Re-download even if files already exist |
-q, --quiet | Suppress progress output |
Downloads tokenizer.json, tokenizer_config.json, and the chosen ONNX weights into .coraline/models/nomic-embed-text-v1.5/.
Available variants (smallest to largest):
| Variant | Size | Notes |
|---|---|---|
model_q4f16.onnx | ~111 MB | Q4 + fp16 mixed (smallest) |
model_int8.onnx | ~137 MB | int8 quantized (recommended) |
model_fp16.onnx | ~274 MB | fp16 |
model.onnx | ~547 MB | full f32 |
coraline model status
Show which model files are present in the model directory.
coraline model status
MCP Tools
Coraline MCP Tools Reference
Coraline exposes 27 MCP tools when running as an MCP server (coraline serve --mcp).
All tool names are prefixed with coraline_ to avoid collisions with other MCP servers.
Protocol notes:
- Negotiates MCP protocol version
2025-11-25(with compatibility fallback to2024-11-05) - Expects
notifications/initializedafterinitializebefore normal requests tools/listsupports pagination viacursorandnextCursor
coraline_semantic_search is available by default (the embeddings feature ships enabled) but only registered when an ONNX model is present in .coraline/models/. Run coraline model download then coraline embed to activate it. The remaining 26 tools are typically available; memory-backed tools may be skipped if their initialization fails (e.g. due to filesystem or permission issues).
Background Auto-Sync
When the MCP server starts, it spawns a background thread that periodically checks index freshness and runs incremental sync when files have changed. This keeps the knowledge graph current without manual coraline_sync calls.
- Default interval: 120 seconds (configurable via
sync.auto_sync_interval_secsinconfig.toml) - Disable: Set
auto_sync_interval_secs = 0in[sync] - When embeddings are enabled and an ONNX model is present, newly-added nodes are automatically embedded after each background sync
- The background thread uses SQLite WAL mode for safe concurrent access alongside the main MCP request loop
Quick Reference
| Category | Tool | Description |
|---|---|---|
| Graph | coraline_search | Find symbols by name or pattern |
coraline_callers | Find what calls a symbol | |
coraline_callees | Find what a symbol calls | |
coraline_impact | Analyze change impact radius | |
coraline_dependencies | Outgoing dependency graph from a node | |
coraline_dependents | Incoming dependency graph (what depends on a node) | |
coraline_path | Find a path between two nodes | |
coraline_stats | Detailed graph statistics by language/kind/edge | |
coraline_find_symbol | Find symbols with rich metadata + optional body | |
coraline_get_symbols_overview | List all symbols in a file | |
coraline_find_references | Find all references to a symbol | |
coraline_node | Get full node details and source code | |
| Context | coraline_context | Build structured context for an AI task |
| File | coraline_read_file | Read file contents |
coraline_list_dir | List directory contents | |
coraline_find_file | Find files by glob pattern | |
coraline_get_file_nodes | Get all indexed nodes in a file | |
coraline_status | Show project index statistics | |
coraline_sync | Trigger incremental index sync | |
coraline_get_config | Read project configuration | |
coraline_update_config | Update a config value | |
coraline_semantic_search | Vector similarity search (requires model download — see below) | |
| Memory | coraline_write_memory | Write or update a project memory |
coraline_read_memory | Read a project memory | |
coraline_list_memories | List all memories | |
coraline_delete_memory | Delete a memory | |
coraline_edit_memory | Edit memory via literal or regex replace |
Graph Tools
coraline_search
Search for code symbols by name or pattern across the indexed codebase.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
query | string | ✅ | — | Symbol name or FTS pattern |
kind | string | — | Filter: function, method, class, struct, interface, trait, module | |
file | string | — | Filter results to this file path (relative or absolute) | |
limit | number | 10 | Maximum results |
Output:
{
"results": [
{
"node": {
"id": "abc123",
"kind": "function",
"name": "resolve_unresolved",
"qualified_name": "coraline::resolution::resolve_unresolved",
"file_path": "/path/to/resolution/mod.rs",
"start_line": 42,
"end_line": 95,
"language": "Rust",
"signature": "fn resolve_unresolved(conn: &mut Connection, ...)"
},
"score": 0.92
}
],
"count": 1
}
coraline_callers
Find all functions/methods that call a given symbol (incoming calls edges).
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
node_id | string | — | ID of the target node | |
name | string | — | Symbol name (alternative to node_id) | |
file | string | — | Disambiguate name by file path | |
limit | number | 20 | Maximum callers to return |
Either node_id or name must be provided. When name matches multiple symbols, supply file to disambiguate or the tool returns a listing of candidates.
Output:
{
"callers": [
{
"id": "def456",
"kind": "function",
"name": "index_all",
"qualified_name": "coraline::extraction::index_all",
"file_path": "/path/to/extraction.rs",
"start_line": 120,
"line": 158
}
],
"count": 1
}
coraline_callees
Find all functions/methods that a given symbol calls (outgoing calls edges).
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
node_id | string | — | ID of the source node | |
name | string | — | Symbol name (alternative to node_id) | |
file | string | — | Disambiguate name by file path | |
limit | number | 20 | Maximum callees to return |
Either node_id or name must be provided.
Output: Same shape as coraline_callers but field is callees.
Precision Notes:
- Call-edge resolution prefers extractor-provided candidate IDs (better locality signal) to avoid false-positive cross-project links in mixed active/legacy workspaces.
- When a call target is ambiguous and no scoped match exists, it is left unresolved (empty) rather than linked to a low-confidence global match.
- Results are ordered deterministically by (line, column, target) to ensure consistency across repeated queries.
coraline_impact
Analyze the impact radius of changing a symbol — finds everything that directly or transitively depends on it, via BFS over incoming calls and references edges.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
node_id | string | — | ID of the node to analyze | |
name | string | — | Symbol name (alternative to node_id) | |
file | string | — | Disambiguate name by file path | |
max_depth | number | 2 | BFS traversal depth | |
max_nodes | number | 50 | Cap on returned nodes |
Either node_id or name must be provided.
Output:
{
"nodes": [ ... ],
"edges": [ ... ],
"stats": {
"node_count": 12,
"edge_count": 15,
"file_count": 4,
"max_depth": 2
}
}
coraline_dependencies
Get the outgoing dependency graph from a node — what does this symbol import, call, or reference, recursively up to a configurable depth?
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
node_id | string | — | ID of the source node | |
name | string | — | Symbol name (alternative to node_id) | |
file | string | — | Disambiguate name by file path | |
max_depth | number | 2 | BFS traversal depth | |
max_nodes | number | 50 | Cap on returned nodes | |
edge_kinds | string[] | all | Edge kinds to follow (e.g. ["calls", "imports"]) |
Either node_id or name must be provided.
Output:
{
"root_id": "abc123",
"nodes": [ ... ],
"edges": [ ... ],
"stats": { "node_count": 8, "edge_count": 10, "file_count": 3, "max_depth": 2 }
}
coraline_dependents
Get the incoming dependency graph — what symbols depend on (call, import, or reference) this node, recursively?
Input: Same as coraline_dependencies (supports node_id or name + file).
Output: Same shape as coraline_dependencies but traversal follows edges in reverse.
coraline_path
Find a path between two nodes in the graph, using BFS over all edge kinds.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
from_id | string | Starting node ID | |
from_name | string | Starting node name (alternative to from_id) | |
from_file | string | Disambiguate from_name by file path | |
to_id | string | Target node ID | |
to_name | string | Target node name (alternative to to_id) | |
to_file | string | Disambiguate to_name by file path |
For each endpoint, either the _id or _name parameter must be provided.
Output:
{
"from_id": "abc123",
"to_id": "def456",
"path_found": true,
"path": ["abc123", "mid789", "def456"],
"length": 3
}
Returns { "path_found": false } if no path exists.
coraline_stats
Return detailed graph statistics: total counts, per-language file breakdown, node kind breakdown, and edge kind breakdown.
Input: None.
Output:
{
"totals": {
"nodes": 1842,
"edges": 4201,
"files": 47,
"unresolved_references": 123,
"vectors": 0
},
"files_by_language": { "rust": 28, "typescript": 14, "toml": 5 },
"nodes_by_kind": { "function": 412, "method": 287, "import": 201, "struct": 88 },
"edges_by_kind": { "contains": 1842, "calls": 987, "imports": 201, "exports": 178 }
}
coraline_find_symbol
Find symbols by name pattern with richer metadata than coraline_search, including optional source code body. Good for Foo/__init__-style path patterns.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
name_pattern | string | ✅ | — | Symbol name or substring |
kind | string | — | Same kind filter as coraline_search | |
file | string | — | Filter results to this file path | |
include_body | boolean | false | Attach source code body | |
limit | number | 10 | Maximum results |
Output: { "symbols": [...], "count": N } — each symbol includes docstring, is_exported, is_async, is_static, score, and optionally body.
coraline_get_symbols_overview
Get an overview of all symbols in a file, grouped by kind and ordered by line number.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
file_path | string | ✅ | Path to file (relative to project root or absolute) |
Output:
{
"file_path": "src/lib.rs",
"symbol_count": 14,
"by_kind": {
"function": [ ... ],
"struct": [ ... ]
},
"symbols": [ ... ]
}
coraline_find_references
Find all nodes that reference (call, import, extend, implement, etc.) a given symbol.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
node_id | string | — | ID of the target node | |
name | string | — | Symbol name (alternative to node_id) | |
file | string | — | Disambiguate name by file path | |
edge_kind | string | all | Filter: calls, imports, extends, implements, references | |
limit | number | 50 | Maximum references |
Either node_id or name must be provided.
Output: { "node_id": "...", "references": [...], "count": N } — each reference includes its edge_kind and the line number of the edge.
coraline_node
Get complete details for a specific node by ID, including its source code body read from disk.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
node_id | string | — | The node ID | |
name | string | — | Symbol name (alternative to node_id) | |
file | string | — | Disambiguate name by file path | |
include_edges | boolean | false | Also return incoming/outgoing edge counts |
Either node_id or name must be provided.
Output: Full node record including body (source lines), visibility, decorators, type_parameters, is_async, is_static, is_abstract, and optionally incoming_edge_count / outgoing_edge_count.
Context Tool
coraline_context
Build structured context for an AI task description. Searches the graph, traverses relationships, and returns relevant code snippets in Markdown or JSON format.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
task | string | ✅ | — | Natural language task description |
max_nodes | number | 20 | Max graph nodes to include | |
max_code_blocks | number | 5 | Max code block attachments | |
max_code_block_size | number | 1500 | Max chars per code block | |
include_code | boolean | true | Attach source code snippets | |
traversal_depth | number | 1 | Graph traversal depth | |
format | string | "markdown" | "markdown" or "json" |
Output: A Markdown or JSON document containing relevant symbols and code, ready to paste as context for an LLM.
File Tools
coraline_read_file
Read the contents of a file within the project.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path | string | ✅ | — | File path (relative to project root or absolute) |
start_line | number | 1 | First line to read (1-indexed, inclusive) | |
limit | number | 200 | Maximum number of lines to return |
coraline_list_dir
List the contents of a directory within the project.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path | string | . | Directory path (relative to project root or absolute). Defaults to project root. |
coraline_get_file_nodes
Get all indexed symbols (nodes) for a specific file.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
file_path | string | ✅ | File path (relative or absolute) |
Output: { "file_path": "...", "nodes": [...], "count": N }
coraline_find_file
Find files by name or glob pattern. Recursively walks the project tree, skipping .git, node_modules, target, and .coraline directories.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
pattern | string | ✅ | — | File name, substring, or glob pattern (*.rs, test_*, [Cc]argo.toml) |
limit | number | 20 | Maximum results |
Output:
{
"pattern": "*.rs",
"files": ["src/lib.rs", "src/db.rs", "src/graph.rs"],
"count": 3
}
coraline_status
Show project statistics: total files, nodes, edges, and unresolved reference counts.
Input: None.
Output:
{
"files": 128,
"nodes": 4201,
"edges": 9872,
"unresolved": 153,
"db_size_bytes": 2097152
}
coraline_get_config
Read the current project configuration from .coraline/config.toml.
Input: None.
Output: Full CoralineConfig as JSON with all four sections (indexing, context, sync, vectors).
coraline_update_config
Update a single configuration value using dot-notation path.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
key | string | ✅ | Dot-notation path, e.g. context.max_nodes |
value | any | ✅ | New value (type must match the field) |
coraline_sync
Trigger an incremental sync of the index. Detects files added, modified, or removed since the last index run and updates only what changed. Run after editing source files to keep the graph current.
Input: None.
Output:
{
"files_checked": 42,
"files_added": 1,
"files_modified": 3,
"files_removed": 0,
"nodes_updated": 47,
"duration_ms": 380
}
coraline_semantic_search
Search indexed nodes using natural-language vector similarity. Included in the default build; only registered as an MCP tool once an ONNX model is present in .coraline/models/. To activate:
coraline model download # download nomic-embed-text-v1.5 (~137 MB)
coraline embed # generate embeddings for all indexed nodes
When this tool is used, Coraline periodically performs a throttled freshness check. If indexed state is stale it runs incremental sync automatically, then refreshes stale/missing embeddings before search.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
query | string | ✅ | — | Natural-language description of what you're looking for |
limit | number | 10 | Max results | |
min_similarity | number | 0.3 | Minimum cosine similarity threshold (0–1) |
Output:
{
"query": "how is sync staleness detected",
"freshness": {
"checked": true,
"stale_files_added": 0,
"stale_files_modified": 2,
"stale_files_removed": 0,
"synced": true,
"files_added": 0,
"files_modified": 2,
"files_removed": 0,
"embeddings_refreshed": true,
"embeddings_refreshed_count": 18,
"check_interval_seconds": 30
},
"results": [
{
"id": "abc123",
"name": "resolve_unresolved",
"qualified_name": "coraline::resolution::ReferenceResolver::resolve_unresolved",
"kind": "function",
"file_path": "src/resolution/mod.rs",
"start_line": 42,
"docstring": null,
"signature": "fn resolve_unresolved(...)",
"score": 0.87
}
]
}
Memory Tools
Project memories are Markdown files stored in .coraline/memories/. They persist across sessions and help AI assistants maintain project context.
coraline_write_memory
Write or update a project memory.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | ✅ | Memory name (without .md). E.g. project_overview |
content | string | ✅ | Memory content in Markdown format |
coraline_read_memory
Read a project memory by name.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | ✅ | Memory name (without .md) |
Output: { "name": "...", "content": "..." }
coraline_list_memories
List all available memories for the project.
Input: None.
Output: { "memories": ["project_overview", "architecture_notes", ...], "count": N }
coraline_delete_memory
Delete a project memory.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | ✅ | Memory name to delete |
coraline_edit_memory
Edit a memory file by replacing text — either as a literal string match or a regex pattern.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | ✅ | — | Memory name (without .md) |
pattern | string | ✅ | — | Text to find |
replacement | string | ✅ | — | Replacement text |
mode | string | "literal" | "literal" or "regex" |
MCP Client Configuration
Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):
{
"mcpServers": {
"coraline": {
"command": "/path/to/coraline",
"args": ["serve", "--mcp", "--path", "/path/to/your/project"]
}
}
}
Claude Code
Add to .claude/mcp.json in your project workspace:
{
"mcpServers": {
"coraline": {
"command": "coraline",
"args": ["serve", "--mcp"]
}
}
}
When --path is omitted, the working directory is used as the project root.
Configuration
Coraline Configuration Reference
Coraline stores its configuration in .coraline/config.toml within each project. All settings are optional — a missing or empty file uses sensible defaults.
File Locations
| File | Purpose |
|---|---|
.coraline/config.toml | Main user-editable configuration |
.coraline/config.json | Internal runtime config (auto-generated, do not edit) |
.coraline/coraline.db | SQLite knowledge graph (do not edit) |
.coraline/memories/ | Project memory files (Markdown) |
.coraline/logs/ | Daily-rotating log files |
Full Default Configuration
# Coraline project configuration
# All settings are optional — defaults are shown below.
[indexing]
max_file_size = 1048576 # 1 MB — skip files larger than this
batch_size = 100 # Files processed per batch
include_patterns = [
"**/*.rs", "**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx",
"**/*.py", "**/*.go", "**/*.java", "**/*.cs", "**/*.cpp",
"**/*.c", "**/*.h", "**/*.rb", "**/*.php", "**/*.swift",
"**/*.kt", "**/*.razor",
]
exclude_patterns = [
"**/.git/**", "**/target/**", "**/node_modules/**",
"**/dist/**", "**/build/**", "**/.coraline/**",
]
[context]
max_nodes = 20 # Max graph nodes in context output
max_code_blocks = 5 # Max code snippets to attach
max_code_block_size = 1500 # Max chars per code block
traversal_depth = 1 # Graph hops from entry nodes
[sync]
git_hooks_enabled = true # Auto-sync on git commit
watch_mode = false # Watch for file changes (not yet implemented)
debounce_ms = 500 # Watch mode debounce delay
auto_sync_interval_secs = 120 # MCP background sync interval (0 = disabled)
[vectors]
enabled = false # Requires ONNX model (see below)
model = "nomic-embed-text-v1.5"
dimension = 384
batch_size = 32
[indexing] Section
Controls which files are indexed and how.
max_file_size
Files larger than this are skipped during indexing.
- Type: integer (bytes)
- Default:
1048576(1 MB)
[indexing]
max_file_size = 524288 # 512 KB
batch_size
Number of files processed per indexing batch.
- Type: integer
- Default:
100
include_patterns
Glob patterns for files to include. Uses ** for recursive matching.
- Type: array of strings
- Default: Common source file extensions for 18+ languages
[indexing]
include_patterns = [
"**/*.rs",
"**/*.ts",
"**/*.tsx",
"src/**/*.js",
]
exclude_patterns
Glob patterns for paths to exclude. Matched against the full relative file path.
- Type: array of strings
- Default: Build artifacts, package caches, generated files, IDE directories
[indexing]
exclude_patterns = [
"**/.git/**",
"**/node_modules/**",
"**/target/**",
"**/dist/**",
"tests/fixtures/**", # custom exclusion
]
Tip: The default exclusion list is extensive. You typically only need to add project-specific paths.
Python virtualenvs: The defaults cover
.venv/,venv/,env/, and named venvs matching*_venv/or*-venv/(e.g.cluster_venv/,memory_venv/). If you use a different naming convention, add it explicitly:exclude_patterns = ["**/my_custom_env/**"]
[context] Section
Controls the output of coraline context (CLI) and coraline_context (MCP).
max_nodes
Maximum number of graph nodes to include in a context response.
- Type: integer
- Default:
20
max_code_blocks
Maximum number of source code snippets to attach.
- Type: integer
- Default:
5
max_code_block_size
Maximum characters per code block. Larger bodies are truncated.
- Type: integer
- Default:
1500
traversal_depth
How many graph hops to follow from the initial matching nodes.
- Type: integer
- Default:
1
[context]
max_nodes = 40
max_code_blocks = 10
max_code_block_size = 2000
traversal_depth = 2
[sync] Section
Controls incremental sync behavior and git hook integration.
git_hooks_enabled
Whether coraline init installs a post-commit hook that automatically runs coraline sync after each commit.
- Type: boolean
- Default:
true
Note: This only determines whether
coraline initauto-installs the hook. To manage the hook manually, usecoraline hooks install|remove|status.
watch_mode
Enable file-system watch mode (re-index on changes). Not yet implemented.
- Type: boolean
- Default:
false
debounce_ms
Debounce delay for watch mode in milliseconds.
- Type: integer
- Default:
500
auto_sync_interval_secs
Interval in seconds for the MCP server's background auto-sync thread. The thread periodically checks whether the index is stale and performs an incremental sync when files have changed. When embeddings are enabled and an ONNX model is present, newly-added nodes are automatically embedded after each sync.
- Type: integer (seconds)
- Default:
120(2 minutes) - Set to
0to disable background auto-sync entirely.
[sync]
auto_sync_interval_secs = 60 # check every minute
Note: The first check is delayed by the configured interval to avoid racing with any initial indexing that may still be in progress when the MCP server starts.
[vectors] Section
Controls vector embedding generation for semantic search.
Status: Infrastructure is in place. Full semantic search with ONNX model embeddings is pending availability of a stable
ort2.0 API. Settingenabled = truecurrently has no effect.
enabled
Enable vector embedding generation.
- Type: boolean
- Default:
false
model
Embedding model identifier.
- Type: string
- Default:
"nomic-embed-text-v1.5"
dimension
Embedding vector dimension. Must match the selected model.
- Type: integer
- Default:
384
batch_size
Number of symbols embedded per batch.
- Type: integer
- Default:
32
CLI Configuration Commands
Read the full config:
coraline config
Read a specific section:
coraline config --section context
coraline config --section indexing
Output as JSON:
coraline config --json
Update a value:
coraline config --set context.max_nodes=30
coraline config --set indexing.batch_size=50
coraline config --set indexing.max_file_size=524288
coraline config --set vectors.enabled=true
The --set flag accepts section.key=value syntax. Values are parsed as JSON when possible (for booleans, numbers, and arrays), otherwise treated as strings.
MCP Configuration Tools
The same operations are available via MCP:
coraline_get_config → returns full config as JSON
coraline_update_config → updates a single key
key: "context.max_nodes"
value: 30
Example: Focused TypeScript Project
[indexing]
include_patterns = [
"src/**/*.ts",
"src/**/*.tsx",
"tests/**/*.ts",
]
exclude_patterns = [
"**/node_modules/**",
"**/dist/**",
"**/.next/**",
"src/**/*.d.ts",
]
[context]
max_nodes = 30
max_code_blocks = 8
traversal_depth = 2
Example: Large Rust Workspace
[indexing]
max_file_size = 2097152 # 2 MB for generated code
batch_size = 200
include_patterns = [
"crates/**/*.rs",
]
exclude_patterns = [
"**/target/**",
"**/.git/**",
]
[context]
max_nodes = 50
traversal_depth = 3
Architecture
Coraline Architecture
Coraline is a local-first code intelligence system that builds a semantic knowledge graph from any codebase. It uses tree-sitter for deterministic AST-based parsing, SQLite for storage and full-text search, and exposes its capabilities via both a CLI and an MCP server.
High-Level Overview

Diagram source: docs/diagrams/high-level-overview.mmd
Source Layout
crates/coraline/src/
├── bin/coraline.rs # CLI entry point (clap)
├── lib.rs # Public API surface
├── types.rs # NodeKind, EdgeKind, all shared types
├── db.rs # SQLite layer + schema + FTS
├── extraction.rs # Tree-sitter parsing + indexing pipeline
├── graph.rs # Graph traversal and subgraph queries
├── resolution/ # Cross-file reference resolution
│ ├── mod.rs # Core resolver + framework fallback
│ └── frameworks/ # Language/framework-specific resolvers
│ ├── mod.rs # FrameworkResolver trait + registry
│ ├── rust.rs # crate::, super::, self:: resolution
│ ├── react.rs # ./Foo imports, @/ aliases, components
│ ├── blazor.rs # .razor file discovery, .NET types
│ └── laravel.rs # PSR-4, blade views, facades
├── context.rs # Context builder (Markdown/JSON output)
├── vectors.rs # Vector storage + cosine similarity
├── memory.rs # Project memory CRUD
├── config.rs # TOML + JSON configuration loading
├── sync.rs # Incremental sync + git hook management
├── logging.rs # Structured logging (tracing)
├── mcp.rs # MCP server (JSON-RPC over stdio)
├── utils.rs # Shared utilities
└── tools/
├── mod.rs # Tool trait + ToolRegistry
├── graph_tools.rs # search, callers, callees, impact, find_symbol, ...
├── context_tools.rs# coraline_context
├── file_tools.rs # read_file, list_dir, status, config
└── memory_tools.rs # write/read/list/delete/edit memory
Data Model
Nodes
Every extracted symbol is a Node:
#![allow(unused)] fn main() { pub struct Node { pub id: String, // SHA-based deterministic ID pub kind: NodeKind, // function, class, method, struct, ... pub name: String, // unqualified symbol name pub qualified_name: Option<String>, pub file_path: String, // absolute path pub language: String, pub start_line: i64, pub end_line: i64, pub start_column: i64, pub end_column: i64, pub signature: Option<String>, pub docstring: Option<String>, pub visibility: Option<String>, pub is_exported: bool, pub is_async: bool, pub is_static: bool, pub is_abstract: bool, pub decorators: Vec<String>, pub type_parameters: Vec<String>, } }
NodeKind values: file, module, class, struct, interface, trait, protocol, function, method, property, field, variable, constant, enum, enum_member, type_alias, namespace, parameter, import, export, route, component
Edges
Relationships between nodes are Edge records:
#![allow(unused)] fn main() { pub struct Edge { pub id: String, pub source: String, // source node ID pub target: String, // target node ID pub kind: EdgeKind, pub line: Option<i64>, // line where the relationship occurs pub metadata: Option<String>, } }
EdgeKind values: contains, calls, imports, exports, extends, implements, references, type_of, returns, instantiates
Indexing Pipeline
- Scan — Glob the project tree using
include_patterns/exclude_patterns. - Parse — For each file, spawn the appropriate tree-sitter grammar and walk the AST.
- Extract — Emit
NodeandEdgerecords from the AST visitor. - Store — Upsert nodes and edges into SQLite. A file content hash prevents re-parsing unchanged files.
- Resolve — Walk
unresolvedreference edges, attempt name-based resolution in the DB; fall back to framework-specific resolvers for zero-candidate references.
Incremental Sync
coraline sync (and the git post-commit hook) uses git diff --name-only HEAD~1 to find changed files, then re-parses only those files. Deleted files have their nodes pruned from the graph.
Reference Resolution
Resolution happens in two passes:
-
Name-based: The
resolution::resolve_unresolvedfunction looks up reference names in the DB using ranked candidate scoring (file proximity, name similarity, kind match). -
Framework fallback: When no candidates score above threshold,
framework_fallbackis called. The registeredFrameworkResolverimplementations detect the active framework (by checking forCargo.toml,package.json,artisan,.csproj, etc.) and return candidate file paths. Nodes from those files are then loaded and filtered by the referenced symbol name.
Current framework resolvers:
- RustResolver —
crate::,super::,self::qualified paths →.rsfile mapping - ReactResolver —
./Foorelative imports,@/path aliases, PascalCase component search - BlazorResolver — PascalCase component →
.razorfile, dot-qualified .NET types - LaravelResolver — PSR-4 FQN → PHP file, dot-notation views → blade templates
Tool Architecture
All MCP tools implement the Tool trait:
#![allow(unused)] fn main() { pub trait Tool: Send + Sync { fn name(&self) -> &'static str; fn description(&self) -> &'static str; fn input_schema(&self) -> Value; fn execute(&self, params: Value) -> ToolResult; } }
Tools are registered in a ToolRegistry, which:
- Dispatches
tools/callMCP requests by name - Automatically generates
tools/listresponses from registered metadata - Can be used outside MCP (CLI, library API, tests)
Database Schema
The SQLite database (.coraline/coraline.db) has three main tables:
| Table | Purpose |
|---|---|
nodes | All indexed symbols with full metadata |
edges | Directed relationships between nodes |
nodes_fts | FTS5 virtual table for fast name search |
A files table tracks content hashes for incremental sync. An unresolved_refs table holds references that couldn't be resolved during extraction, to be retried on full resolution passes.
MCP Protocol
The MCP server (coraline serve --mcp) communicates over stdin/stdout using JSON-RPC 2.0, conforming to the Model Context Protocol specification.
Supported MCP methods:
initialize/notifications/initializedtools/list— returns tool descriptors with cursor pagination (cursor/nextCursor)tools/call— dispatches toToolRegistryping
The server is single-threaded and synchronous; each request is fully processed before the next is read.
Logging
Structured logs use the tracing crate:
- Console: stderr at the level set by
CORALINE_LOG(default:info) - File:
.coraline/logs/coraline.logwith daily rotation (kept 7 days)
CORALINE_LOG=debug coraline index # verbose
CORALINE_LOG=warn coraline serve --mcp # quiet
Development
Coraline Development Guide
This document covers building, testing, and contributing to Coraline.
Prerequisites
| Tool | Version | Notes |
|---|---|---|
| Rust | ≥ 1.85 | MSRV — install via rustup |
| Git | any | Required for sync and hooks |
| SQLite | bundled | Included via rusqlite — no separate install needed |
Getting Started
git clone https://github.com/greysquirr3l/coraline.git
cd coraline
# Build (debug)
cargo build --all-features
# Build and install to ~/.cargo/bin
cargo install --path crates/coraline --force
# Verify
coraline --version
Common Commands
# Development build
cargo build --all-features
# Release build
cargo build --release --all-features
# Run all tests
cargo test --all-features
# Run tests with output
cargo test --all-features -- --nocapture
# Run a specific test by name
cargo test resolve_unresolved
# Run a specific integration test file
cargo test --test extraction_test
# Lint (project default clippy baseline)
cargo lint
# Format
cargo fmt
# Check formatting without modifying
cargo fmt -- --check
Project Structure
coraline/
├── Cargo.toml # Workspace manifest
├── deny.toml # cargo-deny license/audit policy
├── crates/
│ ├── coraline/ # Main crate
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── bin/coraline.rs # CLI binary
│ │ └── ... # Library modules
│ └── tree-sitter-blazor/ # Custom Blazor grammar
├── docs/ # Documentation
├── reference_projects/ # Reference implementations (not built)
└── .github/workflows/ # CI/CD pipelines
Tests
Test Overview
| Location | Count | Type |
|---|---|---|
src/tools/mod.rs | 3 | Unit: ToolRegistry |
src/tools/memory_tools.rs | 5 | Unit: MCP memory tools |
src/memory.rs | 11 | Unit: memory CRUD |
src/vectors.rs | 5 | Unit: cosine similarity |
tests/extraction_test.rs | 4 (1 ignored) | Integration: AST parsing |
tests/graph_test.rs | 4 | Integration: graph traversal |
tests/context_test.rs | 5 | Integration: context building |
Current status: 37/37 passing, 1 ignored (test_cross_file_references — import edge extraction not yet implemented).
Running Tests
# All tests
cargo test --all-features 2>&1 | grep "test result"
# Single integration file
cargo test --test graph_test
# Single unit test
cargo test memory::tests::test_write_read
# With output (for debugging)
cargo test test_name -- --nocapture
Test Fixtures
Integration tests use fixtures in crates/coraline/tests/fixtures/:
| Fixture | Purpose |
|---|---|
simple-project/ | Basic TypeScript + Rust extraction |
blazor-app/ | Blazor/Razor component parsing |
mixed-language/ | Multi-language extraction |
Fixtures are small, self-contained codebases checked into the repo.
Adding a New Tree-Sitter Language
- Add the tree-sitter crate to
crates/coraline/Cargo.toml. - Add the language variant to
Languageenum intypes.rs. - Add the file extension mapping in
extraction.rs(language_from_path). - Add an extraction branch in
extraction.rs(extract_nodes_from_ast). - Add to the
is_language_supportedlist inconfig.rs. - Add at least one fixture file and a test case in
tests/extraction_test.rs.
Adding a New MCP Tool
-
Implement the
Tooltrait in the appropriatesrc/tools/*.rsfile:#![allow(unused)] fn main() { pub struct MyTool { project_root: PathBuf } impl Tool for MyTool { fn name(&self) -> &'static str { "coraline_my_tool" } fn description(&self) -> &'static str { "..." } fn input_schema(&self) -> Value { json!({ ... }) } fn execute(&self, params: Value) -> ToolResult { ... } } } -
Register in
src/tools/mod.rsinsidecreate_default_registry(...):#![allow(unused)] fn main() { registry.register(Box::new(MyTool::new(project_root.to_path_buf()))); } -
Add unit tests in the same file or
src/tools/mod.rs. -
Document in
docs/MCP_TOOLS.md.
Adding a Framework Resolver
-
Create
src/resolution/frameworks/my_lang.rsimplementingFrameworkResolver:#![allow(unused)] fn main() { pub struct MyLangResolver; impl FrameworkResolver for MyLangResolver { fn name(&self) -> &'static str { "my_lang" } fn detect(&self, project_root: &Path) -> bool { ... } fn resolve_to_paths(&self, ctx: &ResolveContext<'_>) -> Vec<PathBuf> { ... } } } -
Add to
default_resolvers()insrc/resolution/frameworks/mod.rs. -
Add
pub mod my_lang;insrc/resolution/frameworks/mod.rs.
CI/CD
GitHub Actions workflows run on every push and pull request:
| Workflow | Triggers | What it does |
|---|---|---|
ci.yml | push, PR | build, test, clippy, fmt, docs; multi-platform (Linux/macOS/Windows); MSRV check |
release.yml | v* tags | Cross-platform binary builds + GitHub release |
security.yml | daily + dep changes | cargo-audit (vulnerabilities) + cargo-deny (licenses) |
codeql.yml | weekly | CodeQL analysis |
Creating a Release
# Bump version in crates/coraline/Cargo.toml and crates/tree-sitter-blazor/Cargo.toml
# Update CHANGELOG.md
git add -A
git commit -m "chore: release v0.2.0"
git tag v0.2.0
git push origin main --tags
The release.yml workflow builds binaries for Linux x86_64, macOS x86_64/ARM64, and Windows x86_64, then creates a GitHub release with the CHANGELOG content attached.
Code Style
#![forbid(unsafe_code)]on all modules — no unsafe codecargo lintmust pass before committingcargo fmtfor formatting (rustfmt defaults)- Keep functions focused; prefer extracting helpers over long function bodies
- Prefer
let Some(x) = opt else { return ...; }over.unwrap()or?in non-Result contexts - Use
tracing::{debug, info, warn, error}for log output — no bareprintln!in library code
See .coraline/memories/style_conventions.md in your project for project-specific conventions.
Useful Dev Workflows
Dogfood Coraline on itself
cd /path/to/coraline
coraline init -i # index itself
coraline query "resolve_unresolved"
coraline context "how does reference resolution work"
Test MCP roundtrip manually
printf '%s\n%s\n%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"test","version":"0.0.1"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
| coraline serve --mcp
Check all tests pass after a change
cargo lint && cargo test --all-features 2>&1 | grep "test result"
Changelog
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
0.8.6 - 2026-04-22
Fixed
- Callees/callers query accuracy:
coraline_calleesandcoraline_callersMCP tools now validate call edges against import/crate boundaries before returning results, eliminating false-positive cross-crate links from name collisions (e.g.,heartbeat()in raccoon-agent falsely callingpost()in raccoon-frontend). Validation checks: same-file, same-directory, or explicit import statements; queries fetch 2x limit to maintain result count after filtering. - CLI callees/callers filtering:
coraline calleesandcoraline callersCLI commands now apply the same boundary validation and show "No callees/callers found" when all edges are filtered out.
Added
is_valid_call_edge()database function — validates whether a call edge respects module/crate boundaries before inclusion in query results.
0.8.5 - 2026-04-21
Dependencies
- Bump
indicatif0.17 → 0.18 - Bump
tree-sitter-scala0.25.0 → 0.26.0
CI
- Bump
actions/upload-artifact7.0.0 → 7.0.1 - Bump
github/codeql-action4.35.1 → 4.35.2 - Bump
actions/deploy-pages4.0.5 → 5.0.0 - Bump
dependabot/fetch-metadata2.3.0 → 3.1.0
[0.8.4] - 2026-04-20
Fixed
- Call graph precision:
coraline_calleesno longer returns false-positive cross-project edges when multiple paths have the same symbol name. Resolver now prefers extractor-provided candidate IDs (better locality signal) and avoids low-confidence global-name fallback for call edges. - Graph queries (
coraline_callees,coraline_callers) now return deterministic, stable result sets via explicitORDER BY (line, col, target/source)in edge retrieval, improving user trust in output consistency across repeated queries. - Windows test portability: graph precision acceptance tests now normalize path separators in assertions, preventing
src\\api.rsvssrc/api.rsmismatches onwindows-latest.
Added
- Graph precision acceptance tests for call-edge disambiguation in mixed active/legacy workspaces, stale-file deletion edge hygiene, and fallback prevention scenarios.
CI
- Replaced hardcoded Rust toolchain commit hashes with
@stabletag to fix transient CI failures and ensure stable Rust channel alignment with MSRV policy.
0.8.3 - 2026-04-17
Changed
coraline index,coraline sync, andcoraline embednow use a Braille spinner with the current phase/file instead of a progress bar, reducing terminal jitter during indexing and embeddingcoraline embednow displays an explicit model-loading status indicator while ONNX Runtime and tokenizer initialization are in progress
Fixed
- Fixed storing-phase progress accounting in
index_allwhere mixed totals (parsed.len()vsfiles.len()) caused visible progress jumps coraline embednow handles ONNX Runtime initialization panics gracefully and returns actionable loader error guidance instead of a panic backtrace
CI
- Release workflow now supports auto-tag-triggered releases via
workflow_runand shared tag/SHA resolution, avoiding theGITHUB_TOKENtag-push trigger gap
0.8.2 - 2026-04-16
Changed
coraline index,coraline sync, andcoraline embednow display anindicatifprogress bar ({spinner} {phase} [{bar}] {pos}/{len}) instead of raw ANSI escape sequences;--quietsuppresses it entirely
Fixed
- macOS
tree-sitter-blazorarchive warning removed — the build now avoids the unsupported BSDar -Dflag probe that previously emitted noisy warnings during local builds on macOS
CI
- Add Dependabot auto-merge workflow — approved Dependabot PRs with passing CI now merge automatically
0.8.1 - 2026-04-15
CI
- Bump
actions/attest-build-provenancefrom 3.0.0 to 4.1.0 - Bump
actions/cachefrom 5.0.4 to 5.0.5 - Bump
actions/configure-pagesfrom 5.0.0 to 6.0.0 - Bump
softprops/action-gh-releasefrom 2.6.1 to 3.0.0 - Bump
actions/upload-pages-artifactfrom 3.0.1 to 5.0.0 - Pin
ortto=2.0.0-rc.11in Dependabot ignore rules pending resolution of VitisAI build regression in rc.12
Security
- Updated
ureqto 3.3.0,rustlsto 0.23.38,rustls-webpkito 0.103.12 — resolves RUSTSEC-2026-0098 and RUSTSEC-2026-0099 (URI name constraint validation bugs)
0.8.0 - 2026-04-15
Added
- Symbol name disambiguation for MCP graph tools —
coraline_callers,coraline_callees,coraline_impact,coraline_find_references,coraline_node,coraline_dependencies,coraline_dependents, andcoraline_pathnow acceptname(+ optionalfile) as an alternative tonode_id, with clear disambiguation errors when multiple symbols share the same name filefilter on search tools —coraline_searchandcoraline_find_symbolaccept an optionalfileparameter to scope results to a specific file pathcoraline_find_fileMCP tool — glob-based file search (*.rs,test_*,[Cc]argo.toml) that walks the project tree, skipping common build/hidden directories
Fixed
- FTS5 search hardened against special-character queries — search terms are now individually double-quoted before SQLite
MATCHexecution, with embedded quotes escaped; blank/whitespace-only input returns empty results instead of an FTS syntax error. Queries containing/(e.g. file paths),", or other FTS special characters now work correctly - MCP tool dispatch resolves prefixed tool names —
ToolRegistrynow normalizes common client prefixes (mcp_coraline_coraline_*,mcp_coraline_*,mcp_*) before lookup, preventingUnknown toolerrors when MCP clients such as VS Code Copilot automatically prefix registered tool names - Removed
#[allow(clippy::cast_possible_truncation)]suppressions — allu64 as usizecasts in MCP toolexecutefunctions replaced withusize::try_from().ok().unwrap_or(N);f64 as f32inSemanticSearchToolnarrowed to a single line-level allow with justification comment - Fixed silent empty-string return in
resolve_node_id— thelen() == 1branch now returns a properinternal_errorinstead of silently producing an empty node ID if the iterator is unexpectedly exhausted - Release workflow not triggered by auto-tag — tags pushed by
github-actions[bot]viaGITHUB_TOKENdon't firepushevents on other workflows; auto-tag now explicitly triggers the release workflow viaworkflow_dispatch
0.7.0 - 2026-04-13
Added
- MCP background auto-sync — the MCP server now spawns a background thread that periodically checks index freshness and performs incremental sync when files have changed, keeping the knowledge graph current without manual intervention
- Automatic incremental embedding — after each background sync, newly-added nodes are automatically embedded when the
embeddingsfeature is enabled and ONNX model files are present on disk auto_sync_interval_secsconfig — new[sync]setting inconfig.tomlcontrols the background check interval (default: 120 seconds, set to 0 to disable)coraline updateCLI command — checks crates.io for newer published versions and prints upgrade instructionsget_unembedded_nodesdatabase query — efficient LEFT JOIN query to find nodes missing vector embeddings, enabling incremental embedding instead of re-embedding everything- Repository logo asset — added
assets/img/coraline_logo.pngand wired it into the README header for consistent project branding
Changed
ureqis now a non-optional dependency — always available for update checking (previously gated behind theembeddingsfeature)tree-sitter-dartupdated to 0.1.0 — migrated from deprecatedlanguage()function to the newLANGUAGEconstant API
Dependencies
- Consolidated Dependabot PRs (#15–#19) — CI action versions (
actions/checkout@v6,codeql-action@v4,upload-artifact@v7,download-artifact@v8.0.1) were already at target versions; no changes needed - Skipped
ort2.0.0-rc.12 due to upstreamVitisAIbuild regression — remains pinned at=2.0.0-rc.11
Documentation
- README cleanup and docs-site routing — removed emoji-heavy formatting, normalized the logo image tag, and updated primary documentation links to point to the published site at
https://greysquirr3l.github.io/coraline/ - Configuration, MCP, and CLI docs updated — documented
auto_sync_interval_secs, background auto-sync behavior, and thecoraline updatecommand
0.6.0 - 2026-04-09
Added
--skip-syncforcoraline embed— allows explicitly bypassing the pre-embed sync check when you intentionally want to embed the current indexed stateSyncStatuspreflight API (extraction::needs_sync) — lightweight sync-status check now returns detailed added/modified/removed counts for reuse by CLI and MCP flows
Changed
coraline embednow preflights index freshness — embed checks for stale index state and auto-runs incrementalsynconly when needed, with progress output that reports detected and applied changescoraline_semantic_searchnow performs periodic freshness maintenance — MCP semantic search throttles freshness checks and, when stale, auto-syncs the graph and refreshes stale/missing node embeddings before serving results
Documentation
- CLI, MCP, and README docs updated — documented
embed --skip-sync, pre-embed auto-sync behavior, and MCP semantic-search freshness metadata - mdBook docs site added — introduced
docs/book/and a GitHub Pages deployment workflow (docs-pages.yml) to publish documentation on the project GitHub Pages site - Architecture docs visual refresh — replaced ASCII overview with GitHub-native Mermaid diagrams for cleaner rendering and maintenance
0.5.0 - 2026-04-08
Added
- MCP protocol negotiation and compatibility fallback — server now negotiates protocol version with clients, preferring
2025-11-25while retaining compatibility with2024-11-05 tools/listpagination support — cursor-based pagination added viacursorrequest param andnextCursorresponse field
Changed
- MCP lifecycle enforcement tightened — normal operations now require successful
initializefollowed bynotifications/initialized - Tool error semantics aligned with MCP expectations — unknown tool calls return protocol errors; tool execution failures continue returning
isError: trueresults - Tool capability declaration expanded — MCP initialize response now advertises
tools.listChangedcapability (currentlyfalse) - Core dependencies refreshed for 0.5.0 — upgraded key libraries including
toml(1.1),rusqlite(0.39),sha2(0.11),tokenizers(0.22), and multiple tree-sitter parser crates; validated with full workspace tests and clippy - Workflow supply-chain hardening — all CI and CodeQL GitHub Actions are now pinned to immutable commit SHAs to improve OSSF Scorecard
Pinned-Dependenciesposture - Strict lint command is now standardized — added tracked
.cargo/config.tomlalias socargo lintconsistently enforces the project clippy policy in local and CI runs
Fixed
- Tool result schema field casing — MCP tool results now serialize as
isError(camelCase) instead ofis_error - Clippy pedantic compliance in MCP server code — removed no-effect underscore bindings and replaced potential panicking slice/index patterns with safe iterator/object mutation patterns
Documentation
- MCP documentation refreshed across README and docs book — updated protocol/lifecycle notes, pagination behavior, and development examples to reflect current server behavior
[0.4.4] - 2026-04-08
Fixed
- Windows cross-platform CI test failure —
parse_project_root_accepts_file_uriunit test now handles Windows file URI format (file:///C:/...) correctly by normalizing the leading slash when present; test is now platform-aware and uses appropriate URIs for each platform
[0.4.3] - 2026-04-07
Fixed
- Cross-compilation builds failing on OpenSSL — switched TLS backend from
native-tls(OpenSSL) torustlsfor all HTTP operations; musl and ARM cross-builds no longer require OpenSSL headers or linking - Root cause:
ortdependency had default features enabled which pulled intls-native→ureq/native-tls→openssl-sys; now usesdefault-features = falsewith explicittls-rustls
Changed
embeddingsfeature now uses rustls — pure Rust TLS for model downloads, no system OpenSSL dependencyembeddings-dynamicno longer includes any TLS stack — users supply their own ONNX runtime, no HTTP downloads needed
Security
- Pinned all GitHub Actions to commit SHAs — OSSF Scorecard
PinnedDependenciesIDcompliance - Added Dependabot configuration — automated dependency updates for Cargo and GitHub Actions
0.4.2 - 2026-04-07
Fixed
- MCP tools discovery without explicit
--path—tools/listnow lazily initializes the tool registry when clients call it beforeinitialize, so tools are returned even whencoraline serve --mcpstarts without-p - Safer MCP project-root URI parsing — non-
file://URIs (for example, remote client scheme URIs) are no longer treated as filesystem paths duringinitialize; server falls back to an actual local path when needed - Regression coverage for MCP startup flow — added tests for pre-initialize
tools/listbehavior and URI parsing guards to prevent regressions
0.4.1 - 2026-04-03
Added
- Embedding model prompt on
coraline init— when stdin is a TTY,initnow offers to download the embedding model (~137 MB) immediately after initialization; declined or non-interactive runs print a tip and continue normally with full graph functionality embeddingsis now the default feature —cargo install coralineincludes ONNX/semantic search support out of the box; no--featuresflag required for most users
Fixed
- MCP server no longer ghost-creates
.coraline/—MemoryManagerpreviously calledcreate_dir_all(.coraline/memories/)eagerly on every MCP startup, leaving a stub directory that blockedcoraline initfrom running cleanly; it now returns an error if.coraline/doesn't exist, which the MCP tool registry handles gracefully coraline init -ion an already-initialized project no longer prompts to overwrite — when--indexis present without--force, init detects the existing directory, skips the destructive overwrite, and runs indexing directly; use--forceto explicitly wipe and reinitializecoraline_semantic_searchMCP tool degrades gracefully without a model — when no ONNX model file is present the tool is not registered (all other tools remain available) and a warning is emitted to the project log
0.4.0 - 2026-03-20
Added
- Full multi-language symbol extraction coverage across all supported languages, including previously missing Python internals and broad AST node-kind mappings.
- Expanded import/export resolution across languages for stronger cross-file graph relationships and MCP traversal behavior.
- Broader call-expression detection and callee extraction across language grammars to improve call graph completeness.
Changed
- Cross-language resolution quality improved for callers/callees/impact tooling due to richer import/export and call mapping.
Internal
- Strict lint compliance restored after expansion (
cargo clippy --all-features -- -D warnings). - Release validated with build + full test suite.
0.3.1 - 2026-03-18
Added
embeddings-dynamicfeature flag — alternative toembeddingsthat usesort/load-dynamicinstead ofort/download-binaries, allowing users on systems with older glibc (e.g., Rocky Linux, HPC nodes) to supply their ownlibonnxruntime.sobuilt against their local glibc (#8)- musl static binaries in releases —
x86_64-unknown-linux-muslandaarch64-unknown-linux-musltargets added to the release CI matrix, producing fully static binaries with zero glibc dependency
0.3.0 - 2026-03-07
Added
- Vector math optimizations — cosine similarity and L2 normalization now use fused multiply-add for improved numerical stability
Changed
- Dependencies updated — refreshed core dependencies and applied transitive updates for security and compatibility (tree-sitter, clap, tempfile, syn, and 16+ transitive deps)
Internal
- All tests validated (37/37 passing); property tests ensure numerical accuracy
0.2.3 - 2026-03-01
Fixed
coraline init -ion an already-initialized project — instead of hard-failing, the CLI now prompts "Overwrite? [y/N]" when stdin is a TTY, or prints a clear error with--forceguidance in non-interactive contexts;--force/-fflag added toinitto skip the prompt- UNIQUE constraint failures on minified/single-line files — node IDs now incorporate
start_columnin addition tostart_line, preventing hash collisions for multiple symbols on the same line - Garbled progress output during
index/sync— progress lines now use\r\x1B[K(erase-to-end-of-line) instead of bare\r, andstdoutis flushed after each update to prevent interleaving with log output
Internal
- OSSF Scorecard CI workflow added
- Security audit workflow now also triggers on
deny.tomlchanges cargo fmtstyle pass acrossconfig.rsandresolution/mod.rs
0.2.2 - 2026-02-21
Fixed
- Release pipeline: binary builds failing on
ort-sys—ort,tokenizers, andndarrayare now optional, gated behind anembeddingsfeature flag; default builds no longer require ONNX Runtime prebuilt binaries - Release pipeline:
coraline publishfailing when version already on crates.io — publish steps for bothtree-sitter-blazorandcoralinenow skip gracefully if the version already exists - Release pipeline: build matrix cancelling all jobs on first failure — added
fail-fast: falseso platform builds run independently - Dropped
x86_64-apple-darwinrelease binary — Intel Mac is not a supported target; ONNX Runtime provides no prebuilt binaries for it
0.2.1 - 2026-02-21
Fixed
coraline initblocked by log directory —logging::init()eagerly created.coraline/logs/beforeis_initialized()ran, making every re-init attempt report "already initialized"synccrash on UNIQUE constraint — incremental sync now catches per-file store errors (warn + continue) instead of aborting the entire sync, consistent withindex_allcallers/calleesCLI showing incorrect results — CLI was passing no edge-kind filter, surfacingcontainsedges as false callers; now filters tocallsedges only, consistent with MCP tools- CI
actions/checkout@v6— updated all workflow steps to the current stablev4
0.2.0 - 2026-02-20
Added
- Vector embeddings — full ONNX pipeline using
ort 2.0.0-rc.11and nomic-embed-text-v1.5 (384-dim).coraline embedCLI command andcoraline_semantic_searchMCP tool - 25 MCP tools (26 with embeddings) — complete symbol, graph, file, memory, config, stats, and sync toolset
coraline_stats— detailed graph statistics grouped by language, node kind, and edge kindcoraline_dependencies/coraline_dependents— traversal tools for outgoing/incoming dependenciescoraline_path— find shortest paths between any two nodescoraline_syncMCP tool — trigger incremental sync from an MCP clientcoraline_semantic_search— semantic similarity search over indexed symbolscoraline_find_symbol/coraline_get_symbols_overview/coraline_node/coraline_find_references— symbol-level tools matching Serena's precisioncoraline_read_file/coraline_list_dir/coraline_get_file_nodes— file exploration toolscoraline_get_config/coraline_update_config— TOML config management via MCP- Memory tools —
coraline_write_memory,coraline_read_memory,coraline_list_memories,coraline_delete_memory,coraline_edit_memory(regex + literal modes) - TOML configuration —
.coraline/config.tomlwith sections for indexing, context, sync, and vectors; written as a commented template oncoraline init - Structured logging —
tracingwith daily-rotating file appender to.coraline/logs/coraline.log; level viaCORALINE_LOGenv var - Framework-specific resolvers — Rust, React, Blazor, Laravel
- CLI commands —
callers,callees,impact,config,stats,embed;--jsonflag on all query commands - Criterion benchmark suite — 9 benchmarks across indexing, search, graph traversal, and context building groups (
cargo bench --bench indexing) - CI/CD — GitHub Actions for multiplatform builds (Linux x86_64/ARM64, macOS x86_64/ARM64, Windows x86_64), crates.io publishing, CodeQL scanning, daily dependency auditing
- 28+ language support via tree-sitter: Rust, TypeScript, JavaScript, TSX, JSX, Python, Go, Java, C, C++, C#, PHP, Ruby, Swift, Kotlin, Bash, Dart, Elixir, Elm, Erlang, Fortran, Groovy, Haskell, Julia, Lua, Markdown, MATLAB, Nix, Perl, PowerShell, R, Scala, TOML, YAML, Zig, Blazor
Fixed
- TypeScript import extraction:
import_statementwas wrongly mapped asimport_declarationin tree-sitter AST import_clauselookup: switched fromchild_by_field_name(alwaysNone) to child iteration- Cross-file import edges test:
SELECT *placed integeridat column 0; changed to explicitSELECT source, target - FTS multi-word search: now uses
ORlogic so partial matches are found - Glob pattern matching: completely rewritten using
globsetcrate; prior regex implementation was non-functional - Parallel indexing: CPU-bound parse phase separated from sequential DB writes; SQLite PRAGMA tuning (
synchronous=NORMAL, 64 MB cache, 256 MB mmap)
Changed
- Database filename:
codegraph.db→coraline.db - Project directory:
.codegraph/→.coraline/ - Post-commit git hook updated to check
.coraline/directory
0.1.3 - 2026-02-15
Added
coraline_statsMCP tool — graph statistics by language, node kind, and edge kind- TypeScript import extraction fix
Fixed
- Cross-file import edge detection
0.1.2 - 2026-02-13
Added
- PHP, Swift, Kotlin, Markdown, TOML parser support
- CI/CD infrastructure (GitHub Actions)
.coraline/directory rename from.codegraph/
Fixed
- Critical glob pattern matching bug (rewritten with
globset)
0.1.1 - 2026-02-10
Added
- Memory system with 5 MCP tools
- Tool abstraction layer and registry
- Integration test suite
0.1.0 - 2026-02-07
Added
- Initial release
- Tree-sitter based AST extraction for Rust, TypeScript, JavaScript, Python, Go, Java, C, C++, C#, Ruby
- SQLite graph storage
- MCP server (
coraline serve --mcp) - Basic CLI:
init,index,sync,status,query,context coraline_search,coraline_callers,coraline_callees,coraline_impact,coraline_contextMCP tools- Git post-commit hook integration