@hanzlaa/rcode 3.4.25 → 3.4.27
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/cli/install.js +22 -5
- package/cli/postinstall.js +40 -26
- package/cli/uninstall.js +35 -15
- package/cli/update.js +4 -0
- package/dist/rcode.js +275 -265
- package/package.json +1 -1
package/cli/install.js
CHANGED
|
@@ -57,7 +57,7 @@ const os = require('os');
|
|
|
57
57
|
|
|
58
58
|
// Atomic write helper (#687) + symlink-safe rmSync (#688) — protect against
|
|
59
59
|
// Ctrl+C mid-write and malicious symlink-traversal during dedup/cleanup.
|
|
60
|
-
const { writeFileAtomic, safeRmSync } = require(
|
|
60
|
+
const { writeFileAtomic, safeRmSync } = require('./lib/fsutil.cjs');
|
|
61
61
|
|
|
62
62
|
// Bundled packages — devDeps inlined by esbuild, loaded from node_modules in dev.
|
|
63
63
|
const pc = require('picocolors');
|
|
@@ -79,6 +79,18 @@ const bold = (s) => pc.bold(s);
|
|
|
79
79
|
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
80
80
|
const SOURCE_ROOT = path.join(PACKAGE_ROOT, 'rihal');
|
|
81
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Single source of truth for supported IDEs (#697 — W4.3).
|
|
84
|
+
*
|
|
85
|
+
* Order matters: this is the order used in detection, prompts, and error
|
|
86
|
+
* messages. Anywhere code used to inline `['claude','cursor','gemini',
|
|
87
|
+
* 'vscode','antigravity']` it now references this constant. Adding a new
|
|
88
|
+
* IDE is now: append here, add a case to getPathsForIde, add a signal to
|
|
89
|
+
* detectIdeSignals, plus a row to runInstallWizard's multiselect — three
|
|
90
|
+
* sites instead of ten.
|
|
91
|
+
*/
|
|
92
|
+
const SUPPORTED_IDES = Object.freeze(['claude', 'cursor', 'gemini', 'vscode', 'antigravity']);
|
|
93
|
+
|
|
82
94
|
// Zod schema for .rihal/config.yaml validation (#250).
|
|
83
95
|
const ConfigSchema = z.object({
|
|
84
96
|
user_name: z.string().min(1),
|
|
@@ -338,12 +350,16 @@ async function resolveIde(opts) {
|
|
|
338
350
|
// nothing detected. (Note: opts.ide defaults to 'claude' from parseArgs,
|
|
339
351
|
// so check opts.ideProvided not opts.ide to honor real --ide overrides.)
|
|
340
352
|
const signals = detectIdeSignals(opts.target);
|
|
341
|
-
const detected =
|
|
353
|
+
const detected = SUPPORTED_IDES.filter(k => signals[k]);
|
|
342
354
|
return detected.length > 0 ? detected : ['claude'];
|
|
343
355
|
}
|
|
344
356
|
|
|
345
357
|
const signals = detectIdeSignals(opts.target);
|
|
346
|
-
|
|
358
|
+
// Antigravity is intentionally excluded from the interactive auto-detect
|
|
359
|
+
// because it's experimental and we don't want to opt-in users without
|
|
360
|
+
// explicit consent. Use SUPPORTED_IDES.filter(k => k !== 'antigravity')
|
|
361
|
+
// to keep the inclusion criteria self-documenting.
|
|
362
|
+
const detected = SUPPORTED_IDES.filter(k => k !== 'antigravity' && signals[k]);
|
|
347
363
|
|
|
348
364
|
// Pre-select detected IDEs, or default to claude
|
|
349
365
|
const initialValues = detected.length > 0 ? detected : ['claude'];
|
|
@@ -1613,7 +1629,7 @@ async function installInner(opts) {
|
|
|
1613
1629
|
}
|
|
1614
1630
|
|
|
1615
1631
|
// Validate IDE(s) — structured error for unsupported editors (#197).
|
|
1616
|
-
|
|
1632
|
+
// SUPPORTED_IDES is the module-level constant (#697 / W4.3).
|
|
1617
1633
|
const unsupported = opts.ides.filter(ide => !SUPPORTED_IDES.includes(ide));
|
|
1618
1634
|
if (unsupported.length > 0) {
|
|
1619
1635
|
console.error(`✖ --ide ${unsupported.join(', ')} is not supported in v${readPackageVersion()}.`);
|
|
@@ -2359,7 +2375,7 @@ function runInstallHealthCheck(target, counts) {
|
|
|
2359
2375
|
// in cli/lib/manifest.cjs already does this; we mirror its result here.
|
|
2360
2376
|
let expected = { agents: 20, skills: 20, commands: 20 };
|
|
2361
2377
|
try {
|
|
2362
|
-
const { readPackageManifest } = require(
|
|
2378
|
+
const { readPackageManifest } = require('./lib/manifest.cjs');
|
|
2363
2379
|
const pkgManifest = readPackageManifest(PACKAGE_ROOT);
|
|
2364
2380
|
if (pkgManifest && pkgManifest.agents instanceof Set && pkgManifest.actions instanceof Set) {
|
|
2365
2381
|
// Tolerate ~10% loss vs source — global precedence, .local.md
|
|
@@ -2597,3 +2613,4 @@ module.exports = runFromCli;
|
|
|
2597
2613
|
module.exports.parseArgs = parseArgs;
|
|
2598
2614
|
module.exports.buildInstallPlan = buildInstallPlan;
|
|
2599
2615
|
module.exports.install = install;
|
|
2616
|
+
module.exports.SUPPORTED_IDES = SUPPORTED_IDES;
|
package/cli/postinstall.js
CHANGED
|
@@ -13,42 +13,52 @@
|
|
|
13
13
|
const os = require('os');
|
|
14
14
|
const path = require('path');
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Decide whether the current postinstall invocation represents a GLOBAL
|
|
18
|
+
* `npm install -g @hanzlaa/rcode` (true) or a transitive devDep install
|
|
19
|
+
* inside someone's project (false).
|
|
20
|
+
*
|
|
21
|
+
* Pure function — takes its inputs explicitly so tests can drive every
|
|
22
|
+
* branch without needing to mutate process.env / __dirname / process.cwd.
|
|
23
|
+
*
|
|
24
|
+
* @param {object} env process.env-like
|
|
25
|
+
* @param {string} dirname __dirname of the postinstall script
|
|
26
|
+
* @param {string} cwd process.cwd() at invocation time
|
|
27
|
+
*/
|
|
28
|
+
function isGlobalInstall(env, dirname, cwd) {
|
|
24
29
|
try {
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
// pnpm sets npm_config_global too, but check PNPM_HOME as a fallback
|
|
28
|
-
if (process.env.PNPM_HOME && __dirname.startsWith(process.env.PNPM_HOME)) return true;
|
|
29
|
-
// Check if __dirname is inside a known global node_modules path.
|
|
30
|
-
// Covers: /usr/local/lib, /usr/lib, ~/.nvm/.../lib, ~/.pnpm/..., ~/.yarn/...
|
|
30
|
+
if (env.npm_config_global === 'true') return true;
|
|
31
|
+
if (env.PNPM_HOME && dirname.startsWith(env.PNPM_HOME)) return true;
|
|
31
32
|
const globalPatterns = [
|
|
32
|
-
/\/node_modules\/@hanzlaa\/rcode/,
|
|
33
|
-
/[/\\]lib[/\\]node_modules[/\\]/,
|
|
34
|
-
/\.nvm[/\\]versions[/\\]/,
|
|
35
|
-
/\.pnpm[/\\]/,
|
|
36
|
-
/\.yarn[/\\]global/,
|
|
33
|
+
/\/node_modules\/@hanzlaa\/rcode/,
|
|
34
|
+
/[/\\]lib[/\\]node_modules[/\\]/,
|
|
35
|
+
/\.nvm[/\\]versions[/\\]/,
|
|
36
|
+
/\.pnpm[/\\]/,
|
|
37
|
+
/\.yarn[/\\]global/,
|
|
37
38
|
];
|
|
38
|
-
if (globalPatterns.some((re) => re.test(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const localNodeModules = path.join(process.cwd(), 'node_modules');
|
|
42
|
-
if (!__dirname.startsWith(localNodeModules)) return true;
|
|
39
|
+
if (globalPatterns.some((re) => re.test(dirname))) return true;
|
|
40
|
+
const localNodeModules = path.join(cwd, 'node_modules');
|
|
41
|
+
if (!dirname.startsWith(localNodeModules)) return true;
|
|
43
42
|
return false;
|
|
44
43
|
} catch {
|
|
45
44
|
return false;
|
|
46
45
|
}
|
|
47
|
-
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Skip in CI or test environments. Tests that import this module bypass
|
|
49
|
+
// the top-level effect by checking require.main !== module.
|
|
50
|
+
if (require.main === module) {
|
|
51
|
+
if (process.env.CI || process.env.NODE_ENV === 'test') {
|
|
52
|
+
process.exit(0);
|
|
53
|
+
}
|
|
54
|
+
runPostInstall();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function runPostInstall() {
|
|
48
58
|
|
|
49
59
|
const globalTarget = path.join(os.homedir(), '.claude');
|
|
50
60
|
|
|
51
|
-
if (isGlobalInstall) {
|
|
61
|
+
if (isGlobalInstall(process.env, __dirname, process.cwd())) {
|
|
52
62
|
// Spawn dist/rcode.js (fully bundled — no devDep requires) to do the global
|
|
53
63
|
// install. Calling cli/install.js directly fails in global npm installs because
|
|
54
64
|
// devDependencies (picocolors, semver, etc.) are not installed for global packages.
|
|
@@ -101,3 +111,7 @@ More:
|
|
|
101
111
|
Docs: https://github.com/hanzlahabib/rihal-code
|
|
102
112
|
`);
|
|
103
113
|
}
|
|
114
|
+
|
|
115
|
+
} // end runPostInstall
|
|
116
|
+
|
|
117
|
+
module.exports = { isGlobalInstall };
|
package/cli/uninstall.js
CHANGED
|
@@ -68,6 +68,25 @@ function isLocalOverride(name) {
|
|
|
68
68
|
return /\.local\.(md|mdc|json|yaml|yml|toml|js|ts)$/.test(name);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Strip the rcode-managed block from a .gitignore string.
|
|
73
|
+
*
|
|
74
|
+
* Pure function (no fs) so it can be unit-tested independently. Issue #684
|
|
75
|
+
* fixed the over-broad legacy regex; this helper centralises the logic so
|
|
76
|
+
* any future shape change has exactly one site to update.
|
|
77
|
+
*
|
|
78
|
+
* Both supported shapes require BOTH the opener AND the closer to match —
|
|
79
|
+
* user comments starting with "# rcode" are safe.
|
|
80
|
+
*/
|
|
81
|
+
function stripRihalGitignoreBlock(text) {
|
|
82
|
+
return text
|
|
83
|
+
// Current shape (install.js BEGIN/END markers — exact match).
|
|
84
|
+
.replace(/\n?# ===== rcode-managed gitignore block[\s\S]*?# ===== end rcode-managed gitignore block =====\n?/g, '\n')
|
|
85
|
+
// Legacy >>> / <<< fenced shape.
|
|
86
|
+
.replace(/\n?# >>> rihal-code >>>[\s\S]*?# <<< rihal-code <<<\n?/g, '\n')
|
|
87
|
+
.replace(/\n{3,}/g, '\n\n');
|
|
88
|
+
}
|
|
89
|
+
|
|
71
90
|
/**
|
|
72
91
|
* Walk a directory and remove all files/subdirs whose name matches a predicate.
|
|
73
92
|
* Returns the number of entries removed. Always skips local overrides (#382).
|
|
@@ -230,7 +249,7 @@ function buildPlan(cwd, editors) {
|
|
|
230
249
|
*/
|
|
231
250
|
function discoverKnownActionSkills() {
|
|
232
251
|
try {
|
|
233
|
-
const { readPackageManifest } = require(
|
|
252
|
+
const { readPackageManifest } = require('./lib/manifest.cjs');
|
|
234
253
|
const packageRoot = path.resolve(__dirname, '..');
|
|
235
254
|
const pkg = readPackageManifest(packageRoot);
|
|
236
255
|
if (pkg && pkg.actions instanceof Set && pkg.actions.size > 0) {
|
|
@@ -419,15 +438,13 @@ async function runUninstall(args) {
|
|
|
419
438
|
const opts = parseArgs(args);
|
|
420
439
|
const cwd = process.cwd();
|
|
421
440
|
|
|
422
|
-
// Issue #693: keep the IDE list in sync with the installer
|
|
423
|
-
//
|
|
424
|
-
//
|
|
425
|
-
|
|
426
|
-
// user with vscode-style commands could never `rcode uninstall`.
|
|
427
|
-
const SUPPORTED_EDITORS = ['claude', 'cursor', 'gemini', 'vscode', 'antigravity'];
|
|
441
|
+
// Issue #693 + #697 (W4.3): keep the IDE list in sync with the installer
|
|
442
|
+
// by importing the single source of truth. Adding an IDE to install.js
|
|
443
|
+
// SUPPORTED_IDES is now the only edit needed for parity.
|
|
444
|
+
const { SUPPORTED_IDES } = require('./install.js');
|
|
428
445
|
const editors = opts.editor
|
|
429
|
-
? (opts.editor === 'all' ?
|
|
430
|
-
:
|
|
446
|
+
? (opts.editor === 'all' ? Array.from(SUPPORTED_IDES) : [opts.editor])
|
|
447
|
+
: Array.from(SUPPORTED_IDES);
|
|
431
448
|
|
|
432
449
|
console.log(`\n🕌 Rihal Code — Uninstall\n`);
|
|
433
450
|
console.log(` Project: ${cwd}`);
|
|
@@ -731,12 +748,7 @@ async function runUninstall(args) {
|
|
|
731
748
|
if (fs.existsSync(gitignorePath)) {
|
|
732
749
|
try {
|
|
733
750
|
const before = fs.readFileSync(gitignorePath, 'utf8');
|
|
734
|
-
const stripped = before
|
|
735
|
-
// Current shape (install.js BEGIN/END markers — exact match).
|
|
736
|
-
.replace(/\n?# ===== rcode-managed gitignore block[\s\S]*?# ===== end rcode-managed gitignore block =====\n?/g, '\n')
|
|
737
|
-
// Legacy >>> / <<< fenced shape.
|
|
738
|
-
.replace(/\n?# >>> rihal-code >>>[\s\S]*?# <<< rihal-code <<<\n?/g, '\n')
|
|
739
|
-
.replace(/\n{3,}/g, '\n\n');
|
|
751
|
+
const stripped = stripRihalGitignoreBlock(before);
|
|
740
752
|
if (stripped !== before) {
|
|
741
753
|
fs.writeFileSync(gitignorePath, stripped);
|
|
742
754
|
console.log(` ✓ stripped rcode block from .gitignore (--purge)`);
|
|
@@ -773,6 +785,14 @@ async function runUninstall(args) {
|
|
|
773
785
|
console.log(` rcode install`);
|
|
774
786
|
}
|
|
775
787
|
|
|
788
|
+
// Re-exports for unit tests (W3.2 — issue #694 follow-up). The default
|
|
789
|
+
// export remains the async runner; these are attached afterwards so pure
|
|
790
|
+
// functions can be exercised without spawning a child process.
|
|
791
|
+
module.exports.isLocalOverride = isLocalOverride;
|
|
792
|
+
module.exports.planToPathList = planToPathList;
|
|
793
|
+
module.exports.discoverKnownActionSkills = discoverKnownActionSkills;
|
|
794
|
+
module.exports.stripRihalGitignoreBlock = stripRihalGitignoreBlock;
|
|
795
|
+
|
|
776
796
|
// Direct invocation — allow `node cli/uninstall.js [flags]` to run end-to-end.
|
|
777
797
|
// When called via cli/index.js, module.exports is invoked directly.
|
|
778
798
|
if (require.main === module) {
|
package/cli/update.js
CHANGED
|
@@ -383,3 +383,7 @@ async function runUpdate(args, { packageRoot, packageJson }) {
|
|
|
383
383
|
}
|
|
384
384
|
console.log();
|
|
385
385
|
}
|
|
386
|
+
|
|
387
|
+
// Re-exports for unit tests (W3.4 — issue #694 follow-up).
|
|
388
|
+
module.exports.parseArgs = parseArgs;
|
|
389
|
+
module.exports.detectInstalledEditors = detectInstalledEditors;
|
package/dist/rcode.js
CHANGED
|
@@ -5,6 +5,88 @@ var __commonJS = (cb, mod) => function __require() {
|
|
|
5
5
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
+
// cli/lib/fsutil.cjs
|
|
9
|
+
var require_fsutil = __commonJS({
|
|
10
|
+
"cli/lib/fsutil.cjs"(exports2, module2) {
|
|
11
|
+
var crypto = require("crypto");
|
|
12
|
+
var fs2 = require("fs");
|
|
13
|
+
var path2 = require("path");
|
|
14
|
+
function writeFileAtomic(filePath, content, opts = {}) {
|
|
15
|
+
const { encoding = "utf8", mode } = opts;
|
|
16
|
+
const dir = path2.dirname(filePath);
|
|
17
|
+
fs2.mkdirSync(dir, { recursive: true });
|
|
18
|
+
const tmpPath = path2.join(
|
|
19
|
+
dir,
|
|
20
|
+
`.${path2.basename(filePath)}.tmp-${process.pid}-${crypto.randomBytes(8).toString("hex")}`
|
|
21
|
+
);
|
|
22
|
+
let fd;
|
|
23
|
+
try {
|
|
24
|
+
fd = fs2.openSync(tmpPath, "wx", mode ?? 420);
|
|
25
|
+
fs2.writeSync(fd, content, 0, encoding);
|
|
26
|
+
fs2.fsyncSync(fd);
|
|
27
|
+
fs2.closeSync(fd);
|
|
28
|
+
fd = null;
|
|
29
|
+
fs2.renameSync(tmpPath, filePath);
|
|
30
|
+
} catch (err) {
|
|
31
|
+
if (fd !== null && fd !== void 0) {
|
|
32
|
+
try {
|
|
33
|
+
fs2.closeSync(fd);
|
|
34
|
+
} catch {
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
fs2.unlinkSync(tmpPath);
|
|
39
|
+
} catch {
|
|
40
|
+
}
|
|
41
|
+
throw err;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function writeJsonAtomic(filePath, obj, opts = {}) {
|
|
45
|
+
const content = JSON.stringify(obj, null, 2) + "\n";
|
|
46
|
+
writeFileAtomic(filePath, content, opts);
|
|
47
|
+
}
|
|
48
|
+
function safeRmSync(targetPath, projectRoot) {
|
|
49
|
+
let stats;
|
|
50
|
+
try {
|
|
51
|
+
stats = fs2.lstatSync(targetPath);
|
|
52
|
+
} catch (err) {
|
|
53
|
+
if (err.code === "ENOENT") return { ok: true, reason: "missing" };
|
|
54
|
+
return { ok: false, reason: `lstat: ${err.message}` };
|
|
55
|
+
}
|
|
56
|
+
if (stats.isSymbolicLink()) {
|
|
57
|
+
try {
|
|
58
|
+
fs2.unlinkSync(targetPath);
|
|
59
|
+
return { ok: true, reason: "symlink-unlinked" };
|
|
60
|
+
} catch (err) {
|
|
61
|
+
return { ok: false, reason: `unlink: ${err.message}` };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const root = path2.resolve(projectRoot);
|
|
65
|
+
let resolved;
|
|
66
|
+
try {
|
|
67
|
+
resolved = fs2.realpathSync(targetPath);
|
|
68
|
+
} catch (err) {
|
|
69
|
+
return { ok: false, reason: `realpath: ${err.message}` };
|
|
70
|
+
}
|
|
71
|
+
const relative = path2.relative(root, resolved);
|
|
72
|
+
if (relative.startsWith("..") || path2.isAbsolute(relative)) {
|
|
73
|
+
return { ok: false, reason: "outside-root" };
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
fs2.rmSync(resolved, { recursive: true, force: true });
|
|
77
|
+
return { ok: true };
|
|
78
|
+
} catch (err) {
|
|
79
|
+
return { ok: false, reason: `rmSync: ${err.message}` };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
module2.exports = {
|
|
83
|
+
writeFileAtomic,
|
|
84
|
+
writeJsonAtomic,
|
|
85
|
+
safeRmSync
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
8
90
|
// node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js
|
|
9
91
|
var require_picocolors = __commonJS({
|
|
10
92
|
"node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js"(exports2, module2) {
|
|
@@ -14939,6 +15021,180 @@ ${e__default.gray(d)} ${t}
|
|
|
14939
15021
|
}
|
|
14940
15022
|
});
|
|
14941
15023
|
|
|
15024
|
+
// cli/lib/manifest.cjs
|
|
15025
|
+
var require_manifest = __commonJS({
|
|
15026
|
+
"cli/lib/manifest.cjs"(exports2, module2) {
|
|
15027
|
+
var fs2 = require("fs");
|
|
15028
|
+
var path2 = require("path");
|
|
15029
|
+
function readPackageManifest(packageRoot) {
|
|
15030
|
+
const skillsRoot = path2.join(packageRoot, "rihal/skills");
|
|
15031
|
+
const manifest = { agents: /* @__PURE__ */ new Set(), actions: /* @__PURE__ */ new Set() };
|
|
15032
|
+
const agentsDir = path2.join(skillsRoot, "agents");
|
|
15033
|
+
if (fs2.existsSync(agentsDir)) {
|
|
15034
|
+
for (const entry of fs2.readdirSync(agentsDir, { withFileTypes: true })) {
|
|
15035
|
+
if (entry.isDirectory()) manifest.agents.add(entry.name);
|
|
15036
|
+
}
|
|
15037
|
+
}
|
|
15038
|
+
function walkActions(dir) {
|
|
15039
|
+
if (!fs2.existsSync(dir)) return;
|
|
15040
|
+
for (const entry of fs2.readdirSync(dir, { withFileTypes: true })) {
|
|
15041
|
+
if (!entry.isDirectory()) continue;
|
|
15042
|
+
const full = path2.join(dir, entry.name);
|
|
15043
|
+
if (fs2.existsSync(path2.join(full, "SKILL.md"))) {
|
|
15044
|
+
const installedName = entry.name.startsWith("rihal-") ? entry.name : `rihal-${entry.name}`;
|
|
15045
|
+
manifest.actions.add(installedName);
|
|
15046
|
+
} else {
|
|
15047
|
+
walkActions(full);
|
|
15048
|
+
}
|
|
15049
|
+
}
|
|
15050
|
+
}
|
|
15051
|
+
walkActions(path2.join(skillsRoot, "actions"));
|
|
15052
|
+
return manifest;
|
|
15053
|
+
}
|
|
15054
|
+
function readInstalledDirs(dir, prefix = null) {
|
|
15055
|
+
if (!fs2.existsSync(dir)) return /* @__PURE__ */ new Set();
|
|
15056
|
+
const names = /* @__PURE__ */ new Set();
|
|
15057
|
+
for (const entry of fs2.readdirSync(dir, { withFileTypes: true })) {
|
|
15058
|
+
if (!entry.isDirectory()) continue;
|
|
15059
|
+
if (prefix && !entry.name.startsWith(prefix)) continue;
|
|
15060
|
+
names.add(prefix ? entry.name.slice(prefix.length) : entry.name);
|
|
15061
|
+
}
|
|
15062
|
+
return names;
|
|
15063
|
+
}
|
|
15064
|
+
function diffSet(editor, kind, expected, installed) {
|
|
15065
|
+
const missing = [...expected].filter((x) => !installed.has(x)).sort();
|
|
15066
|
+
const extra = [...installed].filter((x) => !expected.has(x)).sort();
|
|
15067
|
+
return {
|
|
15068
|
+
editor,
|
|
15069
|
+
kind,
|
|
15070
|
+
expectedCount: expected.size,
|
|
15071
|
+
installedCount: installed.size,
|
|
15072
|
+
missing,
|
|
15073
|
+
extra
|
|
15074
|
+
};
|
|
15075
|
+
}
|
|
15076
|
+
function verifyClaudeInstall(cwd, packageRoot) {
|
|
15077
|
+
const pkg = readPackageManifest(packageRoot);
|
|
15078
|
+
const agentsDir = path2.join(cwd, ".claude/agents");
|
|
15079
|
+
const skillsDir = path2.join(cwd, ".claude/skills");
|
|
15080
|
+
const installedAgents = /* @__PURE__ */ new Set();
|
|
15081
|
+
if (fs2.existsSync(agentsDir)) {
|
|
15082
|
+
for (const f of fs2.readdirSync(agentsDir)) {
|
|
15083
|
+
if (f.startsWith("rihal-") && f.endsWith(".md")) {
|
|
15084
|
+
installedAgents.add(f.replace(/^rihal-/, "").replace(/\.md$/, ""));
|
|
15085
|
+
}
|
|
15086
|
+
}
|
|
15087
|
+
}
|
|
15088
|
+
if (installedAgents.size === 0) {
|
|
15089
|
+
try {
|
|
15090
|
+
const os = require("os");
|
|
15091
|
+
const globalAgentsDir = path2.join(os.homedir(), ".claude/agents");
|
|
15092
|
+
if (fs2.existsSync(globalAgentsDir)) {
|
|
15093
|
+
for (const f of fs2.readdirSync(globalAgentsDir)) {
|
|
15094
|
+
if (f.startsWith("rihal-") && f.endsWith(".md")) {
|
|
15095
|
+
installedAgents.add(f.replace(/^rihal-/, "").replace(/\.md$/, ""));
|
|
15096
|
+
}
|
|
15097
|
+
}
|
|
15098
|
+
}
|
|
15099
|
+
} catch {
|
|
15100
|
+
}
|
|
15101
|
+
}
|
|
15102
|
+
const allInstalled = readInstalledDirs(skillsDir);
|
|
15103
|
+
const actionsInstalled = new Set(
|
|
15104
|
+
[...allInstalled].filter((n) => !n.startsWith("rihal-"))
|
|
15105
|
+
);
|
|
15106
|
+
return [
|
|
15107
|
+
diffSet("claude", "agents", pkg.agents, installedAgents),
|
|
15108
|
+
diffSet("claude", "actions", pkg.actions, actionsInstalled)
|
|
15109
|
+
];
|
|
15110
|
+
}
|
|
15111
|
+
function verifyRulesInstall(editor, cwd, packageRoot) {
|
|
15112
|
+
const pkg = readPackageManifest(packageRoot);
|
|
15113
|
+
const rulesDir = path2.join(
|
|
15114
|
+
cwd,
|
|
15115
|
+
editor === "cursor" ? ".cursor/rules" : ".windsurf/rules"
|
|
15116
|
+
);
|
|
15117
|
+
const installed = /* @__PURE__ */ new Set();
|
|
15118
|
+
if (fs2.existsSync(rulesDir)) {
|
|
15119
|
+
for (const file of fs2.readdirSync(rulesDir)) {
|
|
15120
|
+
if (!file.startsWith("rihal-") || !file.endsWith(".mdc")) continue;
|
|
15121
|
+
if (file === "rihal-code.mdc") continue;
|
|
15122
|
+
installed.add(file.replace(/^rihal-/, "").replace(/\.mdc$/, ""));
|
|
15123
|
+
}
|
|
15124
|
+
}
|
|
15125
|
+
const digestsDir = path2.join(packageRoot, "rihal/digests");
|
|
15126
|
+
const expected = /* @__PURE__ */ new Set();
|
|
15127
|
+
if (fs2.existsSync(digestsDir)) {
|
|
15128
|
+
for (const file of fs2.readdirSync(digestsDir)) {
|
|
15129
|
+
if (!file.endsWith(".md") || file === "README.md") continue;
|
|
15130
|
+
expected.add(file.replace(/\.md$/, ""));
|
|
15131
|
+
}
|
|
15132
|
+
}
|
|
15133
|
+
return [diffSet(editor, "rules", expected, installed)];
|
|
15134
|
+
}
|
|
15135
|
+
function verifyAntigravityInstall(cwd, packageRoot) {
|
|
15136
|
+
const agentsDir = path2.join(cwd, ".antigravity/agents");
|
|
15137
|
+
const installed = /* @__PURE__ */ new Set();
|
|
15138
|
+
if (fs2.existsSync(agentsDir)) {
|
|
15139
|
+
for (const file of fs2.readdirSync(agentsDir)) {
|
|
15140
|
+
if (!file.startsWith("rihal-") || !file.endsWith(".md")) continue;
|
|
15141
|
+
installed.add(file.replace(/^rihal-/, "").replace(/\.md$/, ""));
|
|
15142
|
+
}
|
|
15143
|
+
}
|
|
15144
|
+
const digestsDir = path2.join(packageRoot, "rihal/digests");
|
|
15145
|
+
const expected = /* @__PURE__ */ new Set();
|
|
15146
|
+
if (fs2.existsSync(digestsDir)) {
|
|
15147
|
+
for (const file of fs2.readdirSync(digestsDir)) {
|
|
15148
|
+
if (!file.endsWith(".md") || file === "README.md") continue;
|
|
15149
|
+
expected.add(file.replace(/\.md$/, ""));
|
|
15150
|
+
}
|
|
15151
|
+
}
|
|
15152
|
+
return [diffSet("antigravity", "agents", expected, installed)];
|
|
15153
|
+
}
|
|
15154
|
+
function verifyInstall(cwd, packageRoot, editors) {
|
|
15155
|
+
const reports = [];
|
|
15156
|
+
if (editors.includes("claude")) {
|
|
15157
|
+
reports.push(...verifyClaudeInstall(cwd, packageRoot));
|
|
15158
|
+
}
|
|
15159
|
+
if (editors.includes("cursor")) {
|
|
15160
|
+
reports.push(...verifyRulesInstall("cursor", cwd, packageRoot));
|
|
15161
|
+
}
|
|
15162
|
+
if (editors.includes("windsurf")) {
|
|
15163
|
+
reports.push(...verifyRulesInstall("windsurf", cwd, packageRoot));
|
|
15164
|
+
}
|
|
15165
|
+
if (editors.includes("antigravity")) {
|
|
15166
|
+
reports.push(...verifyAntigravityInstall(cwd, packageRoot));
|
|
15167
|
+
}
|
|
15168
|
+
const hasDrift = reports.some((r) => r.missing.length > 0 || r.extra.length > 0);
|
|
15169
|
+
return { reports, hasDrift };
|
|
15170
|
+
}
|
|
15171
|
+
function formatReport(reports) {
|
|
15172
|
+
const lines = [];
|
|
15173
|
+
for (const r of reports) {
|
|
15174
|
+
const symbol = r.missing.length === 0 && r.extra.length === 0 ? "\u2713" : "\u26A0";
|
|
15175
|
+
lines.push(
|
|
15176
|
+
` ${symbol} ${r.editor.padEnd(12)} ${r.kind.padEnd(8)} ${r.installedCount}/${r.expectedCount}`
|
|
15177
|
+
);
|
|
15178
|
+
if (r.missing.length > 0) {
|
|
15179
|
+
lines.push(` missing: ${r.missing.join(", ")}`);
|
|
15180
|
+
}
|
|
15181
|
+
if (r.extra.length > 0) {
|
|
15182
|
+
lines.push(` extra: ${r.extra.join(", ")}`);
|
|
15183
|
+
}
|
|
15184
|
+
}
|
|
15185
|
+
return lines.join("\n");
|
|
15186
|
+
}
|
|
15187
|
+
module2.exports = {
|
|
15188
|
+
readPackageManifest,
|
|
15189
|
+
verifyInstall,
|
|
15190
|
+
verifyClaudeInstall,
|
|
15191
|
+
verifyRulesInstall,
|
|
15192
|
+
verifyAntigravityInstall,
|
|
15193
|
+
formatReport
|
|
15194
|
+
};
|
|
15195
|
+
}
|
|
15196
|
+
});
|
|
15197
|
+
|
|
14942
15198
|
// cli/install.js
|
|
14943
15199
|
var require_install = __commonJS({
|
|
14944
15200
|
"cli/install.js"(exports2, module2) {
|
|
@@ -14946,7 +15202,7 @@ var require_install = __commonJS({
|
|
|
14946
15202
|
var path2 = require("path");
|
|
14947
15203
|
var crypto = require("crypto");
|
|
14948
15204
|
var os = require("os");
|
|
14949
|
-
var { writeFileAtomic, safeRmSync } =
|
|
15205
|
+
var { writeFileAtomic, safeRmSync } = require_fsutil();
|
|
14950
15206
|
var pc = require_picocolors();
|
|
14951
15207
|
var { createSpinner } = require_dist();
|
|
14952
15208
|
var fg = require_out4();
|
|
@@ -14962,6 +15218,7 @@ var require_install = __commonJS({
|
|
|
14962
15218
|
var bold = (s) => pc.bold(s);
|
|
14963
15219
|
var PACKAGE_ROOT2 = path2.resolve(__dirname, "..");
|
|
14964
15220
|
var SOURCE_ROOT = path2.join(PACKAGE_ROOT2, "rihal");
|
|
15221
|
+
var SUPPORTED_IDES = Object.freeze(["claude", "cursor", "gemini", "vscode", "antigravity"]);
|
|
14965
15222
|
var ConfigSchema = z.object({
|
|
14966
15223
|
user_name: z.string().min(1),
|
|
14967
15224
|
project_name: z.string().min(1),
|
|
@@ -15163,11 +15420,11 @@ var require_install = __commonJS({
|
|
|
15163
15420
|
if (opts.noPrompt || opts.global) return ["claude"];
|
|
15164
15421
|
if (opts.yes || !process.stdin.isTTY) {
|
|
15165
15422
|
const signals2 = detectIdeSignals(opts.target);
|
|
15166
|
-
const detected2 =
|
|
15423
|
+
const detected2 = SUPPORTED_IDES.filter((k) => signals2[k]);
|
|
15167
15424
|
return detected2.length > 0 ? detected2 : ["claude"];
|
|
15168
15425
|
}
|
|
15169
15426
|
const signals = detectIdeSignals(opts.target);
|
|
15170
|
-
const detected =
|
|
15427
|
+
const detected = SUPPORTED_IDES.filter((k) => k !== "antigravity" && signals[k]);
|
|
15171
15428
|
const initialValues = detected.length > 0 ? detected : ["claude"];
|
|
15172
15429
|
const choices = await clack.multiselect({
|
|
15173
15430
|
message: "\u{1F3AF} Which editor(s) will you use rcode with?",
|
|
@@ -16144,7 +16401,6 @@ ${BLOCK}`, { mode: 493 });
|
|
|
16144
16401
|
console.error(`\u2716 Source tree not found at ${SOURCE_ROOT}. Running from wrong dir?`);
|
|
16145
16402
|
return 1;
|
|
16146
16403
|
}
|
|
16147
|
-
const SUPPORTED_IDES = ["claude", "cursor", "gemini", "vscode", "antigravity"];
|
|
16148
16404
|
const unsupported = opts.ides.filter((ide) => !SUPPORTED_IDES.includes(ide));
|
|
16149
16405
|
if (unsupported.length > 0) {
|
|
16150
16406
|
console.error(`\u2716 --ide ${unsupported.join(", ")} is not supported in v${readPackageVersion()}.`);
|
|
@@ -16738,7 +16994,7 @@ commit_planning: ${desired}
|
|
|
16738
16994
|
let fails = 0;
|
|
16739
16995
|
let expected = { agents: 20, skills: 20, commands: 20 };
|
|
16740
16996
|
try {
|
|
16741
|
-
const { readPackageManifest } =
|
|
16997
|
+
const { readPackageManifest } = require_manifest();
|
|
16742
16998
|
const pkgManifest = readPackageManifest(PACKAGE_ROOT2);
|
|
16743
16999
|
if (pkgManifest && pkgManifest.agents instanceof Set && pkgManifest.actions instanceof Set) {
|
|
16744
17000
|
const tolerate = (n) => Math.max(1, Math.floor(n * 0.9));
|
|
@@ -16948,6 +17204,7 @@ commit_planning: ${desired}
|
|
|
16948
17204
|
module2.exports.parseArgs = parseArgs;
|
|
16949
17205
|
module2.exports.buildInstallPlan = buildInstallPlan;
|
|
16950
17206
|
module2.exports.install = install;
|
|
17207
|
+
module2.exports.SUPPORTED_IDES = SUPPORTED_IDES;
|
|
16951
17208
|
}
|
|
16952
17209
|
});
|
|
16953
17210
|
|
|
@@ -17155,262 +17412,6 @@ var require_prompts = __commonJS({
|
|
|
17155
17412
|
}
|
|
17156
17413
|
});
|
|
17157
17414
|
|
|
17158
|
-
// cli/lib/fsutil.cjs
|
|
17159
|
-
var require_fsutil = __commonJS({
|
|
17160
|
-
"cli/lib/fsutil.cjs"(exports2, module2) {
|
|
17161
|
-
var crypto = require("crypto");
|
|
17162
|
-
var fs2 = require("fs");
|
|
17163
|
-
var path2 = require("path");
|
|
17164
|
-
function writeFileAtomic(filePath, content, opts = {}) {
|
|
17165
|
-
const { encoding = "utf8", mode } = opts;
|
|
17166
|
-
const dir = path2.dirname(filePath);
|
|
17167
|
-
fs2.mkdirSync(dir, { recursive: true });
|
|
17168
|
-
const tmpPath = path2.join(
|
|
17169
|
-
dir,
|
|
17170
|
-
`.${path2.basename(filePath)}.tmp-${process.pid}-${crypto.randomBytes(8).toString("hex")}`
|
|
17171
|
-
);
|
|
17172
|
-
let fd;
|
|
17173
|
-
try {
|
|
17174
|
-
fd = fs2.openSync(tmpPath, "wx", mode ?? 420);
|
|
17175
|
-
fs2.writeSync(fd, content, 0, encoding);
|
|
17176
|
-
fs2.fsyncSync(fd);
|
|
17177
|
-
fs2.closeSync(fd);
|
|
17178
|
-
fd = null;
|
|
17179
|
-
fs2.renameSync(tmpPath, filePath);
|
|
17180
|
-
} catch (err) {
|
|
17181
|
-
if (fd !== null && fd !== void 0) {
|
|
17182
|
-
try {
|
|
17183
|
-
fs2.closeSync(fd);
|
|
17184
|
-
} catch {
|
|
17185
|
-
}
|
|
17186
|
-
}
|
|
17187
|
-
try {
|
|
17188
|
-
fs2.unlinkSync(tmpPath);
|
|
17189
|
-
} catch {
|
|
17190
|
-
}
|
|
17191
|
-
throw err;
|
|
17192
|
-
}
|
|
17193
|
-
}
|
|
17194
|
-
function writeJsonAtomic(filePath, obj, opts = {}) {
|
|
17195
|
-
const content = JSON.stringify(obj, null, 2) + "\n";
|
|
17196
|
-
writeFileAtomic(filePath, content, opts);
|
|
17197
|
-
}
|
|
17198
|
-
function safeRmSync(targetPath, projectRoot) {
|
|
17199
|
-
let stats;
|
|
17200
|
-
try {
|
|
17201
|
-
stats = fs2.lstatSync(targetPath);
|
|
17202
|
-
} catch (err) {
|
|
17203
|
-
if (err.code === "ENOENT") return { ok: true, reason: "missing" };
|
|
17204
|
-
return { ok: false, reason: `lstat: ${err.message}` };
|
|
17205
|
-
}
|
|
17206
|
-
if (stats.isSymbolicLink()) {
|
|
17207
|
-
try {
|
|
17208
|
-
fs2.unlinkSync(targetPath);
|
|
17209
|
-
return { ok: true, reason: "symlink-unlinked" };
|
|
17210
|
-
} catch (err) {
|
|
17211
|
-
return { ok: false, reason: `unlink: ${err.message}` };
|
|
17212
|
-
}
|
|
17213
|
-
}
|
|
17214
|
-
const root = path2.resolve(projectRoot);
|
|
17215
|
-
let resolved;
|
|
17216
|
-
try {
|
|
17217
|
-
resolved = fs2.realpathSync(targetPath);
|
|
17218
|
-
} catch (err) {
|
|
17219
|
-
return { ok: false, reason: `realpath: ${err.message}` };
|
|
17220
|
-
}
|
|
17221
|
-
const relative = path2.relative(root, resolved);
|
|
17222
|
-
if (relative.startsWith("..") || path2.isAbsolute(relative)) {
|
|
17223
|
-
return { ok: false, reason: "outside-root" };
|
|
17224
|
-
}
|
|
17225
|
-
try {
|
|
17226
|
-
fs2.rmSync(resolved, { recursive: true, force: true });
|
|
17227
|
-
return { ok: true };
|
|
17228
|
-
} catch (err) {
|
|
17229
|
-
return { ok: false, reason: `rmSync: ${err.message}` };
|
|
17230
|
-
}
|
|
17231
|
-
}
|
|
17232
|
-
module2.exports = {
|
|
17233
|
-
writeFileAtomic,
|
|
17234
|
-
writeJsonAtomic,
|
|
17235
|
-
safeRmSync
|
|
17236
|
-
};
|
|
17237
|
-
}
|
|
17238
|
-
});
|
|
17239
|
-
|
|
17240
|
-
// cli/lib/manifest.cjs
|
|
17241
|
-
var require_manifest = __commonJS({
|
|
17242
|
-
"cli/lib/manifest.cjs"(exports2, module2) {
|
|
17243
|
-
var fs2 = require("fs");
|
|
17244
|
-
var path2 = require("path");
|
|
17245
|
-
function readPackageManifest(packageRoot) {
|
|
17246
|
-
const skillsRoot = path2.join(packageRoot, "rihal/skills");
|
|
17247
|
-
const manifest = { agents: /* @__PURE__ */ new Set(), actions: /* @__PURE__ */ new Set() };
|
|
17248
|
-
const agentsDir = path2.join(skillsRoot, "agents");
|
|
17249
|
-
if (fs2.existsSync(agentsDir)) {
|
|
17250
|
-
for (const entry of fs2.readdirSync(agentsDir, { withFileTypes: true })) {
|
|
17251
|
-
if (entry.isDirectory()) manifest.agents.add(entry.name);
|
|
17252
|
-
}
|
|
17253
|
-
}
|
|
17254
|
-
function walkActions(dir) {
|
|
17255
|
-
if (!fs2.existsSync(dir)) return;
|
|
17256
|
-
for (const entry of fs2.readdirSync(dir, { withFileTypes: true })) {
|
|
17257
|
-
if (!entry.isDirectory()) continue;
|
|
17258
|
-
const full = path2.join(dir, entry.name);
|
|
17259
|
-
if (fs2.existsSync(path2.join(full, "SKILL.md"))) {
|
|
17260
|
-
const installedName = entry.name.startsWith("rihal-") ? entry.name : `rihal-${entry.name}`;
|
|
17261
|
-
manifest.actions.add(installedName);
|
|
17262
|
-
} else {
|
|
17263
|
-
walkActions(full);
|
|
17264
|
-
}
|
|
17265
|
-
}
|
|
17266
|
-
}
|
|
17267
|
-
walkActions(path2.join(skillsRoot, "actions"));
|
|
17268
|
-
return manifest;
|
|
17269
|
-
}
|
|
17270
|
-
function readInstalledDirs(dir, prefix = null) {
|
|
17271
|
-
if (!fs2.existsSync(dir)) return /* @__PURE__ */ new Set();
|
|
17272
|
-
const names = /* @__PURE__ */ new Set();
|
|
17273
|
-
for (const entry of fs2.readdirSync(dir, { withFileTypes: true })) {
|
|
17274
|
-
if (!entry.isDirectory()) continue;
|
|
17275
|
-
if (prefix && !entry.name.startsWith(prefix)) continue;
|
|
17276
|
-
names.add(prefix ? entry.name.slice(prefix.length) : entry.name);
|
|
17277
|
-
}
|
|
17278
|
-
return names;
|
|
17279
|
-
}
|
|
17280
|
-
function diffSet(editor, kind, expected, installed) {
|
|
17281
|
-
const missing = [...expected].filter((x) => !installed.has(x)).sort();
|
|
17282
|
-
const extra = [...installed].filter((x) => !expected.has(x)).sort();
|
|
17283
|
-
return {
|
|
17284
|
-
editor,
|
|
17285
|
-
kind,
|
|
17286
|
-
expectedCount: expected.size,
|
|
17287
|
-
installedCount: installed.size,
|
|
17288
|
-
missing,
|
|
17289
|
-
extra
|
|
17290
|
-
};
|
|
17291
|
-
}
|
|
17292
|
-
function verifyClaudeInstall(cwd, packageRoot) {
|
|
17293
|
-
const pkg = readPackageManifest(packageRoot);
|
|
17294
|
-
const agentsDir = path2.join(cwd, ".claude/agents");
|
|
17295
|
-
const skillsDir = path2.join(cwd, ".claude/skills");
|
|
17296
|
-
const installedAgents = /* @__PURE__ */ new Set();
|
|
17297
|
-
if (fs2.existsSync(agentsDir)) {
|
|
17298
|
-
for (const f of fs2.readdirSync(agentsDir)) {
|
|
17299
|
-
if (f.startsWith("rihal-") && f.endsWith(".md")) {
|
|
17300
|
-
installedAgents.add(f.replace(/^rihal-/, "").replace(/\.md$/, ""));
|
|
17301
|
-
}
|
|
17302
|
-
}
|
|
17303
|
-
}
|
|
17304
|
-
if (installedAgents.size === 0) {
|
|
17305
|
-
try {
|
|
17306
|
-
const os = require("os");
|
|
17307
|
-
const globalAgentsDir = path2.join(os.homedir(), ".claude/agents");
|
|
17308
|
-
if (fs2.existsSync(globalAgentsDir)) {
|
|
17309
|
-
for (const f of fs2.readdirSync(globalAgentsDir)) {
|
|
17310
|
-
if (f.startsWith("rihal-") && f.endsWith(".md")) {
|
|
17311
|
-
installedAgents.add(f.replace(/^rihal-/, "").replace(/\.md$/, ""));
|
|
17312
|
-
}
|
|
17313
|
-
}
|
|
17314
|
-
}
|
|
17315
|
-
} catch {
|
|
17316
|
-
}
|
|
17317
|
-
}
|
|
17318
|
-
const allInstalled = readInstalledDirs(skillsDir);
|
|
17319
|
-
const actionsInstalled = new Set(
|
|
17320
|
-
[...allInstalled].filter((n) => !n.startsWith("rihal-"))
|
|
17321
|
-
);
|
|
17322
|
-
return [
|
|
17323
|
-
diffSet("claude", "agents", pkg.agents, installedAgents),
|
|
17324
|
-
diffSet("claude", "actions", pkg.actions, actionsInstalled)
|
|
17325
|
-
];
|
|
17326
|
-
}
|
|
17327
|
-
function verifyRulesInstall(editor, cwd, packageRoot) {
|
|
17328
|
-
const pkg = readPackageManifest(packageRoot);
|
|
17329
|
-
const rulesDir = path2.join(
|
|
17330
|
-
cwd,
|
|
17331
|
-
editor === "cursor" ? ".cursor/rules" : ".windsurf/rules"
|
|
17332
|
-
);
|
|
17333
|
-
const installed = /* @__PURE__ */ new Set();
|
|
17334
|
-
if (fs2.existsSync(rulesDir)) {
|
|
17335
|
-
for (const file of fs2.readdirSync(rulesDir)) {
|
|
17336
|
-
if (!file.startsWith("rihal-") || !file.endsWith(".mdc")) continue;
|
|
17337
|
-
if (file === "rihal-code.mdc") continue;
|
|
17338
|
-
installed.add(file.replace(/^rihal-/, "").replace(/\.mdc$/, ""));
|
|
17339
|
-
}
|
|
17340
|
-
}
|
|
17341
|
-
const digestsDir = path2.join(packageRoot, "rihal/digests");
|
|
17342
|
-
const expected = /* @__PURE__ */ new Set();
|
|
17343
|
-
if (fs2.existsSync(digestsDir)) {
|
|
17344
|
-
for (const file of fs2.readdirSync(digestsDir)) {
|
|
17345
|
-
if (!file.endsWith(".md") || file === "README.md") continue;
|
|
17346
|
-
expected.add(file.replace(/\.md$/, ""));
|
|
17347
|
-
}
|
|
17348
|
-
}
|
|
17349
|
-
return [diffSet(editor, "rules", expected, installed)];
|
|
17350
|
-
}
|
|
17351
|
-
function verifyAntigravityInstall(cwd, packageRoot) {
|
|
17352
|
-
const agentsDir = path2.join(cwd, ".antigravity/agents");
|
|
17353
|
-
const installed = /* @__PURE__ */ new Set();
|
|
17354
|
-
if (fs2.existsSync(agentsDir)) {
|
|
17355
|
-
for (const file of fs2.readdirSync(agentsDir)) {
|
|
17356
|
-
if (!file.startsWith("rihal-") || !file.endsWith(".md")) continue;
|
|
17357
|
-
installed.add(file.replace(/^rihal-/, "").replace(/\.md$/, ""));
|
|
17358
|
-
}
|
|
17359
|
-
}
|
|
17360
|
-
const digestsDir = path2.join(packageRoot, "rihal/digests");
|
|
17361
|
-
const expected = /* @__PURE__ */ new Set();
|
|
17362
|
-
if (fs2.existsSync(digestsDir)) {
|
|
17363
|
-
for (const file of fs2.readdirSync(digestsDir)) {
|
|
17364
|
-
if (!file.endsWith(".md") || file === "README.md") continue;
|
|
17365
|
-
expected.add(file.replace(/\.md$/, ""));
|
|
17366
|
-
}
|
|
17367
|
-
}
|
|
17368
|
-
return [diffSet("antigravity", "agents", expected, installed)];
|
|
17369
|
-
}
|
|
17370
|
-
function verifyInstall(cwd, packageRoot, editors) {
|
|
17371
|
-
const reports = [];
|
|
17372
|
-
if (editors.includes("claude")) {
|
|
17373
|
-
reports.push(...verifyClaudeInstall(cwd, packageRoot));
|
|
17374
|
-
}
|
|
17375
|
-
if (editors.includes("cursor")) {
|
|
17376
|
-
reports.push(...verifyRulesInstall("cursor", cwd, packageRoot));
|
|
17377
|
-
}
|
|
17378
|
-
if (editors.includes("windsurf")) {
|
|
17379
|
-
reports.push(...verifyRulesInstall("windsurf", cwd, packageRoot));
|
|
17380
|
-
}
|
|
17381
|
-
if (editors.includes("antigravity")) {
|
|
17382
|
-
reports.push(...verifyAntigravityInstall(cwd, packageRoot));
|
|
17383
|
-
}
|
|
17384
|
-
const hasDrift = reports.some((r) => r.missing.length > 0 || r.extra.length > 0);
|
|
17385
|
-
return { reports, hasDrift };
|
|
17386
|
-
}
|
|
17387
|
-
function formatReport(reports) {
|
|
17388
|
-
const lines = [];
|
|
17389
|
-
for (const r of reports) {
|
|
17390
|
-
const symbol = r.missing.length === 0 && r.extra.length === 0 ? "\u2713" : "\u26A0";
|
|
17391
|
-
lines.push(
|
|
17392
|
-
` ${symbol} ${r.editor.padEnd(12)} ${r.kind.padEnd(8)} ${r.installedCount}/${r.expectedCount}`
|
|
17393
|
-
);
|
|
17394
|
-
if (r.missing.length > 0) {
|
|
17395
|
-
lines.push(` missing: ${r.missing.join(", ")}`);
|
|
17396
|
-
}
|
|
17397
|
-
if (r.extra.length > 0) {
|
|
17398
|
-
lines.push(` extra: ${r.extra.join(", ")}`);
|
|
17399
|
-
}
|
|
17400
|
-
}
|
|
17401
|
-
return lines.join("\n");
|
|
17402
|
-
}
|
|
17403
|
-
module2.exports = {
|
|
17404
|
-
readPackageManifest,
|
|
17405
|
-
verifyInstall,
|
|
17406
|
-
verifyClaudeInstall,
|
|
17407
|
-
verifyRulesInstall,
|
|
17408
|
-
verifyAntigravityInstall,
|
|
17409
|
-
formatReport
|
|
17410
|
-
};
|
|
17411
|
-
}
|
|
17412
|
-
});
|
|
17413
|
-
|
|
17414
17415
|
// cli/update.js
|
|
17415
17416
|
var require_update = __commonJS({
|
|
17416
17417
|
"cli/update.js"(exports2, module2) {
|
|
@@ -17703,6 +17704,8 @@ var require_update = __commonJS({
|
|
|
17703
17704
|
}
|
|
17704
17705
|
console.log();
|
|
17705
17706
|
}
|
|
17707
|
+
module2.exports.parseArgs = parseArgs;
|
|
17708
|
+
module2.exports.detectInstalledEditors = detectInstalledEditors;
|
|
17706
17709
|
}
|
|
17707
17710
|
});
|
|
17708
17711
|
|
|
@@ -17746,6 +17749,9 @@ var require_uninstall = __commonJS({
|
|
|
17746
17749
|
function isLocalOverride(name) {
|
|
17747
17750
|
return /\.local\.(md|mdc|json|yaml|yml|toml|js|ts)$/.test(name);
|
|
17748
17751
|
}
|
|
17752
|
+
function stripRihalGitignoreBlock(text) {
|
|
17753
|
+
return text.replace(/\n?# ===== rcode-managed gitignore block[\s\S]*?# ===== end rcode-managed gitignore block =====\n?/g, "\n").replace(/\n?# >>> rihal-code >>>[\s\S]*?# <<< rihal-code <<<\n?/g, "\n").replace(/\n{3,}/g, "\n\n");
|
|
17754
|
+
}
|
|
17749
17755
|
function removeMatching(dir, predicate) {
|
|
17750
17756
|
if (!fs2.existsSync(dir)) return 0;
|
|
17751
17757
|
let count = 0;
|
|
@@ -17856,7 +17862,7 @@ var require_uninstall = __commonJS({
|
|
|
17856
17862
|
}
|
|
17857
17863
|
function discoverKnownActionSkills() {
|
|
17858
17864
|
try {
|
|
17859
|
-
const { readPackageManifest } =
|
|
17865
|
+
const { readPackageManifest } = require_manifest();
|
|
17860
17866
|
const packageRoot = path2.resolve(__dirname, "..");
|
|
17861
17867
|
const pkg = readPackageManifest(packageRoot);
|
|
17862
17868
|
if (pkg && pkg.actions instanceof Set && pkg.actions.size > 0) {
|
|
@@ -17981,8 +17987,8 @@ var require_uninstall = __commonJS({
|
|
|
17981
17987
|
async function runUninstall(args) {
|
|
17982
17988
|
const opts = parseArgs(args);
|
|
17983
17989
|
const cwd = process.cwd();
|
|
17984
|
-
const
|
|
17985
|
-
const editors = opts.editor ? opts.editor === "all" ?
|
|
17990
|
+
const { SUPPORTED_IDES } = require_install();
|
|
17991
|
+
const editors = opts.editor ? opts.editor === "all" ? Array.from(SUPPORTED_IDES) : [opts.editor] : Array.from(SUPPORTED_IDES);
|
|
17986
17992
|
console.log(`
|
|
17987
17993
|
\u{1F54C} Rihal Code \u2014 Uninstall
|
|
17988
17994
|
`);
|
|
@@ -18219,7 +18225,7 @@ var require_uninstall = __commonJS({
|
|
|
18219
18225
|
if (fs2.existsSync(gitignorePath)) {
|
|
18220
18226
|
try {
|
|
18221
18227
|
const before = fs2.readFileSync(gitignorePath, "utf8");
|
|
18222
|
-
const stripped = before
|
|
18228
|
+
const stripped = stripRihalGitignoreBlock(before);
|
|
18223
18229
|
if (stripped !== before) {
|
|
18224
18230
|
fs2.writeFileSync(gitignorePath, stripped);
|
|
18225
18231
|
console.log(` \u2713 stripped rcode block from .gitignore (--purge)`);
|
|
@@ -18248,6 +18254,10 @@ var require_uninstall = __commonJS({
|
|
|
18248
18254
|
To reinstall later:`);
|
|
18249
18255
|
console.log(` rcode install`);
|
|
18250
18256
|
}
|
|
18257
|
+
module2.exports.isLocalOverride = isLocalOverride;
|
|
18258
|
+
module2.exports.planToPathList = planToPathList;
|
|
18259
|
+
module2.exports.discoverKnownActionSkills = discoverKnownActionSkills;
|
|
18260
|
+
module2.exports.stripRihalGitignoreBlock = stripRihalGitignoreBlock;
|
|
18251
18261
|
if (require.main === module2) {
|
|
18252
18262
|
module2.exports(process.argv.slice(2)).catch((err) => {
|
|
18253
18263
|
if (err instanceof PromptAbortError) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzlaa/rcode",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.27",
|
|
4
4
|
"description": "rcode — the memory bank for AI-driven SaaS teams. Persistent project context, distinctive engineering personas, and phase-based workflows. Built by Rihal. Works in Claude Code, Cursor, Gemini, VS Code, and Antigravity.",
|
|
5
5
|
"main": "cli/index.js",
|
|
6
6
|
"bin": {
|