@agentrules/cli 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +38 -13
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -35,6 +35,11 @@ const RULE_TYPE_TUPLE = [
|
|
|
35
35
|
|
|
36
36
|
//#endregion
|
|
37
37
|
//#region ../core/src/platform/config.ts
|
|
38
|
+
/**
|
|
39
|
+
* Placeholder for user's home directory in path templates.
|
|
40
|
+
* Consumers (e.g., CLI) are responsible for expanding this at runtime.
|
|
41
|
+
*/
|
|
42
|
+
const USER_HOME_DIR_PLACEHOLDER = "{userHomeDir}";
|
|
38
43
|
const PLATFORM_IDS = PLATFORM_ID_TUPLE;
|
|
39
44
|
/**
|
|
40
45
|
* Platform configuration including supported types and install paths.
|
|
@@ -43,7 +48,7 @@ const PLATFORMS = {
|
|
|
43
48
|
opencode: {
|
|
44
49
|
label: "OpenCode",
|
|
45
50
|
platformDir: ".opencode",
|
|
46
|
-
globalDir: "
|
|
51
|
+
globalDir: "{userHomeDir}/.config/opencode",
|
|
47
52
|
types: {
|
|
48
53
|
instruction: {
|
|
49
54
|
description: "Project instructions",
|
|
@@ -75,7 +80,7 @@ const PLATFORMS = {
|
|
|
75
80
|
claude: {
|
|
76
81
|
label: "Claude Code",
|
|
77
82
|
platformDir: ".claude",
|
|
78
|
-
globalDir: "
|
|
83
|
+
globalDir: "{userHomeDir}/.claude",
|
|
79
84
|
types: {
|
|
80
85
|
instruction: {
|
|
81
86
|
description: "Project instructions",
|
|
@@ -102,7 +107,7 @@ const PLATFORMS = {
|
|
|
102
107
|
cursor: {
|
|
103
108
|
label: "Cursor",
|
|
104
109
|
platformDir: ".cursor",
|
|
105
|
-
globalDir: "
|
|
110
|
+
globalDir: "{userHomeDir}/.cursor",
|
|
106
111
|
types: {
|
|
107
112
|
instruction: {
|
|
108
113
|
description: "Project instructions",
|
|
@@ -129,7 +134,7 @@ const PLATFORMS = {
|
|
|
129
134
|
codex: {
|
|
130
135
|
label: "Codex",
|
|
131
136
|
platformDir: ".codex",
|
|
132
|
-
globalDir: "
|
|
137
|
+
globalDir: "{userHomeDir}/.codex",
|
|
133
138
|
types: {
|
|
134
139
|
instruction: {
|
|
135
140
|
description: "Project instructions",
|
|
@@ -183,7 +188,7 @@ function getInstallPath({ platform, type, name, scope = "project" }) {
|
|
|
183
188
|
* Returns the path relative to the platform's root directory.
|
|
184
189
|
*
|
|
185
190
|
* Example: For codex instruction with scope="global", returns "AGENTS.md"
|
|
186
|
-
* (not
|
|
191
|
+
* (not the full path with {userHomeDir})
|
|
187
192
|
*/
|
|
188
193
|
function getRelativeInstallPath({ platform, type, name, scope = "project" }) {
|
|
189
194
|
const typeConfig = getTypeConfig(platform, type);
|
|
@@ -3505,6 +3510,21 @@ const COMMON_LICENSES = [
|
|
|
3505
3510
|
];
|
|
3506
3511
|
const licenseSchema = string().trim().min(1, "License is required").max(128, "License must be 128 characters or less");
|
|
3507
3512
|
const pathSchema = string().trim().min(1);
|
|
3513
|
+
/**
|
|
3514
|
+
* Validate a bundle file path for security.
|
|
3515
|
+
* Rejects paths that could escape the install directory.
|
|
3516
|
+
*
|
|
3517
|
+
* @returns true if path is safe, false otherwise
|
|
3518
|
+
*/
|
|
3519
|
+
function isValidBundlePath(path$1) {
|
|
3520
|
+
if (path$1.includes("..")) return false;
|
|
3521
|
+
if (path$1.startsWith("/")) return false;
|
|
3522
|
+
if (path$1.startsWith("~")) return false;
|
|
3523
|
+
if (path$1.includes("/~/") || path$1.includes("\\~\\")) return false;
|
|
3524
|
+
if (path$1.includes("{userHomeDir}")) return false;
|
|
3525
|
+
return true;
|
|
3526
|
+
}
|
|
3527
|
+
const bundlePathSchema = string().min(1).refine(isValidBundlePath, { message: "Path must be relative without traversal (no .., ~, absolute paths, or {userHomeDir})" });
|
|
3508
3528
|
const ignorePatternSchema = string().trim().min(1, "Ignore pattern cannot be empty");
|
|
3509
3529
|
const ignoreSchema = array(ignorePatternSchema).max(50, "Maximum 50 ignore patterns allowed");
|
|
3510
3530
|
/**
|
|
@@ -3549,7 +3569,7 @@ const ruleConfigSchema = object({
|
|
|
3549
3569
|
platforms: array(platformEntrySchema).min(1, "At least one platform is required")
|
|
3550
3570
|
}).strict();
|
|
3551
3571
|
const bundledFileSchema = object({
|
|
3552
|
-
path:
|
|
3572
|
+
path: bundlePathSchema,
|
|
3553
3573
|
size: number().int().nonnegative(),
|
|
3554
3574
|
checksum: string().length(64),
|
|
3555
3575
|
content: string()
|
|
@@ -5611,7 +5631,7 @@ function resolveInstallTarget(platform, type, name, options) {
|
|
|
5611
5631
|
const { platformDir, globalDir } = PLATFORMS[platform];
|
|
5612
5632
|
if (options.global) {
|
|
5613
5633
|
if (!globalDir) throw new Error(`Platform "${platform}" does not support global installation`);
|
|
5614
|
-
const globalRoot = resolve(
|
|
5634
|
+
const globalRoot = resolve(expandUserHomeDir(globalDir));
|
|
5615
5635
|
return {
|
|
5616
5636
|
root: globalRoot,
|
|
5617
5637
|
mode: "global",
|
|
@@ -5623,7 +5643,7 @@ function resolveInstallTarget(platform, type, name, options) {
|
|
|
5623
5643
|
label: `global path ${globalRoot}`
|
|
5624
5644
|
};
|
|
5625
5645
|
}
|
|
5626
|
-
const projectRoot = options.directory ? resolve(
|
|
5646
|
+
const projectRoot = options.directory ? resolve(expandUserHomeDir(options.directory)) : process.cwd();
|
|
5627
5647
|
const label = options.directory ? `directory ${projectRoot}` : `project root ${projectRoot}`;
|
|
5628
5648
|
return {
|
|
5629
5649
|
root: projectRoot,
|
|
@@ -5723,15 +5743,20 @@ function ensureWithinRoot(candidate, root) {
|
|
|
5723
5743
|
if (candidate === root) return;
|
|
5724
5744
|
if (!candidate.startsWith(normalizedRoot)) throw new Error(`Refusing to write outside of ${root}. Derived path: ${candidate}`);
|
|
5725
5745
|
}
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5746
|
+
/**
|
|
5747
|
+
* Expand home directory references in a path string.
|
|
5748
|
+
* Handles both {userHomeDir} placeholder and ~ prefix.
|
|
5749
|
+
*/
|
|
5750
|
+
function expandUserHomeDir(path$1) {
|
|
5751
|
+
const home = process.env.HOME || homedir();
|
|
5752
|
+
if (path$1.includes(USER_HOME_DIR_PLACEHOLDER)) return path$1.replace(USER_HOME_DIR_PLACEHOLDER, home);
|
|
5753
|
+
if (path$1.startsWith("~")) {
|
|
5754
|
+
const remainder = path$1.slice(1);
|
|
5730
5755
|
if (!remainder) return home;
|
|
5731
5756
|
if (remainder.startsWith("/") || remainder.startsWith("\\")) return `${home}${remainder}`;
|
|
5732
5757
|
return `${home}/${remainder}`;
|
|
5733
5758
|
}
|
|
5734
|
-
return
|
|
5759
|
+
return path$1;
|
|
5735
5760
|
}
|
|
5736
5761
|
|
|
5737
5762
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentrules/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"author": "Brian Cheung <bcheung.dev@gmail.com> (https://github.com/bcheung)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://agentrules.directory",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"clean": "rm -rf node_modules dist .turbo"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@agentrules/core": "0.3.
|
|
56
|
+
"@agentrules/core": "0.3.1",
|
|
57
57
|
"@clack/prompts": "^0.11.0",
|
|
58
58
|
"chalk": "^5.4.1",
|
|
59
59
|
"commander": "^12.1.0",
|