composto-ai 0.6.1 → 0.7.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/dist/index.js +51 -33
- package/dist/mcp/server.js +5 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3062,40 +3062,45 @@ function writeCursorHooks(projectPath, result) {
|
|
|
3062
3062
|
if (existed) result.merged.push(relPath);
|
|
3063
3063
|
else result.written.push(relPath);
|
|
3064
3064
|
}
|
|
3065
|
-
function initCursor(projectPath, result) {
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3065
|
+
function initCursor(projectPath, result, options) {
|
|
3066
|
+
if (options.withMcp) {
|
|
3067
|
+
writeJsonMerged(
|
|
3068
|
+
join7(projectPath, ".cursor", "mcp.json"),
|
|
3069
|
+
{
|
|
3070
|
+
mcpServers: {
|
|
3071
|
+
composto: {
|
|
3072
|
+
command: "composto-mcp",
|
|
3073
|
+
env: { COMPOSTO_BLASTRADIUS: "1" }
|
|
3074
|
+
}
|
|
3073
3075
|
}
|
|
3074
|
-
}
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3076
|
+
},
|
|
3077
|
+
result,
|
|
3078
|
+
".cursor/mcp.json"
|
|
3079
|
+
);
|
|
3080
|
+
}
|
|
3081
|
+
if (options.withRules) {
|
|
3082
|
+
writeFileSkipIfExists(
|
|
3083
|
+
join7(projectPath, ".cursor", "rules", "composto.mdc"),
|
|
3084
|
+
CURSOR_RULES_MDC,
|
|
3085
|
+
result,
|
|
3086
|
+
".cursor/rules/composto.mdc"
|
|
3087
|
+
);
|
|
3088
|
+
}
|
|
3085
3089
|
writeCursorHooks(projectPath, result);
|
|
3086
3090
|
}
|
|
3087
|
-
function initClaudeCode(projectPath, result) {
|
|
3091
|
+
function initClaudeCode(projectPath, result, options) {
|
|
3088
3092
|
const settingsPath = join7(projectPath, ".claude", "settings.json");
|
|
3089
3093
|
const relPath = ".claude/settings.json";
|
|
3090
3094
|
const existed = existsSync4(settingsPath);
|
|
3091
3095
|
const existing = readJsonIfExists(settingsPath);
|
|
3092
|
-
const
|
|
3093
|
-
|
|
3096
|
+
const baseExistingMcp = existing.mcpServers ?? {};
|
|
3097
|
+
const mcpServers = options.withMcp ? {
|
|
3098
|
+
...baseExistingMcp,
|
|
3094
3099
|
composto: {
|
|
3095
3100
|
command: "composto-mcp",
|
|
3096
3101
|
env: { COMPOSTO_BLASTRADIUS: "1" }
|
|
3097
3102
|
}
|
|
3098
|
-
};
|
|
3103
|
+
} : baseExistingMcp;
|
|
3099
3104
|
const compostoHookEntry = {
|
|
3100
3105
|
matcher: "Edit|Write|MultiEdit",
|
|
3101
3106
|
hooks: [
|
|
@@ -3110,9 +3115,11 @@ function initClaudeCode(projectPath, result) {
|
|
|
3110
3115
|
);
|
|
3111
3116
|
const merged = {
|
|
3112
3117
|
...existing,
|
|
3113
|
-
mcpServers,
|
|
3114
3118
|
hooks: { ...existingHooks, PreToolUse: preToolUse }
|
|
3115
3119
|
};
|
|
3120
|
+
if (Object.keys(mcpServers).length > 0) {
|
|
3121
|
+
merged.mcpServers = mcpServers;
|
|
3122
|
+
}
|
|
3116
3123
|
ensureDir(settingsPath);
|
|
3117
3124
|
writeFileSync2(settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
3118
3125
|
if (existed) result.merged.push(relPath);
|
|
@@ -3124,13 +3131,14 @@ function initGeminiCli(_projectPath, result, options) {
|
|
|
3124
3131
|
try {
|
|
3125
3132
|
const existed = existsSync4(settingsPath);
|
|
3126
3133
|
const existing = readJsonIfExists(settingsPath);
|
|
3127
|
-
const
|
|
3128
|
-
|
|
3134
|
+
const baseExistingMcp = existing.mcpServers ?? {};
|
|
3135
|
+
const mcpServers = options.withMcp ? {
|
|
3136
|
+
...baseExistingMcp,
|
|
3129
3137
|
composto: {
|
|
3130
3138
|
command: "composto-mcp",
|
|
3131
3139
|
env: { COMPOSTO_BLASTRADIUS: "1" }
|
|
3132
3140
|
}
|
|
3133
|
-
};
|
|
3141
|
+
} : baseExistingMcp;
|
|
3134
3142
|
const compostoHookEntry = {
|
|
3135
3143
|
matcher: "edit_file|write_file|replace",
|
|
3136
3144
|
hooks: [
|
|
@@ -3145,9 +3153,11 @@ function initGeminiCli(_projectPath, result, options) {
|
|
|
3145
3153
|
);
|
|
3146
3154
|
const merged = {
|
|
3147
3155
|
...existing,
|
|
3148
|
-
mcpServers,
|
|
3149
3156
|
hooks: { ...existingHooks, BeforeTool: beforeTool }
|
|
3150
3157
|
};
|
|
3158
|
+
if (Object.keys(mcpServers).length > 0) {
|
|
3159
|
+
merged.mcpServers = mcpServers;
|
|
3160
|
+
}
|
|
3151
3161
|
ensureDir(settingsPath);
|
|
3152
3162
|
writeFileSync2(settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
3153
3163
|
if (existed) result.merged.push(relPath);
|
|
@@ -3160,9 +3170,9 @@ function initGeminiCli(_projectPath, result, options) {
|
|
|
3160
3170
|
function runInit(projectPath, options) {
|
|
3161
3171
|
const client = options.client ?? "cursor";
|
|
3162
3172
|
const result = { client, written: [], skipped: [], merged: [] };
|
|
3163
|
-
if (client === "claude-code") initClaudeCode(projectPath, result);
|
|
3173
|
+
if (client === "claude-code") initClaudeCode(projectPath, result, options);
|
|
3164
3174
|
else if (client === "gemini-cli") initGeminiCli(projectPath, result, options);
|
|
3165
|
-
else initCursor(projectPath, result);
|
|
3175
|
+
else initCursor(projectPath, result, options);
|
|
3166
3176
|
return result;
|
|
3167
3177
|
}
|
|
3168
3178
|
|
|
@@ -3675,7 +3685,13 @@ switch (command) {
|
|
|
3675
3685
|
console.error(`Unknown --client=${clientArg}. Valid: ${valid.join(", ")}`);
|
|
3676
3686
|
process.exit(1);
|
|
3677
3687
|
}
|
|
3678
|
-
const
|
|
3688
|
+
const withRules = args.includes("--with-rules");
|
|
3689
|
+
const withMcp = args.includes("--with-mcp");
|
|
3690
|
+
const result = runInit(resolve2("."), {
|
|
3691
|
+
client: clientArg,
|
|
3692
|
+
withRules,
|
|
3693
|
+
withMcp
|
|
3694
|
+
});
|
|
3679
3695
|
console.log(`composto init \u2014 configured for ${result.client}
|
|
3680
3696
|
`);
|
|
3681
3697
|
for (const f of result.written) console.log(` wrote ${f}`);
|
|
@@ -3753,8 +3769,10 @@ switch (command) {
|
|
|
3753
3769
|
console.log(" impact <file> Show historical blast radius for a file");
|
|
3754
3770
|
console.log(" index [--since=YYYY-MM-DD] Build or refresh the memory index (--since bounds work for huge repos)");
|
|
3755
3771
|
console.log(" index --status Show memory index diagnostics");
|
|
3756
|
-
console.log(" init [--client=<name>]
|
|
3757
|
-
console.log("
|
|
3772
|
+
console.log(" init [--client=<name>] [--with-mcp] [--with-rules]");
|
|
3773
|
+
console.log(" Lean Hook init (clients: cursor, claude-code, gemini-cli)");
|
|
3774
|
+
console.log(" --with-mcp register the composto MCP server (5 tools)");
|
|
3775
|
+
console.log(" --with-rules write .cursor/rules/composto.mdc (cursor only)");
|
|
3758
3776
|
console.log(" hook <platform> <event> Run BlastRadius hook (reads tool JSON from stdin)");
|
|
3759
3777
|
console.log(" stats [--json] [--disable] Show hook telemetry (last 7d); --disable opts out");
|
|
3760
3778
|
console.log(" version Show version");
|
package/dist/mcp/server.js
CHANGED
|
@@ -2387,7 +2387,7 @@ var server = new McpServer({
|
|
|
2387
2387
|
});
|
|
2388
2388
|
server.tool(
|
|
2389
2389
|
"composto_ir",
|
|
2390
|
-
"
|
|
2390
|
+
"Compressed AST-based IR for a file. ~89% fewer tokens than raw read.",
|
|
2391
2391
|
{
|
|
2392
2392
|
file: z.string().describe("Path to the source file"),
|
|
2393
2393
|
layer: z.enum(["L0", "L1", "L2", "L3"]).default("L1").describe("L0=structure only, L1=full IR (default), L2=delta context, L3=raw source")
|
|
@@ -2423,7 +2423,7 @@ ${result}` }]
|
|
|
2423
2423
|
);
|
|
2424
2424
|
server.tool(
|
|
2425
2425
|
"composto_benchmark",
|
|
2426
|
-
"
|
|
2426
|
+
"Per-file token-savings benchmark across a directory.",
|
|
2427
2427
|
{
|
|
2428
2428
|
path: z.string().default(".").describe("Directory to benchmark")
|
|
2429
2429
|
},
|
|
@@ -2455,7 +2455,7 @@ server.tool(
|
|
|
2455
2455
|
);
|
|
2456
2456
|
server.tool(
|
|
2457
2457
|
"composto_context",
|
|
2458
|
-
"Pack
|
|
2458
|
+
"Pack code into a token budget; target raw, neighbors as IR.",
|
|
2459
2459
|
{
|
|
2460
2460
|
path: z.string().default(".").describe("Directory to pack"),
|
|
2461
2461
|
budget: z.number().default(4e3).describe("Maximum tokens to use"),
|
|
@@ -2518,7 +2518,7 @@ Files: ${parts.join(", ")}`);
|
|
|
2518
2518
|
);
|
|
2519
2519
|
server.tool(
|
|
2520
2520
|
"composto_scan",
|
|
2521
|
-
"Scan
|
|
2521
|
+
"Scan for hardcoded secrets and debug artifacts. Local-only.",
|
|
2522
2522
|
{
|
|
2523
2523
|
path: z.string().default(".").describe("Directory to scan")
|
|
2524
2524
|
},
|
|
@@ -2551,7 +2551,7 @@ server.tool(
|
|
|
2551
2551
|
);
|
|
2552
2552
|
server.tool(
|
|
2553
2553
|
"composto_blastradius",
|
|
2554
|
-
|
|
2554
|
+
"Risk verdict (low/medium/high/unknown) for editing a file, from git history.",
|
|
2555
2555
|
{
|
|
2556
2556
|
file: z.string().describe("Repo-relative path of the file the agent intends to modify."),
|
|
2557
2557
|
intent: z.enum(["refactor", "bugfix", "feature", "test", "docs", "unknown"]).default("unknown").optional(),
|