carto-md 2.0.9 → 2.1.1
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/CHANGELOG.md +135 -0
- package/CONTRIBUTING.md +27 -20
- package/README.md +177 -448
- package/docs/anci/v0.1-DRAFT.md +132 -2
- package/docs/api/README.md +124 -0
- package/docs/api/did_we_discuss_this.md +36 -0
- package/docs/api/dismiss_gap.md +39 -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 +36 -0
- package/docs/api/get_action_patterns.md +34 -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 +44 -0
- package/docs/api/get_architectural_drift.md +39 -0
- package/docs/api/get_architecture.md +25 -0
- package/docs/api/get_blast_radius.md +36 -0
- package/docs/api/get_canonical_pattern.md +41 -0
- package/docs/api/get_change_plan.md +34 -0
- package/docs/api/get_change_velocity.md +34 -0
- package/docs/api/get_churn_vs_blast_radius.md +34 -0
- package/docs/api/get_complexity_trend.md +41 -0
- package/docs/api/get_context.md +34 -0
- package/docs/api/get_conventions.md +34 -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 +36 -0
- package/docs/api/get_cross_team_coupling.md +25 -0
- package/docs/api/get_data_flow.md +35 -0
- package/docs/api/get_dead_code_with_confidence.md +32 -0
- package/docs/api/get_decision_log.md +34 -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 +41 -0
- package/docs/api/get_domain_health.md +34 -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_receipts.md +34 -0
- package/docs/api/get_file_summary.md +34 -0
- package/docs/api/get_gaps.md +52 -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 +39 -0
- package/docs/api/get_iac_resources.md +25 -0
- package/docs/api/get_intent.md +25 -0
- package/docs/api/get_interface_contract.md +33 -0
- package/docs/api/get_intervention_history.md +34 -0
- package/docs/api/get_invariants.md +39 -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 +27 -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 +41 -0
- package/docs/api/get_org_architecture.md +27 -0
- package/docs/api/get_org_domain_mapping.md +27 -0
- package/docs/api/get_pending_decisions.md +34 -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 +39 -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 +27 -0
- package/docs/api/get_service_dependency_graph.md +27 -0
- package/docs/api/get_session_context.md +34 -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 +36 -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/history.md +78 -0
- package/docs/api/impact.md +56 -0
- package/docs/api/ingest_otlp_traces.md +34 -0
- package/docs/api/memory.md +70 -0
- package/docs/api/org.md +51 -0
- package/docs/api/patterns.md +63 -0
- package/docs/api/scaffold_for_intent.md +34 -0
- package/docs/api/search_routes.md +34 -0
- package/docs/api/set_intent.md +45 -0
- package/docs/api/simulate_change_impact.md +39 -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 +116 -0
- package/docs/concepts/import-graph.md +102 -0
- package/docs/concepts/mcp-integration.md +150 -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/screenshots/carto-supabase-blast-radius.png +0 -0
- package/docs/troubleshooting.md +180 -0
- package/package.json +11 -4
- package/scripts/gen-api-docs.js +202 -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/domains.js +72 -24
- 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 +425 -0
- package/src/anci/consumer.js +83 -3
- package/src/anci/emit.js +20 -3
- package/src/anci/git-meta.js +171 -0
- package/src/anci/pack.js +288 -0
- package/src/anci/serialize.js +77 -6
- package/src/anci/staleness.js +161 -0
- package/src/bitmap/index.js +1 -1
- package/src/bitmap/tools.js +2 -2
- package/src/brain/conventions/index.js +299 -0
- package/src/brain/index.js +31 -0
- package/src/brain/invariants/index.js +306 -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/anci.js +27 -1
- package/src/cli/check.js +47 -1
- package/src/cli/diff.js +83 -0
- package/src/cli/doctor.js +339 -0
- package/src/cli/explain.js +61 -0
- package/src/cli/export.js +128 -0
- package/src/cli/index.js +120 -1
- package/src/cli/init.js +227 -6
- package/src/cli/load.js +125 -0
- 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/imports.js +35 -10
- package/src/extractors/languages/dart.js +138 -0
- package/src/extractors/languages/go.js +11 -1
- package/src/extractors/languages/javascript.js +21 -7
- package/src/extractors/languages/kotlin.js +169 -0
- package/src/extractors/languages/php.js +195 -0
- package/src/extractors/languages/prisma.js +1 -1
- package/src/extractors/languages/python.js +12 -1
- package/src/extractors/languages/swift.js +140 -0
- package/src/extractors/languages/typescript.js +28 -51
- package/src/extractors/plugin-api.js +102 -0
- package/src/extractors/schemas.js +60 -0
- package/src/extractors/tree-sitter-parser.js +39 -0
- package/src/mcp/change-plan.js +131 -12
- package/src/mcp/files-without-tests.js +285 -0
- package/src/mcp/impact.js +119 -0
- package/src/mcp/middleware/index.js +451 -0
- package/src/mcp/server.js +2918 -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/rules/concepts/auth-middleware.md +111 -0
- package/src/rules/concepts/money-as-float.md +80 -0
- package/src/rules/engine.js +178 -0
- package/src/rules/intent.js +178 -0
- package/src/rules/registry.js +24 -0
- package/src/rules/rules/auth-missing-on-mutating-route.js +255 -0
- package/src/rules/rules/money-as-float.js +166 -0
- package/src/store/config-loader.js +77 -3
- package/src/store/sqlite-store.js +248 -7
- package/src/store/store-adapter.js +3 -3
- package/src/store/{sync-v2.js → sync.js} +122 -52
- 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
|
@@ -1,13 +1,52 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Carto
|
|
2
|
+
|
|
3
|
+
**The portable AI container for your codebase. Package a repo once - every AI tool understands it in seconds, and knows what breaks before it changes anything.**
|
|
4
|
+
|
|
5
|
+
[Docs](docs/) · [Quickstart](docs/quickstart.md) · [Tools](#tools-your-ai-can-call) · [ANCI Spec](docs/anci/v0.1-DRAFT.md) · [Benchmarks](docs/scale.md) · [Changelog](CHANGELOG.md)
|
|
2
6
|
|
|
3
7
|
[](https://github.com/theanshsonkar/carto/actions/workflows/test.yml)
|
|
4
8
|
[](https://www.npmjs.com/package/carto-md)
|
|
5
9
|
[](LICENSE)
|
|
6
10
|
[](https://www.npmjs.com/package/carto-md)
|
|
7
11
|
|
|
8
|
-
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
> **Docker made apps portable. Carto makes codebases portable for AI.**
|
|
15
|
+
|
|
16
|
+
Every AI tool re-reads your entire codebase from scratch, every single session. Cursor builds its own index. Copilot builds its own. Claude Code builds its own. Same parsing, every tool, every time - and none of them remember what they learned yesterday.
|
|
17
|
+
|
|
18
|
+
Carto fixes that. It packages a repository into a **portable AI container** that captures its architecture, dependencies, engineering history, and safety context - so any AI coding assistant understands the project in seconds instead of rediscovering it from scratch. And because the container knows how everything connects, it can tell you **what breaks before you change it.**
|
|
19
|
+
|
|
20
|
+
One SQLite file on your disk. No network. No telemetry. No cloud.
|
|
21
|
+
|
|
22
|
+
> **Passive context vs. active guardrail.** Most tools hand the AI context and hope for the best. Carto grades every proposed diff *before* it lands - blast radius, risk, cross-domain violations - and can block a HIGH-risk edit before it ever reaches disk. Context that pushes back.
|
|
23
|
+
|
|
24
|
+

|
|
9
25
|
|
|
10
|
-
|
|
26
|
+
| | |
|
|
27
|
+
|---|---|
|
|
28
|
+
| 🗺️ **Architecture** | Import graph, routes, models, and auto-detected domains - the whole shape of the repo, mapped once. |
|
|
29
|
+
| 💥 **Blast Radius** | "Touch this file and 22 things break." Transitive impact of any change, in microseconds. |
|
|
30
|
+
| 🧠 **Memory** | Every decision and validated diff is remembered across sessions. Ask *"did we agree on snake_case here?"* six weeks later and get the actual verdict. |
|
|
31
|
+
| ⏳ **History** | Snapshots every commit. Tracks drift, churn, and architectural events. The container gets smarter the longer the repo lives. |
|
|
32
|
+
| 🎯 **Predictive Risk** | Every file scored 0–1: *P(this causes the next incident)*. High-risk files surface before the PR is opened. |
|
|
33
|
+
| 📦 **Portable (ANCI)** | The **structural core** is an open format - `.carto/anci.{yaml,bin}`, stamped with its source commit + a content digest so it's versioned and verifiable. Any AI tool can read it without re-indexing. |
|
|
34
|
+
| 🔐 **Verifiable** | Every container is stamped with its source commit, grammar versions, and a sha256 content digest. Same repo → same digest. Integrity is checked on load. |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Use Carto
|
|
39
|
+
|
|
40
|
+
| | |
|
|
41
|
+
|---|---|
|
|
42
|
+
| ### 🧑💻 I use AI coding tools | ### 🔧 I'm building AI dev tools |
|
|
43
|
+
| Install once and Carto auto-wires into every AI tool on your machine. Your assistant instantly knows your architecture, remembers past decisions, and gets blocked from risky edits. **[→ Quick start](#quick-start)** | Consume the portable container directly via the ANCI format, or query it live through a compact MCP surface (a core-10 plus parameterized families). Stop building your own index. **[→ Build on Carto](#build-on-carto)** |
|
|
44
|
+
|
|
45
|
+
**Works with:** Cursor · Claude Code · Codex · Kiro · Claude Desktop · Windsurf · VS Code Copilot · Zed · JetBrains
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Quick start
|
|
11
50
|
|
|
12
51
|
```bash
|
|
13
52
|
npm install -g carto-md
|
|
@@ -15,562 +54,252 @@ cd your-project
|
|
|
15
54
|
carto init
|
|
16
55
|
```
|
|
17
56
|
|
|
18
|
-
That's it.
|
|
57
|
+
That's it. `carto init` reads your repo, builds the container, and wires itself into every AI tool it finds. Restart the tool. Your AI now knows your codebase - and keeps a memory of every decision it makes inside it.
|
|
19
58
|
|
|
20
|
-
|
|
59
|
+
### Wiring it into your AI tool
|
|
21
60
|
|
|
22
|
-
|
|
61
|
+
`carto init` auto-detects the AI tools on your machine and writes each one's MCP config for you. If you'd rather wire it by hand, the MCP server config is just:
|
|
23
62
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"mcpServers": {
|
|
66
|
+
"carto": {
|
|
67
|
+
"command": "carto",
|
|
68
|
+
"args": ["serve"]
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
27
73
|
|
|
28
|
-
|
|
74
|
+
Point any MCP client at that and restart it - the tool spawns `carto serve` on demand, and every chat starts with your architecture, blast radius, and past decisions already loaded. Exact config file per tool is below.
|
|
29
75
|
|
|
30
|
-
|
|
76
|
+
<details>
|
|
77
|
+
<summary>Manual MCP wiring for every other tool (if it wasn't auto-detected)</summary>
|
|
31
78
|
|
|
32
|
-
|
|
79
|
+
### Cursor - `~/.cursor/mcp.json`
|
|
33
80
|
```json
|
|
34
81
|
{ "mcpServers": { "carto": { "command": "carto", "args": ["serve"], "cwd": "/your/project" } } }
|
|
35
82
|
```
|
|
36
83
|
|
|
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:
|
|
84
|
+
### Claude Code - `<project>/.mcp.json`
|
|
40
85
|
```bash
|
|
41
86
|
claude mcp add carto -- carto serve
|
|
42
87
|
```
|
|
43
|
-
Or create `.mcp.json` at the project root:
|
|
44
|
-
```json
|
|
45
|
-
{ "mcpServers": { "carto": { "command": "carto", "args": ["serve"] } } }
|
|
46
|
-
```
|
|
47
88
|
|
|
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`:
|
|
89
|
+
### Codex - `~/.codex/config.toml`
|
|
55
90
|
```toml
|
|
56
91
|
[mcp_servers.carto]
|
|
57
92
|
command = "carto"
|
|
58
93
|
args = ["serve"]
|
|
59
|
-
cwd = "/your/project"
|
|
60
|
-
enabled = true
|
|
61
94
|
```
|
|
62
95
|
|
|
63
|
-
### Kiro
|
|
64
|
-
|
|
65
|
-
`carto init` writes this for you. Manual: `~/.kiro/settings/mcp.json`
|
|
96
|
+
### Kiro - `~/.kiro/settings/mcp.json`
|
|
66
97
|
```json
|
|
67
98
|
{ "mcpServers": { "carto": { "command": "carto", "args": ["serve"], "cwd": "/your/project" } } }
|
|
68
99
|
```
|
|
69
100
|
|
|
70
101
|
### Claude Desktop
|
|
71
|
-
|
|
72
|
-
`carto init` writes this for you (cross-platform). Manual paths:
|
|
73
102
|
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
74
103
|
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
75
|
-
- Linux: `~/.config/Claude/claude_desktop_config.json`
|
|
104
|
+
- Linux: `~/.config/Claude/claude_desktop_config.json`
|
|
76
105
|
|
|
77
106
|
```json
|
|
78
107
|
{ "mcpServers": { "carto": { "command": "carto", "args": ["serve"], "cwd": "/your/project" } } }
|
|
79
108
|
```
|
|
80
109
|
|
|
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"`.
|
|
110
|
+
### VS Code Copilot - `.vscode/mcp.json`
|
|
84
111
|
```json
|
|
85
112
|
{ "servers": { "carto": { "type": "stdio", "command": "carto", "args": ["serve"] } } }
|
|
86
113
|
```
|
|
87
114
|
|
|
88
|
-
### Windsurf
|
|
89
|
-
|
|
90
|
-
`carto init` writes this for you when Windsurf is detected. Manual: `~/.codeium/windsurf/mcp_config.json`
|
|
115
|
+
### Windsurf - `~/.codeium/windsurf/mcp_config.json`
|
|
91
116
|
```json
|
|
92
117
|
{ "mcpServers": { "carto": { "command": "carto", "args": ["serve"], "cwd": "/your/project" } } }
|
|
93
118
|
```
|
|
94
119
|
|
|
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.
|
|
98
|
-
|
|
99
|
-
---
|
|
100
|
-
|
|
101
|
-
## What changes for your AI
|
|
102
|
-
|
|
103
|
-
Without carto, your AI greps text and guesses. With carto, it queries structural facts:
|
|
104
|
-
|
|
105
|
-
> *"Add rate limiting to /api/users"*
|
|
106
|
-
|
|
107
|
-
**Without carto:** AI grep-searches your codebase, finds 12 files mentioning "users", picks 3 at random, hopes for the best.
|
|
108
|
-
|
|
109
|
-
**With carto:** AI calls `get_change_plan("add rate limiting to /api/users")` and gets back:
|
|
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
|
|
120
|
+
</details>
|
|
115
121
|
|
|
116
|
-
|
|
122
|
+
### How it works
|
|
117
123
|
|
|
118
|
-
|
|
124
|
+
1. **`carto init` builds the container.** It parses your repo (imports, routes, models, domains, blast radius), writes it to `.carto/`, and auto-wires every AI tool on your machine.
|
|
125
|
+
2. **Your AI loads it instead of re-reading everything.** Every chat starts with the architecture already known - the right 6–12 files, not the usual 40+.
|
|
126
|
+
3. **Every proposed diff is checked first.** Risky changes are graded *before* they hit your screen - and `carto mcp-middleware` can block a HIGH-risk edit before it ever reaches disk. Carto also nudges: *"coupling jumped in AUTH," "two sessions are editing this file."*
|
|
127
|
+
4. **The container remembers - and knows when it's stale.** Decisions, validations, and drift accumulate in one SQLite file, so the next session picks up where the last left off. And if the repo moves ahead of the index, queries warn *"graph is N commits stale"* instead of silently serving old numbers.
|
|
119
128
|
|
|
120
|
-
|
|
129
|
+
---
|
|
121
130
|
|
|
122
|
-
|
|
131
|
+
## An index is not a container
|
|
123
132
|
|
|
124
|
-
|
|
125
|
-
# Diff Validation
|
|
133
|
+
Most tools build an **index** - a snapshot of what's in the repo *right now*. Stateless. Thrown away at the end of the session. Rebuilt from scratch by the next tool.
|
|
126
134
|
|
|
127
|
-
**
|
|
128
|
-
**Files changed:** 1
|
|
129
|
-
**Union blast radius:** 83 transitive dependents
|
|
135
|
+
A **container** is different: portable, versioned, and verifiable. Carto's engine keeps **five kinds of memory** a plain index can't - all queryable **live** over MCP:
|
|
130
136
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
```
|
|
137
|
+
- **Structural** - imports, routes, models, domains, blast radius.
|
|
138
|
+
- **Episodic** - every diff validated, every decision made. Queryable weeks later.
|
|
139
|
+
- **Temporal** - snapshots, churn, deltas. *"AUTH grew 18 files and lost stability when `billing.ts` moved out."*
|
|
140
|
+
- **Semantic** - invariants and conventions mined from the import graph, not declared by humans.
|
|
141
|
+
- **Procedural** - patterns mined from git history. *"When a route is added, auth middleware is touched 89% of the time."*
|
|
137
142
|
|
|
138
|
-
The
|
|
143
|
+
All five run live in the engine - one SQLite file (`.carto/carto.db`), queried over MCP. The **portable container file** - the open [ANCI](docs/anci/v0.1-DRAFT.md) export any tool can read *without* Carto's runtime - today carries the **structural core** (import graph, domains, routes, models, blast radius), stamped with its source commit + a content digest so it's versioned and verifiable. Making the other four memories portable *in the file* is on the roadmap.
|
|
139
144
|
|
|
140
|
-
|
|
145
|
+
Your AI tool sees files. Carto's container sees architecture, history, *and* consequences.
|
|
141
146
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-

|
|
147
|
+
---
|
|
145
148
|
|
|
146
|
-
|
|
149
|
+
## Is this Docker?
|
|
147
150
|
|
|
148
|
-
|
|
151
|
+
No. Docker containerizes **compute** - the OS, libraries, and binaries a CPU needs to run your code anywhere. Carto containerizes **context** - the import graph, blast radius, and structural boundaries an LLM needs to reason about your code without re-reading it.
|
|
149
152
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
### Import graph + symbols (any repo)
|
|
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.
|
|
153
|
+
There's no daemon, no image pull, no virtual network. A Carto container is just a lightweight `.carto/` folder: a local SQLite database plus an open [ANCI](docs/anci/v0.1-DRAFT.md) map. It costs nothing while idle, answers a blast-radius query in microseconds on a 7,500-file repo, and never touches the cloud. Any AI agent - Claude Code, Cursor, or your CI pipeline - taps into it instantly instead of re-indexing from scratch.
|
|
195
154
|
|
|
196
155
|
---
|
|
197
156
|
|
|
198
|
-
##
|
|
157
|
+
## Build once, load anywhere
|
|
199
158
|
|
|
200
|
-
|
|
159
|
+
The whole point of a container is that it's *one file you can move.* Build it on one machine, load it on another - no re-index, no Carto runtime needed to read it.
|
|
201
160
|
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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
|
|
161
|
+
```bash
|
|
162
|
+
# machine A - build and pack into a single file
|
|
163
|
+
carto init
|
|
164
|
+
carto export --out myrepo.anci # one file: yaml + bitmap + manifest
|
|
216
165
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
"agent_servers": {
|
|
221
|
-
"Carto": { "command": "carto", "args": ["agent"] }
|
|
222
|
-
}
|
|
223
|
-
}
|
|
166
|
+
# machine B - load it, no re-parsing the repo
|
|
167
|
+
carto load myrepo.anci # unpacks + verifies the content digest
|
|
168
|
+
carto impact src/auth/session.ts # blast radius, instantly
|
|
224
169
|
```
|
|
225
170
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
Carto supports any LLM provider — configure in your editor:
|
|
229
|
-
|
|
230
|
-
| Provider | Models |
|
|
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 |
|
|
171
|
+
Copy it, attach it to a release, or hand it to a teammate - the receiving machine gets the full structural container in seconds. The digest is verified on load, and loaded contents are treated as **untrusted data, never instructions.**
|
|
240
172
|
|
|
241
173
|
---
|
|
242
174
|
|
|
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.
|
|
246
|
-
|
|
247
|
-
`.github/workflows/carto.yml`:
|
|
248
|
-
```yaml
|
|
249
|
-
name: Carto Impact Report
|
|
250
|
-
|
|
251
|
-
on:
|
|
252
|
-
pull_request:
|
|
253
|
-
branches: [main]
|
|
175
|
+
## Under the hood
|
|
254
176
|
|
|
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
177
|
```
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
| Output | Description |
|
|
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
|
|
292
|
-
|
|
293
|
-
This PR touches AUTH and DATABASE domains.
|
|
294
|
-
|
|
295
|
-
| Metric | Value |
|
|
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) |
|
|
302
|
-
|
|
303
|
-
<details>
|
|
304
|
-
<summary>Affected routes (4)</summary>
|
|
305
|
-
|
|
306
|
-
- POST /auth/login — risk: HIGH
|
|
307
|
-
- GET /auth/me — risk: HIGH
|
|
308
|
-
- POST /auth/register — risk: MEDIUM
|
|
309
|
-
- POST /api/users — risk: LOW
|
|
310
|
-
|
|
311
|
-
</details>
|
|
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>
|
|
178
|
+
your repo
|
|
179
|
+
↓
|
|
180
|
+
carto init ──────────── parse (tree-sitter, 17 languages)
|
|
181
|
+
↓
|
|
182
|
+
┌─────────────────────────────────────────────────────┐
|
|
183
|
+
│ the container ── .carto/ │
|
|
184
|
+
│ │
|
|
185
|
+
│ ├── carto.db SQLite: graph, routes, models, │
|
|
186
|
+
│ │ domains, decisions, history │
|
|
187
|
+
│ ├── bitmap.bin Roaring Bitmap reverse-dep │
|
|
188
|
+
│ │ graph - blast radius in µs │
|
|
189
|
+
│ └── anci.{yaml,bin} portable open format - `carto export` │
|
|
190
|
+
│ packs it into one verifiable .anci file │
|
|
191
|
+
└─────────────────────────────────────────────────────┘
|
|
192
|
+
↓
|
|
193
|
+
your AI tool ── loads it via MCP (core-10 + families) or ANCI directly
|
|
320
194
|
```
|
|
321
195
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
The action is a thin wrapper around `carto pr-impact`. Use it locally, in custom CI, or in pre-commit hooks:
|
|
325
|
-
|
|
326
|
-
```bash
|
|
327
|
-
carto pr-impact --base origin/main --head HEAD # markdown to stdout
|
|
328
|
-
carto pr-impact --base origin/main --head HEAD --format json
|
|
329
|
-
carto pr-impact --base origin/main --head HEAD --fail-on HIGH # exit 2 on HIGH risk
|
|
330
|
-
```
|
|
196
|
+
**Blast radius is not search.** Search finds files that *mention* something. Blast radius finds files that *break* when you change something - transitively, over the real import graph. On a 7,500-file repo, one query returns in ~3 microseconds thanks to the bitmap engine.
|
|
331
197
|
|
|
332
198
|
---
|
|
333
199
|
|
|
334
|
-
##
|
|
335
|
-
|
|
336
|
-
Every AI coding tool today re-discovers a codebase's architecture from scratch on every session. Cursor builds its own embedding index. Cline builds its own. Continue builds its own. Same parsing, every tool, every session.
|
|
200
|
+
## Build on Carto
|
|
337
201
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
`carto sync` writes both files automatically. The header is grep-able YAML; the body is a compact binary import graph. Spec lives in [`docs/anci/v0.1-DRAFT.md`](docs/anci/v0.1-DRAFT.md). Carto is the reference implementation.
|
|
341
|
-
|
|
342
|
-
```bash
|
|
343
|
-
carto anci publish # re-emit anci.{yaml,bin} from the index
|
|
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:
|
|
202
|
+
The container is an open format. Read it without running Carto's engine:
|
|
349
203
|
|
|
350
204
|
```js
|
|
351
205
|
const { loadAnci } = require('carto-md/src/anci/consumer');
|
|
352
|
-
|
|
353
206
|
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
|
-
]));
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
> **Status:** v0.1.0-DRAFT — wire format may change up to v1.0. The reference implementation lives in this repo at `src/anci/`.
|
|
364
|
-
|
|
365
|
-
---
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
Once carto is wired in, your AI tool can call any of these mid-task. You don't need to memorize them — your AI will pick the right ones.
|
|
370
|
-
|
|
371
|
-
| Tool | What it returns |
|
|
372
|
-
|------|----------------|
|
|
373
|
-
| `get_architecture()` | 500-word project overview: domains, entry points, stack, key patterns. **Use this first.** |
|
|
374
|
-
| `get_change_plan(intent)` | Given "add rate limiting to /api/users" → files to touch, domains affected, blast radius, similar patterns |
|
|
375
|
-
| `get_blast_radius(file)` | All files affected by changing a given file, with hop distance |
|
|
376
|
-
| `simulate_change_impact(files)` | Union of all files transitively affected by changing **multiple** files at once. Powered by the bitmap engine — sub-millisecond on 7K-file repos. |
|
|
377
|
-
| `validate_diff(diff)` | Given a unified diff: violations (cross-domain imports, high-blast files), blast radius per file, risk level (SAFE/LOW/MEDIUM/HIGH), suggestions. Each call is recorded in the **episodic memory** log so other tools can ask "did we discuss this?". Sub-15ms p99. |
|
|
378
|
-
| `get_context(file)` | Everything about a file: domain, blast radius, neighbors, routes, models |
|
|
379
|
-
| `get_file_summary(file)` | What a file does, its role, key deps and dependents |
|
|
380
|
-
| `get_similar_patterns(file)` | Files with same domain, route shape, or shared deps — find conventions before writing new code |
|
|
381
|
-
| `get_routes()` | All API endpoints with file mapping |
|
|
382
|
-
| `get_structure()` | Import graph, entry points, high-impact files, tech stack |
|
|
383
|
-
| `get_domain(name)` | All routes, models, functions for a domain. Lazily regenerated when stale. |
|
|
384
|
-
| `get_neighbors(file, hops)` | Import graph neighbors: nodes and edges |
|
|
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
|
|
405
|
-
|
|
406
|
-
Carto uses **Leiden+CPM graph clustering** — files that import each other heavily cluster together. Domain names are inferred from path tokens, with keyword hints for well-known patterns (AUTH, PAYMENTS, DATABASE, etc.).
|
|
407
|
-
|
|
408
|
-
**Adaptive strategy:** Repos under 100 files use keyword-only clustering (avoids over-fragmentation). Larger repos with dense import graphs get graph-based clustering with a gamma that scales continuously with repo size.
|
|
409
|
-
|
|
410
|
-
Works on any repo — not just SaaS apps. vscode gets AUTH/EVENTS/DATABASE. zed (Rust) gets DATABASE/AUTH/EVENTS. A game engine would get RENDERER/PHYSICS/AUDIO.
|
|
411
|
-
|
|
412
|
-
Custom domains via `carto.config.json`:
|
|
413
|
-
```json
|
|
414
|
-
{
|
|
415
|
-
"domains": {
|
|
416
|
-
"EDITOR": ["editor", "monaco", "text"],
|
|
417
|
-
"WORKBENCH": ["workbench", "layout", "panel"]
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
```
|
|
421
207
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
{
|
|
425
|
-
"domains": {
|
|
426
|
-
"AUTH": {
|
|
427
|
-
"keywords": ["auth", "login", "session"],
|
|
428
|
-
"anchor": ["src/auth/session.ts", "src/auth/middleware.ts"]
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
}
|
|
208
|
+
reader.domains; // [{ name: 'AUTH', file_count: 42 }, ...]
|
|
209
|
+
reader.getHighImpactFiles(5); // top 5 by transitive dependents
|
|
210
|
+
reader.blastRadius('src/auth/session.ts'); // { count, hops, files: [...] }
|
|
432
211
|
```
|
|
433
212
|
|
|
434
|
-
|
|
213
|
+
Or query it live through the MCP server your AI tool already runs.
|
|
435
214
|
|
|
436
215
|
---
|
|
437
216
|
|
|
438
|
-
##
|
|
217
|
+
## Tools your AI can call
|
|
439
218
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
| `carto init` | Detect project, index codebase, generate AGENTS.md, install git hooks (pre-commit, post-checkout, post-merge, post-rewrite), auto-wire MCP into every AI tool found |
|
|
443
|
-
| `carto sync` | Full re-index (skips unchanged files via mtime+size cache). Called automatically by git hooks on commit/checkout/merge/rebase. |
|
|
444
|
-
| `carto serve` | Start MCP server (called by your AI tool — usually you don't run this directly). On every file-aware query the server mtime+size-checks the file and re-parses inline if stale. |
|
|
445
|
-
| `carto watch` | **Optional.** Live re-index on every file save. Not required — git hooks + lazy MCP re-parse keep the index fresh by default. Use only for AI-heavy workflows that write 50+ files between commits. |
|
|
446
|
-
| `carto agent` | Start ACP agent mode (for Zed / JetBrains / VS Code) |
|
|
447
|
-
| `carto impact <file>` | Blast radius: risk level, affected files, routes at risk |
|
|
448
|
-
| `carto pr-impact` | Diff-shaped impact report between two git refs. Markdown (default) or JSON. Used by the [GitHub Action](#github-action--pr-impact-reports); works locally too. `--fail-on HIGH\|MEDIUM\|LOW` exits non-zero on threshold trip. |
|
|
449
|
-
| `carto check` | Cross-domain violations, high-risk uncommitted changes, domain health |
|
|
450
|
-
| `carto inspect` | Read-only diagnostic: index paths, sizes, freshness, bitmap sidecar shape, top-impact files, schema version, sync timestamps. `--json` for piping into `jq`. Never triggers a rebuild. |
|
|
451
|
-
| `carto remove` | Remove AGENTS.md and .carto/ from project |
|
|
219
|
+
A small **core** is exposed by default (≈10 tools), with the rest collapsed into a handful of
|
|
220
|
+
**parameterized families** - so your AI tool spends its context on your codebase, not on a tool menu.
|
|
452
221
|
|
|
453
|
-
|
|
222
|
+
| Core tool | What it's for |
|
|
223
|
+
|---|---|
|
|
224
|
+
| `get_architecture` · `get_context` | Orient in the repo; full context for one file |
|
|
225
|
+
| `impact` | Blast radius / multi-file simulate / neighbors / data flow - *what breaks if I touch this?* (`mode=`) |
|
|
226
|
+
| `validate_diff` | Grade a proposed diff (risk + violations) |
|
|
227
|
+
| `get_change_plan` | Natural-language intent → files to touch |
|
|
228
|
+
| `memory` | Episodic memory - search past decisions, logs, sessions, interventions (`kind=`) |
|
|
229
|
+
| `history` | Temporal history - drift, hotspots, evolution, churn, health (`view=`) |
|
|
230
|
+
| `patterns` | Mined invariants / conventions / canonical exemplar / co-change patterns (`kind=`) |
|
|
231
|
+
| `get_predictive_risk` · `get_minimal_context_for_intent` | Risk score per file; token-budgeted context picker |
|
|
454
232
|
|
|
455
|
-
|
|
233
|
+
Beyond the core, `org(view=…)` covers multi-repo, and advanced/experimental tools (`get_routes`,
|
|
234
|
+
`get_models`, `get_gaps`, `scaffold_for_intent`, …) are available by widening the surface with
|
|
235
|
+
`CARTO_MCP_TIER=advanced` (or `all`), or `carto.config.json` → `mcp.tier`. The ~30 former sibling
|
|
236
|
+
tools (`get_blast_radius`, `did_we_discuss_this`, …) still resolve as **deprecated shims** that
|
|
237
|
+
forward to the new families with byte-identical output.
|
|
456
238
|
|
|
457
|
-
|
|
239
|
+
Full reference at [`docs/api/`](docs/api/). You don't need to memorize any of these - your AI picks the right one mid-task.
|
|
458
240
|
|
|
459
|
-
|
|
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) |
|
|
483
|
-
|
|
484
|
-
Median speedup across all five tools on vscode: **10.7×**. Smaller repos with denser graphs hit higher peaks — supabase `get_high_impact_files` clocks well over 100× on its tighter import graph. Reproducible via `npm run bench:bitmap -- --repo <path>`.
|
|
485
|
-
|
|
486
|
-
### `validate_diff` latency
|
|
487
|
-
|
|
488
|
-
The new diff-shaped query that lets the AI ask "is this patch safe?" before showing it to the user. Profiled with a representative 20-line diff against 20 random mid-blast-radius files per repo, 1000 calls each.
|
|
489
|
-
|
|
490
|
-
| Repo | Files | p50 | p99 |
|
|
491
|
-
|------|-------|----:|----:|
|
|
492
|
-
| supabase | 6,259 | **0.082ms** | **0.298ms** |
|
|
493
|
-
| vscode | 7,567 | **0.084ms** | **0.489ms** |
|
|
241
|
+
---
|
|
494
242
|
|
|
495
|
-
|
|
243
|
+
## How fast
|
|
496
244
|
|
|
497
|
-
|
|
245
|
+
Fresh runs on real open-source repos (Apple M-series, 8 CPUs, 8 GB RAM):
|
|
498
246
|
|
|
499
|
-
|
|
247
|
+
| Repo | Files | First index | Re-index | Container size |
|
|
248
|
+
|---|--:|--:|--:|--:|
|
|
249
|
+
| [cal.com](https://github.com/calcom/cal.com) | 4,352 | 3.9s | 805ms | 3.1 MB |
|
|
250
|
+
| [supabase/supabase](https://github.com/supabase/supabase) | 6,358 | 5.9s | 967ms | 4.8 MB |
|
|
251
|
+
| [vercel/next.js](https://github.com/vercel/next.js) | 6,193 | 6.9s | 978ms | 15.1 MB |
|
|
252
|
+
| [microsoft/vscode](https://github.com/microsoft/vscode) | 7,567 | 8.6s | 1.1s | 14.3 MB |
|
|
500
253
|
|
|
501
|
-
|
|
502
|
-
- Real-world (vscode, 7,567 files): `blast_radius` p50 2.7µs, `cross_domain` p50 1.23ms, `similar_patterns` p50 834ns, `simulate_change_impact` p50 19µs.
|
|
254
|
+
Query latency on vscode (7,567 files): `validate_diff` p50 **84 µs** · `get_blast_radius` p50 **2.7 µs** · `get_high_impact_files` p50 **750 ns**. Full table in [`docs/scale.md`](docs/scale.md).
|
|
503
255
|
|
|
504
|
-
|
|
256
|
+
---
|
|
505
257
|
|
|
506
|
-
|
|
258
|
+
## Languages
|
|
507
259
|
|
|
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 |
|
|
260
|
+
**Import graph + symbols:** JavaScript/TypeScript · Python · Go · Rust · Java/Kotlin · C/C++ · C# · Ruby · PHP · Swift · Dart · R · Prisma · HTML
|
|
514
261
|
|
|
515
|
-
|
|
262
|
+
**Routes:** Express · Next.js · tRPC · React Router · FastAPI · Flask · Django · Gin · Echo · Chi · Actix · Axum · Rocket · Spring · JAX-RS · ASP.NET · Rails · Sinatra
|
|
516
263
|
|
|
517
|
-
|
|
264
|
+
**Models:** Prisma · Zod · Drizzle · Pydantic · SQLAlchemy · Django · Go structs · Rust structs · JPA · ActiveRecord · Eloquent
|
|
518
265
|
|
|
519
|
-
|
|
266
|
+
> _Planned (not yet extracted end-to-end):_ EF Core.
|
|
520
267
|
|
|
521
268
|
---
|
|
522
269
|
|
|
523
|
-
##
|
|
270
|
+
## CLI
|
|
524
271
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
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
|
-
```
|
|
272
|
+
| Command | What it does |
|
|
273
|
+
|---|---|
|
|
274
|
+
| `carto init` | Build the container, generate AGENTS.md, install git hooks, wire every AI tool found |
|
|
275
|
+
| `carto sync` | Re-build changed files (auto-runs on commit / checkout / merge / rebase) |
|
|
276
|
+
| `carto export` | Pack the container into one portable, verifiable `.anci` file |
|
|
277
|
+
| `carto load <file>` | Load an `.anci` container into a queryable `.carto/` - no re-index, digest verified |
|
|
278
|
+
| `carto serve` | Start the MCP server (your AI tool runs this) |
|
|
279
|
+
| `carto impact <file>` | Blast radius of one file |
|
|
280
|
+
| `carto pr-impact` | Diff-shaped impact report between two refs |
|
|
281
|
+
| `carto check` | Domain health, cross-domain violations, drift |
|
|
282
|
+
| `carto status` | One-screen project health |
|
|
283
|
+
| `carto doctor` | 9-check setup diagnostic |
|
|
284
|
+
| `carto why <file>` | 3-line file summary |
|
|
285
|
+
| `carto explain <intent>` | Natural-language intent → architectural plan |
|
|
554
286
|
|
|
555
287
|
---
|
|
556
288
|
|
|
557
289
|
## What Carto never does
|
|
558
290
|
|
|
559
|
-
- **Sends your code anywhere.** Local only. SQLite on disk.
|
|
560
|
-
- **Writes secrets into
|
|
561
|
-
- **Touches your manual notes.**
|
|
562
|
-
- **
|
|
563
|
-
- **Costs money.** MIT license. Free forever.
|
|
291
|
+
- **Sends your code anywhere.** Local only. SQLite on disk. No telemetry.
|
|
292
|
+
- **Writes secrets into the container.** `.cartoignore` blocks `.env` and credential files by default.
|
|
293
|
+
- **Touches your manual notes.** Only writes between `<!-- CARTO:AUTO -->` markers.
|
|
294
|
+
- **Costs money.** MIT. Free forever.
|
|
564
295
|
|
|
565
296
|
---
|
|
566
297
|
|
|
567
298
|
## Origin
|
|
568
299
|
|
|
569
|
-
I was building [Emfirge](https://www.emfirge.cloud)
|
|
570
|
-
|
|
571
|
-
To make the AI inside Emfirge understand infrastructure, I wrote a module called `cartography.py`. It mapped AWS resources, built a graph of how they connected, and wrote it into a structured map. The AI stopped hallucinating. It worked with facts, not guesses.
|
|
300
|
+
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. The AI inside it kept hallucinating about resources it had only half-seen, so I wrote a module that mapped every account into a structured graph the AI could query directly. The hallucinations stopped.
|
|
572
301
|
|
|
573
|
-
Carto is
|
|
302
|
+
Carto is that idea, applied to source code: package a system into a container the AI can query - and it stops guessing, and stops forgetting.
|
|
574
303
|
|
|
575
304
|
---
|
|
576
305
|
|
|
@@ -580,4 +309,4 @@ MIT. Free forever.
|
|
|
580
309
|
|
|
581
310
|
---
|
|
582
311
|
|
|
583
|
-
*Your code changes. Carto knows. Every AI you use knows.*
|
|
312
|
+
*Your code changes. Carto knows. Every AI you use knows - and remembers.*
|