cocoindex-code 0.2.36__tar.gz → 0.2.38__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cocoindex_code-0.2.36/README.md → cocoindex_code-0.2.38/PKG-INFO +160 -3
- cocoindex_code-0.2.36/PKG-INFO → cocoindex_code-0.2.38/README.md +116 -47
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/pyproject.toml +5 -5
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/src/cocoindex_code/_daemon_paths.py +50 -0
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/src/cocoindex_code/_version.py +2 -2
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/src/cocoindex_code/cli.py +134 -19
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/src/cocoindex_code/client.py +106 -19
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/src/cocoindex_code/daemon.py +175 -29
- cocoindex_code-0.2.36/src/cocoindex_code/indexer.py → cocoindex_code-0.2.38/src/cocoindex_code/file_walk.py +63 -118
- cocoindex_code-0.2.38/src/cocoindex_code/grep.py +411 -0
- cocoindex_code-0.2.38/src/cocoindex_code/indexer.py +123 -0
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/src/cocoindex_code/protocol.py +25 -0
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/src/cocoindex_code/server.py +50 -2
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/src/cocoindex_code/settings.py +18 -1
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/.gitignore +0 -0
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/LICENSE +0 -0
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/src/cocoindex_code/__init__.py +0 -0
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/src/cocoindex_code/__main__.py +0 -0
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/src/cocoindex_code/chunking.py +0 -0
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/src/cocoindex_code/embedder_defaults.py +0 -0
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/src/cocoindex_code/embedder_params.py +0 -0
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/src/cocoindex_code/litellm_embedder.py +0 -0
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/src/cocoindex_code/project.py +0 -0
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/src/cocoindex_code/query.py +0 -0
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/src/cocoindex_code/schema.py +0 -0
- {cocoindex_code-0.2.36 → cocoindex_code-0.2.38}/src/cocoindex_code/shared.py +0 -0
|
@@ -1,3 +1,47 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cocoindex-code
|
|
3
|
+
Version: 0.2.38
|
|
4
|
+
Summary: MCP server for indexing and querying codebases using CocoIndex
|
|
5
|
+
Project-URL: Homepage, https://github.com/cocoindex-io/cocoindex-code
|
|
6
|
+
Project-URL: Repository, https://github.com/cocoindex-io/cocoindex-code
|
|
7
|
+
Project-URL: Issues, https://github.com/cocoindex-io/cocoindex-code/issues
|
|
8
|
+
License-Expression: Apache-2.0
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: cocoindex,codebase,indexing,mcp,vector-search
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Requires-Dist: cocoindex[litellm]<1.1.0,>=1.0.13
|
|
21
|
+
Requires-Dist: einops>=0.8.2
|
|
22
|
+
Requires-Dist: mcp>=1.0.0
|
|
23
|
+
Requires-Dist: msgspec>=0.19.0
|
|
24
|
+
Requires-Dist: numpy>=1.24.0
|
|
25
|
+
Requires-Dist: pathspec>=0.12.1
|
|
26
|
+
Requires-Dist: pydantic>=2.0.0
|
|
27
|
+
Requires-Dist: pyyaml>=6.0
|
|
28
|
+
Requires-Dist: questionary>=2.0.0
|
|
29
|
+
Requires-Dist: sqlite-vec>=0.1.0
|
|
30
|
+
Requires-Dist: typer>=0.9.0
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: cocoindex[sentence-transformers]<1.1.0,>=1.0.13; extra == 'dev'
|
|
33
|
+
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: prek>=0.1.0; extra == 'dev'
|
|
35
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
39
|
+
Provides-Extra: embeddings-local
|
|
40
|
+
Requires-Dist: cocoindex[sentence-transformers]<1.1.0,>=1.0.13; extra == 'embeddings-local'
|
|
41
|
+
Provides-Extra: full
|
|
42
|
+
Requires-Dist: cocoindex[sentence-transformers]<1.1.0,>=1.0.13; extra == 'full'
|
|
43
|
+
Description-Content-Type: text/markdown
|
|
44
|
+
|
|
1
45
|
<p align="center">
|
|
2
46
|
<img width="2428" alt="cocoindex code" src="https://github.com/user-attachments/assets/d05961b4-0b7b-42ea-834a-59c3c01717ca" />
|
|
3
47
|
</p>
|
|
@@ -63,6 +107,8 @@ Next, set up your [coding agent integration](#coding-agent-integration) — or j
|
|
|
63
107
|
|
|
64
108
|
## Coding Agent Integration
|
|
65
109
|
|
|
110
|
+
This repository is a **single plugin marketplace** (`.claude-plugin/marketplace.json`) consumed by both **Claude Code** and **Grok** — same plugin id `cocoindex-code`, same `ccc` skill. Grok optionally activates the bundled hooks and MCP server with `--trust`; Claude Code users can install the same marketplace and rely on the skill alone or load hooks/MCP from the plugin as needed.
|
|
111
|
+
|
|
66
112
|
### Skill (Recommended)
|
|
67
113
|
|
|
68
114
|
Install the `ccc` skill so your coding agent automatically uses semantic search when needed:
|
|
@@ -82,11 +128,59 @@ Works with [Claude Code](https://docs.anthropic.com/en/docs/claude-code) and oth
|
|
|
82
128
|
For Claude Code users, this repository is also a [plugin marketplace](https://code.claude.com/docs/en/plugin-marketplaces). Install the skill from inside Claude Code with:
|
|
83
129
|
|
|
84
130
|
```text
|
|
85
|
-
/plugin marketplace add
|
|
131
|
+
/plugin marketplace add cocoindex-io/cocoindex-code
|
|
86
132
|
/plugin install cocoindex-code@cocoindex-code
|
|
87
133
|
```
|
|
88
134
|
|
|
89
|
-
This bundles the same `ccc` skill, with version pinning and `/plugin marketplace update` for updates.
|
|
135
|
+
This bundles the same `ccc` skill, with version pinning and `/plugin marketplace update` for updates. The repository also ships `hooks/hooks.json` and `.mcp.json` for Grok (and Claude Code plugin installs that load those files); Claude users who want skill-only search can rely on the skill alone and add MCP manually in the [MCP Server](#mcp-server) section below instead of using the bundled `.mcp.json`.
|
|
136
|
+
|
|
137
|
+
#### Grok plugin
|
|
138
|
+
|
|
139
|
+
For [Grok](https://github.com/xai-org/grok) users, install via Grok's plugin system. The plugin bundles three components:
|
|
140
|
+
|
|
141
|
+
| Component | Purpose |
|
|
142
|
+
|-----------|---------|
|
|
143
|
+
| **Skill** (`skills/ccc/`) | Agent runs `ccc search` / `ccc index` via the CLI (same as Claude Code above) |
|
|
144
|
+
| **Hook** (`hooks/hooks.json`) | `SessionStart` → incremental `ccc index` when `.cocoindex_code/` exists |
|
|
145
|
+
| **MCP** (`.mcp.json`) | `ccc mcp` stdio server — `search` tool with `refresh_index=true` by default |
|
|
146
|
+
|
|
147
|
+
Grok does **not** import Claude's `enabledPlugins` or plugin cache; install separately even if you already use cocoindex in Claude Code.
|
|
148
|
+
|
|
149
|
+
**Full install** (skill + hook + MCP):
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
grok plugin marketplace add cocoindex-io/cocoindex-code
|
|
153
|
+
grok plugin install cocoindex-io/cocoindex-code --trust
|
|
154
|
+
grok plugin enable cocoindex-code
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Prefer the GitHub shorthand (`cocoindex-io/cocoindex-code`) for install — `grok plugin install cocoindex-code` can fail when no marketplace plugin matches that bare name.
|
|
158
|
+
|
|
159
|
+
`--trust` is required so Grok activates the plugin's hooks and MCP server (skills load when the plugin is enabled).
|
|
160
|
+
|
|
161
|
+
**Skill-only** (match Claude Code — no auto-index hook, no MCP tool):
|
|
162
|
+
|
|
163
|
+
Install and enable as above, then disable the optional components:
|
|
164
|
+
|
|
165
|
+
1. **Hooks** — open `/hooks`, select the `SessionStart` hook from `cocoindex-code`, press `Space` to disable.
|
|
166
|
+
2. **MCP** — open `/mcps`, select `cocoindex-code`, press `Space` to disable; or persist in `~/.grok/config.toml`:
|
|
167
|
+
|
|
168
|
+
```toml
|
|
169
|
+
[mcp_servers.cocoindex-code]
|
|
170
|
+
enabled = false
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The agent still owns indexing via the `ccc` skill (`ccc index` / `ccc search --refresh` when stale), same as Claude Code.
|
|
174
|
+
|
|
175
|
+
To avoid importing MCP servers from your Claude/Cursor user config (unrelated to this plugin):
|
|
176
|
+
|
|
177
|
+
```toml
|
|
178
|
+
[compat.claude]
|
|
179
|
+
mcps = false
|
|
180
|
+
|
|
181
|
+
[compat.cursor]
|
|
182
|
+
mcps = false
|
|
183
|
+
```
|
|
90
184
|
|
|
91
185
|
### MCP Server
|
|
92
186
|
|
|
@@ -134,6 +228,24 @@ Or use opencode.json:
|
|
|
134
228
|
```
|
|
135
229
|
</details>
|
|
136
230
|
|
|
231
|
+
<details>
|
|
232
|
+
<summary>Kilo Code</summary>
|
|
233
|
+
|
|
234
|
+
Add a local MCP server in `~/.config/kilo/kilo.jsonc`, `kilo.jsonc`, or `.kilo/kilo.jsonc`:
|
|
235
|
+
|
|
236
|
+
```json
|
|
237
|
+
{
|
|
238
|
+
"mcp": {
|
|
239
|
+
"cocoindex-code": {
|
|
240
|
+
"type": "local",
|
|
241
|
+
"command": ["ccc", "mcp"],
|
|
242
|
+
"enabled": true
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
</details>
|
|
248
|
+
|
|
137
249
|
Once configured, the agent automatically decides when semantic code search is helpful — finding code by description, exploring unfamiliar codebases, fuzzy/conceptual matches, or locating implementations without knowing exact names.
|
|
138
250
|
|
|
139
251
|
> **Note:** The `cocoindex-code` command (without subcommand) still works as an MCP server for backward compatibility. It auto-creates settings from environment variables on first run.
|
|
@@ -171,7 +283,7 @@ ccc search "authentication logic" # search!
|
|
|
171
283
|
|
|
172
284
|
The background daemon starts automatically on first use.
|
|
173
285
|
|
|
174
|
-
> **Tip:** `ccc index` auto-initializes
|
|
286
|
+
> **Tip:** You can skip `ccc init` and go straight to `ccc index` — it auto-initializes new projects with default settings. If global settings are missing too (first use on the machine), it walks you through the same model setup as `ccc init` when run interactively; non-interactive runs (scripts, hooks) still require a one-time `ccc init` first.
|
|
175
287
|
|
|
176
288
|
### CLI Reference
|
|
177
289
|
|
|
@@ -180,6 +292,7 @@ The background daemon starts automatically on first use.
|
|
|
180
292
|
| `ccc init` | Initialize a project — creates settings files, adds `.cocoindex_code/` to `.gitignore` |
|
|
181
293
|
| `ccc index` | Build or update the index (auto-inits if needed). Shows streaming progress. |
|
|
182
294
|
| `ccc search <query>` | Semantic search across the codebase |
|
|
295
|
+
| `ccc grep <pattern> [path]` | Structural code search by example (no index needed) |
|
|
183
296
|
| `ccc status` | Show index stats (chunk count, file count, language breakdown) |
|
|
184
297
|
| `ccc mcp` | Run as MCP server in stdio mode |
|
|
185
298
|
| `ccc doctor` | Run diagnostics — checks settings, daemon, model, file matching, and index health |
|
|
@@ -200,6 +313,36 @@ ccc search --refresh database schema # update index first, then
|
|
|
200
313
|
|
|
201
314
|
By default, `ccc search` scopes results to your current working directory (relative to the project root). Use `--path` to override.
|
|
202
315
|
|
|
316
|
+
### Structural Search (`ccc grep`)
|
|
317
|
+
|
|
318
|
+
`ccc grep` finds code by **structure**, not text — you write a by-example pattern
|
|
319
|
+
and it matches the syntax tree (via cocoindex's `code_match`), so formatting,
|
|
320
|
+
whitespace, and intervening tokens don't matter. It runs entirely locally: no
|
|
321
|
+
index, daemon, or embeddings required.
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
ccc grep 'def \NAME(\(ARGS*\)):' # every Python function def under the cwd
|
|
325
|
+
ccc grep 'foo(\(ARGS*\))' src/ # calls to foo(...) anywhere under src/
|
|
326
|
+
ccc grep 'fn \NAME(\(A*\))' --lang rust # restrict to one language
|
|
327
|
+
ccc grep 'class \NAME:' --path 'tests/**' # restrict to a path glob
|
|
328
|
+
ccc grep 'TODO(\(A*\))' path/to/file.py # a single file
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Metavariables use the `\` sigil: `\NAME` captures one node, `\(NAME*\)` a run of
|
|
332
|
+
siblings, `\_`/`\*` match anonymously. The pattern is matched per language, so a
|
|
333
|
+
single invocation scans every supported source file (others are skipped). Inside
|
|
334
|
+
an initialized project, `ccc grep` honors the project's include/exclude patterns
|
|
335
|
+
and `.gitignore`; otherwise it scans all supported source files under the path.
|
|
336
|
+
|
|
337
|
+
Results stream to the terminal file-by-file as each match is found (in completion
|
|
338
|
+
order, since files are matched in parallel) rather than all at once at the end.
|
|
339
|
+
Each matching file shows its matched line range; under a TTY the path is colored,
|
|
340
|
+
line numbers are dimmed, and the unmatched context around a match is dimmed so the
|
|
341
|
+
match stands out.
|
|
342
|
+
|
|
343
|
+
> **Note:** `ccc grep` relies on cocoindex's structural `code_match` feature.
|
|
344
|
+
> Until it ships in a released cocoindex, run against a local cocoindex build.
|
|
345
|
+
|
|
203
346
|
## Docker
|
|
204
347
|
|
|
205
348
|
A Docker image is available for teams who want a reproducible, dependency-free
|
|
@@ -416,10 +559,15 @@ embedding:
|
|
|
416
559
|
|
|
417
560
|
envs: # extra environment variables for the daemon
|
|
418
561
|
OPENAI_API_KEY: your-key # only needed if not already in your shell environment
|
|
562
|
+
|
|
563
|
+
daemon:
|
|
564
|
+
idle_timeout_minutes: 180 # optional: exit the daemon after this long without client activity (default 180, 0 = never)
|
|
419
565
|
```
|
|
420
566
|
|
|
421
567
|
> **Note:** The daemon inherits your shell environment. If an API key (e.g. `OPENAI_API_KEY`) is already set as an environment variable, you don't need to duplicate it in `envs`. The `envs` field is only for values that aren't in your environment.
|
|
422
568
|
|
|
569
|
+
> **Idle timeout:** the background daemon holds the embedding model in RAM, so it exits after `daemon.idle_timeout_minutes` without client activity and is restarted automatically on your next `ccc` command or MCP search. A live MCP session sends periodic heartbeats, so the daemon never idles out while your coding agent is connected. Set `0` to keep the daemon running forever.
|
|
570
|
+
|
|
423
571
|
> **Custom location:** set `COCOINDEX_CODE_DIR` to place `global_settings.yml` somewhere other than `~/.cocoindex_code/` — useful if you want the file to live alongside your projects (e.g. on a synced folder).
|
|
424
572
|
|
|
425
573
|
#### `indexing_params` / `query_params`
|
|
@@ -477,6 +625,14 @@ chunkers:
|
|
|
477
625
|
|
|
478
626
|
> `.cocoindex_code/` is automatically added to `.gitignore` during init.
|
|
479
627
|
|
|
628
|
+
After editing `include_patterns`, `exclude_patterns`, or `language_overrides`:
|
|
629
|
+
|
|
630
|
+
- Run `ccc doctor` to preview which files match.
|
|
631
|
+
- Run `ccc index` or `ccc search --refresh ...` to update the existing index.
|
|
632
|
+
- You do not need to delete the index or restart the daemon for these file-matching changes.
|
|
633
|
+
|
|
634
|
+
If you add or change custom `chunkers`, restart the daemon first so the chunker registry is reloaded, then run `ccc index`.
|
|
635
|
+
|
|
480
636
|
Use `chunkers` when you want to control how a file type is split into chunks before indexing.
|
|
481
637
|
|
|
482
638
|
`module: example_toml_chunker:toml_chunker` means:
|
|
@@ -675,6 +831,7 @@ embedding:
|
|
|
675
831
|
| cpp | c++ | `.cpp`, `.cc`, `.cxx`, `.h`, `.hpp` |
|
|
676
832
|
| csharp | csharp, cs | `.cs` |
|
|
677
833
|
| css | | `.css`, `.scss` |
|
|
834
|
+
| dart | | `.dart` |
|
|
678
835
|
| dtd | | `.dtd` |
|
|
679
836
|
| fortran | f, f90, f95, f03 | `.f`, `.f90`, `.f95`, `.f03` |
|
|
680
837
|
| go | golang | `.go` |
|
|
@@ -1,47 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: cocoindex-code
|
|
3
|
-
Version: 0.2.36
|
|
4
|
-
Summary: MCP server for indexing and querying codebases using CocoIndex
|
|
5
|
-
Project-URL: Homepage, https://github.com/cocoindex-io/cocoindex-code
|
|
6
|
-
Project-URL: Repository, https://github.com/cocoindex-io/cocoindex-code
|
|
7
|
-
Project-URL: Issues, https://github.com/cocoindex-io/cocoindex-code/issues
|
|
8
|
-
License-Expression: Apache-2.0
|
|
9
|
-
License-File: LICENSE
|
|
10
|
-
Keywords: cocoindex,codebase,indexing,mcp,vector-search
|
|
11
|
-
Classifier: Development Status :: 3 - Alpha
|
|
12
|
-
Classifier: Intended Audience :: Developers
|
|
13
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
|
-
Classifier: Programming Language :: Python :: 3
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
-
Requires-Python: >=3.11
|
|
20
|
-
Requires-Dist: cocoindex[litellm]<1.1.0,>=1.0.6
|
|
21
|
-
Requires-Dist: einops>=0.8.2
|
|
22
|
-
Requires-Dist: mcp>=1.0.0
|
|
23
|
-
Requires-Dist: msgspec>=0.19.0
|
|
24
|
-
Requires-Dist: numpy>=1.24.0
|
|
25
|
-
Requires-Dist: pathspec>=0.12.1
|
|
26
|
-
Requires-Dist: pydantic>=2.0.0
|
|
27
|
-
Requires-Dist: pyyaml>=6.0
|
|
28
|
-
Requires-Dist: questionary>=2.0.0
|
|
29
|
-
Requires-Dist: sqlite-vec>=0.1.0
|
|
30
|
-
Requires-Dist: typer>=0.9.0
|
|
31
|
-
Provides-Extra: dev
|
|
32
|
-
Requires-Dist: cocoindex[sentence-transformers]<1.1.0,>=1.0.6; extra == 'dev'
|
|
33
|
-
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
34
|
-
Requires-Dist: prek>=0.1.0; extra == 'dev'
|
|
35
|
-
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
36
|
-
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
37
|
-
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
38
|
-
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
39
|
-
Provides-Extra: embeddings-local
|
|
40
|
-
Requires-Dist: cocoindex[sentence-transformers]<1.1.0,>=1.0.6; extra == 'embeddings-local'
|
|
41
|
-
Provides-Extra: full
|
|
42
|
-
Requires-Dist: cocoindex[sentence-transformers]<1.1.0,>=1.0.6; extra == 'full'
|
|
43
|
-
Description-Content-Type: text/markdown
|
|
44
|
-
|
|
45
1
|
<p align="center">
|
|
46
2
|
<img width="2428" alt="cocoindex code" src="https://github.com/user-attachments/assets/d05961b4-0b7b-42ea-834a-59c3c01717ca" />
|
|
47
3
|
</p>
|
|
@@ -107,6 +63,8 @@ Next, set up your [coding agent integration](#coding-agent-integration) — or j
|
|
|
107
63
|
|
|
108
64
|
## Coding Agent Integration
|
|
109
65
|
|
|
66
|
+
This repository is a **single plugin marketplace** (`.claude-plugin/marketplace.json`) consumed by both **Claude Code** and **Grok** — same plugin id `cocoindex-code`, same `ccc` skill. Grok optionally activates the bundled hooks and MCP server with `--trust`; Claude Code users can install the same marketplace and rely on the skill alone or load hooks/MCP from the plugin as needed.
|
|
67
|
+
|
|
110
68
|
### Skill (Recommended)
|
|
111
69
|
|
|
112
70
|
Install the `ccc` skill so your coding agent automatically uses semantic search when needed:
|
|
@@ -126,11 +84,59 @@ Works with [Claude Code](https://docs.anthropic.com/en/docs/claude-code) and oth
|
|
|
126
84
|
For Claude Code users, this repository is also a [plugin marketplace](https://code.claude.com/docs/en/plugin-marketplaces). Install the skill from inside Claude Code with:
|
|
127
85
|
|
|
128
86
|
```text
|
|
129
|
-
/plugin marketplace add
|
|
87
|
+
/plugin marketplace add cocoindex-io/cocoindex-code
|
|
130
88
|
/plugin install cocoindex-code@cocoindex-code
|
|
131
89
|
```
|
|
132
90
|
|
|
133
|
-
This bundles the same `ccc` skill, with version pinning and `/plugin marketplace update` for updates.
|
|
91
|
+
This bundles the same `ccc` skill, with version pinning and `/plugin marketplace update` for updates. The repository also ships `hooks/hooks.json` and `.mcp.json` for Grok (and Claude Code plugin installs that load those files); Claude users who want skill-only search can rely on the skill alone and add MCP manually in the [MCP Server](#mcp-server) section below instead of using the bundled `.mcp.json`.
|
|
92
|
+
|
|
93
|
+
#### Grok plugin
|
|
94
|
+
|
|
95
|
+
For [Grok](https://github.com/xai-org/grok) users, install via Grok's plugin system. The plugin bundles three components:
|
|
96
|
+
|
|
97
|
+
| Component | Purpose |
|
|
98
|
+
|-----------|---------|
|
|
99
|
+
| **Skill** (`skills/ccc/`) | Agent runs `ccc search` / `ccc index` via the CLI (same as Claude Code above) |
|
|
100
|
+
| **Hook** (`hooks/hooks.json`) | `SessionStart` → incremental `ccc index` when `.cocoindex_code/` exists |
|
|
101
|
+
| **MCP** (`.mcp.json`) | `ccc mcp` stdio server — `search` tool with `refresh_index=true` by default |
|
|
102
|
+
|
|
103
|
+
Grok does **not** import Claude's `enabledPlugins` or plugin cache; install separately even if you already use cocoindex in Claude Code.
|
|
104
|
+
|
|
105
|
+
**Full install** (skill + hook + MCP):
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
grok plugin marketplace add cocoindex-io/cocoindex-code
|
|
109
|
+
grok plugin install cocoindex-io/cocoindex-code --trust
|
|
110
|
+
grok plugin enable cocoindex-code
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Prefer the GitHub shorthand (`cocoindex-io/cocoindex-code`) for install — `grok plugin install cocoindex-code` can fail when no marketplace plugin matches that bare name.
|
|
114
|
+
|
|
115
|
+
`--trust` is required so Grok activates the plugin's hooks and MCP server (skills load when the plugin is enabled).
|
|
116
|
+
|
|
117
|
+
**Skill-only** (match Claude Code — no auto-index hook, no MCP tool):
|
|
118
|
+
|
|
119
|
+
Install and enable as above, then disable the optional components:
|
|
120
|
+
|
|
121
|
+
1. **Hooks** — open `/hooks`, select the `SessionStart` hook from `cocoindex-code`, press `Space` to disable.
|
|
122
|
+
2. **MCP** — open `/mcps`, select `cocoindex-code`, press `Space` to disable; or persist in `~/.grok/config.toml`:
|
|
123
|
+
|
|
124
|
+
```toml
|
|
125
|
+
[mcp_servers.cocoindex-code]
|
|
126
|
+
enabled = false
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The agent still owns indexing via the `ccc` skill (`ccc index` / `ccc search --refresh` when stale), same as Claude Code.
|
|
130
|
+
|
|
131
|
+
To avoid importing MCP servers from your Claude/Cursor user config (unrelated to this plugin):
|
|
132
|
+
|
|
133
|
+
```toml
|
|
134
|
+
[compat.claude]
|
|
135
|
+
mcps = false
|
|
136
|
+
|
|
137
|
+
[compat.cursor]
|
|
138
|
+
mcps = false
|
|
139
|
+
```
|
|
134
140
|
|
|
135
141
|
### MCP Server
|
|
136
142
|
|
|
@@ -178,6 +184,24 @@ Or use opencode.json:
|
|
|
178
184
|
```
|
|
179
185
|
</details>
|
|
180
186
|
|
|
187
|
+
<details>
|
|
188
|
+
<summary>Kilo Code</summary>
|
|
189
|
+
|
|
190
|
+
Add a local MCP server in `~/.config/kilo/kilo.jsonc`, `kilo.jsonc`, or `.kilo/kilo.jsonc`:
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"mcp": {
|
|
195
|
+
"cocoindex-code": {
|
|
196
|
+
"type": "local",
|
|
197
|
+
"command": ["ccc", "mcp"],
|
|
198
|
+
"enabled": true
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
</details>
|
|
204
|
+
|
|
181
205
|
Once configured, the agent automatically decides when semantic code search is helpful — finding code by description, exploring unfamiliar codebases, fuzzy/conceptual matches, or locating implementations without knowing exact names.
|
|
182
206
|
|
|
183
207
|
> **Note:** The `cocoindex-code` command (without subcommand) still works as an MCP server for backward compatibility. It auto-creates settings from environment variables on first run.
|
|
@@ -215,7 +239,7 @@ ccc search "authentication logic" # search!
|
|
|
215
239
|
|
|
216
240
|
The background daemon starts automatically on first use.
|
|
217
241
|
|
|
218
|
-
> **Tip:** `ccc index` auto-initializes
|
|
242
|
+
> **Tip:** You can skip `ccc init` and go straight to `ccc index` — it auto-initializes new projects with default settings. If global settings are missing too (first use on the machine), it walks you through the same model setup as `ccc init` when run interactively; non-interactive runs (scripts, hooks) still require a one-time `ccc init` first.
|
|
219
243
|
|
|
220
244
|
### CLI Reference
|
|
221
245
|
|
|
@@ -224,6 +248,7 @@ The background daemon starts automatically on first use.
|
|
|
224
248
|
| `ccc init` | Initialize a project — creates settings files, adds `.cocoindex_code/` to `.gitignore` |
|
|
225
249
|
| `ccc index` | Build or update the index (auto-inits if needed). Shows streaming progress. |
|
|
226
250
|
| `ccc search <query>` | Semantic search across the codebase |
|
|
251
|
+
| `ccc grep <pattern> [path]` | Structural code search by example (no index needed) |
|
|
227
252
|
| `ccc status` | Show index stats (chunk count, file count, language breakdown) |
|
|
228
253
|
| `ccc mcp` | Run as MCP server in stdio mode |
|
|
229
254
|
| `ccc doctor` | Run diagnostics — checks settings, daemon, model, file matching, and index health |
|
|
@@ -244,6 +269,36 @@ ccc search --refresh database schema # update index first, then
|
|
|
244
269
|
|
|
245
270
|
By default, `ccc search` scopes results to your current working directory (relative to the project root). Use `--path` to override.
|
|
246
271
|
|
|
272
|
+
### Structural Search (`ccc grep`)
|
|
273
|
+
|
|
274
|
+
`ccc grep` finds code by **structure**, not text — you write a by-example pattern
|
|
275
|
+
and it matches the syntax tree (via cocoindex's `code_match`), so formatting,
|
|
276
|
+
whitespace, and intervening tokens don't matter. It runs entirely locally: no
|
|
277
|
+
index, daemon, or embeddings required.
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
ccc grep 'def \NAME(\(ARGS*\)):' # every Python function def under the cwd
|
|
281
|
+
ccc grep 'foo(\(ARGS*\))' src/ # calls to foo(...) anywhere under src/
|
|
282
|
+
ccc grep 'fn \NAME(\(A*\))' --lang rust # restrict to one language
|
|
283
|
+
ccc grep 'class \NAME:' --path 'tests/**' # restrict to a path glob
|
|
284
|
+
ccc grep 'TODO(\(A*\))' path/to/file.py # a single file
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Metavariables use the `\` sigil: `\NAME` captures one node, `\(NAME*\)` a run of
|
|
288
|
+
siblings, `\_`/`\*` match anonymously. The pattern is matched per language, so a
|
|
289
|
+
single invocation scans every supported source file (others are skipped). Inside
|
|
290
|
+
an initialized project, `ccc grep` honors the project's include/exclude patterns
|
|
291
|
+
and `.gitignore`; otherwise it scans all supported source files under the path.
|
|
292
|
+
|
|
293
|
+
Results stream to the terminal file-by-file as each match is found (in completion
|
|
294
|
+
order, since files are matched in parallel) rather than all at once at the end.
|
|
295
|
+
Each matching file shows its matched line range; under a TTY the path is colored,
|
|
296
|
+
line numbers are dimmed, and the unmatched context around a match is dimmed so the
|
|
297
|
+
match stands out.
|
|
298
|
+
|
|
299
|
+
> **Note:** `ccc grep` relies on cocoindex's structural `code_match` feature.
|
|
300
|
+
> Until it ships in a released cocoindex, run against a local cocoindex build.
|
|
301
|
+
|
|
247
302
|
## Docker
|
|
248
303
|
|
|
249
304
|
A Docker image is available for teams who want a reproducible, dependency-free
|
|
@@ -460,10 +515,15 @@ embedding:
|
|
|
460
515
|
|
|
461
516
|
envs: # extra environment variables for the daemon
|
|
462
517
|
OPENAI_API_KEY: your-key # only needed if not already in your shell environment
|
|
518
|
+
|
|
519
|
+
daemon:
|
|
520
|
+
idle_timeout_minutes: 180 # optional: exit the daemon after this long without client activity (default 180, 0 = never)
|
|
463
521
|
```
|
|
464
522
|
|
|
465
523
|
> **Note:** The daemon inherits your shell environment. If an API key (e.g. `OPENAI_API_KEY`) is already set as an environment variable, you don't need to duplicate it in `envs`. The `envs` field is only for values that aren't in your environment.
|
|
466
524
|
|
|
525
|
+
> **Idle timeout:** the background daemon holds the embedding model in RAM, so it exits after `daemon.idle_timeout_minutes` without client activity and is restarted automatically on your next `ccc` command or MCP search. A live MCP session sends periodic heartbeats, so the daemon never idles out while your coding agent is connected. Set `0` to keep the daemon running forever.
|
|
526
|
+
|
|
467
527
|
> **Custom location:** set `COCOINDEX_CODE_DIR` to place `global_settings.yml` somewhere other than `~/.cocoindex_code/` — useful if you want the file to live alongside your projects (e.g. on a synced folder).
|
|
468
528
|
|
|
469
529
|
#### `indexing_params` / `query_params`
|
|
@@ -521,6 +581,14 @@ chunkers:
|
|
|
521
581
|
|
|
522
582
|
> `.cocoindex_code/` is automatically added to `.gitignore` during init.
|
|
523
583
|
|
|
584
|
+
After editing `include_patterns`, `exclude_patterns`, or `language_overrides`:
|
|
585
|
+
|
|
586
|
+
- Run `ccc doctor` to preview which files match.
|
|
587
|
+
- Run `ccc index` or `ccc search --refresh ...` to update the existing index.
|
|
588
|
+
- You do not need to delete the index or restart the daemon for these file-matching changes.
|
|
589
|
+
|
|
590
|
+
If you add or change custom `chunkers`, restart the daemon first so the chunker registry is reloaded, then run `ccc index`.
|
|
591
|
+
|
|
524
592
|
Use `chunkers` when you want to control how a file type is split into chunks before indexing.
|
|
525
593
|
|
|
526
594
|
`module: example_toml_chunker:toml_chunker` means:
|
|
@@ -719,6 +787,7 @@ embedding:
|
|
|
719
787
|
| cpp | c++ | `.cpp`, `.cc`, `.cxx`, `.h`, `.hpp` |
|
|
720
788
|
| csharp | csharp, cs | `.cs` |
|
|
721
789
|
| css | | `.css`, `.scss` |
|
|
790
|
+
| dart | | `.dart` |
|
|
722
791
|
| dtd | | `.dtd` |
|
|
723
792
|
| fortran | f, f90, f95, f03 | `.f`, `.f90`, `.f95`, `.f03` |
|
|
724
793
|
| go | golang | `.go` |
|
|
@@ -23,7 +23,7 @@ classifiers = [
|
|
|
23
23
|
|
|
24
24
|
dependencies = [
|
|
25
25
|
"mcp>=1.0.0",
|
|
26
|
-
"cocoindex[litellm]>=1.0.
|
|
26
|
+
"cocoindex[litellm]>=1.0.13,<1.1.0",
|
|
27
27
|
"sqlite-vec>=0.1.0",
|
|
28
28
|
"pydantic>=2.0.0",
|
|
29
29
|
"numpy>=1.24.0",
|
|
@@ -39,7 +39,7 @@ dependencies = [
|
|
|
39
39
|
# `embeddings-local` is the primary feature extra: it pulls in
|
|
40
40
|
# `sentence-transformers` (via cocoindex) so local embeddings work without
|
|
41
41
|
# an API key.
|
|
42
|
-
embeddings-local = ["cocoindex[sentence-transformers]>=1.0.
|
|
42
|
+
embeddings-local = ["cocoindex[sentence-transformers]>=1.0.13,<1.1.0"]
|
|
43
43
|
# `full` is the umbrella "batteries-included" alias. Today it's just
|
|
44
44
|
# `embeddings-local`, but we expect to bundle more optional niceties under
|
|
45
45
|
# it over time — users who want everything can keep using `[full]` and pick
|
|
@@ -47,7 +47,7 @@ embeddings-local = ["cocoindex[sentence-transformers]>=1.0.6,<1.1.0"]
|
|
|
47
47
|
# `:full` image variant for consistency across install paths. Contents are
|
|
48
48
|
# inlined rather than self-referencing `cocoindex-code[embeddings-local]`
|
|
49
49
|
# to avoid resolver edge cases with older pip.
|
|
50
|
-
full = ["cocoindex[sentence-transformers]>=1.0.
|
|
50
|
+
full = ["cocoindex[sentence-transformers]>=1.0.13,<1.1.0"]
|
|
51
51
|
dev = [
|
|
52
52
|
"pytest>=7.0.0",
|
|
53
53
|
"pytest-asyncio>=0.21.0",
|
|
@@ -55,7 +55,7 @@ dev = [
|
|
|
55
55
|
"ruff>=0.1.0",
|
|
56
56
|
"mypy>=1.0.0",
|
|
57
57
|
"prek>=0.1.0",
|
|
58
|
-
"cocoindex[sentence-transformers]>=1.0.
|
|
58
|
+
"cocoindex[sentence-transformers]>=1.0.13,<1.1.0",
|
|
59
59
|
]
|
|
60
60
|
|
|
61
61
|
[project.scripts]
|
|
@@ -89,7 +89,7 @@ dev = [
|
|
|
89
89
|
"mypy>=1.0.0",
|
|
90
90
|
"prek>=0.1.0",
|
|
91
91
|
"types-pyyaml>=6.0.12.20250915",
|
|
92
|
-
"cocoindex[sentence-transformers]>=1.0.
|
|
92
|
+
"cocoindex[sentence-transformers]>=1.0.13,<1.1.0",
|
|
93
93
|
]
|
|
94
94
|
|
|
95
95
|
[tool.ruff]
|
|
@@ -6,8 +6,11 @@ can import these without pulling in the full daemon stack.
|
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
|
+
import json
|
|
9
10
|
import os
|
|
10
11
|
import sys
|
|
12
|
+
import time
|
|
13
|
+
from dataclasses import dataclass
|
|
11
14
|
from pathlib import Path
|
|
12
15
|
|
|
13
16
|
from .settings import user_settings_dir
|
|
@@ -58,3 +61,50 @@ def daemon_pid_path() -> Path:
|
|
|
58
61
|
def daemon_log_path() -> Path:
|
|
59
62
|
"""Return the path for the daemon's log file."""
|
|
60
63
|
return daemon_runtime_dir() / "daemon.log"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def daemon_last_exit_path() -> Path:
|
|
67
|
+
"""Return the path for the daemon's graceful-exit marker file."""
|
|
68
|
+
return daemon_runtime_dir() / "last_exit"
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass
|
|
72
|
+
class LastExitMarker:
|
|
73
|
+
"""Record of the most recent *graceful* daemon exit.
|
|
74
|
+
|
|
75
|
+
Written by the daemon's graceful shutdown path (``StopRequest``,
|
|
76
|
+
SIGTERM/SIGINT) and removed again at the next daemon startup. A crashed
|
|
77
|
+
daemon (SIGKILL, OOM, segfault) never writes it — that absence is how the
|
|
78
|
+
client tells a crash from a graceful exit.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
pid: int
|
|
82
|
+
reason: str
|
|
83
|
+
timestamp: float
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def write_last_exit_marker(pid: int, reason: str) -> None:
|
|
87
|
+
"""Persist the graceful-exit marker. Best-effort — never raises."""
|
|
88
|
+
payload = json.dumps({"pid": pid, "reason": reason, "timestamp": time.time()})
|
|
89
|
+
try:
|
|
90
|
+
daemon_last_exit_path().write_text(payload)
|
|
91
|
+
except OSError:
|
|
92
|
+
pass
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def read_last_exit_marker() -> LastExitMarker | None:
|
|
96
|
+
"""Read the graceful-exit marker, or None when absent/unreadable."""
|
|
97
|
+
try:
|
|
98
|
+
data = json.loads(daemon_last_exit_path().read_text())
|
|
99
|
+
return LastExitMarker(
|
|
100
|
+
pid=int(data["pid"]),
|
|
101
|
+
reason=str(data["reason"]),
|
|
102
|
+
timestamp=float(data["timestamp"]),
|
|
103
|
+
)
|
|
104
|
+
except (OSError, ValueError, KeyError, TypeError):
|
|
105
|
+
return None
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def clear_last_exit_marker() -> None:
|
|
109
|
+
"""Remove the marker (daemon startup) so it always refers to the most recent exit."""
|
|
110
|
+
daemon_last_exit_path().unlink(missing_ok=True)
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.2.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 2,
|
|
21
|
+
__version__ = version = '0.2.38'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 2, 38)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|