Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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

  1. Index - Coraline scans your project and builds a knowledge graph of all symbols (functions, classes, types, etc.) and their relationships
  2. Query - Use the CLI or MCP tools to search, traverse, and analyze your codebase
  3. 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

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

  1. Download the appropriate binary for your platform
  2. Extract the archive
  3. Move the binary to a directory in your PATH:
# macOS/Linux example
chmod +x coraline
sudo mv coraline /usr/local/bin/
  1. 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:

VariantSizeNotes
model_q4f16.onnx~111 MBQ4 + fp16 mixed (smallest)
model_int8.onnx~137 MBint8 quantized (recommended)
model_fp16.onnx~274 MBfp16
model.onnx~547 MBfull 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

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 graph
  • config.toml - Configuration file
  • memories/ - Project memory directory
  • logs/ - 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:

  1. Visit nomic-ai/nomic-embed-text-v1.5
  2. Download tokenizer.json, tokenizer_config.json, and your chosen ONNX variant
  3. 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

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

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

For AI Assistant Integration

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):

  1. Use more specific include_patterns
  2. Increase batch_size in config
  3. 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 name
  • coraline_semantic_search - Natural language search (requires embeddings)
  • coraline_callers - Find what calls a symbol
  • coraline_callees - Find what a symbol calls
  • coraline_impact - Analyze change impact
  • coraline_context - Build context for a task

Advanced:

  • coraline_batch_get_nodes - Fetch multiple nodes (60-90% token savings)
  • coraline_batch_callers - Batch caller queries
  • coraline_batch_callees - Batch callee queries
  • coraline_search_by_signature - Search by type signature
  • coraline_search_by_docstring - Search docstrings
  • coraline_search_exported_symbols - Public API only

File & Config:

  • coraline_read_file - Read file contents
  • coraline_list_dir - List directory
  • coraline_get_file_nodes - Symbols in a file
  • coraline_status - Project statistics
  • coraline_sync - Incremental update
  • coraline_get_config / coraline_update_config - Configuration

Memory:

  • coraline_write_memory - Create/update memories
  • coraline_read_memory - Read memories
  • coraline_list_memories - List all memories
  • coraline_delete_memory - Delete a memory
  • coraline_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

  1. Check that Coraline is in your PATH:

    which coraline
    
  2. Verify the config path is correct

  3. Restart the MCP client

  4. 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

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:

OperationTypical DurationRecommended Timeout
coraline_search<1sDefault (120s) OK
coraline_callers1-5sDefault OK
coraline_impact (large)5-30s300000ms (5 min)
coraline_sync (many files)10-60s300000ms (5 min)
coraline_context (deep)5-20s300000ms (5 min)
coraline_embed30-300s600000ms (10 min)

Timeout Error Handling

If you see timeout errors:

  1. Increase timeout in .opencode/config.json:

    "args": ["serve", "--mcp", "--timeout", "600000"]
    
  2. Optimize your queries:

    • Use --limit parameters to reduce result size
    • Use --max-depth to limit traversal depth
    • Use compact output format
  3. 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”

  1. Verify .opencode/config.json exists in your project root
  2. Check that coraline is in your PATH or use absolute path
  3. 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

  1. Check Coraline version:

    coraline --version
    
  2. Check logs:

    tail -f .coraline/logs/coraline.log
    
  3. 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

  1. No Claude models - Anthropic restriction (as of Jan 2026)
  2. Stdio only - WebSocket transport not supported
  3. Single project per server - Multi-repo workspaces not yet implemented
  4. No streaming responses - All results returned at once

Comparison with Claude Desktop/Code

FeatureOpenCodeClaude DesktopClaude Code
Model choice75+ providersClaude onlyClaude only
Terminal-based✅❌✅
GUI❌✅❌
Coraline support✅✅✅
Timeout config✅ (required)OptionalOptional
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

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

CommandDescription
initInitialize a new project
indexFull reindex of the project
syncIncremental update (git-diff based)
statusShow project status and paths
statsShow index statistics
querySearch symbols by name
contextBuild AI context for a task
callersFind what calls a node
calleesFind what a node calls
impactAnalyze change impact radius
configRead or update configuration
hooksManage git hooks
doctorRun diagnostic checks (config, database, model, embed coverage)
serveStart the MCP server
embedGenerate vector embeddings for indexed nodes
modelManage 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:

FlagDescription
-i, --indexRun a full index immediately after initialization
-f, --forceOverwrite an existing .coraline/ directory without prompting
--no-hooksSkip automatic git hook installation
--embedDownload the embedding model during init (skips the TTY prompt)
--no-embedSkip the embedding model entirely — no prompt, no download. Conflicts with --embed and always wins over --yes
-y, --yesNon-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.model in config (default nomic-embed-text-v1.5), not by an init flag — see coraline model below 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:

FlagDescription
-f, --forceForce re-parse all files, even unchanged ones
-q, --quietSuppress 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:

FlagDescription
-q, --quietSuppress 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:

FlagDescription
-j, --jsonOutput 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:

ArgumentDescription
SEARCHSymbol name or search pattern

Options:

FlagDescription
-p, --path PATHProject root path
-l, --limit NMaximum results (default: 10)
-k, --kind KINDFilter by node kind (see below)
-j, --jsonOutput 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:

ArgumentDescription
TASKNatural language task description

Options:

FlagDescription
-p, --path PATHProject root path
-n, --max-nodes NMax graph nodes (default: 50)
-c, --max-code NMax code blocks (default: 10)
--no-codeOmit source code snippets
-f, --format FMTmarkdown (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:

ArgumentDescription
NODE_IDNode ID (from query or stats --json output)

Options:

FlagDescription
-p, --path PATHProject root path
-l, --limit NMaximum results (default: 20)
-j, --jsonOutput 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:

ArgumentDescription
NODE_IDNode ID to analyze

Options:

FlagDescription
-p, --path PATHProject root path
-d, --depth NBFS depth (default: 3)
-j, --jsonOutput 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:

FlagDescription
-p, --path PATHProject root path
-j, --jsonPrint config as JSON
-s, --section SECPrint only a section (indexing, context, sync, vectors)
--set KEY=VALUESet 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:

ActionDescription
installInstall the hook (backs up existing hook)
removeRemove the hook (restores backup if present)
statusShow whether the hook is installed

Options:

FlagDescription
-p, --path PATHProject 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):

CheckWhat it verifies
config.coraline/config.toml exists and is readable
database.coraline/coraline.db opens and returns stats (node/edge/file counts)
git hooksThe post-commit hook is installed (or the project isn’t a git repo, which is fine)
model fileAt 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:

FlagDescription
--quickSkip the three deep model-load/inference/coverage checks (fast, no ONNX runtime needed)
--deepExplicit deep mode — this is already the default; mutually exclusive with --quick
--jsonPrint 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:

FlagDescription
-p, --path PATHProject root path
--mcpStart 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

VariableDescription
CORALINE_LOGLog 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:

FlagDescription
--downloadDownload the model automatically before embedding
--variant FILENAMEONNX variant to download (default: the configured model’s recommended variant)
--batch-size NNodes per progress batch (default: 50)
-q, --quietSuppress 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.

FlagDescription
--model NAMEWhich supported model to download (default: vectors.model from config.toml)
--variant FILENAMEONNX variant to download (default: the model’s recommended variant)
-f, --forceRe-download even if files already exist
-q, --quietSuppress 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):

VariantSizeNotes
model_q4f16.onnx~111 MBQ4 + fp16 mixed (smallest)
model_int8.onnx~137 MBint8 quantized (recommended)
model_fp16.onnx~274 MBfp16
model.onnx~547 MBfull f32

jina-embeddings-v2-base-code variants:

VariantSizeNotes
model_quantized.onnx~162 MBint8 quantized (recommended)
model_fp16.onnx~321 MBfp16
model.onnx~642 MBfull 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.

FlagDescription
--model NAMEWhich 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

CategoryToolDescription
Graphcoraline_searchFind symbols by name or pattern
coraline_callersFind what calls a symbol
coraline_calleesFind what a symbol calls
coraline_impactAnalyze change impact radius
coraline_dependenciesOutgoing dependency graph from a node
coraline_dependentsIncoming dependency graph (what depends on a node)
coraline_pathFind a path between two nodes
coraline_statsDetailed graph statistics by language/kind/edge
coraline_find_symbolFind symbols with rich metadata + optional body
coraline_get_symbols_overviewList all symbols in a file
coraline_find_referencesFind all references to a symbol
coraline_nodeGet full node details and source code
coraline_cluster_overviewList Louvain clusters with one representative node per cluster
coraline_cluster_membersList nodes that share a given cluster_id
coraline_process_forReturn the call-graph trace (entry point + nodes + edges) for the given node
Batchcoraline_batch_get_nodesFetch multiple nodes by ID in one call
coraline_batch_callersGet callers for multiple symbols in one call
coraline_batch_calleesGet callees for multiple symbols in one call
Advanced Searchcoraline_search_by_signatureFind symbols by type signature pattern
coraline_search_by_docstringFind symbols by documentation/comment content
coraline_search_exported_symbolsSearch only public/exported symbols
coraline_find_by_kind_in_fileGet all symbols of a kind in one file
Contextcoraline_contextBuild structured context for an AI task
Auditcoraline_audit_docsAudit Markdown docs for stale references and undocumented exports
Filecoraline_read_fileRead file contents
coraline_list_dirList directory contents
coraline_find_fileFind files by glob pattern
coraline_get_file_nodesGet all indexed nodes in a file
coraline_statusShow project index statistics
coraline_syncTrigger incremental index sync
coraline_get_configRead project configuration
coraline_update_configUpdate a config value
coraline_semantic_searchVector similarity search (requires model download — see below)
Memorycoraline_write_memoryWrite or update a project memory
coraline_read_memoryRead a project memory
coraline_list_memoriesList all memories
coraline_delete_memoryDelete a memory
coraline_edit_memoryEdit memory via literal or regex replace

Graph Tools

Search for code symbols by name or pattern across the indexed codebase.

Input:

ParameterTypeRequiredDefaultDescription
querystring✅—Symbol name or FTS pattern
kindstring—Filter: function, method, class, struct, interface, trait, module
limitnumber10Maximum 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:

ParameterTypeRequiredDefaultDescription
node_idstring✅—ID of the target node
limitnumber20Maximum callers to return
min_confidencenumber0.0Minimum 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:

ParameterTypeRequiredDefaultDescription
node_idstring✅—ID of the source node
limitnumber20Maximum callees to return
min_confidencenumber0.0Minimum edge resolution confidence in [0.0, 1.0]. Same scale as coraline_callers.
limitnumber20Maximum 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:

ParameterTypeRequiredDefaultDescription
node_idstring✅—ID of the node to analyze
max_depthnumber2BFS traversal depth
max_nodesnumber50Cap 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:

ParameterTypeRequiredDefaultDescription
node_idstring✅—ID of the source node
max_depthnumber2BFS traversal depth
max_nodesnumber50Cap on returned nodes
edge_kindsstring[]allEdge 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:

ParameterTypeRequiredDescription
from_idstring✅Starting node ID
to_idstring✅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:

ParameterTypeRequiredDefaultDescription
name_patternstring✅—Symbol name or substring
kindstring—Same kind filter as coraline_search
include_bodybooleanfalseAttach source code body
limitnumber10Maximum 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:

ParameterTypeRequiredDescription
file_pathstring✅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:

ParameterTypeRequiredDefaultDescription
node_idstring✅—ID of the target node
edge_kindstringallFilter: calls, imports, extends, implements, references
limitnumber50Maximum references
min_confidencenumber0.0Minimum 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:

ParameterTypeRequiredDefaultDescription
node_idstring✅—The node ID
include_edgesbooleanfalseAlso 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:

ParameterTypeRequiredDefaultDescription
node_idsarray of string✅—Node IDs to fetch
include_bodybooleanfalseInclude source code body for each node
output_formatstring"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:

ParameterTypeRequiredDefaultDescription
node_idsarray of string✅—Node IDs to find callers for
limit_per_nodenumber20Maximum 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:

ParameterTypeRequiredDefaultDescription
node_idsarray of string✅—Node IDs to find callees for
limit_per_nodenumber20Maximum 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:

ParameterTypeRequiredDefaultDescription
patternstring✅—Signature substring to search for (e.g. "Result<", "async fn", "<T>")
kindstring—Filter: function, method, class, struct, interface, trait
limitnumber20Maximum results
output_formatstring"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:

ParameterTypeRequiredDefaultDescription
querystring✅—Text to search for in docstrings/comments
kindstring—Filter: function, method, class, struct, interface, trait
limitnumber20Maximum results
output_formatstring"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:

ParameterTypeRequiredDefaultDescription
querystring✅—Symbol name pattern; use "*" to list all
kindstring—Filter: function, method, class, struct, interface, trait, module
limitnumber20Maximum results
output_formatstring"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:

ParameterTypeRequiredDefaultDescription
file_pathstring✅—Path to the file (relative to project root)
kindstring✅—function, method, class, struct, interface, trait, module, constant, or variable
output_formatstring"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:

ParameterTypeRequiredDefaultDescription
taskstring✅—Natural language task description
max_nodesnumber20Max graph nodes to include
max_code_blocksnumber5Max code block attachments
max_code_block_sizenumber1500Max chars per code block
include_codebooleantrueAttach source code snippets
traversal_depthnumber1Graph traversal depth
formatstring"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 symbols
  • undocumented_exports: exported code symbols with no inbound references edge from Markdown docs

Input:

ParameterTypeRequiredDefaultDescription
show_undocumentedbooleantrueInclude undocumented export results
show_stalebooleantrueInclude stale reference results
limitnumber50Max 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:

ParameterTypeRequiredDefaultDescription
file_pathstring✅—File path (relative or absolute)
start_linenumber—Start line (1-based, inclusive)
end_linenumber—End line (1-based, inclusive)

coraline_list_dir

List the contents of a directory within the project.

Input:

ParameterTypeRequiredDefaultDescription
pathstring.Directory path (relative or absolute)
recursivebooleanfalseRecurse into subdirectories

coraline_get_file_nodes

Get all indexed symbols (nodes) for a specific file.

Input:

ParameterTypeRequiredDescription
file_pathstring✅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:

ParameterTypeRequiredDefaultDescription
patternstring✅—File name, substring, or glob pattern (*.rs, test_*, [Cc]argo.toml)
limitnumber20Maximum 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:

ParameterTypeRequiredDefaultDescription
include_doctorboolfalseWhen true, also runs coraline doctor probes and returns the full report under doctor_report, plus a top-level doctor_needs_attention bool.
deepboolfalseOnly 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:

ParameterTypeRequiredDescription
keystring✅Dot-notation path, e.g. context.max_nodes
valueany✅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
}

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:

ParameterTypeRequiredDefaultDescription
querystring✅—Natural-language description of what you’re looking for
limitnumber10Max results
min_similaritynumber0.3Minimum 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:

ParameterTypeRequiredDescription
namestring✅Memory name (without .md). E.g. project_overview
contentstring✅Memory content in Markdown format

coraline_read_memory

Read a project memory by name.

Input:

ParameterTypeRequiredDescription
namestring✅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:

ParameterTypeRequiredDescription
namestring✅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:

ParameterTypeRequiredDefaultDescription
namestring✅—Memory name (without .md)
patternstring✅—Text to find
replacementstring✅—Replacement text
modestring"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:

ParameterTypeRequiredDefaultDescription
limitnumber50Maximum 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:

ParameterTypeRequiredDefaultDescription
cluster_idnumber✅—Cluster id from coraline_cluster_overview
limitnumber200Maximum 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:

ParameterTypeRequiredDefaultDescription
node_idstring✅—ID of the node to trace
max_depthnumber50Maximum 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:

FeatureToken SavingsUse Case
Compact output format65%All tool responses
Batch query tools60-90%Multiple lookups
Edge filtering15%Targeted traversals
Precomputed metrics20% latencyImpact analysis
Smart result limitsVariableLarge 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

StandardCompactType
idistring
kindkint (enum)
namenstring
qualified_nameqstring
file_pathfstring
start_linelint
end_lineeint
languagegstring
signaturesstring

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 KindMeaning
callsFunction/method calls
importsImport statements
exportsExport declarations
extendsClass inheritance
implementsInterface implementation
referencesGeneric references
type_ofType annotations
returnsReturn types
instantiatesObject 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

ToolDefault LimitRecommended
coraline_search105-20
coraline_callers2010-50
coraline_callees2010-50
coraline_impact50 nodes20-100
coraline_context20 nodes10-30
coraline_semantic_search105-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:

  1. Start with limit: 5
  2. If more needed, increase to limit: 20
  3. 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 identification
  • coraline_dependencies - Quick dependency counts
  • coraline_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

  1. Use specific search terms
  2. Apply kind filters (--kind function)
  3. Use small limits initially
  4. 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

  1. Collect IDs from search
  2. Use batch tools for details
  3. 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

  1. Determine relationship type needed
  2. Filter edges in query
  3. Get only relevant results

Example:

Find classes extending BaseController (not just referencing it)
→ Use edge_kinds=["extends"]
→ Skip unrelated references

Strategy 4: Incremental Context

  1. Build initial context with max_nodes=10
  2. Identify gaps
  3. Fetch specific details with targeted queries
  4. 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

  1. Always use output_format: "compact"
  2. Only request full format when displaying to user
  3. 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:

  1. Exclude aggressively:

    [indexing]
    exclude_patterns = [
      "**/test/**",
      "**/tests/**",
      "**/node_modules/**",
      "**/vendor/**",
      "**/.venv/**",
      "**/dist/**",
      "**/build/**",
    ]
    
  2. Increase batch size:

    [indexing]
    batch_size = 200
    
  3. Use incremental sync:

    coraline sync  # vs coraline index
    
  4. Target specific paths:

    [indexing]
    include_patterns = [
      "src/**/*.rs",
      "lib/**/*.ts",
    ]
    

Benchmarks

Project SizeFull IndexIncremental SyncMemory
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 VariantSizeInference Time (384-dim)
model_q4f16.onnx111 MB~5ms/item
model_int8.onnx137 MB~8ms/item
model_fp16.onnx274 MB~12ms/item
model.onnx547 MB~20ms/item

Recommendation: Use model_int8.onnx for best balance of size/speed/accuracy.

Embedding Generation

Project SizeEmbedding 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

NodesEdgesDB Size
1,0002,500~500KB
10,00025,000~5MB
100,000250,000~50MB

Vector Storage

NodesEmbedding Size (384-dim, fp32)
1,000~1.5MB
10,000~15MB
100,000~150MB

Runtime Memory

OperationPeak Memory
Indexing (10K files)~200MB
MCP server (idle)~30MB
Impact analysis~50MB
Semantic search~100MB (model loaded)

Best Practices Summary

  1. Always use compact output format for internal operations
  2. Use batch tools for multiple related queries (3+ items)
  3. Apply edge filters when relationship type is known
  4. Start with small limits and expand if needed
  5. Use incremental sync instead of full reindex
  6. Exclude test/fixture directories from indexing
  7. Use precomputed metrics for impact analysis
  8. Cache results in project memories for repeated contexts
  9. Use advanced search tools to find symbols in one query
  10. 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

LanguageStatustree-sitter grammarFramework Support
Bash✅ Fulltree-sitter-bash 0.25.1-
C✅ Fulltree-sitter-c 0.23-
C++✅ Fulltree-sitter-cpp 0.23-
C#✅ Fulltree-sitter-c-sharp 0.23.NET
Blazor✅ Fulltree-sitter-blazor 0.1.1 (custom)Blazor components
Dart✅ Fulltree-sitter-dart 0.0.4Flutter
Elixir✅ Fulltree-sitter-elixir 0.3.4Phoenix
Elm✅ Fulltree-sitter-elm 5.9.0-
Erlang✅ Fulltree-sitter-erlang 0.15.0OTP
Fortran✅ Fulltree-sitter-fortran 0.5.1-
Go✅ Fulltree-sitter-go 0.23-
Groovy✅ Fulltree-sitter-groovy 0.1.2Gradle
Haskell✅ Fulltree-sitter-haskell 0.23.1-
Java✅ Fulltree-sitter-java 0.23Spring
JavaScript✅ Fulltree-sitter-javascript 0.25.0Node.js
JSX✅ Fulltree-sitter-javascript 0.25.0React
Julia✅ Fulltree-sitter-julia 0.23.1-
Kotlin✅ Fulltree-sitter-kotlin-ng 1.1.0Android
Lua✅ Fulltree-sitter-lua 0.4.1-
Markdown✅ Fulltree-sitter-markdown-fork 0.7.3-
MATLAB✅ Fulltree-sitter-matlab 1.3.0-
Nix✅ Fulltree-sitter-nix 0.3.0-
Perl✅ Fulltree-sitter-perl 1.1.2-
PHP✅ Fulltree-sitter-php 0.24.2Laravel
PowerShell✅ Fulltree-sitter-powershell 0.25.10-
Python✅ Fulltree-sitter-python 0.23Django, Flask
R✅ Fulltree-sitter-r 1.2.0-
Ruby✅ Fulltree-sitter-ruby 0.23Rails
Rust✅ Fulltree-sitter-rust 0.24.0-
Scala✅ Fulltree-sitter-scala 0.24.0-
Swift✅ Fulltree-sitter-swift 0.7.1iOS/macOS
TOML✅ Fulltree-sitter-toml-ng 0.7.0Config files
TypeScript✅ Fulltree-sitter-typescript 0.23.1Node.js
TSX✅ Fulltree-sitter-typescript 0.23.1React
YAML✅ Fulltree-sitter-yaml 0.7.2Config files
Zig✅ Fulltree-sitter-zig 1.1.2-

Language Detection

Coraline detects languages by file extension:

Extension(s)Language
.rsRust
.tsTypeScript
.tsxTSX (TypeScript + JSX)
.jsJavaScript
.jsxJSX (JavaScript + JSX)
.pyPython
.goGo
.javaJava
.c, .hC
.cpp, .cc, .cxx, .hppC++
.csC#
.phpPHP
.rbRuby
.swiftSwift
.kt, .ktsKotlin
.sh, .bashBash
.ps1, .psm1PowerShell
.razorBlazor
.dartDart
.ex, .exsElixir
.elmElm
.erl, .hrlErlang
.f90, .f95, .f03Fortran
.groovy, .gradleGroovy
.hsHaskell
.jlJulia
.luaLua
.md, .markdownMarkdown
.mMATLAB
.nixNix
.pl, .pmPerl
.r, .RR
.scala, .scScala
.tomlTOML
.yaml, .ymlYAML
.zigZig

Node Types by Language

Different languages produce different node kinds:

Object-Oriented (Java, C#, Swift, Kotlin)

  • class
  • interface
  • method
  • property
  • field
  • enum
  • enum_member

Functional (Haskell, Scala, Elixir, Erlang)

  • function
  • module
  • trait (Scala)
  • type_alias
  • constant

Systems (Rust, C, C++, Zig)

  • struct
  • function
  • trait (Rust)
  • enum
  • type_alias
  • module (Rust)

Scripting (Python, Ruby, PHP, Bash)

  • function
  • class
  • method
  • variable
  • constant

Web Frontend (JavaScript, TypeScript, TSX, JSX)

  • function
  • class
  • method
  • component (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 (.razor files)
  • 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:

  1. Add the grammar to Cargo.toml:

    tree-sitter-newlang = "0.1.0"
    
  2. Register in extraction.rs:

    #![allow(unused)]
    fn main() {
    ".newlang" => tree_sitter_newlang::language(),
    }
  3. Add extraction patterns for node/edge types

  4. (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 constant nodes
  • 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 GroupRelative SpeedNotes
Rust, Go, CFastSimple, deterministic grammars
TypeScript, PythonMediumMore complex syntax rules
C++, ScalaSlowerHigh grammar complexity
Markdown, YAMLVery FastSimple 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:

  1. Check if a tree-sitter grammar exists at tree-sitter.github.io
  2. Open an issue at github.com/greysquirr3l/coraline/issues
  3. Include:
    • Language name and typical file extensions
    • Link to tree-sitter grammar
    • Example files for testing
    • (Optional) Framework-specific features needed

Next Steps

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

FilePurpose
.coraline/config.tomlUser-editable configuration (all settings)
.coraline/coraline.dbSQLite 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.json file, run coraline config --migrate to convert it to config.toml. The old file will be backed up as config.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 init auto-installs the hook. To manage the hook manually, use coraline 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 model on 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-run coraline 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

  1. Scan — Glob the project tree using include_patterns/exclude_patterns.
  2. Parse — For each file, spawn the appropriate tree-sitter grammar and walk the AST.
  3. Extract — Emit Node and Edge records from the AST visitor. Every Edge carries a confidence field (see Edges).
  4. Store — Upsert nodes and edges into SQLite. A file content hash prevents re-parsing unchanged files.
  5. Resolve — Walk unresolved reference edges, attempt name-based resolution in the DB; fall back to framework-specific resolvers for zero-candidate references. Resolved edges are stamped with their confidence.
  6. 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).
  7. Trace processes (Phase 5.1) — For each exported Function/Method with no incoming calls edge (an “entry point”), DFS forward through the call graph with cycle protection and a depth cap, writing edges.process_id. Every edge that participates in some process trace gets a process_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:

  1. Name-based: The resolution::resolve_unresolved function looks up reference names in the DB using ranked candidate scoring (file proximity, name similarity, kind match).

  2. Framework fallback: When no candidates score above threshold, framework_fallback is called. The registered FrameworkResolver implementations detect the active framework (by checking for Cargo.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 → .rs file mapping
  • ReactResolver — ./Foo relative imports, @/ path aliases, PascalCase component search
  • BlazorResolver — PascalCase component → .razor file, 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/call MCP requests by name
  • Automatically generates tools/list responses from registered metadata
  • Can be used outside MCP (CLI, library API, tests)

Database Schema

The SQLite database (.coraline/coraline.db) has these tables:

TablePurpose
nodesAll indexed symbols with full metadata, plus a nullable cluster_id (Phase 5.1, Louvain community id)
edgesDirected 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_ftsFTS5 virtual table for fast name search
vectorsOptional embeddings storage. embedding BLOB (v1) or vec0 vec0 virtual table (--features vec-ext)
schema_versionsAdditive-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 / initialized
  • tools/list — returns all 38 tool descriptors
  • tools/call — dispatches to ToolRegistry
  • ping

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.log with 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

ToolVersionNotes
Rust≥ 1.85MSRV — install via rustup
GitanyRequired for sync and hooks
SQLitebundledIncluded 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

LocationCountType
src/tools/mod.rs3Unit: ToolRegistry
src/tools/memory_tools.rs5Unit: MCP memory tools
src/memory.rs11Unit: memory CRUD
src/vectors.rs5Unit: cosine similarity
tests/extraction_test.rs4 (1 ignored)Integration: AST parsing
tests/graph_test.rs4Integration: graph traversal
tests/context_test.rs5Integration: 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/:

FixturePurpose
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

  1. Add the tree-sitter crate to crates/coraline/Cargo.toml.
  2. Add the language variant to Language enum in types.rs.
  3. Add the file extension mapping in extraction.rs (language_from_path).
  4. Add an extraction branch in extraction.rs (extract_nodes_from_ast).
  5. Add to the is_language_supported list in config.rs.
  6. Add at least one fixture file and a test case in tests/extraction_test.rs.

Adding a New MCP Tool

  1. Implement the Tool trait in the appropriate src/tools/*.rs file:

    #![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 { ... }
    }
    }
  2. Register in mcp.rs McpServer::register_tools():

    #![allow(unused)]
    fn main() {
    registry.register(Box::new(MyTool::new(root.clone())));
    }
  3. Add unit tests in the same file or src/tools/mod.rs.

  4. Document in docs/MCP_TOOLS.md.


Adding a Framework Resolver

  1. Create src/resolution/frameworks/my_lang.rs implementing FrameworkResolver:

    #![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> { ... }
    }
    }
  2. Add to default_resolvers() in src/resolution/frameworks/mod.rs.

  3. Add pub mod my_lang; in src/resolution/frameworks/mod.rs.


CI/CD

GitHub Actions workflows run on every push and pull request:

WorkflowTriggersWhat it does
ci.ymlpush, PRbuild, test, clippy, fmt, docs; multi-platform (Linux/macOS/Windows); MSRV check
release.ymlv* tagsCross-platform binary builds + GitHub release
security.ymldaily + dep changescargo-audit (vulnerabilities) + cargo-deny (licenses)
codeql.ymlweeklyCodeQL analysis
fuzz.ymldaily + fuzz/** or surface changescargo-fuzz nightly run against MCP + SQLite targets
cifuzz.ymlPR + surface changesClusterFuzzLite 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 code
  • cargo clippy --all-features -- -D warnings must pass before committing
  • cargo fmt for 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 bare println! 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.