ctxloom-pro 1.0.24 → 1.0.26
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/README.md +25 -25
- package/apps/dashboard/dist/server/index.js +12 -5
- package/dist/{chunk-O4TQWLH6.js → chunk-GI354NTO.js} +4 -4
- package/dist/{chunk-TVQ7CBWU.js → chunk-NYBVAPM3.js} +13 -6
- package/dist/{embedder-VHOY4L6L.js → embedder-ZGEKFHHK.js} +2 -2
- package/dist/index.js +155 -19
- package/dist/setup/postinstall.js +5 -2
- package/dist/{src-BYFMDHDZ.js → src-BRXQZ22F.js} +3 -3
- package/dist/workers/indexerWorker.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,70 +10,70 @@ No cloud indexing. No Python. Everything runs on your machine.
|
|
|
10
10
|
|
|
11
11
|
**Prerequisites:** Node.js 20+ and an MCP-compatible AI tool (Claude Code, Cursor, Windsurf, etc.)
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
The full first-run flow is **one install + one trial + one init per project.** Each step is a single command.
|
|
14
|
+
|
|
15
|
+
### 1 — Install (once per machine)
|
|
14
16
|
|
|
15
17
|
```bash
|
|
16
|
-
# 1. Install globally
|
|
17
18
|
npm install -g ctxloom-pro
|
|
18
|
-
|
|
19
|
-
# 2. Auto-configure your AI tools (one-time)
|
|
20
|
-
ctxloom setup
|
|
21
|
-
|
|
22
|
-
# 3. Index your project (once per project)
|
|
23
|
-
cd /path/to/your/project
|
|
24
|
-
ctxloom index
|
|
25
19
|
```
|
|
26
20
|
|
|
27
|
-
### 2 — Start your free trial
|
|
21
|
+
### 2 — Start your free trial (once per email)
|
|
28
22
|
|
|
29
23
|
```bash
|
|
30
24
|
ctxloom trial
|
|
31
25
|
# Enter your email — a checkout link opens in your browser.
|
|
32
|
-
# No credit card. After checkout,
|
|
26
|
+
# No credit card required. After checkout, you receive a license key by email.
|
|
33
27
|
```
|
|
34
28
|
|
|
35
29
|
Already have a key?
|
|
36
30
|
|
|
37
31
|
```bash
|
|
38
|
-
ctxloom activate
|
|
32
|
+
ctxloom activate <your-key>
|
|
39
33
|
```
|
|
40
34
|
|
|
41
|
-
### 3 —
|
|
35
|
+
### 3 — Configure your AI tools (once per machine)
|
|
42
36
|
|
|
43
37
|
```bash
|
|
44
|
-
ctxloom setup
|
|
38
|
+
ctxloom setup
|
|
39
|
+
# Detects Claude Code, Cursor, Windsurf, Claude Desktop, Codex,
|
|
40
|
+
# Kimi, Continue, Aider, Augment, Kilo, Qwen, JetBrains, VS Code —
|
|
41
|
+
# writes the global MCP entry for each one you have installed.
|
|
45
42
|
```
|
|
46
43
|
|
|
47
|
-
### 4 —
|
|
44
|
+
### 4 — Bootstrap each project (once per project)
|
|
48
45
|
|
|
49
46
|
```bash
|
|
50
47
|
cd /path/to/your/project
|
|
48
|
+
ctxloom init # writes .mcp.json + appends .ctxloom/ to .gitignore
|
|
51
49
|
ctxloom index # builds vector + graph + git overlay
|
|
52
50
|
```
|
|
53
51
|
|
|
54
|
-
|
|
52
|
+
`ctxloom init` is the piece that pins ctxloom to **this** project. Without it, MCP clients (notably Claude Code) launch the global MCP server with cwd inherited from wherever the IDE was first opened — and **do not relaunch on project switch** — so a single Claude Code session ends up serving graph queries from the wrong codebase. The `.mcp.json` produced by `init` carries an explicit `CTXLOOM_ROOT` and short-circuits that ambiguity.
|
|
53
|
+
|
|
54
|
+
After `init` + `index`, reopen your AI tool in the project directory. Your assistant now has full structural context.
|
|
55
55
|
|
|
56
56
|
### License commands
|
|
57
57
|
|
|
58
58
|
```bash
|
|
59
|
-
ctxloom status #
|
|
59
|
+
ctxloom status # tier, expiry, last validation
|
|
60
60
|
ctxloom deactivate # release this machine's seat (to move to a new machine)
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
### CI / headless environments
|
|
64
64
|
|
|
65
65
|
```bash
|
|
66
|
-
CTXLOOM_LICENSE_KEY
|
|
66
|
+
CTXLOOM_LICENSE_KEY=<your-key> ctxloom index
|
|
67
67
|
```
|
|
68
68
|
|
|
69
69
|
Set `CTXLOOM_LICENSE_KEY` in your CI secrets. The key is validated on every run — no local state written to the runner.
|
|
70
70
|
|
|
71
|
-
### Manual MCP
|
|
71
|
+
### Manual MCP configuration (if you skip `ctxloom setup`)
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
Global MCP entry — match this in your client's config file by hand:
|
|
74
74
|
|
|
75
75
|
```jsonc
|
|
76
|
-
// Claude Code: ~/.claude.json
|
|
76
|
+
// Claude Code: ~/.claude.json or .mcp.json in the project
|
|
77
77
|
// Cursor: ~/.cursor/mcp.json
|
|
78
78
|
// Codex CLI: ~/.codex/mcp.json
|
|
79
79
|
// Kimi: ~/.kimi/mcp.json
|
|
@@ -88,9 +88,9 @@ This is what `ctxloom setup` writes for you. Match it by hand if you prefer:
|
|
|
88
88
|
}
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
Then run `ctxloom init` inside each project — it writes a `.mcp.json` in the project root with `env.CTXLOOM_ROOT` set, which overrides the global entry on a per-project basis (Claude Code, Cursor, and the other MCP-aware clients merge per-project config over global automatically).
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
If you have a single fixed project (e.g. a CI runner or a Claude Desktop session with no project concept), pin the global entry directly:
|
|
94
94
|
|
|
95
95
|
```jsonc
|
|
96
96
|
{
|
|
@@ -103,8 +103,8 @@ For hosts without a project concept (Claude Desktop, CI), set the root explicitl
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
```
|
|
106
|
-
|
|
107
|
-
> Pricing: **Pro** €9.90/mo or €99/yr (1
|
|
106
|
+
|
|
107
|
+
> Pricing: **Pro** €9.90/mo or €99/yr (1 seat) · **Team** €29.90/mo or €299/yr (5 seats) · [ctxloom.com/pricing](https://ctxloom.com/pricing)
|
|
108
108
|
|
|
109
109
|
---
|
|
110
110
|
|
|
@@ -82,17 +82,24 @@ import fs3 from "fs";
|
|
|
82
82
|
import path3 from "path";
|
|
83
83
|
function collectFiles(dir, results = []) {
|
|
84
84
|
const IGNORED_DIRS = /* @__PURE__ */ new Set([
|
|
85
|
+
// Build artifacts + dependency caches
|
|
85
86
|
"node_modules",
|
|
86
|
-
".git",
|
|
87
87
|
"dist",
|
|
88
88
|
"build",
|
|
89
|
-
"
|
|
89
|
+
"out",
|
|
90
|
+
"target",
|
|
90
91
|
"coverage",
|
|
92
|
+
".cache",
|
|
93
|
+
".turbo",
|
|
91
94
|
".next",
|
|
92
95
|
".nuxt",
|
|
93
|
-
|
|
94
|
-
".
|
|
95
|
-
".
|
|
96
|
+
// Version control + ctxloom state
|
|
97
|
+
".git",
|
|
98
|
+
".ctxloom",
|
|
99
|
+
// Other tools' working state (often contains duplicated source)
|
|
100
|
+
".claude",
|
|
101
|
+
".code-review-graph",
|
|
102
|
+
".vscode-test"
|
|
96
103
|
]);
|
|
97
104
|
const SUPPORTED_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
98
105
|
".ts",
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
collectFiles,
|
|
6
6
|
generateEmbedding
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-NYBVAPM3.js";
|
|
8
8
|
import {
|
|
9
9
|
logger
|
|
10
10
|
} from "./chunk-TYDMSHV7.js";
|
|
@@ -6583,7 +6583,7 @@ function registerFullTextSearchTool(registry, ctx) {
|
|
|
6583
6583
|
const { query, mode, case_sensitive, limit, context_lines } = Schema22.parse(args);
|
|
6584
6584
|
if (mode === "semantic") {
|
|
6585
6585
|
try {
|
|
6586
|
-
const { generateEmbedding: generateEmbedding2 } = await import("./embedder-
|
|
6586
|
+
const { generateEmbedding: generateEmbedding2 } = await import("./embedder-ZGEKFHHK.js");
|
|
6587
6587
|
const store = await ctx.getStore();
|
|
6588
6588
|
const embedding = await generateEmbedding2(query);
|
|
6589
6589
|
const results = await store.search(embedding, limit);
|
|
@@ -6620,7 +6620,7 @@ function registerFullTextSearchTool(registry, ctx) {
|
|
|
6620
6620
|
let merged = keywordResults.slice(0, limit);
|
|
6621
6621
|
if (mode === "hybrid") {
|
|
6622
6622
|
try {
|
|
6623
|
-
const { generateEmbedding: generateEmbedding2 } = await import("./embedder-
|
|
6623
|
+
const { generateEmbedding: generateEmbedding2 } = await import("./embedder-ZGEKFHHK.js");
|
|
6624
6624
|
const store = await ctx.getStore();
|
|
6625
6625
|
const embedding = await generateEmbedding2(query);
|
|
6626
6626
|
const vectorResults = await store.search(embedding, Math.ceil(limit / 2));
|
|
@@ -8741,4 +8741,4 @@ export {
|
|
|
8741
8741
|
track,
|
|
8742
8742
|
captureError
|
|
8743
8743
|
};
|
|
8744
|
-
//# sourceMappingURL=chunk-
|
|
8744
|
+
//# sourceMappingURL=chunk-GI354NTO.js.map
|
|
@@ -63,17 +63,24 @@ async function generateEmbedding(text) {
|
|
|
63
63
|
}
|
|
64
64
|
function collectFiles(dir, results = []) {
|
|
65
65
|
const IGNORED_DIRS = /* @__PURE__ */ new Set([
|
|
66
|
+
// Build artifacts + dependency caches
|
|
66
67
|
"node_modules",
|
|
67
|
-
".git",
|
|
68
68
|
"dist",
|
|
69
69
|
"build",
|
|
70
|
-
"
|
|
70
|
+
"out",
|
|
71
|
+
"target",
|
|
71
72
|
"coverage",
|
|
73
|
+
".cache",
|
|
74
|
+
".turbo",
|
|
72
75
|
".next",
|
|
73
76
|
".nuxt",
|
|
74
|
-
|
|
75
|
-
".
|
|
76
|
-
".
|
|
77
|
+
// Version control + ctxloom state
|
|
78
|
+
".git",
|
|
79
|
+
".ctxloom",
|
|
80
|
+
// Other tools' working state (often contains duplicated source)
|
|
81
|
+
".claude",
|
|
82
|
+
".code-review-graph",
|
|
83
|
+
".vscode-test"
|
|
77
84
|
]);
|
|
78
85
|
const SUPPORTED_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
79
86
|
".ts",
|
|
@@ -173,4 +180,4 @@ export {
|
|
|
173
180
|
collectFiles,
|
|
174
181
|
indexDirectory
|
|
175
182
|
};
|
|
176
|
-
//# sourceMappingURL=chunk-
|
|
183
|
+
//# sourceMappingURL=chunk-NYBVAPM3.js.map
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
collectFiles,
|
|
4
4
|
generateEmbedding,
|
|
5
5
|
indexDirectory
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-NYBVAPM3.js";
|
|
7
7
|
import "./chunk-TYDMSHV7.js";
|
|
8
8
|
export {
|
|
9
9
|
EMBEDDING_DIMENSION,
|
|
@@ -11,4 +11,4 @@ export {
|
|
|
11
11
|
generateEmbedding,
|
|
12
12
|
indexDirectory
|
|
13
13
|
};
|
|
14
|
-
//# sourceMappingURL=embedder-
|
|
14
|
+
//# sourceMappingURL=embedder-ZGEKFHHK.js.map
|
package/dist/index.js
CHANGED
|
@@ -34,14 +34,14 @@ import {
|
|
|
34
34
|
startTrial,
|
|
35
35
|
track,
|
|
36
36
|
writeCODEOWNERS
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-GI354NTO.js";
|
|
38
38
|
import {
|
|
39
39
|
VectorStore
|
|
40
40
|
} from "./chunk-NEHYSE2Y.js";
|
|
41
41
|
import {
|
|
42
42
|
generateEmbedding,
|
|
43
43
|
indexDirectory
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-NYBVAPM3.js";
|
|
45
45
|
import {
|
|
46
46
|
logger
|
|
47
47
|
} from "./chunk-TYDMSHV7.js";
|
|
@@ -423,13 +423,114 @@ function printNextSteps() {
|
|
|
423
423
|
console.log(` ${C.bold}Next steps:${C.reset}`);
|
|
424
424
|
console.log("");
|
|
425
425
|
console.log(` 1. ${C.cyan}cd /path/to/your/project${C.reset}`);
|
|
426
|
-
console.log(` 2. ${C.cyan}ctxloom
|
|
427
|
-
console.log(` 3. ${C.dim}
|
|
426
|
+
console.log(` 2. ${C.cyan}ctxloom init${C.reset} ${C.dim}# Pin ctxloom to this project (.mcp.json + .gitignore)${C.reset}`);
|
|
427
|
+
console.log(` 3. ${C.cyan}ctxloom index${C.reset} ${C.dim}# Build the dependency graph${C.reset}`);
|
|
428
|
+
console.log(` 4. ${C.dim}Open your AI tool in this directory \u2014 ctxloom provides context automatically${C.reset}`);
|
|
428
429
|
console.log("");
|
|
429
430
|
console.log(` ${C.dim}Documentation: https://ctxloom.dev/docs${C.reset}`);
|
|
430
431
|
console.log("");
|
|
431
432
|
}
|
|
432
433
|
|
|
434
|
+
// src/setup/init.ts
|
|
435
|
+
import fs2 from "fs";
|
|
436
|
+
import path2 from "path";
|
|
437
|
+
function runInit(cwd = process.cwd()) {
|
|
438
|
+
const root = path2.resolve(cwd);
|
|
439
|
+
const stat = fs2.statSync(root);
|
|
440
|
+
if (!stat.isDirectory()) {
|
|
441
|
+
throw new Error(`ctxloom init: ${root} is not a directory`);
|
|
442
|
+
}
|
|
443
|
+
const warnings = [];
|
|
444
|
+
if (!fs2.existsSync(path2.join(root, ".git"))) {
|
|
445
|
+
warnings.push(
|
|
446
|
+
"No .git directory found here. ctxloom init still works, but most graph features (git coupling, risk overlay, churn) require git history."
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
const mcpJson = writeMcpJson(root);
|
|
450
|
+
const gitignore = appendGitignore(root);
|
|
451
|
+
return { cwd: root, mcpJson, gitignore, warnings };
|
|
452
|
+
}
|
|
453
|
+
function buildCtxloomEntry(projectRoot) {
|
|
454
|
+
return {
|
|
455
|
+
command: "ctxloom",
|
|
456
|
+
args: [],
|
|
457
|
+
env: { CTXLOOM_ROOT: projectRoot }
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
function writeMcpJson(projectRoot) {
|
|
461
|
+
const mcpPath = path2.join(projectRoot, ".mcp.json");
|
|
462
|
+
const entry = buildCtxloomEntry(projectRoot);
|
|
463
|
+
if (!fs2.existsSync(mcpPath)) {
|
|
464
|
+
const payload = { mcpServers: { ctxloom: entry } };
|
|
465
|
+
fs2.writeFileSync(mcpPath, JSON.stringify(payload, null, 2) + "\n", "utf-8");
|
|
466
|
+
return { path: mcpPath, created: true, merged: false, alreadyCorrect: false };
|
|
467
|
+
}
|
|
468
|
+
const raw = fs2.readFileSync(mcpPath, "utf-8");
|
|
469
|
+
let parsed2;
|
|
470
|
+
try {
|
|
471
|
+
parsed2 = JSON.parse(raw);
|
|
472
|
+
} catch {
|
|
473
|
+
throw new Error(
|
|
474
|
+
`ctxloom init: ${mcpPath} is not valid JSON. Fix the file and re-run, or remove it and re-run init to regenerate.`
|
|
475
|
+
);
|
|
476
|
+
}
|
|
477
|
+
if (!parsed2.mcpServers || typeof parsed2.mcpServers !== "object") {
|
|
478
|
+
parsed2.mcpServers = {};
|
|
479
|
+
}
|
|
480
|
+
const servers = parsed2.mcpServers;
|
|
481
|
+
const existing = servers["ctxloom"];
|
|
482
|
+
const sameRoot = existing && typeof existing === "object" && existing.env && typeof existing.env === "object" && existing.env.CTXLOOM_ROOT === projectRoot;
|
|
483
|
+
if (sameRoot) {
|
|
484
|
+
return { path: mcpPath, created: false, merged: false, alreadyCorrect: true };
|
|
485
|
+
}
|
|
486
|
+
servers["ctxloom"] = entry;
|
|
487
|
+
fs2.writeFileSync(mcpPath, JSON.stringify(parsed2, null, 2) + "\n", "utf-8");
|
|
488
|
+
return { path: mcpPath, created: false, merged: true, alreadyCorrect: false };
|
|
489
|
+
}
|
|
490
|
+
var GITIGNORE_BANNER = "# ctxloom local index (machine-specific, do not commit)";
|
|
491
|
+
var GITIGNORE_PATTERN = ".ctxloom/";
|
|
492
|
+
function appendGitignore(projectRoot) {
|
|
493
|
+
const gitignorePath = path2.join(projectRoot, ".gitignore");
|
|
494
|
+
if (!fs2.existsSync(gitignorePath)) {
|
|
495
|
+
const content = `${GITIGNORE_BANNER}
|
|
496
|
+
${GITIGNORE_PATTERN}
|
|
497
|
+
`;
|
|
498
|
+
fs2.writeFileSync(gitignorePath, content, "utf-8");
|
|
499
|
+
return {
|
|
500
|
+
path: gitignorePath,
|
|
501
|
+
created: true,
|
|
502
|
+
appended: true,
|
|
503
|
+
alreadyPresent: false
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
const raw = fs2.readFileSync(gitignorePath, "utf-8");
|
|
507
|
+
const alreadyPresent = raw.split("\n").some((line) => {
|
|
508
|
+
const trimmed = line.trim();
|
|
509
|
+
if (trimmed.startsWith("#") || trimmed.startsWith("!")) return false;
|
|
510
|
+
return trimmed === ".ctxloom" || trimmed === ".ctxloom/" || trimmed === "/.ctxloom" || trimmed === "/.ctxloom/";
|
|
511
|
+
});
|
|
512
|
+
if (alreadyPresent) {
|
|
513
|
+
return {
|
|
514
|
+
path: gitignorePath,
|
|
515
|
+
created: false,
|
|
516
|
+
appended: false,
|
|
517
|
+
alreadyPresent: true
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
const sep = raw.endsWith("\n") ? "" : "\n";
|
|
521
|
+
const addition = `${sep}
|
|
522
|
+
${GITIGNORE_BANNER}
|
|
523
|
+
${GITIGNORE_PATTERN}
|
|
524
|
+
`;
|
|
525
|
+
fs2.appendFileSync(gitignorePath, addition, "utf-8");
|
|
526
|
+
return {
|
|
527
|
+
path: gitignorePath,
|
|
528
|
+
created: false,
|
|
529
|
+
appended: true,
|
|
530
|
+
alreadyPresent: false
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
|
|
433
534
|
// src/cli/format.ts
|
|
434
535
|
import pc from "picocolors";
|
|
435
536
|
var isTTY = process.stdout.isTTY === true;
|
|
@@ -501,7 +602,7 @@ ${body}
|
|
|
501
602
|
import { execSync } from "child_process";
|
|
502
603
|
import * as readline from "readline";
|
|
503
604
|
import os from "os";
|
|
504
|
-
import
|
|
605
|
+
import path3 from "path";
|
|
505
606
|
try {
|
|
506
607
|
const proc = process;
|
|
507
608
|
if (typeof proc.getrlimit === "function" && typeof proc.setrlimit === "function") {
|
|
@@ -512,7 +613,7 @@ try {
|
|
|
512
613
|
} catch {
|
|
513
614
|
}
|
|
514
615
|
var args = process.argv.slice(2);
|
|
515
|
-
var ctxloomVersion = "1.0.
|
|
616
|
+
var ctxloomVersion = "1.0.26".length > 0 ? "1.0.26" : "dev";
|
|
516
617
|
if (args.includes("--version") || args.includes("-v")) {
|
|
517
618
|
process.stdout.write(`ctxloom ${ctxloomVersion}
|
|
518
619
|
`);
|
|
@@ -585,7 +686,7 @@ async function checkLicense() {
|
|
|
585
686
|
if (command !== void 0 && LICENSE_GATE_BYPASS_COMMANDS.has(command)) return;
|
|
586
687
|
const ciKey = process.env["CTXLOOM_LICENSE_KEY"];
|
|
587
688
|
if (ciKey) {
|
|
588
|
-
const { ApiClient } = await import("./src-
|
|
689
|
+
const { ApiClient } = await import("./src-BRXQZ22F.js");
|
|
589
690
|
const client = new ApiClient(process.env["CTXLOOM_API_BASE"]);
|
|
590
691
|
try {
|
|
591
692
|
const result = await client.validate(ciKey, "ci-ephemeral");
|
|
@@ -878,9 +979,43 @@ async function main() {
|
|
|
878
979
|
await runSetupWizard();
|
|
879
980
|
break;
|
|
880
981
|
}
|
|
982
|
+
case "init": {
|
|
983
|
+
process.stdout.write(header("Init"));
|
|
984
|
+
const initRoot = process.cwd();
|
|
985
|
+
process.stdout.write(` ${style.dim("Root:")} ${initRoot}
|
|
986
|
+
|
|
987
|
+
`);
|
|
988
|
+
try {
|
|
989
|
+
const result = runInit(initRoot);
|
|
990
|
+
const mcpLabel = result.mcpJson.created ? `${style.bold("Created")} ${result.mcpJson.path}` : result.mcpJson.merged ? `${style.bold("Merged ctxloom entry into")} ${result.mcpJson.path}` : `${style.dim("Already up to date:")} ${result.mcpJson.path}`;
|
|
991
|
+
process.stdout.write(` ${success(mcpLabel)}
|
|
992
|
+
`);
|
|
993
|
+
const giLabel = result.gitignore.created ? `${style.bold("Created")} ${result.gitignore.path} (added .ctxloom/)` : result.gitignore.appended ? `${style.bold("Appended .ctxloom/ to")} ${result.gitignore.path}` : `${style.dim(".ctxloom/ already in")} ${result.gitignore.path}`;
|
|
994
|
+
process.stdout.write(` ${success(giLabel)}
|
|
995
|
+
`);
|
|
996
|
+
for (const w of result.warnings) {
|
|
997
|
+
process.stdout.write(` ${warn(w)}
|
|
998
|
+
`);
|
|
999
|
+
}
|
|
1000
|
+
process.stdout.write("\n");
|
|
1001
|
+
process.stdout.write(nextStep("Build the index", "ctxloom index"));
|
|
1002
|
+
process.stdout.write(
|
|
1003
|
+
` ${style.dim("Then reopen your AI tool in this directory to pick up the new .mcp.json.")}
|
|
1004
|
+
|
|
1005
|
+
`
|
|
1006
|
+
);
|
|
1007
|
+
} catch (err) {
|
|
1008
|
+
process.stdout.write(`
|
|
1009
|
+
${error(String(err instanceof Error ? err.message : err))}
|
|
1010
|
+
|
|
1011
|
+
`);
|
|
1012
|
+
process.exit(1);
|
|
1013
|
+
}
|
|
1014
|
+
break;
|
|
1015
|
+
}
|
|
881
1016
|
case "register": {
|
|
882
1017
|
const repoPath = process.argv[3] ?? ".";
|
|
883
|
-
const absPath =
|
|
1018
|
+
const absPath = path3.resolve(repoPath);
|
|
884
1019
|
try {
|
|
885
1020
|
const stat = await import("fs").then((m) => m.statSync(absPath));
|
|
886
1021
|
if (!stat.isDirectory()) {
|
|
@@ -891,8 +1026,8 @@ async function main() {
|
|
|
891
1026
|
console.error(`[ctxloom] Path does not exist: ${absPath}`);
|
|
892
1027
|
process.exit(1);
|
|
893
1028
|
}
|
|
894
|
-
const dbPath =
|
|
895
|
-
const registryPath =
|
|
1029
|
+
const dbPath = path3.join(absPath, ".ctxloom", "vectors.lancedb");
|
|
1030
|
+
const registryPath = path3.join(os.homedir(), ".ctxloom", "repos.json");
|
|
896
1031
|
const reg = new RepoRegistry(registryPath);
|
|
897
1032
|
reg.register(absPath, dbPath);
|
|
898
1033
|
console.log(`[ctxloom] Registered repo: ${absPath}`);
|
|
@@ -901,7 +1036,7 @@ async function main() {
|
|
|
901
1036
|
break;
|
|
902
1037
|
}
|
|
903
1038
|
case "repos": {
|
|
904
|
-
const registryPath =
|
|
1039
|
+
const registryPath = path3.join(os.homedir(), ".ctxloom", "repos.json");
|
|
905
1040
|
const reg = new RepoRegistry(registryPath);
|
|
906
1041
|
const repos = reg.list();
|
|
907
1042
|
if (repos.length === 0) {
|
|
@@ -953,7 +1088,7 @@ async function main() {
|
|
|
953
1088
|
}
|
|
954
1089
|
case "review-suggest": {
|
|
955
1090
|
const root = process.cwd();
|
|
956
|
-
const ctxloomDir =
|
|
1091
|
+
const ctxloomDir = path3.join(root, ".ctxloom");
|
|
957
1092
|
const max = parseInt(getFlagValue("--max=") ?? "3", 10);
|
|
958
1093
|
if (isNaN(max) || max <= 0) {
|
|
959
1094
|
console.error("[ctxloom] --max must be a positive integer.");
|
|
@@ -987,7 +1122,7 @@ async function main() {
|
|
|
987
1122
|
const allFiles = store.ownership.allNodes();
|
|
988
1123
|
const ruleMap = /* @__PURE__ */ new Map();
|
|
989
1124
|
for (const file of allFiles) {
|
|
990
|
-
const dir =
|
|
1125
|
+
const dir = path3.dirname(file);
|
|
991
1126
|
const stats = store.ownership.statsFor(file);
|
|
992
1127
|
if (!stats) continue;
|
|
993
1128
|
const topOwners = stats.owners.filter((o) => o.share >= minShare).slice(0, 2);
|
|
@@ -1001,7 +1136,7 @@ async function main() {
|
|
|
1001
1136
|
}
|
|
1002
1137
|
}
|
|
1003
1138
|
const rules = Array.from(ruleMap.entries()).map(([pattern, handles]) => ({ pattern, handles: Array.from(handles) })).sort((a, b) => a.pattern.localeCompare(b.pattern));
|
|
1004
|
-
const codeownersPath =
|
|
1139
|
+
const codeownersPath = path3.join(root, ".github", "CODEOWNERS");
|
|
1005
1140
|
const content = await generateCODEOWNERS(codeownersPath, rules);
|
|
1006
1141
|
if (writeFlag) {
|
|
1007
1142
|
await writeCODEOWNERS(codeownersPath, content);
|
|
@@ -1057,7 +1192,7 @@ Suggested reviewers for ${files.length} file(s):`);
|
|
|
1057
1192
|
}
|
|
1058
1193
|
case "authors-sync": {
|
|
1059
1194
|
const root = process.cwd();
|
|
1060
|
-
const ctxloomDir =
|
|
1195
|
+
const ctxloomDir = path3.join(root, ".ctxloom");
|
|
1061
1196
|
const token = process.env.GITHUB_TOKEN;
|
|
1062
1197
|
if (!token) {
|
|
1063
1198
|
console.error("[ctxloom] GITHUB_TOKEN env var required for authors-sync.");
|
|
@@ -1112,7 +1247,7 @@ Suggested reviewers for ${files.length} file(s):`);
|
|
|
1112
1247
|
process.stderr.write("[ctxloom] --limit must be a non-negative integer (0 for unlimited)\n");
|
|
1113
1248
|
process.exit(2);
|
|
1114
1249
|
}
|
|
1115
|
-
const { loadRulesConfig, RulesChecker, formatText, formatJson, RulesConfigError } = await import("./src-
|
|
1250
|
+
const { loadRulesConfig, RulesChecker, formatText, formatJson, RulesConfigError } = await import("./src-BRXQZ22F.js");
|
|
1116
1251
|
let config;
|
|
1117
1252
|
try {
|
|
1118
1253
|
config = await loadRulesConfig(root);
|
|
@@ -1136,7 +1271,7 @@ Suggested reviewers for ${files.length} file(s):`);
|
|
|
1136
1271
|
}
|
|
1137
1272
|
let graph;
|
|
1138
1273
|
if (useSnapshot) {
|
|
1139
|
-
const { DependencyGraph: DG } = await import("./src-
|
|
1274
|
+
const { DependencyGraph: DG } = await import("./src-BRXQZ22F.js");
|
|
1140
1275
|
graph = new DG();
|
|
1141
1276
|
const loaded = await graph.loadSnapshotOnly(root);
|
|
1142
1277
|
if (!loaded) {
|
|
@@ -1145,7 +1280,7 @@ Suggested reviewers for ${files.length} file(s):`);
|
|
|
1145
1280
|
}
|
|
1146
1281
|
} else {
|
|
1147
1282
|
process.stderr.write("[ctxloom] Building dependency graph...\n");
|
|
1148
|
-
const { ASTParser: ASTParser2, DependencyGraph: DependencyGraph2 } = await import("./src-
|
|
1283
|
+
const { ASTParser: ASTParser2, DependencyGraph: DependencyGraph2 } = await import("./src-BRXQZ22F.js");
|
|
1149
1284
|
let parser;
|
|
1150
1285
|
try {
|
|
1151
1286
|
parser = new ASTParser2();
|
|
@@ -1185,8 +1320,9 @@ Usage:
|
|
|
1185
1320
|
ctxloom activate <KEY> Activate a purchased license key on this machine
|
|
1186
1321
|
ctxloom deactivate Release this machine's license seat
|
|
1187
1322
|
ctxloom status Show current license status
|
|
1323
|
+
ctxloom init Scaffold .mcp.json + .gitignore for this project
|
|
1188
1324
|
ctxloom index Index the current directory and build dependency graph
|
|
1189
|
-
ctxloom setup Detect and configure MCP-compatible AI tools
|
|
1325
|
+
ctxloom setup Detect and configure MCP-compatible AI tools (global)
|
|
1190
1326
|
ctxloom grammars Show grammar cache status
|
|
1191
1327
|
ctxloom grammars --download Pre-download all language grammars
|
|
1192
1328
|
ctxloom register [path] Register a repo for cross-repo search (defaults to cwd)
|
|
@@ -36,7 +36,10 @@ if (unconfigured.length > 0) {
|
|
|
36
36
|
console.log(` ${C.dim}No MCP-compatible AI tools detected.${C.reset}`);
|
|
37
37
|
}
|
|
38
38
|
console.log("");
|
|
39
|
-
console.log(` Quick start
|
|
40
|
-
console.log(`
|
|
39
|
+
console.log(` Quick start (run from your project directory):`);
|
|
40
|
+
console.log(` ${C.cyan}ctxloom init${C.reset} ${C.dim}# Pin ctxloom to this project${C.reset}`);
|
|
41
|
+
console.log(` ${C.cyan}ctxloom index${C.reset} ${C.dim}# Build the dependency graph${C.reset}`);
|
|
42
|
+
console.log("");
|
|
43
|
+
console.log(` Configure AI tools (one-time, global): ${C.cyan}ctxloom setup${C.reset}`);
|
|
41
44
|
console.log("");
|
|
42
45
|
//# sourceMappingURL=postinstall.js.map
|
|
@@ -80,7 +80,7 @@ import {
|
|
|
80
80
|
startTrial,
|
|
81
81
|
track,
|
|
82
82
|
writeCODEOWNERS
|
|
83
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-GI354NTO.js";
|
|
84
84
|
import {
|
|
85
85
|
VectorStore
|
|
86
86
|
} from "./chunk-NEHYSE2Y.js";
|
|
@@ -89,7 +89,7 @@ import {
|
|
|
89
89
|
collectFiles,
|
|
90
90
|
generateEmbedding,
|
|
91
91
|
indexDirectory
|
|
92
|
-
} from "./chunk-
|
|
92
|
+
} from "./chunk-NYBVAPM3.js";
|
|
93
93
|
import {
|
|
94
94
|
logger
|
|
95
95
|
} from "./chunk-TYDMSHV7.js";
|
|
@@ -182,4 +182,4 @@ export {
|
|
|
182
182
|
track,
|
|
183
183
|
writeCODEOWNERS
|
|
184
184
|
};
|
|
185
|
-
//# sourceMappingURL=src-
|
|
185
|
+
//# sourceMappingURL=src-BRXQZ22F.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ctxloom-pro",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.26",
|
|
4
4
|
"description": "ctxloom — The Universal Code Context Engine. A local-first MCP server providing intelligent code context via hybrid Vector + AST + Graph search with Skeletonization (92% token reduction).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|