scopecairn 0.3.0 → 0.4.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/README.md +21 -5
- package/dist/cli.js +103 -50
- package/package.json +1 -1
- package/skills/scopecairn/SKILL.md +22 -23
package/README.md
CHANGED
|
@@ -28,8 +28,10 @@ No MCP server, no embeddings, no network calls, no telemetry.
|
|
|
28
28
|
Prisma models, and Drizzle tables/queries detected automatically.
|
|
29
29
|
- **Multi-language** — TypeScript, JavaScript, Python, Java, Go, Rust,
|
|
30
30
|
PHP, C#, C/C++, Ruby, HTML (plus config/schema files as graph nodes).
|
|
31
|
-
- **Multi-agent setup** —
|
|
32
|
-
|
|
31
|
+
- **Multi-agent setup** — skills for Claude Code (plugin + marketplace
|
|
32
|
+
ready), Antigravity, Cursor, Windsurf, Copilot, Kiro, and an OpenCode
|
|
33
|
+
slash command. ScopeCairn never touches your `AGENTS.md`/`CLAUDE.md` —
|
|
34
|
+
those hold your repo's details, not tool instructions.
|
|
33
35
|
|
|
34
36
|
## Install
|
|
35
37
|
|
|
@@ -63,7 +65,20 @@ it runs project setup itself.
|
|
|
63
65
|
|
|
64
66
|
```bash
|
|
65
67
|
cd your-repo
|
|
66
|
-
scopecairn init # index +
|
|
68
|
+
scopecairn init # index + Antigravity Skill + Workflow
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Claude Code (project skill, committed with the repo):
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
scopecairn claude install
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Or as a plugin from the bundled marketplace (this repo):
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
/plugin marketplace add <github-user>/scopecairn
|
|
81
|
+
/plugin install scopecairn@scopecairn
|
|
67
82
|
```
|
|
68
83
|
|
|
69
84
|
After setup, your agent calls ScopeCairn automatically on every coding task.
|
|
@@ -82,7 +97,8 @@ Per-agent installers (instead of `init --agents …`):
|
|
|
82
97
|
|
|
83
98
|
```bash
|
|
84
99
|
scopecairn antigravity install # Skill + Workflow + allowlist guide
|
|
85
|
-
scopecairn claude install #
|
|
100
|
+
scopecairn claude install # project skill .claude/skills (also: cursor, windsurf, copilot, kiro)
|
|
101
|
+
scopecairn opencode install # /scopecairn slash command + permission snippet
|
|
86
102
|
scopecairn claude uninstall # clean removal, user content preserved
|
|
87
103
|
scopecairn agents list
|
|
88
104
|
```
|
|
@@ -91,7 +107,7 @@ scopecairn agents list
|
|
|
91
107
|
|
|
92
108
|
| Command | Description |
|
|
93
109
|
|---|---|
|
|
94
|
-
| `init [path]` | Initial indexing +
|
|
110
|
+
| `init [path]` | Initial indexing + Skill, Workflow, detected agent skills (`--agents …\|all`; never writes `AGENTS.md`) |
|
|
95
111
|
| `scan` / `rebuild` | Manual index management (`scan` inkremental; `rebuild` dari nol) |
|
|
96
112
|
| `status` / `doctor` | Index status (incl. adapters, invocations) and health checks |
|
|
97
113
|
| `context "<task>"` | Main entry point: context + scope (`--escalate`, `--no-refresh`); a path task returns an orientation map |
|
package/dist/cli.js
CHANGED
|
@@ -2021,9 +2021,28 @@ Jalankan \`${prefix} scan\` agar indeks ScopeCairn mencerminkan perubahanmu.
|
|
|
2021
2021
|
Lewati ScopeCairn hanya untuk pertanyaan non-coding.
|
|
2022
2022
|
`;
|
|
2023
2023
|
}
|
|
2024
|
-
function
|
|
2025
|
-
return
|
|
2026
|
-
|
|
2024
|
+
function claudeSkillMd(prefix) {
|
|
2025
|
+
return `---
|
|
2026
|
+
name: scopecairn
|
|
2027
|
+
description: ScopeCairn codebase context + scope. Use for ALL coding tasks
|
|
2028
|
+
(feature, bugfix, refactor, code questions) before exploring the repo,
|
|
2029
|
+
and when the user says "scopecairn", asks for a repo overview, or asks
|
|
2030
|
+
to set up ScopeCairn.
|
|
2031
|
+
allowed-tools: Bash
|
|
2032
|
+
---
|
|
2033
|
+
|
|
2034
|
+
# ScopeCairn
|
|
2035
|
+
|
|
2036
|
+
1. Jika \`.scopecairn/scopecairn.db\` belum ada: jalankan \`${prefix} init\`
|
|
2037
|
+
(bila CLI belum ada: \`npm install -g scopecairn\`), laporkan file/simbol/relasi, berhenti.
|
|
2038
|
+
2. Jika sudah ada: jalankan \`${prefix} context "<task user>"\`.
|
|
2039
|
+
Mulai dari Relevant Files. Jangan menjelajah dari nol.
|
|
2040
|
+
3. Ubah hanya Required/Optional; Protected perlu persetujuan user.
|
|
2041
|
+
Simbol bersama \u2192 \`${prefix} impact <path>\`.
|
|
2042
|
+
Butuh isi fungsi \u2192 \`${prefix} read symbol <nama>\`, bukan baca file penuh.
|
|
2043
|
+
4. Task membesar (>2 file)? Panggil ulang \`${prefix} context --escalate\`.
|
|
2044
|
+
5. Setelah mengedit: \`${prefix} scan\`. Berhenti saat acceptance criteria terpenuhi.
|
|
2045
|
+
`;
|
|
2027
2046
|
}
|
|
2028
2047
|
function genericRuleMd(prefix) {
|
|
2029
2048
|
return `${MARKER}
|
|
@@ -2064,6 +2083,37 @@ Shortcut manual bila agent lupa memanggil ScopeCairn otomatis.
|
|
|
2064
2083
|
4. Perlu source simbol? \`${prefix} read symbol <nama>\`.
|
|
2065
2084
|
`;
|
|
2066
2085
|
}
|
|
2086
|
+
function opencodeCommandMd(prefix) {
|
|
2087
|
+
return `---
|
|
2088
|
+
description: ScopeCairn codebase context + scope for a task
|
|
2089
|
+
---
|
|
2090
|
+
|
|
2091
|
+
Run \`${prefix} context "$ARGUMENTS"\` with the bash tool, then:
|
|
2092
|
+
|
|
2093
|
+
1. Use Relevant Files as the starting point \u2014 do not explore from zero.
|
|
2094
|
+
2. Change only Required and Optional files; Protected needs user approval.
|
|
2095
|
+
3. If shared symbols change, run \`${prefix} impact <path>\`.
|
|
2096
|
+
4. Need a function body? Use \`${prefix} read symbol <nama>\`, not full reads.
|
|
2097
|
+
5. After editing, run \`${prefix} scan\` so the ScopeCairn index stays fresh.
|
|
2098
|
+
<!-- scopecairn:managed -->
|
|
2099
|
+
`;
|
|
2100
|
+
}
|
|
2101
|
+
function opencodePermissionGuide(prefix) {
|
|
2102
|
+
const cmds = ["context", "impact", "read", "graph", "status", "doctor"];
|
|
2103
|
+
const rules = cmds.map((c) => ` "${prefix} ${c} *": "allow"`).join(",\n");
|
|
2104
|
+
return `Agar command di atas jalan tanpa persetujuan, gabungkan ke opencode.json
|
|
2105
|
+
(project root atau ~/.config/opencode/opencode.json):
|
|
2106
|
+
|
|
2107
|
+
{
|
|
2108
|
+
"permission": {
|
|
2109
|
+
"bash": {
|
|
2110
|
+
${rules}
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
Catatan: ScopeCairn tidak mengubah opencode.json Anda secara otomatis.`;
|
|
2116
|
+
}
|
|
2067
2117
|
var ALLOWLIST_COMMANDS = [
|
|
2068
2118
|
"context",
|
|
2069
2119
|
"impact",
|
|
@@ -2085,29 +2135,13 @@ Catatan: ScopeCairn tidak mengubah pengaturan IDE Anda secara otomatis.`;
|
|
|
2085
2135
|
|
|
2086
2136
|
// src/integrate/matrix.ts
|
|
2087
2137
|
var AGENT_MATRIX = [
|
|
2088
|
-
{
|
|
2089
|
-
id: "agents",
|
|
2090
|
-
label: "AGENTS.md (universal: Codex, Aider, Opencode, Amp, Jules, ...)",
|
|
2091
|
-
rel: "AGENTS.md",
|
|
2092
|
-
mode: "merge",
|
|
2093
|
-
render: agentsMd,
|
|
2094
|
-
presentMarker: "AGENTS.md"
|
|
2095
|
-
},
|
|
2096
2138
|
{
|
|
2097
2139
|
id: "claude",
|
|
2098
2140
|
label: "Claude Code",
|
|
2099
|
-
rel: "
|
|
2100
|
-
mode: "
|
|
2101
|
-
render:
|
|
2102
|
-
presentMarker: "
|
|
2103
|
-
},
|
|
2104
|
-
{
|
|
2105
|
-
id: "gemini",
|
|
2106
|
-
label: "Gemini / Antigravity CLI",
|
|
2107
|
-
rel: "GEMINI.md",
|
|
2108
|
-
mode: "merge",
|
|
2109
|
-
render: genericRuleMd,
|
|
2110
|
-
presentMarker: "GEMINI.md"
|
|
2141
|
+
rel: ".claude/skills/scopecairn/SKILL.md",
|
|
2142
|
+
mode: "new",
|
|
2143
|
+
render: claudeSkillMd,
|
|
2144
|
+
presentMarker: ".claude"
|
|
2111
2145
|
},
|
|
2112
2146
|
{
|
|
2113
2147
|
id: "cursor",
|
|
@@ -2140,6 +2174,14 @@ var AGENT_MATRIX = [
|
|
|
2140
2174
|
mode: "new",
|
|
2141
2175
|
render: genericRuleMd,
|
|
2142
2176
|
presentMarker: ".kiro"
|
|
2177
|
+
},
|
|
2178
|
+
{
|
|
2179
|
+
id: "opencode",
|
|
2180
|
+
label: "OpenCode",
|
|
2181
|
+
rel: ".opencode/commands/scopecairn.md",
|
|
2182
|
+
mode: "new",
|
|
2183
|
+
render: opencodeCommandMd,
|
|
2184
|
+
presentMarker: ".opencode"
|
|
2143
2185
|
}
|
|
2144
2186
|
];
|
|
2145
2187
|
function findTarget(id) {
|
|
@@ -2194,7 +2236,7 @@ async function cmdDoctor(repoRoot2) {
|
|
|
2194
2236
|
const abs = path11.join(repoRoot2, t.rel);
|
|
2195
2237
|
if (!fs11.existsSync(abs)) continue;
|
|
2196
2238
|
const text = fs11.readFileSync(abs, "utf8");
|
|
2197
|
-
if (!text.includes(MARKER)) continue;
|
|
2239
|
+
if (t.mode === "merge" && !text.includes(MARKER)) continue;
|
|
2198
2240
|
matrixOk++;
|
|
2199
2241
|
const used = extractPrefixUsed(text);
|
|
2200
2242
|
if (used && used !== expectedPrefix) {
|
|
@@ -2216,7 +2258,7 @@ async function cmdDoctor(repoRoot2) {
|
|
|
2216
2258
|
const wfPath = path11.join(repoRoot2, "workflows", "scopecairn.md");
|
|
2217
2259
|
console.log(`${tick(fs11.existsSync(wfPath))} Workflow (workflows/scopecairn.md, opsional)`);
|
|
2218
2260
|
console.log(`i Strict Mode mengabaikan allowlist \u2014 semua perintah tetap perlu persetujuan.`);
|
|
2219
|
-
const healthy = nodeOk && sqliteOk && ts.ok && dbOk && matrixOk > 0
|
|
2261
|
+
const healthy = nodeOk && sqliteOk && ts.ok && dbOk && (matrixOk > 0 || skillOk) && prefixOk;
|
|
2220
2262
|
console.log(`Status: ${healthy ? "HEALTHY" : "DEGRADED (see \u2717 above)"}`);
|
|
2221
2263
|
}
|
|
2222
2264
|
|
|
@@ -2464,29 +2506,36 @@ function retrieve(db, repoRoot2, task, opts) {
|
|
|
2464
2506
|
proximity.set(s.symbolId, Math.max(proximity.get(s.symbolId) ?? 0, s.bm25));
|
|
2465
2507
|
visited.add(s.symbolId);
|
|
2466
2508
|
});
|
|
2467
|
-
const
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2509
|
+
const CHUNK = 2e3;
|
|
2510
|
+
function neighborsOf(ids) {
|
|
2511
|
+
const out = [];
|
|
2512
|
+
for (let i = 0; i < ids.length; i += CHUNK) {
|
|
2513
|
+
const c = ids.slice(i, i + CHUNK);
|
|
2514
|
+
const ph = c.map(() => "?").join(",");
|
|
2515
|
+
for (const r of db.prepare(
|
|
2516
|
+
`SELECT source_id AS f, target_id AS t, weight AS w FROM relationships WHERE source_id IN (${ph})`
|
|
2517
|
+
).all(...c)) {
|
|
2518
|
+
out.push({ from: r.f, to: r.t, w: r.w });
|
|
2519
|
+
}
|
|
2520
|
+
for (const r of db.prepare(
|
|
2521
|
+
`SELECT target_id AS f, source_id AS t, weight * 0.8 AS w FROM relationships WHERE target_id IN (${ph})`
|
|
2522
|
+
).all(...c)) {
|
|
2523
|
+
out.push({ from: r.f, to: r.t, w: r.w });
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
return out;
|
|
2476
2527
|
}
|
|
2477
2528
|
let hopScore = 1;
|
|
2478
2529
|
for (let depth = 1; depth <= config.maxDepth; depth++) {
|
|
2479
2530
|
hopScore *= config.decayPerHop;
|
|
2480
2531
|
const next = [];
|
|
2481
|
-
for (const
|
|
2482
|
-
const base = proximity.get(
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
next.push(e.to);
|
|
2489
|
-
}
|
|
2532
|
+
for (const e of neighborsOf(frontier)) {
|
|
2533
|
+
const base = proximity.get(e.from) ?? 0;
|
|
2534
|
+
const cand = base * e.w * hopScore;
|
|
2535
|
+
if (cand > (proximity.get(e.to) ?? 0)) proximity.set(e.to, cand);
|
|
2536
|
+
if (!visited.has(e.to)) {
|
|
2537
|
+
visited.add(e.to);
|
|
2538
|
+
next.push(e.to);
|
|
2490
2539
|
}
|
|
2491
2540
|
}
|
|
2492
2541
|
frontier = next;
|
|
@@ -3256,14 +3305,13 @@ function withCore(ids) {
|
|
|
3256
3305
|
console.log(`! Unknown agent "${id}" (pilihan: ${AGENT_MATRIX.map((x) => x.id).join(", ")}, all)`);
|
|
3257
3306
|
continue;
|
|
3258
3307
|
}
|
|
3259
|
-
out.push(t);
|
|
3308
|
+
if (!out.includes(t)) out.push(t);
|
|
3260
3309
|
}
|
|
3261
|
-
if (!out.includes(AGENT_MATRIX[0])) out.unshift(AGENT_MATRIX[0]);
|
|
3262
3310
|
return out;
|
|
3263
3311
|
}
|
|
3264
3312
|
function withDetected(repoRoot2) {
|
|
3265
|
-
const targets = [
|
|
3266
|
-
for (const t of AGENT_MATRIX
|
|
3313
|
+
const targets = [];
|
|
3314
|
+
for (const t of AGENT_MATRIX) {
|
|
3267
3315
|
if (fs15.existsSync(path15.join(repoRoot2, t.presentMarker))) targets.push(t);
|
|
3268
3316
|
}
|
|
3269
3317
|
return targets;
|
|
@@ -3499,8 +3547,13 @@ function registerAgentCommands(program2, repoRoot2) {
|
|
|
3499
3547
|
const cmd = program2.command(t.id).description(`${t.label} integration`);
|
|
3500
3548
|
cmd.command("install").description(`Write ${t.rel}`).action(() => {
|
|
3501
3549
|
const root = repoRoot2();
|
|
3502
|
-
const
|
|
3550
|
+
const prefix = detectPrefix(root);
|
|
3551
|
+
const r = installTarget(root, t, prefix);
|
|
3503
3552
|
console.log(`\u2713 ${t.label}: ${r.rel} (${r.how})`);
|
|
3553
|
+
if (t.id === "opencode") {
|
|
3554
|
+
console.log("");
|
|
3555
|
+
console.log(opencodePermissionGuide(prefix));
|
|
3556
|
+
}
|
|
3504
3557
|
});
|
|
3505
3558
|
cmd.command("uninstall").description(`Remove ScopeCairn block from ${t.rel}`).action(() => {
|
|
3506
3559
|
const r = uninstallTarget(repoRoot2(), t);
|
|
@@ -3512,7 +3565,7 @@ function registerAgentCommands(program2, repoRoot2) {
|
|
|
3512
3565
|
// package.json
|
|
3513
3566
|
var package_default = {
|
|
3514
3567
|
name: "scopecairn",
|
|
3515
|
-
version: "0.
|
|
3568
|
+
version: "0.4.0",
|
|
3516
3569
|
description: "ScopeCairn \u2014 Codebase Intelligence & Agent Optimization Layer (local-first)",
|
|
3517
3570
|
license: "MIT",
|
|
3518
3571
|
type: "module",
|
|
@@ -3599,7 +3652,7 @@ program.command("context <task>").description("Main entry point: auto-refresh +
|
|
|
3599
3652
|
program.command("impact <target>").description("Change impact analysis: file, symbol, function, or class").option("--no-refresh", "skip incremental refresh (debugging/benchmark)").action(
|
|
3600
3653
|
(target, opts) => cmdImpact(repoRoot(), target, opts)
|
|
3601
3654
|
);
|
|
3602
|
-
program.command("init [path]").description("Initial indexing +
|
|
3655
|
+
program.command("init [path]").description("Initial indexing + Skill, Workflow, agent skills (never touches AGENTS.md)").option("--agents <list>", "agent targets: comma list from claude,cursor,windsurf,copilot,kiro,opencode, or 'all'").action(
|
|
3603
3656
|
(targetPath, opts) => cmdInit(resolveRoot(targetPath), opts)
|
|
3604
3657
|
);
|
|
3605
3658
|
program.command("benchmark").description("Retrieval recall, irrelevant ratio, context reduction + weight tuning").option("--tune", "grid search bobot FR-05").option("--no-refresh", "skip incremental refresh (debugging/benchmark)").action(
|
package/package.json
CHANGED
|
@@ -1,31 +1,30 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: scopecairn
|
|
3
|
-
description: Set up ScopeCairn codebase intelligence
|
|
3
|
+
description: Set up ScopeCairn codebase intelligence, then use it for coding
|
|
4
|
+
tasks. Use when the user says "scopecairn", "scopecairn ./",
|
|
5
|
+
"scopecairn <path>", asks to index a repo for an AI agent, asks for a
|
|
6
|
+
repo overview, or for ALL coding tasks (feature, bugfix, refactor)
|
|
7
|
+
before exploring the repo.
|
|
8
|
+
allowed-tools: Bash
|
|
4
9
|
---
|
|
5
10
|
|
|
6
|
-
# ScopeCairn
|
|
11
|
+
# ScopeCairn
|
|
7
12
|
|
|
8
|
-
|
|
9
|
-
Your job: run project setup so this repo becomes agent-readable.
|
|
13
|
+
## Setup (bila `.scopecairn/scopecairn.db` belum ada)
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
1. Resolve path: `.`/`./` = direktori proyek saat ini.
|
|
16
|
+
2. Jalankan `scopecairn init <path>` (`npx -y scopecairn init <path>`
|
|
17
|
+
bila CLI belum ada; atau `npm install -g scopecairn` dulu).
|
|
18
|
+
3. Laporkan singkat: file terindex, simbol, relasi, adapter,
|
|
19
|
+
file integrasi yang ditulis. Berhenti setelah setup.
|
|
12
20
|
|
|
13
|
-
|
|
14
|
-
A relative or absolute path means that directory.
|
|
15
|
-
2. Run setup in that directory:
|
|
16
|
-
`scopecairn init <path>` (or `npx -y scopecairn init <path>` if it is not installed).
|
|
17
|
-
3. If the command is not found, install globally first
|
|
18
|
-
(`npm install -g scopecairn`), then retry step 2.
|
|
19
|
-
4. Report back, briefly: files indexed, symbols, relationships,
|
|
20
|
-
detected adapters, and which integration files were written
|
|
21
|
-
(AGENTS.md, Skill, Workflow, agent matrix).
|
|
21
|
+
## Tiap task coding (bila index sudah ada)
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
never by re-exploring the repository from zero.
|
|
23
|
+
1. Jalankan `scopecairn context "<task user>"`.
|
|
24
|
+
Mulai dari Relevant Files. Jangan menjelajah dari nol.
|
|
25
|
+
2. Ubah hanya Required/Optional; Protected perlu persetujuan user.
|
|
26
|
+
Simbol bersama → `scopecairn impact <path>`.
|
|
27
|
+
Butuh isi fungsi → `scopecairn read symbol <nama>`, bukan baca file penuh.
|
|
28
|
+
3. Task membesar (>2 file)? Panggil ulang `scopecairn context --escalate`.
|
|
29
|
+
4. Setelah mengedit: `scopecairn scan`.
|
|
30
|
+
Berhenti saat acceptance criteria terpenuhi.
|