create-nola-lang 0.1.3 → 0.1.4
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/agents.d.ts +27 -2
- package/dist/agents.d.ts.map +1 -1
- package/dist/agents.js +136 -67
- package/dist/agents.js.map +1 -1
- package/dist/{chunk-CMVM4Q25.js → chunk-VZM5EYBG.js} +118 -59
- package/dist/index.js +5 -3
- package/dist/main.js +1 -1
- package/dist/skill-install.d.ts +2 -0
- package/dist/skill-install.d.ts.map +1 -1
- package/dist/skill-install.js +6 -2
- package/dist/skill-install.js.map +1 -1
- package/package.json +3 -2
- package/skills/nola/SKILL.md +75 -0
- package/skills/nola/references/config.md +227 -0
- package/skills/nola/references/patterns.md +277 -0
- package/skills/nola/references/pitfalls.md +289 -0
- package/skills/nola/references/syntax.md +377 -0
- package/templates/starter/_gitignore +2 -0
package/dist/agents.d.ts
CHANGED
|
@@ -6,6 +6,22 @@ export declare const AGENT_OPTIONS: {
|
|
|
6
6
|
label: string;
|
|
7
7
|
hint: string;
|
|
8
8
|
}[];
|
|
9
|
+
/**
|
|
10
|
+
* Adapters that inject context inline embed SKILL.md's BODY verbatim, so no
|
|
11
|
+
* adapter restates the language rules in its own words and the four can
|
|
12
|
+
* never drift from each other (spec §2).
|
|
13
|
+
*/
|
|
14
|
+
export interface SkillSource {
|
|
15
|
+
/** the frontmatter block of SKILL.md, without the --- fences */
|
|
16
|
+
frontmatter: string;
|
|
17
|
+
/** the first heading up to (not including) `## References` */
|
|
18
|
+
body: string;
|
|
19
|
+
/** the whole file, verbatim — what the claude adapter copies */
|
|
20
|
+
full: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function readSkillSource(): Promise<SkillSource>;
|
|
23
|
+
/** The `## Nola` section for AGENTS.md — also the paste snippet when skipped. */
|
|
24
|
+
export declare function agentsSection(s: SkillSource, version: string): string;
|
|
9
25
|
/** Agents whose tooling is already present in the project. */
|
|
10
26
|
export declare function detectAgents(targetDir: string): AgentId[];
|
|
11
27
|
/** The interactive preselection: detected agents + the cross-agent baseline. */
|
|
@@ -17,7 +33,16 @@ export interface AgentSetupResult {
|
|
|
17
33
|
wrote: string[];
|
|
18
34
|
/** human-readable notes about files left untouched */
|
|
19
35
|
skipped: string[];
|
|
36
|
+
/** true when something was left stale — the caller can suggest --force */
|
|
37
|
+
stale: boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface WriteAgentSkillsOptions {
|
|
40
|
+
/** replace files stamped by another version (never touches unstamped files) */
|
|
41
|
+
force?: boolean;
|
|
20
42
|
}
|
|
21
|
-
/**
|
|
22
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Write the selected adapters as self-contained, version-stamped content.
|
|
45
|
+
* Existing files are classified, never blindly overwritten (spec §3).
|
|
46
|
+
*/
|
|
47
|
+
export declare function writeAgentSkills(targetDir: string, agents: AgentId[], opts?: WriteAgentSkillsOptions): Promise<AgentSetupResult>;
|
|
23
48
|
//# sourceMappingURL=agents.d.ts.map
|
package/dist/agents.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;AAEpE,eAAO,MAAM,SAAS,EAAE,SAAS,OAAO,EAAiD,CAAC;AAE1F,wEAAwE;AACxE,eAAO,MAAM,aAAa,EAAE;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAK1E,CAAC;AAiBF;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,gEAAgE;IAChE,WAAW,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,WAAW,CAAC,CAQ5D;AA6BD,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAErE;AAMD,8DAA8D;AAC9D,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,EAAE,CAOzD;AAED,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,EAAE,CAE1D;AAED,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,CAaxD;AAED,MAAM,WAAW,gBAAgB;IAC/B,2CAA2C;IAC3C,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,sDAAsD;IACtD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,0EAA0E;IAC1E,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,uBAAuB;IACtC,+EAA+E;IAC/E,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAyCD;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,OAAO,EAAE,EACjB,IAAI,GAAE,uBAA4B,GACjC,OAAO,CAAC,gBAAgB,CAAC,CAsD3B"}
|
package/dist/agents.js
CHANGED
|
@@ -1,70 +1,68 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import { dirname, join, resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { ownVersion } from "./scaffold.js";
|
|
4
6
|
export const AGENT_IDS = ["claude", "cursor", "copilot", "agents-md"];
|
|
5
7
|
/** Shared option list for every "Set up coding agents?" multiselect. */
|
|
6
8
|
export const AGENT_OPTIONS = [
|
|
7
|
-
{ value: "agents-md", label: "AGENTS.md", hint: "cross-agent
|
|
8
|
-
{ value: "claude", label: "Claude Code", hint: ".claude/skills/nola/
|
|
9
|
+
{ value: "agents-md", label: "AGENTS.md", hint: "cross-agent instructions (Codex, Gemini CLI, …)" },
|
|
10
|
+
{ value: "claude", label: "Claude Code", hint: ".claude/skills/nola/ (full skill + references)" },
|
|
9
11
|
{ value: "cursor", label: "Cursor", hint: ".cursor/rules/nola.mdc" },
|
|
10
12
|
{ value: "copilot", label: "GitHub Copilot", hint: ".github/instructions/nola.instructions.md" },
|
|
11
13
|
];
|
|
12
14
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* (
|
|
15
|
+
* The canonical skill content, resolved relative to this module — `src/` in
|
|
16
|
+
* this checkout, `dist/` in the published tarball, both one level under the
|
|
17
|
+
* package root (the same trick TEMPLATES_DIR uses in scaffold.ts).
|
|
16
18
|
*/
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
cursor: { path: ".cursor/rules/nola.mdc", content: CURSOR_RULE },
|
|
65
|
-
copilot: { path: ".github/instructions/nola.instructions.md", content: COPILOT_INSTRUCTIONS },
|
|
66
|
-
"agents-md": { path: "AGENTS.md", content: AGENTS_MD },
|
|
67
|
-
};
|
|
19
|
+
const SKILLS_DIR = fileURLToPath(new URL("../skills/nola/", import.meta.url));
|
|
20
|
+
/** Marks a generated file so staleness is detectable (spec §3). */
|
|
21
|
+
const STAMP_RE = /^<!-- nola-skill v(\S+)/m;
|
|
22
|
+
const stamp = (version) => `<!-- nola-skill v${version} — regenerate with: nola skill install --force -->`;
|
|
23
|
+
/** Pointer-era adapters (0.1.0–0.1.3) named this path; they are superseded. */
|
|
24
|
+
const LEGACY_MARKER = "node_modules/nola-lang/skills/nola";
|
|
25
|
+
export async function readSkillSource() {
|
|
26
|
+
const full = (await readFile(join(SKILLS_DIR, "SKILL.md"), "utf8")).replaceAll("\r\n", "\n");
|
|
27
|
+
const fm = /^---\n([\s\S]*?)\n---\n/.exec(full);
|
|
28
|
+
if (!fm)
|
|
29
|
+
throw new Error("SKILL.md is missing its frontmatter block");
|
|
30
|
+
const afterFm = full.slice(fm[0].length);
|
|
31
|
+
const refsAt = afterFm.indexOf("\n## References");
|
|
32
|
+
const body = (refsAt === -1 ? afterFm : afterFm.slice(0, refsAt)).trim();
|
|
33
|
+
return { frontmatter: fm[1], body, full };
|
|
34
|
+
}
|
|
35
|
+
/** Points at the project-local copy — never node_modules (spec §1). */
|
|
36
|
+
const LOCAL_REFERENCES = [
|
|
37
|
+
"Deeper references, when this repo has them:",
|
|
38
|
+
"`.claude/skills/nola/references/` — syntax.md, patterns.md, config.md,",
|
|
39
|
+
"pitfalls.md.",
|
|
40
|
+
].join("\n");
|
|
41
|
+
function cursorRule(s, version) {
|
|
42
|
+
return [
|
|
43
|
+
"---",
|
|
44
|
+
"description: Nola (.tsi) language rules",
|
|
45
|
+
'globs: ["**/*.tsi", "nola.config.ts"]',
|
|
46
|
+
"alwaysApply: false",
|
|
47
|
+
"---",
|
|
48
|
+
stamp(version),
|
|
49
|
+
"",
|
|
50
|
+
s.body,
|
|
51
|
+
"",
|
|
52
|
+
LOCAL_REFERENCES,
|
|
53
|
+
"",
|
|
54
|
+
].join("\n");
|
|
55
|
+
}
|
|
56
|
+
function copilotInstructions(s, version) {
|
|
57
|
+
return ["---", 'applyTo: "**/*.tsi"', "---", stamp(version), "", s.body, "", LOCAL_REFERENCES, ""].join("\n");
|
|
58
|
+
}
|
|
59
|
+
/** The `## Nola` section for AGENTS.md — also the paste snippet when skipped. */
|
|
60
|
+
export function agentsSection(s, version) {
|
|
61
|
+
return ["## Nola", "", stamp(version), "", s.body, "", LOCAL_REFERENCES, ""].join("\n");
|
|
62
|
+
}
|
|
63
|
+
function agentsMd(s, version) {
|
|
64
|
+
return `# AGENTS.md\n\n${agentsSection(s, version)}`;
|
|
65
|
+
}
|
|
68
66
|
/** Agents whose tooling is already present in the project. */
|
|
69
67
|
export function detectAgents(targetDir) {
|
|
70
68
|
const root = resolve(targetDir);
|
|
@@ -87,7 +85,10 @@ export function parseAgentsFlag(value) {
|
|
|
87
85
|
return [...AGENT_IDS];
|
|
88
86
|
if (value === "none")
|
|
89
87
|
return [];
|
|
90
|
-
const ids = value
|
|
88
|
+
const ids = value
|
|
89
|
+
.split(",")
|
|
90
|
+
.map((s) => s.trim())
|
|
91
|
+
.filter(Boolean);
|
|
91
92
|
for (const id of ids) {
|
|
92
93
|
if (!AGENT_IDS.includes(id)) {
|
|
93
94
|
throw new Error(`invalid --agents "${value}" (valid: ${AGENT_IDS.join(", ")} — or all, none)`);
|
|
@@ -95,27 +96,95 @@ export function parseAgentsFlag(value) {
|
|
|
95
96
|
}
|
|
96
97
|
return [...new Set(ids)];
|
|
97
98
|
}
|
|
98
|
-
/**
|
|
99
|
-
|
|
99
|
+
/** Classify an existing target per spec §3. */
|
|
100
|
+
function disposition(path, existing, version, force) {
|
|
101
|
+
const found = STAMP_RE.exec(existing);
|
|
102
|
+
// Legacy pointers are checked FIRST and independently of the stamp: the
|
|
103
|
+
// 0.1.0–0.1.3 adapters predate stamping, so they carry none at all.
|
|
104
|
+
const legacy = existing.includes(LEGACY_MARKER);
|
|
105
|
+
if (!legacy) {
|
|
106
|
+
if (!found) {
|
|
107
|
+
return {
|
|
108
|
+
write: false,
|
|
109
|
+
note: `${path} already exists and was not generated by nola — left untouched`,
|
|
110
|
+
stale: false,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
if (found[1] === version)
|
|
114
|
+
return { write: false, note: `${path} is up to date (v${version})`, stale: false };
|
|
115
|
+
}
|
|
116
|
+
if (force)
|
|
117
|
+
return { write: true };
|
|
118
|
+
const what = legacy
|
|
119
|
+
? `${path} uses the superseded pointer form`
|
|
120
|
+
: `${path} is stale (v${found?.[1]} → v${version})`;
|
|
121
|
+
return { write: false, note: `${what} — re-run with --force to replace it`, stale: true };
|
|
122
|
+
}
|
|
123
|
+
/** Copy the canonical skill dir verbatim (stamp aside) into .claude/skills/nola/. */
|
|
124
|
+
async function writeClaudeSkill(root, s, version) {
|
|
125
|
+
const dir = join(root, ".claude", "skills", "nola");
|
|
126
|
+
await mkdir(join(dir, "references"), { recursive: true });
|
|
127
|
+
const stamped = s.full.replace(/^(---\n[\s\S]*?\n---\n)/, `$1${stamp(version)}\n`);
|
|
128
|
+
await writeFile(join(dir, "SKILL.md"), stamped);
|
|
129
|
+
const wrote = [".claude/skills/nola/SKILL.md"];
|
|
130
|
+
for (const name of (await readdir(join(SKILLS_DIR, "references"))).sort()) {
|
|
131
|
+
await writeFile(join(dir, "references", name), await readFile(join(SKILLS_DIR, "references", name), "utf8"));
|
|
132
|
+
wrote.push(`.claude/skills/nola/references/${name}`);
|
|
133
|
+
}
|
|
134
|
+
return wrote;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Write the selected adapters as self-contained, version-stamped content.
|
|
138
|
+
* Existing files are classified, never blindly overwritten (spec §3).
|
|
139
|
+
*/
|
|
140
|
+
export async function writeAgentSkills(targetDir, agents, opts = {}) {
|
|
100
141
|
const root = resolve(targetDir);
|
|
142
|
+
const version = await ownVersion();
|
|
143
|
+
const source = await readSkillSource();
|
|
144
|
+
const force = opts.force === true;
|
|
101
145
|
const wrote = [];
|
|
102
146
|
const skipped = [];
|
|
147
|
+
let stale = false;
|
|
148
|
+
const flat = {
|
|
149
|
+
cursor: { path: ".cursor/rules/nola.mdc", content: cursorRule(source, version) },
|
|
150
|
+
copilot: { path: ".github/instructions/nola.instructions.md", content: copilotInstructions(source, version) },
|
|
151
|
+
"agents-md": { path: "AGENTS.md", content: agentsMd(source, version) },
|
|
152
|
+
};
|
|
103
153
|
for (const id of AGENT_IDS) {
|
|
104
154
|
if (!agents.includes(id))
|
|
105
155
|
continue;
|
|
106
|
-
|
|
156
|
+
if (id === "claude") {
|
|
157
|
+
const marker = join(root, ".claude", "skills", "nola", "SKILL.md");
|
|
158
|
+
if (existsSync(marker)) {
|
|
159
|
+
const d = disposition(".claude/skills/nola/SKILL.md", await readFile(marker, "utf8"), version, force);
|
|
160
|
+
if (!d.write) {
|
|
161
|
+
skipped.push(d.note);
|
|
162
|
+
stale ||= d.stale;
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
wrote.push(...(await writeClaudeSkill(root, source, version)));
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
const { path, content } = flat[id];
|
|
107
170
|
const abs = join(root, ...path.split("/"));
|
|
108
171
|
if (existsSync(abs)) {
|
|
109
|
-
// AGENTS.md
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
172
|
+
// AGENTS.md is a user file: never modified, --force included.
|
|
173
|
+
if (id === "agents-md") {
|
|
174
|
+
skipped.push(`AGENTS.md already exists — left untouched. Add this section manually:\n\n${agentsSection(source, version)}`);
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
const d = disposition(path, await readFile(abs, "utf8"), version, force);
|
|
178
|
+
if (!d.write) {
|
|
179
|
+
skipped.push(d.note);
|
|
180
|
+
stale ||= d.stale;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
114
183
|
}
|
|
115
184
|
await mkdir(dirname(abs), { recursive: true });
|
|
116
185
|
await writeFile(abs, content);
|
|
117
186
|
wrote.push(path);
|
|
118
187
|
}
|
|
119
|
-
return { wrote, skipped };
|
|
188
|
+
return { wrote, skipped, stale };
|
|
120
189
|
}
|
|
121
190
|
//# sourceMappingURL=agents.js.map
|
package/dist/agents.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"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"}
|
|
@@ -224,61 +224,60 @@ async function addNola(targetDir, opts = {}) {
|
|
|
224
224
|
|
|
225
225
|
// src/agents.ts
|
|
226
226
|
import { existsSync as existsSync4 } from "node:fs";
|
|
227
|
-
import { mkdir as mkdir2, writeFile as writeFile3 } from "node:fs/promises";
|
|
227
|
+
import { mkdir as mkdir2, readdir as readdir3, readFile as readFile4, writeFile as writeFile3 } from "node:fs/promises";
|
|
228
228
|
import { dirname, join as join4, resolve as resolve3 } from "node:path";
|
|
229
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
229
230
|
var AGENT_IDS = ["claude", "cursor", "copilot", "agents-md"];
|
|
230
231
|
var AGENT_OPTIONS = [
|
|
231
|
-
{ value: "agents-md", label: "AGENTS.md", hint: "cross-agent
|
|
232
|
-
{ value: "claude", label: "Claude Code", hint: ".claude/skills/nola/
|
|
232
|
+
{ value: "agents-md", label: "AGENTS.md", hint: "cross-agent instructions (Codex, Gemini CLI, \u2026)" },
|
|
233
|
+
{ value: "claude", label: "Claude Code", hint: ".claude/skills/nola/ (full skill + references)" },
|
|
233
234
|
{ value: "cursor", label: "Cursor", hint: ".cursor/rules/nola.mdc" },
|
|
234
235
|
{ value: "copilot", label: "GitHub Copilot", hint: ".github/instructions/nola.instructions.md" }
|
|
235
236
|
];
|
|
236
|
-
var
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
237
|
+
var SKILLS_DIR = fileURLToPath3(new URL("../skills/nola/", import.meta.url));
|
|
238
|
+
var STAMP_RE = /^<!-- nola-skill v(\S+)/m;
|
|
239
|
+
var stamp = (version) => `<!-- nola-skill v${version} \u2014 regenerate with: nola skill install --force -->`;
|
|
240
|
+
var LEGACY_MARKER = "node_modules/nola-lang/skills/nola";
|
|
241
|
+
async function readSkillSource() {
|
|
242
|
+
const full = (await readFile4(join4(SKILLS_DIR, "SKILL.md"), "utf8")).replaceAll("\r\n", "\n");
|
|
243
|
+
const fm = /^---\n([\s\S]*?)\n---\n/.exec(full);
|
|
244
|
+
if (!fm) throw new Error("SKILL.md is missing its frontmatter block");
|
|
245
|
+
const afterFm = full.slice(fm[0].length);
|
|
246
|
+
const refsAt = afterFm.indexOf("\n## References");
|
|
247
|
+
const body = (refsAt === -1 ? afterFm : afterFm.slice(0, refsAt)).trim();
|
|
248
|
+
return { frontmatter: fm[1], body, full };
|
|
249
|
+
}
|
|
250
|
+
var LOCAL_REFERENCES = [
|
|
251
|
+
"Deeper references, when this repo has them:",
|
|
252
|
+
"`.claude/skills/nola/references/` \u2014 syntax.md, patterns.md, config.md,",
|
|
253
|
+
"pitfalls.md."
|
|
254
|
+
].join("\n");
|
|
255
|
+
function cursorRule(s, version) {
|
|
256
|
+
return [
|
|
257
|
+
"---",
|
|
258
|
+
"description: Nola (.tsi) language rules",
|
|
259
|
+
'globs: ["**/*.tsi", "nola.config.ts"]',
|
|
260
|
+
"alwaysApply: false",
|
|
261
|
+
"---",
|
|
262
|
+
stamp(version),
|
|
263
|
+
"",
|
|
264
|
+
s.body,
|
|
265
|
+
"",
|
|
266
|
+
LOCAL_REFERENCES,
|
|
267
|
+
""
|
|
268
|
+
].join("\n");
|
|
269
|
+
}
|
|
270
|
+
function copilotInstructions(s, version) {
|
|
271
|
+
return ["---", 'applyTo: "**/*.tsi"', "---", stamp(version), "", s.body, "", LOCAL_REFERENCES, ""].join("\n");
|
|
272
|
+
}
|
|
273
|
+
function agentsSection(s, version) {
|
|
274
|
+
return ["## Nola", "", stamp(version), "", s.body, "", LOCAL_REFERENCES, ""].join("\n");
|
|
275
|
+
}
|
|
276
|
+
function agentsMd(s, version) {
|
|
277
|
+
return `# AGENTS.md
|
|
274
278
|
|
|
275
|
-
${
|
|
276
|
-
|
|
277
|
-
claude: { path: ".claude/skills/nola/SKILL.md", content: CLAUDE_SKILL },
|
|
278
|
-
cursor: { path: ".cursor/rules/nola.mdc", content: CURSOR_RULE },
|
|
279
|
-
copilot: { path: ".github/instructions/nola.instructions.md", content: COPILOT_INSTRUCTIONS },
|
|
280
|
-
"agents-md": { path: "AGENTS.md", content: AGENTS_MD }
|
|
281
|
-
};
|
|
279
|
+
${agentsSection(s, version)}`;
|
|
280
|
+
}
|
|
282
281
|
function detectAgents(targetDir) {
|
|
283
282
|
const root = resolve3(targetDir);
|
|
284
283
|
const found = [];
|
|
@@ -301,27 +300,87 @@ function parseAgentsFlag(value) {
|
|
|
301
300
|
}
|
|
302
301
|
return [...new Set(ids)];
|
|
303
302
|
}
|
|
304
|
-
|
|
303
|
+
function disposition(path, existing, version, force) {
|
|
304
|
+
const found = STAMP_RE.exec(existing);
|
|
305
|
+
const legacy = existing.includes(LEGACY_MARKER);
|
|
306
|
+
if (!legacy) {
|
|
307
|
+
if (!found) {
|
|
308
|
+
return {
|
|
309
|
+
write: false,
|
|
310
|
+
note: `${path} already exists and was not generated by nola \u2014 left untouched`,
|
|
311
|
+
stale: false
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
if (found[1] === version) return { write: false, note: `${path} is up to date (v${version})`, stale: false };
|
|
315
|
+
}
|
|
316
|
+
if (force) return { write: true };
|
|
317
|
+
const what = legacy ? `${path} uses the superseded pointer form` : `${path} is stale (v${found?.[1]} \u2192 v${version})`;
|
|
318
|
+
return { write: false, note: `${what} \u2014 re-run with --force to replace it`, stale: true };
|
|
319
|
+
}
|
|
320
|
+
async function writeClaudeSkill(root, s, version) {
|
|
321
|
+
const dir = join4(root, ".claude", "skills", "nola");
|
|
322
|
+
await mkdir2(join4(dir, "references"), { recursive: true });
|
|
323
|
+
const stamped = s.full.replace(/^(---\n[\s\S]*?\n---\n)/, `$1${stamp(version)}
|
|
324
|
+
`);
|
|
325
|
+
await writeFile3(join4(dir, "SKILL.md"), stamped);
|
|
326
|
+
const wrote = [".claude/skills/nola/SKILL.md"];
|
|
327
|
+
for (const name of (await readdir3(join4(SKILLS_DIR, "references"))).sort()) {
|
|
328
|
+
await writeFile3(join4(dir, "references", name), await readFile4(join4(SKILLS_DIR, "references", name), "utf8"));
|
|
329
|
+
wrote.push(`.claude/skills/nola/references/${name}`);
|
|
330
|
+
}
|
|
331
|
+
return wrote;
|
|
332
|
+
}
|
|
333
|
+
async function writeAgentSkills(targetDir, agents, opts = {}) {
|
|
305
334
|
const root = resolve3(targetDir);
|
|
335
|
+
const version = await ownVersion();
|
|
336
|
+
const source = await readSkillSource();
|
|
337
|
+
const force = opts.force === true;
|
|
306
338
|
const wrote = [];
|
|
307
339
|
const skipped = [];
|
|
340
|
+
let stale = false;
|
|
341
|
+
const flat = {
|
|
342
|
+
cursor: { path: ".cursor/rules/nola.mdc", content: cursorRule(source, version) },
|
|
343
|
+
copilot: { path: ".github/instructions/nola.instructions.md", content: copilotInstructions(source, version) },
|
|
344
|
+
"agents-md": { path: "AGENTS.md", content: agentsMd(source, version) }
|
|
345
|
+
};
|
|
308
346
|
for (const id of AGENT_IDS) {
|
|
309
347
|
if (!agents.includes(id)) continue;
|
|
310
|
-
|
|
348
|
+
if (id === "claude") {
|
|
349
|
+
const marker = join4(root, ".claude", "skills", "nola", "SKILL.md");
|
|
350
|
+
if (existsSync4(marker)) {
|
|
351
|
+
const d = disposition(".claude/skills/nola/SKILL.md", await readFile4(marker, "utf8"), version, force);
|
|
352
|
+
if (!d.write) {
|
|
353
|
+
skipped.push(d.note);
|
|
354
|
+
stale ||= d.stale;
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
wrote.push(...await writeClaudeSkill(root, source, version));
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
const { path, content } = flat[id];
|
|
311
362
|
const abs = join4(root, ...path.split("/"));
|
|
312
363
|
if (existsSync4(abs)) {
|
|
313
|
-
|
|
314
|
-
|
|
364
|
+
if (id === "agents-md") {
|
|
365
|
+
skipped.push(
|
|
366
|
+
`AGENTS.md already exists \u2014 left untouched. Add this section manually:
|
|
315
367
|
|
|
316
|
-
${
|
|
317
|
-
|
|
318
|
-
|
|
368
|
+
${agentsSection(source, version)}`
|
|
369
|
+
);
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
const d = disposition(path, await readFile4(abs, "utf8"), version, force);
|
|
373
|
+
if (!d.write) {
|
|
374
|
+
skipped.push(d.note);
|
|
375
|
+
stale ||= d.stale;
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
319
378
|
}
|
|
320
379
|
await mkdir2(dirname(abs), { recursive: true });
|
|
321
380
|
await writeFile3(abs, content);
|
|
322
381
|
wrote.push(path);
|
|
323
382
|
}
|
|
324
|
-
return { wrote, skipped };
|
|
383
|
+
return { wrote, skipped, stale };
|
|
325
384
|
}
|
|
326
385
|
|
|
327
386
|
// src/ide.ts
|
|
@@ -375,7 +434,7 @@ async function writeVscodeSetup(targetDir) {
|
|
|
375
434
|
|
|
376
435
|
// src/flow.ts
|
|
377
436
|
import { existsSync as existsSync6 } from "node:fs";
|
|
378
|
-
import { readdir as
|
|
437
|
+
import { readdir as readdir4, readFile as readFile5 } from "node:fs/promises";
|
|
379
438
|
import { basename as basename2, join as join6, resolve as resolve5 } from "node:path";
|
|
380
439
|
|
|
381
440
|
// src/package-manager.ts
|
|
@@ -438,7 +497,7 @@ async function resolveScaffoldOptions(input, prompter) {
|
|
|
438
497
|
if (existsSync6(cwdManifest)) {
|
|
439
498
|
let pkgName = "this project";
|
|
440
499
|
try {
|
|
441
|
-
const parsed = JSON.parse(await
|
|
500
|
+
const parsed = JSON.parse(await readFile5(cwdManifest, "utf8"));
|
|
442
501
|
if (parsed.name) pkgName = `"${parsed.name}"`;
|
|
443
502
|
} catch {
|
|
444
503
|
}
|
|
@@ -464,7 +523,7 @@ async function resolveScaffoldOptions(input, prompter) {
|
|
|
464
523
|
}
|
|
465
524
|
let force = false;
|
|
466
525
|
const absRoot = resolve5(dir);
|
|
467
|
-
if (existsSync6(absRoot) && (await
|
|
526
|
+
if (existsSync6(absRoot) && (await readdir4(absRoot)).length > 0) {
|
|
468
527
|
if (!input.interactive) throw new Error(`target directory ${absRoot} is not empty`);
|
|
469
528
|
if (existsSync6(join6(absRoot, "package.json"))) {
|
|
470
529
|
const choice = await prompter.select(`Target directory "${dir}" is not empty and has a package.json.`, [
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
templateNames,
|
|
21
21
|
writeAgentSkills,
|
|
22
22
|
writeVscodeSetup
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-VZM5EYBG.js";
|
|
24
24
|
import "./chunk-TRTQSARU.js";
|
|
25
25
|
|
|
26
26
|
// src/skill-install.ts
|
|
@@ -54,9 +54,11 @@ async function runSkillInstall(args, opts = {}) {
|
|
|
54
54
|
prompter.note("Nothing selected \u2014 no files written.");
|
|
55
55
|
return 0;
|
|
56
56
|
}
|
|
57
|
-
const result = await writeAgentSkills(dir, agents);
|
|
57
|
+
const result = await writeAgentSkills(dir, agents, { force: args.force });
|
|
58
58
|
for (const note of result.skipped) prompter.note(note);
|
|
59
|
-
|
|
59
|
+
let message = "Nothing new to write.";
|
|
60
|
+
if (result.wrote.length > 0) message = `Installed agent skill files: ${result.wrote.join(", ")}`;
|
|
61
|
+
else if (result.stale) message = "Nothing written \u2014 re-run with --force to replace outdated files.";
|
|
60
62
|
if (prompter.outro) prompter.outro(message);
|
|
61
63
|
else prompter.note(message);
|
|
62
64
|
return 0;
|
package/dist/main.js
CHANGED
package/dist/skill-install.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-install.d.ts","sourceRoot":"","sources":["../src/skill-install.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,QAAQ,EAAiB,MAAM,WAAW,CAAC;AAEzD,MAAM,WAAW,gBAAgB;IAC/B,sCAAsC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,uFAAuF;AACvF,wBAAsB,eAAe,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,GAAE,mBAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"skill-install.d.ts","sourceRoot":"","sources":["../src/skill-install.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,QAAQ,EAAiB,MAAM,WAAW,CAAC;AAEzD,MAAM,WAAW,gBAAgB;IAC/B,sCAAsC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,uFAAuF;AACvF,wBAAsB,eAAe,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,GAAE,mBAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,CAwC7G"}
|
package/dist/skill-install.js
CHANGED
|
@@ -34,10 +34,14 @@ export async function runSkillInstall(args, opts = {}) {
|
|
|
34
34
|
prompter.note("Nothing selected — no files written.");
|
|
35
35
|
return 0;
|
|
36
36
|
}
|
|
37
|
-
const result = await writeAgentSkills(dir, agents);
|
|
37
|
+
const result = await writeAgentSkills(dir, agents, { force: args.force });
|
|
38
38
|
for (const note of result.skipped)
|
|
39
39
|
prompter.note(note);
|
|
40
|
-
|
|
40
|
+
let message = "Nothing new to write.";
|
|
41
|
+
if (result.wrote.length > 0)
|
|
42
|
+
message = `Installed agent skill files: ${result.wrote.join(", ")}`;
|
|
43
|
+
else if (result.stale)
|
|
44
|
+
message = "Nothing written — re-run with --force to replace outdated files.";
|
|
41
45
|
if (prompter.outro)
|
|
42
46
|
prompter.outro(message);
|
|
43
47
|
else
|