Cocode — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Cocode (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
MCP server for semantic codebase search, powered by CocoIndex for real-time incremental indexing and intelligent ranking.
Search your codebase semantically without memorizing exact function names—find "HTTP error handler" and get all error handling logic, even if it doesn't contain those exact keywords.
Cocode leverages CocoIndex, a data transformation framework designed for AI applications. CocoIndex provides:
This combination enables fast, accurate semantic search that stays up-to-date as your code evolves.
pgvector (vector) extension (the server will also attempt to enable pgcrypto for UUIDs)curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shcargo and the Rust compilerInstall from PyPI using pip, uvx, or pipx:
# Using pip
pip install cocode-mcp
# Or using uvx (isolated environment, no global install)
uvx --from cocode-mcp cocode
# Or using pipx (isolated environment with global command)
pipx install cocode-mcp
# Verify installation
cocode --help#### Standard Installation
# Clone the repository
git clone https://github.com/hrayleung/Cocode.git
cd Cocode
# Install dependencies and build Rust extensions (requires Rust toolchain)
# This single command installs Python deps and builds the Rust extension in release mode
maturin develop --release
# Create .env file
cp .env.example .env
# Edit .env with your API keys#### NixOS / Nix Flakes
# Clone repository
git clone https://github.com/hrayleung/Cocode.git
cd Cocode
# Enter dev shell (includes Python 3.11, PostgreSQL 16, and dependencies)
nix develop
# Install dependencies and build Rust extensions (requires Rust toolchain)
maturin develop --release
# Create .env file (automatically copied by shellHook)
# Edit .env with your API keysThe Nix flake automatically:
.postgres/venv/.env.example to .env if it doesn't exist# PostgreSQL (requires pgvector; server also attempts to CREATE EXTENSION pgcrypto)
COCOINDEX_DATABASE_URL=postgresql://localhost:5432/cocode
# Embeddings (choose one)
OPENAI_API_KEY=sk-... # Required unless using Jina late chunking
JINA_API_KEY=jina_... # Can run without OpenAI if USE_LATE_CHUNKING=true
MISTRAL_API_KEY=... # Optional (requires OPENAI_API_KEY as fallback)
# Select provider: jina, mistral, or openai (default: jina)
EMBEDDING_PROVIDER=jina
USE_LATE_CHUNKING=true
# Optional: Cohere reranking
COHERE_API_KEY=...
ENABLE_RERANKER=true # enabled by default when COHERE_API_KEY is setCocode works with multiple MCP clients. Choose the setup that matches your workflow.
<details> <summary><b>Claude Desktop</b></summary>
Claude Desktop reads its configuration from claude_desktop_config.json:
Configuration File Locations:
~/Library/Application Support/Claude/claude_desktop_config.json%APPDATA%\Claude\claude_desktop_config.json~/.config/Claude/claude_desktop_config.jsonConfiguration Example:
{
"mcpServers": {
"cocode": {
"command": "cocode",
"args": [],
"env": {
"COCOINDEX_DATABASE_URL": "postgresql://localhost:5432/cocode",
"JINA_API_KEY": "jina_...",
"EMBEDDING_PROVIDER": "jina",
"USE_LATE_CHUNKING": "true",
"COHERE_API_KEY": "your_cohere_key_optional"
}
}
}
}Important Notes:
args if needed${VAR_NAME} environment variable substitution (use literal values instead). Other clients like VS Code and .mcp.json configs support ${VAR_NAME} or ${env:VAR} syntaxAlternative: Using uvx for isolation:
{
"mcpServers": {
"cocode": {
"command": "uvx",
"args": ["--from", "cocode-mcp", "cocode"],
"env": {
"COCOINDEX_DATABASE_URL": "postgresql://localhost:5432/cocode",
"JINA_API_KEY": "jina_..."
}
}
}
}Note: Before PyPI publication, use `"args": ["--from", "git+https://github.com/hrayleung/Cocode.git", "cocode"]` to install from source.
</details>
<details> <summary><b>Claude Code CLI</b></summary>
#### Option 1: Add via CLI (Recommended)
# Add to your user config (available across all projects)
claude mcp add --scope user cocode -- cocode
# Or add to current project only
claude mcp add --scope project cocode -- cocode
# With environment variables baked in
claude mcp add --scope user \
-e COCOINDEX_DATABASE_URL=postgresql://localhost:5432/cocode \
-e JINA_API_KEY="${JINA_API_KEY}" \
-e EMBEDDING_PROVIDER=jina \
-e USE_LATE_CHUNKING=true \
cocode -- cocode#### Option 2: Project Configuration
Create .mcp.json in your project root:
{
"mcpServers": {
"cocode": {
"command": "cocode",
"args": [],
"env": {
"COCOINDEX_DATABASE_URL": "postgresql://localhost:5432/cocode",
"JINA_API_KEY": "${JINA_API_KEY}",
"EMBEDDING_PROVIDER": "jina",
"USE_LATE_CHUNKING": "true"
}
}
}
}#### Option 3: Run Standalone
cocode
# or
python -m src.server#### Verify Installation
In Claude Code:
/mcp</details>
<details> <summary><b>VS Code (GitHub Copilot)</b></summary>
VS Code supports MCP servers through workspace or user settings.
Workspace Configuration (.vscode/settings.json):
{
"github.copilot.chat.mcp.servers": {
"cocode": {
"command": "cocode",
"args": [],
"env": {
"COCOINDEX_DATABASE_URL": "postgresql://localhost:5432/cocode",
"JINA_API_KEY": "${env:JINA_API_KEY}",
"EMBEDDING_PROVIDER": "jina",
"USE_LATE_CHUNKING": "true"
}
}
}
}User Configuration (global settings):
Cmd+Shift+P / Ctrl+Shift+P)github.copilot.chat.mcp.servers objectUsing Input Variables for Secrets:
{
"github.copilot.chat.mcp.servers": {
"cocode": {
"command": "cocode",
"args": [],
"env": {
"COCOINDEX_DATABASE_URL": "${input:databaseUrl}",
"JINA_API_KEY": "${input:jinaApiKey}"
}
}
},
"inputs": [
{
"id": "databaseUrl",
"type": "promptString",
"description": "PostgreSQL database URL"
},
{
"id": "jinaApiKey",
"type": "promptString",
"password": true,
"description": "Jina API Key"
}
]
}</details>
<details> <summary><b>Codex CLI</b></summary>
Codex stores MCP server configs in ~/.codex/config.toml.
#### Option 1: Add via CLI (Codex)
# Add the server (stdio transport)
codex mcp add cocode \
--env COCOINDEX_DATABASE_URL=postgresql://localhost:5432/cocode \
--env JINA_API_KEY="${JINA_API_KEY}" \
--env EMBEDDING_PROVIDER=jina \
--env USE_LATE_CHUNKING=true \
-- cocode
# Verify
codex mcp list
codex mcp get cocode#### Option 2: Edit ~/.codex/config.toml
[mcp_servers.cocode]
command = "cocode"
args = []
[mcp_servers.cocode.env]
COCOINDEX_DATABASE_URL = "postgresql://localhost:5432/cocode"
JINA_API_KEY = "jina_..."
EMBEDDING_PROVIDER = "jina"
USE_LATE_CHUNKING = "true"</details>
<details> <summary><b>Warp Terminal</b></summary>
Warp supports MCP servers through its settings UI.
Setup Steps:
Settings > MCP Servers, orWarp Drive > Personal > MCP Servers, orSettings > AI > Manage MCP servers+ Add buttonCLI Server Configuration:
{
"command": "cocode",
"args": [],
"env": {
"COCOINDEX_DATABASE_URL": "postgresql://localhost:5432/cocode",
"JINA_API_KEY": "jina_...",
"EMBEDDING_PROVIDER": "jina",
"USE_LATE_CHUNKING": "true"
},
"working_directory": "/path/to/your/project"
}Multiple Servers: Paste JSON under the mcpServers key:
{
"mcpServers": {
"cocode": {
"command": "cocode",
"args": [],
"env": {
"COCOINDEX_DATABASE_URL": "postgresql://localhost:5432/cocode",
"JINA_API_KEY": "jina_..."
}
}
}
}</details>
<details> <summary><b>Troubleshooting MCP Setup</b></summary>
#### Server Not Appearing
args if needed# Check if cocode is in PATH
which cocode
# Test server directly
cocode#### Connection Failures
# Test database connection
psql postgresql://localhost:5432/cocode
# Verify pgvector extension
psql -d cocode -c "SELECT * FROM pg_extension WHERE extname = 'vector';"EMBEDDING_PROVIDER matches the key you providedUSE_LATE_CHUNKING=true must be set#### Common Errors
"Could not connect to server":
"Database connection failed":
pg_isreadypostgresql://user:pass@host:port/dbnamecreatedb cocode"Missing API key":
JINA_API_KEY and USE_LATE_CHUNKING=trueMISTRAL_API_KEY and OPENAI_API_KEY (fallback)Silent Failures:
Performance Issues:
</details>
| Tool | Description |
|---|---|
codebase_retrieval_full(query, path, top_k, max_symbols, max_symbols_per_file, max_code_chars, include_dependencies) | Returns key files + import dependencies + full implementations of relevant symbols (functions/classes/methods). |
clear_index(path) | Delete index to force re-indexing on next search. |
codebase_retrieval_full returns an object:
files: ranked key files (with category + line hints)dependencies: import edges between returned filessymbols: full code implementations for the most relevant functions/classes/methods"Where is user authentication implemented?"
"How does the payment processing work?"
"Find all database connection code"When you search a codebase for the first time, Cocode:
.py, .ts, .js, .go, .rs, etc.)Subsequent searches reuse the index, only re-indexing files that changed (via mtime comparison).
When you query the codebase:
ts_rank_cd scoringOn subsequent searches, Cocode automatically:
ON CONFLICT constraintsThis ensures your search results always reflect the current state of the codebase with minimal latency.
config/
└── settings.py # Environment-driven configuration
src/
├── server.py # FastMCP entry point (2 tools)
│
├── indexer/ # CocoIndex Integration
│ ├── service.py # IndexerService singleton - orchestrates indexing
│ ├── flow.py # CocoIndex flows for chunking/embedding
│ ├── repo_manager.py # Repository metadata and status tracking
│ ├── symbol_indexing.py # AST-based function/class extraction
│ └── call_graph_indexing.py # (Experimental) call edge extraction
│
├── retrieval/ # Hybrid Search Pipeline
│ ├── service.py # SearchService singleton - orchestrates search
│ ├── hybrid.py # RRF fusion + parallel execution
│ ├── vector_search.py # pgvector cosine similarity
│ ├── bm25_search.py # PostgreSQL FTS with ts_rank_cd
│ ├── symbol_search.py # Symbol-level search (vector + BM25)
│ ├── file_categorizer.py # Category-based score boosting
│ ├── centrality.py # PageRank computation and boosting
│ ├── graph_expansion.py # Multi-hop import traversal (BFS)
│ ├── graph_cache.py # Import graph caching (30-50% faster)
│ ├── fts_setup.py # Lazy FTS index creation
│ └── reranker.py # Cohere rerank-v3.5 integration
│
├── parser/ # AST-Based Code Analysis
│ ├── ast_parser.py # Tree-sitter import parsing (8 languages)
│ ├── symbol_extractor.py # Symbol metadata extraction (Python, Go)
│ └── call_extractor.py # Function call extraction (Python, Go)
│
├── embeddings/ # Multi-Provider Support
│ ├── backend.py # Provider selection + API key validation
│ ├── provider.py # Base provider interface (singleton pattern)
│ ├── jina.py # Jina late chunking implementation
│ ├── mistral.py # Codestral Embed implementation
│ └── openai.py # OpenAI embeddings implementation
│
└── storage/ # Database Layer
├── schema.py # PostgreSQL table definitions
└── postgres.py # Connection pooling + query helpersQuery → Embedding
↓
[Parallel Search - ThreadPoolExecutor]
├─ Vector search (pgvector cosine)
├─ BM25 search (PostgreSQL FTS)
└─ Symbol search (functions/classes)
↓
Reciprocal Rank Fusion (weights: vector=0.6, bm25=0.4, symbol=0.7)
↓
Centrality Boost (PageRank)
↓
Category Boost (impl=1.0, docs=0.7, config=0.6, tests=0.3)
↓
Cohere Rerank (optional)
↓
Aggregate by File (top 3 chunks per file)
↓
Graph Expansion (related files via imports)| Variable | Description |
|---|---|
EMBEDDING_PROVIDER | jina, mistral, or openai (default: jina) |
JINA_API_KEY | Jina late chunking - preserves cross-chunk context |
USE_LATE_CHUNKING | Must be true for Jina selection (default: true) |
JINA_MODEL | Jina model name (default: jina-embeddings-v3) |
MISTRAL_API_KEY | Codestral Embed - optimized for code |
MISTRAL_EMBED_MODEL | Mistral model name (default: codestral-embed) |
OPENAI_API_KEY | OpenAI embeddings (default fallback) |
EMBEDDING_MODEL | OpenAI embedding model (default: text-embedding-3-large) |
EMBEDDING_DIMENSIONS | Embedding dimensions (default: 1024; changing requires re-index) |
| Variable | Default | Description |
|---|---|---|
VECTOR_WEIGHT | 0.6 | RRF weight for vector search |
BM25_WEIGHT | 0.4 | RRF weight for BM25 |
SYMBOL_WEIGHT | 0.7 | RRF weight for symbol search |
CENTRALITY_WEIGHT | 1.0 | PageRank boost (0=disabled) |
MAX_GRAPH_HOPS | 3 | Import traversal depth |
MAX_GRAPH_RESULTS | 30 | Max related files |
| Variable | Default | Description |
|---|---|---|
CHUNK_SIZE | 2000 | Characters per chunk |
CHUNK_OVERLAP | 400 | Overlap between chunks |
ENABLE_SYMBOL_INDEXING | true | Index functions/classes |
repos - Repository metadata
id, name, path, status (pending/indexing/ready/failed)created_at, last_indexedfile_count, chunk_counterror_message{repo}_centrality - PageRank scores (created on demand)
filename (PK), score (float)codeindex_{repo}__{repo}_chunks - CocoIndex-managed chunk store
filename, location (char range), content, embedding (vector)embedding for vector searchcontent_tsv (tsvector) + GIN index added lazily on first searchcodeindex_{repo}__cocoindex_tracking - CocoIndex internal state
{schema}.symbols - Functions/classes/methods
symbol_name, symbol_type (function/class/method), signature, docstringfilename, line_start, line_end (1-indexed, inclusive)parent_symbol, visibility (public/private/internal), category (implementation/test/api/config)embedding (vector) + HNSW, content_tsv (tsvector) + GIN(filename, symbol_name, line_start) for UPSERT supportcreated_at, updated_at{schema}.edges - Call graph relationships (experimental)
source_symbol_id, target_symbol_id, edge_type ('calls', 'implements', etc.)source_file, source_line, target_file, target_line1.0 (exact match), 0.7 (partial), 0.5 (unresolved/external){schema}.graph_cache - Import graph cache
filename (PK), imports (JSONB), imported_by (JSONB)symbol_count, edge_countAll table names derived from repository folder name + path hash (to handle duplicates).
Import Parsing + Graph Expansion: Python, Go, Rust, C, C++, JavaScript, TypeScript, TSX
Symbol Extraction: Python, Go
All these extensions are chunked and embedded for semantic + keyword search:
.py .rs .ts .tsx .js .jsx .go .java .cpp .c .h .hpp .rb .php .swift .kt .scala .md .mdx
Files not matching these extensions are ignored during indexing.
# All tests
pytest
# Verbose output with details
pytest -v
# Single test file
pytest tests/test_file_categorizer.py -v
# Single test method
pytest tests/test_file_categorizer.py::TestFileCategorizerDetection::test_python_test_files -v
# Pattern matching
pytest -k "test_python"
# With coverage
pytest --cov=src --cov-report=htmlIndexerService and SearchService use singleton pattern to prevent duplicate connectionsMIT
Questions or issues? Open an issue on GitHub.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.