codecortex 0.23.0__tar.gz → 0.23.2__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.
- {codecortex-0.23.0/src/codecortex.egg-info → codecortex-0.23.2}/PKG-INFO +163 -170
- {codecortex-0.23.0 → codecortex-0.23.2}/README.md +161 -169
- {codecortex-0.23.0 → codecortex-0.23.2}/pyproject.toml +1 -0
- {codecortex-0.23.0 → codecortex-0.23.2/src/codecortex.egg-info}/PKG-INFO +163 -170
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codecortex.egg-info/SOURCES.txt +3 -0
- codecortex-0.23.2/src/codeintel/__init__.py +1 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/__main__.py +25 -1
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/commands/index.py +26 -11
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/commands/status.py +38 -14
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/doctor.py +16 -3
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/gateway.py +16 -7
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/indexer.py +51 -6
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/mapper.py +26 -4
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/provider.py +35 -1
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/providers/graph.py +114 -7
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/providers/lsp.py +117 -7
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/providers/semantic.py +372 -25
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/reindexer.py +16 -2
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/searcher.py +56 -8
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/semantic_db.py +238 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/server.py +12 -2
- codecortex-0.23.2/tests/test_background_index_failure.py +546 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_bench_oracle.py +8 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_cli_commands.py +51 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_cli_help.py +11 -1
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_cold_process.py +4 -0
- codecortex-0.23.2/tests/test_could_not_ask_semantic.py +289 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_doctor.py +60 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_gateway.py +1 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_graph_failure_population.py +18 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_graph_provider.py +84 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_incompleteness.py +51 -0
- codecortex-0.23.2/tests/test_index_failure_reason.py +518 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_lsp_provider.py +144 -1
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_lsp_real.py +3 -2
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_mapper.py +54 -1
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_mcp_server.py +10 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_model_dimension.py +19 -1
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_never_raise.py +83 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_semantic_provider.py +30 -1
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_staleness.py +16 -0
- codecortex-0.23.0/src/codeintel/__init__.py +0 -1
- {codecortex-0.23.0 → codecortex-0.23.2}/LICENSE +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/setup.cfg +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codecortex.egg-info/dependency_links.txt +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codecortex.egg-info/entry_points.txt +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codecortex.egg-info/requires.txt +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codecortex.egg-info/top_level.txt +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/agent_prompt.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/auth.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/c4.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/c4_check.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/c4_layers.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/cache.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/commands/__init__.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/commands/_common.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/commands/c4.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/commands/doctor.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/commands/gen_token.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/commands/graph.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/commands/install.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/commands/map.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/commands/prompt.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/commands/query.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/commands/reset.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/commands/serve.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/commands/serve_http.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/commands/setup.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/config.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/containment.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/graph_backend.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/graph_render.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/graph_resolution.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/grapher.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/http_server.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/injector.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/installer.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/lang_config.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/loc.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/logconfig.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/metrics.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/onboarding.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/outcome.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/paths.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/policy.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/progress.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/providers/__init__.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/providers/none.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/py.typed +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/query_ops.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/redact.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/reset.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/source_kind.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/term.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/verify.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/viewer/__init__.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/viewer/graph_template.html +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/src/codeintel/wire_text.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_agent_prompt.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_backend_reaper.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_bench_oracle_ts.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_c4.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_c4_check.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_c4_layers.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_c4_model.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_c4_output.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_cache.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_chunking.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_cli_install_dry_run.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_cli_install_offer_injection.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_config.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_corpus.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_docs_ci_claims.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_docs_deadcode_withdrawal.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_e2e.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_edge_confidence.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_engine_adoption.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_enterprise.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_graph_real.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_graph_stdin.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_grapher.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_hard_exit.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_hardening.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_http_auth.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_http_server.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_index_progress.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_indexer_binary.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_installer.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_integration.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_lang_config.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_loc_census.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_lsp_language_coverage.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_mcp_handshake.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_null_reason_and_ripple.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_onboarding.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_rbac.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_redaction_boundary.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_reindexer.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_rerank.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_reset.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_source_kind.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_symbol_context.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_term.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_treesitter.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_verify.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_verify_call.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_version_skew.py +0 -0
- {codecortex-0.23.0 → codecortex-0.23.2}/tests/test_wire_text.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codecortex
|
|
3
|
-
Version: 0.23.
|
|
3
|
+
Version: 0.23.2
|
|
4
4
|
Summary: Local-first, MCP-native code-intelligence server — graph, LSP, and semantic search behind one safe code.query tool for coding agents.
|
|
5
5
|
Author: Shammai Hamilton
|
|
6
6
|
License-Expression: MIT
|
|
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
21
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
22
|
Classifier: Topic :: Software Development :: Quality Assurance
|
|
22
23
|
Classifier: Typing :: Typed
|
|
@@ -57,173 +58,19 @@ Dynamic: license-file
|
|
|
57
58
|
|
|
58
59
|
> *codeintel visualizing its own codebase.* One command — `codeintel graph <repo> --html` — turns any indexed repo into a **self-contained, interactive call graph** you can open offline or share as a file. Layouts, complexity-sized nodes, click-to-inspect metrics, and JSON/Markdown/SVG/PNG export. See **[docs/graph-viewer.md](docs/graph-viewer.md)**.
|
|
59
60
|
|
|
60
|
-
Prefer plain text? `codeintel map` writes a **readable architecture overview** to `CODE_INTEL.md` — node/edge counts, ranked symbols by caller count, and entry points — for skimming or for MCP hosts that can't render a graph:
|
|
61
|
-
|
|
62
|
-
<img src="docs/images/code-intel-map.png" width="520" alt="CODE_INTEL.md — the codeintel map: an architecture overview with node/edge counts and symbols ranked by caller count.">
|
|
63
|
-
|
|
64
|
-
**What `CODE_INTEL.md` is for.** It's a *static, committable* snapshot of a codebase's shape — meant to be read (by a person or an agent) **first**, instead of reconstructing structure by grepping. It covers the cases the live `code.query` tool doesn't:
|
|
65
|
-
|
|
66
|
-
- **Agents & hosts that don't speak MCP.** Not every agent supports MCP, and the server isn't always running. `codeintel map` writes a plain file any agent can read; `codeintel map --inject` also drops a short, tool-naming pointer block into `AGENTS.md` (the cross-tool surface read by Codex, Cursor, Zed, and others — created with your consent if it doesn't exist yet) plus a one-line `@AGENTS.md` import into `CLAUDE.md`, and writes the fuller `USING_CODEINTEL.md` guide the block points to — into **your** repo, which is why there is no such file to click here — so an agent knows to reach for `code.query` before it reaches for grep, not just that a `CODE_INTEL.md` exists.
|
|
67
|
-
- **A committed, diffable overview.** It lives *in the repo* — reviewable in a PR, browsable on GitHub, available offline. Re-run `codeintel map` after `codeintel index` to refresh it.
|
|
68
|
-
- **The load-bearing code at a glance.** Ranking symbols by caller count surfaces what most of the codebase depends on (the risky-to-change core) plus the entry points — the first things a newcomer, or an agent, should understand before touching anything. The ranking counts `CALLS` edges into **callable** nodes only (functions, methods, classes, interfaces, routes), and skips test, generated and archived files. Both constraints are load-bearing rather than tidy-up: without them a 12,638-node TypeScript repo ranked `logger` (a *folder* node) at 716 and `onClick` at 107, and a Python repo ranked YAML and JSON keys — `flow` from a `.flow.yaml`, `feature` from a `.schema.json` — as its most depended-on symbols. This repo's own map is Python-heavy and barely showed it, which is exactly why dogfooding did not catch it.
|
|
69
|
-
|
|
70
|
-
See **[docs/map-file.md](docs/map-file.md)** for the format and the `--inject` flow.
|
|
71
|
-
|
|
72
|
-
## Why an agent needs it
|
|
73
|
-
|
|
74
|
-
Without structural tools, an agent dropped into unfamiliar code falls back on `grep` and reads whole files to reconstruct relationships by hand — burning tokens, missing call sites, and guessing at blast radius before it edits anything. codeintel answers those questions directly instead:
|
|
75
|
-
|
|
76
|
-
- **"What calls this? What breaks if I change it?"** → the real call graph, which catches cross-file and module-level callers a text search silently misses.
|
|
77
|
-
- **"Where is this symbol defined, and everywhere it's used?"** → the language server, with exact locations.
|
|
78
|
-
- **"Where's the code that does X?"** (when you don't know the name) → semantic search over the repo.
|
|
79
|
-
- **Always a clean answer.** Every call returns the same JSON envelope. A missing or broken backend degrades to a safe `null` *with a reason* — so the agent falls back to grep instead of crashing on an exception it can't reason its way out of.
|
|
80
|
-
|
|
81
|
-
Net effect: fewer, sharper tool calls, less re-reading, and an agent that can see *structure* — callers, impact, call chains — that plain search can't.
|
|
82
|
-
|
|
83
|
-
**The honest framing.** Agentic grep is still the backbone, and codeintel doesn't claim otherwise — Claude Code itself ships grep-only and that is a reasonable default for most of what an agent reads. The defensible claim is narrower: a structural index *where it pays*, degrading to grep the moment an engine is missing or not indexed, which is exactly what the safe-null contract above already does under the hood. Worth saying explicitly rather than leaving it implicit in a failure mode.
|
|
84
|
-
|
|
85
|
-
## What your agent can ask
|
|
86
|
-
|
|
87
|
-
It's one call: `code.query(op, target, engine="auto")`. In `auto` mode (the default) codeintel picks the engine per operation:
|
|
88
|
-
|
|
89
|
-
| Ask | `op` | Engine (auto) | Comes back as |
|
|
90
|
-
|---|---|---|---|
|
|
91
|
-
| Find code by meaning ("auth middleware") | `search` | semantic | ranked `path:line │ snippet` hits |
|
|
92
|
-
| A symbol's definition **and** all references | `symbol` | lsp | definition body + reference list |
|
|
93
|
-
| Who calls this? | `callers` | graph | caller symbols + files |
|
|
94
|
-
| What does this call? | `callees` | graph | callee symbols + files |
|
|
95
|
-
| Blast radius of a change | `impact` | graph | callers **and** callees together |
|
|
96
|
-
| Trace a call chain up/downstream | `chain` | graph | ordered hops, each labelled with how it was resolved |
|
|
97
|
-
| Find symbols by pattern | `pattern` | graph | matching nodes + locations |
|
|
98
|
-
| Project shape at a glance | `overview` | graph → lsp | modules, node/edge counts, languages |
|
|
99
|
-
| Everything about one symbol | `context` | graph + lsp | both views merged |
|
|
100
|
-
| **Impact of your uncommitted edits** | `changed` | graph | changed files → impacted symbols |
|
|
101
|
-
| Refactor-risk hotspots | `hotspots` | graph | highest complexity / fan-in symbols |
|
|
102
|
-
| Unreferenced (dead) code | `deadcode` | graph | **withdrawn and now retired** — a labelled corpus measured its precision at 25%; safe-nulls with `reason: "op-withdrawn"`, and no flag brings it back — [the measurement, and what to use instead](#deadcode-is-retired) |
|
|
103
|
-
|
|
104
|
-
Pin one engine with `--engine graph│lsp│semantic`, or fan out with `--engine both` / `all` to merge results.
|
|
105
|
-
|
|
106
|
-
`callers`, `callees` and `impact` resolve the target by its **unqualified name**. When several
|
|
107
|
-
symbols share it, each matched symbol's rows are reported separately under its own heading and the
|
|
108
|
-
result says how many it found — narrow to one with a qualified target (`core.Group.invoke`) or a file
|
|
109
|
-
hint (`invoke@src/click/testing.py`); see
|
|
110
|
-
[when several symbols share a name](docs/graph.md#when-several-symbols-share-a-name).
|
|
111
|
-
|
|
112
|
-
#### `deadcode` is retired
|
|
113
|
-
|
|
114
|
-
`deadcode` no longer exists. Asking for it returns a safe-null (`reason: "op-withdrawn"`) with a hint
|
|
115
|
-
naming what to use instead, and **no flag brings it back** — the implementation has been deleted.
|
|
116
|
-
|
|
117
|
-
It was withdrawn pending one condition: *"it returns when a labelled corpus measures its precision
|
|
118
|
-
and recall — not before."* That corpus now exists, in
|
|
119
|
-
[`tests/test_corpus.py`](tests/test_corpus.py), and the measurement is what retired it.
|
|
120
|
-
|
|
121
|
-
**How it was measured.** Two pinned real Python repositories (`pallets/click`, `psf/requests`), with
|
|
122
|
-
every function and method collected from the **AST** — 2,425 definitions, `async def` and class
|
|
123
|
-
methods included, because a verification whose population comes from a pattern like `^\s*def ` cannot
|
|
124
|
-
see half of them. Each is labelled live or dead with the reference behind the label recorded beside
|
|
125
|
-
it. The oracle errs toward *live*: a decorator, a dunder, an override of an external interface, a
|
|
126
|
-
string-dispatch mention, or public-API status is each enough to call a symbol live, so "dead" is only
|
|
127
|
-
what survives all of them. That biases the numbers against the op, which is the correct direction for
|
|
128
|
-
a check whose output is an instruction to delete code. Known-answer canaries are planted in both trees
|
|
129
|
-
so recall has a denominator at all.
|
|
130
|
-
|
|
131
|
-
**The numbers.**
|
|
132
|
-
|
|
133
|
-
| | precision | recall |
|
|
134
|
-
|---|---|---|
|
|
135
|
-
| as shipped | **25%** (6 of 24) | 60% (6 of 10) |
|
|
136
|
-
| with the two repairs this codebase already contains elsewhere | 89% (8 of 9) | 80% (8 of 10) |
|
|
137
|
-
|
|
138
|
-
And the measurement that decided it — **real code only, canaries removed**: the op as shipped named
|
|
139
|
-
**18 candidates across those two repositories, and every one of them was live.** All 18 were Makefile
|
|
140
|
-
targets, which the graph backend indexes as `Function` nodes. Repaired, it names exactly one, and
|
|
141
|
-
that one is `MockRequest.get_type` in requests — a method `http.cookiejar` calls by duck-typed
|
|
142
|
-
convention, whose name appears once in the source.
|
|
143
|
-
|
|
144
|
-
**Why it was not repaired further.** The verification was a name-frequency scan over the source, so it
|
|
145
|
-
fails on exactly one condition: a symbol whose name appears once and is called by a convention
|
|
146
|
-
outside the source. Two repositories produced three distinct instances of that condition — non-code
|
|
147
|
-
nodes labelled `Function`, interpreter-called dunders, and stdlib duck-typed protocol methods — and
|
|
148
|
-
the earlier TypeScript evidence adds a rollup plugin hook and object-literal properties. The set is
|
|
149
|
-
not enumerable: no specification lists `get_type`. Every repository added revealed a new member of it.
|
|
150
|
-
|
|
151
|
-
Weighed against that: in 2,425 real definitions across two maintained repositories there was **not
|
|
152
|
-
one** dead private symbol to find. An op whose measured yield on real code is zero true positives has
|
|
153
|
-
no benefit to set against that error rate.
|
|
154
|
-
|
|
155
|
-
**Use `callers` on a specific symbol instead.** "Does anything call this?" is exactly the question
|
|
156
|
-
`deadcode` was trying to answer in bulk, and `callers` answers it accurately, one symbol at a time.
|
|
157
|
-
|
|
158
|
-
## An architecture model, as source
|
|
159
|
-
|
|
160
|
-
`codeintel c4` turns the graph index into a [LikeC4](https://likec4.dev) model — architecture-as-code
|
|
161
|
-
you can commit, diff and hand-edit, rather than a rendered picture you have to regenerate to read.
|
|
162
|
-
Abridged output, from `--scope src/codeintel/providers`:
|
|
163
|
-
|
|
164
|
-
```
|
|
165
|
-
// Generated by codeintel from the graph index — do not edit by hand.
|
|
166
|
-
// edges: union of IMPORTS (static module-level imports) and CALLS|USAGE (call/usage references)
|
|
167
|
-
// coverage is NOT complete: dispatch through a name/lookup table can still be invisible to both
|
|
168
|
-
// hotspot ranking uses IMPORTS-only fan-in, never the CALLS|USAGE union
|
|
169
|
-
|
|
170
|
-
model {
|
|
171
|
-
src = area 'src' {
|
|
172
|
-
codeintel = area 'codeintel' {
|
|
173
|
-
providers = area 'providers' {
|
|
174
|
-
lsp = module 'lsp' {
|
|
175
|
-
technology 'Python'
|
|
176
|
-
metadata { path 'src/codeintel/providers/lsp.py' churn '12' fan_out '2' }
|
|
177
|
-
}
|
|
178
|
-
graph = module 'graph' { /* … */ }
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
src.codeintel.providers.lsp -[calls_usage]-> src.codeintel.providers.graph { metadata { n '2' } }
|
|
184
|
-
}
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
Directories become `area`, files become `module`, and every element carries its real path plus churn
|
|
188
|
-
and fan-in as `metadata` — so the model is queryable, not only drawable. Each file opens with what it
|
|
189
|
-
cannot know: which edge sources it used, that coverage is incomplete, and how many references were
|
|
190
|
-
folded or dropped. `npx likec4 start codeintel-c4` renders it; nothing else here needs Node.
|
|
191
|
-
|
|
192
|
-
**Two edge sources, and the choice matters more than it sounds.** The default unions static `IMPORTS`
|
|
193
|
-
with `CALLS|USAGE`, which recovers lazy and function-body imports. On this repo at
|
|
194
|
-
`--scope src --depth 3` that is 179 relations — **134 of them `CALLS|USAGE`-only**, which renders as a
|
|
195
|
-
hairball. `--edges imports` leaves the same 45 elements with 45 edges: legible, and roughly layered,
|
|
196
|
-
because every remaining edge descends.
|
|
197
|
-
|
|
198
|
-
**It also answers two questions without drawing anything.** `--layers` infers architectural bands
|
|
199
|
-
from the import graph — 7 bands over 35 of those 45 elements, the other 10 having no module-level
|
|
200
|
-
import edge either way. `--check` gates CI on a declared
|
|
201
|
-
`[layers]` block in `.codeintel.toml`, exiting **2** on architectural drift — deliberately distinct
|
|
202
|
-
from exit 1 for a broken run, so a CI step can tell "your architecture drifted" from "codeintel is
|
|
203
|
-
broken". A config generated by `--suggest-config` is a *provably* green baseline on the commit that
|
|
204
|
-
produced it, so adoption is paste-confirm-tighten rather than a wall of false positives.
|
|
205
|
-
|
|
206
|
-
Full reference: **[docs/c4.md](docs/c4.md)**. Why LikeC4 and not something else, measured:
|
|
207
|
-
[docs/eval-2026-08-26-likec4.md](docs/eval-2026-08-26-likec4.md).
|
|
208
|
-
|
|
209
|
-
## What makes it good
|
|
210
|
-
|
|
211
|
-
- **Local-first and private.** One process on your machine — no cloud service, no API keys, no telemetry, no per-query network. Safe to point at a private repo, even with `--engine all`. (The one-time exception: `fastembed` downloads its embedding model once, then runs fully offline.)
|
|
212
|
-
- **It never throws.** Every call returns the same JSON envelope; a missing or broken backend degrades to `null` *with a reason*. No exceptions, no 500s, no malformed output for the agent to trip over — so you never wrap `code.query` in a `try`.
|
|
213
|
-
- **One tool, not three.** Register a single MCP server and it auto-routes each question to graph, LSP, or semantic — instead of wiring up three backends with three response shapes and three failure modes.
|
|
214
|
-
- **Degrades instead of breaking.** No graph backend installed? That engine returns `null` and the agent falls back to grep. The semantic engine needs nothing external, so codeintel is useful the moment it's installed and only gets sharper as you add backends.
|
|
215
|
-
- **Fast on repeat, and the cache never lies.** A content-hash cache returns instantly for unchanged code and self-invalidates when a background reindex advances the index, so you never read a cached answer for code that moved on. The cache is bounded (LRU), so a long-running server holds steady memory. (The *cache* is always consistent with the index; how current the index itself is depends on the engine — see [Keeping answers fresh](#keeping-answers-fresh).)
|
|
216
|
-
- **Concurrency-safe.** The HTTP transport handles requests on threads, so one slow query (an LSP session warming, a first-time index) can't block every other agent.
|
|
217
|
-
- **Honest about its own health.** `codeintel doctor` answers three separate questions per engine — *installed?* *runnable?* *is this repo indexed?* — with the single command to fix each gap, so "installed" is never mistaken for "working". And a readiness claim is one a query can actually honor: install a missing backend mid-session and the running server picks it up on the next call, rather than reporting the engine healthy while quietly routing around it until you restart the host.
|
|
218
|
-
|
|
219
61
|
## Quickstart
|
|
220
62
|
|
|
221
63
|
```bash
|
|
222
64
|
pip install codecortex
|
|
223
65
|
```
|
|
224
66
|
|
|
225
|
-
This installs the `codeintel` CLI; the **semantic** engine works out of the box
|
|
226
|
-
|
|
67
|
+
This installs the `codeintel` CLI; the **semantic** engine works out of the box — with one
|
|
68
|
+
network step: `fastembed` downloads its ~50 MB embedding model from `huggingface.co` the first
|
|
69
|
+
time you index, then runs fully offline. Behind a corporate proxy, in restricted CI, or
|
|
70
|
+
air-gapped, that download is the one thing here that can fail — see
|
|
71
|
+
[Offline / air-gapped install](docs/install.md#offline--air-gapped-install) for the
|
|
72
|
+
`FASTEMBED_CACHE_PATH` workaround. (On PyPI the distribution is `codecortex` because `codeintel`
|
|
73
|
+
was taken; the CLI and import stay `codeintel`.)
|
|
227
74
|
|
|
228
75
|
**One command prepares the rest and indexes your repo:**
|
|
229
76
|
|
|
@@ -237,19 +84,34 @@ remaining step. It's idempotent, so re-running is safe. The **graph** engine (`c
|
|
|
237
84
|
is an *optional* external binary that adds who-calls / impact / hotspots / `changed`; codeintel is
|
|
238
85
|
fully usable without it.
|
|
239
86
|
|
|
240
|
-
|
|
87
|
+
**Then verify, before trusting an answer.** `doctor` answers three separate questions per engine —
|
|
88
|
+
*installed?* *runnable?* *is this repo indexed?* — so "installed" is never mistaken for "working",
|
|
89
|
+
and names the one command that fixes each gap:
|
|
241
90
|
|
|
242
91
|
```bash
|
|
243
|
-
|
|
244
|
-
cd codeintel
|
|
245
|
-
pip install -e .
|
|
92
|
+
codeintel doctor
|
|
246
93
|
```
|
|
247
94
|
|
|
248
|
-
Register with your
|
|
95
|
+
**Register with your agent, and ask it something grep cannot answer:**
|
|
249
96
|
|
|
250
97
|
```bash
|
|
251
98
|
codeintel install # registers with the agents you actually have installed
|
|
252
|
-
codeintel query --op
|
|
99
|
+
codeintel query --op callers --target aFunctionYouKnow
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
`callers` is the first query worth running because you can check it by eye: it should name the call
|
|
103
|
+
sites you already know about, including cross-file and module-level ones a text search misses. If
|
|
104
|
+
the graph engine isn't installed it safe-nulls with a reason and a hint rather than failing — that
|
|
105
|
+
is the contract, visible on your first call. `--op search --target "authentication middleware"`
|
|
106
|
+
works with no backend at all, but a semantic hit on an unfamiliar repo is harder to judge, which
|
|
107
|
+
makes it the weaker thing to try first.
|
|
108
|
+
|
|
109
|
+
Or from source:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
git clone https://github.com/hamilton-sky/codeintel.git
|
|
113
|
+
cd codeintel
|
|
114
|
+
pip install -e .
|
|
253
115
|
```
|
|
254
116
|
|
|
255
117
|
### Or: have your agent set it up
|
|
@@ -351,6 +213,136 @@ against the built wheel in a clean environment: it registers Codex and Claude Co
|
|
|
351
213
|
> Full reference — what each host reads, the absolute-path rationale, and troubleshooting:
|
|
352
214
|
> **[docs/install.md](docs/install.md)**.
|
|
353
215
|
|
|
216
|
+
## Why an agent needs it
|
|
217
|
+
|
|
218
|
+
Without structural tools, an agent dropped into unfamiliar code falls back on `grep` and reads whole files to reconstruct relationships by hand — burning tokens, missing call sites, and guessing at blast radius before it edits anything. codeintel answers those questions directly instead:
|
|
219
|
+
|
|
220
|
+
- **"What calls this? What breaks if I change it?"** → the real call graph, which catches cross-file and module-level callers a text search silently misses.
|
|
221
|
+
- **"Where is this symbol defined, and everywhere it's used?"** → the language server, with exact locations.
|
|
222
|
+
- **"Where's the code that does X?"** (when you don't know the name) → semantic search over the repo.
|
|
223
|
+
- **Always a clean answer.** Every call returns the same JSON envelope. A missing or broken backend degrades to a safe `null` *with a reason* — so the agent falls back to grep instead of crashing on an exception it can't reason its way out of.
|
|
224
|
+
|
|
225
|
+
Net effect: fewer, sharper tool calls, less re-reading, and an agent that can see *structure* — callers, impact, call chains — that plain search can't.
|
|
226
|
+
|
|
227
|
+
**The honest framing.** Agentic grep is still the backbone, and codeintel doesn't claim otherwise — Claude Code itself ships grep-only and that is a reasonable default for most of what an agent reads. The defensible claim is narrower: a structural index *where it pays*, degrading to grep the moment an engine is missing or not indexed, which is exactly what the safe-null contract above already does under the hood. Worth saying explicitly rather than leaving it implicit in a failure mode.
|
|
228
|
+
|
|
229
|
+
## What your agent can ask
|
|
230
|
+
|
|
231
|
+
It's one call: `code.query(op, target, engine="auto")`. In `auto` mode (the default) codeintel picks the engine per operation:
|
|
232
|
+
|
|
233
|
+
| Ask | `op` | Engine (auto) | Comes back as |
|
|
234
|
+
|---|---|---|---|
|
|
235
|
+
| Find code by meaning ("auth middleware") | `search` | semantic | ranked `path:line │ snippet` hits |
|
|
236
|
+
| A symbol's definition **and** all references | `symbol` | lsp | definition body + reference list |
|
|
237
|
+
| Who calls this? | `callers` | graph | caller symbols + files |
|
|
238
|
+
| What does this call? | `callees` | graph | callee symbols + files |
|
|
239
|
+
| Blast radius of a change | `impact` | graph | callers **and** callees together |
|
|
240
|
+
| Trace a call chain up/downstream | `chain` | graph | ordered hops, each labelled with how it was resolved |
|
|
241
|
+
| Find symbols by pattern | `pattern` | graph | matching nodes + locations |
|
|
242
|
+
| Project shape at a glance | `overview` | graph → lsp | modules, node/edge counts, languages |
|
|
243
|
+
| Everything about one symbol | `context` | graph + lsp | both views merged |
|
|
244
|
+
| **Impact of your uncommitted edits** | `changed` | graph | changed files → impacted symbols |
|
|
245
|
+
| Refactor-risk hotspots | `hotspots` | graph | highest complexity / fan-in symbols |
|
|
246
|
+
| Unreferenced (dead) code | `deadcode` | graph | **withdrawn and now retired** — a labelled corpus measured its precision at 25%; safe-nulls with `reason: "op-withdrawn"`, and no flag brings it back — [the measurement, and what to use instead](#deadcode-is-retired) |
|
|
247
|
+
|
|
248
|
+
Pin one engine with `--engine graph│lsp│semantic`, or fan out with `--engine both` / `all` to merge results.
|
|
249
|
+
|
|
250
|
+
`callers`, `callees` and `impact` resolve the target by its **unqualified name**. When several
|
|
251
|
+
symbols share it, each matched symbol's rows are reported separately under its own heading and the
|
|
252
|
+
result says how many it found — narrow to one with a qualified target (`core.Group.invoke`) or a file
|
|
253
|
+
hint (`invoke@src/click/testing.py`); see
|
|
254
|
+
[when several symbols share a name](docs/graph.md#when-several-symbols-share-a-name).
|
|
255
|
+
|
|
256
|
+
#### `deadcode` is retired
|
|
257
|
+
|
|
258
|
+
`deadcode` no longer exists. Asking for it returns a safe-null (`reason: "op-withdrawn"`) with a
|
|
259
|
+
hint naming what to use instead, and **no flag brings it back** — the implementation has been
|
|
260
|
+
deleted. A labelled corpus of 2,425 AST-collected definitions across `pallets/click` and
|
|
261
|
+
`psf/requests` measured it at **25% precision**, and on real code with the canaries removed it
|
|
262
|
+
named 18 candidates of which **every one was live**.
|
|
263
|
+
|
|
264
|
+
**Use `callers` on a specific symbol instead.** "Does anything call this?" is exactly the question
|
|
265
|
+
`deadcode` was trying to answer in bulk, and `callers` answers it accurately, one symbol at a time.
|
|
266
|
+
|
|
267
|
+
The full measurement — the oracle's design, why it errs toward *live*, the two repairs that would
|
|
268
|
+
take it to 89%, and why it was not repaired further — is
|
|
269
|
+
[ADR 0002](docs/adr/0002-retire-deadcode.md).
|
|
270
|
+
|
|
271
|
+
## A committed architecture overview
|
|
272
|
+
|
|
273
|
+
Prefer plain text? `codeintel map` writes a **readable architecture overview** to `CODE_INTEL.md` — node/edge counts, ranked symbols by caller count, and entry points — for skimming or for MCP hosts that can't render a graph:
|
|
274
|
+
|
|
275
|
+
<img src="docs/images/code-intel-map.png" width="520" alt="CODE_INTEL.md — the codeintel map: an architecture overview with node/edge counts and symbols ranked by caller count.">
|
|
276
|
+
|
|
277
|
+
**What `CODE_INTEL.md` is for.** It's a *static, committable* snapshot of a codebase's shape — meant to be read (by a person or an agent) **first**, instead of reconstructing structure by grepping. It covers the cases the live `code.query` tool doesn't:
|
|
278
|
+
|
|
279
|
+
- **Agents & hosts that don't speak MCP.** Not every agent supports MCP, and the server isn't always running. `codeintel map` writes a plain file any agent can read; `codeintel map --inject` also drops a short, tool-naming pointer block into `AGENTS.md` (the cross-tool surface read by Codex, Cursor, Zed, and others — created with your consent if it doesn't exist yet) plus a one-line `@AGENTS.md` import into `CLAUDE.md`, and writes the fuller `USING_CODEINTEL.md` guide the block points to — into **your** repo, which is why there is no such file to click here — so an agent knows to reach for `code.query` before it reaches for grep, not just that a `CODE_INTEL.md` exists.
|
|
280
|
+
- **A committed, diffable overview.** It lives *in the repo* — reviewable in a PR, browsable on GitHub, available offline. Re-run `codeintel map` after `codeintel index` to refresh it.
|
|
281
|
+
- **The load-bearing code at a glance.** Ranking symbols by caller count surfaces what most of the codebase depends on (the risky-to-change core) plus the entry points — the first things a newcomer, or an agent, should understand before touching anything. The ranking counts `CALLS` edges into **callable** nodes only (functions, methods, classes, interfaces, routes), and skips test, generated and archived files. Both constraints are load-bearing rather than tidy-up: without them a 12,638-node TypeScript repo ranked `logger` (a *folder* node) at 716 and `onClick` at 107, and a Python repo ranked YAML and JSON keys — `flow` from a `.flow.yaml`, `feature` from a `.schema.json` — as its most depended-on symbols. This repo's own map is Python-heavy and barely showed it, which is exactly why dogfooding did not catch it.
|
|
282
|
+
|
|
283
|
+
See **[docs/map-file.md](docs/map-file.md)** for the format and the `--inject` flow.
|
|
284
|
+
|
|
285
|
+
## An architecture model, as source
|
|
286
|
+
|
|
287
|
+
`codeintel c4` turns the graph index into a [LikeC4](https://likec4.dev) model — architecture-as-code
|
|
288
|
+
you can commit, diff and hand-edit, rather than a rendered picture you have to regenerate to read.
|
|
289
|
+
Abridged output, from `--scope src/codeintel/providers`:
|
|
290
|
+
|
|
291
|
+
```
|
|
292
|
+
// Generated by codeintel from the graph index — do not edit by hand.
|
|
293
|
+
// edges: union of IMPORTS (static module-level imports) and CALLS|USAGE (call/usage references)
|
|
294
|
+
// coverage is NOT complete: dispatch through a name/lookup table can still be invisible to both
|
|
295
|
+
// hotspot ranking uses IMPORTS-only fan-in, never the CALLS|USAGE union
|
|
296
|
+
|
|
297
|
+
model {
|
|
298
|
+
src = area 'src' {
|
|
299
|
+
codeintel = area 'codeintel' {
|
|
300
|
+
providers = area 'providers' {
|
|
301
|
+
lsp = module 'lsp' {
|
|
302
|
+
technology 'Python'
|
|
303
|
+
metadata { path 'src/codeintel/providers/lsp.py' churn '12' fan_out '2' }
|
|
304
|
+
}
|
|
305
|
+
graph = module 'graph' { /* … */ }
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
src.codeintel.providers.lsp -[calls_usage]-> src.codeintel.providers.graph { metadata { n '2' } }
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Directories become `area`, files become `module`, and every element carries its real path plus churn
|
|
315
|
+
and fan-in as `metadata` — so the model is queryable, not only drawable. Each file opens with what it
|
|
316
|
+
cannot know: which edge sources it used, that coverage is incomplete, and how many references were
|
|
317
|
+
folded or dropped. `npx likec4 start codeintel-c4` renders it; nothing else here needs Node.
|
|
318
|
+
|
|
319
|
+
**Two edge sources, and the choice matters more than it sounds.** The default unions static `IMPORTS`
|
|
320
|
+
with `CALLS|USAGE`, which recovers lazy and function-body imports. On this repo at
|
|
321
|
+
`--scope src --depth 3` that is 179 relations — **134 of them `CALLS|USAGE`-only**, which renders as a
|
|
322
|
+
hairball. `--edges imports` leaves the same 45 elements with 45 edges: legible, and roughly layered,
|
|
323
|
+
because every remaining edge descends.
|
|
324
|
+
|
|
325
|
+
**It also answers two questions without drawing anything.** `--layers` infers architectural bands
|
|
326
|
+
from the import graph — 7 bands over 35 of those 45 elements, the other 10 having no module-level
|
|
327
|
+
import edge either way. `--check` gates CI on a declared
|
|
328
|
+
`[layers]` block in `.codeintel.toml`, exiting **2** on architectural drift — deliberately distinct
|
|
329
|
+
from exit 1 for a broken run, so a CI step can tell "your architecture drifted" from "codeintel is
|
|
330
|
+
broken". A config generated by `--suggest-config` is a *provably* green baseline on the commit that
|
|
331
|
+
produced it, so adoption is paste-confirm-tighten rather than a wall of false positives.
|
|
332
|
+
|
|
333
|
+
Full reference: **[docs/c4.md](docs/c4.md)**. Why LikeC4 and not something else, measured:
|
|
334
|
+
[docs/eval-2026-08-26-likec4.md](docs/eval-2026-08-26-likec4.md).
|
|
335
|
+
|
|
336
|
+
## What makes it good
|
|
337
|
+
|
|
338
|
+
- **Local-first and private.** One process on your machine — no cloud service, no API keys, no telemetry, no per-query network. Safe to point at a private repo, even with `--engine all`. (The one-time exception: `fastembed` downloads its embedding model once, then runs fully offline.)
|
|
339
|
+
- **It never throws.** Every call returns the same JSON envelope; a missing or broken backend degrades to `null` *with a reason*. No exceptions, no 500s, no malformed output for the agent to trip over — so you never wrap `code.query` in a `try`.
|
|
340
|
+
- **One tool, not three.** Register a single MCP server and it auto-routes each question to graph, LSP, or semantic — instead of wiring up three backends with three response shapes and three failure modes.
|
|
341
|
+
- **Degrades instead of breaking.** No graph backend installed? That engine returns `null` and the agent falls back to grep. The semantic engine needs nothing external, so codeintel is useful the moment it's installed and only gets sharper as you add backends.
|
|
342
|
+
- **Fast on repeat, and the cache never lies.** A content-hash cache returns instantly for unchanged code and self-invalidates when a background reindex advances the index, so you never read a cached answer for code that moved on. The cache is bounded (LRU), so a long-running server holds steady memory. (The *cache* is always consistent with the index; how current the index itself is depends on the engine — see [Keeping answers fresh](#keeping-answers-fresh).)
|
|
343
|
+
- **Concurrency-safe.** The HTTP transport handles requests on threads, so one slow query (an LSP session warming, a first-time index) can't block every other agent.
|
|
344
|
+
- **Honest about its own health.** `codeintel doctor` answers three separate questions per engine — *installed?* *runnable?* *is this repo indexed?* — with the single command to fix each gap, so "installed" is never mistaken for "working". And a readiness claim is one a query can actually honor: install a missing backend mid-session and the running server picks it up on the next call, rather than reporting the engine healthy while quietly routing around it until you restart the host.
|
|
345
|
+
|
|
354
346
|
## How it works
|
|
355
347
|
|
|
356
348
|
A `Gateway` receives every query and dispatches it to one of three providers — graph (structural relationships), LSP (precise symbol resolution), or semantic (embedding-based search) — based on the operation type. Each provider is fully isolated: if it is unavailable or raises an exception, the gateway catches it and returns a safe-null envelope. The caller always gets a well-formed response with no exception to catch.
|
|
@@ -542,7 +534,7 @@ Register codeintel as an MCP server (`codeintel install`) and the agent gets fou
|
|
|
542
534
|
| MCP tool | HTTP equivalent | Purpose |
|
|
543
535
|
|---|---|---|
|
|
544
536
|
| `code.query` | `POST /code/query` | The main call — search, trace, understand (the `op` table above) |
|
|
545
|
-
| `code.status` | `GET /code/status` | Per-engine `installed` / `runnable` / `repo_indexed
|
|
537
|
+
| `code.status` | `GET /code/status` | Per-engine `installed` / `runnable` / `repo_indexed` (plus `model_cached` for semantic), probed against the live engines a query actually hits |
|
|
546
538
|
| `code.doctor` | `POST /code/doctor` | Per-engine health + repo index status, with a fix for each gap |
|
|
547
539
|
| `code.map` | — | Generate/refresh `CODE_INTEL.md`, a static orientation file for hosts without MCP |
|
|
548
540
|
|
|
@@ -648,7 +640,8 @@ answer — and `deadcode` in particular is retired rather than merely caveated (
|
|
|
648
640
|
something looks off please [report it](#reporting-a-problem) — an issue from someone who is not the
|
|
649
641
|
author is the single most useful thing this project can receive right now.
|
|
650
642
|
|
|
651
|
-
**Engine coverage depends on external binaries.** Semantic search works out of the box
|
|
643
|
+
**Engine coverage depends on external binaries.** Semantic search works out of the box once its
|
|
644
|
+
embedding model is cached ([offline install](docs/install.md#offline--air-gapped-install)). The graph
|
|
652
645
|
engine needs `codebase-memory-mcp` and the LSP engine needs `uvx` on `PATH` — without them those
|
|
653
646
|
engines safe-null and you get a fraction of the capability table above. `codeintel setup --all`
|
|
654
647
|
installs what it can and `codeintel doctor` tells you exactly what is missing and how to fix it.
|