202 Commits

Author SHA1 Message Date
LJ 🥥🌴 6529a56779 docs(rust): user-facing README for the Rust ccc build (#197)
* docs(rust): document how the port uses the CocoIndex Rust SDK

Add a "How it uses the CocoIndex Rust SDK" section to rust/PORTING.md — a
code-grounded walkthrough of the SDK API the port exercises (Environment/App/run,
ContextKey DI + change detection, #[cocoindex::function] memoization, walk_dir +
mount_each!, the sqlite/vec0 table target + declare_row, and the sqlite-vec
from_pool gotcha). Snippets cite live file:line anchors so the doc stays
verifiable against the source.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(rust): make it a standalone Rust README (drop Python framing)

Rename rust/PORTING.md -> rust/README.md and rewrite as a Rust-only usage doc:
drop the Python->Rust module map, the parity audit, the Python backward-compat
section, and the "vs Python" deltas. Keep build/run, architecture, the
"How it uses the CocoIndex Rust SDK" walkthrough, CLI commands, configuration,
testing, and a plain limitations/follow-ups list. Update the e2e fixture that
copies the doc as a sample markdown file.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(rust): rewrite README as a user guide (install / CLI / MCP / config)

Drop the SDK-internals walkthrough. The Rust README now mirrors the main
cocoindex-code README's user-facing structure — Install (build from source),
Quick start, Coding Agent Integration (Skill + MCP), CLI Reference, Search
options, MCP tool reference, Configuration (user/project settings), Supported
languages, and a short "Differences from the Python build" note (local-only
embeddings; no custom Python chunkers).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 23:55:30 -07:00
LJ 🥥🌴 1649b5e803 Add Rust port of cocoindex-code (ccc)
Feature-parity Rust implementation of the Python `ccc` CLI on the CocoIndex
Rust SDK: daemon/client over a Unix socket (length-prefixed msgpack), MCP
stdio server, fastembed local embeddings, sqlite-vec (vec0) storage,
tree-sitter chunking, and gitignore-aware walking.

Includes fixes from a deep review:
- daemon: fix lost-wakeup in wait_for_indexing_done (enable the Notified future
  before the flag check); bind before claiming the PID file and refuse to
  clobber a live daemon's socket; drain in-flight connections on shutdown.
- query: clamp negative limit/offset (avoid as-usize wrap / unbounded LIMIT).
- protocol: cap inbound frame size before allocating.
- mcp: reply to unknown JSON-RPC methods with -32601 instead of hanging the
  client; reject an empty `query`.
- main: `reset --all` uses remove_dir_all (SQLite -wal/-shm sidecars);
  POSIX-separated GLOB path for cross-platform matching.
- db: WAL + busy_timeout so the read-only query pool reads concurrently with
  the indexer.

Verified: cargo test + 67 e2e checks (tests/e2e_cli.sh, tests/e2e_advanced.sh).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 23:21:45 -07:00
Claudio Ferreira Filho a18a0ee0f6 fix: remove logging.basicConfig from __init__.py (#155)
* fix: remove logging.basicConfig from __init__.py

Calling logging.basicConfig() at import time configures the root logger
for the entire Python process, which interferes with logging setups in
applications that use cocoindex-code as a dependency.

Libraries should not configure the root logger — that is the
application's responsibility.

Closes #124

* Update __init__.py

---------

Co-authored-by: Jiangzhou <jiangzhou@cocoindex.io>
v0.2.36
2026-06-18 21:52:43 -07:00
Jiangzhou c98f8cccb8 docs(readme): document COCOINDEX_LMDB_MAP_SIZE for large codebases (#185) (#187)
Add a Troubleshooting entry for `MDB_MAP_FULL: Environment mapsize limit
reached`, explaining the 4 GiB LMDB default and how to raise it via
`COCOINDEX_LMDB_MAP_SIZE` (both global_settings.yml `envs:` and shell
forms). Note the value is read at daemon startup and that the workaround
is temporary pending cocoindex#2108. Cross-link from the Large codebase
section.
2026-06-15 23:04:17 -07:00
Jim McKeeth 72f6283a1b Add Embedding Options guide and model discovery script (#188)
* Add EMBEDDINGS.md guide and model discovery script (fixes #181)

* fix(scripts): fix ruff lint and format violations in find_best_models.py

- Replace bare `except:` with `except Exception:` (E722)
- Expand inline `if x: return y` to multi-line (E701)
- Break long lines >100 chars (E501)
- Move docstring above imports; sort stdlib before third-party (I001)
- Remove unused `numpy` and `datetime` imports (F401)
- Fix `== True` comparison to use truthiness directly (E712)
- Remove trailing whitespace in string literals (W291/W293)

https://claude.ai/code/session_01GguRSHkNNjDxvP4o8Va2Kp

* chore:formatting, fix lint errors, formatting and cleanup

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-14 23:08:55 -07:00
Jiangzhou 7aa2d8fc7c docs(readme): document running prek checks locally before PRs (#189)
Rewrite the Contributing section to match the actual dev setup. The
old instructions used pip + upstream pre-commit, but the repo uses
prek (a dev dependency) and CI runs `uv run prek run --all-files`.

New steps: `uv sync` to install dev deps, `uv run prek run
--all-files` to reproduce the full CI gate before opening a PR, and
an optional `uv run prek install` for the per-commit git hook.
2026-06-14 16:31:17 -07:00
Mickael B. 17ff8c533c feat: ship as a Claude Code plugin marketplace (#162)
* feat: ship as a Claude Code plugin marketplace

Adds `.claude-plugin/marketplace.json` and `.claude-plugin/plugin.json`
so this repo can be installed directly from inside Claude Code:

    /plugin marketplace add cocoindex-io/cocoindex-code
    /plugin install cocoindex-code@cocoindex-code

The existing `skills/ccc/SKILL.md` is auto-discovered as the plugin's
skill — no file moves, the `npx skills add` workflow keeps working
unchanged. README gets a short subsection under "Skill (Recommended)"
linking the new install path.

Refs: https://code.claude.com/docs/en/plugin-marketplaces

* chore: point plugin manifests to Roxabi fork

Update owner, homepage, repository, and README install command
from cocoindex-io to Roxabi/cocoindex-code.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 23:32:51 -07:00
Jiangzhou 4372baedfa fix(init): clarify providers, add interactive recovery, fix retry crash (#181) (#184)
Addresses the `ccc init` issues reported in #181:

- Relabel embedding providers so local Ollama is clearly under `litellm`
  ("litellm (100+ providers — cloud APIs & local Ollama)") and
  sentence-transformers is marked as built-in HuggingFace models.
- Reject `ollama/` models inline at the sentence-transformers prompt, before
  anything is written or tested, instead of crashing later.
- On a failed init model check, loop with an interactive "try a different
  model / keep & finish" choice, pre-filling the previous provider and model
  on retry, and print a prominent "Next steps" recovery block.
- Add `ccc doctor -v` to show full tracebacks; by default show the one-line
  error plus a hint to rerun with `-v`.
- Fix the retry crash where a rewritten global_settings.yml made the already
  -ensured daemon report a bogus "version mismatch": restart the daemon on a
  stale-settings handshake even after it was ensured, while still failing fast
  on a genuine mid-session version mismatch. Make DaemonVersionError's message
  reflect the actual cause.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
v0.2.35
2026-06-09 00:19:44 -07:00
Jiangzhou 65125c67ca chore(deps): bump cocoindex to 1.0.7 (#178)
Update the cocoindex dependency from 1.0.6 to 1.0.7 in pyproject.toml
and uv.lock. Also ignore the local .claude/ directory.
v0.2.34
2026-06-03 10:19:39 -07:00
Jiangzhou a821c20a64 feat(doctor): surface daemon-side exception tracebacks (#173) (#177)
When a daemon-side `ccc doctor` check failed (e.g. the model check), only a
one-line, 500-char-truncated summary reached the CLI; the full traceback was
logged to daemon.log but never surfaced, making failures hard to debug.

Carry the full traceback across both daemon→CLI error paths:

- Per-check failures: add `traceback` to `EmbeddingCheckResult` and
  `DoctorCheckResult`; `check_embedding` captures `format_exc()` and
  `_check_model` propagates it. The CLI prints it dimmed under the error.
- Streaming exceptions: add `traceback` to `ErrorResponse`, populated by the
  daemon's streaming handler and appended to the client-raised RuntimeError.

Both new fields default to None, keeping the msgpack wire format
backward-compatible.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 09:49:57 -07:00
Jiangzhou 43d7eb1951 Revert "docs(skills/ccc): document ccc describe and ccc guide (#165)" (#176)
This reverts commit cc55f32cd7.
2026-06-03 09:11:45 -07:00
Jiangzhou e6a077fc60 feat(deps): bump cocoindex to 1.0.6 and tag telemetry as cocoindex-code (#172)
Bump cocoindex (and the sentence-transformers extra) lower bound to 1.0.6,
the first release including cocoindex-io/cocoindex#1992 which adds the
optional `COCOINDEX_APPLICATION_FOR_TRACKING` env var.

Set `COCOINDEX_APPLICATION_FOR_TRACKING=cocoindex-code` at the top of
`cocoindex_code/__init__.py` (before any submodule imports `cocoindex`)
so aggregate telemetry can identify this application. Uses `setdefault`
to leave any explicit user value untouched.

Document the telemetry behavior and `COCOINDEX_DISABLE_USAGE_TRACKING`
opt-out in the README.
2026-05-18 21:49:47 -07:00
Jiangzhou 43922296cb fix(deps): bump typer-slim to 0.24.0 to match typer 0.24.1 (#169)
The lockfile pinned typer==0.24.1 alongside typer-slim==0.21.1, two
versions that both ship into the `typer/` namespace and overwrite each
other on install. When the install order leaves typer-slim's stale
`_completion_shared.py` next to typer's new `core.py`, importing typer
fails with

  ImportError: cannot import name 'HAS_SHELLINGHAM' from 'typer.core'

which is what broke pre-commit (windows-latest, 3.11) on PR #168.

Since typer-slim 0.22.0 it's been a meta-package that just depends on
`typer` and ships no `typer/*.py` of its own, so upgrading typer-slim
to 0.24.0 removes the conflict.
2026-05-15 11:54:10 -07:00
Jiangzhou 0234f54e53 docs(readme): document OpenAI-compatible endpoint configuration (#168)
Add an "OpenAI-compatible (custom endpoint)" section under Embedding
Models showing the `openai/` prefix plus `OPENAI_BASE_URL` /
`OPENAI_API_KEY` env vars, and link the LiteLLM "Setting API Keys" doc
from the general LiteLLM note so users of any provider can find the
canonical env-var list.
2026-05-15 11:36:30 -07:00
Jiangzhou cc55f32cd7 docs(skills/ccc): document ccc describe and ccc guide (#165)
Adds two sections to the `ccc` skill:

- `Describing Files and Directories` — `ccc describe <path>` for
  per-file/dir summaries when the path is known.
- `Concept Guides` — `ccc guide [slug]` for cross-cutting
  architectural docs (`.cocoindex_code/guides.yml`), plus an
  "Authoring guides.yml interactively" subsection that gives the
  agent a 5-step collaborative flow (survey → propose → iterate →
  write → generate) and a YAML schema reference.

Inserts a `Following Hints in Search Output` subsection under
search: when a hit is tagged `[summary]` or `[guide]`, follow the
embedded `ccc describe`/`ccc guide` hint rather than running those
commands proactively as a triage step. This reflects empirical
finding that explicit guide-tier triage hurts (matched-vs-unmatched
guide reads are net-neutral in aggregate); search-driven discovery
is strictly better (~−34% tools, −26% time vs no-ccc on a 10-Q
battery).

Frontmatter trigger phrases extended to include `describe this
file` and `read the concept guide`.
2026-05-10 18:20:06 -07:00
Jiangzhou d429632c5e perf(cli): lazy-load server, pathspec, and protocol imports (#164)
Cuts `ccc status` cold-cache startup from ~0.5-0.9s to ~0.15s.

- `cocoindex_code/__init__.py`: replace eager `from .server import main`
  with a PEP 562 `__getattr__` so importing the package no longer pulls
  `mcp.server.fastmcp` (~300ms). The `cocoindex-code = "cocoindex_code:main"`
  console script still resolves.
- `settings.py`: defer `from pathspec import GitIgnoreSpec` into
  `load_gitignore_spec()` (only called by indexer/daemon).
- `cli.py`: move protocol type-only imports under `TYPE_CHECKING`
  (safe with `from __future__ import annotations`); lazy-import
  `DaemonStartError` inside the wrapper and `DoctorCheckResult` next to
  the existing lazy `client` import.

Also drops a stale paragraph from CLAUDE.md.
v0.2.33
2026-05-08 09:25:15 -07:00
Jiangzhou efd1273ab1 docs(claude-md): link to /review-changes; condense write-time rules (#159)
Point reviewers at the `/review-changes` skill for the full detection
checklist, and collapse the per-rule sections (Imports / Type Annotations
/ Multi-Value Returns / Single Source of Truth / Dead Code) into a
shorter bulleted "General principles" list. Project-specific rules
(Internal vs External Modules, Testing) stay in full.
v0.2.32
2026-05-04 20:18:50 -07:00
Jiangzhou 9e9e58af00 feat: add Svelte and Vue support (#158)
Wire up the new Svelte and Vue tree-sitter languages from cocoindex 1.0.3
(cocoindex-io/cocoindex#1937) so `.svelte` and `.vue` files are picked up
by the default include patterns and chunked syntax-aware.

- Add `**/*.svelte` and `**/*.vue` to DEFAULT_INCLUDED_PATTERNS
- Document svelte/vue in the Supported Languages table
- Bump cocoindex dev-group floor to >=1.0.3 (the version that adds the
  tree-sitter parsers); lockfile follows
2026-05-04 20:02:18 -07:00
Jiangzhou 51ea6efea1 fix(litellm): skip encoding_format="float" for voyage/bedrock (#152)
Voyage models (e.g. voyage/voyage-code-3) reject encoding_format="float"
and require base64. Only inject encoding_format/drop_params for providers
that accept the float hint, leaving voyage/ and bedrock/ to use their
native defaults.

Fixes #148
v0.2.31
2026-04-26 17:49:04 -07:00
Jiangzhou 9700655aa6 refactor(embedder-params): drop dimensions knob; pass indexing kwargs into LiteLLM ctor (#151)
- Remove `dimensions` from the litellm whitelist in `_ACCEPTED_KWARGS`.
  Output dimension must be identical for indexing and query for vectors to
  be comparable, so it's a model-wide setting, not a per-side knob —
  exposing it under `indexing_params` / `query_params` invited
  misconfiguration. Updated comment template, README, design doc, and
  testing plan accordingly.
- Plumb `indexing_params` into `create_embedder` and pass them as
  constructor kwargs to `PacedLiteLLMEmbedder`. The values land in
  `self._kwargs` and become defaults forwarded into every
  `litellm.aembedding` call — including paths that don't go through the
  `INDEXING_EMBED_PARAMS` context var (e.g. the dim probe in `_get_dim`).
  Per-call overrides (`query_params` spread at query time) still win
  because `_embed` overlays kwargs on top of `self._kwargs`. Sentence-
  transformers ignores `indexing_params` (its constructor doesn't accept
  arbitrary kwargs; `prompt_name` is per-call only).
v0.2.30
2026-04-25 09:33:24 -07:00
Jiangzhou ee3515fa57 feat: configurable embedder indexing_params/query_params + curated defaults (#150)
Users can now set `indexing_params` and `query_params` under `embedding:` in
`global_settings.yml` to pass extra kwargs to the embedder separately for
indexing vs. query — supporting asymmetric retrieval models (Cohere v3,
Voyage, Nvidia NIM, Gemini, nomic-ai code/text models, Snowflake arctic,
etc.).

- `ccc init` auto-populates these from a curated table of known models and
  prints the applied defaults; unknown models get a commented-out template
  for the accepted keys (`prompt_name` for sentence-transformers;
  `input_type`, `dimensions` for litellm).
- Daemon validates the effective params at startup; invalid keys fail fast
  with a clear error.
- Backward compat: configs for `nomic-ai/CodeRankEmbed` /
  `nomic-ai/nomic-embed-code` that predate this feature keep the previous
  hardcoded `prompt_name=query` behavior, and a one-time handshake warning
  asks users to make the setting explicit. The warning is suppressible by
  any non-None `query_params` (including `{}`).
- `ccc doctor` now tests indexing and query separately so asymmetric
  misconfigurations surface independently.

Drops the legacy `shared.query_prompt_name` module variable and
`_QUERY_PROMPT_MODELS` set; the new resolution path is centralized in
`embedder_params.resolve_embedder_params` and the curated defaults live in
`embedder_defaults._DEFAULT_PARAMS`.

Also enables `litellm.drop_params = True` so provider-specific kwargs that
a particular model doesn't accept are silently dropped instead of failing.
v0.2.29
2026-04-24 16:08:20 -07:00
Jiangzhou da886d5d0d refactor: drop unused shared.embedder global (#149)
The module-level `shared.embedder` global was written by `create_embedder()`
but never read from production code — the embedder flows through the
`EMBEDDER` ContextKey via `context.provide` / `use_context`.

Drop the global along with the two test readers that kept it alive:

- `tests/test_daemon.py` — the `daemon_sock` fixture pre-loaded an embedder
  and monkeypatched `dm.create_embedder` to reuse it. That was only useful
  as a cross-module cache via the now-dead global; with a session-scoped
  fixture, `run_daemon()` loads the embedder once from the saved settings
  regardless.
- `tests/test_chunker_registry.py` — removed a stale
  `monkeypatch.setattr(_shared, "embedder", stub)` whose comment claimed
  CodeChunk.embedding read the global at schema resolution time. It reads
  the EMBEDDER ContextKey instead; the stub is already wired through
  `Project.create(..., stub, ...)`.
2026-04-24 09:51:28 -07:00
Jiangzhou a264038e74 chore: drop cocoindex prerelease install flags (#145)
Now that cocoindex 1.0.0 is stable, we no longer need `--prerelease`
or explicit prerelease version pins in install instructions.

- README.md: simplify `uv tool install` commands
- docker/Dockerfile: drop `--prerelease=allow` and the redundant
  `cocoindex>=1.0.0a33` pin (pyproject.toml already constrains
  `cocoindex[litellm]>=1.0.0,<1.1.0`)
2026-04-22 20:08:48 -07:00
Jiangzhou 755e7036f3 fix(litellm): explicitly pass encoding_format="float" (#144)
LiteLLM documents encoding_format as defaulting to float, but in
practice some providers (e.g. nvidia_nim) error out when it's not
provided. Pass it explicitly as a workaround.
v0.2.28
2026-04-22 15:17:18 -07:00
Jiangzhou a81b72927c chore: upgrade to cocoindex 1.0.0 stable (#143)
- Bump cocoindex from 1.0.0a43 to >=1.0.0,<1.1.0
- Drop `[tool.uv] prerelease = "explicit"` now that the dep is stable
- Adapt ContextKey usage to 1.0 API: opt-in `detect_change=True`
  replaces opt-out `tracked=False`
2026-04-22 14:39:20 -07:00
Jiangzhou 09d022daee docs(docker): one-liner compose install + env-overridable image (#142)
- README: bash/zsh one-liner using `docker compose -f <(curl ...)`,
  plus keep the clone-the-file path for non-POSIX shells.
- docker-compose.yml: `image:` now reads `${COCOINDEX_CODE_IMAGE:-...}`
  so users can switch to `:full` or GHCR without editing the file.
- pyproject: scope mypy to `src/` and collapse single-entry extras arrays.
2026-04-22 13:08:47 -07:00
Jiangzhou 90d8ff9f08 ci(docker): switch to registry-backed BuildKit cache (GHCR) (#140)
The previous `type=gha` cache was scoped per Git ref, so each release
tag created a new cache scope and never reused a previous release's
layers. Add to that GHA's 10 GB per-repo limit (which we already hit at
~10 GB before the v0.2.26 release), and the cache effectively never
helped consecutive releases.

Move to `type=registry` cache stored as separate `buildcache-<variant>`
tags on the same GHCR package. Branch/tag-independent, no LRU eviction,
unlimited size for our purposes. Standard pattern for multi-arch
buildx + multi-registry publishes.

Per-variant cache tag (`buildcache-slim`, `buildcache-full`) so the two
variants don't evict each other's layers.

`mode=max` exports all intermediate layers, not just the final ones —
needed for the per-RUN-layer reuse strategy in the Dockerfile.

Also cleaned up 23 orphaned GHA cache entries on the deleted
g/docker-layer-cache-v2 branch (3.4 GB freed).
v0.2.27
2026-04-14 18:13:09 -07:00
Jiangzhou 00ae2d2d6d perf(docker): single-stage with cache-friendly layer ordering (#139)
Reshape the Dockerfile so heavy deps live in a stable early layer (digest
reproducible across releases, users cache it) and per-release cocoindex +
cocoindex-code installs land in their own small layer at the end. Cuts
the per-release `docker pull` from ~5 GB to ~470 MB.

Specifically:
- Drop the multi-stage builder/model_cache layout; do everything in one
  runtime image so each install RUN produces its own distinct layer.
  BuildKit COPY in a multi-stage emits the full copied tree as a layer
  (not a diff) — that's what made the previous two-COPY split bloat the
  image to ~10 GB without saving any pull cost.
- Order layers so per-release content (the source-tree-dependent install)
  is last; everything before reuses across releases.
- Use `RUN --mount=type=bind,source=.,target=/ccc-src,rw=true` instead of
  `COPY . /ccc-src` so hatch-vcs can write `_version.py` during the PEP 517
  build without persisting the source tree as a layer in the final image.

Image sizes: slim 534 MB (was 598 MB), full 5.77 GB (was 5.83 GB).
Per-release layer: 468 MB (uv install on top of pre-installed ST).
Verified: docker E2E suite passes (6 passed, 2 Linux-only skipped on macOS).
v0.2.26
2026-04-14 17:38:00 -07:00
Jiangzhou 6f84edca2e feat(docker): slim/full image variants + cached deps layer + [full] extra rename (#138)
* perf(docker): split install into stable deps + per-release layers; add GHA cache

Dockerfile previously installed cocoindex-code, cocoindex, torch,
sentence-transformers, and all transitive deps in one RUN. Any change to
the source tree (via COPY . /ccc-src) invalidated that single layer,
forcing a full re-install — ~1 GB of wheels for torch + friends — on
every release. Under QEMU for the arm64 cross-build this was slow
enough to be painful.

Split into two stages:
- `deps`: install cocoindex + cocoindex-code[default] from PyPI. Cache
  key is just the RUN command string, so this layer is reused across
  releases until we bump the pins.
- `builder`: overlay the release version via
  `CCC_INSTALL_SPEC=/ccc-src[default]` with `--no-deps
  --force-reinstall` — only the cocoindex-code package is touched; the
  heavy deps layer stays untouched.

Also add BuildKit layer cache (`type=gha`) to the publish-docker job so
the deps layer persists across workflow runs, not just within a single
build.

* feat(docker,packaging): slim/full image variants; rename [default]→[full] extra

Build two Docker image variants per release:
- slim (:latest, default) — ~450 MB. LiteLLM-only. cocoindex + cocoindex-code
  without sentence-transformers. Targets cloud-backed embeddings.
- full (:full)            — ~5 GB. Bundles sentence-transformers + torch +
  a pre-baked default model. Targets offline-ready local embeddings.

Dockerfile gains a CCC_VARIANT build arg that gates stage 1's
sentence-transformers install and stage 3's model bake. Release workflow
matrices on {slim, full}; each variant has its own GHA cache scope so
layer reuse works across releases without the variants evicting each
other.

Also rename the PyPI `[default]` umbrella extra to `[full]` so pip and
Docker names match. `[embeddings-local]` remains the canonical primary
extra (the one that specifically pulls in sentence-transformers); `[full]`
is its umbrella alias that may bundle additional optional niceties later.
CLI hints that point at missing sentence-transformers continue to name
`[embeddings-local]` directly — the most specific pointer for that case.

README documents both image variants with a comparison table and narrows
the Mac-on-Docker MPS note to only :full users (slim + LiteLLM is
unaffected).
2026-04-14 16:25:42 -07:00
Jiangzhou 745dcd6875 feat(ci): build multi-arch Docker image (linux/amd64 + linux/arm64) (#137)
Adds QEMU setup and the `platforms: linux/amd64,linux/arm64` arg to the
build-push-action. Apple Silicon Macs and arm64 Linux hosts get a native
image (pulled automatically via manifest selection) instead of running
under QEMU emulation. amd64 users are unaffected.

Tradeoff: arm64 is cross-compiled via QEMU on the x86_64 runner, so
release builds are noticeably longer (the torch install + model bake
stage both run emulated). Acceptable at current release cadence; can
upgrade to a native arm64 runner matrix if it becomes painful.
2026-04-14 15:06:31 -07:00
Jiangzhou 4b98490aa2 fix(ci): build Docker image from local source and add test-dispatch (#136)
- Install cocoindex-code from the checked-out source tree (same build-arg
  used by local E2E tests) instead of pulling from PyPI. Avoids a race
  where the just-published wheel hadn't propagated to PyPI's CDN when
  publish-docker started, and ensures the image matches the tagged
  commit byte-for-byte.
- Add a `test_docker` workflow_dispatch input so registry credentials
  (Docker Hub + GHCR) can be verified before the next release without
  having to cut one. Dispatch pushes `:test` only; release pushes
  `:latest` + `:<version>`.
- Drop the needs: publish-to-pypi dependency — with local-source install
  we no longer need PyPI to be up-to-date first.
v0.2.25
2026-04-14 13:51:50 -07:00
Jiangzhou 92d611968e feat: unified Docker workspace mount with supervised daemon (#135)
* feat: unified Docker workspace mount with supervised daemon

Reshape the Docker experience around a single bind mount and a single
named volume. Global settings live on the host under
$HOME/.cocoindex_code/ (visible and editable); index data and the model
cache persist in one cocoindex-data volume; daemon runtime state stays
on the container's native filesystem.

CLI and MCP output now show host-side paths via a bidirectional
COCOINDEX_CODE_HOST_PATH_MAPPING translator. A shell wrapper that
forwards $PWD (COCOINDEX_CODE_HOST_CWD) lets ccc work from any project
subdirectory on the host.

The daemon tolerates a missing global_settings.yml (starts in
no-settings mode) so ccc init's interactive picker works in Docker on
first run. A supervisor restart loop in the entrypoint, driven by a new
COCOINDEX_CODE_DAEMON_SUPERVISED contract, makes settings-change
auto-restart safe — editing global_settings.yml triggers an in-place
daemon respawn without taking the container down.

Linux ownership alignment via PUID/PGID, gosu privilege drop, and a
coco user baked into the image. Release workflow now publishes to both
Docker Hub (cocoindex/cocoindex-code) and GHCR
(ghcr.io/cocoindex-io/cocoindex-code).

Also:
- Merge cocoindex-db and cocoindex-model-cache into a single volume
- find_parent_with_marker requires .cocoindex_code/settings.yml, so a
  workspace-root global-only dir doesn't trigger nested-init warnings
- New pytest marker `docker_e2e` gates the Docker-backed E2E suite
  (excluded from default pytest runs)

* fix: mypy on Windows for POSIX-only os.getuid/getgid calls
v0.2.24
2026-04-14 13:30:50 -07:00
Jiangzhou 0a8fb50312 docs: update ccc skill install + init guidance (#134)
Follow-up to #132: the skill's management.md still said `pipx install
cocoindex-code` and described `ccc init` as a purely non-interactive
command. Update to reflect:

- Two install styles — `[default]` (batteries included) vs bare
  (slim, LiteLLM-only).
- First-run `ccc init` is interactive; prompts for provider/model and
  runs a test embed via the daemon.
- `--litellm-model MODEL` flag for non-TTY / scripted use.
- Pointer to `ccc doctor` if the init model test fails.
2026-04-14 09:57:58 -07:00
Jiangzhou baa69ee56f ci: drop macOS 3.14t matrix cell (#133)
`tokenizers` (transitive via `litellm`) ships only `abi3` wheels, with
no free-threaded variant. On macOS arm64 runners since the early-Apr
image update, the source-build fallback fails to link against CPython
3.14t. Excluding the cell cleans up CI signal — end users on standard
Python 3.14 remain unaffected (they pick up the `abi3` wheel).

Ubuntu + 3.14t stays enabled (it still passes, via source build that
Linux's ld accepts). Re-enable macOS once HuggingFace/tokenizers ships
free-threaded wheels or litellm drops the dep.
2026-04-13 22:55:41 -07:00
Jiangzhou 5b6e3f5538 feat: make sentence-transformers optional; interactive ccc init (#132)
- Move `sentence-transformers` behind `[embeddings-local]` and `[default]`
  extras (via `cocoindex[sentence-transformers]`), so `pip install
  cocoindex-code` is LiteLLM-only. Closes #117.
- `ccc init` is now interactive when global settings don't exist: pick
  provider (sentence-transformers / litellm) and model via a
  questionary TUI. New `--litellm-model MODEL` flag skips prompts and
  is the non-TTY escape hatch for LiteLLM. Closes #70.
- Change the default sentence-transformers model from
  `all-MiniLM-L6-v2` to `Snowflake/snowflake-arctic-embed-xs`
  (lighter, better quality for code).
- Generated `global_settings.yml` now includes a `ccc doctor` reminder
  and commented-out env-var examples (OPENAI_API_KEY, GEMINI_API_KEY,
  ANTHROPIC_API_KEY, VOYAGE_API_KEY).
- Model test during init runs in the daemon via the existing
  `DoctorRequest` path; the daemon loads the model once and stays
  running, so the user's next `ccc index` starts warm.
- Docker image now installs `cocoindex-code[default]` and pre-caches
  the new default model. The `COCOINDEX_CODE_EMBEDDING_MODEL` env var
  is no longer documented for Docker; users mount a
  `global_settings.yml` or pass `--litellm-model`.
- Extract `check_embedding` + `EmbeddingCheckResult` into `shared.py`;
  refactor daemon `_check_model` to delegate. Error messages in doctor
  output now include the exception type name (strictly more
  informative).
- Tests switch to a lighter `paraphrase-MiniLM-L3-v2` model via a new
  `make_test_user_settings()` helper in `conftest.py`, leaving CI
  cache costs unchanged.
v0.2.23
2026-04-13 22:25:17 -07:00
Jiangzhou 49374cf4b5 chore: bump cocoindex to 1.0.0a43 (#131)
Update mount_each call to match the new API where component
subpath is passed as a positional argument instead of using a
context manager.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v0.2.22
2026-04-09 13:05:54 -07:00
Jiangzhou 21f858e840 refactor: extract daemon path helpers to avoid CLI importing cocoindex (#130)
* refactor: extract daemon path helpers to avoid CLI importing cocoindex

Move daemon_dir, daemon_socket_path, daemon_pid_path, daemon_log_path,
and connection_family from daemon.py into a new lightweight _daemon_paths.py
module. This prevents the CLI client from transitively importing cocoindex
and its heavy dependencies (numpy, torch, etc.) when it only needs path
utilities.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* ci: mark free-threaded Python CI jobs as continue-on-error

tokenizers lacks pre-built wheels for cp314t (free-threaded ABI),
so uv falls back to compiling from Rust source. This source build
is fragile across macOS runner image updates and broke after the
20260406 image bump. Mark 3.14t jobs as continue-on-error since
free-threaded wheel coverage across the ecosystem is still limited.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 12:38:52 -07:00
faysou 34565b47c3 Add a rate limiter for litellm (#125) v0.2.11 2026-04-05 19:03:26 -07:00
Jiangzhou c74e2ba0f2 chore: bump cocoindex to 1.0.0a38 (#121)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v0.2.10
2026-03-24 15:11:19 -07:00
Jiangzhou 8bbbc27b92 chore: bump cocoindex to 1.0.0a38 (#121)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 15:09:54 -07:00
Eli-Golin 12ca493b85 feat: add Docker support with persistent-container model (#66)
- docker/Dockerfile — multi-stage build (builder → model_cache →
    runtime);
    copies both `cocoindex-code` and `ccc` binaries; sets
    COCOINDEX_CODE_DB_PATH_MAPPING=/workspace=/db so index databases live
    in the container's native filesystem (avoids slow cross-OS volume I/O)
  - docker/entrypoint.sh — creates user settings on first start via
    `ccc init`, then runs `ccc run-daemon` in the foreground to keep the
    container alive as a persistent daemon
  - README — adds Docker section: persistent container as primary pattern
    (`docker run -d` + `docker exec`), named volumes for DB and model cache,
    Claude Code / Codex MCP configuration via `docker exec -i ... ccc mcp`
2026-03-23 19:10:08 -07:00
Jiangzhou a042bdc810 feat: add missing file extensions to DEFAULT_INCLUDED_PATTERNS (#119)
Add 19 file extensions from the supported languages table in README.md
that were missing from the default include patterns: Ruby, Swift, Kotlin,
Scala, R, HTML, CSS/SCSS, JSON, XML, YAML, TOML, Solidity, Pascal/Delphi,
DTD, and Fortran.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v0.2.9
2026-03-23 17:03:44 -07:00
Vasilii Alferov f2ecfb5df3 feat: pluggable chunker registry with settings integration (#105)
* chore: enable mypy explicit_package_bases, remove stale type: ignore comments

explicit_package_bases = true resolves module paths from the repo root,
preventing double-discovery of files in tests/ under different module names.
Required for tests/example_toml_chunker.py to be importable as
example_toml_chunker rather than an ambiguous bare module.

Also sets asyncio_mode = auto so pytest-asyncio behaviour is explicit
(default in 1.3.0 is strict).

With explicit_package_bases active, mypy can fully resolve the Response
union in test_daemon.py — the 16 type: ignore[union-attr] and
type: ignore[attr-defined] comments that were suppressing false positives
under the old resolution are now unused and removed.

# Conflicts:
#	tests/test_daemon.py

* feat: pluggable chunker registry with settings integration

Improves retrieval precision by letting users split specific file types at
semantic boundaries (e.g. TOML sections, SQL statements) instead of the
default line-window splitter.

## What

- cocoindex_code/chunking.py: public API module exporting ChunkerFn
  (Callable alias), CHUNKER_REGISTRY context key, and re-exports of
  Chunk/TextPosition from upstream. Single import path for chunker authors.

- tests/example_toml_chunker.py: demo chunker splitting at [section]
  headers; excludes [[array_of_tables]] via negative lookahead. Lives in
  tests/ to signal it belongs to a separate package, not the core library.

- ProjectSettings.chunkers: new list[ChunkerMapping] field, serialised as
  YAML. Each entry maps a file extension to a 'module.path:callable' string.
  Users activate chunkers by editing .cocoindex_code/settings.yml — no code
  changes required.

- daemon.py: _resolve_chunker_registry resolves ChunkerMapping entries via
  importlib at project load time and passes the result to Project.create().
  callable() guard gives a clear error at startup rather than a TypeError
  per file.

- Project.create(chunker_registry=...): new optional parameter. Injected as
  a cocoindex context key (tracked=False) rather than exposed via env internals.
  Empty registry by default — zero behavioural delta for existing users.

- indexer.py: process_file checks the registry per file suffix; falls through
  to RecursiveSplitter unchanged when no chunker is registered.

## Design decisions

- ChunkerFn returns (language_override, chunks): language_override=None keeps
  detect_code_language() result; non-None lets the chunker correct it (e.g.
  .sls files starting with #!py).

- tracked=False is consistent with SQLITE_DB, CODEBASE_DIR, and other
  non-serialisable context keys. Changing a chunker requires a daemon restart,
  which triggers a full re-index anyway.

- _resolve_chunker_registry lives in daemon.py, its only call site, keeping
  settings.py as pure schema/IO and chunking.py as pure type definitions.

# Conflicts:
#	src/cocoindex_code/daemon.py
#	src/cocoindex_code/indexer.py
#	src/cocoindex_code/project.py
#	tests/test_settings.py
2026-03-22 23:03:17 -07:00
Jiangzhou 9826fd153e refactor: consolidate hardcoded file paths into settings helpers (#118)
Add target_sqlite_db_path() and cocoindex_db_path() to settings.py as
the single source of truth for database paths, replacing scattered
hardcoded "target_sqlite.db" and "cocoindex.db" strings across cli.py,
daemon.py, project.py, and config.py. Also use daemon_log_path() for
daemon log references and project_settings_path() for settings file
references.

Remove config.py (unused legacy module) and its tests — no production
code imported it.

Add settings/index-db location display to `ccc status`.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 10:13:36 -07:00
Jiangzhou 33334bc996 feat: add COCOINDEX_CODE_DB_PATH_MAPPING for custom database locations (#116)
* feat: add COCOINDEX_CODE_DB_PATH_MAPPING for custom database locations

Allow remapping database file locations via environment variable, enabling
Docker deployments where databases live on the container's native filesystem
while source code is mounted from the host.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: use = delimiter for DB path mapping (avoid Windows colon conflict)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: use platform-agnostic tmp_path in DB mapping tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v0.2.8
2026-03-22 00:13:36 -07:00
Jiangzhou e1a66b0009 docs: add contributing guide with pre-commit hook setup (#115)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:07:01 -07:00
Jiangzhou 3066e02194 feat: handle setting file issues more gracefully (#114) v0.2.7 2026-03-21 10:31:14 -07:00
Jiangzhou 01556383a9 docs: update skill for ccc doctor subcommand (#112) 2026-03-20 21:43:34 -07:00
Jiangzhou 3706cf0315 docs: update README (#111) 2026-03-20 21:18:03 -07:00
Jiangzhou 05d38f2733 feat: ccc doctor and upgrade cocoindex version (#110) v0.2.6 2026-03-20 21:16:55 -07:00