heymark 1.1.0 → 1.1.2
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/LICENSE +21 -0
- package/README.ko.md +170 -0
- package/README.md +170 -226
- package/package.json +57 -57
- package/scripts/lib/config.js +73 -73
- package/scripts/lib/parser.js +82 -82
- package/scripts/sync.js +239 -239
- package/scripts/tools/antigravity.js +41 -0
- package/scripts/tools/claude.js +42 -42
- package/scripts/tools/codex.js +41 -41
- package/scripts/tools/copilot.js +41 -41
- package/scripts/tools/cursor.js +41 -41
package/scripts/sync.js
CHANGED
|
@@ -1,239 +1,239 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
|
|
4
|
-
const fs = require("fs");
|
|
5
|
-
const path = require("path");
|
|
6
|
-
const { loadRules } = require("./lib/parser");
|
|
7
|
-
const { CONFIG_RELATIVE, loadConfig, writeConfig } = require("./lib/config");
|
|
8
|
-
const { getRulesDirFromRepo } = require("./lib/repo");
|
|
9
|
-
|
|
10
|
-
const SCRIPT_DIR = __dirname;
|
|
11
|
-
const PROJECT_ROOT = process.cwd();
|
|
12
|
-
|
|
13
|
-
function discoverTools() {
|
|
14
|
-
const toolsDir = path.join(SCRIPT_DIR, "tools");
|
|
15
|
-
const registry = {};
|
|
16
|
-
|
|
17
|
-
fs.readdirSync(toolsDir)
|
|
18
|
-
.filter((f) => f.endsWith(".js"))
|
|
19
|
-
.sort()
|
|
20
|
-
.forEach((file) => {
|
|
21
|
-
const key = path.basename(file, ".js");
|
|
22
|
-
registry[key] = require(path.join(toolsDir, file));
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
return registry;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function parseArgs(availableTools) {
|
|
29
|
-
const args = process.argv.slice(2);
|
|
30
|
-
const config = {
|
|
31
|
-
tools: Object.keys(availableTools),
|
|
32
|
-
clean: false,
|
|
33
|
-
preview: false,
|
|
34
|
-
help: false,
|
|
35
|
-
source: null,
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
for (let i = 0; i < args.length; i++) {
|
|
39
|
-
const arg = args[i];
|
|
40
|
-
|
|
41
|
-
if (arg === "--tools" || arg === "-t") {
|
|
42
|
-
const val = args[++i];
|
|
43
|
-
if (!val) {
|
|
44
|
-
console.error("[Error] --tools requires a comma-separated list.");
|
|
45
|
-
process.exit(1);
|
|
46
|
-
}
|
|
47
|
-
config.tools = val.split(",").map((t) => t.trim().toLowerCase());
|
|
48
|
-
} else if (arg === "--clean" || arg === "-c") {
|
|
49
|
-
config.clean = true;
|
|
50
|
-
} else if (arg === "--preview" || arg === "-p") {
|
|
51
|
-
config.preview = true;
|
|
52
|
-
} else if (arg === "--source" || arg === "-s") {
|
|
53
|
-
const val = args[++i];
|
|
54
|
-
if (!val) {
|
|
55
|
-
console.error("[Error] --source requires a GitHub repository URL.");
|
|
56
|
-
process.exit(1);
|
|
57
|
-
}
|
|
58
|
-
config.source = val.trim();
|
|
59
|
-
} else if (arg === "--help" || arg === "-h") {
|
|
60
|
-
config.help = true;
|
|
61
|
-
} else {
|
|
62
|
-
console.error(`[Error] Unknown option: ${arg}`);
|
|
63
|
-
console.error(" Use --help for usage information.");
|
|
64
|
-
process.exit(1);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const invalid = config.tools.filter((t) => !availableTools[t]);
|
|
69
|
-
if (invalid.length > 0) {
|
|
70
|
-
console.error(`[Error] Unknown tool(s): ${invalid.join(", ")}`);
|
|
71
|
-
console.error(` Available: ${Object.keys(availableTools).join(", ")}`);
|
|
72
|
-
process.exit(1);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return config;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function showHelp(tools) {
|
|
79
|
-
const toolLines = Object.entries(tools)
|
|
80
|
-
.map(([key, t]) => ` ${key.padEnd(10)} ${t.name.padEnd(16)} -> ${t.output}`)
|
|
81
|
-
.join("\n");
|
|
82
|
-
|
|
83
|
-
console.log(`
|
|
84
|
-
AI Coding Tool Convention Sync
|
|
85
|
-
|
|
86
|
-
Reads *.md from a GitHub repository (public or private) and generates
|
|
87
|
-
tool-specific configuration files for various AI coding assistants.
|
|
88
|
-
Same rules everywhere: A computer, B computer, same remote repo.
|
|
89
|
-
|
|
90
|
-
Usage:
|
|
91
|
-
heymark init <repo-url> Set rules source (creates ${CONFIG_RELATIVE})
|
|
92
|
-
heymark [options] Sync from configured or --source repo
|
|
93
|
-
|
|
94
|
-
Options:
|
|
95
|
-
--source, -s <url> GitHub repo URL for this run (overrides ${CONFIG_RELATIVE})
|
|
96
|
-
--tools, -t <list> Comma-separated tool names (default: all)
|
|
97
|
-
--clean, -c Remove all generated files
|
|
98
|
-
--preview, -p Preview what will be generated without writing
|
|
99
|
-
--help, -h Show this help message
|
|
100
|
-
|
|
101
|
-
Rules source (in order):
|
|
102
|
-
1. --source <repo-url>
|
|
103
|
-
2. ${CONFIG_RELATIVE} (set via 'heymark init <repo-url>')
|
|
104
|
-
Private repos: use SSH (git@github.com:org/repo.git) or HTTPS with token.
|
|
105
|
-
|
|
106
|
-
Available tools:
|
|
107
|
-
${toolLines}
|
|
108
|
-
|
|
109
|
-
Examples:
|
|
110
|
-
heymark init https://github.com/org/my-rules.git
|
|
111
|
-
heymark init https://github.com/org/my-rules.git --dir rules --branch main
|
|
112
|
-
heymark
|
|
113
|
-
heymark -s https://github.com/org/other-rules.git
|
|
114
|
-
heymark -t cursor,claude
|
|
115
|
-
heymark -c
|
|
116
|
-
heymark -p
|
|
117
|
-
`);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function runInit(initArgs) {
|
|
121
|
-
const args = initArgs.slice(0);
|
|
122
|
-
const repoUrl = args[0];
|
|
123
|
-
if (!repoUrl || repoUrl.startsWith("--")) {
|
|
124
|
-
console.error("[Error] init requires a GitHub repository URL.");
|
|
125
|
-
console.error(" Example: heymark init https://github.com/org/my-rules.git");
|
|
126
|
-
console.error(" Example: heymark init git@github.com:org/my-rules.git");
|
|
127
|
-
console.error(" Optional: --branch <branch> --dir <subdir> (e.g. --dir rules)");
|
|
128
|
-
process.exit(1);
|
|
129
|
-
}
|
|
130
|
-
let branch = "main";
|
|
131
|
-
let rulesSourceDir = "";
|
|
132
|
-
for (let i = 1; i < args.length; i++) {
|
|
133
|
-
if ((args[i] === "--branch" || args[i] === "-b") && args[i + 1]) {
|
|
134
|
-
branch = args[++i].trim();
|
|
135
|
-
} else if ((args[i] === "--dir" || args[i] === "-d") && args[i + 1]) {
|
|
136
|
-
rulesSourceDir = args[++i].trim();
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
const config = { rulesSource: repoUrl.trim(), branch, rulesSourceDir };
|
|
140
|
-
const configPath = writeConfig(PROJECT_ROOT, config);
|
|
141
|
-
console.log(
|
|
142
|
-
`[Init] Rules source saved to ${path.relative(PROJECT_ROOT, configPath) || configPath}`
|
|
143
|
-
);
|
|
144
|
-
console.log(` rulesSource: ${config.rulesSource}`);
|
|
145
|
-
if (branch !== "main") console.log(` branch: ${branch}`);
|
|
146
|
-
if (rulesSourceDir) console.log(` rulesSourceDir: ${rulesSourceDir}`);
|
|
147
|
-
console.log("");
|
|
148
|
-
console.log("Run 'heymark' to fetch rules from the repo and generate tool configs.");
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
function resolveRulesDir(config) {
|
|
152
|
-
const repoConfig = config.source
|
|
153
|
-
? { rulesSource: config.source, branch: "main", rulesSourceDir: "" }
|
|
154
|
-
: loadConfig(PROJECT_ROOT);
|
|
155
|
-
if (!repoConfig) return null;
|
|
156
|
-
return getRulesDirFromRepo(PROJECT_ROOT, repoConfig);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
function main() {
|
|
160
|
-
const args = process.argv.slice(2);
|
|
161
|
-
const subcommand = args[0];
|
|
162
|
-
if (subcommand === "init") {
|
|
163
|
-
runInit(args.slice(1));
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
const tools = discoverTools();
|
|
168
|
-
const config = parseArgs(tools);
|
|
169
|
-
|
|
170
|
-
if (config.help) {
|
|
171
|
-
showHelp(tools);
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const RULES_SRC_DIR = resolveRulesDir(config);
|
|
176
|
-
if (!RULES_SRC_DIR) {
|
|
177
|
-
console.error("[Error] Rules source not set.");
|
|
178
|
-
console.error(" Run: heymark init <github-repo-url>");
|
|
179
|
-
console.error(" Example: heymark init https://github.com/org/my-rules.git");
|
|
180
|
-
console.error(" Or use: heymark --source <repo-url>");
|
|
181
|
-
process.exit(1);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const rulesRelPath = path.relative(PROJECT_ROOT, RULES_SRC_DIR) || ".";
|
|
185
|
-
|
|
186
|
-
console.log("[Sync] Starting convention sync...");
|
|
187
|
-
console.log(` Source: ${rulesRelPath} (from remote repo)`);
|
|
188
|
-
console.log(` Target: ${PROJECT_ROOT}`);
|
|
189
|
-
console.log(` Tools: ${config.tools.join(", ")}`);
|
|
190
|
-
console.log("");
|
|
191
|
-
|
|
192
|
-
const rules = loadRules(RULES_SRC_DIR);
|
|
193
|
-
console.log(`[Load] ${rules.length} rule(s): ${rules.map((r) => r.name).join(", ")}`);
|
|
194
|
-
console.log("");
|
|
195
|
-
|
|
196
|
-
if (config.clean) {
|
|
197
|
-
console.log("[Clean] Removing generated files...");
|
|
198
|
-
const ruleNames = rules.map((r) => r.name);
|
|
199
|
-
for (const key of config.tools) {
|
|
200
|
-
const cleaned = tools[key].clean(ruleNames, PROJECT_ROOT);
|
|
201
|
-
cleaned.forEach((p) => console.log(` Deleted: ${p}`));
|
|
202
|
-
}
|
|
203
|
-
console.log("");
|
|
204
|
-
console.log(`[Done] Cleaned ${config.tools.length} tool(s) successfully.`);
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if (config.preview) {
|
|
209
|
-
console.log("[Preview] Would generate:");
|
|
210
|
-
for (const key of config.tools) {
|
|
211
|
-
const t = tools[key];
|
|
212
|
-
console.log(` ${t.name.padEnd(16)} -> ${t.output} (${rules.length} rules)`);
|
|
213
|
-
}
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// Clean existing files before generating (for fresh sync)
|
|
218
|
-
console.log("[Clean] Removing existing generated files...");
|
|
219
|
-
const ruleNames = rules.map((r) => r.name);
|
|
220
|
-
for (const key of config.tools) {
|
|
221
|
-
const cleaned = tools[key].clean(ruleNames, PROJECT_ROOT);
|
|
222
|
-
if (cleaned.length > 0) {
|
|
223
|
-
cleaned.forEach((p) => console.log(` Deleted: ${p}`));
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
console.log("");
|
|
227
|
-
|
|
228
|
-
console.log("[Generate]");
|
|
229
|
-
for (const key of config.tools) {
|
|
230
|
-
const t = tools[key];
|
|
231
|
-
const count = t.generate(rules, PROJECT_ROOT);
|
|
232
|
-
console.log(` ${t.name.padEnd(16)} -> ${t.output} (${count} rules)`);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
console.log("");
|
|
236
|
-
console.log(`[Done] ${config.tools.length} tool(s) synced successfully.`);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
main();
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const { loadRules } = require("./lib/parser");
|
|
7
|
+
const { CONFIG_RELATIVE, loadConfig, writeConfig } = require("./lib/config");
|
|
8
|
+
const { getRulesDirFromRepo } = require("./lib/repo");
|
|
9
|
+
|
|
10
|
+
const SCRIPT_DIR = __dirname;
|
|
11
|
+
const PROJECT_ROOT = process.cwd();
|
|
12
|
+
|
|
13
|
+
function discoverTools() {
|
|
14
|
+
const toolsDir = path.join(SCRIPT_DIR, "tools");
|
|
15
|
+
const registry = {};
|
|
16
|
+
|
|
17
|
+
fs.readdirSync(toolsDir)
|
|
18
|
+
.filter((f) => f.endsWith(".js"))
|
|
19
|
+
.sort()
|
|
20
|
+
.forEach((file) => {
|
|
21
|
+
const key = path.basename(file, ".js");
|
|
22
|
+
registry[key] = require(path.join(toolsDir, file));
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return registry;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function parseArgs(availableTools) {
|
|
29
|
+
const args = process.argv.slice(2);
|
|
30
|
+
const config = {
|
|
31
|
+
tools: Object.keys(availableTools),
|
|
32
|
+
clean: false,
|
|
33
|
+
preview: false,
|
|
34
|
+
help: false,
|
|
35
|
+
source: null,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
for (let i = 0; i < args.length; i++) {
|
|
39
|
+
const arg = args[i];
|
|
40
|
+
|
|
41
|
+
if (arg === "--tools" || arg === "-t") {
|
|
42
|
+
const val = args[++i];
|
|
43
|
+
if (!val) {
|
|
44
|
+
console.error("[Error] --tools requires a comma-separated list.");
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
config.tools = val.split(",").map((t) => t.trim().toLowerCase());
|
|
48
|
+
} else if (arg === "--clean" || arg === "-c") {
|
|
49
|
+
config.clean = true;
|
|
50
|
+
} else if (arg === "--preview" || arg === "-p") {
|
|
51
|
+
config.preview = true;
|
|
52
|
+
} else if (arg === "--source" || arg === "-s") {
|
|
53
|
+
const val = args[++i];
|
|
54
|
+
if (!val) {
|
|
55
|
+
console.error("[Error] --source requires a GitHub repository URL.");
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
config.source = val.trim();
|
|
59
|
+
} else if (arg === "--help" || arg === "-h") {
|
|
60
|
+
config.help = true;
|
|
61
|
+
} else {
|
|
62
|
+
console.error(`[Error] Unknown option: ${arg}`);
|
|
63
|
+
console.error(" Use --help for usage information.");
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const invalid = config.tools.filter((t) => !availableTools[t]);
|
|
69
|
+
if (invalid.length > 0) {
|
|
70
|
+
console.error(`[Error] Unknown tool(s): ${invalid.join(", ")}`);
|
|
71
|
+
console.error(` Available: ${Object.keys(availableTools).join(", ")}`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return config;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function showHelp(tools) {
|
|
79
|
+
const toolLines = Object.entries(tools)
|
|
80
|
+
.map(([key, t]) => ` ${key.padEnd(10)} ${t.name.padEnd(16)} -> ${t.output}`)
|
|
81
|
+
.join("\n");
|
|
82
|
+
|
|
83
|
+
console.log(`
|
|
84
|
+
AI Coding Tool Convention Sync
|
|
85
|
+
|
|
86
|
+
Reads *.md from a GitHub repository (public or private) and generates
|
|
87
|
+
tool-specific configuration files for various AI coding assistants.
|
|
88
|
+
Same rules everywhere: A computer, B computer, same remote repo.
|
|
89
|
+
|
|
90
|
+
Usage:
|
|
91
|
+
heymark init <repo-url> Set rules source (creates ${CONFIG_RELATIVE})
|
|
92
|
+
heymark [options] Sync from configured or --source repo
|
|
93
|
+
|
|
94
|
+
Options:
|
|
95
|
+
--source, -s <url> GitHub repo URL for this run (overrides ${CONFIG_RELATIVE})
|
|
96
|
+
--tools, -t <list> Comma-separated tool names (default: all)
|
|
97
|
+
--clean, -c Remove all generated files
|
|
98
|
+
--preview, -p Preview what will be generated without writing
|
|
99
|
+
--help, -h Show this help message
|
|
100
|
+
|
|
101
|
+
Rules source (in order):
|
|
102
|
+
1. --source <repo-url>
|
|
103
|
+
2. ${CONFIG_RELATIVE} (set via 'heymark init <repo-url>')
|
|
104
|
+
Private repos: use SSH (git@github.com:org/repo.git) or HTTPS with token.
|
|
105
|
+
|
|
106
|
+
Available tools:
|
|
107
|
+
${toolLines}
|
|
108
|
+
|
|
109
|
+
Examples:
|
|
110
|
+
heymark init https://github.com/org/my-rules.git
|
|
111
|
+
heymark init https://github.com/org/my-rules.git --dir rules --branch main
|
|
112
|
+
heymark
|
|
113
|
+
heymark -s https://github.com/org/other-rules.git
|
|
114
|
+
heymark -t cursor,claude
|
|
115
|
+
heymark -c
|
|
116
|
+
heymark -p
|
|
117
|
+
`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function runInit(initArgs) {
|
|
121
|
+
const args = initArgs.slice(0);
|
|
122
|
+
const repoUrl = args[0];
|
|
123
|
+
if (!repoUrl || repoUrl.startsWith("--")) {
|
|
124
|
+
console.error("[Error] init requires a GitHub repository URL.");
|
|
125
|
+
console.error(" Example: heymark init https://github.com/org/my-rules.git");
|
|
126
|
+
console.error(" Example: heymark init git@github.com:org/my-rules.git");
|
|
127
|
+
console.error(" Optional: --branch <branch> --dir <subdir> (e.g. --dir rules)");
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
let branch = "main";
|
|
131
|
+
let rulesSourceDir = "";
|
|
132
|
+
for (let i = 1; i < args.length; i++) {
|
|
133
|
+
if ((args[i] === "--branch" || args[i] === "-b") && args[i + 1]) {
|
|
134
|
+
branch = args[++i].trim();
|
|
135
|
+
} else if ((args[i] === "--dir" || args[i] === "-d") && args[i + 1]) {
|
|
136
|
+
rulesSourceDir = args[++i].trim();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const config = { rulesSource: repoUrl.trim(), branch, rulesSourceDir };
|
|
140
|
+
const configPath = writeConfig(PROJECT_ROOT, config);
|
|
141
|
+
console.log(
|
|
142
|
+
`[Init] Rules source saved to ${path.relative(PROJECT_ROOT, configPath) || configPath}`
|
|
143
|
+
);
|
|
144
|
+
console.log(` rulesSource: ${config.rulesSource}`);
|
|
145
|
+
if (branch !== "main") console.log(` branch: ${branch}`);
|
|
146
|
+
if (rulesSourceDir) console.log(` rulesSourceDir: ${rulesSourceDir}`);
|
|
147
|
+
console.log("");
|
|
148
|
+
console.log("Run 'heymark' to fetch rules from the repo and generate tool configs.");
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function resolveRulesDir(config) {
|
|
152
|
+
const repoConfig = config.source
|
|
153
|
+
? { rulesSource: config.source, branch: "main", rulesSourceDir: "" }
|
|
154
|
+
: loadConfig(PROJECT_ROOT);
|
|
155
|
+
if (!repoConfig) return null;
|
|
156
|
+
return getRulesDirFromRepo(PROJECT_ROOT, repoConfig);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function main() {
|
|
160
|
+
const args = process.argv.slice(2);
|
|
161
|
+
const subcommand = args[0];
|
|
162
|
+
if (subcommand === "init") {
|
|
163
|
+
runInit(args.slice(1));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const tools = discoverTools();
|
|
168
|
+
const config = parseArgs(tools);
|
|
169
|
+
|
|
170
|
+
if (config.help) {
|
|
171
|
+
showHelp(tools);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const RULES_SRC_DIR = resolveRulesDir(config);
|
|
176
|
+
if (!RULES_SRC_DIR) {
|
|
177
|
+
console.error("[Error] Rules source not set.");
|
|
178
|
+
console.error(" Run: heymark init <github-repo-url>");
|
|
179
|
+
console.error(" Example: heymark init https://github.com/org/my-rules.git");
|
|
180
|
+
console.error(" Or use: heymark --source <repo-url>");
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const rulesRelPath = path.relative(PROJECT_ROOT, RULES_SRC_DIR) || ".";
|
|
185
|
+
|
|
186
|
+
console.log("[Sync] Starting convention sync...");
|
|
187
|
+
console.log(` Source: ${rulesRelPath} (from remote repo)`);
|
|
188
|
+
console.log(` Target: ${PROJECT_ROOT}`);
|
|
189
|
+
console.log(` Tools: ${config.tools.join(", ")}`);
|
|
190
|
+
console.log("");
|
|
191
|
+
|
|
192
|
+
const rules = loadRules(RULES_SRC_DIR);
|
|
193
|
+
console.log(`[Load] ${rules.length} rule(s): ${rules.map((r) => r.name).join(", ")}`);
|
|
194
|
+
console.log("");
|
|
195
|
+
|
|
196
|
+
if (config.clean) {
|
|
197
|
+
console.log("[Clean] Removing generated files...");
|
|
198
|
+
const ruleNames = rules.map((r) => r.name);
|
|
199
|
+
for (const key of config.tools) {
|
|
200
|
+
const cleaned = tools[key].clean(ruleNames, PROJECT_ROOT);
|
|
201
|
+
cleaned.forEach((p) => console.log(` Deleted: ${p}`));
|
|
202
|
+
}
|
|
203
|
+
console.log("");
|
|
204
|
+
console.log(`[Done] Cleaned ${config.tools.length} tool(s) successfully.`);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (config.preview) {
|
|
209
|
+
console.log("[Preview] Would generate:");
|
|
210
|
+
for (const key of config.tools) {
|
|
211
|
+
const t = tools[key];
|
|
212
|
+
console.log(` ${t.name.padEnd(16)} -> ${t.output} (${rules.length} rules)`);
|
|
213
|
+
}
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Clean existing files before generating (for fresh sync)
|
|
218
|
+
console.log("[Clean] Removing existing generated files...");
|
|
219
|
+
const ruleNames = rules.map((r) => r.name);
|
|
220
|
+
for (const key of config.tools) {
|
|
221
|
+
const cleaned = tools[key].clean(ruleNames, PROJECT_ROOT);
|
|
222
|
+
if (cleaned.length > 0) {
|
|
223
|
+
cleaned.forEach((p) => console.log(` Deleted: ${p}`));
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
console.log("");
|
|
227
|
+
|
|
228
|
+
console.log("[Generate]");
|
|
229
|
+
for (const key of config.tools) {
|
|
230
|
+
const t = tools[key];
|
|
231
|
+
const count = t.generate(rules, PROJECT_ROOT);
|
|
232
|
+
console.log(` ${t.name.padEnd(16)} -> ${t.output} (${count} rules)`);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
console.log("");
|
|
236
|
+
console.log(`[Done] ${config.tools.length} tool(s) synced successfully.`);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
main();
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
name: "Antigravity",
|
|
8
|
+
output: ".agent/skills/*/SKILL.md",
|
|
9
|
+
|
|
10
|
+
generate(rules, projectRoot) {
|
|
11
|
+
for (const rule of rules) {
|
|
12
|
+
const skillDir = path.join(projectRoot, ".agent", "skills", rule.name);
|
|
13
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
14
|
+
|
|
15
|
+
const lines = [
|
|
16
|
+
"---",
|
|
17
|
+
`name: ${rule.name}`,
|
|
18
|
+
`description: "${rule.description}"`,
|
|
19
|
+
"---",
|
|
20
|
+
];
|
|
21
|
+
const content = lines.join("\n") + "\n\n" + rule.body + "\n";
|
|
22
|
+
fs.writeFileSync(path.join(skillDir, "SKILL.md"), content);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return rules.length;
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
clean(ruleNames, projectRoot) {
|
|
29
|
+
const cleaned = [];
|
|
30
|
+
|
|
31
|
+
for (const name of ruleNames) {
|
|
32
|
+
const skillDir = path.join(projectRoot, ".agent", "skills", name);
|
|
33
|
+
if (fs.existsSync(skillDir)) {
|
|
34
|
+
fs.rmSync(skillDir, { recursive: true });
|
|
35
|
+
cleaned.push(path.join(".agent", "skills", name));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return cleaned;
|
|
40
|
+
},
|
|
41
|
+
};
|
package/scripts/tools/claude.js
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const fs = require("fs");
|
|
4
|
-
const path = require("path");
|
|
5
|
-
|
|
6
|
-
module.exports = {
|
|
7
|
-
name: "Claude Code",
|
|
8
|
-
output: ".claude/skills/*/SKILL.md",
|
|
9
|
-
|
|
10
|
-
generate(rules, projectRoot) {
|
|
11
|
-
for (const rule of rules) {
|
|
12
|
-
const skillDir = path.join(projectRoot, ".claude", "skills", rule.name);
|
|
13
|
-
fs.mkdirSync(skillDir, { recursive: true });
|
|
14
|
-
|
|
15
|
-
const lines = [
|
|
16
|
-
"---",
|
|
17
|
-
`name: ${rule.name}`,
|
|
18
|
-
`description: "${rule.description}"`,
|
|
19
|
-
"---",
|
|
20
|
-
];
|
|
21
|
-
|
|
22
|
-
const content = lines.join("\n") + "\n\n" + rule.body + "\n";
|
|
23
|
-
fs.writeFileSync(path.join(skillDir, "SKILL.md"), content);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return rules.length;
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
clean(ruleNames, projectRoot) {
|
|
30
|
-
const cleaned = [];
|
|
31
|
-
|
|
32
|
-
for (const name of ruleNames) {
|
|
33
|
-
const skillDir = path.join(projectRoot, ".claude", "skills", name);
|
|
34
|
-
if (fs.existsSync(skillDir)) {
|
|
35
|
-
fs.rmSync(skillDir, { recursive: true });
|
|
36
|
-
cleaned.push(path.join(".claude", "skills", name));
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return cleaned;
|
|
41
|
-
},
|
|
42
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
name: "Claude Code",
|
|
8
|
+
output: ".claude/skills/*/SKILL.md",
|
|
9
|
+
|
|
10
|
+
generate(rules, projectRoot) {
|
|
11
|
+
for (const rule of rules) {
|
|
12
|
+
const skillDir = path.join(projectRoot, ".claude", "skills", rule.name);
|
|
13
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
14
|
+
|
|
15
|
+
const lines = [
|
|
16
|
+
"---",
|
|
17
|
+
`name: ${rule.name}`,
|
|
18
|
+
`description: "${rule.description}"`,
|
|
19
|
+
"---",
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
const content = lines.join("\n") + "\n\n" + rule.body + "\n";
|
|
23
|
+
fs.writeFileSync(path.join(skillDir, "SKILL.md"), content);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return rules.length;
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
clean(ruleNames, projectRoot) {
|
|
30
|
+
const cleaned = [];
|
|
31
|
+
|
|
32
|
+
for (const name of ruleNames) {
|
|
33
|
+
const skillDir = path.join(projectRoot, ".claude", "skills", name);
|
|
34
|
+
if (fs.existsSync(skillDir)) {
|
|
35
|
+
fs.rmSync(skillDir, { recursive: true });
|
|
36
|
+
cleaned.push(path.join(".claude", "skills", name));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return cleaned;
|
|
41
|
+
},
|
|
42
|
+
};
|