rulesync 7.18.2 → 7.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-JP3BFD7L.js → chunk-J2ZF4SHC.js} +150 -13
- package/dist/cli/index.cjs +602 -362
- package/dist/cli/index.js +461 -350
- package/dist/index.cjs +135 -13
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/cli/index.cjs
CHANGED
|
@@ -26,9 +26,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
// src/cli/index.ts
|
|
27
27
|
var import_commander = require("commander");
|
|
28
28
|
|
|
29
|
-
// src/constants/announcements.ts
|
|
30
|
-
var ANNOUNCEMENT = "".trim();
|
|
31
|
-
|
|
32
29
|
// src/types/features.ts
|
|
33
30
|
var import_mini = require("zod/mini");
|
|
34
31
|
var ALL_FEATURES = [
|
|
@@ -48,6 +45,32 @@ var RulesyncFeaturesSchema = import_mini.z.union([
|
|
|
48
45
|
import_mini.z.record(import_mini.z.string(), import_mini.z.array(import_mini.z.enum(ALL_FEATURES_WITH_WILDCARD)))
|
|
49
46
|
]);
|
|
50
47
|
|
|
48
|
+
// src/types/json-output.ts
|
|
49
|
+
var ErrorCodes = {
|
|
50
|
+
CONFIG_NOT_FOUND: "CONFIG_NOT_FOUND",
|
|
51
|
+
RULESYNC_DIR_NOT_FOUND: "RULESYNC_DIR_NOT_FOUND",
|
|
52
|
+
INVALID_TARGET: "INVALID_TARGET",
|
|
53
|
+
FETCH_FAILED: "FETCH_FAILED",
|
|
54
|
+
WRITE_FAILED: "WRITE_FAILED",
|
|
55
|
+
VALIDATION_FAILED: "VALIDATION_FAILED",
|
|
56
|
+
GENERATION_FAILED: "GENERATION_FAILED",
|
|
57
|
+
IMPORT_FAILED: "IMPORT_FAILED",
|
|
58
|
+
INSTALL_FAILED: "INSTALL_FAILED",
|
|
59
|
+
UPDATE_FAILED: "UPDATE_FAILED",
|
|
60
|
+
GITIGNORE_FAILED: "GITIGNORE_FAILED",
|
|
61
|
+
INIT_FAILED: "INIT_FAILED",
|
|
62
|
+
MCP_FAILED: "MCP_FAILED",
|
|
63
|
+
UNKNOWN_ERROR: "UNKNOWN_ERROR"
|
|
64
|
+
};
|
|
65
|
+
var CLIError = class extends Error {
|
|
66
|
+
constructor(message, code = ErrorCodes.UNKNOWN_ERROR, exitCode = 1) {
|
|
67
|
+
super(message);
|
|
68
|
+
this.code = code;
|
|
69
|
+
this.exitCode = exitCode;
|
|
70
|
+
this.name = "CLIError";
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
51
74
|
// src/utils/error.ts
|
|
52
75
|
var import_zod = require("zod");
|
|
53
76
|
function isZodErrorLike(error) {
|
|
@@ -75,16 +98,24 @@ function isEnvTest() {
|
|
|
75
98
|
|
|
76
99
|
// src/utils/logger.ts
|
|
77
100
|
var Logger = class {
|
|
101
|
+
/**
|
|
102
|
+
* Create a new Logger instance
|
|
103
|
+
*/
|
|
104
|
+
constructor(_version = "0.0.0") {
|
|
105
|
+
this._version = _version;
|
|
106
|
+
}
|
|
78
107
|
_verbose = false;
|
|
79
108
|
_silent = false;
|
|
109
|
+
_jsonMode = false;
|
|
110
|
+
_jsonOutputDone = false;
|
|
111
|
+
_commandName = "";
|
|
112
|
+
_jsonData = {};
|
|
80
113
|
console = import_consola.consola.withDefaults({
|
|
81
114
|
tag: "rulesync"
|
|
82
115
|
});
|
|
83
116
|
/**
|
|
84
117
|
* Configure logger with verbose and silent mode settings.
|
|
85
118
|
* Handles conflicting flags where silent takes precedence.
|
|
86
|
-
* @param verbose - Enable verbose logging
|
|
87
|
-
* @param silent - Enable silent mode (suppresses all output except errors)
|
|
88
119
|
*/
|
|
89
120
|
configure({ verbose, silent }) {
|
|
90
121
|
if (verbose && silent) {
|
|
@@ -100,34 +131,120 @@ var Logger = class {
|
|
|
100
131
|
get silent() {
|
|
101
132
|
return this._silent;
|
|
102
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Enable JSON output mode
|
|
136
|
+
*/
|
|
137
|
+
setJsonMode(enabled, command) {
|
|
138
|
+
this._jsonMode = enabled;
|
|
139
|
+
this._jsonOutputDone = false;
|
|
140
|
+
this._commandName = command;
|
|
141
|
+
if (enabled) {
|
|
142
|
+
this._jsonData = {};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Check if JSON mode is enabled
|
|
147
|
+
*/
|
|
148
|
+
get jsonMode() {
|
|
149
|
+
return this._jsonMode;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Capture data for JSON output
|
|
153
|
+
*/
|
|
154
|
+
captureData(key, value) {
|
|
155
|
+
if (this._jsonMode) {
|
|
156
|
+
this._jsonData[key] = value;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Get captured JSON data
|
|
161
|
+
*/
|
|
162
|
+
getJsonData() {
|
|
163
|
+
return { ...this._jsonData };
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Output final JSON result
|
|
167
|
+
*/
|
|
168
|
+
outputJson(success, error) {
|
|
169
|
+
if (!this._jsonMode || this._jsonOutputDone) return;
|
|
170
|
+
this._jsonOutputDone = true;
|
|
171
|
+
const output = {
|
|
172
|
+
success,
|
|
173
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
174
|
+
command: this._commandName,
|
|
175
|
+
version: this._version
|
|
176
|
+
};
|
|
177
|
+
if (success) {
|
|
178
|
+
output.data = this._jsonData;
|
|
179
|
+
} else if (error) {
|
|
180
|
+
output.error = {
|
|
181
|
+
code: error.code,
|
|
182
|
+
message: error.message
|
|
183
|
+
};
|
|
184
|
+
if (error.details) {
|
|
185
|
+
output.error.details = error.details;
|
|
186
|
+
}
|
|
187
|
+
if (error.stack) {
|
|
188
|
+
output.error.stack = error.stack;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
const jsonStr = JSON.stringify(output, null, 2);
|
|
192
|
+
if (success) {
|
|
193
|
+
console.log(jsonStr);
|
|
194
|
+
} else {
|
|
195
|
+
console.error(jsonStr);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
103
198
|
info(message, ...args) {
|
|
104
199
|
if (isEnvTest() || this._silent) return;
|
|
200
|
+
if (this._jsonMode) return;
|
|
105
201
|
this.console.info(message, ...args);
|
|
106
202
|
}
|
|
107
|
-
// Success (always shown unless silent)
|
|
108
203
|
success(message, ...args) {
|
|
109
204
|
if (isEnvTest() || this._silent) return;
|
|
205
|
+
if (this._jsonMode) return;
|
|
110
206
|
this.console.success(message, ...args);
|
|
111
207
|
}
|
|
112
|
-
// Warning (always shown unless silent)
|
|
113
208
|
warn(message, ...args) {
|
|
114
209
|
if (isEnvTest() || this._silent) return;
|
|
210
|
+
if (this._jsonMode) return;
|
|
115
211
|
this.console.warn(message, ...args);
|
|
116
212
|
}
|
|
117
|
-
|
|
118
|
-
error(message, ...args) {
|
|
213
|
+
error(message, code, ...args) {
|
|
119
214
|
if (isEnvTest()) return;
|
|
120
|
-
|
|
215
|
+
const errorMessage = message instanceof Error ? message.message : message;
|
|
216
|
+
if (this._jsonMode) {
|
|
217
|
+
const errorInfo = {
|
|
218
|
+
code: code || ErrorCodes.UNKNOWN_ERROR,
|
|
219
|
+
message: errorMessage
|
|
220
|
+
};
|
|
221
|
+
if (this._verbose && message instanceof Error && message.stack) {
|
|
222
|
+
errorInfo.stack = message.stack;
|
|
223
|
+
}
|
|
224
|
+
this.outputJson(false, errorInfo);
|
|
225
|
+
} else {
|
|
226
|
+
this.console.error(errorMessage, ...args);
|
|
227
|
+
}
|
|
121
228
|
}
|
|
122
|
-
// Debug level (shown only in verbose mode)
|
|
123
229
|
debug(message, ...args) {
|
|
124
230
|
if (isEnvTest() || this._silent) return;
|
|
231
|
+
if (this._jsonMode) return;
|
|
125
232
|
if (this._verbose) {
|
|
126
233
|
this.console.info(message, ...args);
|
|
127
234
|
}
|
|
128
235
|
}
|
|
236
|
+
/**
|
|
237
|
+
* Get the internal console instance (for testing only)
|
|
238
|
+
* @internal
|
|
239
|
+
*/
|
|
240
|
+
_getConsole() {
|
|
241
|
+
return this.console;
|
|
242
|
+
}
|
|
129
243
|
};
|
|
130
|
-
|
|
244
|
+
function createLogger(version) {
|
|
245
|
+
return new Logger(version);
|
|
246
|
+
}
|
|
247
|
+
var logger = new Logger("0.0.0");
|
|
131
248
|
|
|
132
249
|
// src/lib/fetch.ts
|
|
133
250
|
var import_node_path117 = require("path");
|
|
@@ -3008,7 +3125,9 @@ var CLAUDE_HOOK_EVENTS = [
|
|
|
3008
3125
|
"preCompact",
|
|
3009
3126
|
"permissionRequest",
|
|
3010
3127
|
"notification",
|
|
3011
|
-
"setup"
|
|
3128
|
+
"setup",
|
|
3129
|
+
"worktreeCreate",
|
|
3130
|
+
"worktreeRemove"
|
|
3012
3131
|
];
|
|
3013
3132
|
var OPENCODE_HOOK_EVENTS = [
|
|
3014
3133
|
"sessionStart",
|
|
@@ -3075,7 +3194,9 @@ var CANONICAL_TO_CLAUDE_EVENT_NAMES = {
|
|
|
3075
3194
|
preCompact: "PreCompact",
|
|
3076
3195
|
permissionRequest: "PermissionRequest",
|
|
3077
3196
|
notification: "Notification",
|
|
3078
|
-
setup: "Setup"
|
|
3197
|
+
setup: "Setup",
|
|
3198
|
+
worktreeCreate: "WorktreeCreate",
|
|
3199
|
+
worktreeRemove: "WorktreeRemove"
|
|
3079
3200
|
};
|
|
3080
3201
|
var CLAUDE_TO_CANONICAL_EVENT_NAMES = Object.fromEntries(
|
|
3081
3202
|
Object.entries(CANONICAL_TO_CLAUDE_EVENT_NAMES).map(([k, v]) => [v, k])
|
|
@@ -3201,7 +3322,13 @@ function canonicalToToolHooks({
|
|
|
3201
3322
|
else byMatcher.set(key, [def]);
|
|
3202
3323
|
}
|
|
3203
3324
|
const entries = [];
|
|
3325
|
+
const isNoMatcherEvent = converterConfig.noMatcherEvents?.has(eventName) ?? false;
|
|
3204
3326
|
for (const [matcherKey, defs] of byMatcher) {
|
|
3327
|
+
if (isNoMatcherEvent && matcherKey) {
|
|
3328
|
+
logger.warn(
|
|
3329
|
+
`matcher "${matcherKey}" on "${eventName}" hook will be ignored \u2014 this event does not support matchers`
|
|
3330
|
+
);
|
|
3331
|
+
}
|
|
3205
3332
|
const hooks = defs.map((def) => {
|
|
3206
3333
|
const commandText = def.command;
|
|
3207
3334
|
const trimmedCommand = typeof commandText === "string" ? commandText.trimStart() : void 0;
|
|
@@ -3214,7 +3341,8 @@ function canonicalToToolHooks({
|
|
|
3214
3341
|
...def.prompt !== void 0 && def.prompt !== null && { prompt: def.prompt }
|
|
3215
3342
|
};
|
|
3216
3343
|
});
|
|
3217
|
-
|
|
3344
|
+
const includeMatcher = matcherKey && !isNoMatcherEvent;
|
|
3345
|
+
entries.push(includeMatcher ? { matcher: matcherKey, hooks } : { hooks });
|
|
3218
3346
|
}
|
|
3219
3347
|
result[toolEventName] = entries;
|
|
3220
3348
|
}
|
|
@@ -3352,12 +3480,14 @@ var ToolHooks = class extends ToolFile {
|
|
|
3352
3480
|
};
|
|
3353
3481
|
|
|
3354
3482
|
// src/features/hooks/claudecode-hooks.ts
|
|
3483
|
+
var CLAUDE_NO_MATCHER_EVENTS = /* @__PURE__ */ new Set(["worktreeCreate", "worktreeRemove"]);
|
|
3355
3484
|
var CLAUDE_CONVERTER_CONFIG = {
|
|
3356
3485
|
supportedEvents: CLAUDE_HOOK_EVENTS,
|
|
3357
3486
|
canonicalToToolEventNames: CANONICAL_TO_CLAUDE_EVENT_NAMES,
|
|
3358
3487
|
toolToCanonicalEventNames: CLAUDE_TO_CANONICAL_EVENT_NAMES,
|
|
3359
3488
|
projectDirVar: "$CLAUDE_PROJECT_DIR",
|
|
3360
|
-
prefixDotRelativeCommandsOnly: true
|
|
3489
|
+
prefixDotRelativeCommandsOnly: true,
|
|
3490
|
+
noMatcherEvents: CLAUDE_NO_MATCHER_EVENTS
|
|
3361
3491
|
};
|
|
3362
3492
|
var ClaudecodeHooks = class _ClaudecodeHooks extends ToolHooks {
|
|
3363
3493
|
constructor(params) {
|
|
@@ -17144,30 +17274,36 @@ function formatFetchSummary(summary) {
|
|
|
17144
17274
|
}
|
|
17145
17275
|
|
|
17146
17276
|
// src/cli/commands/fetch.ts
|
|
17147
|
-
async function fetchCommand(options) {
|
|
17277
|
+
async function fetchCommand(logger2, options) {
|
|
17148
17278
|
const { source, ...fetchOptions } = options;
|
|
17149
|
-
|
|
17150
|
-
verbose: fetchOptions.verbose ?? false,
|
|
17151
|
-
silent: fetchOptions.silent ?? false
|
|
17152
|
-
});
|
|
17153
|
-
logger.debug(`Fetching files from ${source}...`);
|
|
17279
|
+
logger2.debug(`Fetching files from ${source}...`);
|
|
17154
17280
|
try {
|
|
17155
17281
|
const summary = await fetchFiles({
|
|
17156
17282
|
source,
|
|
17157
17283
|
options: fetchOptions
|
|
17158
17284
|
});
|
|
17285
|
+
if (logger2.jsonMode) {
|
|
17286
|
+
const createdFiles = summary.files.filter((f) => f.status === "created").map((f) => f.relativePath);
|
|
17287
|
+
const overwrittenFiles = summary.files.filter((f) => f.status === "overwritten").map((f) => f.relativePath);
|
|
17288
|
+
const skippedFiles = summary.files.filter((f) => f.status === "skipped").map((f) => f.relativePath);
|
|
17289
|
+
logger2.captureData("source", source);
|
|
17290
|
+
logger2.captureData("path", fetchOptions.path);
|
|
17291
|
+
logger2.captureData("created", createdFiles);
|
|
17292
|
+
logger2.captureData("overwritten", overwrittenFiles);
|
|
17293
|
+
logger2.captureData("skipped", skippedFiles);
|
|
17294
|
+
logger2.captureData("totalFetched", summary.created + summary.overwritten + summary.skipped);
|
|
17295
|
+
}
|
|
17159
17296
|
const output = formatFetchSummary(summary);
|
|
17160
|
-
|
|
17297
|
+
logger2.success(output);
|
|
17161
17298
|
if (summary.created + summary.overwritten === 0 && summary.skipped === 0) {
|
|
17162
|
-
|
|
17299
|
+
logger2.warn("No files were fetched.");
|
|
17163
17300
|
}
|
|
17164
17301
|
} catch (error) {
|
|
17165
17302
|
if (error instanceof GitHubClientError) {
|
|
17166
|
-
|
|
17167
|
-
|
|
17168
|
-
logger.error(formatError(error));
|
|
17303
|
+
const authHint = error.statusCode === 401 || error.statusCode === 403 ? " Tip: Set GITHUB_TOKEN or GH_TOKEN environment variable, or use `GITHUB_TOKEN=$(gh auth token) rulesync fetch ...`" : "";
|
|
17304
|
+
throw new CLIError(`GitHub API Error: ${error.message}.${authHint}`, ErrorCodes.FETCH_FAILED);
|
|
17169
17305
|
}
|
|
17170
|
-
|
|
17306
|
+
throw error;
|
|
17171
17307
|
}
|
|
17172
17308
|
}
|
|
17173
17309
|
|
|
@@ -17881,110 +18017,92 @@ function calculateTotalCount(result) {
|
|
|
17881
18017
|
}
|
|
17882
18018
|
|
|
17883
18019
|
// src/cli/commands/generate.ts
|
|
17884
|
-
function logFeatureResult(params) {
|
|
18020
|
+
function logFeatureResult(logger2, params) {
|
|
17885
18021
|
const { count, paths, featureName, isPreview, modePrefix } = params;
|
|
17886
18022
|
if (count > 0) {
|
|
17887
18023
|
if (isPreview) {
|
|
17888
|
-
|
|
18024
|
+
logger2.info(`${modePrefix} Would write ${count} ${featureName}`);
|
|
17889
18025
|
} else {
|
|
17890
|
-
|
|
18026
|
+
logger2.success(`Written ${count} ${featureName}`);
|
|
17891
18027
|
}
|
|
17892
18028
|
for (const p of paths) {
|
|
17893
|
-
|
|
18029
|
+
logger2.info(` ${p}`);
|
|
17894
18030
|
}
|
|
17895
18031
|
}
|
|
17896
18032
|
}
|
|
17897
|
-
async function generateCommand(options) {
|
|
18033
|
+
async function generateCommand(logger2, options) {
|
|
17898
18034
|
const config = await ConfigResolver.resolve(options);
|
|
17899
|
-
logger.configure({
|
|
17900
|
-
verbose: config.getVerbose(),
|
|
17901
|
-
silent: config.getSilent()
|
|
17902
|
-
});
|
|
17903
18035
|
const check = config.getCheck();
|
|
17904
18036
|
const isPreview = config.isPreviewMode();
|
|
17905
18037
|
const modePrefix = isPreview ? "[DRY RUN]" : "";
|
|
17906
|
-
|
|
18038
|
+
logger2.debug("Generating files...");
|
|
17907
18039
|
if (!await checkRulesyncDirExists({ baseDir: process.cwd() })) {
|
|
17908
|
-
|
|
17909
|
-
|
|
18040
|
+
throw new CLIError(
|
|
18041
|
+
".rulesync directory not found. Run 'rulesync init' first.",
|
|
18042
|
+
ErrorCodes.RULESYNC_DIR_NOT_FOUND
|
|
18043
|
+
);
|
|
17910
18044
|
}
|
|
17911
|
-
|
|
18045
|
+
logger2.debug(`Base directories: ${config.getBaseDirs().join(", ")}`);
|
|
17912
18046
|
const features = config.getFeatures();
|
|
17913
18047
|
if (features.includes("ignore")) {
|
|
17914
|
-
|
|
18048
|
+
logger2.debug("Generating ignore files...");
|
|
17915
18049
|
}
|
|
17916
18050
|
if (features.includes("mcp")) {
|
|
17917
|
-
|
|
18051
|
+
logger2.debug("Generating MCP files...");
|
|
17918
18052
|
}
|
|
17919
18053
|
if (features.includes("commands")) {
|
|
17920
|
-
|
|
18054
|
+
logger2.debug("Generating command files...");
|
|
17921
18055
|
}
|
|
17922
18056
|
if (features.includes("subagents")) {
|
|
17923
|
-
|
|
18057
|
+
logger2.debug("Generating subagent files...");
|
|
17924
18058
|
}
|
|
17925
18059
|
if (features.includes("skills")) {
|
|
17926
|
-
|
|
18060
|
+
logger2.debug("Generating skill files...");
|
|
17927
18061
|
}
|
|
17928
18062
|
if (features.includes("hooks")) {
|
|
17929
|
-
|
|
18063
|
+
logger2.debug("Generating hooks...");
|
|
17930
18064
|
}
|
|
17931
18065
|
if (features.includes("rules")) {
|
|
17932
|
-
|
|
18066
|
+
logger2.debug("Generating rule files...");
|
|
17933
18067
|
}
|
|
17934
18068
|
const result = await generate({ config });
|
|
17935
|
-
logFeatureResult({
|
|
17936
|
-
count: result.ignoreCount,
|
|
17937
|
-
paths: result.ignorePaths,
|
|
17938
|
-
featureName: "ignore file(s)",
|
|
17939
|
-
isPreview,
|
|
17940
|
-
modePrefix
|
|
17941
|
-
});
|
|
17942
|
-
logFeatureResult({
|
|
17943
|
-
count: result.mcpCount,
|
|
17944
|
-
paths: result.mcpPaths,
|
|
17945
|
-
featureName: "MCP configuration(s)",
|
|
17946
|
-
isPreview,
|
|
17947
|
-
modePrefix
|
|
17948
|
-
});
|
|
17949
|
-
logFeatureResult({
|
|
17950
|
-
count: result.commandsCount,
|
|
17951
|
-
paths: result.commandsPaths,
|
|
17952
|
-
featureName: "command(s)",
|
|
17953
|
-
isPreview,
|
|
17954
|
-
modePrefix
|
|
17955
|
-
});
|
|
17956
|
-
logFeatureResult({
|
|
17957
|
-
count: result.subagentsCount,
|
|
17958
|
-
paths: result.subagentsPaths,
|
|
17959
|
-
featureName: "subagent(s)",
|
|
17960
|
-
isPreview,
|
|
17961
|
-
modePrefix
|
|
17962
|
-
});
|
|
17963
|
-
logFeatureResult({
|
|
17964
|
-
count: result.skillsCount,
|
|
17965
|
-
paths: result.skillsPaths,
|
|
17966
|
-
featureName: "skill(s)",
|
|
17967
|
-
isPreview,
|
|
17968
|
-
modePrefix
|
|
17969
|
-
});
|
|
17970
|
-
logFeatureResult({
|
|
17971
|
-
count: result.hooksCount,
|
|
17972
|
-
paths: result.hooksPaths,
|
|
17973
|
-
featureName: "hooks file(s)",
|
|
17974
|
-
isPreview,
|
|
17975
|
-
modePrefix
|
|
17976
|
-
});
|
|
17977
|
-
logFeatureResult({
|
|
17978
|
-
count: result.rulesCount,
|
|
17979
|
-
paths: result.rulesPaths,
|
|
17980
|
-
featureName: "rule(s)",
|
|
17981
|
-
isPreview,
|
|
17982
|
-
modePrefix
|
|
17983
|
-
});
|
|
17984
18069
|
const totalGenerated = calculateTotalCount(result);
|
|
18070
|
+
const featureResults = {
|
|
18071
|
+
ignore: { count: result.ignoreCount, paths: result.ignorePaths },
|
|
18072
|
+
mcp: { count: result.mcpCount, paths: result.mcpPaths },
|
|
18073
|
+
commands: { count: result.commandsCount, paths: result.commandsPaths },
|
|
18074
|
+
subagents: { count: result.subagentsCount, paths: result.subagentsPaths },
|
|
18075
|
+
skills: { count: result.skillsCount, paths: result.skillsPaths },
|
|
18076
|
+
hooks: { count: result.hooksCount, paths: result.hooksPaths },
|
|
18077
|
+
rules: { count: result.rulesCount, paths: result.rulesPaths }
|
|
18078
|
+
};
|
|
18079
|
+
const featureLabels = {
|
|
18080
|
+
rules: (count) => `${count === 1 ? "rule" : "rules"}`,
|
|
18081
|
+
ignore: (count) => `${count === 1 ? "ignore file" : "ignore files"}`,
|
|
18082
|
+
mcp: (count) => `${count === 1 ? "MCP file" : "MCP files"}`,
|
|
18083
|
+
commands: (count) => `${count === 1 ? "command" : "commands"}`,
|
|
18084
|
+
subagents: (count) => `${count === 1 ? "subagent" : "subagents"}`,
|
|
18085
|
+
skills: (count) => `${count === 1 ? "skill" : "skills"}`,
|
|
18086
|
+
hooks: (count) => `${count === 1 ? "hooks file" : "hooks files"}`
|
|
18087
|
+
};
|
|
18088
|
+
for (const [feature, data] of Object.entries(featureResults)) {
|
|
18089
|
+
logFeatureResult(logger2, {
|
|
18090
|
+
count: data.count,
|
|
18091
|
+
paths: data.paths,
|
|
18092
|
+
featureName: featureLabels[feature]?.(data.count) ?? feature,
|
|
18093
|
+
isPreview,
|
|
18094
|
+
modePrefix
|
|
18095
|
+
});
|
|
18096
|
+
}
|
|
18097
|
+
if (logger2.jsonMode) {
|
|
18098
|
+
logger2.captureData("features", featureResults);
|
|
18099
|
+
logger2.captureData("totalFiles", totalGenerated);
|
|
18100
|
+
logger2.captureData("hasDiff", result.hasDiff);
|
|
18101
|
+
logger2.captureData("skills", result.skills ?? []);
|
|
18102
|
+
}
|
|
17985
18103
|
if (totalGenerated === 0) {
|
|
17986
18104
|
const enabledFeatures = features.join(", ");
|
|
17987
|
-
|
|
18105
|
+
logger2.info(`\u2713 All files are up to date (${enabledFeatures})`);
|
|
17988
18106
|
return;
|
|
17989
18107
|
}
|
|
17990
18108
|
const parts = [];
|
|
@@ -17996,129 +18114,209 @@ async function generateCommand(options) {
|
|
|
17996
18114
|
if (result.skillsCount > 0) parts.push(`${result.skillsCount} skills`);
|
|
17997
18115
|
if (result.hooksCount > 0) parts.push(`${result.hooksCount} hooks`);
|
|
17998
18116
|
if (isPreview) {
|
|
17999
|
-
|
|
18117
|
+
logger2.info(`${modePrefix} Would write ${totalGenerated} file(s) total (${parts.join(" + ")})`);
|
|
18000
18118
|
} else {
|
|
18001
|
-
|
|
18119
|
+
logger2.success(`\u{1F389} All done! Written ${totalGenerated} file(s) total (${parts.join(" + ")})`);
|
|
18002
18120
|
}
|
|
18003
18121
|
if (check) {
|
|
18004
18122
|
if (result.hasDiff) {
|
|
18005
|
-
|
|
18006
|
-
|
|
18123
|
+
throw new CLIError(
|
|
18124
|
+
"Files are not up to date. Run 'rulesync generate' to update.",
|
|
18125
|
+
ErrorCodes.GENERATION_FAILED
|
|
18126
|
+
);
|
|
18007
18127
|
} else {
|
|
18008
|
-
|
|
18128
|
+
logger2.success("\u2713 All files are up to date.");
|
|
18009
18129
|
}
|
|
18010
18130
|
}
|
|
18011
18131
|
}
|
|
18012
18132
|
|
|
18013
18133
|
// src/cli/commands/gitignore.ts
|
|
18014
18134
|
var import_node_path121 = require("path");
|
|
18015
|
-
|
|
18016
|
-
|
|
18017
|
-
var
|
|
18018
|
-
//
|
|
18019
|
-
`${RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH}
|
|
18135
|
+
|
|
18136
|
+
// src/cli/commands/gitignore-entries.ts
|
|
18137
|
+
var GITIGNORE_ENTRY_REGISTRY = [
|
|
18138
|
+
// Common / general
|
|
18139
|
+
{ target: "common", feature: "general", entry: `${RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH}/` },
|
|
18140
|
+
{ target: "common", feature: "general", entry: ".rulesync/rules/*.local.md" },
|
|
18141
|
+
{ target: "common", feature: "general", entry: "rulesync.local.jsonc" },
|
|
18142
|
+
{ target: "common", feature: "general", entry: "!.rulesync/.aiignore" },
|
|
18020
18143
|
// AGENTS.md
|
|
18021
|
-
"**/AGENTS.md",
|
|
18022
|
-
"**/.agents/",
|
|
18023
|
-
// Augment
|
|
18024
|
-
"**/.
|
|
18025
|
-
"**/.augment
|
|
18026
|
-
"**/.
|
|
18144
|
+
{ target: "agentsmd", feature: "rules", entry: "**/AGENTS.md" },
|
|
18145
|
+
{ target: "agentsmd", feature: "rules", entry: "**/.agents/" },
|
|
18146
|
+
// Augment Code
|
|
18147
|
+
{ target: "augmentcode", feature: "rules", entry: "**/.augment/rules/" },
|
|
18148
|
+
{ target: "augmentcode", feature: "rules", entry: "**/.augment-guidelines" },
|
|
18149
|
+
{ target: "augmentcode", feature: "ignore", entry: "**/.augmentignore" },
|
|
18027
18150
|
// Claude Code
|
|
18028
|
-
"**/CLAUDE.md",
|
|
18029
|
-
"**/CLAUDE.local.md",
|
|
18030
|
-
"**/.claude/CLAUDE.md",
|
|
18031
|
-
"**/.claude/CLAUDE.local.md",
|
|
18032
|
-
"**/.claude/
|
|
18033
|
-
"**/.claude/
|
|
18034
|
-
"**/.claude/
|
|
18035
|
-
"**/.claude/
|
|
18036
|
-
"**/.
|
|
18037
|
-
"**/.claude/
|
|
18038
|
-
"**/.
|
|
18151
|
+
{ target: "claudecode", feature: "rules", entry: "**/CLAUDE.md" },
|
|
18152
|
+
{ target: "claudecode", feature: "rules", entry: "**/CLAUDE.local.md" },
|
|
18153
|
+
{ target: "claudecode", feature: "rules", entry: "**/.claude/CLAUDE.md" },
|
|
18154
|
+
{ target: "claudecode", feature: "rules", entry: "**/.claude/CLAUDE.local.md" },
|
|
18155
|
+
{ target: "claudecode", feature: "rules", entry: "**/.claude/rules/" },
|
|
18156
|
+
{ target: "claudecode", feature: "commands", entry: "**/.claude/commands/" },
|
|
18157
|
+
{ target: "claudecode", feature: "subagents", entry: "**/.claude/agents/" },
|
|
18158
|
+
{ target: "claudecode", feature: "skills", entry: "**/.claude/skills/" },
|
|
18159
|
+
{ target: "claudecode", feature: "mcp", entry: "**/.mcp.json" },
|
|
18160
|
+
{ target: "claudecode", feature: "general", entry: "**/.claude/memories/" },
|
|
18161
|
+
{ target: "claudecode", feature: "general", entry: "**/.claude/settings.local.json" },
|
|
18039
18162
|
// Cline
|
|
18040
|
-
"**/.clinerules/",
|
|
18041
|
-
"**/.clinerules/workflows/",
|
|
18042
|
-
"**/.clineignore",
|
|
18043
|
-
"**/.cline/mcp.json",
|
|
18044
|
-
// Codex
|
|
18045
|
-
"**/.codexignore",
|
|
18046
|
-
"**/.codex/
|
|
18047
|
-
"**/.codex/
|
|
18048
|
-
"**/.codex/
|
|
18049
|
-
"**/.codex/config.toml",
|
|
18163
|
+
{ target: "cline", feature: "rules", entry: "**/.clinerules/" },
|
|
18164
|
+
{ target: "cline", feature: "commands", entry: "**/.clinerules/workflows/" },
|
|
18165
|
+
{ target: "cline", feature: "ignore", entry: "**/.clineignore" },
|
|
18166
|
+
{ target: "cline", feature: "mcp", entry: "**/.cline/mcp.json" },
|
|
18167
|
+
// Codex CLI
|
|
18168
|
+
{ target: "codexcli", feature: "ignore", entry: "**/.codexignore" },
|
|
18169
|
+
{ target: "codexcli", feature: "skills", entry: "**/.codex/skills/" },
|
|
18170
|
+
{ target: "codexcli", feature: "subagents", entry: "**/.codex/agents/" },
|
|
18171
|
+
{ target: "codexcli", feature: "general", entry: "**/.codex/memories/" },
|
|
18172
|
+
{ target: "codexcli", feature: "general", entry: "**/.codex/config.toml" },
|
|
18050
18173
|
// Cursor
|
|
18051
|
-
"**/.cursor/",
|
|
18052
|
-
"**/.cursorignore",
|
|
18174
|
+
{ target: "cursor", feature: "rules", entry: "**/.cursor/" },
|
|
18175
|
+
{ target: "cursor", feature: "ignore", entry: "**/.cursorignore" },
|
|
18053
18176
|
// Factory Droid
|
|
18054
|
-
"**/.factory/rules/",
|
|
18055
|
-
"**/.factory/commands/",
|
|
18056
|
-
"**/.factory/droids/",
|
|
18057
|
-
"**/.factory/skills/",
|
|
18058
|
-
"**/.factory/mcp.json",
|
|
18059
|
-
"**/.factory/settings.json",
|
|
18060
|
-
// Gemini
|
|
18061
|
-
"**/GEMINI.md",
|
|
18062
|
-
"**/.gemini/
|
|
18063
|
-
"**/.gemini/
|
|
18064
|
-
"**/.gemini/
|
|
18065
|
-
"**/.
|
|
18066
|
-
"**/.
|
|
18177
|
+
{ target: "factorydroid", feature: "rules", entry: "**/.factory/rules/" },
|
|
18178
|
+
{ target: "factorydroid", feature: "commands", entry: "**/.factory/commands/" },
|
|
18179
|
+
{ target: "factorydroid", feature: "subagents", entry: "**/.factory/droids/" },
|
|
18180
|
+
{ target: "factorydroid", feature: "skills", entry: "**/.factory/skills/" },
|
|
18181
|
+
{ target: "factorydroid", feature: "mcp", entry: "**/.factory/mcp.json" },
|
|
18182
|
+
{ target: "factorydroid", feature: "general", entry: "**/.factory/settings.json" },
|
|
18183
|
+
// Gemini CLI
|
|
18184
|
+
{ target: "geminicli", feature: "rules", entry: "**/GEMINI.md" },
|
|
18185
|
+
{ target: "geminicli", feature: "commands", entry: "**/.gemini/commands/" },
|
|
18186
|
+
{ target: "geminicli", feature: "subagents", entry: "**/.gemini/subagents/" },
|
|
18187
|
+
{ target: "geminicli", feature: "skills", entry: "**/.gemini/skills/" },
|
|
18188
|
+
{ target: "geminicli", feature: "ignore", entry: "**/.geminiignore" },
|
|
18189
|
+
{ target: "geminicli", feature: "general", entry: "**/.gemini/memories/" },
|
|
18067
18190
|
// Goose
|
|
18068
|
-
"**/.goosehints",
|
|
18069
|
-
"**/.goose/",
|
|
18070
|
-
"**/.gooseignore",
|
|
18191
|
+
{ target: "goose", feature: "rules", entry: "**/.goosehints" },
|
|
18192
|
+
{ target: "goose", feature: "rules", entry: "**/.goose/" },
|
|
18193
|
+
{ target: "goose", feature: "ignore", entry: "**/.gooseignore" },
|
|
18071
18194
|
// GitHub Copilot
|
|
18072
|
-
"**/.github/copilot-instructions.md",
|
|
18073
|
-
"**/.github/instructions/",
|
|
18074
|
-
"**/.github/prompts/",
|
|
18075
|
-
"**/.github/agents/",
|
|
18076
|
-
"**/.github/skills/",
|
|
18077
|
-
"**/.github/hooks/",
|
|
18078
|
-
"**/.vscode/mcp.json",
|
|
18195
|
+
{ target: "copilot", feature: "rules", entry: "**/.github/copilot-instructions.md" },
|
|
18196
|
+
{ target: "copilot", feature: "rules", entry: "**/.github/instructions/" },
|
|
18197
|
+
{ target: "copilot", feature: "commands", entry: "**/.github/prompts/" },
|
|
18198
|
+
{ target: "copilot", feature: "subagents", entry: "**/.github/agents/" },
|
|
18199
|
+
{ target: "copilot", feature: "skills", entry: "**/.github/skills/" },
|
|
18200
|
+
{ target: "copilot", feature: "hooks", entry: "**/.github/hooks/" },
|
|
18201
|
+
{ target: "copilot", feature: "mcp", entry: "**/.vscode/mcp.json" },
|
|
18079
18202
|
// Junie
|
|
18080
|
-
"**/.junie/guidelines.md",
|
|
18081
|
-
"**/.junie/mcp.json",
|
|
18082
|
-
"**/.junie/skills/",
|
|
18083
|
-
"**/.junie/agents/",
|
|
18203
|
+
{ target: "junie", feature: "rules", entry: "**/.junie/guidelines.md" },
|
|
18204
|
+
{ target: "junie", feature: "mcp", entry: "**/.junie/mcp.json" },
|
|
18205
|
+
{ target: "junie", feature: "skills", entry: "**/.junie/skills/" },
|
|
18206
|
+
{ target: "junie", feature: "subagents", entry: "**/.junie/agents/" },
|
|
18084
18207
|
// Kilo Code
|
|
18085
|
-
"**/.kilocode/rules/",
|
|
18086
|
-
"**/.kilocode/skills/",
|
|
18087
|
-
"**/.kilocode/workflows/",
|
|
18088
|
-
"**/.kilocode/mcp.json",
|
|
18089
|
-
"**/.kilocodeignore",
|
|
18208
|
+
{ target: "kilo", feature: "rules", entry: "**/.kilocode/rules/" },
|
|
18209
|
+
{ target: "kilo", feature: "skills", entry: "**/.kilocode/skills/" },
|
|
18210
|
+
{ target: "kilo", feature: "commands", entry: "**/.kilocode/workflows/" },
|
|
18211
|
+
{ target: "kilo", feature: "mcp", entry: "**/.kilocode/mcp.json" },
|
|
18212
|
+
{ target: "kilo", feature: "ignore", entry: "**/.kilocodeignore" },
|
|
18090
18213
|
// Kiro
|
|
18091
|
-
"**/.kiro/steering/",
|
|
18092
|
-
"**/.kiro/prompts/",
|
|
18093
|
-
"**/.kiro/skills/",
|
|
18094
|
-
"**/.kiro/agents/",
|
|
18095
|
-
"**/.kiro/settings/mcp.json",
|
|
18096
|
-
"**/.aiignore",
|
|
18214
|
+
{ target: "kiro", feature: "rules", entry: "**/.kiro/steering/" },
|
|
18215
|
+
{ target: "kiro", feature: "commands", entry: "**/.kiro/prompts/" },
|
|
18216
|
+
{ target: "kiro", feature: "skills", entry: "**/.kiro/skills/" },
|
|
18217
|
+
{ target: "kiro", feature: "subagents", entry: "**/.kiro/agents/" },
|
|
18218
|
+
{ target: "kiro", feature: "mcp", entry: "**/.kiro/settings/mcp.json" },
|
|
18219
|
+
{ target: "kiro", feature: "ignore", entry: "**/.aiignore" },
|
|
18097
18220
|
// OpenCode
|
|
18098
|
-
"**/.opencode/
|
|
18099
|
-
"**/.opencode/
|
|
18100
|
-
"**/.opencode/
|
|
18101
|
-
"**/.opencode/
|
|
18102
|
-
"**/.opencode/
|
|
18103
|
-
// Qwen
|
|
18104
|
-
"**/QWEN.md",
|
|
18105
|
-
"**/.qwen/memories/",
|
|
18221
|
+
{ target: "opencode", feature: "commands", entry: "**/.opencode/command/" },
|
|
18222
|
+
{ target: "opencode", feature: "subagents", entry: "**/.opencode/agent/" },
|
|
18223
|
+
{ target: "opencode", feature: "skills", entry: "**/.opencode/skill/" },
|
|
18224
|
+
{ target: "opencode", feature: "mcp", entry: "**/.opencode/plugins/" },
|
|
18225
|
+
{ target: "opencode", feature: "general", entry: "**/.opencode/memories/" },
|
|
18226
|
+
// Qwen Code
|
|
18227
|
+
{ target: "qwencode", feature: "rules", entry: "**/QWEN.md" },
|
|
18228
|
+
{ target: "qwencode", feature: "general", entry: "**/.qwen/memories/" },
|
|
18106
18229
|
// Replit
|
|
18107
|
-
"**/replit.md",
|
|
18230
|
+
{ target: "replit", feature: "rules", entry: "**/replit.md" },
|
|
18108
18231
|
// Roo
|
|
18109
|
-
"**/.roo/rules/",
|
|
18110
|
-
"**/.roo/skills/",
|
|
18111
|
-
"**/.rooignore",
|
|
18112
|
-
"**/.roo/mcp.json",
|
|
18113
|
-
"**/.roo/subagents/",
|
|
18232
|
+
{ target: "roo", feature: "rules", entry: "**/.roo/rules/" },
|
|
18233
|
+
{ target: "roo", feature: "skills", entry: "**/.roo/skills/" },
|
|
18234
|
+
{ target: "roo", feature: "ignore", entry: "**/.rooignore" },
|
|
18235
|
+
{ target: "roo", feature: "mcp", entry: "**/.roo/mcp.json" },
|
|
18236
|
+
{ target: "roo", feature: "subagents", entry: "**/.roo/subagents/" },
|
|
18114
18237
|
// Warp
|
|
18115
|
-
"**/.warp/",
|
|
18116
|
-
"**/WARP.md"
|
|
18117
|
-
// Others
|
|
18118
|
-
".rulesync/rules/*.local.md",
|
|
18119
|
-
"rulesync.local.jsonc",
|
|
18120
|
-
"!.rulesync/.aiignore"
|
|
18238
|
+
{ target: "warp", feature: "rules", entry: "**/.warp/" },
|
|
18239
|
+
{ target: "warp", feature: "rules", entry: "**/WARP.md" }
|
|
18121
18240
|
];
|
|
18241
|
+
var ALL_GITIGNORE_ENTRIES = GITIGNORE_ENTRY_REGISTRY.map(
|
|
18242
|
+
(tag) => tag.entry
|
|
18243
|
+
);
|
|
18244
|
+
var isTargetSelected = (target, selectedTargets) => {
|
|
18245
|
+
if (target === "common") return true;
|
|
18246
|
+
if (!selectedTargets || selectedTargets.length === 0) return true;
|
|
18247
|
+
if (selectedTargets.includes("*")) return true;
|
|
18248
|
+
return selectedTargets.includes(target);
|
|
18249
|
+
};
|
|
18250
|
+
var isFeatureSelected = (feature, target, features) => {
|
|
18251
|
+
if (feature === "general") return true;
|
|
18252
|
+
if (!features) return true;
|
|
18253
|
+
if (Array.isArray(features)) {
|
|
18254
|
+
if (features.length === 0) return true;
|
|
18255
|
+
if (features.includes("*")) return true;
|
|
18256
|
+
return features.includes(feature);
|
|
18257
|
+
}
|
|
18258
|
+
if (target === "common") return true;
|
|
18259
|
+
const targetFeatures = features[target];
|
|
18260
|
+
if (!targetFeatures) return true;
|
|
18261
|
+
if (targetFeatures.includes("*")) return true;
|
|
18262
|
+
return targetFeatures.includes(feature);
|
|
18263
|
+
};
|
|
18264
|
+
var warnInvalidTargets = (targets) => {
|
|
18265
|
+
const validTargets = new Set(ALL_TOOL_TARGETS_WITH_WILDCARD);
|
|
18266
|
+
for (const target of targets) {
|
|
18267
|
+
if (!validTargets.has(target)) {
|
|
18268
|
+
logger.warn(
|
|
18269
|
+
`Unknown target '${target}'. Valid targets: ${ALL_TOOL_TARGETS_WITH_WILDCARD.join(", ")}`
|
|
18270
|
+
);
|
|
18271
|
+
}
|
|
18272
|
+
}
|
|
18273
|
+
};
|
|
18274
|
+
var warnInvalidFeatures = (features) => {
|
|
18275
|
+
const validFeatures = new Set(ALL_FEATURES_WITH_WILDCARD);
|
|
18276
|
+
if (Array.isArray(features)) {
|
|
18277
|
+
for (const feature of features) {
|
|
18278
|
+
if (!validFeatures.has(feature)) {
|
|
18279
|
+
logger.warn(
|
|
18280
|
+
`Unknown feature '${feature}'. Valid features: ${ALL_FEATURES_WITH_WILDCARD.join(", ")}`
|
|
18281
|
+
);
|
|
18282
|
+
}
|
|
18283
|
+
}
|
|
18284
|
+
} else {
|
|
18285
|
+
for (const targetFeatures of Object.values(features)) {
|
|
18286
|
+
if (!targetFeatures) continue;
|
|
18287
|
+
for (const feature of targetFeatures) {
|
|
18288
|
+
if (!validFeatures.has(feature)) {
|
|
18289
|
+
logger.warn(
|
|
18290
|
+
`Unknown feature '${feature}'. Valid features: ${ALL_FEATURES_WITH_WILDCARD.join(", ")}`
|
|
18291
|
+
);
|
|
18292
|
+
}
|
|
18293
|
+
}
|
|
18294
|
+
}
|
|
18295
|
+
}
|
|
18296
|
+
};
|
|
18297
|
+
var filterGitignoreEntries = (params) => {
|
|
18298
|
+
const { targets, features } = params ?? {};
|
|
18299
|
+
if (targets && targets.length > 0) {
|
|
18300
|
+
warnInvalidTargets(targets);
|
|
18301
|
+
}
|
|
18302
|
+
if (features) {
|
|
18303
|
+
warnInvalidFeatures(features);
|
|
18304
|
+
}
|
|
18305
|
+
const seen = /* @__PURE__ */ new Set();
|
|
18306
|
+
const result = [];
|
|
18307
|
+
for (const tag of GITIGNORE_ENTRY_REGISTRY) {
|
|
18308
|
+
if (!isTargetSelected(tag.target, targets)) continue;
|
|
18309
|
+
if (!isFeatureSelected(tag.feature, tag.target, features)) continue;
|
|
18310
|
+
if (seen.has(tag.entry)) continue;
|
|
18311
|
+
seen.add(tag.entry);
|
|
18312
|
+
result.push(tag.entry);
|
|
18313
|
+
}
|
|
18314
|
+
return result;
|
|
18315
|
+
};
|
|
18316
|
+
|
|
18317
|
+
// src/cli/commands/gitignore.ts
|
|
18318
|
+
var RULESYNC_HEADER = "# Generated by Rulesync";
|
|
18319
|
+
var LEGACY_RULESYNC_HEADER = "# Generated by rulesync - AI tool configuration files";
|
|
18122
18320
|
var isRulesyncHeader = (line) => {
|
|
18123
18321
|
const trimmed = line.trim();
|
|
18124
18322
|
return trimmed === RULESYNC_HEADER || trimmed === LEGACY_RULESYNC_HEADER;
|
|
@@ -18128,7 +18326,7 @@ var isRulesyncEntry = (line) => {
|
|
|
18128
18326
|
if (trimmed === "" || isRulesyncHeader(line)) {
|
|
18129
18327
|
return false;
|
|
18130
18328
|
}
|
|
18131
|
-
return
|
|
18329
|
+
return ALL_GITIGNORE_ENTRIES.includes(trimmed);
|
|
18132
18330
|
};
|
|
18133
18331
|
var removeExistingRulesyncEntries = (content) => {
|
|
18134
18332
|
const lines = content.split("\n");
|
|
@@ -18168,37 +18366,56 @@ var removeExistingRulesyncEntries = (content) => {
|
|
|
18168
18366
|
}
|
|
18169
18367
|
return result;
|
|
18170
18368
|
};
|
|
18171
|
-
var gitignoreCommand = async () => {
|
|
18369
|
+
var gitignoreCommand = async (logger2, options) => {
|
|
18172
18370
|
const gitignorePath = (0, import_node_path121.join)(process.cwd(), ".gitignore");
|
|
18173
18371
|
let gitignoreContent = "";
|
|
18174
18372
|
if (await fileExists(gitignorePath)) {
|
|
18175
18373
|
gitignoreContent = await readFileContent(gitignorePath);
|
|
18176
18374
|
}
|
|
18177
18375
|
const cleanedContent = removeExistingRulesyncEntries(gitignoreContent);
|
|
18178
|
-
const
|
|
18376
|
+
const filteredEntries = filterGitignoreEntries({
|
|
18377
|
+
targets: options?.targets,
|
|
18378
|
+
features: options?.features
|
|
18379
|
+
});
|
|
18380
|
+
const existingEntries = new Set(
|
|
18381
|
+
gitignoreContent.split("\n").map((line) => line.trim()).filter((line) => line !== "" && !isRulesyncHeader(line))
|
|
18382
|
+
);
|
|
18383
|
+
const alreadyExistedEntries = filteredEntries.filter((entry) => existingEntries.has(entry));
|
|
18384
|
+
const entriesToAdd = filteredEntries.filter((entry) => !existingEntries.has(entry));
|
|
18385
|
+
const rulesyncBlock = [RULESYNC_HEADER, ...filteredEntries].join("\n");
|
|
18179
18386
|
const newContent = cleanedContent.trim() ? `${cleanedContent.trimEnd()}
|
|
18180
18387
|
|
|
18181
18388
|
${rulesyncBlock}
|
|
18182
18389
|
` : `${rulesyncBlock}
|
|
18183
18390
|
`;
|
|
18184
18391
|
if (gitignoreContent === newContent) {
|
|
18185
|
-
|
|
18392
|
+
if (logger2.jsonMode) {
|
|
18393
|
+
logger2.captureData("entriesAdded", []);
|
|
18394
|
+
logger2.captureData("gitignorePath", gitignorePath);
|
|
18395
|
+
logger2.captureData("alreadyExisted", filteredEntries);
|
|
18396
|
+
}
|
|
18397
|
+
logger2.success(".gitignore is already up to date");
|
|
18186
18398
|
return;
|
|
18187
18399
|
}
|
|
18188
18400
|
await writeFileContent(gitignorePath, newContent);
|
|
18189
|
-
|
|
18190
|
-
|
|
18191
|
-
|
|
18401
|
+
if (logger2.jsonMode) {
|
|
18402
|
+
logger2.captureData("entriesAdded", entriesToAdd);
|
|
18403
|
+
logger2.captureData("gitignorePath", gitignorePath);
|
|
18404
|
+
logger2.captureData("alreadyExisted", alreadyExistedEntries);
|
|
18192
18405
|
}
|
|
18193
|
-
|
|
18194
|
-
|
|
18406
|
+
logger2.success("Updated .gitignore with rulesync entries:");
|
|
18407
|
+
for (const entry of filteredEntries) {
|
|
18408
|
+
logger2.info(` ${entry}`);
|
|
18409
|
+
}
|
|
18410
|
+
logger2.info("");
|
|
18411
|
+
logger2.info(
|
|
18195
18412
|
"\u{1F4A1} If you're using Google Antigravity, note that rules, workflows, and skills won't load if they're gitignored."
|
|
18196
18413
|
);
|
|
18197
|
-
|
|
18198
|
-
|
|
18199
|
-
|
|
18200
|
-
|
|
18201
|
-
|
|
18414
|
+
logger2.info(" You can add the following to .git/info/exclude instead:");
|
|
18415
|
+
logger2.info(" **/.agent/rules/");
|
|
18416
|
+
logger2.info(" **/.agent/workflows/");
|
|
18417
|
+
logger2.info(" **/.agent/skills/");
|
|
18418
|
+
logger2.info(" For more details: https://github.com/dyoshikawa/rulesync/issues/981");
|
|
18202
18419
|
};
|
|
18203
18420
|
|
|
18204
18421
|
// src/lib/import.ts
|
|
@@ -18421,29 +18638,36 @@ async function importHooksCore(params) {
|
|
|
18421
18638
|
}
|
|
18422
18639
|
|
|
18423
18640
|
// src/cli/commands/import.ts
|
|
18424
|
-
async function importCommand(options) {
|
|
18641
|
+
async function importCommand(logger2, options) {
|
|
18425
18642
|
if (!options.targets) {
|
|
18426
|
-
|
|
18427
|
-
process.exit(1);
|
|
18643
|
+
throw new CLIError("No tools found in --targets", ErrorCodes.IMPORT_FAILED);
|
|
18428
18644
|
}
|
|
18429
18645
|
if (options.targets.length > 1) {
|
|
18430
|
-
|
|
18431
|
-
process.exit(1);
|
|
18646
|
+
throw new CLIError("Only one tool can be imported at a time", ErrorCodes.IMPORT_FAILED);
|
|
18432
18647
|
}
|
|
18433
18648
|
const config = await ConfigResolver.resolve(options);
|
|
18434
|
-
logger.configure({
|
|
18435
|
-
verbose: config.getVerbose(),
|
|
18436
|
-
silent: config.getSilent()
|
|
18437
|
-
});
|
|
18438
18649
|
const tool = config.getTargets()[0];
|
|
18439
|
-
|
|
18650
|
+
logger2.debug(`Importing files from ${tool}...`);
|
|
18440
18651
|
const result = await importFromTool({ config, tool });
|
|
18441
18652
|
const totalImported = calculateTotalCount(result);
|
|
18442
18653
|
if (totalImported === 0) {
|
|
18443
18654
|
const enabledFeatures = config.getFeatures().join(", ");
|
|
18444
|
-
|
|
18655
|
+
logger2.warn(`No files imported for enabled features: ${enabledFeatures}`);
|
|
18445
18656
|
return;
|
|
18446
18657
|
}
|
|
18658
|
+
if (logger2.jsonMode) {
|
|
18659
|
+
logger2.captureData("tool", tool);
|
|
18660
|
+
logger2.captureData("features", {
|
|
18661
|
+
rules: { count: result.rulesCount },
|
|
18662
|
+
ignore: { count: result.ignoreCount },
|
|
18663
|
+
mcp: { count: result.mcpCount },
|
|
18664
|
+
commands: { count: result.commandsCount },
|
|
18665
|
+
subagents: { count: result.subagentsCount },
|
|
18666
|
+
skills: { count: result.skillsCount },
|
|
18667
|
+
hooks: { count: result.hooksCount }
|
|
18668
|
+
});
|
|
18669
|
+
logger2.captureData("totalFiles", totalImported);
|
|
18670
|
+
}
|
|
18447
18671
|
const parts = [];
|
|
18448
18672
|
if (result.rulesCount > 0) parts.push(`${result.rulesCount} rules`);
|
|
18449
18673
|
if (result.ignoreCount > 0) parts.push(`${result.ignoreCount} ignore files`);
|
|
@@ -18452,7 +18676,7 @@ async function importCommand(options) {
|
|
|
18452
18676
|
if (result.subagentsCount > 0) parts.push(`${result.subagentsCount} subagents`);
|
|
18453
18677
|
if (result.skillsCount > 0) parts.push(`${result.skillsCount} skills`);
|
|
18454
18678
|
if (result.hooksCount > 0) parts.push(`${result.hooksCount} hooks`);
|
|
18455
|
-
|
|
18679
|
+
logger2.success(`Imported ${totalImported} file(s) total (${parts.join(" + ")})`);
|
|
18456
18680
|
}
|
|
18457
18681
|
|
|
18458
18682
|
// src/lib/init.ts
|
|
@@ -18681,28 +18905,38 @@ async function writeIfNotExists(path4, content) {
|
|
|
18681
18905
|
}
|
|
18682
18906
|
|
|
18683
18907
|
// src/cli/commands/init.ts
|
|
18684
|
-
async function initCommand() {
|
|
18685
|
-
|
|
18908
|
+
async function initCommand(logger2) {
|
|
18909
|
+
logger2.debug("Initializing rulesync...");
|
|
18686
18910
|
await ensureDir(RULESYNC_RELATIVE_DIR_PATH);
|
|
18687
18911
|
const result = await init();
|
|
18912
|
+
const createdFiles = [];
|
|
18913
|
+
const skippedFiles = [];
|
|
18688
18914
|
for (const file of result.sampleFiles) {
|
|
18689
18915
|
if (file.created) {
|
|
18690
|
-
|
|
18916
|
+
createdFiles.push(file.path);
|
|
18917
|
+
logger2.success(`Created ${file.path}`);
|
|
18691
18918
|
} else {
|
|
18692
|
-
|
|
18919
|
+
skippedFiles.push(file.path);
|
|
18920
|
+
logger2.info(`Skipped ${file.path} (already exists)`);
|
|
18693
18921
|
}
|
|
18694
18922
|
}
|
|
18695
18923
|
if (result.configFile.created) {
|
|
18696
|
-
|
|
18924
|
+
createdFiles.push(result.configFile.path);
|
|
18925
|
+
logger2.success(`Created ${result.configFile.path}`);
|
|
18697
18926
|
} else {
|
|
18698
|
-
|
|
18927
|
+
skippedFiles.push(result.configFile.path);
|
|
18928
|
+
logger2.info(`Skipped ${result.configFile.path} (already exists)`);
|
|
18699
18929
|
}
|
|
18700
|
-
|
|
18701
|
-
|
|
18702
|
-
|
|
18930
|
+
if (logger2.jsonMode) {
|
|
18931
|
+
logger2.captureData("created", createdFiles);
|
|
18932
|
+
logger2.captureData("skipped", skippedFiles);
|
|
18933
|
+
}
|
|
18934
|
+
logger2.success("rulesync initialized successfully!");
|
|
18935
|
+
logger2.info("Next steps:");
|
|
18936
|
+
logger2.info(
|
|
18703
18937
|
`1. Edit ${RULESYNC_RELATIVE_DIR_PATH}/**/*.md, ${RULESYNC_RELATIVE_DIR_PATH}/skills/*/${SKILL_FILE_NAME}, ${RULESYNC_MCP_RELATIVE_FILE_PATH}, ${RULESYNC_HOOKS_RELATIVE_FILE_PATH} and ${RULESYNC_AIIGNORE_RELATIVE_FILE_PATH}`
|
|
18704
18938
|
);
|
|
18705
|
-
|
|
18939
|
+
logger2.info("2. Run 'rulesync generate' to create configuration files");
|
|
18706
18940
|
}
|
|
18707
18941
|
|
|
18708
18942
|
// src/lib/sources.ts
|
|
@@ -19428,11 +19662,7 @@ async function fetchSourceViaGit(params) {
|
|
|
19428
19662
|
}
|
|
19429
19663
|
|
|
19430
19664
|
// src/cli/commands/install.ts
|
|
19431
|
-
async function installCommand(options) {
|
|
19432
|
-
logger.configure({
|
|
19433
|
-
verbose: options.verbose ?? false,
|
|
19434
|
-
silent: options.silent ?? false
|
|
19435
|
-
});
|
|
19665
|
+
async function installCommand(logger2, options) {
|
|
19436
19666
|
const config = await ConfigResolver.resolve({
|
|
19437
19667
|
configPath: options.configPath,
|
|
19438
19668
|
verbose: options.verbose,
|
|
@@ -19440,10 +19670,10 @@ async function installCommand(options) {
|
|
|
19440
19670
|
});
|
|
19441
19671
|
const sources = config.getSources();
|
|
19442
19672
|
if (sources.length === 0) {
|
|
19443
|
-
|
|
19673
|
+
logger2.warn("No sources defined in configuration. Nothing to install.");
|
|
19444
19674
|
return;
|
|
19445
19675
|
}
|
|
19446
|
-
|
|
19676
|
+
logger2.debug(`Installing skills from ${sources.length} source(s)...`);
|
|
19447
19677
|
const result = await resolveAndFetchSources({
|
|
19448
19678
|
sources,
|
|
19449
19679
|
baseDir: process.cwd(),
|
|
@@ -19453,12 +19683,16 @@ async function installCommand(options) {
|
|
|
19453
19683
|
token: options.token
|
|
19454
19684
|
}
|
|
19455
19685
|
});
|
|
19686
|
+
if (logger2.jsonMode) {
|
|
19687
|
+
logger2.captureData("sourcesProcessed", result.sourcesProcessed);
|
|
19688
|
+
logger2.captureData("skillsFetched", result.fetchedSkillCount);
|
|
19689
|
+
}
|
|
19456
19690
|
if (result.fetchedSkillCount > 0) {
|
|
19457
|
-
|
|
19691
|
+
logger2.success(
|
|
19458
19692
|
`Installed ${result.fetchedSkillCount} skill(s) from ${result.sourcesProcessed} source(s).`
|
|
19459
19693
|
);
|
|
19460
19694
|
} else {
|
|
19461
|
-
|
|
19695
|
+
logger2.success(`All skills up to date (${result.sourcesProcessed} source(s) checked).`);
|
|
19462
19696
|
}
|
|
19463
19697
|
}
|
|
19464
19698
|
|
|
@@ -20873,7 +21107,7 @@ var rulesyncTool = {
|
|
|
20873
21107
|
};
|
|
20874
21108
|
|
|
20875
21109
|
// src/cli/commands/mcp.ts
|
|
20876
|
-
async function mcpCommand({ version }) {
|
|
21110
|
+
async function mcpCommand(logger2, { version }) {
|
|
20877
21111
|
const server = new import_fastmcp.FastMCP({
|
|
20878
21112
|
name: "Rulesync MCP Server",
|
|
20879
21113
|
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
@@ -20881,7 +21115,7 @@ async function mcpCommand({ version }) {
|
|
|
20881
21115
|
instructions: "This server handles Rulesync files including rules, commands, MCP, ignore files, subagents and skills for any AI agents. It should be used when you need those files."
|
|
20882
21116
|
});
|
|
20883
21117
|
server.addTool(rulesyncTool);
|
|
20884
|
-
|
|
21118
|
+
logger2.info("Rulesync MCP server started via stdio");
|
|
20885
21119
|
void server.start({
|
|
20886
21120
|
transportType: "stdio"
|
|
20887
21121
|
});
|
|
@@ -21197,158 +21431,185 @@ To upgrade, run:
|
|
|
21197
21431
|
}
|
|
21198
21432
|
|
|
21199
21433
|
// src/cli/commands/update.ts
|
|
21200
|
-
async function updateCommand(currentVersion, options) {
|
|
21201
|
-
const { check = false, force = false,
|
|
21202
|
-
logger.configure({ verbose, silent });
|
|
21434
|
+
async function updateCommand(logger2, currentVersion, options) {
|
|
21435
|
+
const { check = false, force = false, token } = options;
|
|
21203
21436
|
try {
|
|
21204
21437
|
const environment = detectExecutionEnvironment();
|
|
21205
|
-
|
|
21438
|
+
logger2.debug(`Detected environment: ${environment}`);
|
|
21206
21439
|
if (environment === "npm") {
|
|
21207
|
-
|
|
21440
|
+
logger2.info(getNpmUpgradeInstructions());
|
|
21208
21441
|
return;
|
|
21209
21442
|
}
|
|
21210
21443
|
if (environment === "homebrew") {
|
|
21211
|
-
|
|
21444
|
+
logger2.info(getHomebrewUpgradeInstructions());
|
|
21212
21445
|
return;
|
|
21213
21446
|
}
|
|
21214
21447
|
if (check) {
|
|
21215
|
-
|
|
21448
|
+
logger2.info("Checking for updates...");
|
|
21216
21449
|
const updateCheck = await checkForUpdate(currentVersion, token);
|
|
21450
|
+
if (logger2.jsonMode) {
|
|
21451
|
+
logger2.captureData("currentVersion", updateCheck.currentVersion);
|
|
21452
|
+
logger2.captureData("latestVersion", updateCheck.latestVersion);
|
|
21453
|
+
logger2.captureData("updateAvailable", updateCheck.hasUpdate);
|
|
21454
|
+
logger2.captureData(
|
|
21455
|
+
"message",
|
|
21456
|
+
updateCheck.hasUpdate ? `Update available: ${updateCheck.currentVersion} -> ${updateCheck.latestVersion}` : `Already at the latest version (${updateCheck.currentVersion})`
|
|
21457
|
+
);
|
|
21458
|
+
}
|
|
21217
21459
|
if (updateCheck.hasUpdate) {
|
|
21218
|
-
|
|
21460
|
+
logger2.success(
|
|
21219
21461
|
`Update available: ${updateCheck.currentVersion} -> ${updateCheck.latestVersion}`
|
|
21220
21462
|
);
|
|
21221
21463
|
} else {
|
|
21222
|
-
|
|
21464
|
+
logger2.info(`Already at the latest version (${updateCheck.currentVersion})`);
|
|
21223
21465
|
}
|
|
21224
21466
|
return;
|
|
21225
21467
|
}
|
|
21226
|
-
|
|
21468
|
+
logger2.info("Checking for updates...");
|
|
21227
21469
|
const message = await performBinaryUpdate(currentVersion, { force, token });
|
|
21228
|
-
|
|
21470
|
+
logger2.success(message);
|
|
21229
21471
|
} catch (error) {
|
|
21230
21472
|
if (error instanceof GitHubClientError) {
|
|
21231
|
-
|
|
21473
|
+
const authHint = error.statusCode === 401 || error.statusCode === 403 ? " Tip: Set GITHUB_TOKEN or GH_TOKEN environment variable, or use `GITHUB_TOKEN=$(gh auth token) rulesync update ...`" : "";
|
|
21474
|
+
throw new CLIError(
|
|
21475
|
+
`GitHub API Error: ${error.message}.${authHint}`,
|
|
21476
|
+
ErrorCodes.UPDATE_FAILED
|
|
21477
|
+
);
|
|
21232
21478
|
} else if (error instanceof UpdatePermissionError) {
|
|
21233
|
-
|
|
21234
|
-
|
|
21235
|
-
|
|
21236
|
-
|
|
21479
|
+
throw new CLIError(
|
|
21480
|
+
`${error.message} Tip: Run with elevated privileges (e.g., sudo rulesync update)`,
|
|
21481
|
+
ErrorCodes.UPDATE_FAILED
|
|
21482
|
+
);
|
|
21237
21483
|
}
|
|
21238
|
-
|
|
21484
|
+
throw error;
|
|
21239
21485
|
}
|
|
21240
21486
|
}
|
|
21241
21487
|
|
|
21242
21488
|
// src/cli/index.ts
|
|
21243
|
-
var getVersion = () => "7.
|
|
21489
|
+
var getVersion = () => "7.19.0";
|
|
21490
|
+
function wrapCommand(name, errorCode, handler) {
|
|
21491
|
+
return async (...args) => {
|
|
21492
|
+
const command = args[args.length - 1];
|
|
21493
|
+
const options = args[args.length - 2];
|
|
21494
|
+
const positionalArgs = args.slice(0, -2);
|
|
21495
|
+
const globalOpts = command.parent?.opts() ?? {};
|
|
21496
|
+
const logger2 = createLogger(getVersion());
|
|
21497
|
+
logger2.setJsonMode(Boolean(globalOpts.json), name);
|
|
21498
|
+
logger2.configure({
|
|
21499
|
+
verbose: Boolean(globalOpts.verbose) || Boolean(options.verbose),
|
|
21500
|
+
silent: Boolean(globalOpts.silent) || Boolean(options.silent)
|
|
21501
|
+
});
|
|
21502
|
+
try {
|
|
21503
|
+
await handler(logger2, options, globalOpts, positionalArgs);
|
|
21504
|
+
if (globalOpts.json) {
|
|
21505
|
+
logger2.outputJson(true);
|
|
21506
|
+
}
|
|
21507
|
+
} catch (error) {
|
|
21508
|
+
const code = error instanceof CLIError ? error.code : errorCode;
|
|
21509
|
+
const errorArg = error instanceof Error ? error : formatError(error);
|
|
21510
|
+
logger2.error(errorArg, code);
|
|
21511
|
+
process.exit(error instanceof CLIError ? error.exitCode : 1);
|
|
21512
|
+
}
|
|
21513
|
+
};
|
|
21514
|
+
}
|
|
21244
21515
|
var main = async () => {
|
|
21245
21516
|
const program = new import_commander.Command();
|
|
21246
21517
|
const version = getVersion();
|
|
21247
|
-
program.
|
|
21248
|
-
|
|
21249
|
-
|
|
21518
|
+
program.name("rulesync").description("Unified AI rules management CLI tool").version(version, "-v, --version", "Show version").option("-j, --json", "Output results as JSON");
|
|
21519
|
+
program.command("init").description("Initialize rulesync in current directory").option("-V, --verbose", "Verbose output").option("-s, --silent", "Suppress all output").action(
|
|
21520
|
+
wrapCommand("init", "INIT_FAILED", async (logger2) => {
|
|
21521
|
+
await initCommand(logger2);
|
|
21522
|
+
})
|
|
21523
|
+
);
|
|
21524
|
+
program.command("gitignore").description("Add generated files to .gitignore").option(
|
|
21525
|
+
"-t, --targets <tools>",
|
|
21526
|
+
"Comma-separated list of tools to include (e.g., 'claudecode,copilot' or '*' for all)",
|
|
21527
|
+
(value) => {
|
|
21528
|
+
return value.split(",").map((t) => t.trim()).filter(Boolean);
|
|
21250
21529
|
}
|
|
21251
|
-
|
|
21252
|
-
|
|
21253
|
-
|
|
21254
|
-
|
|
21530
|
+
).option(
|
|
21531
|
+
"-f, --features <features>",
|
|
21532
|
+
`Comma-separated list of features to include (${ALL_FEATURES.join(",")}) or '*' for all`,
|
|
21533
|
+
(value) => {
|
|
21534
|
+
return value.split(",").map((f) => f.trim()).filter(Boolean);
|
|
21535
|
+
}
|
|
21536
|
+
).option("-V, --verbose", "Verbose output").option("-s, --silent", "Suppress all output").action(
|
|
21537
|
+
wrapCommand("gitignore", "GITIGNORE_FAILED", async (logger2, options) => {
|
|
21538
|
+
await gitignoreCommand(logger2, {
|
|
21539
|
+
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
21540
|
+
targets: options.targets,
|
|
21541
|
+
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
21542
|
+
features: options.features
|
|
21543
|
+
});
|
|
21544
|
+
})
|
|
21545
|
+
);
|
|
21255
21546
|
program.command("fetch <source>").description("Fetch files from a Git repository (GitHub/GitLab)").option(
|
|
21256
21547
|
"-t, --target <target>",
|
|
21257
21548
|
"Target format to interpret files as (e.g., 'rulesync', 'claudecode'). Default: rulesync"
|
|
21258
21549
|
).option(
|
|
21259
21550
|
"-f, --features <features>",
|
|
21260
21551
|
`Comma-separated list of features to fetch (${ALL_FEATURES.join(",")}) or '*' for all`,
|
|
21261
|
-
(value) =>
|
|
21262
|
-
return value.split(",").map((f) => f.trim());
|
|
21263
|
-
}
|
|
21552
|
+
(value) => value.split(",").map((f) => f.trim())
|
|
21264
21553
|
).option("-r, --ref <ref>", "Branch, tag, or commit SHA to fetch from").option("-p, --path <path>", "Subdirectory path within the repository").option("-o, --output <dir>", "Output directory (default: .rulesync)").option(
|
|
21265
21554
|
"-c, --conflict <strategy>",
|
|
21266
21555
|
"Conflict resolution strategy: skip, overwrite (default: overwrite)"
|
|
21267
|
-
).option("--token <token>", "Git provider token for private repositories").option("-V, --verbose", "Verbose output").option("-s, --silent", "Suppress all output").action(
|
|
21268
|
-
|
|
21269
|
-
source
|
|
21270
|
-
|
|
21271
|
-
|
|
21272
|
-
|
|
21273
|
-
path: options.path,
|
|
21274
|
-
output: options.output,
|
|
21275
|
-
conflict: options.conflict,
|
|
21276
|
-
token: options.token,
|
|
21277
|
-
verbose: options.verbose,
|
|
21278
|
-
silent: options.silent
|
|
21279
|
-
});
|
|
21280
|
-
});
|
|
21556
|
+
).option("--token <token>", "Git provider token for private repositories").option("-V, --verbose", "Verbose output").option("-s, --silent", "Suppress all output").action(
|
|
21557
|
+
wrapCommand("fetch", "FETCH_FAILED", async (logger2, options, _globalOpts, positionalArgs) => {
|
|
21558
|
+
const source = positionalArgs[0];
|
|
21559
|
+
await fetchCommand(logger2, { ...options, source });
|
|
21560
|
+
})
|
|
21561
|
+
);
|
|
21281
21562
|
program.command("import").description("Import configurations from AI tools to rulesync format").option(
|
|
21282
21563
|
"-t, --targets <tool>",
|
|
21283
21564
|
"Tool to import from (e.g., 'copilot', 'cursor', 'cline')",
|
|
21284
|
-
(value) =>
|
|
21285
|
-
return value.split(",").map((t) => t.trim());
|
|
21286
|
-
}
|
|
21565
|
+
(value) => value.split(",").map((t) => t.trim())
|
|
21287
21566
|
).option(
|
|
21288
21567
|
"-f, --features <features>",
|
|
21289
21568
|
`Comma-separated list of features to import (${ALL_FEATURES.join(",")}) or '*' for all`,
|
|
21290
|
-
(value) =>
|
|
21291
|
-
|
|
21292
|
-
|
|
21293
|
-
|
|
21294
|
-
|
|
21295
|
-
|
|
21296
|
-
|
|
21297
|
-
|
|
21298
|
-
|
|
21299
|
-
|
|
21300
|
-
|
|
21301
|
-
global: options.global
|
|
21302
|
-
});
|
|
21303
|
-
} catch (error) {
|
|
21304
|
-
logger.error(formatError(error));
|
|
21305
|
-
process.exit(1);
|
|
21306
|
-
}
|
|
21307
|
-
});
|
|
21308
|
-
program.command("mcp").description("Start MCP server for rulesync").action(async () => {
|
|
21309
|
-
try {
|
|
21310
|
-
await mcpCommand({ version });
|
|
21311
|
-
} catch (error) {
|
|
21312
|
-
logger.error(formatError(error));
|
|
21313
|
-
process.exit(1);
|
|
21314
|
-
}
|
|
21315
|
-
});
|
|
21569
|
+
(value) => value.split(",").map((f) => f.trim())
|
|
21570
|
+
).option("-V, --verbose", "Verbose output").option("-s, --silent", "Suppress all output").option("-g, --global", "Import for global(user scope) configuration files").action(
|
|
21571
|
+
wrapCommand("import", "IMPORT_FAILED", async (logger2, options) => {
|
|
21572
|
+
await importCommand(logger2, options);
|
|
21573
|
+
})
|
|
21574
|
+
);
|
|
21575
|
+
program.command("mcp").description("Start MCP server for rulesync").action(
|
|
21576
|
+
wrapCommand("mcp", "MCP_FAILED", async (logger2, _options) => {
|
|
21577
|
+
await mcpCommand(logger2, { version });
|
|
21578
|
+
})
|
|
21579
|
+
);
|
|
21316
21580
|
program.command("install").description("Install skills from declarative sources in rulesync.jsonc").option("--update", "Force re-resolve all source refs, ignoring lockfile").option(
|
|
21317
21581
|
"--frozen",
|
|
21318
21582
|
"Fail if lockfile is missing or out of sync (for CI); fetches missing skills using locked refs"
|
|
21319
|
-
).option("--token <token>", "GitHub token for private repos").option("-c, --config <path>", "Path to configuration file").option("-V, --verbose", "Verbose output").option("-s, --silent", "Suppress all output").action(
|
|
21320
|
-
|
|
21321
|
-
await installCommand({
|
|
21583
|
+
).option("--token <token>", "GitHub token for private repos").option("-c, --config <path>", "Path to configuration file").option("-V, --verbose", "Verbose output").option("-s, --silent", "Suppress all output").action(
|
|
21584
|
+
wrapCommand("install", "INSTALL_FAILED", async (logger2, options) => {
|
|
21585
|
+
await installCommand(logger2, {
|
|
21586
|
+
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
21322
21587
|
update: options.update,
|
|
21588
|
+
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
21323
21589
|
frozen: options.frozen,
|
|
21590
|
+
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
21324
21591
|
token: options.token,
|
|
21592
|
+
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
21325
21593
|
configPath: options.config,
|
|
21594
|
+
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
21326
21595
|
verbose: options.verbose,
|
|
21596
|
+
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
21327
21597
|
silent: options.silent
|
|
21328
21598
|
});
|
|
21329
|
-
}
|
|
21330
|
-
|
|
21331
|
-
process.exit(1);
|
|
21332
|
-
}
|
|
21333
|
-
});
|
|
21599
|
+
})
|
|
21600
|
+
);
|
|
21334
21601
|
program.command("generate").description("Generate configuration files for AI tools").option(
|
|
21335
21602
|
"-t, --targets <tools>",
|
|
21336
21603
|
"Comma-separated list of tools to generate for (e.g., 'copilot,cursor,cline' or '*' for all)",
|
|
21337
|
-
(value) =>
|
|
21338
|
-
return value.split(",").map((t) => t.trim());
|
|
21339
|
-
}
|
|
21604
|
+
(value) => value.split(",").map((t) => t.trim())
|
|
21340
21605
|
).option(
|
|
21341
21606
|
"-f, --features <features>",
|
|
21342
21607
|
`Comma-separated list of features to generate (${ALL_FEATURES.join(",")}) or '*' for all`,
|
|
21343
|
-
(value) =>
|
|
21344
|
-
return value.split(",").map((f) => f.trim());
|
|
21345
|
-
}
|
|
21608
|
+
(value) => value.split(",").map((f) => f.trim())
|
|
21346
21609
|
).option("--delete", "Delete all existing files in output directories before generating").option(
|
|
21347
21610
|
"-b, --base-dir <paths>",
|
|
21348
21611
|
"Base directories to generate files (comma-separated for multiple paths)",
|
|
21349
|
-
(value) =>
|
|
21350
|
-
return value.split(",").map((p) => p.trim());
|
|
21351
|
-
}
|
|
21612
|
+
(value) => value.split(",").map((p) => p.trim())
|
|
21352
21613
|
).option("-V, --verbose", "Verbose output").option("-s, --silent", "Suppress all output").option("-c, --config <path>", "Path to configuration file").option("-g, --global", "Generate for global(user scope) configuration files").option(
|
|
21353
21614
|
"--simulate-commands",
|
|
21354
21615
|
"Generate simulated commands. This feature is only available for copilot, cursor and codexcli."
|
|
@@ -21358,40 +21619,19 @@ var main = async () => {
|
|
|
21358
21619
|
).option(
|
|
21359
21620
|
"--simulate-skills",
|
|
21360
21621
|
"Generate simulated skills. This feature is only available for copilot, cursor and codexcli."
|
|
21361
|
-
).option("--dry-run", "Dry run: show changes without writing files").option("--check", "Check if files are up to date (exits with code 1 if changes needed)").action(
|
|
21362
|
-
|
|
21363
|
-
await generateCommand(
|
|
21364
|
-
|
|
21365
|
-
|
|
21366
|
-
|
|
21367
|
-
|
|
21368
|
-
|
|
21369
|
-
|
|
21370
|
-
|
|
21371
|
-
global: options.global,
|
|
21372
|
-
simulateCommands: options.simulateCommands,
|
|
21373
|
-
simulateSubagents: options.simulateSubagents,
|
|
21374
|
-
simulateSkills: options.simulateSkills,
|
|
21375
|
-
dryRun: options.dryRun,
|
|
21376
|
-
check: options.check
|
|
21377
|
-
});
|
|
21378
|
-
} catch (error) {
|
|
21379
|
-
logger.error(formatError(error));
|
|
21380
|
-
process.exit(1);
|
|
21381
|
-
}
|
|
21382
|
-
});
|
|
21383
|
-
program.command("update").description("Update rulesync to the latest version").option("--check", "Check for updates without installing").option("--force", "Force update even if already at latest version").option("--token <token>", "GitHub token for API access").option("-V, --verbose", "Verbose output").option("-s, --silent", "Suppress all output").action(async (options) => {
|
|
21384
|
-
await updateCommand(version, {
|
|
21385
|
-
check: options.check,
|
|
21386
|
-
force: options.force,
|
|
21387
|
-
token: options.token,
|
|
21388
|
-
verbose: options.verbose,
|
|
21389
|
-
silent: options.silent
|
|
21390
|
-
});
|
|
21391
|
-
});
|
|
21622
|
+
).option("--dry-run", "Dry run: show changes without writing files").option("--check", "Check if files are up to date (exits with code 1 if changes needed)").action(
|
|
21623
|
+
wrapCommand("generate", "GENERATION_FAILED", async (logger2, options) => {
|
|
21624
|
+
await generateCommand(logger2, options);
|
|
21625
|
+
})
|
|
21626
|
+
);
|
|
21627
|
+
program.command("update").description("Update rulesync to the latest version").option("--check", "Check for updates without installing").option("--force", "Force update even if already at latest version").option("--token <token>", "GitHub token for API access").option("-V, --verbose", "Verbose output").option("-s, --silent", "Suppress all output").action(
|
|
21628
|
+
wrapCommand("update", "UPDATE_FAILED", async (logger2, options) => {
|
|
21629
|
+
await updateCommand(logger2, version, options);
|
|
21630
|
+
})
|
|
21631
|
+
);
|
|
21392
21632
|
program.parse();
|
|
21393
21633
|
};
|
|
21394
21634
|
main().catch((error) => {
|
|
21395
|
-
|
|
21635
|
+
console.error(formatError(error));
|
|
21396
21636
|
process.exit(1);
|
|
21397
21637
|
});
|