rulesync 7.18.2 → 7.20.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-5OPNV62F.js} +152 -36
- package/dist/cli/index.cjs +601 -386
- package/dist/cli/index.js +459 -350
- package/dist/index.cjs +52 -37
- package/dist/index.js +1 -1
- package/package.json +2 -3
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) {
|
|
@@ -65,69 +88,141 @@ function formatError(error) {
|
|
|
65
88
|
return String(error);
|
|
66
89
|
}
|
|
67
90
|
|
|
68
|
-
// src/utils/logger.ts
|
|
69
|
-
var import_consola = require("consola");
|
|
70
|
-
|
|
71
91
|
// src/utils/vitest.ts
|
|
72
92
|
function isEnvTest() {
|
|
73
93
|
return process.env.NODE_ENV === "test";
|
|
74
94
|
}
|
|
75
95
|
|
|
76
96
|
// src/utils/logger.ts
|
|
77
|
-
var
|
|
97
|
+
var BaseLogger = class {
|
|
78
98
|
_verbose = false;
|
|
79
99
|
_silent = false;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
* @param verbose - Enable verbose logging
|
|
87
|
-
* @param silent - Enable silent mode (suppresses all output except errors)
|
|
88
|
-
*/
|
|
100
|
+
get verbose() {
|
|
101
|
+
return this._verbose;
|
|
102
|
+
}
|
|
103
|
+
get silent() {
|
|
104
|
+
return this._silent;
|
|
105
|
+
}
|
|
89
106
|
configure({ verbose, silent }) {
|
|
90
107
|
if (verbose && silent) {
|
|
91
108
|
this._silent = false;
|
|
92
|
-
|
|
109
|
+
if (!isEnvTest()) {
|
|
110
|
+
console.warn("Both --verbose and --silent specified; --silent takes precedence");
|
|
111
|
+
}
|
|
93
112
|
}
|
|
94
113
|
this._silent = silent;
|
|
95
114
|
this._verbose = verbose && !silent;
|
|
96
115
|
}
|
|
97
|
-
|
|
98
|
-
|
|
116
|
+
};
|
|
117
|
+
var ConsoleLogger = class extends BaseLogger {
|
|
118
|
+
isSuppressed() {
|
|
119
|
+
return isEnvTest() || this._silent;
|
|
99
120
|
}
|
|
100
|
-
get
|
|
101
|
-
return
|
|
121
|
+
get jsonMode() {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
captureData(_key, _value) {
|
|
125
|
+
}
|
|
126
|
+
getJsonData() {
|
|
127
|
+
return {};
|
|
128
|
+
}
|
|
129
|
+
outputJson(_success, _error) {
|
|
102
130
|
}
|
|
103
131
|
info(message, ...args) {
|
|
104
|
-
if (
|
|
105
|
-
|
|
132
|
+
if (this.isSuppressed()) return;
|
|
133
|
+
console.log(message, ...args);
|
|
106
134
|
}
|
|
107
|
-
// Success (always shown unless silent)
|
|
108
135
|
success(message, ...args) {
|
|
109
|
-
if (
|
|
110
|
-
|
|
136
|
+
if (this.isSuppressed()) return;
|
|
137
|
+
console.log(message, ...args);
|
|
111
138
|
}
|
|
112
|
-
// Warning (always shown unless silent)
|
|
113
139
|
warn(message, ...args) {
|
|
114
|
-
if (
|
|
115
|
-
|
|
140
|
+
if (this.isSuppressed()) return;
|
|
141
|
+
console.warn(message, ...args);
|
|
116
142
|
}
|
|
117
|
-
|
|
118
|
-
error(message, ...args) {
|
|
143
|
+
error(message, _code, ...args) {
|
|
119
144
|
if (isEnvTest()) return;
|
|
120
|
-
|
|
145
|
+
const errorMessage = message instanceof Error ? message.message : message;
|
|
146
|
+
console.error(errorMessage, ...args);
|
|
121
147
|
}
|
|
122
|
-
// Debug level (shown only in verbose mode)
|
|
123
148
|
debug(message, ...args) {
|
|
124
|
-
if (
|
|
149
|
+
if (this.isSuppressed()) return;
|
|
125
150
|
if (this._verbose) {
|
|
126
|
-
|
|
151
|
+
console.log(message, ...args);
|
|
127
152
|
}
|
|
128
153
|
}
|
|
129
154
|
};
|
|
130
|
-
var
|
|
155
|
+
var JsonLogger = class extends BaseLogger {
|
|
156
|
+
_jsonOutputDone = false;
|
|
157
|
+
_jsonData = {};
|
|
158
|
+
_commandName;
|
|
159
|
+
_version;
|
|
160
|
+
constructor({ command, version }) {
|
|
161
|
+
super();
|
|
162
|
+
this._commandName = command;
|
|
163
|
+
this._version = version;
|
|
164
|
+
}
|
|
165
|
+
get jsonMode() {
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
captureData(key, value) {
|
|
169
|
+
this._jsonData[key] = value;
|
|
170
|
+
}
|
|
171
|
+
getJsonData() {
|
|
172
|
+
return { ...this._jsonData };
|
|
173
|
+
}
|
|
174
|
+
outputJson(success, error) {
|
|
175
|
+
if (this._jsonOutputDone) return;
|
|
176
|
+
this._jsonOutputDone = true;
|
|
177
|
+
const output = {
|
|
178
|
+
success,
|
|
179
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
180
|
+
command: this._commandName,
|
|
181
|
+
version: this._version
|
|
182
|
+
};
|
|
183
|
+
if (success) {
|
|
184
|
+
output.data = this._jsonData;
|
|
185
|
+
} else if (error) {
|
|
186
|
+
output.error = {
|
|
187
|
+
code: error.code,
|
|
188
|
+
message: error.message
|
|
189
|
+
};
|
|
190
|
+
if (error.details) {
|
|
191
|
+
output.error.details = error.details;
|
|
192
|
+
}
|
|
193
|
+
if (error.stack) {
|
|
194
|
+
output.error.stack = error.stack;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
const jsonStr = JSON.stringify(output, null, 2);
|
|
198
|
+
if (success) {
|
|
199
|
+
console.log(jsonStr);
|
|
200
|
+
} else {
|
|
201
|
+
console.error(jsonStr);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
info(_message, ..._args) {
|
|
205
|
+
}
|
|
206
|
+
success(_message, ..._args) {
|
|
207
|
+
}
|
|
208
|
+
warn(_message, ..._args) {
|
|
209
|
+
}
|
|
210
|
+
error(message, code, ..._args) {
|
|
211
|
+
if (isEnvTest()) return;
|
|
212
|
+
const errorMessage = message instanceof Error ? message.message : message;
|
|
213
|
+
const errorInfo = {
|
|
214
|
+
code: code || ErrorCodes.UNKNOWN_ERROR,
|
|
215
|
+
message: errorMessage
|
|
216
|
+
};
|
|
217
|
+
if (this._verbose && message instanceof Error && message.stack) {
|
|
218
|
+
errorInfo.stack = message.stack;
|
|
219
|
+
}
|
|
220
|
+
this.outputJson(false, errorInfo);
|
|
221
|
+
}
|
|
222
|
+
debug(_message, ..._args) {
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
var logger = new ConsoleLogger();
|
|
131
226
|
|
|
132
227
|
// src/lib/fetch.ts
|
|
133
228
|
var import_node_path117 = require("path");
|
|
@@ -3008,7 +3103,9 @@ var CLAUDE_HOOK_EVENTS = [
|
|
|
3008
3103
|
"preCompact",
|
|
3009
3104
|
"permissionRequest",
|
|
3010
3105
|
"notification",
|
|
3011
|
-
"setup"
|
|
3106
|
+
"setup",
|
|
3107
|
+
"worktreeCreate",
|
|
3108
|
+
"worktreeRemove"
|
|
3012
3109
|
];
|
|
3013
3110
|
var OPENCODE_HOOK_EVENTS = [
|
|
3014
3111
|
"sessionStart",
|
|
@@ -3075,7 +3172,9 @@ var CANONICAL_TO_CLAUDE_EVENT_NAMES = {
|
|
|
3075
3172
|
preCompact: "PreCompact",
|
|
3076
3173
|
permissionRequest: "PermissionRequest",
|
|
3077
3174
|
notification: "Notification",
|
|
3078
|
-
setup: "Setup"
|
|
3175
|
+
setup: "Setup",
|
|
3176
|
+
worktreeCreate: "WorktreeCreate",
|
|
3177
|
+
worktreeRemove: "WorktreeRemove"
|
|
3079
3178
|
};
|
|
3080
3179
|
var CLAUDE_TO_CANONICAL_EVENT_NAMES = Object.fromEntries(
|
|
3081
3180
|
Object.entries(CANONICAL_TO_CLAUDE_EVENT_NAMES).map(([k, v]) => [v, k])
|
|
@@ -3201,7 +3300,13 @@ function canonicalToToolHooks({
|
|
|
3201
3300
|
else byMatcher.set(key, [def]);
|
|
3202
3301
|
}
|
|
3203
3302
|
const entries = [];
|
|
3303
|
+
const isNoMatcherEvent = converterConfig.noMatcherEvents?.has(eventName) ?? false;
|
|
3204
3304
|
for (const [matcherKey, defs] of byMatcher) {
|
|
3305
|
+
if (isNoMatcherEvent && matcherKey) {
|
|
3306
|
+
logger.warn(
|
|
3307
|
+
`matcher "${matcherKey}" on "${eventName}" hook will be ignored \u2014 this event does not support matchers`
|
|
3308
|
+
);
|
|
3309
|
+
}
|
|
3205
3310
|
const hooks = defs.map((def) => {
|
|
3206
3311
|
const commandText = def.command;
|
|
3207
3312
|
const trimmedCommand = typeof commandText === "string" ? commandText.trimStart() : void 0;
|
|
@@ -3214,7 +3319,8 @@ function canonicalToToolHooks({
|
|
|
3214
3319
|
...def.prompt !== void 0 && def.prompt !== null && { prompt: def.prompt }
|
|
3215
3320
|
};
|
|
3216
3321
|
});
|
|
3217
|
-
|
|
3322
|
+
const includeMatcher = matcherKey && !isNoMatcherEvent;
|
|
3323
|
+
entries.push(includeMatcher ? { matcher: matcherKey, hooks } : { hooks });
|
|
3218
3324
|
}
|
|
3219
3325
|
result[toolEventName] = entries;
|
|
3220
3326
|
}
|
|
@@ -3352,12 +3458,14 @@ var ToolHooks = class extends ToolFile {
|
|
|
3352
3458
|
};
|
|
3353
3459
|
|
|
3354
3460
|
// src/features/hooks/claudecode-hooks.ts
|
|
3461
|
+
var CLAUDE_NO_MATCHER_EVENTS = /* @__PURE__ */ new Set(["worktreeCreate", "worktreeRemove"]);
|
|
3355
3462
|
var CLAUDE_CONVERTER_CONFIG = {
|
|
3356
3463
|
supportedEvents: CLAUDE_HOOK_EVENTS,
|
|
3357
3464
|
canonicalToToolEventNames: CANONICAL_TO_CLAUDE_EVENT_NAMES,
|
|
3358
3465
|
toolToCanonicalEventNames: CLAUDE_TO_CANONICAL_EVENT_NAMES,
|
|
3359
3466
|
projectDirVar: "$CLAUDE_PROJECT_DIR",
|
|
3360
|
-
prefixDotRelativeCommandsOnly: true
|
|
3467
|
+
prefixDotRelativeCommandsOnly: true,
|
|
3468
|
+
noMatcherEvents: CLAUDE_NO_MATCHER_EVENTS
|
|
3361
3469
|
};
|
|
3362
3470
|
var ClaudecodeHooks = class _ClaudecodeHooks extends ToolHooks {
|
|
3363
3471
|
constructor(params) {
|
|
@@ -17144,30 +17252,36 @@ function formatFetchSummary(summary) {
|
|
|
17144
17252
|
}
|
|
17145
17253
|
|
|
17146
17254
|
// src/cli/commands/fetch.ts
|
|
17147
|
-
async function fetchCommand(options) {
|
|
17255
|
+
async function fetchCommand(logger2, options) {
|
|
17148
17256
|
const { source, ...fetchOptions } = options;
|
|
17149
|
-
|
|
17150
|
-
verbose: fetchOptions.verbose ?? false,
|
|
17151
|
-
silent: fetchOptions.silent ?? false
|
|
17152
|
-
});
|
|
17153
|
-
logger.debug(`Fetching files from ${source}...`);
|
|
17257
|
+
logger2.debug(`Fetching files from ${source}...`);
|
|
17154
17258
|
try {
|
|
17155
17259
|
const summary = await fetchFiles({
|
|
17156
17260
|
source,
|
|
17157
17261
|
options: fetchOptions
|
|
17158
17262
|
});
|
|
17263
|
+
if (logger2.jsonMode) {
|
|
17264
|
+
const createdFiles = summary.files.filter((f) => f.status === "created").map((f) => f.relativePath);
|
|
17265
|
+
const overwrittenFiles = summary.files.filter((f) => f.status === "overwritten").map((f) => f.relativePath);
|
|
17266
|
+
const skippedFiles = summary.files.filter((f) => f.status === "skipped").map((f) => f.relativePath);
|
|
17267
|
+
logger2.captureData("source", source);
|
|
17268
|
+
logger2.captureData("path", fetchOptions.path);
|
|
17269
|
+
logger2.captureData("created", createdFiles);
|
|
17270
|
+
logger2.captureData("overwritten", overwrittenFiles);
|
|
17271
|
+
logger2.captureData("skipped", skippedFiles);
|
|
17272
|
+
logger2.captureData("totalFetched", summary.created + summary.overwritten + summary.skipped);
|
|
17273
|
+
}
|
|
17159
17274
|
const output = formatFetchSummary(summary);
|
|
17160
|
-
|
|
17275
|
+
logger2.success(output);
|
|
17161
17276
|
if (summary.created + summary.overwritten === 0 && summary.skipped === 0) {
|
|
17162
|
-
|
|
17277
|
+
logger2.warn("No files were fetched.");
|
|
17163
17278
|
}
|
|
17164
17279
|
} catch (error) {
|
|
17165
17280
|
if (error instanceof GitHubClientError) {
|
|
17166
|
-
|
|
17167
|
-
|
|
17168
|
-
logger.error(formatError(error));
|
|
17281
|
+
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 ...`" : "";
|
|
17282
|
+
throw new CLIError(`GitHub API Error: ${error.message}.${authHint}`, ErrorCodes.FETCH_FAILED);
|
|
17169
17283
|
}
|
|
17170
|
-
|
|
17284
|
+
throw error;
|
|
17171
17285
|
}
|
|
17172
17286
|
}
|
|
17173
17287
|
|
|
@@ -17881,110 +17995,92 @@ function calculateTotalCount(result) {
|
|
|
17881
17995
|
}
|
|
17882
17996
|
|
|
17883
17997
|
// src/cli/commands/generate.ts
|
|
17884
|
-
function logFeatureResult(params) {
|
|
17998
|
+
function logFeatureResult(logger2, params) {
|
|
17885
17999
|
const { count, paths, featureName, isPreview, modePrefix } = params;
|
|
17886
18000
|
if (count > 0) {
|
|
17887
18001
|
if (isPreview) {
|
|
17888
|
-
|
|
18002
|
+
logger2.info(`${modePrefix} Would write ${count} ${featureName}`);
|
|
17889
18003
|
} else {
|
|
17890
|
-
|
|
18004
|
+
logger2.success(`Written ${count} ${featureName}`);
|
|
17891
18005
|
}
|
|
17892
18006
|
for (const p of paths) {
|
|
17893
|
-
|
|
18007
|
+
logger2.info(` ${p}`);
|
|
17894
18008
|
}
|
|
17895
18009
|
}
|
|
17896
18010
|
}
|
|
17897
|
-
async function generateCommand(options) {
|
|
18011
|
+
async function generateCommand(logger2, options) {
|
|
17898
18012
|
const config = await ConfigResolver.resolve(options);
|
|
17899
|
-
logger.configure({
|
|
17900
|
-
verbose: config.getVerbose(),
|
|
17901
|
-
silent: config.getSilent()
|
|
17902
|
-
});
|
|
17903
18013
|
const check = config.getCheck();
|
|
17904
18014
|
const isPreview = config.isPreviewMode();
|
|
17905
18015
|
const modePrefix = isPreview ? "[DRY RUN]" : "";
|
|
17906
|
-
|
|
18016
|
+
logger2.debug("Generating files...");
|
|
17907
18017
|
if (!await checkRulesyncDirExists({ baseDir: process.cwd() })) {
|
|
17908
|
-
|
|
17909
|
-
|
|
18018
|
+
throw new CLIError(
|
|
18019
|
+
".rulesync directory not found. Run 'rulesync init' first.",
|
|
18020
|
+
ErrorCodes.RULESYNC_DIR_NOT_FOUND
|
|
18021
|
+
);
|
|
17910
18022
|
}
|
|
17911
|
-
|
|
18023
|
+
logger2.debug(`Base directories: ${config.getBaseDirs().join(", ")}`);
|
|
17912
18024
|
const features = config.getFeatures();
|
|
17913
18025
|
if (features.includes("ignore")) {
|
|
17914
|
-
|
|
18026
|
+
logger2.debug("Generating ignore files...");
|
|
17915
18027
|
}
|
|
17916
18028
|
if (features.includes("mcp")) {
|
|
17917
|
-
|
|
18029
|
+
logger2.debug("Generating MCP files...");
|
|
17918
18030
|
}
|
|
17919
18031
|
if (features.includes("commands")) {
|
|
17920
|
-
|
|
18032
|
+
logger2.debug("Generating command files...");
|
|
17921
18033
|
}
|
|
17922
18034
|
if (features.includes("subagents")) {
|
|
17923
|
-
|
|
18035
|
+
logger2.debug("Generating subagent files...");
|
|
17924
18036
|
}
|
|
17925
18037
|
if (features.includes("skills")) {
|
|
17926
|
-
|
|
18038
|
+
logger2.debug("Generating skill files...");
|
|
17927
18039
|
}
|
|
17928
18040
|
if (features.includes("hooks")) {
|
|
17929
|
-
|
|
18041
|
+
logger2.debug("Generating hooks...");
|
|
17930
18042
|
}
|
|
17931
18043
|
if (features.includes("rules")) {
|
|
17932
|
-
|
|
18044
|
+
logger2.debug("Generating rule files...");
|
|
17933
18045
|
}
|
|
17934
18046
|
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
18047
|
const totalGenerated = calculateTotalCount(result);
|
|
18048
|
+
const featureResults = {
|
|
18049
|
+
ignore: { count: result.ignoreCount, paths: result.ignorePaths },
|
|
18050
|
+
mcp: { count: result.mcpCount, paths: result.mcpPaths },
|
|
18051
|
+
commands: { count: result.commandsCount, paths: result.commandsPaths },
|
|
18052
|
+
subagents: { count: result.subagentsCount, paths: result.subagentsPaths },
|
|
18053
|
+
skills: { count: result.skillsCount, paths: result.skillsPaths },
|
|
18054
|
+
hooks: { count: result.hooksCount, paths: result.hooksPaths },
|
|
18055
|
+
rules: { count: result.rulesCount, paths: result.rulesPaths }
|
|
18056
|
+
};
|
|
18057
|
+
const featureLabels = {
|
|
18058
|
+
rules: (count) => `${count === 1 ? "rule" : "rules"}`,
|
|
18059
|
+
ignore: (count) => `${count === 1 ? "ignore file" : "ignore files"}`,
|
|
18060
|
+
mcp: (count) => `${count === 1 ? "MCP file" : "MCP files"}`,
|
|
18061
|
+
commands: (count) => `${count === 1 ? "command" : "commands"}`,
|
|
18062
|
+
subagents: (count) => `${count === 1 ? "subagent" : "subagents"}`,
|
|
18063
|
+
skills: (count) => `${count === 1 ? "skill" : "skills"}`,
|
|
18064
|
+
hooks: (count) => `${count === 1 ? "hooks file" : "hooks files"}`
|
|
18065
|
+
};
|
|
18066
|
+
for (const [feature, data] of Object.entries(featureResults)) {
|
|
18067
|
+
logFeatureResult(logger2, {
|
|
18068
|
+
count: data.count,
|
|
18069
|
+
paths: data.paths,
|
|
18070
|
+
featureName: featureLabels[feature]?.(data.count) ?? feature,
|
|
18071
|
+
isPreview,
|
|
18072
|
+
modePrefix
|
|
18073
|
+
});
|
|
18074
|
+
}
|
|
18075
|
+
if (logger2.jsonMode) {
|
|
18076
|
+
logger2.captureData("features", featureResults);
|
|
18077
|
+
logger2.captureData("totalFiles", totalGenerated);
|
|
18078
|
+
logger2.captureData("hasDiff", result.hasDiff);
|
|
18079
|
+
logger2.captureData("skills", result.skills ?? []);
|
|
18080
|
+
}
|
|
17985
18081
|
if (totalGenerated === 0) {
|
|
17986
18082
|
const enabledFeatures = features.join(", ");
|
|
17987
|
-
|
|
18083
|
+
logger2.info(`\u2713 All files are up to date (${enabledFeatures})`);
|
|
17988
18084
|
return;
|
|
17989
18085
|
}
|
|
17990
18086
|
const parts = [];
|
|
@@ -17996,129 +18092,209 @@ async function generateCommand(options) {
|
|
|
17996
18092
|
if (result.skillsCount > 0) parts.push(`${result.skillsCount} skills`);
|
|
17997
18093
|
if (result.hooksCount > 0) parts.push(`${result.hooksCount} hooks`);
|
|
17998
18094
|
if (isPreview) {
|
|
17999
|
-
|
|
18095
|
+
logger2.info(`${modePrefix} Would write ${totalGenerated} file(s) total (${parts.join(" + ")})`);
|
|
18000
18096
|
} else {
|
|
18001
|
-
|
|
18097
|
+
logger2.success(`\u{1F389} All done! Written ${totalGenerated} file(s) total (${parts.join(" + ")})`);
|
|
18002
18098
|
}
|
|
18003
18099
|
if (check) {
|
|
18004
18100
|
if (result.hasDiff) {
|
|
18005
|
-
|
|
18006
|
-
|
|
18101
|
+
throw new CLIError(
|
|
18102
|
+
"Files are not up to date. Run 'rulesync generate' to update.",
|
|
18103
|
+
ErrorCodes.GENERATION_FAILED
|
|
18104
|
+
);
|
|
18007
18105
|
} else {
|
|
18008
|
-
|
|
18106
|
+
logger2.success("\u2713 All files are up to date.");
|
|
18009
18107
|
}
|
|
18010
18108
|
}
|
|
18011
18109
|
}
|
|
18012
18110
|
|
|
18013
18111
|
// src/cli/commands/gitignore.ts
|
|
18014
18112
|
var import_node_path121 = require("path");
|
|
18015
|
-
|
|
18016
|
-
|
|
18017
|
-
var
|
|
18018
|
-
//
|
|
18019
|
-
`${RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH}
|
|
18113
|
+
|
|
18114
|
+
// src/cli/commands/gitignore-entries.ts
|
|
18115
|
+
var GITIGNORE_ENTRY_REGISTRY = [
|
|
18116
|
+
// Common / general
|
|
18117
|
+
{ target: "common", feature: "general", entry: `${RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH}/` },
|
|
18118
|
+
{ target: "common", feature: "general", entry: ".rulesync/rules/*.local.md" },
|
|
18119
|
+
{ target: "common", feature: "general", entry: "rulesync.local.jsonc" },
|
|
18120
|
+
{ target: "common", feature: "general", entry: "!.rulesync/.aiignore" },
|
|
18020
18121
|
// AGENTS.md
|
|
18021
|
-
"**/AGENTS.md",
|
|
18022
|
-
"**/.agents/",
|
|
18023
|
-
// Augment
|
|
18024
|
-
"**/.
|
|
18025
|
-
"**/.augment
|
|
18026
|
-
"**/.
|
|
18122
|
+
{ target: "agentsmd", feature: "rules", entry: "**/AGENTS.md" },
|
|
18123
|
+
{ target: "agentsmd", feature: "rules", entry: "**/.agents/" },
|
|
18124
|
+
// Augment Code
|
|
18125
|
+
{ target: "augmentcode", feature: "rules", entry: "**/.augment/rules/" },
|
|
18126
|
+
{ target: "augmentcode", feature: "rules", entry: "**/.augment-guidelines" },
|
|
18127
|
+
{ target: "augmentcode", feature: "ignore", entry: "**/.augmentignore" },
|
|
18027
18128
|
// 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
|
-
"**/.
|
|
18129
|
+
{ target: "claudecode", feature: "rules", entry: "**/CLAUDE.md" },
|
|
18130
|
+
{ target: "claudecode", feature: "rules", entry: "**/CLAUDE.local.md" },
|
|
18131
|
+
{ target: "claudecode", feature: "rules", entry: "**/.claude/CLAUDE.md" },
|
|
18132
|
+
{ target: "claudecode", feature: "rules", entry: "**/.claude/CLAUDE.local.md" },
|
|
18133
|
+
{ target: "claudecode", feature: "rules", entry: "**/.claude/rules/" },
|
|
18134
|
+
{ target: "claudecode", feature: "commands", entry: "**/.claude/commands/" },
|
|
18135
|
+
{ target: "claudecode", feature: "subagents", entry: "**/.claude/agents/" },
|
|
18136
|
+
{ target: "claudecode", feature: "skills", entry: "**/.claude/skills/" },
|
|
18137
|
+
{ target: "claudecode", feature: "mcp", entry: "**/.mcp.json" },
|
|
18138
|
+
{ target: "claudecode", feature: "general", entry: "**/.claude/memories/" },
|
|
18139
|
+
{ target: "claudecode", feature: "general", entry: "**/.claude/settings.local.json" },
|
|
18039
18140
|
// 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",
|
|
18141
|
+
{ target: "cline", feature: "rules", entry: "**/.clinerules/" },
|
|
18142
|
+
{ target: "cline", feature: "commands", entry: "**/.clinerules/workflows/" },
|
|
18143
|
+
{ target: "cline", feature: "ignore", entry: "**/.clineignore" },
|
|
18144
|
+
{ target: "cline", feature: "mcp", entry: "**/.cline/mcp.json" },
|
|
18145
|
+
// Codex CLI
|
|
18146
|
+
{ target: "codexcli", feature: "ignore", entry: "**/.codexignore" },
|
|
18147
|
+
{ target: "codexcli", feature: "skills", entry: "**/.codex/skills/" },
|
|
18148
|
+
{ target: "codexcli", feature: "subagents", entry: "**/.codex/agents/" },
|
|
18149
|
+
{ target: "codexcli", feature: "general", entry: "**/.codex/memories/" },
|
|
18150
|
+
{ target: "codexcli", feature: "general", entry: "**/.codex/config.toml" },
|
|
18050
18151
|
// Cursor
|
|
18051
|
-
"**/.cursor/",
|
|
18052
|
-
"**/.cursorignore",
|
|
18152
|
+
{ target: "cursor", feature: "rules", entry: "**/.cursor/" },
|
|
18153
|
+
{ target: "cursor", feature: "ignore", entry: "**/.cursorignore" },
|
|
18053
18154
|
// 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
|
-
"**/.
|
|
18155
|
+
{ target: "factorydroid", feature: "rules", entry: "**/.factory/rules/" },
|
|
18156
|
+
{ target: "factorydroid", feature: "commands", entry: "**/.factory/commands/" },
|
|
18157
|
+
{ target: "factorydroid", feature: "subagents", entry: "**/.factory/droids/" },
|
|
18158
|
+
{ target: "factorydroid", feature: "skills", entry: "**/.factory/skills/" },
|
|
18159
|
+
{ target: "factorydroid", feature: "mcp", entry: "**/.factory/mcp.json" },
|
|
18160
|
+
{ target: "factorydroid", feature: "general", entry: "**/.factory/settings.json" },
|
|
18161
|
+
// Gemini CLI
|
|
18162
|
+
{ target: "geminicli", feature: "rules", entry: "**/GEMINI.md" },
|
|
18163
|
+
{ target: "geminicli", feature: "commands", entry: "**/.gemini/commands/" },
|
|
18164
|
+
{ target: "geminicli", feature: "subagents", entry: "**/.gemini/subagents/" },
|
|
18165
|
+
{ target: "geminicli", feature: "skills", entry: "**/.gemini/skills/" },
|
|
18166
|
+
{ target: "geminicli", feature: "ignore", entry: "**/.geminiignore" },
|
|
18167
|
+
{ target: "geminicli", feature: "general", entry: "**/.gemini/memories/" },
|
|
18067
18168
|
// Goose
|
|
18068
|
-
"**/.goosehints",
|
|
18069
|
-
"**/.goose/",
|
|
18070
|
-
"**/.gooseignore",
|
|
18169
|
+
{ target: "goose", feature: "rules", entry: "**/.goosehints" },
|
|
18170
|
+
{ target: "goose", feature: "rules", entry: "**/.goose/" },
|
|
18171
|
+
{ target: "goose", feature: "ignore", entry: "**/.gooseignore" },
|
|
18071
18172
|
// 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",
|
|
18173
|
+
{ target: "copilot", feature: "rules", entry: "**/.github/copilot-instructions.md" },
|
|
18174
|
+
{ target: "copilot", feature: "rules", entry: "**/.github/instructions/" },
|
|
18175
|
+
{ target: "copilot", feature: "commands", entry: "**/.github/prompts/" },
|
|
18176
|
+
{ target: "copilot", feature: "subagents", entry: "**/.github/agents/" },
|
|
18177
|
+
{ target: "copilot", feature: "skills", entry: "**/.github/skills/" },
|
|
18178
|
+
{ target: "copilot", feature: "hooks", entry: "**/.github/hooks/" },
|
|
18179
|
+
{ target: "copilot", feature: "mcp", entry: "**/.vscode/mcp.json" },
|
|
18079
18180
|
// Junie
|
|
18080
|
-
"**/.junie/guidelines.md",
|
|
18081
|
-
"**/.junie/mcp.json",
|
|
18082
|
-
"**/.junie/skills/",
|
|
18083
|
-
"**/.junie/agents/",
|
|
18181
|
+
{ target: "junie", feature: "rules", entry: "**/.junie/guidelines.md" },
|
|
18182
|
+
{ target: "junie", feature: "mcp", entry: "**/.junie/mcp.json" },
|
|
18183
|
+
{ target: "junie", feature: "skills", entry: "**/.junie/skills/" },
|
|
18184
|
+
{ target: "junie", feature: "subagents", entry: "**/.junie/agents/" },
|
|
18084
18185
|
// Kilo Code
|
|
18085
|
-
"**/.kilocode/rules/",
|
|
18086
|
-
"**/.kilocode/skills/",
|
|
18087
|
-
"**/.kilocode/workflows/",
|
|
18088
|
-
"**/.kilocode/mcp.json",
|
|
18089
|
-
"**/.kilocodeignore",
|
|
18186
|
+
{ target: "kilo", feature: "rules", entry: "**/.kilocode/rules/" },
|
|
18187
|
+
{ target: "kilo", feature: "skills", entry: "**/.kilocode/skills/" },
|
|
18188
|
+
{ target: "kilo", feature: "commands", entry: "**/.kilocode/workflows/" },
|
|
18189
|
+
{ target: "kilo", feature: "mcp", entry: "**/.kilocode/mcp.json" },
|
|
18190
|
+
{ target: "kilo", feature: "ignore", entry: "**/.kilocodeignore" },
|
|
18090
18191
|
// Kiro
|
|
18091
|
-
"**/.kiro/steering/",
|
|
18092
|
-
"**/.kiro/prompts/",
|
|
18093
|
-
"**/.kiro/skills/",
|
|
18094
|
-
"**/.kiro/agents/",
|
|
18095
|
-
"**/.kiro/settings/mcp.json",
|
|
18096
|
-
"**/.aiignore",
|
|
18192
|
+
{ target: "kiro", feature: "rules", entry: "**/.kiro/steering/" },
|
|
18193
|
+
{ target: "kiro", feature: "commands", entry: "**/.kiro/prompts/" },
|
|
18194
|
+
{ target: "kiro", feature: "skills", entry: "**/.kiro/skills/" },
|
|
18195
|
+
{ target: "kiro", feature: "subagents", entry: "**/.kiro/agents/" },
|
|
18196
|
+
{ target: "kiro", feature: "mcp", entry: "**/.kiro/settings/mcp.json" },
|
|
18197
|
+
{ target: "kiro", feature: "ignore", entry: "**/.aiignore" },
|
|
18097
18198
|
// OpenCode
|
|
18098
|
-
"**/.opencode/
|
|
18099
|
-
"**/.opencode/
|
|
18100
|
-
"**/.opencode/
|
|
18101
|
-
"**/.opencode/
|
|
18102
|
-
"**/.opencode/
|
|
18103
|
-
// Qwen
|
|
18104
|
-
"**/QWEN.md",
|
|
18105
|
-
"**/.qwen/memories/",
|
|
18199
|
+
{ target: "opencode", feature: "commands", entry: "**/.opencode/command/" },
|
|
18200
|
+
{ target: "opencode", feature: "subagents", entry: "**/.opencode/agent/" },
|
|
18201
|
+
{ target: "opencode", feature: "skills", entry: "**/.opencode/skill/" },
|
|
18202
|
+
{ target: "opencode", feature: "mcp", entry: "**/.opencode/plugins/" },
|
|
18203
|
+
{ target: "opencode", feature: "general", entry: "**/.opencode/memories/" },
|
|
18204
|
+
// Qwen Code
|
|
18205
|
+
{ target: "qwencode", feature: "rules", entry: "**/QWEN.md" },
|
|
18206
|
+
{ target: "qwencode", feature: "general", entry: "**/.qwen/memories/" },
|
|
18106
18207
|
// Replit
|
|
18107
|
-
"**/replit.md",
|
|
18208
|
+
{ target: "replit", feature: "rules", entry: "**/replit.md" },
|
|
18108
18209
|
// Roo
|
|
18109
|
-
"**/.roo/rules/",
|
|
18110
|
-
"**/.roo/skills/",
|
|
18111
|
-
"**/.rooignore",
|
|
18112
|
-
"**/.roo/mcp.json",
|
|
18113
|
-
"**/.roo/subagents/",
|
|
18210
|
+
{ target: "roo", feature: "rules", entry: "**/.roo/rules/" },
|
|
18211
|
+
{ target: "roo", feature: "skills", entry: "**/.roo/skills/" },
|
|
18212
|
+
{ target: "roo", feature: "ignore", entry: "**/.rooignore" },
|
|
18213
|
+
{ target: "roo", feature: "mcp", entry: "**/.roo/mcp.json" },
|
|
18214
|
+
{ target: "roo", feature: "subagents", entry: "**/.roo/subagents/" },
|
|
18114
18215
|
// Warp
|
|
18115
|
-
"**/.warp/",
|
|
18116
|
-
"**/WARP.md"
|
|
18117
|
-
// Others
|
|
18118
|
-
".rulesync/rules/*.local.md",
|
|
18119
|
-
"rulesync.local.jsonc",
|
|
18120
|
-
"!.rulesync/.aiignore"
|
|
18216
|
+
{ target: "warp", feature: "rules", entry: "**/.warp/" },
|
|
18217
|
+
{ target: "warp", feature: "rules", entry: "**/WARP.md" }
|
|
18121
18218
|
];
|
|
18219
|
+
var ALL_GITIGNORE_ENTRIES = GITIGNORE_ENTRY_REGISTRY.map(
|
|
18220
|
+
(tag) => tag.entry
|
|
18221
|
+
);
|
|
18222
|
+
var isTargetSelected = (target, selectedTargets) => {
|
|
18223
|
+
if (target === "common") return true;
|
|
18224
|
+
if (!selectedTargets || selectedTargets.length === 0) return true;
|
|
18225
|
+
if (selectedTargets.includes("*")) return true;
|
|
18226
|
+
return selectedTargets.includes(target);
|
|
18227
|
+
};
|
|
18228
|
+
var isFeatureSelected = (feature, target, features) => {
|
|
18229
|
+
if (feature === "general") return true;
|
|
18230
|
+
if (!features) return true;
|
|
18231
|
+
if (Array.isArray(features)) {
|
|
18232
|
+
if (features.length === 0) return true;
|
|
18233
|
+
if (features.includes("*")) return true;
|
|
18234
|
+
return features.includes(feature);
|
|
18235
|
+
}
|
|
18236
|
+
if (target === "common") return true;
|
|
18237
|
+
const targetFeatures = features[target];
|
|
18238
|
+
if (!targetFeatures) return true;
|
|
18239
|
+
if (targetFeatures.includes("*")) return true;
|
|
18240
|
+
return targetFeatures.includes(feature);
|
|
18241
|
+
};
|
|
18242
|
+
var warnInvalidTargets = (targets) => {
|
|
18243
|
+
const validTargets = new Set(ALL_TOOL_TARGETS_WITH_WILDCARD);
|
|
18244
|
+
for (const target of targets) {
|
|
18245
|
+
if (!validTargets.has(target)) {
|
|
18246
|
+
logger.warn(
|
|
18247
|
+
`Unknown target '${target}'. Valid targets: ${ALL_TOOL_TARGETS_WITH_WILDCARD.join(", ")}`
|
|
18248
|
+
);
|
|
18249
|
+
}
|
|
18250
|
+
}
|
|
18251
|
+
};
|
|
18252
|
+
var warnInvalidFeatures = (features) => {
|
|
18253
|
+
const validFeatures = new Set(ALL_FEATURES_WITH_WILDCARD);
|
|
18254
|
+
if (Array.isArray(features)) {
|
|
18255
|
+
for (const feature of features) {
|
|
18256
|
+
if (!validFeatures.has(feature)) {
|
|
18257
|
+
logger.warn(
|
|
18258
|
+
`Unknown feature '${feature}'. Valid features: ${ALL_FEATURES_WITH_WILDCARD.join(", ")}`
|
|
18259
|
+
);
|
|
18260
|
+
}
|
|
18261
|
+
}
|
|
18262
|
+
} else {
|
|
18263
|
+
for (const targetFeatures of Object.values(features)) {
|
|
18264
|
+
if (!targetFeatures) continue;
|
|
18265
|
+
for (const feature of targetFeatures) {
|
|
18266
|
+
if (!validFeatures.has(feature)) {
|
|
18267
|
+
logger.warn(
|
|
18268
|
+
`Unknown feature '${feature}'. Valid features: ${ALL_FEATURES_WITH_WILDCARD.join(", ")}`
|
|
18269
|
+
);
|
|
18270
|
+
}
|
|
18271
|
+
}
|
|
18272
|
+
}
|
|
18273
|
+
}
|
|
18274
|
+
};
|
|
18275
|
+
var filterGitignoreEntries = (params) => {
|
|
18276
|
+
const { targets, features } = params ?? {};
|
|
18277
|
+
if (targets && targets.length > 0) {
|
|
18278
|
+
warnInvalidTargets(targets);
|
|
18279
|
+
}
|
|
18280
|
+
if (features) {
|
|
18281
|
+
warnInvalidFeatures(features);
|
|
18282
|
+
}
|
|
18283
|
+
const seen = /* @__PURE__ */ new Set();
|
|
18284
|
+
const result = [];
|
|
18285
|
+
for (const tag of GITIGNORE_ENTRY_REGISTRY) {
|
|
18286
|
+
if (!isTargetSelected(tag.target, targets)) continue;
|
|
18287
|
+
if (!isFeatureSelected(tag.feature, tag.target, features)) continue;
|
|
18288
|
+
if (seen.has(tag.entry)) continue;
|
|
18289
|
+
seen.add(tag.entry);
|
|
18290
|
+
result.push(tag.entry);
|
|
18291
|
+
}
|
|
18292
|
+
return result;
|
|
18293
|
+
};
|
|
18294
|
+
|
|
18295
|
+
// src/cli/commands/gitignore.ts
|
|
18296
|
+
var RULESYNC_HEADER = "# Generated by Rulesync";
|
|
18297
|
+
var LEGACY_RULESYNC_HEADER = "# Generated by rulesync - AI tool configuration files";
|
|
18122
18298
|
var isRulesyncHeader = (line) => {
|
|
18123
18299
|
const trimmed = line.trim();
|
|
18124
18300
|
return trimmed === RULESYNC_HEADER || trimmed === LEGACY_RULESYNC_HEADER;
|
|
@@ -18128,7 +18304,7 @@ var isRulesyncEntry = (line) => {
|
|
|
18128
18304
|
if (trimmed === "" || isRulesyncHeader(line)) {
|
|
18129
18305
|
return false;
|
|
18130
18306
|
}
|
|
18131
|
-
return
|
|
18307
|
+
return ALL_GITIGNORE_ENTRIES.includes(trimmed);
|
|
18132
18308
|
};
|
|
18133
18309
|
var removeExistingRulesyncEntries = (content) => {
|
|
18134
18310
|
const lines = content.split("\n");
|
|
@@ -18168,37 +18344,56 @@ var removeExistingRulesyncEntries = (content) => {
|
|
|
18168
18344
|
}
|
|
18169
18345
|
return result;
|
|
18170
18346
|
};
|
|
18171
|
-
var gitignoreCommand = async () => {
|
|
18347
|
+
var gitignoreCommand = async (logger2, options) => {
|
|
18172
18348
|
const gitignorePath = (0, import_node_path121.join)(process.cwd(), ".gitignore");
|
|
18173
18349
|
let gitignoreContent = "";
|
|
18174
18350
|
if (await fileExists(gitignorePath)) {
|
|
18175
18351
|
gitignoreContent = await readFileContent(gitignorePath);
|
|
18176
18352
|
}
|
|
18177
18353
|
const cleanedContent = removeExistingRulesyncEntries(gitignoreContent);
|
|
18178
|
-
const
|
|
18354
|
+
const filteredEntries = filterGitignoreEntries({
|
|
18355
|
+
targets: options?.targets,
|
|
18356
|
+
features: options?.features
|
|
18357
|
+
});
|
|
18358
|
+
const existingEntries = new Set(
|
|
18359
|
+
gitignoreContent.split("\n").map((line) => line.trim()).filter((line) => line !== "" && !isRulesyncHeader(line))
|
|
18360
|
+
);
|
|
18361
|
+
const alreadyExistedEntries = filteredEntries.filter((entry) => existingEntries.has(entry));
|
|
18362
|
+
const entriesToAdd = filteredEntries.filter((entry) => !existingEntries.has(entry));
|
|
18363
|
+
const rulesyncBlock = [RULESYNC_HEADER, ...filteredEntries].join("\n");
|
|
18179
18364
|
const newContent = cleanedContent.trim() ? `${cleanedContent.trimEnd()}
|
|
18180
18365
|
|
|
18181
18366
|
${rulesyncBlock}
|
|
18182
18367
|
` : `${rulesyncBlock}
|
|
18183
18368
|
`;
|
|
18184
18369
|
if (gitignoreContent === newContent) {
|
|
18185
|
-
|
|
18370
|
+
if (logger2.jsonMode) {
|
|
18371
|
+
logger2.captureData("entriesAdded", []);
|
|
18372
|
+
logger2.captureData("gitignorePath", gitignorePath);
|
|
18373
|
+
logger2.captureData("alreadyExisted", filteredEntries);
|
|
18374
|
+
}
|
|
18375
|
+
logger2.success(".gitignore is already up to date");
|
|
18186
18376
|
return;
|
|
18187
18377
|
}
|
|
18188
18378
|
await writeFileContent(gitignorePath, newContent);
|
|
18189
|
-
|
|
18190
|
-
|
|
18191
|
-
|
|
18379
|
+
if (logger2.jsonMode) {
|
|
18380
|
+
logger2.captureData("entriesAdded", entriesToAdd);
|
|
18381
|
+
logger2.captureData("gitignorePath", gitignorePath);
|
|
18382
|
+
logger2.captureData("alreadyExisted", alreadyExistedEntries);
|
|
18192
18383
|
}
|
|
18193
|
-
|
|
18194
|
-
|
|
18384
|
+
logger2.success("Updated .gitignore with rulesync entries:");
|
|
18385
|
+
for (const entry of filteredEntries) {
|
|
18386
|
+
logger2.info(` ${entry}`);
|
|
18387
|
+
}
|
|
18388
|
+
logger2.info("");
|
|
18389
|
+
logger2.info(
|
|
18195
18390
|
"\u{1F4A1} If you're using Google Antigravity, note that rules, workflows, and skills won't load if they're gitignored."
|
|
18196
18391
|
);
|
|
18197
|
-
|
|
18198
|
-
|
|
18199
|
-
|
|
18200
|
-
|
|
18201
|
-
|
|
18392
|
+
logger2.info(" You can add the following to .git/info/exclude instead:");
|
|
18393
|
+
logger2.info(" **/.agent/rules/");
|
|
18394
|
+
logger2.info(" **/.agent/workflows/");
|
|
18395
|
+
logger2.info(" **/.agent/skills/");
|
|
18396
|
+
logger2.info(" For more details: https://github.com/dyoshikawa/rulesync/issues/981");
|
|
18202
18397
|
};
|
|
18203
18398
|
|
|
18204
18399
|
// src/lib/import.ts
|
|
@@ -18421,29 +18616,36 @@ async function importHooksCore(params) {
|
|
|
18421
18616
|
}
|
|
18422
18617
|
|
|
18423
18618
|
// src/cli/commands/import.ts
|
|
18424
|
-
async function importCommand(options) {
|
|
18619
|
+
async function importCommand(logger2, options) {
|
|
18425
18620
|
if (!options.targets) {
|
|
18426
|
-
|
|
18427
|
-
process.exit(1);
|
|
18621
|
+
throw new CLIError("No tools found in --targets", ErrorCodes.IMPORT_FAILED);
|
|
18428
18622
|
}
|
|
18429
18623
|
if (options.targets.length > 1) {
|
|
18430
|
-
|
|
18431
|
-
process.exit(1);
|
|
18624
|
+
throw new CLIError("Only one tool can be imported at a time", ErrorCodes.IMPORT_FAILED);
|
|
18432
18625
|
}
|
|
18433
18626
|
const config = await ConfigResolver.resolve(options);
|
|
18434
|
-
logger.configure({
|
|
18435
|
-
verbose: config.getVerbose(),
|
|
18436
|
-
silent: config.getSilent()
|
|
18437
|
-
});
|
|
18438
18627
|
const tool = config.getTargets()[0];
|
|
18439
|
-
|
|
18628
|
+
logger2.debug(`Importing files from ${tool}...`);
|
|
18440
18629
|
const result = await importFromTool({ config, tool });
|
|
18441
18630
|
const totalImported = calculateTotalCount(result);
|
|
18442
18631
|
if (totalImported === 0) {
|
|
18443
18632
|
const enabledFeatures = config.getFeatures().join(", ");
|
|
18444
|
-
|
|
18633
|
+
logger2.warn(`No files imported for enabled features: ${enabledFeatures}`);
|
|
18445
18634
|
return;
|
|
18446
18635
|
}
|
|
18636
|
+
if (logger2.jsonMode) {
|
|
18637
|
+
logger2.captureData("tool", tool);
|
|
18638
|
+
logger2.captureData("features", {
|
|
18639
|
+
rules: { count: result.rulesCount },
|
|
18640
|
+
ignore: { count: result.ignoreCount },
|
|
18641
|
+
mcp: { count: result.mcpCount },
|
|
18642
|
+
commands: { count: result.commandsCount },
|
|
18643
|
+
subagents: { count: result.subagentsCount },
|
|
18644
|
+
skills: { count: result.skillsCount },
|
|
18645
|
+
hooks: { count: result.hooksCount }
|
|
18646
|
+
});
|
|
18647
|
+
logger2.captureData("totalFiles", totalImported);
|
|
18648
|
+
}
|
|
18447
18649
|
const parts = [];
|
|
18448
18650
|
if (result.rulesCount > 0) parts.push(`${result.rulesCount} rules`);
|
|
18449
18651
|
if (result.ignoreCount > 0) parts.push(`${result.ignoreCount} ignore files`);
|
|
@@ -18452,7 +18654,7 @@ async function importCommand(options) {
|
|
|
18452
18654
|
if (result.subagentsCount > 0) parts.push(`${result.subagentsCount} subagents`);
|
|
18453
18655
|
if (result.skillsCount > 0) parts.push(`${result.skillsCount} skills`);
|
|
18454
18656
|
if (result.hooksCount > 0) parts.push(`${result.hooksCount} hooks`);
|
|
18455
|
-
|
|
18657
|
+
logger2.success(`Imported ${totalImported} file(s) total (${parts.join(" + ")})`);
|
|
18456
18658
|
}
|
|
18457
18659
|
|
|
18458
18660
|
// src/lib/init.ts
|
|
@@ -18681,28 +18883,38 @@ async function writeIfNotExists(path4, content) {
|
|
|
18681
18883
|
}
|
|
18682
18884
|
|
|
18683
18885
|
// src/cli/commands/init.ts
|
|
18684
|
-
async function initCommand() {
|
|
18685
|
-
|
|
18886
|
+
async function initCommand(logger2) {
|
|
18887
|
+
logger2.debug("Initializing rulesync...");
|
|
18686
18888
|
await ensureDir(RULESYNC_RELATIVE_DIR_PATH);
|
|
18687
18889
|
const result = await init();
|
|
18890
|
+
const createdFiles = [];
|
|
18891
|
+
const skippedFiles = [];
|
|
18688
18892
|
for (const file of result.sampleFiles) {
|
|
18689
18893
|
if (file.created) {
|
|
18690
|
-
|
|
18894
|
+
createdFiles.push(file.path);
|
|
18895
|
+
logger2.success(`Created ${file.path}`);
|
|
18691
18896
|
} else {
|
|
18692
|
-
|
|
18897
|
+
skippedFiles.push(file.path);
|
|
18898
|
+
logger2.info(`Skipped ${file.path} (already exists)`);
|
|
18693
18899
|
}
|
|
18694
18900
|
}
|
|
18695
18901
|
if (result.configFile.created) {
|
|
18696
|
-
|
|
18902
|
+
createdFiles.push(result.configFile.path);
|
|
18903
|
+
logger2.success(`Created ${result.configFile.path}`);
|
|
18697
18904
|
} else {
|
|
18698
|
-
|
|
18905
|
+
skippedFiles.push(result.configFile.path);
|
|
18906
|
+
logger2.info(`Skipped ${result.configFile.path} (already exists)`);
|
|
18699
18907
|
}
|
|
18700
|
-
|
|
18701
|
-
|
|
18702
|
-
|
|
18908
|
+
if (logger2.jsonMode) {
|
|
18909
|
+
logger2.captureData("created", createdFiles);
|
|
18910
|
+
logger2.captureData("skipped", skippedFiles);
|
|
18911
|
+
}
|
|
18912
|
+
logger2.success("rulesync initialized successfully!");
|
|
18913
|
+
logger2.info("Next steps:");
|
|
18914
|
+
logger2.info(
|
|
18703
18915
|
`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
18916
|
);
|
|
18705
|
-
|
|
18917
|
+
logger2.info("2. Run 'rulesync generate' to create configuration files");
|
|
18706
18918
|
}
|
|
18707
18919
|
|
|
18708
18920
|
// src/lib/sources.ts
|
|
@@ -19428,11 +19640,7 @@ async function fetchSourceViaGit(params) {
|
|
|
19428
19640
|
}
|
|
19429
19641
|
|
|
19430
19642
|
// src/cli/commands/install.ts
|
|
19431
|
-
async function installCommand(options) {
|
|
19432
|
-
logger.configure({
|
|
19433
|
-
verbose: options.verbose ?? false,
|
|
19434
|
-
silent: options.silent ?? false
|
|
19435
|
-
});
|
|
19643
|
+
async function installCommand(logger2, options) {
|
|
19436
19644
|
const config = await ConfigResolver.resolve({
|
|
19437
19645
|
configPath: options.configPath,
|
|
19438
19646
|
verbose: options.verbose,
|
|
@@ -19440,10 +19648,10 @@ async function installCommand(options) {
|
|
|
19440
19648
|
});
|
|
19441
19649
|
const sources = config.getSources();
|
|
19442
19650
|
if (sources.length === 0) {
|
|
19443
|
-
|
|
19651
|
+
logger2.warn("No sources defined in configuration. Nothing to install.");
|
|
19444
19652
|
return;
|
|
19445
19653
|
}
|
|
19446
|
-
|
|
19654
|
+
logger2.debug(`Installing skills from ${sources.length} source(s)...`);
|
|
19447
19655
|
const result = await resolveAndFetchSources({
|
|
19448
19656
|
sources,
|
|
19449
19657
|
baseDir: process.cwd(),
|
|
@@ -19453,12 +19661,16 @@ async function installCommand(options) {
|
|
|
19453
19661
|
token: options.token
|
|
19454
19662
|
}
|
|
19455
19663
|
});
|
|
19664
|
+
if (logger2.jsonMode) {
|
|
19665
|
+
logger2.captureData("sourcesProcessed", result.sourcesProcessed);
|
|
19666
|
+
logger2.captureData("skillsFetched", result.fetchedSkillCount);
|
|
19667
|
+
}
|
|
19456
19668
|
if (result.fetchedSkillCount > 0) {
|
|
19457
|
-
|
|
19669
|
+
logger2.success(
|
|
19458
19670
|
`Installed ${result.fetchedSkillCount} skill(s) from ${result.sourcesProcessed} source(s).`
|
|
19459
19671
|
);
|
|
19460
19672
|
} else {
|
|
19461
|
-
|
|
19673
|
+
logger2.success(`All skills up to date (${result.sourcesProcessed} source(s) checked).`);
|
|
19462
19674
|
}
|
|
19463
19675
|
}
|
|
19464
19676
|
|
|
@@ -20873,7 +21085,7 @@ var rulesyncTool = {
|
|
|
20873
21085
|
};
|
|
20874
21086
|
|
|
20875
21087
|
// src/cli/commands/mcp.ts
|
|
20876
|
-
async function mcpCommand({ version }) {
|
|
21088
|
+
async function mcpCommand(logger2, { version }) {
|
|
20877
21089
|
const server = new import_fastmcp.FastMCP({
|
|
20878
21090
|
name: "Rulesync MCP Server",
|
|
20879
21091
|
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
@@ -20881,7 +21093,7 @@ async function mcpCommand({ version }) {
|
|
|
20881
21093
|
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
21094
|
});
|
|
20883
21095
|
server.addTool(rulesyncTool);
|
|
20884
|
-
|
|
21096
|
+
logger2.info("Rulesync MCP server started via stdio");
|
|
20885
21097
|
void server.start({
|
|
20886
21098
|
transportType: "stdio"
|
|
20887
21099
|
});
|
|
@@ -21197,158 +21409,182 @@ To upgrade, run:
|
|
|
21197
21409
|
}
|
|
21198
21410
|
|
|
21199
21411
|
// src/cli/commands/update.ts
|
|
21200
|
-
async function updateCommand(currentVersion, options) {
|
|
21201
|
-
const { check = false, force = false,
|
|
21202
|
-
logger.configure({ verbose, silent });
|
|
21412
|
+
async function updateCommand(logger2, currentVersion, options) {
|
|
21413
|
+
const { check = false, force = false, token } = options;
|
|
21203
21414
|
try {
|
|
21204
21415
|
const environment = detectExecutionEnvironment();
|
|
21205
|
-
|
|
21416
|
+
logger2.debug(`Detected environment: ${environment}`);
|
|
21206
21417
|
if (environment === "npm") {
|
|
21207
|
-
|
|
21418
|
+
logger2.info(getNpmUpgradeInstructions());
|
|
21208
21419
|
return;
|
|
21209
21420
|
}
|
|
21210
21421
|
if (environment === "homebrew") {
|
|
21211
|
-
|
|
21422
|
+
logger2.info(getHomebrewUpgradeInstructions());
|
|
21212
21423
|
return;
|
|
21213
21424
|
}
|
|
21214
21425
|
if (check) {
|
|
21215
|
-
|
|
21426
|
+
logger2.info("Checking for updates...");
|
|
21216
21427
|
const updateCheck = await checkForUpdate(currentVersion, token);
|
|
21428
|
+
if (logger2.jsonMode) {
|
|
21429
|
+
logger2.captureData("currentVersion", updateCheck.currentVersion);
|
|
21430
|
+
logger2.captureData("latestVersion", updateCheck.latestVersion);
|
|
21431
|
+
logger2.captureData("updateAvailable", updateCheck.hasUpdate);
|
|
21432
|
+
logger2.captureData(
|
|
21433
|
+
"message",
|
|
21434
|
+
updateCheck.hasUpdate ? `Update available: ${updateCheck.currentVersion} -> ${updateCheck.latestVersion}` : `Already at the latest version (${updateCheck.currentVersion})`
|
|
21435
|
+
);
|
|
21436
|
+
}
|
|
21217
21437
|
if (updateCheck.hasUpdate) {
|
|
21218
|
-
|
|
21438
|
+
logger2.success(
|
|
21219
21439
|
`Update available: ${updateCheck.currentVersion} -> ${updateCheck.latestVersion}`
|
|
21220
21440
|
);
|
|
21221
21441
|
} else {
|
|
21222
|
-
|
|
21442
|
+
logger2.info(`Already at the latest version (${updateCheck.currentVersion})`);
|
|
21223
21443
|
}
|
|
21224
21444
|
return;
|
|
21225
21445
|
}
|
|
21226
|
-
|
|
21446
|
+
logger2.info("Checking for updates...");
|
|
21227
21447
|
const message = await performBinaryUpdate(currentVersion, { force, token });
|
|
21228
|
-
|
|
21448
|
+
logger2.success(message);
|
|
21229
21449
|
} catch (error) {
|
|
21230
21450
|
if (error instanceof GitHubClientError) {
|
|
21231
|
-
|
|
21451
|
+
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 ...`" : "";
|
|
21452
|
+
throw new CLIError(
|
|
21453
|
+
`GitHub API Error: ${error.message}.${authHint}`,
|
|
21454
|
+
ErrorCodes.UPDATE_FAILED
|
|
21455
|
+
);
|
|
21232
21456
|
} else if (error instanceof UpdatePermissionError) {
|
|
21233
|
-
|
|
21234
|
-
|
|
21235
|
-
|
|
21236
|
-
|
|
21457
|
+
throw new CLIError(
|
|
21458
|
+
`${error.message} Tip: Run with elevated privileges (e.g., sudo rulesync update)`,
|
|
21459
|
+
ErrorCodes.UPDATE_FAILED
|
|
21460
|
+
);
|
|
21237
21461
|
}
|
|
21238
|
-
|
|
21462
|
+
throw error;
|
|
21239
21463
|
}
|
|
21240
21464
|
}
|
|
21241
21465
|
|
|
21242
21466
|
// src/cli/index.ts
|
|
21243
|
-
var getVersion = () => "7.
|
|
21467
|
+
var getVersion = () => "7.20.0";
|
|
21468
|
+
function wrapCommand(name, errorCode, handler) {
|
|
21469
|
+
return async (...args) => {
|
|
21470
|
+
const command = args[args.length - 1];
|
|
21471
|
+
const options = args[args.length - 2];
|
|
21472
|
+
const positionalArgs = args.slice(0, -2);
|
|
21473
|
+
const globalOpts = command.parent?.opts() ?? {};
|
|
21474
|
+
const logger2 = globalOpts.json ? new JsonLogger({ command: name, version: getVersion() }) : new ConsoleLogger();
|
|
21475
|
+
logger2.configure({
|
|
21476
|
+
verbose: Boolean(globalOpts.verbose) || Boolean(options.verbose),
|
|
21477
|
+
silent: Boolean(globalOpts.silent) || Boolean(options.silent)
|
|
21478
|
+
});
|
|
21479
|
+
try {
|
|
21480
|
+
await handler(logger2, options, globalOpts, positionalArgs);
|
|
21481
|
+
logger2.outputJson(true);
|
|
21482
|
+
} catch (error) {
|
|
21483
|
+
const code = error instanceof CLIError ? error.code : errorCode;
|
|
21484
|
+
const errorArg = error instanceof Error ? error : formatError(error);
|
|
21485
|
+
logger2.error(errorArg, code);
|
|
21486
|
+
process.exit(error instanceof CLIError ? error.exitCode : 1);
|
|
21487
|
+
}
|
|
21488
|
+
};
|
|
21489
|
+
}
|
|
21244
21490
|
var main = async () => {
|
|
21245
21491
|
const program = new import_commander.Command();
|
|
21246
21492
|
const version = getVersion();
|
|
21247
|
-
program.
|
|
21248
|
-
|
|
21249
|
-
|
|
21493
|
+
program.name("rulesync").description("Unified AI rules management CLI tool").version(version, "-v, --version", "Show version").option("-j, --json", "Output results as JSON");
|
|
21494
|
+
program.command("init").description("Initialize rulesync in current directory").option("-V, --verbose", "Verbose output").option("-s, --silent", "Suppress all output").action(
|
|
21495
|
+
wrapCommand("init", "INIT_FAILED", async (logger2) => {
|
|
21496
|
+
await initCommand(logger2);
|
|
21497
|
+
})
|
|
21498
|
+
);
|
|
21499
|
+
program.command("gitignore").description("Add generated files to .gitignore").option(
|
|
21500
|
+
"-t, --targets <tools>",
|
|
21501
|
+
"Comma-separated list of tools to include (e.g., 'claudecode,copilot' or '*' for all)",
|
|
21502
|
+
(value) => {
|
|
21503
|
+
return value.split(",").map((t) => t.trim()).filter(Boolean);
|
|
21250
21504
|
}
|
|
21251
|
-
|
|
21252
|
-
|
|
21253
|
-
|
|
21254
|
-
|
|
21505
|
+
).option(
|
|
21506
|
+
"-f, --features <features>",
|
|
21507
|
+
`Comma-separated list of features to include (${ALL_FEATURES.join(",")}) or '*' for all`,
|
|
21508
|
+
(value) => {
|
|
21509
|
+
return value.split(",").map((f) => f.trim()).filter(Boolean);
|
|
21510
|
+
}
|
|
21511
|
+
).option("-V, --verbose", "Verbose output").option("-s, --silent", "Suppress all output").action(
|
|
21512
|
+
wrapCommand("gitignore", "GITIGNORE_FAILED", async (logger2, options) => {
|
|
21513
|
+
await gitignoreCommand(logger2, {
|
|
21514
|
+
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
21515
|
+
targets: options.targets,
|
|
21516
|
+
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
21517
|
+
features: options.features
|
|
21518
|
+
});
|
|
21519
|
+
})
|
|
21520
|
+
);
|
|
21255
21521
|
program.command("fetch <source>").description("Fetch files from a Git repository (GitHub/GitLab)").option(
|
|
21256
21522
|
"-t, --target <target>",
|
|
21257
21523
|
"Target format to interpret files as (e.g., 'rulesync', 'claudecode'). Default: rulesync"
|
|
21258
21524
|
).option(
|
|
21259
21525
|
"-f, --features <features>",
|
|
21260
21526
|
`Comma-separated list of features to fetch (${ALL_FEATURES.join(",")}) or '*' for all`,
|
|
21261
|
-
(value) =>
|
|
21262
|
-
return value.split(",").map((f) => f.trim());
|
|
21263
|
-
}
|
|
21527
|
+
(value) => value.split(",").map((f) => f.trim())
|
|
21264
21528
|
).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
21529
|
"-c, --conflict <strategy>",
|
|
21266
21530
|
"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
|
-
});
|
|
21531
|
+
).option("--token <token>", "Git provider token for private repositories").option("-V, --verbose", "Verbose output").option("-s, --silent", "Suppress all output").action(
|
|
21532
|
+
wrapCommand("fetch", "FETCH_FAILED", async (logger2, options, _globalOpts, positionalArgs) => {
|
|
21533
|
+
const source = positionalArgs[0];
|
|
21534
|
+
await fetchCommand(logger2, { ...options, source });
|
|
21535
|
+
})
|
|
21536
|
+
);
|
|
21281
21537
|
program.command("import").description("Import configurations from AI tools to rulesync format").option(
|
|
21282
21538
|
"-t, --targets <tool>",
|
|
21283
21539
|
"Tool to import from (e.g., 'copilot', 'cursor', 'cline')",
|
|
21284
|
-
(value) =>
|
|
21285
|
-
return value.split(",").map((t) => t.trim());
|
|
21286
|
-
}
|
|
21540
|
+
(value) => value.split(",").map((t) => t.trim())
|
|
21287
21541
|
).option(
|
|
21288
21542
|
"-f, --features <features>",
|
|
21289
21543
|
`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
|
-
});
|
|
21544
|
+
(value) => value.split(",").map((f) => f.trim())
|
|
21545
|
+
).option("-V, --verbose", "Verbose output").option("-s, --silent", "Suppress all output").option("-g, --global", "Import for global(user scope) configuration files").action(
|
|
21546
|
+
wrapCommand("import", "IMPORT_FAILED", async (logger2, options) => {
|
|
21547
|
+
await importCommand(logger2, options);
|
|
21548
|
+
})
|
|
21549
|
+
);
|
|
21550
|
+
program.command("mcp").description("Start MCP server for rulesync").action(
|
|
21551
|
+
wrapCommand("mcp", "MCP_FAILED", async (logger2, _options) => {
|
|
21552
|
+
await mcpCommand(logger2, { version });
|
|
21553
|
+
})
|
|
21554
|
+
);
|
|
21316
21555
|
program.command("install").description("Install skills from declarative sources in rulesync.jsonc").option("--update", "Force re-resolve all source refs, ignoring lockfile").option(
|
|
21317
21556
|
"--frozen",
|
|
21318
21557
|
"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({
|
|
21558
|
+
).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(
|
|
21559
|
+
wrapCommand("install", "INSTALL_FAILED", async (logger2, options) => {
|
|
21560
|
+
await installCommand(logger2, {
|
|
21561
|
+
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
21322
21562
|
update: options.update,
|
|
21563
|
+
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
21323
21564
|
frozen: options.frozen,
|
|
21565
|
+
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
21324
21566
|
token: options.token,
|
|
21567
|
+
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
21325
21568
|
configPath: options.config,
|
|
21569
|
+
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
21326
21570
|
verbose: options.verbose,
|
|
21571
|
+
// eslint-disable-next-line no-type-assertion/no-type-assertion
|
|
21327
21572
|
silent: options.silent
|
|
21328
21573
|
});
|
|
21329
|
-
}
|
|
21330
|
-
|
|
21331
|
-
process.exit(1);
|
|
21332
|
-
}
|
|
21333
|
-
});
|
|
21574
|
+
})
|
|
21575
|
+
);
|
|
21334
21576
|
program.command("generate").description("Generate configuration files for AI tools").option(
|
|
21335
21577
|
"-t, --targets <tools>",
|
|
21336
21578
|
"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
|
-
}
|
|
21579
|
+
(value) => value.split(",").map((t) => t.trim())
|
|
21340
21580
|
).option(
|
|
21341
21581
|
"-f, --features <features>",
|
|
21342
21582
|
`Comma-separated list of features to generate (${ALL_FEATURES.join(",")}) or '*' for all`,
|
|
21343
|
-
(value) =>
|
|
21344
|
-
return value.split(",").map((f) => f.trim());
|
|
21345
|
-
}
|
|
21583
|
+
(value) => value.split(",").map((f) => f.trim())
|
|
21346
21584
|
).option("--delete", "Delete all existing files in output directories before generating").option(
|
|
21347
21585
|
"-b, --base-dir <paths>",
|
|
21348
21586
|
"Base directories to generate files (comma-separated for multiple paths)",
|
|
21349
|
-
(value) =>
|
|
21350
|
-
return value.split(",").map((p) => p.trim());
|
|
21351
|
-
}
|
|
21587
|
+
(value) => value.split(",").map((p) => p.trim())
|
|
21352
21588
|
).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
21589
|
"--simulate-commands",
|
|
21354
21590
|
"Generate simulated commands. This feature is only available for copilot, cursor and codexcli."
|
|
@@ -21358,40 +21594,19 @@ var main = async () => {
|
|
|
21358
21594
|
).option(
|
|
21359
21595
|
"--simulate-skills",
|
|
21360
21596
|
"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
|
-
});
|
|
21597
|
+
).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(
|
|
21598
|
+
wrapCommand("generate", "GENERATION_FAILED", async (logger2, options) => {
|
|
21599
|
+
await generateCommand(logger2, options);
|
|
21600
|
+
})
|
|
21601
|
+
);
|
|
21602
|
+
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(
|
|
21603
|
+
wrapCommand("update", "UPDATE_FAILED", async (logger2, options) => {
|
|
21604
|
+
await updateCommand(logger2, version, options);
|
|
21605
|
+
})
|
|
21606
|
+
);
|
|
21392
21607
|
program.parse();
|
|
21393
21608
|
};
|
|
21394
21609
|
main().catch((error) => {
|
|
21395
|
-
|
|
21610
|
+
console.error(formatError(error));
|
|
21396
21611
|
process.exit(1);
|
|
21397
21612
|
});
|