@stainless-code/codemap 0.1.1 → 0.1.3
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 +14 -0
- package/README.md +3 -2
- package/dist/agents-init-COkjrzc5.mjs +303 -0
- package/dist/agents-init-interactive-HLqgP8gL.mjs +122 -0
- package/dist/cmd-agents-Dph66vnf.mjs +17 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +27 -10
- package/dist/parse-worker.d.mts +1 -1
- package/package.json +2 -1
- package/templates/agents/README.md +6 -2
- package/templates/agents/rules/codemap.mdc +22 -13
- package/templates/agents/skills/codemap/SKILL.md +16 -16
- package/dist/cmd-agents-BJPx1vGG.mjs +0 -38
- package/templates/agents/rules/agents-first-convention.mdc +0 -37
- /package/dist/{cmd-index-oyoHr0c4.mjs → cmd-index-UeGdciH7.mjs} +0 -0
- /package/dist/{cmd-query-D3zXZu7K.mjs → cmd-query-lSSRXMX8.mjs} +0 -0
- /package/dist/{parsed-types-udxNyD9e.d.mts → parsed-types-CtqqGr-K.d.mts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @stainless-code/codemap
|
|
2
2
|
|
|
3
|
+
## 0.1.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#6](https://github.com/stainless-code/codemap/pull/6) [`ad29694`](https://github.com/stainless-code/codemap/commit/ad2969481d4bd4e60d4f29818e4f1e64986216f9) Thanks [@SutuSebastian](https://github.com/SutuSebastian)! - Align shipped agent templates with the published CLI (`codemap`, `npx @stainless-code/codemap`, …). Keep this repository’s `.agents/` rule and skill dev-oriented (`bun src/index.ts`). Remove the redundant `agents-first-convention` template. Document the dev vs `templates/agents/` split in `templates/agents/README.md` and `docs/agents.md`.
|
|
8
|
+
|
|
9
|
+
## 0.1.2
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#4](https://github.com/stainless-code/codemap/pull/4) [`0a9d829`](https://github.com/stainless-code/codemap/commit/0a9d82935e775edfb942029c03b8a427f18f9e71) Thanks [@SutuSebastian](https://github.com/SutuSebastian)! - **`codemap agents init`:** For Git repos, ensure **`.codemap.*`** is in **`.gitignore`** (create the file or append the line once). **`--force`** removes only template file paths (same relpaths under **`.agents/rules/`** and **`.agents/skills/`** as **`templates/agents`**) before merging; other files under **`.agents/`**, **`rules/`**, or **`skills/`** are kept. **`--interactive` / `-i`** — pick IDE integrations (Cursor, GitHub Copilot, Windsurf, Continue, Cline, Amazon Q, **`CLAUDE.md`**, **`AGENTS.md`**, **`GEMINI.md`**) and symlink vs copy for rule mirrors; requires a TTY. Unknown positional arguments (e.g. `interactive` without `--interactive`) are rejected. Depends on **`@clack/prompts`**.
|
|
14
|
+
|
|
15
|
+
**Docs:** **[`docs/agents.md`](https://github.com/stainless-code/codemap/blob/main/docs/agents.md)**; **[`docs/README.md`](https://github.com/stainless-code/codemap/blob/main/docs/README.md)** index updated. Root **[`.gitignore`](https://github.com/stainless-code/codemap/blob/main/.gitignore)** uses a single **`.codemap.*`** line.
|
|
16
|
+
|
|
3
17
|
## 0.1.1
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
- **Not** full-text search or grep on arbitrary strings — use those when you need raw file-body search.
|
|
6
6
|
- **Is** a fast, token-efficient way to navigate **structure**: definitions, imports, dependency direction, components, and other extracted facts.
|
|
7
7
|
|
|
8
|
-
**Documentation:** [docs/README.md](docs/README.md) is the index
|
|
8
|
+
**Documentation:** [docs/README.md](docs/README.md) is the hub (topic index + single-source rules). Topics: [architecture](docs/architecture.md), [agents](docs/agents.md) (`codemap agents init`), [benchmark](docs/benchmark.md), [packaging](docs/packaging.md), [roadmap](docs/roadmap.md), [why Codemap](docs/why-codemap.md). **Bundled rules/skills:** [`.agents/rules/`](.agents/rules/), [`.agents/skills/codemap/SKILL.md`](.agents/skills/codemap/SKILL.md). **Consumers:** [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md).
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -47,9 +47,10 @@ codemap --config /path/to/codemap.config.json --full
|
|
|
47
47
|
# Re-index only given paths (relative to project root)
|
|
48
48
|
codemap --files src/a.ts src/b.tsx
|
|
49
49
|
|
|
50
|
-
# Scaffold .agents/
|
|
50
|
+
# Scaffold .agents/ from bundled templates — full matrix: docs/agents.md
|
|
51
51
|
codemap agents init
|
|
52
52
|
codemap agents init --force
|
|
53
|
+
codemap agents init --interactive # -i; IDE wiring + symlink vs copy
|
|
53
54
|
```
|
|
54
55
|
|
|
55
56
|
**Environment / flags:** `--root` overrides **`CODEMAP_ROOT`** / **`CODEMAP_TEST_BENCH`**, then **`process.cwd()`**. Indexing a project outside this clone: [docs/benchmark.md § Indexing another project](docs/benchmark.md#indexing-another-project).
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { dirname, join, relative } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { appendFileSync, copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, symlinkSync, writeFileSync } from "node:fs";
|
|
6
|
+
//#region src/agents-init.ts
|
|
7
|
+
/**
|
|
8
|
+
* Directory containing `rules/` and `skills/` (next to `dist/` in published packages).
|
|
9
|
+
*/
|
|
10
|
+
function resolveAgentsTemplateDir() {
|
|
11
|
+
return join(dirname(fileURLToPath(import.meta.url)), "..", "templates", "agents");
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Every regular file path under `dir` relative to `dir` (POSIX-style `/`).
|
|
15
|
+
* Used for template paths (`--force` removal), template writes, and copy-mode IDE sync.
|
|
16
|
+
*/
|
|
17
|
+
function listRegularFilesRecursive(dir, relPrefix = "") {
|
|
18
|
+
const out = [];
|
|
19
|
+
if (!existsSync(dir)) return out;
|
|
20
|
+
for (const ent of readdirSync(dir, { withFileTypes: true })) {
|
|
21
|
+
const name = ent.name;
|
|
22
|
+
const rel = relPrefix ? `${relPrefix}/${name}` : name;
|
|
23
|
+
const full = join(dir, name);
|
|
24
|
+
if (ent.isDirectory()) out.push(...listRegularFilesRecursive(full, rel));
|
|
25
|
+
else if (ent.isFile()) out.push(rel);
|
|
26
|
+
}
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
function relPathToAbsSegments(rel) {
|
|
30
|
+
return rel.split("/").filter(Boolean);
|
|
31
|
+
}
|
|
32
|
+
/** Copy only listed relative paths from `srcRoot` into `destRoot` (mkdir parents per file). */
|
|
33
|
+
function copyFilesGranular(srcRoot, destRoot, relPaths) {
|
|
34
|
+
for (const rel of relPaths) {
|
|
35
|
+
const from = join(srcRoot, ...relPathToAbsSegments(rel));
|
|
36
|
+
const to = join(destRoot, ...relPathToAbsSegments(rel));
|
|
37
|
+
mkdirSync(dirname(to), { recursive: true });
|
|
38
|
+
copyFileSync(from, to);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Symlink each file: `destRoot/<rel>` → relative path to `srcRoot/<rel>` (mkdir parents per file). */
|
|
42
|
+
function symlinkFilesGranular(srcRoot, destRoot, relPaths, labelForErrors) {
|
|
43
|
+
mkdirSync(destRoot, { recursive: true });
|
|
44
|
+
for (const rel of relPaths) {
|
|
45
|
+
const srcFile = join(srcRoot, ...relPathToAbsSegments(rel));
|
|
46
|
+
const destFile = join(destRoot, ...relPathToAbsSegments(rel));
|
|
47
|
+
mkdirSync(dirname(destFile), { recursive: true });
|
|
48
|
+
const target = relative(dirname(destFile), srcFile);
|
|
49
|
+
try {
|
|
50
|
+
symlinkSync(target, destFile, "file");
|
|
51
|
+
} catch (err) {
|
|
52
|
+
throw new Error(`Codemap: symlink failed for ${labelForErrors} (${destFile}): ${String(err)}. Try copy mode or check permissions on Windows.`, { cause: err });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function removeBundledPathsIfExist(destBase, relPaths) {
|
|
57
|
+
for (const rel of relPaths) {
|
|
58
|
+
const abs = join(destBase, ...relPathToAbsSegments(rel));
|
|
59
|
+
if (!existsSync(abs)) continue;
|
|
60
|
+
rmSync(abs, {
|
|
61
|
+
recursive: true,
|
|
62
|
+
force: true
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Default DB basename `.codemap` plus SQLite sidecars (`.db`, `-wal`, `-shm`, …). */
|
|
67
|
+
const GITIGNORE_CODEMAP_PATTERN = ".codemap.*";
|
|
68
|
+
/** Targets that mirror `.agents/rules` (and Cursor also `.agents/skills`) via per-file symlink or copy. */
|
|
69
|
+
const AGENTS_INIT_SYMLINK_TARGETS = [
|
|
70
|
+
"cursor",
|
|
71
|
+
"windsurf",
|
|
72
|
+
"continue",
|
|
73
|
+
"cline",
|
|
74
|
+
"amazon-q"
|
|
75
|
+
];
|
|
76
|
+
function targetsNeedLinkMode(targets) {
|
|
77
|
+
return targets.some((t) => AGENTS_INIT_SYMLINK_TARGETS.includes(t));
|
|
78
|
+
}
|
|
79
|
+
const POINTER_BODY = `This project uses [Codemap](https://github.com/stainless-code/codemap) — a structural SQLite index for AI agents.
|
|
80
|
+
|
|
81
|
+
- **Skill:** \`.agents/skills/codemap/SKILL.md\`
|
|
82
|
+
- **CLI:** \`codemap\` to index, \`codemap query "SELECT …"\` for SQL
|
|
83
|
+
- **Rules:** \`.agents/rules/\`
|
|
84
|
+
|
|
85
|
+
`;
|
|
86
|
+
const CLAUDE_MD_TEMPLATE = `# Codemap\n\n${POINTER_BODY}`;
|
|
87
|
+
const AGENTS_MD_TEMPLATE = `# Agent instructions (Codemap)
|
|
88
|
+
|
|
89
|
+
${POINTER_BODY}
|
|
90
|
+
Also referenced by **Zed**, **JetBrains AI**-style tools, **Aider**, and other agents that read \`AGENTS.md\` at the repo root.
|
|
91
|
+
|
|
92
|
+
`;
|
|
93
|
+
const GEMINI_MD_TEMPLATE = `# Codemap (Gemini)
|
|
94
|
+
|
|
95
|
+
${POINTER_BODY}
|
|
96
|
+
Use this file if your **Gemini** CLI or IDE loads \`GEMINI.md\` at the repo root.
|
|
97
|
+
|
|
98
|
+
`;
|
|
99
|
+
const COPILOT_TEMPLATE = `# Codemap — GitHub Copilot custom instructions
|
|
100
|
+
|
|
101
|
+
${POINTER_BODY}
|
|
102
|
+
See [GitHub Docs: custom instructions for Copilot](https://docs.github.com/copilot/customizing-copilot/adding-custom-instructions-for-github-copilot).
|
|
103
|
+
|
|
104
|
+
`;
|
|
105
|
+
/** HTML comments — invisible in most Markdown renderers; used to upsert without duplicating on re-run. */
|
|
106
|
+
const CODMAP_POINTER_BEGIN = "<!-- codemap-pointer:begin -->";
|
|
107
|
+
const CODMAP_POINTER_END = "<!-- codemap-pointer:end -->";
|
|
108
|
+
function wrapCodemapPointerBlock(inner) {
|
|
109
|
+
return `${CODMAP_POINTER_BEGIN}\n${inner.trim()}\n${CODMAP_POINTER_END}\n`;
|
|
110
|
+
}
|
|
111
|
+
function escapeRegexChars(s) {
|
|
112
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
113
|
+
}
|
|
114
|
+
function codemapPointerBlockRegex() {
|
|
115
|
+
return new RegExp(`${escapeRegexChars(CODMAP_POINTER_BEGIN)}\\s*[\\s\\S]*?${escapeRegexChars(CODMAP_POINTER_END)}`, "m");
|
|
116
|
+
}
|
|
117
|
+
/** Heuristic: file looks like a prior Codemap pointer file before we added markers (upgrade → single managed block). */
|
|
118
|
+
function looksLikeLegacyCodemapPointer(content) {
|
|
119
|
+
const t = content.trim();
|
|
120
|
+
if (t.length < 80) return false;
|
|
121
|
+
return t.includes("stainless-code/codemap") && t.includes(".agents/skills/codemap") && t.includes("codemap query");
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Create or merge a Codemap pointer file. Idempotent: managed section is between
|
|
125
|
+
* {@link CODMAP_POINTER_BEGIN} / {@link CODMAP_POINTER_END}; re-runs replace that section only.
|
|
126
|
+
* - **No file:** write managed block.
|
|
127
|
+
* - **Existing + markers:** replace inner section (updates stale template text).
|
|
128
|
+
* - **Existing, no markers, legacy Codemap content:** replace whole file with managed block.
|
|
129
|
+
* - **Existing, other content:** append managed block once.
|
|
130
|
+
* - **`force`:** replace entire file with the latest managed block (same as a fresh write).
|
|
131
|
+
*/
|
|
132
|
+
function upsertCodemapPointerFile(path, innerTemplate, label, force) {
|
|
133
|
+
const wrapped = wrapCodemapPointerBlock(innerTemplate);
|
|
134
|
+
if (!existsSync(path)) {
|
|
135
|
+
writeFileSync(path, wrapped, "utf-8");
|
|
136
|
+
console.log(` Wrote ${label} with Codemap pointers`);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (force) {
|
|
140
|
+
writeFileSync(path, wrapped, "utf-8");
|
|
141
|
+
console.log(` Replaced ${label} (--force)`);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const content = readFileSync(path, "utf-8");
|
|
145
|
+
const re = codemapPointerBlockRegex();
|
|
146
|
+
if (content.match(re)) {
|
|
147
|
+
const next = content.replace(re, wrapped);
|
|
148
|
+
if (next === content) {
|
|
149
|
+
console.log(` Codemap section in ${label} already up to date`);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
writeFileSync(path, next, "utf-8");
|
|
153
|
+
console.log(` Updated Codemap section in ${label}`);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (looksLikeLegacyCodemapPointer(content)) {
|
|
157
|
+
writeFileSync(path, wrapped, "utf-8");
|
|
158
|
+
console.log(` Migrated ${label} to managed Codemap section`);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
writeFileSync(path, content + (content.endsWith("\n") ? "\n" : "\n\n") + wrapped, "utf-8");
|
|
162
|
+
console.log(` Appended Codemap section to ${label}`);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Ensure `.codemap.*` is listed in `.gitignore` when the project uses Git:
|
|
166
|
+
* - If `<projectRoot>/.git` exists and there is no `.gitignore`, create one with `.codemap.*`.
|
|
167
|
+
* - If `.gitignore` exists, append `.codemap.*` once when missing.
|
|
168
|
+
* - If there is no `.git`, do nothing (not a Git working tree).
|
|
169
|
+
*/
|
|
170
|
+
function ensureGitignoreCodemapPattern(projectRoot) {
|
|
171
|
+
const gitDir = join(projectRoot, ".git");
|
|
172
|
+
const gitignorePath = join(projectRoot, ".gitignore");
|
|
173
|
+
if (!existsSync(gitDir)) return;
|
|
174
|
+
if (!existsSync(gitignorePath)) {
|
|
175
|
+
writeFileSync(gitignorePath, `${GITIGNORE_CODEMAP_PATTERN}\n`, "utf-8");
|
|
176
|
+
console.log(` Created .gitignore with ${GITIGNORE_CODEMAP_PATTERN} (Git repo, no .gitignore yet)`);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
const content = readFileSync(gitignorePath, "utf-8");
|
|
180
|
+
if (content.split(/\r?\n/).some((line) => line.trim() === GITIGNORE_CODEMAP_PATTERN)) return;
|
|
181
|
+
appendFileSync(gitignorePath, `${content.length > 0 && !content.endsWith("\n") ? "\n" : ""}${GITIGNORE_CODEMAP_PATTERN}\n`, "utf-8");
|
|
182
|
+
console.log(` Appended ${GITIGNORE_CODEMAP_PATTERN} to .gitignore`);
|
|
183
|
+
}
|
|
184
|
+
function removePathForRewrite(path, force, label) {
|
|
185
|
+
if (!existsSync(path)) return;
|
|
186
|
+
if (!force) throw new Error(`Codemap: ${label} already exists — use --force to replace, or remove it manually.`);
|
|
187
|
+
rmSync(path, {
|
|
188
|
+
recursive: true,
|
|
189
|
+
force: true
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Map `.agents/rules` into a destination directory (symlink or copy).
|
|
194
|
+
*/
|
|
195
|
+
function wireAgentsRulesTo(projectRoot, destPath, label, linkMode, force) {
|
|
196
|
+
const agentsRules = join(projectRoot, ".agents", "rules");
|
|
197
|
+
mkdirSync(dirname(destPath), { recursive: true });
|
|
198
|
+
removePathForRewrite(destPath, force, label);
|
|
199
|
+
if (linkMode === "symlink") {
|
|
200
|
+
const ruleFiles = listRegularFilesRecursive(agentsRules);
|
|
201
|
+
symlinkFilesGranular(agentsRules, destPath, ruleFiles, label);
|
|
202
|
+
console.log(` Linked each file under ${label} → .agents/rules (${ruleFiles.length} files)`);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
copyFilesGranular(agentsRules, destPath, listRegularFilesRecursive(agentsRules));
|
|
206
|
+
console.log(` Copied .agents/rules → ${label}`);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Wire Cursor or other tools after `.agents/` exists.
|
|
210
|
+
*/
|
|
211
|
+
function applyAgentsInitTargets(projectRoot, targets, linkMode, force) {
|
|
212
|
+
const agentsRules = join(projectRoot, ".agents", "rules");
|
|
213
|
+
const agentsSkills = join(projectRoot, ".agents", "skills");
|
|
214
|
+
if (!existsSync(agentsRules) || !existsSync(agentsSkills)) throw new Error("Codemap: .agents/rules and .agents/skills must exist before wiring integrations");
|
|
215
|
+
for (const t of targets) switch (t) {
|
|
216
|
+
case "cursor":
|
|
217
|
+
applyCursorIntegration(projectRoot, linkMode, force);
|
|
218
|
+
break;
|
|
219
|
+
case "windsurf":
|
|
220
|
+
wireAgentsRulesTo(projectRoot, join(projectRoot, ".windsurf", "rules"), ".windsurf/rules", linkMode, force);
|
|
221
|
+
break;
|
|
222
|
+
case "continue":
|
|
223
|
+
wireAgentsRulesTo(projectRoot, join(projectRoot, ".continue", "rules"), ".continue/rules", linkMode, force);
|
|
224
|
+
break;
|
|
225
|
+
case "cline":
|
|
226
|
+
wireAgentsRulesTo(projectRoot, join(projectRoot, ".clinerules"), ".clinerules", linkMode, force);
|
|
227
|
+
break;
|
|
228
|
+
case "amazon-q":
|
|
229
|
+
wireAgentsRulesTo(projectRoot, join(projectRoot, ".amazonq", "rules"), ".amazonq/rules", linkMode, force);
|
|
230
|
+
break;
|
|
231
|
+
case "claude-md":
|
|
232
|
+
upsertCodemapPointerFile(join(projectRoot, "CLAUDE.md"), CLAUDE_MD_TEMPLATE, "CLAUDE.md", force);
|
|
233
|
+
break;
|
|
234
|
+
case "copilot":
|
|
235
|
+
mkdirSync(join(projectRoot, ".github"), { recursive: true });
|
|
236
|
+
upsertCodemapPointerFile(join(projectRoot, ".github", "copilot-instructions.md"), COPILOT_TEMPLATE, ".github/copilot-instructions.md", force);
|
|
237
|
+
break;
|
|
238
|
+
case "agents-md":
|
|
239
|
+
upsertCodemapPointerFile(join(projectRoot, "AGENTS.md"), AGENTS_MD_TEMPLATE, "AGENTS.md", force);
|
|
240
|
+
break;
|
|
241
|
+
case "gemini-md":
|
|
242
|
+
upsertCodemapPointerFile(join(projectRoot, "GEMINI.md"), GEMINI_MD_TEMPLATE, "GEMINI.md", force);
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
function applyCursorIntegration(projectRoot, linkMode, force) {
|
|
247
|
+
const agentsRules = join(projectRoot, ".agents", "rules");
|
|
248
|
+
const agentsSkills = join(projectRoot, ".agents", "skills");
|
|
249
|
+
const cursorRules = join(projectRoot, ".cursor", "rules");
|
|
250
|
+
const cursorSkills = join(projectRoot, ".cursor", "skills");
|
|
251
|
+
mkdirSync(join(projectRoot, ".cursor"), { recursive: true });
|
|
252
|
+
if (linkMode === "symlink") {
|
|
253
|
+
removePathForRewrite(cursorRules, force, ".cursor/rules");
|
|
254
|
+
removePathForRewrite(cursorSkills, force, ".cursor/skills");
|
|
255
|
+
const ruleFiles = listRegularFilesRecursive(agentsRules);
|
|
256
|
+
const skillFiles = listRegularFilesRecursive(agentsSkills);
|
|
257
|
+
symlinkFilesGranular(agentsRules, cursorRules, ruleFiles, ".cursor/rules");
|
|
258
|
+
symlinkFilesGranular(agentsSkills, cursorSkills, skillFiles, ".cursor/skills");
|
|
259
|
+
console.log(` Linked ${ruleFiles.length} rule file(s) and ${skillFiles.length} skill file(s) under .cursor/ → .agents/`);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
removePathForRewrite(cursorRules, force, ".cursor/rules");
|
|
263
|
+
removePathForRewrite(cursorSkills, force, ".cursor/skills");
|
|
264
|
+
copyFilesGranular(agentsRules, cursorRules, listRegularFilesRecursive(agentsRules));
|
|
265
|
+
copyFilesGranular(agentsSkills, cursorSkills, listRegularFilesRecursive(agentsSkills));
|
|
266
|
+
console.log(" Copied rules and skills into .cursor/rules and .cursor/skills");
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Copy bundled `rules/` and `skills/` into `<projectRoot>/.agents/`, optional integrations, `.gitignore` hint.
|
|
270
|
+
* **`--force`** deletes only template-backed files, then writes those files again with per-file copies — your other files under **`.agents/`**, **`rules/`**, or **`skills/`** stay.
|
|
271
|
+
* @returns `false` when `.agents/` exists and `--force` was not used.
|
|
272
|
+
*/
|
|
273
|
+
function runAgentsInit(options) {
|
|
274
|
+
const templateRoot = resolveAgentsTemplateDir();
|
|
275
|
+
if (!existsSync(templateRoot)) throw new Error(`Codemap: agent templates not found at ${templateRoot} (expected npm package layout: templates/agents next to dist/)`);
|
|
276
|
+
const templateRules = join(templateRoot, "rules");
|
|
277
|
+
const templateSkills = join(templateRoot, "skills");
|
|
278
|
+
const bundledRuleFiles = listRegularFilesRecursive(templateRules);
|
|
279
|
+
const bundledSkillFiles = listRegularFilesRecursive(templateSkills);
|
|
280
|
+
const destRoot = join(options.projectRoot, ".agents");
|
|
281
|
+
const destRules = join(destRoot, "rules");
|
|
282
|
+
const destSkills = join(destRoot, "skills");
|
|
283
|
+
if (existsSync(destRoot)) {
|
|
284
|
+
if (!statSync(destRoot).isDirectory()) throw new Error(`Codemap: ${destRoot} exists but is not a directory — remove or rename it, then retry.`);
|
|
285
|
+
if (!options.force) {
|
|
286
|
+
console.error(` .agents/ already exists at ${destRoot}. Re-run with --force to refresh bundled template files under rules/ and skills/, or remove the directory.`);
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
removeBundledPathsIfExist(destRules, bundledRuleFiles);
|
|
290
|
+
removeBundledPathsIfExist(destSkills, bundledSkillFiles);
|
|
291
|
+
} else mkdirSync(destRoot, { recursive: true });
|
|
292
|
+
copyFilesGranular(templateRules, destRules, bundledRuleFiles);
|
|
293
|
+
copyFilesGranular(templateSkills, destSkills, bundledSkillFiles);
|
|
294
|
+
console.log(` Wrote agent templates to ${destRoot}`);
|
|
295
|
+
const targets = options.targets ?? [];
|
|
296
|
+
const linkMode = options.linkMode ?? "symlink";
|
|
297
|
+
if (targets.length > 0) applyAgentsInitTargets(options.projectRoot, targets, linkMode, !!options.force);
|
|
298
|
+
else console.log(" Tip: run `codemap agents init --interactive` to wire editors (Cursor, Copilot, …) or add CLAUDE.md / AGENTS.md");
|
|
299
|
+
ensureGitignoreCodemapPattern(options.projectRoot);
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
//#endregion
|
|
303
|
+
export { targetsNeedLinkMode as n, runAgentsInit as t };
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { n as targetsNeedLinkMode, t as runAgentsInit } from "./agents-init-COkjrzc5.mjs";
|
|
4
|
+
import { cancel, confirm, intro, isCancel, multiselect, note, outro, select } from "@clack/prompts";
|
|
5
|
+
//#region src/agents-init-interactive.ts
|
|
6
|
+
const INTEGRATION_OPTIONS = [
|
|
7
|
+
{
|
|
8
|
+
value: "cursor",
|
|
9
|
+
label: "Cursor",
|
|
10
|
+
hint: ".cursor/rules + skills → .agents/"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
value: "claude-md",
|
|
14
|
+
label: "Claude Code",
|
|
15
|
+
hint: "CLAUDE.md"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
value: "copilot",
|
|
19
|
+
label: "GitHub Copilot",
|
|
20
|
+
hint: ".github/copilot-instructions.md"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
value: "windsurf",
|
|
24
|
+
label: "Windsurf (Cascade)",
|
|
25
|
+
hint: ".windsurf/rules → .agents/rules"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
value: "continue",
|
|
29
|
+
label: "Continue",
|
|
30
|
+
hint: ".continue/rules → .agents/rules"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
value: "cline",
|
|
34
|
+
label: "Cline",
|
|
35
|
+
hint: ".clinerules → .agents/rules"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
value: "amazon-q",
|
|
39
|
+
label: "Amazon Q Developer",
|
|
40
|
+
hint: ".amazonq/rules → .agents/rules"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
value: "agents-md",
|
|
44
|
+
label: "AGENTS.md (Zed, JetBrains, Aider, …)",
|
|
45
|
+
hint: "Root AGENTS.md"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
value: "gemini-md",
|
|
49
|
+
label: "Gemini",
|
|
50
|
+
hint: "GEMINI.md"
|
|
51
|
+
}
|
|
52
|
+
];
|
|
53
|
+
function summarizeTargets(targets) {
|
|
54
|
+
const lines = [];
|
|
55
|
+
for (const t of targets) {
|
|
56
|
+
const opt = INTEGRATION_OPTIONS.find((o) => o.value === t);
|
|
57
|
+
lines.push(opt ? `${opt.label}: ${opt.hint}` : t);
|
|
58
|
+
}
|
|
59
|
+
return lines;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Interactive `codemap agents init`: choose integrations and symlink vs copy for rule mirrors.
|
|
63
|
+
*/
|
|
64
|
+
async function runAgentsInitInteractive(opts) {
|
|
65
|
+
intro("codemap agents init");
|
|
66
|
+
note("Canonical templates always install to .agents/ (rules + skills).\nOptional steps wire other tools to the same content.", "Codemap");
|
|
67
|
+
const targetsRaw = await multiselect({
|
|
68
|
+
message: "Integrations (space to toggle, enter to confirm)",
|
|
69
|
+
options: INTEGRATION_OPTIONS,
|
|
70
|
+
required: false,
|
|
71
|
+
initialValues: []
|
|
72
|
+
});
|
|
73
|
+
if (isCancel(targetsRaw)) {
|
|
74
|
+
cancel("Cancelled.");
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
const targets = targetsRaw;
|
|
78
|
+
let linkMode = "symlink";
|
|
79
|
+
if (targetsNeedLinkMode(targets)) {
|
|
80
|
+
const mode = await select({
|
|
81
|
+
message: "How should tools that mirror .agents/rules (and Cursor skills) link?",
|
|
82
|
+
options: [{
|
|
83
|
+
value: "symlink",
|
|
84
|
+
label: "Symlink",
|
|
85
|
+
hint: "One source of truth; best on macOS / Linux"
|
|
86
|
+
}, {
|
|
87
|
+
value: "copy",
|
|
88
|
+
label: "Copy",
|
|
89
|
+
hint: "Duplicate files; safest on Windows / sandboxes"
|
|
90
|
+
}],
|
|
91
|
+
initialValue: "symlink"
|
|
92
|
+
});
|
|
93
|
+
if (isCancel(mode)) {
|
|
94
|
+
cancel("Cancelled.");
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
linkMode = mode;
|
|
98
|
+
}
|
|
99
|
+
note([
|
|
100
|
+
`Project: ${opts.projectRoot}`,
|
|
101
|
+
"Will write: .agents/rules, .agents/skills",
|
|
102
|
+
...summarizeTargets(targets).map((l) => `• ${l}`)
|
|
103
|
+
].join("\n"), "Summary");
|
|
104
|
+
const ok = await confirm({
|
|
105
|
+
message: "Proceed?",
|
|
106
|
+
initialValue: true
|
|
107
|
+
});
|
|
108
|
+
if (isCancel(ok) || !ok) {
|
|
109
|
+
cancel("Cancelled.");
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
const success = runAgentsInit({
|
|
113
|
+
projectRoot: opts.projectRoot,
|
|
114
|
+
force: opts.force,
|
|
115
|
+
targets,
|
|
116
|
+
linkMode
|
|
117
|
+
});
|
|
118
|
+
if (success) outro("Done. Edit .agents/ for your team; restart IDEs if rules did not reload.");
|
|
119
|
+
return success;
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
export { runAgentsInitInteractive };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { t as runAgentsInit } from "./agents-init-COkjrzc5.mjs";
|
|
4
|
+
//#region src/cli/cmd-agents.ts
|
|
5
|
+
async function runAgentsInitCmd(opts) {
|
|
6
|
+
if (opts.interactive) {
|
|
7
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
8
|
+
console.error("codemap: --interactive requires an interactive terminal (TTY).");
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
const { runAgentsInitInteractive } = await import("./agents-init-interactive-HLqgP8gL.mjs");
|
|
12
|
+
return runAgentsInitInteractive(opts);
|
|
13
|
+
}
|
|
14
|
+
return runAgentsInit(opts);
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { runAgentsInitCmd };
|
package/dist/index.d.mts
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { fileURLToPath } from "node:url";
|
|
|
8
8
|
//#endregion
|
|
9
9
|
//#region src/version.ts
|
|
10
10
|
/** Package version from `package.json` (inlined at build time). */
|
|
11
|
-
const CODEMAP_VERSION = "0.1.
|
|
11
|
+
const CODEMAP_VERSION = "0.1.3";
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region src/cli/bootstrap.ts
|
|
14
14
|
/** Printed for `codemap --help` / `-h` (must run before config or DB access). */
|
|
@@ -23,7 +23,7 @@ Query:
|
|
|
23
23
|
codemap query "<SQL>"
|
|
24
24
|
|
|
25
25
|
Agents:
|
|
26
|
-
codemap agents init [--force]
|
|
26
|
+
codemap agents init [--force] [--interactive|-i]
|
|
27
27
|
|
|
28
28
|
Other:
|
|
29
29
|
codemap version
|
|
@@ -48,7 +48,7 @@ function validateIndexModeArgs(rest) {
|
|
|
48
48
|
if (rest[0] === "query") return;
|
|
49
49
|
if (rest[0] === "agents") {
|
|
50
50
|
if (rest[1] === "init") return;
|
|
51
|
-
console.error(`codemap: unknown agents command "${rest[1] ?? "(missing)"}". Expected: codemap agents init [--force]`);
|
|
51
|
+
console.error(`codemap: unknown agents command "${rest[1] ?? "(missing)"}". Expected: codemap agents init [--force] [--interactive|-i]`);
|
|
52
52
|
process.exit(1);
|
|
53
53
|
}
|
|
54
54
|
let i = 0;
|
|
@@ -116,17 +116,34 @@ async function main() {
|
|
|
116
116
|
}
|
|
117
117
|
if (rest[0] === "agents" && rest[1] === "init") {
|
|
118
118
|
if (rest.includes("--help") || rest.includes("-h")) {
|
|
119
|
-
console.log(`Usage: codemap agents init [--force]
|
|
119
|
+
console.log(`Usage: codemap agents init [--force] [--interactive|-i]
|
|
120
120
|
|
|
121
121
|
Copies bundled agent templates into .agents/ under the project root.
|
|
122
|
-
|
|
122
|
+
--force Refresh only files that ship in templates/agents (merge into rules/ & skills/)
|
|
123
|
+
--interactive Pick IDEs (Cursor, Copilot, Windsurf, …) and symlink vs copy
|
|
123
124
|
`);
|
|
124
125
|
return;
|
|
125
126
|
}
|
|
126
|
-
const
|
|
127
|
-
|
|
127
|
+
const initRest = rest.slice(2);
|
|
128
|
+
const knownInit = new Set([
|
|
129
|
+
"--force",
|
|
130
|
+
"--interactive",
|
|
131
|
+
"-i",
|
|
132
|
+
"--help",
|
|
133
|
+
"-h"
|
|
134
|
+
]);
|
|
135
|
+
for (const a of initRest) {
|
|
136
|
+
if (knownInit.has(a)) continue;
|
|
137
|
+
if (a.startsWith("-")) console.error(`codemap: unknown option "${a}"`);
|
|
138
|
+
else console.error(`codemap: unexpected argument "${a}"`);
|
|
139
|
+
console.error("Run codemap agents init --help for usage.");
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
const { runAgentsInitCmd } = await import("./cmd-agents-Dph66vnf.mjs");
|
|
143
|
+
if (!await runAgentsInitCmd({
|
|
128
144
|
projectRoot: root,
|
|
129
|
-
force: rest.includes("--force")
|
|
145
|
+
force: rest.includes("--force"),
|
|
146
|
+
interactive: rest.includes("--interactive") || rest.includes("-i")
|
|
130
147
|
})) process.exit(1);
|
|
131
148
|
return;
|
|
132
149
|
}
|
|
@@ -140,7 +157,7 @@ Example: codemap query "SELECT name, file_path FROM symbols LIMIT 10"
|
|
|
140
157
|
`);
|
|
141
158
|
return;
|
|
142
159
|
}
|
|
143
|
-
const { runQueryCmd } = await import("./cmd-query-
|
|
160
|
+
const { runQueryCmd } = await import("./cmd-query-lSSRXMX8.mjs");
|
|
144
161
|
await runQueryCmd({
|
|
145
162
|
root,
|
|
146
163
|
configFile,
|
|
@@ -148,7 +165,7 @@ Example: codemap query "SELECT name, file_path FROM symbols LIMIT 10"
|
|
|
148
165
|
});
|
|
149
166
|
return;
|
|
150
167
|
}
|
|
151
|
-
const { runIndexCmd } = await import("./cmd-index-
|
|
168
|
+
const { runIndexCmd } = await import("./cmd-index-UeGdciH7.mjs");
|
|
152
169
|
await runIndexCmd({
|
|
153
170
|
root,
|
|
154
171
|
configFile,
|
package/dist/parse-worker.d.mts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stainless-code/codemap",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Query your codebase — structural SQLite index for AI agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
"typecheck": "tsgo --noEmit"
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
|
+
"@clack/prompts": "^1.2.0",
|
|
69
70
|
"better-sqlite3": "^12.8.0",
|
|
70
71
|
"fast-glob": "^3.3.3",
|
|
71
72
|
"lightningcss": "^1.32.0",
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Bundled agent templates
|
|
2
2
|
|
|
3
|
-
These files
|
|
3
|
+
These files ship with **`@stainless-code/codemap`** for **`codemap agents init`** — written for **npm consumers** ( **`codemap`**, **`npx @stainless-code/codemap`**, etc.).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
In **this** repository, **`.agents/`** (and **`.cursor/`** symlinks) are **maintainer / dev** copies: examples use **`bun src/index.ts`** where that matters. **`templates/agents/`** is the **published** agent surface and is **not** required to match **`.agents/`** byte-for-byte (the **codemap** rule and skill intentionally differ).
|
|
6
|
+
|
|
7
|
+
**Documentation:** [docs/agents.md](../../docs/agents.md) — interactive setup, **`.gitignore`**, and optional IDE wiring (Cursor, Copilot, …).
|
|
8
|
+
|
|
9
|
+
After running the command in **your** project, **edit** **`.agents/`** there (paths, SQL, team conventions). Treat updates here as a reference when refreshing your copy.
|
|
@@ -8,24 +8,33 @@ alwaysApply: true
|
|
|
8
8
|
|
|
9
9
|
A local database (default **`.codemap.db`**) indexes structure: symbols, imports, exports, components, dependencies, markers, CSS variables, CSS classes, CSS keyframes.
|
|
10
10
|
|
|
11
|
-
**Generic defaults:** This rule is **project-agnostic**. After
|
|
11
|
+
**Generic defaults:** This rule is **project-agnostic**. After **`codemap agents init`** (or copying these files into **`.agents/`**), **edit your copy** to add app-specific triggers and SQL — upstream text is only a baseline.
|
|
12
12
|
|
|
13
|
-
## CLI (
|
|
13
|
+
## CLI (npm package **`@stainless-code/codemap`**)
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
| ------- | ----------------- | ----- |
|
|
17
|
-
| Developing in this repo | `bun src/index.ts` | `bun src/index.ts query "<SQL>"` |
|
|
18
|
-
| After `bun link` / global `codemap` | `codemap` | `codemap query "<SQL>"` |
|
|
19
|
-
| Published package (when available) | `bunx @stainless-code/codemap` | `bunx @stainless-code/codemap query "<SQL>"` |
|
|
15
|
+
Install **[@stainless-code/codemap](https://www.npmjs.com/package/@stainless-code/codemap)** from npm. The executable name is **`codemap`**.
|
|
20
16
|
|
|
21
|
-
|
|
17
|
+
**Run without a global install:** **`npx @stainless-code/codemap`** (npm), **`pnpm dlx @stainless-code/codemap`** (pnpm), **`yarn dlx @stainless-code/codemap`** (Yarn 2+), or **`bunx @stainless-code/codemap`** (Bun) — same flags everywhere. With a **local** devDependency, **`npx codemap`** / **`pnpm exec codemap`**. With a **global** install, **`codemap`** on your **`PATH`**.
|
|
18
|
+
|
|
19
|
+
**Examples below use `codemap`** — prefix with **`npx @stainless-code/codemap`** (or **`pnpm dlx`**, **`yarn dlx`**, **`bunx`**) when the CLI is not on your **`PATH`**.
|
|
20
|
+
|
|
21
|
+
| Action | Command |
|
|
22
|
+
| ------ | ------- |
|
|
23
|
+
| Incremental index | `codemap` |
|
|
24
|
+
| Query | `codemap query "<SQL>"` |
|
|
25
|
+
|
|
26
|
+
**Bundled rules/skills:** **`codemap agents init`** writes **`.agents/`** from the package (see [docs/agents.md](../../../docs/agents.md)).
|
|
27
|
+
|
|
28
|
+
Index another project: **`--root /path/to/repo`**, or set **`CODEMAP_ROOT`** or **`CODEMAP_TEST_BENCH`** (e.g. in **`.env`** — see [docs/benchmark.md § Indexing another project](../../../docs/benchmark.md#indexing-another-project)). Full rebuild: **`--full`**. Targeted re-index: **`--files path/to/a.ts path/to/b.tsx`**.
|
|
29
|
+
|
|
30
|
+
**Developing the Codemap repo itself:** from a clone, **`bun src/index.ts`** matches **`codemap`** (same flags); see the repository README.
|
|
22
31
|
|
|
23
32
|
## Session start (do this ONCE per conversation)
|
|
24
33
|
|
|
25
34
|
Run incremental indexing to catch changes made outside this session:
|
|
26
35
|
|
|
27
36
|
```bash
|
|
28
|
-
|
|
37
|
+
codemap
|
|
29
38
|
```
|
|
30
39
|
|
|
31
40
|
## Pre-flight check (do this EVERY time before searching)
|
|
@@ -62,7 +71,7 @@ If the question looks like any of these → use the index:
|
|
|
62
71
|
## How to query
|
|
63
72
|
|
|
64
73
|
```bash
|
|
65
|
-
|
|
74
|
+
codemap query "<SQL>"
|
|
66
75
|
```
|
|
67
76
|
|
|
68
77
|
## Quick reference queries
|
|
@@ -94,13 +103,13 @@ For the full schema, advanced query patterns, and troubleshooting, read the skil
|
|
|
94
103
|
|
|
95
104
|
```bash
|
|
96
105
|
# Targeted — re-index only the files you just touched
|
|
97
|
-
|
|
106
|
+
codemap --files path/to/file1.tsx path/to/file2.ts
|
|
98
107
|
|
|
99
108
|
# Incremental — auto-detects changed files via git
|
|
100
|
-
|
|
109
|
+
codemap
|
|
101
110
|
|
|
102
111
|
# Full rebuild — after rebase, branch switch, or stale index
|
|
103
|
-
|
|
112
|
+
codemap --full
|
|
104
113
|
```
|
|
105
114
|
|
|
106
115
|
### When to re-index
|
|
@@ -6,15 +6,15 @@ Query codebase structure via SQLite instead of scanning files. Use when explorin
|
|
|
6
6
|
|
|
7
7
|
Examples below use **placeholders** (`'...'`, `getConfig`, `~/lib/api`, etc.) — not a real product tree. **Shipped skill and rules stay generic** so they apply to any repo.
|
|
8
8
|
|
|
9
|
-
**In your project:**
|
|
9
|
+
**In your project:** run **`codemap agents init`** (ships **`.agents/`** from **[@stainless-code/codemap](https://www.npmjs.com/package/@stainless-code/codemap)**), or copy/symlink rules and skills manually (see your repo’s contributor docs). Then **edit your copy** to add your team’s tsconfig aliases, directory conventions, and SQL snippets you reuse. Treat upstream updates as a reference; merge deliberately.
|
|
10
10
|
|
|
11
|
-
**Run queries**
|
|
11
|
+
**Run queries** (same CLI everywhere — use **`npx @stainless-code/codemap`**, **`pnpm dlx @stainless-code/codemap`**, **`yarn dlx @stainless-code/codemap`**, or **`bunx @stainless-code/codemap`** if **`codemap`** is not on your **`PATH`**):
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
|
|
14
|
+
codemap query "<SQL>"
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Use **`codemap --root /path/to/project`** (or **`CODEMAP_ROOT`**) to index another tree.
|
|
18
18
|
|
|
19
19
|
## Schema
|
|
20
20
|
|
|
@@ -282,31 +282,31 @@ SELECT kind, COUNT(*) as count FROM markers GROUP BY kind;
|
|
|
282
282
|
|
|
283
283
|
## Maintenance
|
|
284
284
|
|
|
285
|
-
From
|
|
285
|
+
From the **[@stainless-code/codemap](https://www.npmjs.com/package/@stainless-code/codemap)** CLI (see the **codemap** rule for **`npx` / `pnpm dlx` / `yarn dlx` / `bunx`** invocations):
|
|
286
286
|
|
|
287
287
|
```bash
|
|
288
288
|
# Targeted — re-index only specific files you just modified
|
|
289
|
-
|
|
289
|
+
codemap --files path/to/file.tsx path/to/other.ts
|
|
290
290
|
|
|
291
291
|
# Incremental — auto-detects changes via git
|
|
292
|
-
|
|
292
|
+
codemap
|
|
293
293
|
|
|
294
294
|
# Full rebuild — after rebase, branch switch, or stale index
|
|
295
|
-
|
|
295
|
+
codemap --full
|
|
296
296
|
|
|
297
297
|
# Check index freshness
|
|
298
|
-
|
|
298
|
+
codemap query "SELECT key, value FROM meta"
|
|
299
299
|
```
|
|
300
300
|
|
|
301
301
|
**Prefer `--files`** when you know which files you changed — it skips git diff and filesystem scanning for the rest of the tree. Deleted files passed to `--files` are auto-removed from the index.
|
|
302
302
|
|
|
303
|
-
|
|
303
|
+
Same flags as **`npx @stainless-code/codemap`**, **`pnpm dlx @stainless-code/codemap`**, etc. **`codemap --root /path/to/project`** indexes another working tree.
|
|
304
304
|
|
|
305
305
|
## Troubleshooting
|
|
306
306
|
|
|
307
|
-
| Problem | Solution
|
|
308
|
-
| -------------------------- |
|
|
309
|
-
| Stale results after rebase | Run
|
|
310
|
-
| Missing file in results | Check exclude / include globs in **`codemap.config.ts`**, **`codemap.config.json`**, or
|
|
311
|
-
| `resolved_path` is NULL | Import is an external package (not in project)
|
|
312
|
-
| Resolver errors | Verify `tsconfig.json` paths (or **`tsconfigPath`** in config) when resolving aliases
|
|
307
|
+
| Problem | Solution |
|
|
308
|
+
| -------------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
309
|
+
| Stale results after rebase | Run **`codemap --full`** (see **`npx @stainless-code/codemap`** / **`pnpm dlx`** / … above if needed) |
|
|
310
|
+
| Missing file in results | Check exclude / include globs in **`codemap.config.ts`**, **`codemap.config.json`**, or **`codemap --help`** defaults |
|
|
311
|
+
| `resolved_path` is NULL | Import is an external package (not in project) |
|
|
312
|
+
| Resolver errors | Verify `tsconfig.json` paths (or **`tsconfigPath`** in config) when resolving aliases |
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { cpSync, existsSync, mkdirSync } from "node:fs";
|
|
6
|
-
//#region src/agents-init.ts
|
|
7
|
-
/**
|
|
8
|
-
* Directory containing `rules/` and `skills/` (next to `dist/` in published packages).
|
|
9
|
-
*/
|
|
10
|
-
function resolveAgentsTemplateDir() {
|
|
11
|
-
return join(dirname(fileURLToPath(import.meta.url)), "..", "templates", "agents");
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Copy bundled rules and skills into `<projectRoot>/.agents/`.
|
|
15
|
-
* @returns `false` when `.agents/` exists and `--force` was not used.
|
|
16
|
-
*/
|
|
17
|
-
function runAgentsInit(options) {
|
|
18
|
-
const templateRoot = resolveAgentsTemplateDir();
|
|
19
|
-
if (!existsSync(templateRoot)) throw new Error(`Codemap: agent templates not found at ${templateRoot} (expected npm package layout: templates/agents next to dist/)`);
|
|
20
|
-
const destRoot = join(options.projectRoot, ".agents");
|
|
21
|
-
if (existsSync(destRoot) && !options.force) {
|
|
22
|
-
console.error(` .agents/ already exists at ${destRoot}. Re-run with --force to overwrite, or remove the directory.`);
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
mkdirSync(destRoot, { recursive: true });
|
|
26
|
-
cpSync(join(templateRoot, "rules"), join(destRoot, "rules"), { recursive: true });
|
|
27
|
-
cpSync(join(templateRoot, "skills"), join(destRoot, "skills"), { recursive: true });
|
|
28
|
-
console.log(` Wrote agent templates to ${destRoot}`);
|
|
29
|
-
console.log(` Symlink into .cursor/ if needed — see https://github.com/stainless-code/codemap/blob/main/.github/CONTRIBUTING.md`);
|
|
30
|
-
return true;
|
|
31
|
-
}
|
|
32
|
-
//#endregion
|
|
33
|
-
//#region src/cli/cmd-agents.ts
|
|
34
|
-
function runAgentsInitCmd(opts) {
|
|
35
|
-
return runAgentsInit(opts);
|
|
36
|
-
}
|
|
37
|
-
//#endregion
|
|
38
|
-
export { runAgentsInitCmd };
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: When creating or moving rules/skills, always store the source file in .agents/ and symlink from .cursor/
|
|
3
|
-
alwaysApply: true
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Agents-First File Convention
|
|
7
|
-
|
|
8
|
-
When creating **any** new rule or skill, follow this convention:
|
|
9
|
-
|
|
10
|
-
## Rules (`.mdc` files)
|
|
11
|
-
|
|
12
|
-
1. Create the file in `.agents/rules/<name>.mdc`
|
|
13
|
-
2. Create a symlink in `.cursor/rules/`:
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
ln -s ../../.agents/rules/<name>.mdc .cursor/rules/<name>.mdc
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Skills (`SKILL.md` files)
|
|
20
|
-
|
|
21
|
-
1. Create the directory and file in `.agents/skills/<name>/SKILL.md`
|
|
22
|
-
2. Create a symlink in `.cursor/skills/`:
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
ln -s ../../.agents/skills/<name> .cursor/skills/<name>
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Why
|
|
29
|
-
|
|
30
|
-
- `.agents/` is the **source of truth** — it is IDE-agnostic and works across different AI coding tools.
|
|
31
|
-
- `.cursor/` only contains **symlinks** pointing back to `.agents/`.
|
|
32
|
-
- This keeps configuration portable and avoids duplication.
|
|
33
|
-
|
|
34
|
-
## Never
|
|
35
|
-
|
|
36
|
-
- Never place original rule/skill content directly in `.cursor/rules/` or `.cursor/skills/`.
|
|
37
|
-
- Never create a rule or skill without both the `.agents/` file and the `.cursor/` symlink.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|