carto-md 2.0.9 → 2.1.0
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.
- package/CONTRIBUTING.md +19 -15
- package/README.md +192 -415
- package/docs/api/README.md +99 -0
- package/docs/api/did_we_discuss_this.md +34 -0
- package/docs/api/dismiss_suggestion.md +34 -0
- package/docs/api/explain_change_in_natural_language.md +33 -0
- package/docs/api/find_consumers_of_api.md +34 -0
- package/docs/api/get_action_patterns.md +32 -0
- package/docs/api/get_active_drift.md +32 -0
- package/docs/api/get_active_suggestions.md +25 -0
- package/docs/api/get_ai_cost_attribution.md +32 -0
- package/docs/api/get_arch_events.md +42 -0
- package/docs/api/get_architectural_drift.md +37 -0
- package/docs/api/get_architecture.md +25 -0
- package/docs/api/get_blast_radius.md +34 -0
- package/docs/api/get_canonical_pattern.md +39 -0
- package/docs/api/get_change_plan.md +34 -0
- package/docs/api/get_change_velocity.md +32 -0
- package/docs/api/get_churn_vs_blast_radius.md +32 -0
- package/docs/api/get_complexity_trend.md +39 -0
- package/docs/api/get_context.md +34 -0
- package/docs/api/get_conventions.md +32 -0
- package/docs/api/get_cross_domain.md +25 -0
- package/docs/api/get_cross_language_call_graph.md +25 -0
- package/docs/api/get_cross_repo_blast_radius.md +34 -0
- package/docs/api/get_cross_team_coupling.md +25 -0
- package/docs/api/get_data_flow.md +33 -0
- package/docs/api/get_dead_code_with_confidence.md +32 -0
- package/docs/api/get_decision_log.md +32 -0
- package/docs/api/get_dependency_surface.md +25 -0
- package/docs/api/get_domain.md +34 -0
- package/docs/api/get_domain_evolution.md +39 -0
- package/docs/api/get_domain_health.md +32 -0
- package/docs/api/get_domains_list.md +25 -0
- package/docs/api/get_drift_digest.md +32 -0
- package/docs/api/get_env_vars.md +32 -0
- package/docs/api/get_evolution_delta.md +36 -0
- package/docs/api/get_file_ownership.md +33 -0
- package/docs/api/get_file_summary.md +34 -0
- package/docs/api/get_high_impact_files.md +32 -0
- package/docs/api/get_hot_in_prod_no_tests.md +34 -0
- package/docs/api/get_hotspot_files.md +37 -0
- package/docs/api/get_iac_resources.md +25 -0
- package/docs/api/get_interface_contract.md +33 -0
- package/docs/api/get_intervention_history.md +32 -0
- package/docs/api/get_invariants.md +37 -0
- package/docs/api/get_llm_enrichment.md +33 -0
- package/docs/api/get_microservice_cut_points.md +32 -0
- package/docs/api/get_microservices_migration_cut_points.md +25 -0
- package/docs/api/get_minimal_context_for_intent.md +39 -0
- package/docs/api/get_models.md +32 -0
- package/docs/api/get_neighbors.md +39 -0
- package/docs/api/get_org_architecture.md +25 -0
- package/docs/api/get_org_domain_mapping.md +25 -0
- package/docs/api/get_pending_decisions.md +32 -0
- package/docs/api/get_predictive_risk.md +32 -0
- package/docs/api/get_progressive_disclosure_tree.md +25 -0
- package/docs/api/get_recent_decisions.md +37 -0
- package/docs/api/get_risk_weighted_blast_radius.md +32 -0
- package/docs/api/get_routes.md +25 -0
- package/docs/api/get_safety_checklist.md +33 -0
- package/docs/api/get_semantic_diff.md +34 -0
- package/docs/api/get_service_boundary_violations.md +25 -0
- package/docs/api/get_service_dependency_graph.md +25 -0
- package/docs/api/get_session_context.md +32 -0
- package/docs/api/get_similar_patterns.md +39 -0
- package/docs/api/get_stale_docs.md +25 -0
- package/docs/api/get_structure.md +25 -0
- package/docs/api/get_temporal_context.md +34 -0
- package/docs/api/get_test_coverage_map.md +25 -0
- package/docs/api/get_token_budget_report.md +36 -0
- package/docs/api/get_upgrade_risk.md +25 -0
- package/docs/api/get_working_memory.md +25 -0
- package/docs/api/ingest_otlp_traces.md +34 -0
- package/docs/api/scaffold_for_intent.md +34 -0
- package/docs/api/search_routes.md +34 -0
- package/docs/api/simulate_change_impact.md +37 -0
- package/docs/api/validate_change.md +39 -0
- package/docs/api/validate_diff.md +39 -0
- package/docs/concepts/anci.md +87 -0
- package/docs/concepts/blast-radius.md +66 -0
- package/docs/concepts/domains.md +91 -0
- package/docs/concepts/import-graph.md +102 -0
- package/docs/concepts/mcp-integration.md +148 -0
- package/docs/guides/adding-feature-safely.md +101 -0
- package/docs/guides/ci-integration.md +175 -0
- package/docs/guides/monorepo-setup.md +121 -0
- package/docs/guides/onboarding-new-engineer.md +121 -0
- package/docs/guides/pre-merge-review.md +139 -0
- package/docs/migration/v1-to-v2.md +110 -0
- package/docs/quickstart.md +95 -0
- package/docs/scale.md +2 -2
- package/docs/troubleshooting.md +180 -0
- package/package.json +10 -4
- package/scripts/gen-api-docs.js +170 -0
- package/src/acp/agent.js +83 -11
- package/src/acp/config.js +64 -0
- package/src/acp/persistence.js +146 -0
- package/src/acp/providers/anthropic.js +179 -27
- package/src/acp/providers/index.js +15 -2
- package/src/acp/providers/openai.js +164 -38
- package/src/acp/providers/sse.js +82 -0
- package/src/acp/safety.js +128 -0
- package/src/acp/session.js +73 -0
- package/src/adjacent/call-graph.js +170 -0
- package/src/adjacent/iac.js +167 -0
- package/src/adjacent/llm-enrich.js +35 -0
- package/src/adjacent/runtime.js +216 -0
- package/src/adjacent/semantic-diff.js +143 -0
- package/src/agents/scan-structure.js +1 -1
- package/src/ai/context-builder.js +215 -0
- package/src/ai/retrieval/lexical.js +122 -0
- package/src/ai/retrieval/rrf.js +121 -0
- package/src/ai/retrieval/semantic.js +35 -0
- package/src/ai/retrieval/structural.js +82 -0
- package/src/ai/tools.js +423 -0
- package/src/anci/emit.js +2 -2
- package/src/bitmap/index.js +1 -1
- package/src/bitmap/tools.js +2 -2
- package/src/brain/conventions/index.js +185 -0
- package/src/brain/index.js +31 -0
- package/src/brain/invariants/index.js +252 -0
- package/src/brain/procedural/index.js +181 -0
- package/src/brain/suggestions/index.js +153 -0
- package/src/brain/working/index.js +170 -0
- package/src/cli/check.js +47 -1
- package/src/cli/diff.js +83 -0
- package/src/cli/doctor.js +270 -0
- package/src/cli/explain.js +61 -0
- package/src/cli/index.js +101 -0
- package/src/cli/init.js +143 -5
- package/src/cli/org.js +172 -0
- package/src/cli/pr-impact.js +59 -2
- package/src/cli/serve.js +1 -1
- package/src/cli/status.js +211 -0
- package/src/cli/sync.js +2 -2
- package/src/cli/temporal.js +188 -0
- package/src/cli/validate.js +201 -0
- package/src/cli/watch.js +4 -4
- package/src/cli/why.js +101 -0
- package/src/extractors/frameworks.js +236 -0
- package/src/extractors/languages/dart.js +138 -0
- package/src/extractors/languages/go.js +11 -1
- package/src/extractors/languages/javascript.js +13 -3
- package/src/extractors/languages/kotlin.js +169 -0
- package/src/extractors/languages/php.js +195 -0
- package/src/extractors/languages/python.js +12 -1
- package/src/extractors/languages/swift.js +140 -0
- package/src/extractors/languages/typescript.js +15 -2
- package/src/extractors/plugin-api.js +102 -0
- package/src/mcp/files-without-tests.js +285 -0
- package/src/mcp/middleware/index.js +451 -0
- package/src/mcp/server.js +2292 -0
- package/src/mcp/validate.js +1 -1
- package/src/org/detect.js +262 -0
- package/src/org/queries.js +144 -0
- package/src/org/store.js +173 -0
- package/src/org/sync.js +106 -0
- package/src/predictive/cut-points.js +83 -0
- package/src/predictive/drift-digest.js +88 -0
- package/src/predictive/ownership.js +145 -0
- package/src/predictive/risk-score.js +121 -0
- package/src/predictive/validate-change.js +55 -0
- package/src/store/store-adapter.js +3 -3
- package/src/store/{sync-v2.js → sync.js} +53 -13
- package/src/temporal/backfill.js +211 -0
- package/src/temporal/delta.js +85 -0
- package/src/temporal/events.js +180 -0
- package/src/temporal/queries.js +358 -0
- package/src/temporal/snapshot.js +151 -0
- package/src/temporal/store.js +400 -0
- package/src/mcp/server-v2.js +0 -986
package/README.md
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
[](https://www.npmjs.com/package/carto-md)
|
|
7
7
|
|
|
8
|
-
**
|
|
8
|
+
**Carto gives your AI tools a brain for your codebase.** One that remembers decisions across chats, tracks how the code evolves, and flags risky edits before they ship.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
> *"Touch that file and 22 things could break. That's exactly what you want to know before refactoring."* — Claude Code, on supabase
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
13
|
npm install -g carto-md
|
|
@@ -15,552 +15,329 @@ cd your-project
|
|
|
15
15
|
carto init
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
That's it. Carto auto-wires
|
|
18
|
+
That's it. Carto auto-wires into every AI tool installed on your machine. Restart it. Your AI now knows your codebase — and keeps a memory of every decision it makes inside it.
|
|
19
19
|
|
|
20
|
-
**Works with:** Cursor · Claude Code · Codex · Kiro · Claude Desktop · Windsurf · VS Code Copilot ·
|
|
20
|
+
**Works with:** Cursor · Claude Code · Codex · Kiro · Claude Desktop · Windsurf · VS Code Copilot · Zed · JetBrains
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
Six weeks later, a new chat can ask "did we agree on snake_case here?" and get the actual prior verdict back. Nothing is re-decided.
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
## What Carto actually does
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
```
|
|
27
|
+
─────────────────────────────────────────────────────────────────────
|
|
28
|
+
carto init reads your repo, builds the map (imports, routes,
|
|
29
|
+
models, domains, blast radius), wires every AI tool
|
|
30
|
+
on your machine. one minute, done.
|
|
31
|
+
|
|
32
|
+
every chat your AI gets the 6–12 files it actually needs.
|
|
33
|
+
every diff it proposes runs validate_diff first —
|
|
34
|
+
risky ones blocked before they hit your screen.
|
|
35
|
+
carto also pushes nudges back: "coupling jumped in
|
|
36
|
+
AUTH", "two sessions are editing this file."
|
|
37
|
+
|
|
38
|
+
brain invariants and conventions are mined from your
|
|
39
|
+
import graph. action patterns ("when a route is
|
|
40
|
+
added, auth/middleware is touched 89% of the time")
|
|
41
|
+
are mined from your git history. nobody writes
|
|
42
|
+
these rules.
|
|
43
|
+
|
|
44
|
+
timeline every commit takes a snapshot. drift, churn, and
|
|
45
|
+
architectural events accumulate. your AI can read
|
|
46
|
+
the whole story at any time: "AUTH grew 18 files
|
|
47
|
+
and lost stability when payments/billing.ts moved
|
|
48
|
+
out." carto gets smarter the longer the repo lives.
|
|
49
|
+
|
|
50
|
+
predicts every file is scored: P(causes the next bug).
|
|
51
|
+
the score blends blast radius × churn × past
|
|
52
|
+
interventions × test coverage. high-risk files
|
|
53
|
+
surface on every PR, before the PR is opened.
|
|
54
|
+
|
|
55
|
+
always one SQLite file on your disk. no network, no
|
|
56
|
+
telemetry, no cloud.
|
|
57
|
+
─────────────────────────────────────────────────────────────────────
|
|
58
|
+
```
|
|
27
59
|
|
|
28
|
-
|
|
60
|
+
---
|
|
29
61
|
|
|
30
|
-
|
|
62
|
+
<details>
|
|
63
|
+
<summary>Manual MCP wiring (if your tool wasn't auto-detected)</summary>
|
|
31
64
|
|
|
32
|
-
|
|
65
|
+
### Cursor — `~/.cursor/mcp.json`
|
|
33
66
|
```json
|
|
34
67
|
{ "mcpServers": { "carto": { "command": "carto", "args": ["serve"], "cwd": "/your/project" } } }
|
|
35
68
|
```
|
|
36
69
|
|
|
37
|
-
### Claude Code
|
|
38
|
-
|
|
39
|
-
`carto init` writes `<project>/.mcp.json` for you when Claude Code is detected (`claude` binary on PATH or `~/.claude/` exists). Manual:
|
|
70
|
+
### Claude Code — `<project>/.mcp.json`
|
|
40
71
|
```bash
|
|
41
72
|
claude mcp add carto -- carto serve
|
|
42
73
|
```
|
|
43
|
-
Or create `.mcp.json` at the project root:
|
|
44
|
-
```json
|
|
45
|
-
{ "mcpServers": { "carto": { "command": "carto", "args": ["serve"] } } }
|
|
46
|
-
```
|
|
47
74
|
|
|
48
|
-
### Codex
|
|
49
|
-
|
|
50
|
-
`carto init` writes `~/.codex/config.toml` for you when Codex is detected (`codex` binary on PATH or `~/.codex/` exists). Manual:
|
|
51
|
-
```bash
|
|
52
|
-
codex mcp add carto -- carto serve
|
|
53
|
-
```
|
|
54
|
-
Or edit `~/.codex/config.toml`:
|
|
75
|
+
### Codex — `~/.codex/config.toml`
|
|
55
76
|
```toml
|
|
56
77
|
[mcp_servers.carto]
|
|
57
78
|
command = "carto"
|
|
58
79
|
args = ["serve"]
|
|
59
|
-
cwd = "/your/project"
|
|
60
|
-
enabled = true
|
|
61
80
|
```
|
|
62
81
|
|
|
63
|
-
### Kiro
|
|
64
|
-
|
|
65
|
-
`carto init` writes this for you. Manual: `~/.kiro/settings/mcp.json`
|
|
82
|
+
### Kiro — `~/.kiro/settings/mcp.json`
|
|
66
83
|
```json
|
|
67
84
|
{ "mcpServers": { "carto": { "command": "carto", "args": ["serve"], "cwd": "/your/project" } } }
|
|
68
85
|
```
|
|
69
86
|
|
|
70
87
|
### Claude Desktop
|
|
71
|
-
|
|
72
|
-
`carto init` writes this for you (cross-platform). Manual paths:
|
|
73
88
|
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
74
89
|
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
75
|
-
- Linux: `~/.config/Claude/claude_desktop_config.json`
|
|
90
|
+
- Linux: `~/.config/Claude/claude_desktop_config.json`
|
|
76
91
|
|
|
77
92
|
```json
|
|
78
93
|
{ "mcpServers": { "carto": { "command": "carto", "args": ["serve"], "cwd": "/your/project" } } }
|
|
79
94
|
```
|
|
80
95
|
|
|
81
|
-
### VS Code Copilot
|
|
82
|
-
|
|
83
|
-
`carto init` writes `<project>/.vscode/mcp.json` for you when the `code` binary is on PATH. Manual: `.vscode/mcp.json` in your project root, or Command Palette → `MCP: Add Server`. Note: VS Code uses `servers` (not `mcpServers`) and requires `"type": "stdio"`.
|
|
96
|
+
### VS Code Copilot — `.vscode/mcp.json`
|
|
84
97
|
```json
|
|
85
98
|
{ "servers": { "carto": { "type": "stdio", "command": "carto", "args": ["serve"] } } }
|
|
86
99
|
```
|
|
87
100
|
|
|
88
|
-
### Windsurf
|
|
89
|
-
|
|
90
|
-
`carto init` writes this for you when Windsurf is detected. Manual: `~/.codeium/windsurf/mcp_config.json`
|
|
101
|
+
### Windsurf — `~/.codeium/windsurf/mcp_config.json`
|
|
91
102
|
```json
|
|
92
103
|
{ "mcpServers": { "carto": { "command": "carto", "args": ["serve"], "cwd": "/your/project" } } }
|
|
93
104
|
```
|
|
94
105
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
Carto also runs as a full **ACP agent** — not just a passive MCP server, but an active coding agent with architectural awareness. See [ACP Agent](#acp-agent-zed--jetbrains--vs-code) below.
|
|
106
|
+
</details>
|
|
98
107
|
|
|
99
108
|
---
|
|
100
109
|
|
|
101
|
-
## What
|
|
110
|
+
## What's actually different
|
|
102
111
|
|
|
103
|
-
|
|
112
|
+
Most code indexers build a snapshot. Cursor's index, Sourcegraph's graph, GitHub's search — they all tell your AI what's in the repo *right now*. That's table stakes.
|
|
104
113
|
|
|
105
|
-
|
|
114
|
+
Carto does that too — and then layers five kinds of memory on top:
|
|
106
115
|
|
|
107
|
-
**
|
|
116
|
+
- **Episodic** — every diff it validated, every decision it made. Six weeks later, your AI can ask `did_we_discuss_this("snake_case naming")` and get back the prior verdict.
|
|
117
|
+
- **Temporal** — snapshots, churn, deltas. *"AUTH grew 18 files this quarter and lost stability when `payments/billing.ts` moved out."*
|
|
118
|
+
- **Semantic** — invariants and conventions mined from the import graph itself, not declared by humans.
|
|
119
|
+
- **Procedural** — patterns mined from git history. *"When a route gets added, the auth middleware is touched 89% of the time."*
|
|
120
|
+
- **Working** — one call that returns what's open, what's drifting, what warnings are unresolved. Read at the start of every session.
|
|
108
121
|
|
|
109
|
-
|
|
110
|
-
- The exact route handler file
|
|
111
|
-
- All 7 files that import it (blast radius)
|
|
112
|
-
- The AUTH domain it lives in
|
|
113
|
-
- Similar middleware patterns already in the codebase
|
|
114
|
-
- Cross-domain dependencies that could break
|
|
122
|
+
Your AI tool sees files. Carto sees architecture *and history*. Every chat starts where the last one left off.
|
|
115
123
|
|
|
116
|
-
|
|
124
|
+
---
|
|
117
125
|
|
|
118
|
-
|
|
126
|
+
## What it looks like in practice
|
|
119
127
|
|
|
120
|
-
|
|
128
|
+
### Stopping a bad refactor before you see the diff
|
|
121
129
|
|
|
122
|
-
|
|
130
|
+
The AI is about to propose a 12-line patch. Before showing it to you, it calls `validate_diff`:
|
|
123
131
|
|
|
124
132
|
```
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
**Files changed:** 1
|
|
129
|
-
**Union blast radius:** 83 transitive dependents
|
|
130
|
-
|
|
131
|
-
## Violations (1)
|
|
133
|
+
Risk: 🔴 HIGH
|
|
134
|
+
Files changed: 1
|
|
135
|
+
Union blast radius: 83 transitive dependents
|
|
132
136
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
137
|
+
Violations
|
|
138
|
+
HIGH · high_blast · packages/pg-meta/src/pg-format/index.ts
|
|
139
|
+
83 transitive dependents (threshold: 50)
|
|
136
140
|
```
|
|
137
141
|
|
|
138
|
-
The AI sees this *before*
|
|
142
|
+
The AI sees this *before* the diff hits your screen. It revises, splits the change, or asks. Sub-millisecond on a 7,000-file repo.
|
|
139
143
|
|
|
140
|
-
|
|
144
|
+
### Packing context that actually fits
|
|
141
145
|
|
|
142
|
-
|
|
146
|
+
You ask: *"add rate limiting to /api/users."* The AI calls `get_minimal_context_for_intent` with a 4,000-token budget. Carto runs hybrid retrieval (structural + lexical + semantic), fuses the channels with RRF, boosts files in the same domain and recent churn, and returns the smallest file set that covers the intent — usually 6–12 files instead of the usual 40+.
|
|
143
147
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
*Claude Code analyzing the [supabase](https://github.com/supabase/supabase) repo via carto. Real session, no editing — 5,974 files indexed in ~780ms, 86 routes, 4,839 import edges, 7 domains. The agent's own verdict at the bottom: "useful, especially for a large codebase like supabase. The blast radius + cross-domain tools are the most valuable."*
|
|
148
|
+
### Remembering decisions across sessions
|
|
147
149
|
|
|
148
|
-
|
|
150
|
+
Every `validate_diff` call writes a row into `.carto/carto.db`. Five hours later, a different chat asks `did_we_discuss_this("snake_case naming")` and gets back the prior decision verbatim. Your AI stops re-deciding settled questions.
|
|
149
151
|
|
|
150
|
-
|
|
152
|
+
### Spotting the bug before the bug
|
|
151
153
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
| Language | Extensions |
|
|
155
|
-
|----------|-----------|
|
|
156
|
-
| JavaScript / TypeScript | `.js` `.jsx` `.ts` `.tsx` `.mjs` `.cjs` |
|
|
157
|
-
| Python | `.py` |
|
|
158
|
-
| Go | `.go` |
|
|
159
|
-
| Rust | `.rs` |
|
|
160
|
-
| Java | `.java` |
|
|
161
|
-
| C / C++ | `.cpp` `.cc` `.cxx` `.h` `.hpp` |
|
|
162
|
-
| C# | `.cs` |
|
|
163
|
-
| Ruby | `.rb` |
|
|
164
|
-
| R | `.r` `.R` |
|
|
165
|
-
| Prisma schema | `.prisma` |
|
|
166
|
-
| HTML | `.html` (for `fetch()` discovery) |
|
|
167
|
-
|
|
168
|
-
### Route extraction (framework-aware)
|
|
169
|
-
|
|
170
|
-
| Framework | Language |
|
|
171
|
-
|-----------|---------|
|
|
172
|
-
| Express, Next.js (App + Pages), tRPC, React Router | TypeScript / JavaScript |
|
|
173
|
-
| FastAPI, Flask, Django | Python |
|
|
174
|
-
| Gin, Echo, Chi, net/http | Go |
|
|
175
|
-
| Actix-web, Axum, Rocket | Rust |
|
|
176
|
-
| Spring MVC / Boot, JAX-RS | Java |
|
|
177
|
-
| ASP.NET Core | C# |
|
|
178
|
-
| Rails, Sinatra | Ruby |
|
|
179
|
-
|
|
180
|
-
### Model extraction
|
|
181
|
-
|
|
182
|
-
| ORM / Schema | Language |
|
|
183
|
-
|-------------|---------|
|
|
184
|
-
| Prisma, Zod, Drizzle, TypeScript interfaces | TypeScript / JavaScript |
|
|
185
|
-
| Pydantic, SQLAlchemy | Python |
|
|
186
|
-
| Go structs | Go |
|
|
187
|
-
| Rust structs | Rust |
|
|
188
|
-
| JPA `@Entity`, Java records | Java |
|
|
189
|
-
| EF Core, C# records | C# |
|
|
190
|
-
| ActiveRecord | Ruby |
|
|
191
|
-
|
|
192
|
-
### TypeScript path aliases
|
|
193
|
-
|
|
194
|
-
Reads `tsconfig.json` / `jsconfig.json` `paths` config. `@/components/Button` resolves to the actual file in the import graph — blast radius works correctly for Next.js and Vite projects.
|
|
154
|
+
`get_predictive_risk` returns a 0–1 score per file: P(this file causes the next incident). It combines blast radius, commit churn, cross-domain coupling, prior intervention history, and test coverage. High-risk files surface in `carto check` and on every PR.
|
|
195
155
|
|
|
196
156
|
---
|
|
197
157
|
|
|
198
|
-
##
|
|
199
|
-
|
|
200
|
-
Beyond MCP, Carto runs as a full **ACP agent** — an active coding agent with built-in architectural awareness.
|
|
201
|
-
|
|
202
|
-
```
|
|
203
|
-
User: "Add rate limiting to /api/users"
|
|
204
|
-
↓
|
|
205
|
-
Carto auto-queries its own SQLite:
|
|
206
|
-
- Blast radius of relevant files
|
|
207
|
-
- Domain context (AUTH)
|
|
208
|
-
- Similar patterns in codebase
|
|
209
|
-
↓
|
|
210
|
-
Builds rich prompt with structural context
|
|
211
|
-
↓
|
|
212
|
-
Sends to LLM (your API key) → streams answer + diffs back to editor
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
### Setup in Zed
|
|
158
|
+
## In the wild
|
|
216
159
|
|
|
217
|
-
|
|
218
|
-
```json
|
|
219
|
-
{
|
|
220
|
-
"agent_servers": {
|
|
221
|
-
"Carto": { "command": "carto", "args": ["agent"] }
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
### Bring Your Own Key
|
|
227
|
-
|
|
228
|
-
Carto supports any LLM provider — configure in your editor:
|
|
160
|
+

|
|
229
161
|
|
|
230
|
-
|
|
231
|
-
|----------|--------|
|
|
232
|
-
| Anthropic | Claude Sonnet 4, Haiku |
|
|
233
|
-
| OpenAI | GPT-4o, GPT-4o-mini, o1, o3 |
|
|
234
|
-
| Google Gemini | Gemini 2.5 Pro, 2.5 Flash |
|
|
235
|
-
| Ollama | Any local model (free) |
|
|
236
|
-
| OpenRouter | Any model via single API |
|
|
237
|
-
| Groq | Ultra-fast inference |
|
|
238
|
-
| Together AI | Open-source models |
|
|
239
|
-
| Azure OpenAI | Enterprise deployments |
|
|
162
|
+
Claude Code analyzing the [supabase](https://github.com/supabase/supabase) repo via carto. Real session, no editing — 5,974 files indexed in ~780ms, 86 routes, 4,839 import edges, 7 domains.
|
|
240
163
|
|
|
241
164
|
---
|
|
242
165
|
|
|
243
|
-
##
|
|
244
|
-
|
|
245
|
-
Drop carto onto every PR your repo gets. Posts a sticky comment on each pull request with the diff's blast radius, cross-domain violations, affected routes, and a risk badge.
|
|
166
|
+
## How fast
|
|
246
167
|
|
|
247
|
-
|
|
248
|
-
```yaml
|
|
249
|
-
name: Carto Impact Report
|
|
250
|
-
|
|
251
|
-
on:
|
|
252
|
-
pull_request:
|
|
253
|
-
branches: [main]
|
|
254
|
-
|
|
255
|
-
permissions:
|
|
256
|
-
contents: read
|
|
257
|
-
pull-requests: write
|
|
258
|
-
|
|
259
|
-
jobs:
|
|
260
|
-
carto:
|
|
261
|
-
runs-on: ubuntu-latest
|
|
262
|
-
steps:
|
|
263
|
-
- uses: actions/checkout@v4
|
|
264
|
-
with: { fetch-depth: 0 }
|
|
265
|
-
- uses: theanshsonkar/carto@v2.0.9
|
|
266
|
-
```
|
|
168
|
+
Measured on real open-source repos, fresh runs on Apple M-series, 8 CPUs, 8 GB RAM.
|
|
267
169
|
|
|
268
|
-
|
|
170
|
+
| Repo | Files | First index | Re-index | DB size |
|
|
171
|
+
|---|--:|--:|--:|--:|
|
|
172
|
+
| [cal.com](https://github.com/calcom/cal.com) | 4,352 | 3.9s | 805ms | 3.1 MB |
|
|
173
|
+
| [supabase/supabase](https://github.com/supabase/supabase) | 6,358 | 5.9s | 967ms | 4.8 MB |
|
|
174
|
+
| [vercel/next.js](https://github.com/vercel/next.js) | 6,193 | 6.9s | 978ms | 15.1 MB |
|
|
175
|
+
| [microsoft/vscode](https://github.com/microsoft/vscode) | 7,567 | 8.6s | 1.1s | 14.3 MB |
|
|
269
176
|
|
|
270
|
-
|
|
177
|
+
**Query latency** on vscode (7,567 files):
|
|
271
178
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
| `head` | auto (`$GITHUB_SHA`) | Git ref of the PR head. |
|
|
277
|
-
| `fail-on` | _(empty)_ | Fail the workflow when risk meets/exceeds this severity. One of `HIGH`, `MEDIUM`, `LOW`. Empty = comment-only. |
|
|
278
|
-
| `comment-mode` | `sticky` | `sticky` updates the existing carto comment in place. `new` posts a new comment every push. `none` skips posting (renders to stdout). |
|
|
279
|
-
| `node-version` | `20` | Node.js version on the runner. |
|
|
179
|
+
- `validate_diff` — p50 **84 µs**, p99 **489 µs** (budget was 5 ms / 15 ms)
|
|
180
|
+
- `get_blast_radius` — p50 **2.7 µs**, **10.7×** faster than the SQLite path
|
|
181
|
+
- `get_high_impact_files` — p50 **750 ns**, **559×** faster
|
|
182
|
+
- `simulate_change_impact` — p50 **19.3 µs**, multi-file blast radius via bitmap OR-aggregation
|
|
280
183
|
|
|
281
|
-
|
|
184
|
+
Bitmap-backed reverse dependency graph. Median speedup across five core tools on vscode: **10.7×**. Synthetic stress at 50K files holds `blast_radius` p50 at **22 µs**. Full table in [`docs/scale.md`](docs/scale.md). Reproducible via `npm run bench:bitmap -- --repo <path>`.
|
|
282
185
|
|
|
283
|
-
|
|
284
|
-
|--------|-------------|
|
|
285
|
-
| `risk` | Rolled-up risk: `SAFE` \| `LOW` \| `MEDIUM` \| `HIGH`. Lets downstream steps gate behavior on Carto's verdict. |
|
|
286
|
-
| `comment-url` | URL of the posted/updated PR comment. |
|
|
287
|
-
|
|
288
|
-
### What the comment looks like
|
|
289
|
-
|
|
290
|
-
```markdown
|
|
291
|
-
## 🗺️ Carto Impact Report
|
|
186
|
+
---
|
|
292
187
|
|
|
293
|
-
|
|
188
|
+
## Tools your AI can call
|
|
294
189
|
|
|
295
|
-
|
|
296
|
-
|--------|-------|
|
|
297
|
-
| Risk | 🔴 HIGH |
|
|
298
|
-
| Blast radius (union) | 23 files |
|
|
299
|
-
| Files changed | 6 |
|
|
300
|
-
| Cross-domain violations introduced | 2 |
|
|
301
|
-
| High-impact file changed | src/auth/session.ts (8 direct dependents) |
|
|
190
|
+
About 75 tools, grouped by what they're for:
|
|
302
191
|
|
|
303
|
-
|
|
304
|
-
|
|
192
|
+
| Group | Tools |
|
|
193
|
+
|---|---|
|
|
194
|
+
| **Structure** | `get_change_plan` · `get_blast_radius` · `simulate_change_impact` · `validate_diff` · `get_context` · `get_routes` · `get_models` · `get_cross_domain` · `get_high_impact_files` |
|
|
195
|
+
| **Episodic memory** | `did_we_discuss_this` · `get_decision_log` · `get_session_context` · `get_pending_decisions` · `get_intervention_history` |
|
|
196
|
+
| **Temporal** | `get_architectural_drift` · `get_domain_evolution` · `get_hotspot_files` · `get_arch_events` · `get_temporal_context` · `get_change_velocity` · `get_complexity_trend` |
|
|
197
|
+
| **Brain** | `get_invariants` · `get_conventions` · `get_canonical_pattern` · `get_action_patterns` · `get_working_memory` · `get_active_suggestions` · `scaffold_for_intent` |
|
|
198
|
+
| **Predictive** | `get_predictive_risk` · `get_safety_checklist` · `get_drift_digest` · `get_test_coverage_map` |
|
|
199
|
+
| **Retrieval** | `get_minimal_context_for_intent` · `get_progressive_disclosure_tree` |
|
|
200
|
+
| **Org / multi-repo** | `get_org_architecture` · `get_service_dependency_graph` · `get_cross_repo_blast_radius` · `find_consumers_of_api` · `get_service_boundary_violations` |
|
|
201
|
+
| **Adjacent** | `get_cross_language_call_graph` · `get_iac_resources` · `ingest_otlp_traces` · `get_risk_weighted_blast_radius` · `get_dead_code_with_confidence` · `get_semantic_diff` |
|
|
305
202
|
|
|
306
|
-
|
|
307
|
-
- GET /auth/me — risk: HIGH
|
|
308
|
-
- POST /auth/register — risk: MEDIUM
|
|
309
|
-
- POST /api/users — risk: LOW
|
|
203
|
+
Full reference at [`docs/api/`](docs/api/). You don't need to memorize any of these — your AI picks the right one mid-task.
|
|
310
204
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
<details>
|
|
314
|
-
<summary>Cross-domain violations (2)</summary>
|
|
315
|
-
|
|
316
|
-
- auth/login.ts now imports from payments/billing.ts (AUTH→PAYMENTS)
|
|
317
|
-
- database/user-repo.ts now imports from auth/jwt.ts (DATABASE→AUTH)
|
|
318
|
-
|
|
319
|
-
</details>
|
|
320
|
-
```
|
|
205
|
+
---
|
|
321
206
|
|
|
322
|
-
|
|
207
|
+
## Multi-repo
|
|
323
208
|
|
|
324
|
-
|
|
209
|
+
Register a group of repos under one org. Carto builds a service graph across them — npm, pypi, go-mod, maven edges all resolved.
|
|
325
210
|
|
|
326
211
|
```bash
|
|
327
|
-
carto
|
|
328
|
-
carto
|
|
329
|
-
carto
|
|
212
|
+
carto org init
|
|
213
|
+
carto org add ../service-a ../service-b ../service-c
|
|
214
|
+
carto org sync
|
|
330
215
|
```
|
|
331
216
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
## ANCI — the open spec for codebases describing themselves to AI
|
|
217
|
+
Then ask: *"if I rename `User.email` in service-a, who notices?"* — one `get_cross_repo_blast_radius` call away.
|
|
335
218
|
|
|
336
|
-
|
|
219
|
+
---
|
|
337
220
|
|
|
338
|
-
|
|
221
|
+
## MCP middleware
|
|
339
222
|
|
|
340
|
-
|
|
223
|
+
Carto can sit in front of *any* MCP server and block bad writes before they reach the model:
|
|
341
224
|
|
|
342
225
|
```bash
|
|
343
|
-
carto
|
|
344
|
-
carto anci show # human-readable summary
|
|
345
|
-
carto anci validate ./.carto # validate a published pair
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
Any tool can consume an ANCI pair without depending on Carto:
|
|
349
|
-
|
|
350
|
-
```js
|
|
351
|
-
const { loadAnci } = require('carto-md/src/anci/consumer');
|
|
352
|
-
|
|
353
|
-
const reader = loadAnci('./.carto');
|
|
354
|
-
console.log(reader.domains); // [{ name: 'AUTH', file_count: 42 }, ...]
|
|
355
|
-
console.log(reader.getHighImpactFiles(5)); // top 5 by transitive dependents
|
|
356
|
-
console.log(reader.blastRadius('src/auth/session.ts'));// { count, hops, files: [...] }
|
|
357
|
-
console.log(reader.simulateChangeImpact([ // multi-file change blast radius
|
|
358
|
-
'src/auth/session.ts',
|
|
359
|
-
'src/db/connection.ts',
|
|
360
|
-
]));
|
|
226
|
+
carto mcp-middleware --block-on HIGH -- claude-code
|
|
361
227
|
```
|
|
362
228
|
|
|
363
|
-
|
|
229
|
+
Every `tools/call` that writes to disk is intercepted. Carto synthesizes a unified diff, runs `validate_diff`, and rejects HIGH-risk writes with the violation reasons surfaced back to the AI. Works with any stdio-based MCP server.
|
|
364
230
|
|
|
365
231
|
---
|
|
366
232
|
|
|
233
|
+
## Languages and frameworks
|
|
367
234
|
|
|
235
|
+
<details>
|
|
236
|
+
<summary>Import graph + symbols (any repo)</summary>
|
|
368
237
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
|
372
|
-
|
|
373
|
-
|
|
|
374
|
-
|
|
|
375
|
-
|
|
|
376
|
-
|
|
|
377
|
-
|
|
|
378
|
-
|
|
|
379
|
-
|
|
|
380
|
-
|
|
|
381
|
-
|
|
|
382
|
-
|
|
|
383
|
-
|
|
|
384
|
-
| `
|
|
385
|
-
| `get_cross_domain()` | Import edges that cross domain boundaries |
|
|
386
|
-
| `search_routes(query)` | Search API routes by path or method |
|
|
387
|
-
| `get_models(domain?)` | All data models, optionally filtered by domain |
|
|
388
|
-
| `get_high_impact_files(n)` | Top N files by blast radius |
|
|
389
|
-
| `get_env_vars(domain?)` | All env vars with domain mapping |
|
|
390
|
-
| `get_domains_list()` | All detected domains with file, route, model counts |
|
|
391
|
-
| `get_recent_decisions(time_range, kind?)` | Recent validation decisions and architectural choices the AI has made in this project |
|
|
392
|
-
| `get_session_context(session_id?)` | Full context for an AI session: every decision and intervention, ordered chronologically |
|
|
393
|
-
| `did_we_discuss_this(topic)` | Substring search over the episodic memory log — avoid re-deciding settled questions |
|
|
394
|
-
| `get_intervention_history(file?)` | Past Carto-issued violations and suggestions, optionally filtered by file |
|
|
395
|
-
|
|
396
|
-
**Latency:** All bitmap-backed queries return in microseconds on real repos; cross-domain and `simulate_change_impact` settle under 2ms even on a 7.5K-file codebase like vscode. See [Benchmarks](#benchmarks) for the per-tool table.
|
|
397
|
-
|
|
398
|
-
## Episodic Memory
|
|
399
|
-
|
|
400
|
-
Carto remembers every diff it validates. The `validate_diff` tool writes one row per call into a local SQLite log (`ai_sessions`/`decisions`/`interventions` tables) — so a session that runs five hours later can still ask `did_we_discuss_this("snake_case naming")` and get back the prior decision. The log lives next to the index in `.carto/carto.db` — never sent over the network, never shared between projects.
|
|
401
|
-
|
|
402
|
-
---
|
|
403
|
-
|
|
404
|
-
## Domain detection
|
|
238
|
+
| Language | Extensions |
|
|
239
|
+
|---|---|
|
|
240
|
+
| JavaScript / TypeScript | `.js` `.jsx` `.ts` `.tsx` `.mjs` `.cjs` |
|
|
241
|
+
| Python | `.py` |
|
|
242
|
+
| Go | `.go` |
|
|
243
|
+
| Rust | `.rs` |
|
|
244
|
+
| Java / Kotlin | `.java` `.kt` |
|
|
245
|
+
| C / C++ | `.cpp` `.cc` `.h` `.hpp` |
|
|
246
|
+
| C# | `.cs` |
|
|
247
|
+
| Ruby | `.rb` |
|
|
248
|
+
| PHP | `.php` |
|
|
249
|
+
| Swift | `.swift` |
|
|
250
|
+
| Dart | `.dart` |
|
|
251
|
+
| R | `.r` `.R` |
|
|
252
|
+
| Prisma schema | `.prisma` |
|
|
253
|
+
| HTML | `.html` (for `fetch()` discovery) |
|
|
405
254
|
|
|
406
|
-
|
|
255
|
+
TypeScript path aliases from `tsconfig.json` / `jsconfig.json` are resolved into the import graph. `@/components/Button` lands on the real file.
|
|
407
256
|
|
|
408
|
-
|
|
257
|
+
</details>
|
|
409
258
|
|
|
410
|
-
|
|
259
|
+
<details>
|
|
260
|
+
<summary>Route + model extraction</summary>
|
|
411
261
|
|
|
412
|
-
|
|
413
|
-
```json
|
|
414
|
-
{
|
|
415
|
-
"domains": {
|
|
416
|
-
"EDITOR": ["editor", "monaco", "text"],
|
|
417
|
-
"WORKBENCH": ["workbench", "layout", "panel"]
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
```
|
|
262
|
+
**Routes:** Express, Next.js (App + Pages), tRPC, React Router, FastAPI, Flask, Django, Gin, Echo, Chi, net/http, Actix-web, Axum, Rocket, Spring MVC, JAX-RS, ASP.NET Core, Rails, Sinatra.
|
|
421
263
|
|
|
422
|
-
|
|
423
|
-
```json
|
|
424
|
-
{
|
|
425
|
-
"domains": {
|
|
426
|
-
"AUTH": {
|
|
427
|
-
"keywords": ["auth", "login", "session"],
|
|
428
|
-
"anchor": ["src/auth/session.ts", "src/auth/middleware.ts"]
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
```
|
|
264
|
+
**Models:** Prisma, Zod, Drizzle, TS interfaces, Pydantic, SQLAlchemy, Go structs, Rust structs, JPA, EF Core, ActiveRecord.
|
|
433
265
|
|
|
434
|
-
|
|
266
|
+
</details>
|
|
435
267
|
|
|
436
268
|
---
|
|
437
269
|
|
|
438
|
-
## CLI
|
|
270
|
+
## CLI
|
|
439
271
|
|
|
440
272
|
| Command | What it does |
|
|
441
|
-
|
|
442
|
-
| `carto init` |
|
|
443
|
-
| `carto sync` |
|
|
444
|
-
| `carto serve` | Start MCP server (
|
|
445
|
-
| `carto
|
|
446
|
-
| `carto
|
|
447
|
-
| `carto impact
|
|
448
|
-
| `carto
|
|
449
|
-
| `carto
|
|
450
|
-
| `carto
|
|
451
|
-
| `carto
|
|
273
|
+
|---|---|
|
|
274
|
+
| `carto init` | Index, generate AGENTS.md, install git hooks, wire MCP into every AI tool found |
|
|
275
|
+
| `carto sync` | Re-index changed files (auto-runs on commit / checkout / merge / rebase) |
|
|
276
|
+
| `carto serve` | Start the MCP server (your AI tool runs this) |
|
|
277
|
+
| `carto agent` | ACP agent mode for Zed / JetBrains |
|
|
278
|
+
| `carto impact <file>` | Blast radius of one file |
|
|
279
|
+
| `carto pr-impact` | Diff-shaped impact report between two refs |
|
|
280
|
+
| `carto check` | Domain health, cross-domain violations, drift |
|
|
281
|
+
| `carto status` | One-screen project health |
|
|
282
|
+
| `carto doctor` | 9-check setup diagnostic |
|
|
283
|
+
| `carto why <file>` | 3-line file summary |
|
|
284
|
+
| `carto explain <intent>` | Natural-language intent → architectural plan |
|
|
285
|
+
| `carto inspect` | Index paths, sizes, freshness (read-only) |
|
|
452
286
|
|
|
453
287
|
---
|
|
454
288
|
|
|
455
|
-
##
|
|
456
|
-
|
|
457
|
-
Measured on real open-source repos. Apple M-series, 8 CPUs, 8GB RAM. SHAs pinned in `~/carto-test-repos`. Reproducible via `~/carto-test-repos/run-bench.sh`.
|
|
458
|
-
|
|
459
|
-
### Indexing speed
|
|
460
|
-
|
|
461
|
-
| Repo | Language | Indexed Files | First Run | Second Run | DB Size | Import Edges |
|
|
462
|
-
|------|----------|---------------|-----------|------------|---------|--------------|
|
|
463
|
-
| [prisma/prisma](https://github.com/prisma/prisma) | TypeScript | 961 | **1.0s** | **350ms** | 1.1 MB | 1,387 |
|
|
464
|
-
| [supabase/supabase](https://github.com/supabase/supabase) | TypeScript | 6,330 | **5.4s** | **1.2s** | 4.8 MB | 5,189 |
|
|
465
|
-
| [microsoft/vscode](https://github.com/microsoft/vscode) | TypeScript | 7,567 | **8.0s** | **935ms** | 14.3 MB | 13,335 |
|
|
466
|
-
| [zed-industries/zed](https://github.com/zed-industries/zed) | Rust | 1,752 | **2.9s** | **468ms** | 4.8 MB | 2,110 |
|
|
467
|
-
|
|
468
|
-
**Indexed Files** counts what Carto actually parses — `.ts/.js/.py/.go/.rs/...` after excluding `node_modules`, build output, and per-file test patterns (`*.test.*` / `*.spec.*` / `*.stories.*` for JS/TS, `test_*.py` / `*_test.py` for Python, `test_*` / `*_test.r` for R). The on-disk file count of the repo is larger.
|
|
469
|
-
|
|
470
|
-
**Second Run** = `carto sync` after no changes. mtime+size checked before reading content — if nothing changed, nothing is re-parsed.
|
|
471
|
-
|
|
472
|
-
### MCP query latency (bitmap engine vs SQLite)
|
|
473
|
-
|
|
474
|
-
Carto's MCP query path is bitmap-backed on five tools, plus a sixth (`simulate_change_impact`) that's only feasible with bitmap OR-aggregation. Speedups measured against the same data, same DB, same machine — bitmap path vs the equivalent SQLite path.
|
|
475
|
-
|
|
476
|
-
| Tool | vscode (7,567 files) | Speedup vs SQLite |
|
|
477
|
-
|------|---------------------:|------------------:|
|
|
478
|
-
| `get_blast_radius` | sub-ms | **10.7×** |
|
|
479
|
-
| `get_cross_domain` | 2.1ms | **6.2×** |
|
|
480
|
-
| `get_high_impact_files` | sub-ms | **559×** |
|
|
481
|
-
| `get_similar_patterns` | sub-ms | **73×** |
|
|
482
|
-
| `simulate_change_impact` | sub-ms | **6.5×** (no SQLite equivalent at this latency) |
|
|
289
|
+
## ACP agent (Zed / JetBrains / VS Code)
|
|
483
290
|
|
|
484
|
-
|
|
291
|
+
Carto also runs as a full ACP agent — not just a passive MCP server. It pulls its own context, streams tokens, applies diffs.
|
|
485
292
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
293
|
+
```json
|
|
294
|
+
{ "agent_servers": { "Carto": { "command": "carto", "args": ["agent"] } } }
|
|
295
|
+
```
|
|
489
296
|
|
|
490
|
-
|
|
491
|
-
|------|-------|----:|----:|
|
|
492
|
-
| supabase | 6,259 | **0.082ms** | **0.298ms** |
|
|
493
|
-
| vscode | 7,567 | **0.084ms** | **0.489ms** |
|
|
297
|
+
Bring your own key: Anthropic, OpenAI, Gemini, Groq, Ollama, OpenRouter, Together, Azure.
|
|
494
298
|
|
|
495
|
-
|
|
299
|
+
---
|
|
496
300
|
|
|
497
|
-
|
|
301
|
+
## GitHub Action
|
|
498
302
|
|
|
499
|
-
|
|
303
|
+
Drop Carto onto every PR. Sticky comment with blast radius, cross-domain violations, affected routes, risk badge.
|
|
500
304
|
|
|
501
|
-
|
|
502
|
-
-
|
|
305
|
+
```yaml
|
|
306
|
+
- uses: theanshsonkar/carto@v2.0.9
|
|
307
|
+
```
|
|
503
308
|
|
|
504
|
-
|
|
309
|
+
`fail-on: HIGH | MEDIUM | LOW` gates the workflow on Carto's verdict. Full config in [`docs/guides/ci-integration.md`](docs/guides/ci-integration.md).
|
|
505
310
|
|
|
506
|
-
|
|
311
|
+
---
|
|
507
312
|
|
|
508
|
-
|
|
509
|
-
|------|---------|
|
|
510
|
-
| prisma | CORE · DATABASE · AUTH · EVENTS |
|
|
511
|
-
| supabase | CORE · AUTH · DATABASE · PAYMENTS · NOTIFICATIONS · EVENTS · TRPC |
|
|
512
|
-
| vscode | EXTENSIONS · AUTH · EVENTS · DATABASE · EXTENSION · CLI · CORE |
|
|
513
|
-
| zed (Rust) | CORE · DATABASE · AUTH · EVENTS · PAYMENTS · TRPC · NOTIFICATIONS |
|
|
313
|
+
## ANCI — the open format for codebases describing themselves to AI
|
|
514
314
|
|
|
515
|
-
|
|
315
|
+
Every AI tool today re-indexes from scratch on every session. Cursor builds its own. Cline builds its own. Continue builds its own. Same parsing, every tool, every time.
|
|
516
316
|
|
|
517
|
-
|
|
317
|
+
**ANCI** (Architecturally Normalized Code Index) fixes that. Two files at `.carto/anci.{yaml,bin}` that describe a codebase's architecture in a form any AI tool can read without doing its own indexing. OpenAPI did this for REST APIs. ANCI does it for codebases.
|
|
518
318
|
|
|
519
|
-
|
|
319
|
+
`carto sync` writes both files automatically. Spec at [`docs/anci/v0.1-DRAFT.md`](docs/anci/v0.1-DRAFT.md). Carto is the reference implementation; any tool can consume an ANCI pair:
|
|
520
320
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
321
|
+
```js
|
|
322
|
+
const { loadAnci } = require('carto-md/src/anci/consumer');
|
|
323
|
+
const reader = loadAnci('./.carto');
|
|
524
324
|
|
|
325
|
+
reader.domains; // [{ name: 'AUTH', file_count: 42 }, ...]
|
|
326
|
+
reader.getHighImpactFiles(5); // top 5 by transitive dependents
|
|
327
|
+
reader.blastRadius('src/auth/session.ts'); // { count, hops, files: [...] }
|
|
525
328
|
```
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
Discovers all files (no cap — SQLite handles the volume)
|
|
529
|
-
mtime+size check → skip unchanged files
|
|
530
|
-
tree-sitter parse → imports + symbols (0.05–0.2ms/file)
|
|
531
|
-
Babel deep parse → routes + models (API handler files only)
|
|
532
|
-
Leiden+CPM graph clustering → auto-detects domains
|
|
533
|
-
Computes reverse deps → blast radius for every file
|
|
534
|
-
Writes AGENTS.md + .carto/context/*.md (lazy, on-demand)
|
|
535
|
-
Auto-wires MCP into every AI tool found
|
|
536
|
-
Installs 4 git hooks: pre-commit, post-checkout, post-merge, post-rewrite
|
|
537
|
-
↓
|
|
538
|
-
[no daemon, no watcher, no background process]
|
|
539
|
-
↓
|
|
540
|
-
─── Freshness mechanism 1: git hooks (90% of cases) ───
|
|
541
|
-
You commit / pull / switch branches / rebase
|
|
542
|
-
→ hook runs `carto sync` quietly in <1s
|
|
543
|
-
→ only changed files re-parsed
|
|
544
|
-
↓
|
|
545
|
-
─── Freshness mechanism 2: lazy mtime check (the gap) ───
|
|
546
|
-
You edit files between commits, AI asks "blast radius of db.ts?"
|
|
547
|
-
→ MCP server stats db.ts (mtime+size vs DB row)
|
|
548
|
-
→ if stale, re-parses just that file inline (<50ms)
|
|
549
|
-
→ returns fresh answer
|
|
550
|
-
↓
|
|
551
|
-
─── Optional: carto watch (AI-heavy workflows only) ───
|
|
552
|
-
File saved → debounce 50ms → re-parse 1 file → SQLite write → <50ms
|
|
553
|
-
```
|
|
329
|
+
|
|
330
|
+
> Status: v0.1.0-DRAFT — wire format may change up to v1.0.
|
|
554
331
|
|
|
555
332
|
---
|
|
556
333
|
|
|
557
334
|
## What Carto never does
|
|
558
335
|
|
|
559
|
-
- **Sends your code anywhere.** Local only. SQLite on disk.
|
|
336
|
+
- **Sends your code anywhere.** Local only. SQLite on disk. No telemetry.
|
|
560
337
|
- **Writes secrets into AGENTS.md.** `.cartoignore` blocks `.env` and credential files by default.
|
|
561
|
-
- **Touches your manual notes.**
|
|
562
|
-
- **Forces you to install a C++ toolchain.** Prebuilt
|
|
563
|
-
- **Costs money.** MIT
|
|
338
|
+
- **Touches your manual notes.** Only writes between `<!-- CARTO:AUTO -->` markers.
|
|
339
|
+
- **Forces you to install a C++ toolchain.** Prebuilt binaries for macOS arm64, Linux x64 (glibc + musl), Windows x64. Other platforms fall back to source build, then regex-only extraction.
|
|
340
|
+
- **Costs money.** MIT. Free forever.
|
|
564
341
|
|
|
565
342
|
---
|
|
566
343
|
|
|
@@ -568,9 +345,9 @@ File saved → debounce 50ms → re-parse 1 file → SQLite write → <50ms
|
|
|
568
345
|
|
|
569
346
|
I was building [Emfirge](https://www.emfirge.cloud) — a cloud security agent that maps AWS infrastructure into a graph and simulates the blast radius of every change.
|
|
570
347
|
|
|
571
|
-
|
|
348
|
+
The AI inside Emfirge kept hallucinating about resources it had only half-seen. So I wrote a module called `cartography.py` that mapped every account into a structured graph the AI could query directly. The hallucinations stopped. The AI worked with facts.
|
|
572
349
|
|
|
573
|
-
Carto is
|
|
350
|
+
Carto is that idea, applied to source code. Same insight: agents stop guessing once they can query the architecture — and they stop forgetting once the architecture remembers them.
|
|
574
351
|
|
|
575
352
|
---
|
|
576
353
|
|
|
@@ -580,4 +357,4 @@ MIT. Free forever.
|
|
|
580
357
|
|
|
581
358
|
---
|
|
582
359
|
|
|
583
|
-
*Your code changes. Carto knows. Every AI you use knows.*
|
|
360
|
+
*Your code changes. Carto knows. Every AI you use knows — and remembers.*
|