{"id":44989504,"url":"https://github.com/lexandro/codeindex-mcp","last_synced_at":"2026-06-12T09:00:15.919Z","repository":{"id":338517851,"uuid":"1158157995","full_name":"lexandro/codeindex-mcp","owner":"lexandro","description":"In-memory MCP server for source code indexing. Replaces grep/find with fast Bleve-powered full-text search, glob file lookup, and auto-updating file   watcher. Built for Claude Code and any MCP-compatible client. Single static Go binary, zero external dependencies at runtime.","archived":false,"fork":false,"pushed_at":"2026-06-12T07:04:48.000Z","size":203,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-12T08:22:08.535Z","etag":null,"topics":["ai-agents","bleve","claude-code","code-search","developer-tools","full-text-search","golang","mcp","mcp-server"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lexandro.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-14T22:18:03.000Z","updated_at":"2026-06-12T07:05:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/lexandro/codeindex-mcp","commit_stats":null,"previous_names":["lexandro/codeindex-mcp"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/lexandro/codeindex-mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lexandro%2Fcodeindex-mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lexandro%2Fcodeindex-mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lexandro%2Fcodeindex-mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lexandro%2Fcodeindex-mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lexandro","download_url":"https://codeload.github.com/lexandro/codeindex-mcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lexandro%2Fcodeindex-mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34236552,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","bleve","claude-code","code-search","developer-tools","full-text-search","golang","mcp","mcp-server"],"created_at":"2026-02-18T21:03:25.287Z","updated_at":"2026-06-12T09:00:15.832Z","avatar_url":"https://github.com/lexandro.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# codeindex-mcp\n\n[![CI](https://github.com/lexandro/codeindex-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/lexandro/codeindex-mcp/actions/workflows/ci.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/lexandro/codeindex-mcp)](https://goreportcard.com/report/github.com/lexandro/codeindex-mcp)\n[![Go Reference](https://pkg.go.dev/badge/github.com/lexandro/codeindex-mcp.svg)](https://pkg.go.dev/github.com/lexandro/codeindex-mcp)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![MCP](https://img.shields.io/badge/MCP-compatible-blue)](https://modelcontextprotocol.io/)\n[![Claude Code](https://img.shields.io/badge/Claude_Code-Extension-blueviolet)](https://docs.anthropic.com/en/docs/claude-code)\n\nIn-memory [MCP](https://modelcontextprotocol.io/) server for source code indexing. A fast, indexed replacement for `grep` and `find`, designed for [Claude Code](https://docs.anthropic.com/en/docs/claude-code) and any MCP-compatible client.\n\n## Why?\n\n- **Orders of magnitude faster** than `grep`/`find` on large codebases — all file contents are served from an in-memory index\n- **Exact grep semantics** — literal substring, exact phrase, and RE2 regex queries with full recall (`mutex` finds `sync.RWMutex`); no tokenizer false negatives\n- **Token-efficient output** — merged context hunks, per-file match caps, and `files`/`count` output modes designed for AI agents\n- **Glob-based file search** with `**` doublestar support\n- **Auto-updating** — a background file watcher plus periodic sync verification keep the index consistent with disk\n- **Configurable filtering** — respects `.gitignore` and `.claudeignore` at every directory level, plus custom exclude patterns\n- **Single binary** — no runtime dependencies; lightweight build has zero CGo, full AST build includes tree-sitter grammars\n\n## Quick start\n\n```bash\n# Register for a project (creates .mcp.json)\n./codeindex-mcp register project /path/to/your/project\n\n# Or register globally for all projects (updates ~/.claude.json)\n./codeindex-mcp register user\n```\n\nThat's it — Claude Code will automatically discover and use the indexed search tools.\n\n## Installation\n\n### Prerequisites\n\n- [Go 1.25+](https://go.dev/dl/)\n- **GCC C compiler** — only required for the full AST build (`make build-ast`); the lightweight build has no CGo dependency\n\nThe setup scripts handle everything automatically.\n\n### Build from source\n\n```bash\ngit clone https://github.com/lexandro/codeindex-mcp.git\ncd codeindex-mcp\n```\n\n**First-time setup** (installs Go, GCC, make if missing):\n\n```bash\n# Windows\npowershell -ExecutionPolicy Bypass -File scripts/setup_build.ps1\n\n# Linux / macOS\nbash scripts/setup_build.sh\n```\n\nThe script detects your package manager (apt, dnf, pacman, brew, winget), installs any missing dependencies, and prints the exact build command at the end.\n\n**Two build variants:**\n\n| | Lightweight | Full AST |\n|---|---|---|\n| Binary size | ~18 MB | ~31 MB |\n| CGo / GCC | not required | required |\n| Go AST indexing | yes | yes |\n| TypeScript / Python / JS AST | no | yes |\n| Build command | `make build` | `make build-ast` |\n\n```bash\n# Lightweight — no GCC needed, works everywhere\nmake build\nmake test\n\n# Full AST — requires GCC (run setup_build first)\nmake build-ast\nmake test-ast\n```\n\nWithout `make`:\n```bash\ngo build -o codeindex-mcp .                               # lightweight\nCGO_ENABLED=1 go build -tags ast -o codeindex-mcp .      # full AST\n```\n\n### Register in Claude Code\n\nAfter building, register the server so Claude Code can find it:\n\n```bash\n# Project-specific (writes .mcp.json in the target directory)\n./codeindex-mcp register project /path/to/your/project\n\n# Global (writes ~/.claude.json — available in all projects)\n./codeindex-mcp register user\n\n# With extra server flags\n./codeindex-mcp register project . -- --max-file-size 5242880 --exclude \"vendor/\"\n```\n\nThe `register` command auto-detects the binary path and creates the correct config entry, including the `cmd /C` wrapper on Windows.\n\n### Run tests\n\n```bash\nmake test        # lightweight (no CGo)\nmake test-ast    # full AST build (requires GCC)\n\n# manually:\ngo test ./...                              # lightweight\nCGO_ENABLED=1 go test -tags ast ./...     # full AST\n```\n\n## Usage\n\n### Standalone (for testing)\n\n```bash\n./codeindex-mcp --root /path/to/project\n```\n\nThe server communicates over stdio (stdin/stdout) using the MCP protocol, so it is not interactive on its own — use it from an MCP client.\n\n### Claude Code integration\n\nThe easiest way to register the server is the built-in `register` subcommand:\n\n```bash\n# Register for a specific project (writes .mcp.json in the project directory)\n./codeindex-mcp register project /path/to/project\n\n# Register globally for all projects (writes ~/.claude.json)\n./codeindex-mcp register user\n\n# Forward extra flags to the server\n./codeindex-mcp register project . -- --max-file-size 5242880 --exclude \"vendor/\"\n```\n\nAlternatively, add to your Claude Code MCP settings manually. For project-specific configuration, create `.mcp.json` in the project root:\n\n```json\n{\n  \"mcpServers\": {\n    \"codeindex\": {\n      \"command\": \"/path/to/codeindex-mcp\",\n      \"args\": [\"--root\", \".\"]\n    }\n  }\n}\n```\n\nFor global configuration, add to `~/.claude.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"codeindex\": {\n      \"command\": \"/path/to/codeindex-mcp\",\n      \"args\": [\"--root\", \"/path/to/project\"]\n    }\n  }\n}\n```\n\nClaude Code will then automatically use `codeindex_search`, `codeindex_files`, `codeindex_read`, `codeindex_status`, and `codeindex_reindex` tools.\n\n## CLI flags\n\n| Flag | Default | Description |\n|------|---------|-------------|\n| `--root DIR` | current directory | Project root directory to index |\n| `--exclude PATTERN` | _(none)_ | Extra ignore pattern, repeatable (e.g. `--exclude \"*.generated.go\" --exclude \"vendor/\"`) |\n| `--force-include PATTERN` | _(none)_ | Force-include pattern that overrides all excludes, repeatable (e.g. `--force-include \"*.log\"`) |\n| `--max-file-size N` | `1048576` (1 MB) | Maximum file size in bytes; larger files are skipped |\n| `--max-results N` | `50` | Default maximum number of search results |\n| `--log-enabled` | `false` | Enable logging (no log file is created when disabled) |\n| `--log-level LEVEL` | `info` | Log level: `debug`, `info`, `warn`, `error` |\n| `--log-file PATH` | `\u003croot\u003e/codeindex-mcp.log` | Log file path |\n| `--sync-interval N` | `300` | Periodic index sync verification interval in seconds (0 = disabled) |\n| `--ast` | `false` | Enable AST symbol indexing (adds 5 `codeindex_ast_*` tools) |\n| `--ast-languages LIST` | `go,typescript,python,javascript` | Languages to AST-index. In the lightweight build only `go` is available; `typescript`, `python`, `javascript` require `-tags ast` |\n| `--ast-max-file-size-kb N` | `500` | Maximum file size in KB to AST-index |\n\n### Examples\n\n```bash\n# Index the current directory\n./codeindex-mcp\n\n# Specify project root with extra exclusions\n./codeindex-mcp --root ~/myproject \\\n  --exclude \"*.generated.go\" \\\n  --exclude \"testdata/\"\n\n# Force-include log files (overrides the default *.log exclusion)\n./codeindex-mcp --root . --force-include \"*.log\"\n\n# Multiple force-include patterns (additive)\n./codeindex-mcp --root . --force-include \"*.log\" --force-include \"vendor/*.go\"\n\n# Combine exclude and force-include\n./codeindex-mcp --root ~/myproject \\\n  --exclude \"*.generated.go\" \\\n  --force-include \"*.log\"\n\n# Enable debug logging to a specific file\n./codeindex-mcp --root . --log-enabled --log-level debug --log-file /tmp/codeindex.log\n\n# Disable periodic sync verification (enabled every 300s by default)\n./codeindex-mcp --root . --sync-interval 0\n\n# Allow larger files (5 MB)\n./codeindex-mcp --root . --max-file-size 5242880\n\n# Enable AST symbol indexing\n./codeindex-mcp --root . --ast\n\n# AST indexing for Go only (faster, smaller memory footprint)\n./codeindex-mcp --root . --ast --ast-languages go\n```\n\n## MCP Tools\n\nThe server registers 5 tools:\n\n### 1. `codeindex_search` — Content search\n\nGrep-equivalent search across all indexed file contents, served from memory.\n\n**Parameters:**\n\n| Name | Type | Required | Description |\n|------|------|----------|-------------|\n| `query` | string | yes | Search query (see formats below) |\n| `filePath` | string | no | Exact relative path to search in a single file (overrides `fileGlob`) |\n| `fileGlob` | string | no | Glob pattern to filter files (e.g. `**/*.go`) |\n| `maxResults` | int | no | Maximum number of file results (default: 50) |\n| `contextLines` | int | no | Context lines before/after each match (default: 2, `0` = matching lines only) |\n| `maxMatchesPerFile` | int | no | Maximum matches rendered per file (default: 10); the real total is still reported |\n| `outputMode` | string | no | `content` (default) = hunks with line numbers; `files` = paths only; `count` = paths with match counts |\n| `caseSensitive` | bool | no | Case-sensitive matching for plain text and regex queries (default: false) |\n\n**Query formats:**\n\n| Format | Example | Behavior |\n|--------|---------|----------|\n| Plain text | `handleRequest` | Literal substring match, case-insensitive — full recall, `mutex` finds `sync.RWMutex` |\n| `\"quoted\"` | `\"func main\"` | Exact literal match, case-sensitive |\n| `/regex/` | `/func\\s+\\w+Handler/` | RE2 regular expression, matched per line, case-insensitive by default |\n\n**Example output** (`content` mode — `N:` marks a match, `N-` marks context, `--` separates hunks):\n\n```\n3 matches in 2 files:\nmain.go\n  4- import \"fmt\"\n  5-\n  6: func main() {\n  7-     fmt.Println(\"hello world\")\n  --\n  21- // entry helper\n  22: func mainHelper() {\n  23-     setup()\n  ... +4 more matches\n\nserver/server.go\n  13-\n  14: func main() {\n  15-     startServer()\n```\n\n`files` mode returns one path per line; `count` mode returns `path: matchCount` per line — both save tokens when you only need locations.\n\n### 2. `codeindex_files` — File search\n\nGlob-based file search across the index.\n\n**Parameters:**\n\n| Name | Type | Required | Description |\n|------|------|----------|-------------|\n| `pattern` | string | yes | Glob pattern (e.g. `**/*.ts`, `src/**/*.go`) |\n| `nameOnly` | bool | no | If `true`, return only file paths without metadata |\n| `maxResults` | int | no | Maximum number of results (default: 50) |\n\n**Example output:**\n\n```\nsrc/main.go (Go, 2.1 KB, 85L)\nsrc/utils/helper.go (Go, 1.3 KB, 42L)\nsrc/server/handler.go (Go, 4.7 KB, 156L)\nsrc/config/config.go (Go, 892 B, 31L)\n```\n\n### 3. `codeindex_read` — Read file from index\n\nRead a file's contents directly from the in-memory index. Zero disk I/O — faster than the built-in Read tool.\n\n**Parameters:**\n\n| Name | Type | Required | Description |\n|------|------|----------|-------------|\n| `filePath` | string | yes | Relative file path to read (e.g. `src/main.go`) |\n\n**Example output:**\n\n```\n1: package main\n2:\n3: import \"fmt\"\n4:\n5: func main() {\n6:     fmt.Println(\"hello\")\n7: }\n```\n\n### 4. `codeindex_status` — Index status\n\nDisplay current index statistics.\n\n**Parameters:** none\n\n**Example output:**\n\n```\nroot: /home/user/myproject\nversion: 0.6.0\nuptime: 45s\nfiles: 1234 (8.5 MB)\nmemory: 24.7 MB\nwatcher: 87 dirs\nsync: every 300s\nlanguages: TypeScript:456, Go:312, JavaScript:189, Python:98\n```\n\n### 5. `codeindex_reindex` — Force reindex\n\nClear the index and rebuild from scratch. Also reloads `.gitignore` and `.claudeignore` rules.\n\n**Parameters:** none\n\n**Example output:**\n\n```\nreindexed: 1234 files (8.5 MB) in 1.234s\n```\n\n## AST Tools (optional, `--ast` flag)\n\nWhen started with `--ast`, the server registers 5 additional tools for structural code navigation.\n\n| Build | Languages | How to build |\n|-------|-----------|-------------|\n| Lightweight (`make build`) | Go only — via `go/parser`, no CGo | `go build .` |\n| Full AST (`make build-ast`) | Go + TypeScript + Python + JavaScript | `go build -tags ast .` |\n\nBoth builds expose the same 5 tools — the difference is which languages get indexed.\n\n### 1. `codeindex_ast_search_symbols` — Search symbols by name\n\n**Parameters:**\n\n| Name | Type | Required | Description |\n|------|------|----------|-------------|\n| `query` | string | yes | Symbol name (case-insensitive substring match) |\n| `kind` | string | no | Filter by kind: `class`, `interface`, `enum`, `function`, `method`, `field`, `variable`, `constant`, `type_alias` |\n| `language` | string | no | Filter by language: `go`, `typescript`, `python`, `javascript` |\n| `limit` | int | no | Max results (default: 20) |\n\n**Example output:**\n```\n3 symbols matching \"handler\":\nfunction  HandleRequest        server/handler.go:12  go\nmethod    HandleError          server/handler.go:45  go\nfunction  handleWatcherEvents  indexing.go:98        go\n```\n\n### 2. `codeindex_ast_file_symbols` — List symbols in a file\n\n**Parameters:**\n\n| Name | Type | Required | Description |\n|------|------|----------|-------------|\n| `file` | string | yes | Relative file path |\n\n**Example output:**\n```\n6 symbols in server/handler.go:\nclass     Server          line 8\nmethod    Start           line 15   parent: Server\nmethod    Stop            line 28   parent: Server\nfunction  HandleRequest   line 45\nfunction  handleError     line 67\nvariable  defaultTimeout  line 5\n```\n\n### 3. `codeindex_ast_find_usages` — Find files referencing a symbol\n\nSearches for the symbol name as a text pattern across all indexed files. Returns files that likely reference it (not a full type-aware analysis).\n\n**Parameters:**\n\n| Name | Type | Required | Description |\n|------|------|----------|-------------|\n| `symbol` | string | yes | Symbol name to search for |\n| `kind` | string | no | Optional kind hint (informational only) |\n\n**Example output:**\n```\n5 files reference \"HandleRequest\":\nserver/handler.go\nserver/handler_test.go\nmain.go\ntools/proxy.go\ndocs/api.md\n```\n\n### 4. `codeindex_ast_get_imports` — List imports for a file\n\n**Parameters:**\n\n| Name | Type | Required | Description |\n|------|------|----------|-------------|\n| `file` | string | yes | Relative file path |\n\n**Example output:**\n```\n4 imports in server/handler.go:\nfmt\nnet/http\ngithub.com/lexandro/codeindex-mcp/index\nlog/slog\n```\n\n### 5. `codeindex_ast_stats` — AST index statistics\n\n**Parameters:** none\n\n**Example output:**\n```\nAST index stats:\nfiles:    142\nsymbols:  1847\nby kind:  function:623 method:441 class:187 variable:312 constant:98 ...\nby lang:  go:1203 typescript:489 python:155\n```\n\n## Ignore system\n\nThe server uses a multi-layered filtering system to determine which files to index:\n\n### 1. Built-in default patterns\n\nAutomatically skipped without any configuration:\n\n| Category | Patterns |\n|----------|----------|\n| Version control | `.git`, `.svn`, `.hg` |\n| Dependencies | `node_modules`, `vendor`, `bower_components`, `.yarn` |\n| Build output | `dist`, `build`, `out`, `target`, `bin`, `obj` |\n| IDE files | `.idea`, `.vscode`, `.vs` |\n| Binaries | `*.exe`, `*.dll`, `*.so`, `*.dylib`, `*.class`, `*.jar` |\n| Images | `*.png`, `*.jpg`, `*.gif`, `*.webp`, `*.ico` |\n| Fonts | `*.woff`, `*.woff2`, `*.ttf`, `*.eot` |\n| Media | `*.mp3`, `*.mp4`, `*.avi`, `*.mov` |\n| Documents | `*.pdf`, `*.doc`, `*.xlsx`, `*.pptx` |\n| Lock files | `package-lock.json`, `yarn.lock`, `go.sum`, `Cargo.lock` |\n| Archives | `*.zip`, `*.tar`, `*.tar.gz`, `*.rar`, `*.7z` |\n| Minified | `*.min.js`, `*.min.css` |\n| Source maps | `*.map` |\n| Cache | `.cache`, `.next`, `.nuxt`, `.parcel-cache` |\n| Logs | `*.log` |\n| Database | `*.sqlite`, `*.sqlite3`, `*.db` |\n| Env / secrets | `.env`, `.env.*`, `*.env` (use `--force-include` to index intentionally) |\n\n### 2. `.gitignore` support\n\nFully respects `.gitignore` patterns **at every directory level** (nested `.gitignore` files included), with globs, negation (`!important.log`), and git's precedence rule: the ignore file closest to a path wins.\n\n### 3. `.claudeignore` support\n\n`.claudeignore` files use the same syntax and the same hierarchical matching as `.gitignore`. Use them to exclude files from the index that you want in git but are not relevant for AI code search.\n\nExample `.claudeignore`:\n```\n# Generated files\n*.generated.go\n*.pb.go\n\n# Large test fixtures\ntestdata/large/\n\n# Archived migrations\nmigrations/archive/\n```\n\n### 4. CLI `--exclude` patterns\n\nRuntime exclusions via the `--exclude` flag:\n\n```bash\n./codeindex-mcp --exclude \"*.generated.go\" --exclude \"vendor/\"\n```\n\n### 5. CLI `--force-include` patterns\n\nForce-include patterns override **all** exclude rules (built-in defaults, `.gitignore`, `.claudeignore`, and `--exclude`). Multiple `--force-include` flags are additive. Binary detection and file size limits still apply.\n\n```bash\n# Index *.log files even though they are excluded by default\n./codeindex-mcp --force-include \"*.log\"\n\n# Force-include vendor Go files while still excluding the rest of vendor/\n./codeindex-mcp --force-include \"vendor/*.go\"\n```\n\nWhen force-include patterns are active, directories that might contain matching files are not pruned during traversal. The `.git` directory is always skipped regardless of force-include patterns.\n\n### 6. Binary file detection\n\nScans the first 512 bytes of each file for null bytes. If found, the file is treated as binary and skipped. This works independently of `.gitignore`.\n\n### 7. File size limit\n\nConfigurable via `--max-file-size` (default: 1 MB). Files larger than this are skipped.\n\n### Priority\n\nFilters are applied in order:\n1. **`--force-include` patterns** (highest priority — if matched, the file is included regardless of rules 2–5)\n2. Built-in default patterns\n3. `.gitignore` rules\n4. `.claudeignore` rules\n5. CLI `--exclude` patterns\n6. Binary detection (always applies, even for force-included files)\n7. File size limit (always applies, even for force-included files)\n\nIf a force-include pattern matches, the file bypasses all exclude rules (2–5). Binary detection and file size limits are safety checks that always apply.\n\n## Architecture\n\n```\nMCP Client (stdio) \u003c──\u003e MCP Server \u003c──\u003e Index Engine\n                                            │\n                                    ┌───────┼────────┐\n                                    │       │        │\n                                ContentMap FileMap  Watcher\n                               (line scan) (path)  (fsnotify)\n```\n\n### Dual index design\n\n| Index | Technology | Purpose |\n|-------|-----------|---------|\n| **Content Index** | Go `map` of pre-split lines | Exact grep-style content search (substring / phrase / RE2 regex), scanned entirely in memory |\n| **File Path Index** | Go `map` + sorted slice | File name/path search with glob patterns |\n\nThere is no tokenizer or inverted index in the search path: queries are compiled to a single RE2 matcher and scanned over the in-memory lines. This guarantees grep-identical results (no recall gaps for substrings inside identifiers) while staying far faster than disk-based grep.\n\n### File watcher\n\n- Uses **fsnotify** (on Windows: `ReadDirectoryChangesW` API)\n- Recursive: watches all non-ignored subdirectories at startup\n- **100ms debounce window**: editors generate multiple events on save — these are collapsed into one\n- Newly created directory trees are watched **recursively** and files already inside them are indexed (covers copy / unzip / `git checkout` bursts)\n- Automatically reloads ignore rules when any `.gitignore` or `.claudeignore` changes, then re-syncs the index against the new rules\n- A periodic sync verification (default: every 300s) heals any missed events by diffing the index against disk\n\n### Startup sequence\n\n1. Parse CLI flags\n2. Create ignore matcher (built-in + hierarchical .gitignore/.claudeignore + CLI patterns)\n3. Initialize in-memory content index and file path index\n4. Parallel indexing with 8 worker goroutines\n5. Start file watcher and periodic sync verification\n6. Start MCP server on stdio transport\n\n## Project structure\n\n```\ncodeindex-mcp/\n├── main.go                  # Entry point, CLI flags, component wiring\n├── indexing.go              # Directory walking, parallel indexing, watcher events\n├── sync.go                  # Periodic background index sync verification\n├── server/\n│   └── server.go            # MCP server setup, tool registration\n├── index/\n│   ├── content.go           # In-memory content index (CRUD operations)\n│   ├── content_search.go    # Line-scan search logic, query parsing, hunk building\n│   ├── content_test.go\n│   ├── files.go             # File path index (glob search) + IndexedFile type\n│   └── files_test.go\n├── watcher/\n│   ├── watcher.go           # Recursive fsnotify wrapper\n│   └── debouncer.go         # 100ms event collapsing\n├── ignore/\n│   ├── ignore.go            # .gitignore + .claudeignore + custom patterns\n│   ├── ignore_test.go\n│   └── defaults.go          # Built-in ignore patterns\n├── register/\n│   ├── register.go          # Auto-register subcommand for Claude Code config\n│   └── register_test.go\n├── tools/\n│   ├── search.go            # codeindex_search handler\n│   ├── files.go             # codeindex_files handler\n│   ├── read.go              # codeindex_read handler\n│   ├── status.go            # codeindex_status handler\n│   ├── reindex.go           # codeindex_reindex handler\n│   └── format.go            # Output formatting\n├── ast/                     # AST symbol indexing (--ast flag)\n│   ├── symbols.go           # Symbol, SymbolKind, SymbolTable\n│   ├── extractor.go         # LanguageExtractor interface\n│   ├── extractor_go.go      # Go extractor — go/parser, always compiled\n│   ├── extractor_typescript.go  # TypeScript extractor — tree-sitter, build tag: ast\n│   ├── extractor_python.go  # Python extractor — tree-sitter, build tag: ast\n│   ├── extractor_javascript.go  # JavaScript extractor — tree-sitter, build tag: ast\n│   ├── languages_noast.go   # Extractor registry, Go only (build tag: !ast)\n│   ├── languages_ast.go     # Extractor registry, all 4 languages (build tag: ast)\n│   ├── module.go            # Module wiring: OnFileChanged/Removed, RegisterTools\n│   ├── tools.go             # 5 codeindex_ast_* MCP tool handlers\n│   └── symbols_test.go\n├── scripts/\n│   ├── setup_build.sh       # Linux/macOS: full build environment setup\n│   ├── setup_build.ps1      # Windows: full build environment setup\n│   └── setup-gcc.ps1        # Windows: GCC-only install helper\n├── Makefile                 # build / build-ast / test / test-ast / run / run-ast\n└── language/\n    ├── detect.go            # Extension → language mapping (70+)\n    ├── detect_test.go\n    ├── binary.go            # Binary file detection\n    └── binary_test.go\n```\n\n## Dependencies\n\n| Library | Version | Purpose |\n|---------|---------|---------|\n| [modelcontextprotocol/go-sdk](https://github.com/modelcontextprotocol/go-sdk) | v1.3.0 | MCP server (stdio transport) |\n| [fsnotify/fsnotify](https://github.com/fsnotify/fsnotify) | v1.9.0 | File system watching |\n| [bmatcuk/doublestar/v4](https://github.com/bmatcuk/doublestar) | v4.10.0 | `**` glob support |\n| [denormal/go-gitignore](https://github.com/denormal/go-gitignore) | latest | .gitignore / .claudeignore parsing |\n| [tree-sitter/go-tree-sitter](https://github.com/tree-sitter/go-tree-sitter) | v0.25.0 | CGo tree-sitter bindings (`-tags ast` only) |\n| [tree-sitter/tree-sitter-typescript](https://github.com/tree-sitter/tree-sitter-typescript) | v0.23.2 | TypeScript grammar (`-tags ast` only) |\n| [tree-sitter/tree-sitter-python](https://github.com/tree-sitter/tree-sitter-python) | v0.25.0 | Python grammar (`-tags ast` only) |\n| [tree-sitter/tree-sitter-javascript](https://github.com/tree-sitter/tree-sitter-javascript) | v0.25.0 | JavaScript grammar (`-tags ast` only) |\n\n## Performance\n\n| Metric | ~5k files | ~10k files |\n|--------|-----------|------------|\n| Initial indexing | ~1s | ~1-2s |\n| Memory usage | ≈ 2× total indexed file size | ≈ 2× total indexed file size |\n| Text / regex search | \u003c30ms | \u003c60ms |\n| Glob search | \u003c2ms | \u003c5ms |\n| Incremental update | \u003c5ms/file | \u003c5ms/file |\n\nSearch is a linear in-memory scan compiled to a single RE2 matcher — no inverted index to build or keep consistent, so indexing is fast and memory stays close to the raw corpus size.\n\n## Supported languages\n\nLanguage detection recognizes 70+ file extensions, including:\n\nGo, TypeScript, JavaScript, Python, Rust, Java, Kotlin, C, C++, C#, Swift, Dart, Ruby, PHP, Shell, PowerShell, HTML, CSS, SCSS, Sass, Less, JSON, YAML, TOML, XML, SQL, GraphQL, Protobuf, Terraform, Lua, R, Scala, Elixir, Erlang, Haskell, Zig, Vue, Svelte, Markdown, Dockerfile, Makefile, CMake, Batch, and more.\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flexandro%2Fcodeindex-mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flexandro%2Fcodeindex-mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flexandro%2Fcodeindex-mcp/lists"}