Introduction
Coraline is a Rust-based code intelligence system that builds semantic knowledge graphs for AI assistants. It provides fast, local code analysis with zero external dependencies.
What is Coraline?
Coraline combines ideas from CodeGraph and Serena to provide:
- Fast indexing - Native Rust performance for rapid code analysis
- Semantic search - Find code by meaning using vector embeddings
- Symbol-level tools - Precise function/class/method operations
- 100% local - All processing happens on your machine
- MCP integration - Works with Claude Desktop, Claude Code, and OpenCode
Key Features
Code Intelligence
- AST-based parsing using tree-sitter (33 languages supported)
- Cross-file reference resolution
- Impact analysis for understanding change ripple effects
- Symbol search with FTS5 full-text indexing
AI Assistant Integration
- Model Context Protocol (MCP) server with 33 tools
- Compact output format for 65% token reduction
- Batch query tools for 60-90% token savings
- Natural language context building
Developer Experience
- CLI for direct command-line usage
- Git hooks for automatic incremental updates
- Project memories for persistent context
- Configurable indexing and exclusion patterns
How It Works
- Index - Coraline scans your project and builds a knowledge graph of all symbols (functions, classes, types, etc.) and their relationships
- Query - Use the CLI or MCP tools to search, traverse, and analyze your codebase
- Assist - AI assistants use Coraline’s tools to understand your code structure and answer questions
All data is stored locally in a SQLite database (.coraline/coraline.db) with no external API calls or cloud dependencies.
Use Cases
- Code exploration - Understand unfamiliar codebases quickly
- Impact analysis - See what will be affected by a change
- Refactoring - Find all callers/callees of a function
- Documentation - Build context for AI-assisted documentation
- Code review - Analyze dependencies and relationships
- Migration planning - Map out cross-file dependencies
Next Steps
- Install Coraline to get started
- Follow the Quick Start Guide for your first project
- Explore the MCP Tools Reference to see what’s available
- Check out MCP Integration for AI assistant setup
Installation & Setup
This guide covers all installation methods for Coraline.
From crates.io
The recommended installation method is via Cargo:
cargo install coraline
This downloads and compiles the latest stable release from crates.io.
Requirements:
- Rust 1.93 or later
- ~5 minutes compilation time on a modern machine
After installation, verify with:
coraline --version
Pre-built Binaries
Download pre-compiled binaries from the GitHub releases page.
Available platforms:
- macOS (x86_64 and ARM64)
- Linux (x86_64 and ARM64)
- Windows (x86_64)
Installation Steps
- Download the appropriate binary for your platform
- Extract the archive
- Move the binary to a directory in your PATH:
# macOS/Linux example
chmod +x coraline
sudo mv coraline /usr/local/bin/
- Verify installation:
coraline --version
Building from Source
For development or custom builds:
# Clone the repository
git clone https://github.com/greysquirr3l/coraline.git
cd coraline
# Build with all features
cargo build --release --all-features
# Install from local source
cargo install --path crates/coraline --force
The binary will be installed to ~/.cargo/bin/coraline.
Development Build
For active development:
cargo build --all-features
The debug binary will be at target/debug/coraline.
Semantic Search Setup
Semantic search is included in the default build but requires downloading an ONNX embedding model.
Download the Model
coraline model download
This downloads nomic-embed-text-v1.5 (~137 MB) to .coraline/models/.
Available model variants:
| 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 |
To download a specific variant:
coraline model download --variant model_fp16.onnx
Generate Embeddings
After downloading the model, generate embeddings for your indexed project:
cd your-project
coraline init -i # Initialize and index
coraline embed # Generate embeddings
Or combine download and embed:
coraline embed --download
Verify Semantic Search
Check that the model is available:
coraline model status
Once embeddings are generated, the coraline_semantic_search MCP tool will be available.
First Project Setup
After installation, initialize your first project:
cd your-project
coraline init -i
This creates .coraline/ with:
coraline.db- SQLite knowledge graphconfig.toml- Configuration filememories/- Project memory directorylogs/- Log file directory
During initialization, you’ll be prompted to download the embedding model. You can decline and download it later with coraline model download.
Updating Coraline
From crates.io
cargo install coraline --force
From pre-built binaries
Download the latest release and replace your existing binary.
From source
cd coraline
git pull
cargo install --path crates/coraline --force
Uninstallation
Cargo installation
cargo uninstall coraline
Binary installation
Remove the binary from your PATH:
sudo rm /usr/local/bin/coraline
Project data
To remove Coraline data from a project:
cd your-project
rm -rf .coraline
Troubleshooting
“command not found: coraline”
Ensure ~/.cargo/bin (or your installation directory) is in your PATH:
export PATH="$HOME/.cargo/bin:$PATH"
Add this to your shell configuration file (.bashrc, .zshrc, etc.) to make it permanent.
Compilation errors
Ensure you have the latest Rust toolchain:
rustup update
Model download fails
If the HuggingFace download fails, you can manually download the model files:
- Visit nomic-ai/nomic-embed-text-v1.5
- Download
tokenizer.json,tokenizer_config.json, and your chosen ONNX variant - Place them in
.coraline/models/nomic-embed-text-v1.5/
Permission denied on git hooks
If coraline init fails to install git hooks:
coraline hooks install
Or manually install:
chmod +x .git/hooks/post-commit
Next Steps
- Quick Start Guide - Index your first project
- MCP Integration - Connect to AI assistants
- Configuration Guide - Customize Coraline’s behavior
Quick Start Guide
Get Coraline running on your project in under 5 minutes.
1. Initialize a Project
Navigate to your project directory and initialize Coraline:
cd your-project
coraline init -i
The -i flag runs indexing immediately after initialization.
You’ll see output like:
Initializing Coraline in /path/to/your-project
Created .coraline/ directory
Created database at .coraline/coraline.db
Created config at .coraline/config.toml
Installed git post-commit hook
Would you like to download the embedding model (~137 MB)? [y/N]:
You can decline the embedding model for now - all other features work without it.
2. Verify the Index
Check the indexing results:
coraline stats
Output:
Coraline Statistics
Files: 128
Nodes: 4201
Edges: 9872
Unresolved refs: 153
3. Search for Symbols
Try searching for a function or class:
coraline query "authenticate"
coraline query "User" --kind class
4. Find Relationships
Get the node ID from the query output, then explore relationships:
# Find what calls a function
coraline callers <node-id>
# Find what a function calls
coraline callees <node-id>
# Analyze impact of changing a symbol
coraline impact <node-id>
5. Build Context for AI
Generate context for a coding task:
coraline context "add authentication middleware"
coraline context "how does the database layer work"
This outputs a Markdown document with relevant code snippets ready to paste into an AI assistant.
Common Workflows
Daily Development
With git hooks installed, Coraline automatically syncs after each commit:
git add .
git commit -m "Add feature"
# Coraline syncs automatically
Or manually sync changes:
coraline sync
Exploring a New Codebase
# Index the project
coraline init -i
# Get overview
coraline stats
# Search for entry points
coraline query "main" --kind function
# Find what main calls
coraline callees <main-node-id>
# Build context for understanding a feature
coraline context "how does the authentication system work"
Refactoring
# Find a symbol to refactor
coraline query "old_function_name"
# Check impact
coraline impact <node-id>
# Find all callers
coraline callers <node-id>
# After making changes, sync
coraline sync
Code Review
# Sync to latest
coraline sync
# Check impact of changed symbols
coraline impact <changed-node-id>
# Find test coverage
coraline query "test_authentication" --kind function
coraline callees <test-node-id>
Incremental vs Full Indexing
Incremental sync (fast, recommended):
coraline sync
Uses git to detect changes and only re-indexes modified files.
Full reindex (slower, comprehensive):
coraline index
Re-parses all files. Use when:
- Switching branches with many changes
- After updating configuration
- If sync results seem incorrect
Optional: Semantic Search
Download the embedding model and generate vectors:
coraline model download
coraline embed
This enables natural language search:
# Via CLI (when MCP tools are used)
coraline serve --mcp
# Then use coraline_semantic_search tool
Semantic search is most useful in MCP integration - see MCP Integration.
Configuration
Customize indexing behavior by editing .coraline/config.toml:
[indexing]
include_patterns = [
"src/**/*.rs",
"lib/**/*.ts",
]
exclude_patterns = [
"**/test/**",
"**/node_modules/**",
]
[context]
max_nodes = 30
max_code_blocks = 10
See Configuration Guide for all options.
Project Memories
Store persistent context about your project:
# Via MCP tools (recommended)
# Use coraline_write_memory, coraline_read_memory, etc.
# Or manually create files in .coraline/memories/
echo "# Project Overview" > .coraline/memories/overview.md
Memories help AI assistants maintain context across sessions.
Next Steps
For CLI Usage
- CLI Reference - Complete command documentation
- Configuration Guide - Customize behavior
- Performance Tips - Optimize for large projects
For AI Assistant Integration
- MCP Integration - Connect to Claude Desktop/Code
- OpenCode Integration - Use with OpenCode
- MCP Tools Reference - Explore available tools
Troubleshooting
“Project not initialized”
Run coraline init first.
“No results found”
Ensure files match include_patterns in .coraline/config.toml. Check:
coraline status
Slow indexing
For large projects (10,000+ files):
- Use more specific
include_patterns - Increase
batch_sizein config - Exclude test/fixture directories
Out-of-date results
Run a full reindex:
coraline index --force
Git hooks not working
Reinstall hooks:
coraline hooks install
Or check hook status:
coraline hooks status
MCP Integration
Coraline exposes its code intelligence capabilities via the Model Context Protocol (MCP), enabling AI assistants to understand and navigate your codebase.
What is MCP?
The Model Context Protocol is a standard for connecting AI assistants to external data sources and tools. Coraline implements MCP to expose 33 code intelligence tools that AI assistants can use.
Supported Clients
Coraline works with any MCP-compatible client:
- Claude Desktop - Official Anthropic desktop app
- Claude Code - CLI-based Claude integration
- OpenCode - Multi-model terminal AI assistant (see OpenCode Integration)
- Any other MCP-compatible client
Claude Desktop
Claude Desktop is the official Anthropic desktop application with built-in MCP support.
Configuration
Add Coraline to Claude Desktop’s MCP configuration:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
Linux: ~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"coraline": {
"command": "/path/to/coraline",
"args": ["serve", "--mcp", "--path", "/path/to/your/project"]
}
}
}
Replace /path/to/coraline with the full path to your Coraline binary:
# Find your Coraline path
which coraline
Common paths:
- Cargo install:
~/.cargo/bin/coraline - macOS Homebrew:
/opt/homebrew/bin/coraline - System install:
/usr/local/bin/coraline
Multiple Projects
To work with multiple projects, add multiple servers:
{
"mcpServers": {
"coraline-projectA": {
"command": "/Users/you/.cargo/bin/coraline",
"args": ["serve", "--mcp", "--path", "/Users/you/projectA"]
},
"coraline-projectB": {
"command": "/Users/you/.cargo/bin/coraline",
"args": ["serve", "--mcp", "--path", "/Users/you/projectB"]
}
}
}
Restart Claude Desktop
After editing the config, restart Claude Desktop to load the new MCP server.
Verify Connection
In Claude Desktop, you should see MCP tools available. Try a prompt like:
Search for authentication functions in my codebase
Claude should use the coraline_search tool automatically.
Claude Code
Claude Code is a terminal-based CLI for Claude with MCP support.
Configuration
Create or edit .claude/mcp.json in your workspace directory:
{
"mcpServers": {
"coraline": {
"command": "coraline",
"args": ["serve", "--mcp"]
}
}
}
When --path is omitted, Coraline uses the current working directory as the project root.
Per-Project Setup
Each project can have its own MCP configuration:
cd your-project
mkdir -p .claude
cat > .claude/mcp.json << 'EOF'
{
"mcpServers": {
"coraline": {
"command": "coraline",
"args": ["serve", "--mcp"]
}
}
}
EOF
Usage
Start Claude Code in your project:
cd your-project
claude
Claude will automatically connect to Coraline and have access to all tools.
Example Prompts
Find all functions that call authenticate()
Show me the impact of changing the User class
Build context for adding a new payment method
What files are in the src/auth directory?
Environment Variables
Logging
Enable debug logging for troubleshooting:
{
"mcpServers": {
"coraline": {
"command": "coraline",
"args": ["serve", "--mcp"],
"env": {
"CORALINE_LOG": "debug"
}
}
}
}
Logs are written to .coraline/logs/coraline.log.
Timeout Configuration
For long-running operations, increase the timeout (in milliseconds):
{
"mcpServers": {
"coraline": {
"command": "coraline",
"args": ["serve", "--mcp", "--timeout", "300000"]
}
}
}
Default: 120000ms (2 minutes) Maximum: 600000ms (10 minutes)
See OpenCode Integration for more timeout details.
Available Tools
Once configured, AI assistants have access to 33 tools:
Core Tools:
coraline_search- Find symbols by namecoraline_semantic_search- Natural language search (requires embeddings)coraline_callers- Find what calls a symbolcoraline_callees- Find what a symbol callscoraline_impact- Analyze change impactcoraline_context- Build context for a task
Advanced:
coraline_batch_get_nodes- Fetch multiple nodes (60-90% token savings)coraline_batch_callers- Batch caller queriescoraline_batch_callees- Batch callee queriescoraline_search_by_signature- Search by type signaturecoraline_search_by_docstring- Search docstringscoraline_search_exported_symbols- Public API only
File & Config:
coraline_read_file- Read file contentscoraline_list_dir- List directorycoraline_get_file_nodes- Symbols in a filecoraline_status- Project statisticscoraline_sync- Incremental updatecoraline_get_config/coraline_update_config- Configuration
Memory:
coraline_write_memory- Create/update memoriescoraline_read_memory- Read memoriescoraline_list_memories- List all memoriescoraline_delete_memory- Delete a memorycoraline_edit_memory- Edit via find/replace
See MCP Tools Reference for complete documentation.
Best Practices
Initialize Before Connecting
Always initialize and index your project before connecting MCP clients:
cd your-project
coraline init -i
Keep Index Updated
Enable git hooks for automatic updates:
coraline hooks install
Or manually sync after changes:
coraline sync
Use Compact Output
All tools support output_format: "compact" for 65% token reduction:
Search for User class with compact output format
The AI assistant will use compact format automatically when instructed.
Batch Queries
For multiple lookups, ask the AI to use batch tools:
Use batch tools to get details for these 10 functions
This saves 60-90% of tokens compared to individual queries.
Project Memories
Use memories to maintain context across sessions:
Write a memory about the authentication architecture
Update the architecture_notes memory with the new JWT approach
Troubleshooting
Tools not appearing
-
Check that Coraline is in your PATH:
which coraline -
Verify the config path is correct
-
Restart the MCP client
-
Check logs in
.coraline/logs/coraline.log
“Project not initialized”
Initialize the project first:
cd /path/to/your/project
coraline init -i
Then restart the MCP client.
Timeout errors
Increase the timeout in your MCP config:
"args": ["serve", "--mcp", "--timeout", "300000"]
Stale results
Sync the index:
coraline sync
Or force a full reindex:
coraline index --force
Permission denied
Ensure Coraline has read access to your project files and write access to .coraline/.
Advanced Configuration
Custom Project Root
Specify a different project root than the working directory:
{
"mcpServers": {
"coraline": {
"command": "coraline",
"args": ["serve", "--mcp", "--path", "/custom/project/path"]
}
}
}
Monorepo Setup
For monorepos, point each server to a different package:
{
"mcpServers": {
"coraline-frontend": {
"command": "coraline",
"args": ["serve", "--mcp", "--path", "/monorepo/packages/frontend"]
},
"coraline-backend": {
"command": "coraline",
"args": ["serve", "--mcp", "--path", "/monorepo/packages/backend"]
}
}
}
Each package needs its own .coraline/ directory.
Next Steps
- MCP Tools Reference - Detailed tool documentation
- OpenCode Integration - Use with non-Claude models
- Performance & Token Savings - Optimize token usage
- Configuration Guide - Customize behavior
OpenCode Integration
OpenCode is a terminal-based AI coding assistant that supports 75+ LLM providers including GPT-4, Gemini, and local models. Coraline’s MCP server is fully compatible with OpenCode.
Compatibility Status
Status: ✅ COMPATIBLE
Coraline works with OpenCode out-of-the-box because:
- Uses MCP protocol version
2024-11-05(standard specification) - Implements JSON-RPC 2.0 (required by MCP spec)
- Uses stdio transport (OpenCode’s expected method)
- Tools properly namespaced (
coraline_prefix)
Supported Models
OpenCode works with:
- ✅ GPT-4 (OpenAI)
- ✅ Gemini (Google)
- ✅ Local models (Ollama, LM Studio, etc.)
- ✅ Other providers (75+ total)
Note: Anthropic blocked Claude models in OpenCode in January 2026. Use Coraline with non-Claude models in OpenCode, or use Claude Desktop / Claude Code for Claude access.
Installation
Install OpenCode
npm install -g opencode
Install Coraline
cargo install coraline
See Installation for detailed instructions.
Configuration
Create .opencode/config.json in your project workspace:
{
"mcpServers": {
"coraline": {
"command": "coraline",
"args": ["serve", "--mcp"]
}
}
}
With Timeout Configuration
For projects with large indexes or complex queries, increase the timeout:
{
"mcpServers": {
"coraline": {
"command": "coraline",
"args": ["serve", "--mcp", "--timeout", "300000"]
}
}
}
Timeout values:
- Default:
120000(2 minutes) - Recommended:
300000(5 minutes) for large projects - Maximum:
600000(10 minutes)
Absolute Path
If coraline is not in your PATH, use an absolute path:
{
"mcpServers": {
"coraline": {
"command": "/Users/you/.cargo/bin/coraline",
"args": ["serve", "--mcp"]
}
}
}
Find your Coraline path:
which coraline
Multiple Projects
Each project needs its own .opencode/config.json:
cd project-a
mkdir -p .opencode
cat > .opencode/config.json << 'EOF'
{
"mcpServers": {
"coraline": {
"command": "coraline",
"args": ["serve", "--mcp"]
}
}
}
EOF
Setup Workflow
1. Initialize Coraline
cd your-project
coraline init -i
2. Configure OpenCode
mkdir -p .opencode
cat > .opencode/config.json << 'EOF'
{
"mcpServers": {
"coraline": {
"command": "coraline",
"args": ["serve", "--mcp", "--timeout", "300000"]
}
}
}
EOF
3. Start OpenCode
opencode --model gpt-4
Or with Gemini:
opencode --model gemini-pro
Or with a local model:
opencode --model ollama/codellama
4. Verify Connection
In OpenCode, type:
List available MCP tools
You should see Coraline’s 33 tools listed.
Usage Examples
Code Exploration
Search for authentication functions
Find all callers of the login() function
Show me the impact of changing the User class
Context Building
Build context for adding a new payment gateway
Show me how the database layer works
What files handle user registration?
Refactoring
Find all functions that call authenticateUser
Analyze the impact of renaming the Auth class
Show me the dependency graph for the API module
File Operations
Read the src/auth/login.ts file
List all TypeScript files in the src directory
Show me all symbols in the User class file
Timeout Configuration Details
OpenCode enforces timeouts on MCP tool calls. Coraline operations that may exceed the default timeout:
| Operation | Typical Duration | Recommended Timeout |
|---|---|---|
coraline_search | <1s | Default (120s) OK |
coraline_callers | 1-5s | Default OK |
coraline_impact (large) | 5-30s | 300000ms (5 min) |
coraline_sync (many files) | 10-60s | 300000ms (5 min) |
coraline_context (deep) | 5-20s | 300000ms (5 min) |
coraline_embed | 30-300s | 600000ms (10 min) |
Timeout Error Handling
If you see timeout errors:
-
Increase timeout in
.opencode/config.json:"args": ["serve", "--mcp", "--timeout", "600000"] -
Optimize your queries:
- Use
--limitparameters to reduce result size - Use
--max-depthto limit traversal depth - Use compact output format
- Use
-
Check logs for actual operation time:
tail -f .coraline/logs/coraline.log
Model-Specific Tips
GPT-4
GPT-4 has excellent tool use capabilities. It will automatically:
- Use batch tools for multiple queries
- Request compact output format
- Chain tool calls efficiently
opencode --model gpt-4 "Find all authentication functions and their callers"
Gemini
Gemini works well with explicit instructions:
opencode --model gemini-pro "Use coraline_search to find the User class, then use coraline_callers to see what uses it"
Local Models
Local models (Ollama, LM Studio) benefit from simpler prompts:
opencode --model ollama/codellama "Search for main function"
For complex tasks, break into steps:
1. Search for the authenticate function
2. Find what calls it
3. Show me the code
Performance Optimization
Use Compact Output
Instruct the model to use compact format:
Search for User class using compact output format
This reduces tokens by ~65%.
Use Batch Tools
For multiple queries:
Use batch tools to fetch details for these 5 functions: login, logout, authenticate, authorize, validate
Saves 60-90% tokens vs individual queries.
Limit Results
Specify limits in your prompts:
Find the top 5 most-called functions in the auth module
Incremental Sync
Keep the index up-to-date with git hooks:
coraline hooks install
This ensures fast sync operations instead of full reindexing.
Troubleshooting
“MCP server not found”
- Verify
.opencode/config.jsonexists in your project root - Check that
coralineis in your PATH or use absolute path - Restart OpenCode
“Project not initialized”
Initialize Coraline first:
coraline init -i
Timeout errors
Increase timeout in config:
"args": ["serve", "--mcp", "--timeout", "600000"]
Tools not working
-
Check Coraline version:
coraline --version -
Check logs:
tail -f .coraline/logs/coraline.log -
Test Coraline directly:
coraline stats
Model doesn’t understand tools
Some models need explicit guidance:
Use the coraline_search tool to find functions named "authenticate"
Instead of:
Find authenticate functions
Advanced Configuration
Custom Log Level
Enable debug logging for troubleshooting:
{
"mcpServers": {
"coraline": {
"command": "coraline",
"args": ["serve", "--mcp"],
"env": {
"CORALINE_LOG": "debug"
}
}
}
}
Specific Project Path
Override the working directory:
{
"mcpServers": {
"coraline": {
"command": "coraline",
"args": ["serve", "--mcp", "--path", "/absolute/path/to/project"]
}
}
}
Multiple Servers
Work with multiple projects simultaneously:
{
"mcpServers": {
"coraline-frontend": {
"command": "coraline",
"args": ["serve", "--mcp", "--path", "/projects/app/frontend"]
},
"coraline-backend": {
"command": "coraline",
"args": ["serve", "--mcp", "--path", "/projects/app/backend"]
}
}
}
Specify which server to use in prompts:
Use coraline-frontend to search for React components
Use coraline-backend to find API routes
Known Limitations
- No Claude models - Anthropic restriction (as of Jan 2026)
- Stdio only - WebSocket transport not supported
- Single project per server - Multi-repo workspaces not yet implemented
- No streaming responses - All results returned at once
Comparison with Claude Desktop/Code
| Feature | OpenCode | Claude Desktop | Claude Code |
|---|---|---|---|
| Model choice | 75+ providers | Claude only | Claude only |
| Terminal-based | ✅ | ❌ | ✅ |
| GUI | ❌ | ✅ | ❌ |
| Coraline support | ✅ | ✅ | ✅ |
| Timeout config | ✅ (required) | Optional | Optional |
| Local models | ✅ | ❌ | ❌ |
Testing Your Setup
1. Verify Installation
opencode --version
coraline --version
2. Test MCP Connection
cd your-project
opencode --model gpt-4 "List MCP tools"
Should show Coraline tools.
3. Test a Tool
opencode --model gpt-4 "Search for main function using coraline_search"
4. Test Context Building
opencode --model gpt-4 "Build context for understanding the authentication system"
5. Check Logs
cat .coraline/logs/coraline.log
Should show MCP requests and responses.
Next Steps
- MCP Tools Reference - All available tools
- Performance & Token Savings - Optimize usage
- Configuration Guide - Customize Coraline
- MCP Integration - Claude Desktop/Code setup
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 |
doctor | Run diagnostic checks (config, database, model, embed coverage) |
serve | Start the MCP server |
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 and no model decision flag is given, 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. Use --embed, --no-embed, or --yes to make the decision non-interactively (see below); if the model is already present on disk, init skips the prompt entirely regardless of flags.
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 |
--embed | Download the embedding model during init (skips the TTY prompt) |
--no-embed | Skip the embedding model entirely — no prompt, no download. Conflicts with --embed and always wins over --yes |
-y, --yes | Non-interactive mode: auto-accept the model download prompt |
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
coraline init --embed # Initialize and download the embedding model, no prompt
coraline init --no-embed # Initialize, skip the model entirely, no prompt
coraline init --yes # Initialize non-interactively; auto-downloads the model
Which model is downloaded is controlled by
vectors.modelin config (defaultnomic-embed-text-v1.5), not by aninitflag — seecoraline modelbelow and the[vectors]section in Configuration.
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, embedding-model state, 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)
Embeddings: model_quantized.onnx (161 MB)
Model: jina-embeddings-v2-base-code
Model dir: /home/user/.config/coraline/models/jina-embeddings-v2-base-code
Git hooks: installed
The Embeddings line shows not present (with a fix hint) when no model file has been downloaded yet for the project’s configured model (vectors.model, default nomic-embed-text-v1.5). See coraline model and coraline doctor below.
For deeper diagnostics (every probe with detail + fix hints, deep model-load / inference / embed-coverage checks, machine-readable JSON), use coraline doctor — it’s the same probe set that the MCP coraline_status tool runs when called with include_doctor: true.
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 doctor [PATH]
Run diagnostic checks against a project and report pass/fail per check, with a fix hint for anything failing. Exits 0 if every check passed, 1 otherwise — safe to use as a CI gate.
Checks (in order):
| Check | What it verifies |
|---|---|
config | .coraline/config.toml exists and is readable |
database | .coraline/coraline.db opens and returns stats (node/edge/file counts) |
git hooks | The post-commit hook is installed (or the project isn’t a git repo, which is fine) |
model file | At least one ONNX variant of the configured model (vectors.model) is present on disk |
model loads (deep only) | The ONNX model actually loads into an inference session |
inference (deep only) | A sample embedding runs through the loaded model successfully |
embed coverage (deep only) | Every indexed node has an embedding for the configured model |
The three deep checks require a build with the embeddings or embeddings-dynamic feature; they’re skipped (not failed) on builds without it.
Options:
| Flag | Description |
|---|---|
--quick | Skip the three deep model-load/inference/coverage checks (fast, no ONNX runtime needed) |
--deep | Explicit deep mode — this is already the default; mutually exclusive with --quick |
--json | Print the report as JSON instead of the human-readable ✔/✘ list |
Examples:
coraline doctor # Full diagnostic run (deep checks included)
coraline doctor --quick # Skip slow model checks — good for CI
coraline doctor --json # Machine-readable report
Sample output:
✔ config
✔ database
✔ git hooks
✘ model file
→ Run `coraline model download`.
Sample --json output:
{
"probes": [
{
"name": "config",
"ok": true,
"detail": "/path/.coraline/config.toml (3775 bytes)"
},
{
"name": "database",
"ok": true,
"detail": "/path/.coraline/coraline.db (2 nodes, 1 edges, 1 files)"
},
{ "name": "git hooks", "ok": true, "detail": "installed" },
{
"name": "model file",
"ok": false,
"detail": "no model file for 'nomic-embed-text-v1.5' in ...",
"fix": "Run `coraline model download`."
}
],
"exit_code": 1
}
The same --json shape is exposed by the MCP coraline_status tool when called with include_doctor: true (plus a top-level doctor_needs_attention bool) — see mcp-tools.md for the full MCP tool reference. This means MCP clients don’t need a separate coraline doctor invocation; one round-trip via coraline_status returns both the index stats and the full probe report.
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.
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.
Options:
| Flag | Description |
|---|---|
--download | Download the model automatically before embedding |
--variant FILENAME | ONNX variant to download (default: the configured model’s recommended variant) |
--batch-size N | Nodes per progress batch (default: 50) |
-q, --quiet | Suppress progress output |
Examples:
coraline embed # Embed using already-downloaded model
coraline embed --download # Download the configured model then embed
coraline embed --download --variant model_fp16.onnx
Run coraline index first. Uses the model configured by vectors.model (default nomic-embed-text-v1.5), stored in ~/.config/coraline/models/<model>/ — see coraline model list.
coraline model [PATH]
Manage embedding model files. Supports multiple models — run coraline model list to see the registry.
coraline model list
List every embedding model Coraline knows how to download and run, with dimension and description.
coraline model list
coraline model download
Download model files from HuggingFace.
| Flag | Description |
|---|---|
--model NAME | Which supported model to download (default: vectors.model from config.toml) |
--variant FILENAME | ONNX variant to download (default: the model’s recommended variant) |
-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 the shared model directory ~/.config/coraline/models/<model>/.
nomic-embed-text-v1.5 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 |
jina-embeddings-v2-base-code variants:
| Variant | Size | Notes |
|---|---|---|
model_quantized.onnx | ~162 MB | int8 quantized (recommended) |
model_fp16.onnx | ~321 MB | fp16 |
model.onnx | ~642 MB | full f32 |
coraline model download # download vectors.model's default variant
coraline model download --model jina-embeddings-v2-base-code
coraline model status
Show which model files are present in the model directory for the configured (or --model-selected) model.
| Flag | Description |
|---|---|
--model NAME | Which supported model to inspect (default: vectors.model from config.toml) |
coraline model status
coraline model status --model jina-embeddings-v2-base-code
Coraline MCP Tools Reference
Coraline exposes 38 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.
coraline_semantic_search is available by default (the embeddings feature ships enabled) but only registered when an ONNX model is present in the shared model directory (~/.config/coraline/models/<model>/, where <model> is vectors.model from config, default nomic-embed-text-v1.5). Run coraline model download then coraline embed to activate it — see coraline model list for every supported model. The remaining 37 tools are always available.
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 | |
coraline_cluster_overview | List Louvain clusters with one representative node per cluster | |
coraline_cluster_members | List nodes that share a given cluster_id | |
coraline_process_for | Return the call-graph trace (entry point + nodes + edges) for the given node | |
| Batch | coraline_batch_get_nodes | Fetch multiple nodes by ID in one call |
coraline_batch_callers | Get callers for multiple symbols in one call | |
coraline_batch_callees | Get callees for multiple symbols in one call | |
| Advanced Search | coraline_search_by_signature | Find symbols by type signature pattern |
coraline_search_by_docstring | Find symbols by documentation/comment content | |
coraline_search_exported_symbols | Search only public/exported symbols | |
coraline_find_by_kind_in_file | Get all symbols of a kind in one file | |
| Context | coraline_context | Build structured context for an AI task |
| Audit | coraline_audit_docs | Audit Markdown docs for stale references and undocumented exports |
| 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 | |
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 |
limit | number | 20 | Maximum callers to return | |
min_confidence | number | 0.0 | Minimum edge resolution confidence in [0.0, 1.0]. Edges below this threshold are filtered out. Direct AST-extracted edges have confidence 1.0; strongly-typed Rust crate:: / super:: / self:: resolutions have confidence 0.95; generic name matches / framework fallbacks have confidence 0.5. Default 0.0 includes every edge. |
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 |
limit | number | 20 | Maximum callees to return | |
min_confidence | number | 0.0 | Minimum edge resolution confidence in [0.0, 1.0]. Same scale as coraline_callers. | |
limit | number | 20 | Maximum callees to return |
Output: Same shape as coraline_callers but field is callees.
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 |
max_depth | number | 2 | BFS traversal depth | |
max_nodes | number | 50 | Cap on returned nodes |
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 |
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"]) |
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.
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 |
to_id | string | ✅ | Target node ID |
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 | |
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 |
edge_kind | string | all | Filter: calls, imports, extends, implements, references | |
limit | number | 50 | Maximum references | |
min_confidence | number | 0.0 | Minimum edge resolution confidence in [0.0, 1.0]. Same scale as coraline_callers / coraline_callees: 1.0 = direct AST-extracted, 0.95 = strong Rust path, 0.5 = generic / framework fallback. Default 0.0 includes every edge. |
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 |
include_edges | boolean | false | Also return incoming/outgoing edge counts |
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.
Batch Tools
Fetch results for multiple symbols in one call instead of N round trips — roughly 60% fewer tokens than the equivalent sequence of single-symbol calls.
coraline_batch_get_nodes
Fetch multiple nodes by ID in a single call.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
node_ids | array of string | ✅ | — | Node IDs to fetch |
include_body | boolean | false | Include source code body for each node | |
output_format | string | "full" | "full" or "compact" (65% token reduction) |
Output: { "nodes": [...], "count": N, "not_found": [...] }
coraline_batch_callers
Get callers for multiple symbols in a single call.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
node_ids | array of string | ✅ | — | Node IDs to find callers for |
limit_per_node | number | 20 | Maximum callers to return per node |
Output: { "callers": { "<node_id>": [...] }, "node_count": N }
coraline_batch_callees
Get callees for multiple symbols in a single call.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
node_ids | array of string | ✅ | — | Node IDs to find callees for |
limit_per_node | number | 20 | Maximum callees to return per node |
Output: { "callees": { "<node_id>": [...] }, "node_count": N }
Advanced Search Tools
Specialized lookups over indexed nodes, faster than full-text coraline_search for these specific shapes — also roughly 60% fewer tokens for the matched use case.
coraline_search_by_signature
Find symbols by type signature pattern (case-insensitive substring match) — e.g. functions by return type or parameters.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
pattern | string | ✅ | — | Signature substring to search for (e.g. "Result<", "async fn", "<T>") |
kind | string | — | Filter: function, method, class, struct, interface, trait | |
limit | number | 20 | Maximum results | |
output_format | string | "full" | "full" or "compact" (65% token reduction) |
coraline_search_by_docstring
Search symbols by documentation/comment content — find code by what it does, not just its name.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
query | string | ✅ | — | Text to search for in docstrings/comments |
kind | string | — | Filter: function, method, class, struct, interface, trait | |
limit | number | 20 | Maximum results | |
output_format | string | "full" | "full" or "compact" (65% token reduction) |
coraline_search_exported_symbols
Search only public/exported symbols — filters out internal implementation details to browse the public API surface.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
query | string | ✅ | — | Symbol name pattern; use "*" to list all |
kind | string | — | Filter: function, method, class, struct, interface, trait, module | |
limit | number | 20 | Maximum results | |
output_format | string | "full" | "full" or "compact" (65% token reduction) |
coraline_find_by_kind_in_file
Get all symbols of a specific kind in one file — fast file-scoped exploration.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
file_path | string | ✅ | — | Path to the file (relative to project root) |
kind | string | ✅ | — | function, method, class, struct, interface, trait, module, constant, or variable |
output_format | string | "full" | "full" or "compact" (65% token reduction) |
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.
Audit Tool
coraline_audit_docs
Audit Markdown documentation coverage against the indexed code graph.
Detects two classes of issues:
stale_refs: inline code-span symbol references in Markdown that do not resolve to indexed symbolsundocumented_exports: exported code symbols with no inboundreferencesedge from Markdown docs
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
show_undocumented | boolean | true | Include undocumented export results | |
show_stale | boolean | true | Include stale reference results | |
limit | number | 50 | Max items returned per result set |
Output:
{
"summary": {
"doc_files_indexed": 12,
"doc_sections_indexed": 89,
"stale_refs_count": 3,
"undocumented_exports_count": 7
},
"stale_refs": [
{
"reference": "resolve_unresolved",
"doc_file": "docs/ARCHITECTURE.md",
"section": "Resolution",
"line": 42,
"column": 18
}
],
"undocumented_exports": [
{
"name": "audit_docs",
"qualified_name": "coraline::audit::audit_docs",
"kind": "function",
"file": "crates/coraline/src/audit.rs",
"line": 48
}
]
}
File Tools
coraline_read_file
Read the contents of a file within the project.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
file_path | string | ✅ | — | File path (relative or absolute) |
start_line | number | — | Start line (1-based, inclusive) | |
end_line | number | — | End line (1-based, inclusive) |
coraline_list_dir
List the contents of a directory within the project.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path | string | . | Directory path (relative or absolute) | |
recursive | boolean | false | Recurse into subdirectories |
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 index statistics: total files, nodes, edges, and unresolved reference counts. Optionally include the full coraline doctor --json report for self-healing UIs.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
include_doctor | bool | false | When true, also runs coraline doctor probes and returns the full report under doctor_report, plus a top-level doctor_needs_attention bool. | |
deep | bool | false | Only meaningful when include_doctor is true. When true, runs the slower model-load / inference / coverage probes. |
Output (without include_doctor):
{
"project_root": "/abs/path/to/project",
"database": "/abs/path/to/project/.coraline/coraline.db",
"database_size_bytes": 2097152,
"stats": {
"nodes": 4201,
"edges": 9872,
"files": 128,
"unresolved_references": 153
}
}
Output (with include_doctor: true): the same fields above, plus:
{
"doctor_report": {
"probes": [
{ "name": "config", "ok": true, "detail": "...", "fix": null },
{ "name": "database", "ok": true, "detail": "...", "fix": null },
{ "name": "git hooks", "ok": false, "detail": "...", "fix": "..." },
{ "name": "vec_ext", "ok": true, "detail": "...", "fix": null },
{
"name": "model file",
"ok": false,
"detail": "...",
"fix": "Run `coraline model download`..."
}
],
"exit_code": 1
},
"doctor_needs_attention": true
}
doctor_needs_attention is derived from exit_code == 0 (inverted) so a UI can render a single bool to decide whether to surface a “fix this” prompt. The probes array carries the per-check name / ok / detail / fix fields — fix is the human-readable remediation hint (e.g. “Run coraline model download to enable semantic search.”).
Back-compat: when include_doctor is omitted (or false), the response shape is identical to the prior version — only the four legacy top-level keys appear.
Connection hygiene: the tool opens the SQLite database for the index stats query and drops that handle before invoking coraline doctor, so the WAL writer lock isn’t held by both queries simultaneously.
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 the shared model directory (~/.config/coraline/models/<model>/, <model> from vectors.model). To activate:
coraline model download # download the configured model (default nomic-embed-text-v1.5, ~137 MB)
coraline embed # generate embeddings for all indexed nodes
Run coraline model list to see every supported model, including the code-specialised jina-embeddings-v2-base-code. Results and coverage are scoped to whichever model is currently configured — embeddings from a previously-configured model are ignored, not mixed in.
Structured error when the model is missing:
If the ONNX model can’t be loaded (not downloaded yet, or tokenizer.json/weights missing), the tool call fails with isError: true and a structured EMBEDDING_MODEL_MISSING envelope in structuredContent, so an agent can branch on code instead of parsing free-form text:
{
"code": "EMBEDDING_MODEL_MISSING",
"message": "Embedding model is not present. Run `coraline model download` to download it.",
"recover": {
"command": "coraline model download",
"docs": "https://github.com/greysquirr3l/coraline#embeddings (debug: load failed: ...)"
}
}
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:
{
"results": [
{
"node_id": "abc123",
"name": "resolve_unresolved",
"similarity": 0.87,
"file_path": "src/resolution/mod.rs"
}
],
"count": 1
}
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" |
Cluster & Process Trace Tools
Louvain community detection (coraline_cluster_overview, coraline_cluster_members) and per-node execution-flow traces (coraline_process_for) are computed at index time during the post-extraction passes (run automatically by coraline index and coraline sync). Both column types are nullable — nodes.cluster_id IS NULL and edges.process_id IS NULL mean “not clustered” / “not part of any traced process” respectively. The tools return data only when the post-extraction passes have completed at least once.
coraline_cluster_overview
List Louvain clusters discovered during indexing, ordered by size, with one representative node per cluster.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
limit | number | 50 | Maximum clusters to return |
Output:
{
"clusters": [
{
"cluster_id": 0,
"size": 42,
"sample_node_id": "abc123",
"sample_qualified_name": "coraline::extraction::index_all",
"sample_kind": "function",
"sample_language": "rust"
},
{
"cluster_id": 1,
"size": 17,
"sample_node_id": "def456",
"sample_qualified_name": "coraline::db::query",
"sample_kind": "function",
"sample_language": "rust"
}
],
"count": 2
}
coraline_cluster_members
List all nodes that share the given cluster_id, ordered by qualified_name. Use the output of coraline_cluster_overview to pick a cluster_id.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
cluster_id | number | ✅ | — | Cluster id from coraline_cluster_overview |
limit | number | 200 | Maximum members to return |
Output:
{
"cluster_id": 0,
"nodes": [ ... full node records ... ],
"count": 42
}
coraline_process_for
Return the call-graph trace (entry point + nodes + edges) for the given node. Walks backward through incoming calls edges to find the owning entry point, then DFS forward through the call graph (with cycle protection + depth cap, default 50) to surface every node and edge in the process trace. Returns null when the node isn’t reachable from any entry point.
Input:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
node_id | string | ✅ | — | ID of the node to trace |
max_depth | number | 50 | Maximum DFS depth from the entry point |
Output (node reachable):
{
"entry_point": { /* full node record */ },
"depth_reached": 3,
"nodes": [ ... full node records ... ],
"edges": [
{
"source": "abc123",
"target": "def456",
"kind": "calls",
"line": 158,
"column": 4,
"confidence": 1.0,
"process_id": 1
}
]
}
Output (node unreachable): JSON null.
Each edge includes its process_id (matches the entry point’s trace ordinal) and confidence (same scale as coraline_callers / coraline_callees).
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.
Performance & Token Savings
Coraline provides several features to optimize performance and reduce AI token consumption.
Token Savings Overview
Coraline’s design focuses on reducing token usage in AI conversations:
| Feature | Token Savings | Use Case |
|---|---|---|
| Compact output format | 65% | All tool responses |
| Batch query tools | 60-90% | Multiple lookups |
| Edge filtering | 15% | Targeted traversals |
| Precomputed metrics | 20% latency | Impact analysis |
| Smart result limits | Variable | Large result sets |
Real-World Example
Without optimization:
20 individual coraline_node calls
= 20 requests × 50 tokens/request
= 1000 tokens
With batch tools:
1 coraline_batch_get_nodes call
= 1 request × 100 tokens
= 100 tokens (90% reduction)
Compact Output Format
All MCP tools support output_format: "compact" parameter for reduced token usage.
Standard vs Compact
Standard output (350 chars):
{
"node": {
"id": "abc123def456",
"kind": "Function",
"name": "authenticate_user",
"qualified_name": "auth::authenticate_user",
"file_path": "/project/src/auth/login.rs",
"start_line": 42,
"end_line": 95,
"language": "Rust",
"signature": "fn authenticate_user(username: &str, password: &str) -> Result<User>"
}
}
Compact output (120 chars, 65% reduction):
{
"n": {
"i": "abc123",
"k": 7,
"n": "authenticate_user",
"f": "src/auth/login.rs",
"l": 42,
"s": "fn authenticate_user(...)"
}
}
Usage
Instruct the AI assistant to use compact format:
Search for User class using compact output format
Find callers of login() with compact output
Or explicitly in tool parameters:
{
"query": "User",
"output_format": "compact"
}
Field Mappings
| Standard | Compact | Type |
|---|---|---|
id | i | string |
kind | k | int (enum) |
name | n | string |
qualified_name | q | string |
file_path | f | string |
start_line | l | int |
end_line | e | int |
language | g | string |
signature | s | string |
NodeKind enum values:
- 0: File, 1: Module, 2: Class, 3: Struct, 4: Interface, 5: Trait, 6: Protocol, 7: Function, 8: Method, etc.
Batch Query Tools
Batch tools eliminate round-trip overhead for multiple operations.
Available Batch Tools
coraline_batch_get_nodes
Fetch multiple nodes in one call:
{
"node_ids": ["id1", "id2", "id3", "id4", "id5"],
"output_format": "compact"
}
Savings: 90% vs 5 individual coraline_node calls
coraline_batch_callers
Get callers for multiple symbols:
{
"node_ids": ["func1", "func2", "func3"],
"limit": 10,
"output_format": "compact"
}
Savings: 70% vs 3 individual coraline_callers calls
coraline_batch_callees
Get callees for multiple symbols:
{
"node_ids": ["func1", "func2", "func3"],
"limit": 10,
"output_format": "compact"
}
Savings: 70% vs 3 individual coraline_callees calls
When to Use Batch Tools
Good use cases:
- Getting details for search results (10-20 nodes)
- Analyzing multiple related functions
- Building comprehensive context
- Investigating multiple API endpoints
Not ideal:
- Single lookups (use regular tools)
- Very large batches (>50 items, split into multiple calls)
- Unrelated queries (batch overhead not worth it)
Edge Filtering
Filter traversal operations to specific edge types for more targeted results.
Edge Types
| Edge Kind | Meaning |
|---|---|
calls | Function/method calls |
imports | Import statements |
exports | Export declarations |
extends | Class inheritance |
implements | Interface implementation |
references | Generic references |
type_of | Type annotations |
returns | Return types |
instantiates | Object creation |
Usage
Find only classes extending a base class:
{
"node_id": "BaseClass_id",
"edge_kinds": ["extends"],
"output_format": "compact"
}
Find only imports of a module:
{
"node_id": "module_id",
"edge_kinds": ["imports"]
}
Find calls and references (exclude type-only):
{
"node_id": "func_id",
"edge_kinds": ["calls", "references"]
}
Savings: ~15% by excluding irrelevant edges from results.
Result Limits
Control result set size to avoid overwhelming token budgets.
Default Limits
| Tool | Default Limit | Recommended |
|---|---|---|
coraline_search | 10 | 5-20 |
coraline_callers | 20 | 10-50 |
coraline_callees | 20 | 10-50 |
coraline_impact | 50 nodes | 20-100 |
coraline_context | 20 nodes | 10-30 |
coraline_semantic_search | 10 | 5-15 |
Adjusting Limits
Search with tight limit:
{
"query": "authenticate",
"limit": 5,
"output_format": "compact"
}
Impact analysis with depth control:
{
"node_id": "User_class",
"max_depth": 2,
"max_nodes": 30
}
Progressive exploration:
- Start with
limit: 5 - If more needed, increase to
limit: 20 - Use batch tools for detailed inspection
Precomputed Metrics
Coraline caches transitive caller/callee counts for instant impact analysis.
Metrics Table
During indexing, Coraline computes:
- Transitive caller count (how many functions call this, directly or indirectly)
- Transitive callee count (how many functions this calls, directly or indirectly)
Performance Impact
Without metrics (BFS traversal):
- 100-500ms per impact query
With precomputed metrics:
- <10ms per impact query (50x speedup)
Usage
Metrics are used automatically by:
coraline_impact- Fast hotspot identificationcoraline_dependencies- Quick dependency countscoraline_dependents- Fast reverse dependency counts
No special configuration required - metrics are computed during coraline index and coraline sync.
Advanced Search Tools
Specialized search tools reduce iterative lookups.
coraline_search_by_signature
Find symbols by type signature pattern:
{
"signature_pattern": "fn.*-> Result<User>",
"limit": 10
}
Use case: Find all functions returning Result<User> without iterating through all functions.
coraline_search_by_docstring
Search within documentation:
{
"query": "authentication middleware",
"limit": 10
}
Use case: Find relevant code by intent/purpose, not just name.
coraline_search_exported_symbols
Filter to public API only:
{
"query": "User",
"limit": 10
}
Use case: Focus on public API surface, ignore internal helpers.
Savings: ~60% by finding the right symbol in one query instead of filtering results manually.
Optimization Strategies
Strategy 1: Start Narrow
- Use specific search terms
- Apply kind filters (
--kind function) - Use small limits initially
- Expand only if needed
Example:
Search for "authenticate" with kind=function and limit=5
→ Found it in first 5 results
→ Saved tokens from fetching 15 more results
Strategy 2: Batch Similar Operations
- Collect IDs from search
- Use batch tools for details
- Process results together
Example:
1. Search for all "User" classes → 5 IDs
2. Batch get details for 5 IDs → 1 call
3. vs 5 individual calls → 80% token savings
Strategy 3: Use Edge Filters
- Determine relationship type needed
- Filter edges in query
- Get only relevant results
Example:
Find classes extending BaseController (not just referencing it)
→ Use edge_kinds=["extends"]
→ Skip unrelated references
Strategy 4: Incremental Context
- Build initial context with
max_nodes=10 - Identify gaps
- Fetch specific details with targeted queries
- vs loading everything upfront
Example:
1. Context for "auth system" with max_nodes=10
2. Identified missing middleware details
3. Search for middleware specifically
4. Saved tokens from overly broad initial context
Strategy 5: Compact by Default
- Always use
output_format: "compact" - Only request full format when displaying to user
- Internal operations use compact
Example:
20 compact queries = 2000 tokens
vs 20 full queries = 7000 tokens
→ 70% savings
Indexing Performance
Large Projects (10,000+ files)
Optimization tips:
-
Exclude aggressively:
[indexing] exclude_patterns = [ "**/test/**", "**/tests/**", "**/node_modules/**", "**/vendor/**", "**/.venv/**", "**/dist/**", "**/build/**", ] -
Increase batch size:
[indexing] batch_size = 200 -
Use incremental sync:
coraline sync # vs coraline index -
Target specific paths:
[indexing] include_patterns = [ "src/**/*.rs", "lib/**/*.ts", ]
Benchmarks
| Project Size | Full Index | Incremental Sync | Memory |
|---|---|---|---|
| 1,000 files | ~10s | ~2s | ~50MB |
| 10,000 files | ~90s | ~8s | ~200MB |
| 50,000 files | ~450s | ~30s | ~800MB |
Times measured on M1 MacBook Pro.
Semantic Search Performance
Model Inference
| Model Variant | Size | Inference Time (384-dim) |
|---|---|---|
model_q4f16.onnx | 111 MB | ~5ms/item |
model_int8.onnx | 137 MB | ~8ms/item |
model_fp16.onnx | 274 MB | ~12ms/item |
model.onnx | 547 MB | ~20ms/item |
Recommendation: Use model_int8.onnx for best balance of size/speed/accuracy.
Embedding Generation
| Project Size | Embedding Time (int8) |
|---|---|
| 1,000 nodes | ~10s |
| 10,000 nodes | ~90s |
| 50,000 nodes | ~450s |
Tip: Run coraline embed after large index operations, not during development.
Memory Usage
Database Size
| Nodes | Edges | DB Size |
|---|---|---|
| 1,000 | 2,500 | ~500KB |
| 10,000 | 25,000 | ~5MB |
| 100,000 | 250,000 | ~50MB |
Vector Storage
| Nodes | Embedding Size (384-dim, fp32) |
|---|---|
| 1,000 | ~1.5MB |
| 10,000 | ~15MB |
| 100,000 | ~150MB |
Runtime Memory
| Operation | Peak Memory |
|---|---|
| Indexing (10K files) | ~200MB |
| MCP server (idle) | ~30MB |
| Impact analysis | ~50MB |
| Semantic search | ~100MB (model loaded) |
Best Practices Summary
- Always use compact output format for internal operations
- Use batch tools for multiple related queries (3+ items)
- Apply edge filters when relationship type is known
- Start with small limits and expand if needed
- Use incremental sync instead of full reindex
- Exclude test/fixture directories from indexing
- Use precomputed metrics for impact analysis
- Cache results in project memories for repeated contexts
- Use advanced search tools to find symbols in one query
- Enable git hooks for automatic incremental updates
Monitoring Performance
Enable Debug Logging
CORALINE_LOG=debug coraline index
Check logs for timing information:
tail -f .coraline/logs/coraline.log
Measure Token Usage
Track token savings in your AI assistant:
- Before optimization: Note token count for a task
- After optimization: Compare token count for same task
- Calculate savings:
(before - after) / before × 100%
Profile Indexing
time coraline index
time coraline sync
Compare times to identify bottlenecks.
Future Optimizations
Planned features for even better performance:
- GCX1 wire format - 27% additional token reduction (vs compact JSON)
- Multi-repo workspaces - Share indexes across related projects
- Speculative execution - Preview changes without reindexing
- Streaming responses - Start processing results before all data arrives
- Incremental embeddings - Update only changed vectors
See Development Guide for contribution opportunities.
Supported Languages
Coraline uses tree-sitter for parsing, enabling support for 33 programming languages with AST-level precision.
Language Support Table
| Language | Status | tree-sitter grammar | Framework Support |
|---|---|---|---|
| Bash | ✅ Full | tree-sitter-bash 0.25.1 | - |
| C | ✅ Full | tree-sitter-c 0.23 | - |
| C++ | ✅ Full | tree-sitter-cpp 0.23 | - |
| C# | ✅ Full | tree-sitter-c-sharp 0.23 | .NET |
| Blazor | ✅ Full | tree-sitter-blazor 0.1.1 (custom) | Blazor components |
| Dart | ✅ Full | tree-sitter-dart 0.0.4 | Flutter |
| Elixir | ✅ Full | tree-sitter-elixir 0.3.4 | Phoenix |
| Elm | ✅ Full | tree-sitter-elm 5.9.0 | - |
| Erlang | ✅ Full | tree-sitter-erlang 0.15.0 | OTP |
| Fortran | ✅ Full | tree-sitter-fortran 0.5.1 | - |
| Go | ✅ Full | tree-sitter-go 0.23 | - |
| Groovy | ✅ Full | tree-sitter-groovy 0.1.2 | Gradle |
| Haskell | ✅ Full | tree-sitter-haskell 0.23.1 | - |
| Java | ✅ Full | tree-sitter-java 0.23 | Spring |
| JavaScript | ✅ Full | tree-sitter-javascript 0.25.0 | Node.js |
| JSX | ✅ Full | tree-sitter-javascript 0.25.0 | React |
| Julia | ✅ Full | tree-sitter-julia 0.23.1 | - |
| Kotlin | ✅ Full | tree-sitter-kotlin-ng 1.1.0 | Android |
| Lua | ✅ Full | tree-sitter-lua 0.4.1 | - |
| Markdown | ✅ Full | tree-sitter-markdown-fork 0.7.3 | - |
| MATLAB | ✅ Full | tree-sitter-matlab 1.3.0 | - |
| Nix | ✅ Full | tree-sitter-nix 0.3.0 | - |
| Perl | ✅ Full | tree-sitter-perl 1.1.2 | - |
| PHP | ✅ Full | tree-sitter-php 0.24.2 | Laravel |
| PowerShell | ✅ Full | tree-sitter-powershell 0.25.10 | - |
| Python | ✅ Full | tree-sitter-python 0.23 | Django, Flask |
| R | ✅ Full | tree-sitter-r 1.2.0 | - |
| Ruby | ✅ Full | tree-sitter-ruby 0.23 | Rails |
| Rust | ✅ Full | tree-sitter-rust 0.24.0 | - |
| Scala | ✅ Full | tree-sitter-scala 0.24.0 | - |
| Swift | ✅ Full | tree-sitter-swift 0.7.1 | iOS/macOS |
| TOML | ✅ Full | tree-sitter-toml-ng 0.7.0 | Config files |
| TypeScript | ✅ Full | tree-sitter-typescript 0.23.1 | Node.js |
| TSX | ✅ Full | tree-sitter-typescript 0.23.1 | React |
| YAML | ✅ Full | tree-sitter-yaml 0.7.2 | Config files |
| Zig | ✅ Full | tree-sitter-zig 1.1.2 | - |
Language Detection
Coraline detects languages by file extension:
| Extension(s) | Language |
|---|---|
.rs | Rust |
.ts | TypeScript |
.tsx | TSX (TypeScript + JSX) |
.js | JavaScript |
.jsx | JSX (JavaScript + JSX) |
.py | Python |
.go | Go |
.java | Java |
.c, .h | C |
.cpp, .cc, .cxx, .hpp | C++ |
.cs | C# |
.php | PHP |
.rb | Ruby |
.swift | Swift |
.kt, .kts | Kotlin |
.sh, .bash | Bash |
.ps1, .psm1 | PowerShell |
.razor | Blazor |
.dart | Dart |
.ex, .exs | Elixir |
.elm | Elm |
.erl, .hrl | Erlang |
.f90, .f95, .f03 | Fortran |
.groovy, .gradle | Groovy |
.hs | Haskell |
.jl | Julia |
.lua | Lua |
.md, .markdown | Markdown |
.m | MATLAB |
.nix | Nix |
.pl, .pm | Perl |
.r, .R | R |
.scala, .sc | Scala |
.toml | TOML |
.yaml, .yml | YAML |
.zig | Zig |
Node Types by Language
Different languages produce different node kinds:
Object-Oriented (Java, C#, Swift, Kotlin)
classinterfacemethodpropertyfieldenumenum_member
Functional (Haskell, Scala, Elixir, Erlang)
functionmoduletrait(Scala)type_aliasconstant
Systems (Rust, C, C++, Zig)
structfunctiontrait(Rust)enumtype_aliasmodule(Rust)
Scripting (Python, Ruby, PHP, Bash)
functionclassmethodvariableconstant
Web Frontend (JavaScript, TypeScript, TSX, JSX)
functionclassmethodcomponent(React/JSX/TSX)interface(TypeScript)type_alias(TypeScript)
Markup (Markdown, YAML, TOML)
module(file-level)constant(YAML/TOML keys)
Framework-Specific Features
Rust
- Crate-relative imports (
crate::,super::,self::) - Trait implementation tracking
- Macro detection
- Module tree resolution
React (JavaScript/TypeScript/JSX/TSX)
- Component detection (PascalCase)
- Hook tracking (
use*functions) - Relative imports (
./,../) - Path aliases (
@/)
Blazor (C# + Razor)
- Razor component detection (
.razorfiles) - Component parameter tracking
- .NET type resolution
- Dependency injection detection
Laravel (PHP)
- PSR-4 autoloading resolution
- Blade template tracking
- Facade detection
- Dot-notation view paths
Python
- Module imports (
from ... import) - Package structure
- Class/function decorators
- Django/Flask detection (future)
Others
- Swift/Kotlin: Protocol/interface conformance
- Elixir: Phoenix routing, Ecto schemas
- Java: Spring annotations, package resolution
Cross-Language Support
Coraline can index polyglot projects with multiple languages:
project/
├── backend/ (Rust)
├── frontend/ (TypeScript + React)
├── mobile/ (Swift, Kotlin)
└── scripts/ (Python, Bash)
All languages are indexed into a unified graph. Cross-language references (e.g., TypeScript calling Rust WASM) are tracked as unresolved edges unless framework resolvers are available.
Language-Specific Configuration
Customize indexing per language via config.toml:
[indexing]
include_patterns = [
"src/**/*.rs", # Rust source
"lib/**/*.ts", # TypeScript libraries
"app/**/*.tsx", # React components
"**/*.py", # Python anywhere
]
exclude_patterns = [
"**/target/**", # Rust builds
"**/node_modules/**", # JS/TS deps
"**/__pycache__/**", # Python cache
"**/dist/**", # Build outputs
]
Adding New Languages
Coraline can be extended with new tree-sitter grammars:
-
Add the grammar to
Cargo.toml:tree-sitter-newlang = "0.1.0" -
Register in
extraction.rs:#![allow(unused)] fn main() { ".newlang" => tree_sitter_newlang::language(), } -
Add extraction patterns for node/edge types
-
(Optional) Add framework resolver in
resolution/frameworks/
See Development Guide for contribution instructions.
Language Limitations
Markdown
- Only headings and code blocks are indexed
- No inline link tracking
YAML/TOML
- Config keys indexed as
constantnodes - No deep structure analysis
Bash/PowerShell
- Function detection only
- Limited variable tracking
Future Enhancements
- SQL query extraction (embedded SQL strings)
- HTML/CSS parsing (currently ignored)
- GraphQL schema tracking
- Protocol Buffers support
Performance by Language
Parse speed varies by grammar complexity:
| Language Group | Relative Speed | Notes |
|---|---|---|
| Rust, Go, C | Fast | Simple, deterministic grammars |
| TypeScript, Python | Medium | More complex syntax rules |
| C++, Scala | Slower | High grammar complexity |
| Markdown, YAML | Very Fast | Simple structure |
Actual impact on indexing is minimal (<5% variation) for most projects.
Testing Language Support
Verify language support for your project:
# Index and check stats
coraline init -i
coraline stats --json
# Check language breakdown
jq '.files_by_language' .coraline/stats.json
Output:
{
"rust": 42,
"typescript": 31,
"python": 12,
"markdown": 5
}
Search for language-specific symbols:
# Rust
coraline query "impl" --kind trait
# TypeScript
coraline query "interface" --kind interface
# Python
coraline query "def" --kind function
Requesting Language Support
To request a new language:
- Check if a tree-sitter grammar exists at tree-sitter.github.io
- Open an issue at github.com/greysquirr3l/coraline/issues
- Include:
- Language name and typical file extensions
- Link to tree-sitter grammar
- Example files for testing
- (Optional) Framework-specific features needed
Next Steps
- Quick Start Guide - Start indexing your project
- Configuration Guide - Customize language filtering
- Architecture - How language parsing works
- Development Guide - Contribute new languages
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 | User-editable configuration (all settings) |
.coraline/coraline.db | SQLite knowledge graph (do not edit) |
.coraline/memories/ | Project memory files (Markdown) |
.coraline/logs/ | Daily-rotating log files |
Migration from v0.3.x or earlier: If you have a legacy
config.jsonfile, runcoraline config --migrateto convert it toconfig.toml. The old file will be backed up asconfig.json.backup.
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
[vectors]
enabled = false # Requires ONNX model (see below)
model = "nomic-embed-text-v1.5" # or "jina-embeddings-v2-base-code"
dimension = 768
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
[vectors] Section
Controls vector embedding generation for semantic search (coraline embed, the coraline_semantic_search MCP tool). Requires a build with the embeddings or embeddings-dynamic feature.
enabled
Enable vector embedding generation.
- Type: boolean
- Default:
false
model
Which embedding model to use. Run coraline model list to see every supported model with its dimension and description.
- Type: string
- Default:
"nomic-embed-text-v1.5"— general-purpose English text embeddings. - Also supported:
"jina-embeddings-v2-base-code"— code-specialised embeddings, opt-in.
Model files live in a shared directory (~/.config/coraline/models/<model>/, or model_dir below), not per-project — every project on the machine reuses the same downloaded weights for a given model. Run coraline model download (add --model <name> to target a non-default model) to fetch it.
Switching models: changing
modelon a project that already has embeddings does not retroactively re-embed existing nodes. Every read path (coraline_semantic_search,coraline doctor’s coverage probe, staleness checks) filters by the configured model, so a switch makes every node look unembedded for the new model until you re-runcoraline embed. This is a real (if usually quick) re-embedding pass, not instant.
dimension
Embedding vector dimension. Must match the selected model — both currently supported models emit 768-dim vectors.
- Type: integer
- Default:
768
batch_size
Number of symbols embedded per batch.
- Type: integer
- Default:
32
model_dir
Override the on-disk model directory. Unset by default — Coraline resolves it from model (~/.config/coraline/models/<model>/).
- Type: string (path), optional
model_file
Pin a specific ONNX filename instead of auto-detecting the best available variant for the configured model.
- Type: string, optional
max_seq_len
Maximum sequence length in tokens fed to the model.
- Type: integer
- Default:
512
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.
Migrate from legacy config.json:
coraline config --migrate
This converts an old config.json file to the new config.toml format and backs up the original as config.json.backup.
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
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
┌─────────────────────────────────────────────────────────────────┐
│ AI Assistant (MCP Client) │
│ (Claude Desktop, Claude Code, etc.) │
└────────────────────────────┬────────────────────────────────────┘
│ MCP (stdio)
▼
┌─────────────────────────────────────────────────────────────────┐
│ coraline serve --mcp │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Tool Registry │ │
│ │ ┌────────────┐ ┌──────────────┐ ┌───────────────┐ │ │
│ │ │ Graph Tools│ │Context Tools │ │ Memory Tools │ │ │
│ │ │ File Tools │ │ │ │ │ │ │
│ │ └─────┬──────┘ └──────┬───────┘ └───────┬───────┘ │ │
│ └────────┼────────────────┼──────────────────┼────────────┘ │
│ └────────────────┼──────────────────┘ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Core Engine │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐ │ │
│ │ │extraction│ │ db │ │ graph │ │context │ │ │
│ │ │(parsers) │ │(SQLite) │ │(traversal│ │(builder│ │ │
│ │ └────┬─────┘ └────┬─────┘ └──────────┘ └────────┘ │ │
│ │ │ │ │ │
│ │ ┌────▼─────┐ ┌────▼─────────────────────────────┐ │ │
│ │ │resolution│ │ vectors │ sync │ memory │ │ │
│ │ │(ref-res) │ │(embeddings)│(git hook│(memories) │ │ │
│ │ └──────────┘ └────────────┴─────────┴───────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
.coraline/ (per project)
├── coraline.db
├── config.toml
├── memories/
└── logs/
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
├── clustering.rs # Louvain community detection + process tracing (Phase 5.1)
├── 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 + ONNX model management
├── vec_ext.rs # Optional sqlite-vec integration (Phase 5.3, `--features vec-ext`)
├── memory.rs # Project memory CRUD
├── config.rs # TOML + JSON configuration loading
├── sync.rs # Incremental sync + git hook management
├── logging.rs # Structured logging (tracing)
├── doctor.rs # Self-healing probes (config, db, model, hooks, embed coverage)
├── security.rs # Path/permission guards for MCP file tools
├── audit.rs # Lightweight structured event log for tool invocations
├── update.rs # Self-update helper (cargo install --force flow)
├── mcp.rs # MCP server (JSON-RPC over stdio)
├── utils.rs # Shared utilities
├── db/ # Schema migrations + table-level helpers
└── 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>,
pub cluster_id: Option<i64>, // Phase 5.1 — Louvain community id; None for unclustered nodes
}
}
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>,
pub confidence: f32, // Phase 5.2 — in [0.0, 1.0], see table below
pub process_id: Option<i64>, // Phase 5.1 — execution-flow trace id; None for edges not in any process trace
}
}
EdgeKind values: contains, calls, imports, exports, extends, implements, references, type_of, returns, instantiates
Every Edge carries a confidence: f32 in [0.0, 1.0]:
1.0— direct AST-extracted (caller wrote the symbol syntactically; no resolution was needed)0.95— strongly-typed Rust path (crate::/super::/self::)0.5— generic name match / framework fallback / heuristic ranker
coraline_callers / coraline_callees / coraline_find_references accept a min_confidence parameter that filters edges below a caller-supplied threshold. Default 0.0 includes every edge; a typical working value is 0.8 to suppress generic matches.
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. EveryEdgecarries aconfidencefield (see Edges). - 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. Resolved edges are stamped with theirconfidence. - Cluster (Phase 5.1) — Run Louvain community detection over the call graph and write
nodes.cluster_id. Detects “module-like” communities (groups of nodes that call each other more than they call outside the group). - Trace processes (Phase 5.1) — For each exported
Function/Methodwith no incomingcallsedge (an “entry point”), DFS forward through the call graph with cycle protection and a depth cap, writingedges.process_id. Every edge that participates in some process trace gets aprocess_id.
Steps 6 and 7 run as part of every coraline index and coraline sync after extraction succeeds. The columns are nullable — cluster_id IS NULL and process_id IS NULL are normal for nodes/edges that don’t participate in any cluster or process trace.
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 these tables:
| Table | Purpose |
|---|---|
nodes | All indexed symbols with full metadata, plus a nullable cluster_id (Phase 5.1, Louvain community id) |
edges | Directed relationships between nodes, plus a confidence REAL (Phase 5.2, in [0.0, 1.0]) and a nullable process_id (Phase 5.1, execution-flow trace id) |
nodes_fts | FTS5 virtual table for fast name search |
vectors | Optional embeddings storage. embedding BLOB (v1) or vec0 vec0 virtual table (--features vec-ext) |
schema_versions | Additive-migration bookkeeping. Every additive ALTER TABLE bumps a version row here. |
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.
Additive migrations
DB schema changes after v1 are additive: each new column is gated by a PRAGMA table_info(<table>) check in db::apply_incremental_migrations and stamped with a row in schema_versions. Existing DBs migrate in place on next coraline init / coraline sync without backfill. The migration order is:
- v2 —
edges.confidence REAL NOT NULL DEFAULT 1.0(Phase 5.2) - v3 —
nodes.cluster_id INTEGER,edges.process_id INTEGER(Phase 5.1)
All migrations are idempotent — the column_exists guard makes re-running safe.
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/initializedtools/list— returns all 38 tool descriptorstools/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
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 (all warnings as errors)
cargo clippy --all-features -- -D warnings
# 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
mcp.rsMcpServer::register_tools():#![allow(unused)] fn main() { registry.register(Box::new(MyTool::new(root.clone()))); } -
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 |
fuzz.yml | daily + fuzz/** or surface changes | cargo-fuzz nightly run against MCP + SQLite targets |
cifuzz.yml | PR + surface changes | ClusterFuzzLite per-PR fuzzing with libFuzzer + AddressSanitizer |
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 clippy --all-features -- -D warningsmust 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
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"0.0.1"}}}' \
| coraline serve --mcp
Check all tests pass after a change
cargo clippy --all-features -- -D warnings && cargo test --all-features 2>&1 | grep "test result"
Run fuzzers locally
Two cargo-fuzz targets live under fuzz/fuzz_targets/. They require the
nightly toolchain because libfuzzer-sys depends on nightly-only features.
# One-time: install cargo-fuzz
cargo install cargo-fuzz --locked
# Run a target for 5 minutes
cargo +nightly fuzz run mcp_request -- -max_total_time=300
cargo +nightly fuzz run db_search -- -max_total_time=300
# Reproduce a crash from CI artifacts
cargo +nightly fuzz run mcp_request fuzz/corpus/mcp_request/crash-<id>
A crash report surfaces as fuzz/artifacts/<target>/crash-<sha1>. Open or
attach the file in a GitHub issue; do not paste the binary contents.
ClusterFuzzLite
.github/workflows/cifuzz.yml runs the same targets on every PR via
ClusterFuzzLite, built on the
upstream base-builder-rust image and configured under .clusterfuzzlite/.
This also satisfies the OpenSSF Scorecard Fuzzing check.