rulesync 8.15.1 → 8.16.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.
@@ -4826,7 +4826,9 @@ async function buildCodexConfigTomlContent({
4826
4826
  if (typeof configToml.features !== "object" || configToml.features === null) {
4827
4827
  configToml.features = {};
4828
4828
  }
4829
- configToml.features.codex_hooks = true;
4829
+ const features = configToml.features;
4830
+ delete features.codex_hooks;
4831
+ features.hooks = true;
4830
4832
  return smolToml2.stringify(configToml);
4831
4833
  }
4832
4834
  var CodexcliConfigToml = class _CodexcliConfigToml extends ToolFile {
@@ -10897,10 +10899,12 @@ var ClinePermissions = class _ClinePermissions extends ToolPermissions {
10897
10899
  };
10898
10900
 
10899
10901
  // src/features/permissions/codexcli-permissions.ts
10900
- import { join as join68 } from "path";
10902
+ import { isAbsolute as isAbsolute3, join as join68 } from "path";
10901
10903
  import * as smolToml4 from "smol-toml";
10902
10904
  var RULESYNC_PROFILE_NAME = "rulesync";
10903
10905
  var RULESYNC_BASH_RULES_FILE_NAME = "rulesync.rules";
10906
+ var CODEX_PROJECT_ROOTS_KEY = ":project_roots";
10907
+ var CODEX_GLOB_SCAN_MAX_DEPTH = 8;
10904
10908
  var CodexcliPermissions = class _CodexcliPermissions extends ToolPermissions {
10905
10909
  static getSettablePaths(_options = {}) {
10906
10910
  return {
@@ -11011,17 +11015,28 @@ function convertRulesyncToCodexProfile({
11011
11015
  logger
11012
11016
  }) {
11013
11017
  const filesystem = {};
11018
+ const projectRootFilesystem = {};
11014
11019
  const domains = {};
11015
11020
  for (const [toolName, rules] of Object.entries(config.permission)) {
11016
11021
  if (toolName === "read") {
11017
11022
  for (const [pattern, action] of Object.entries(rules)) {
11018
- filesystem[pattern] = mapReadAction(action);
11023
+ addFilesystemRule({
11024
+ filesystem,
11025
+ projectRootFilesystem,
11026
+ pattern,
11027
+ access: mapReadAction(action)
11028
+ });
11019
11029
  }
11020
11030
  continue;
11021
11031
  }
11022
11032
  if (toolName === "edit" || toolName === "write") {
11023
11033
  for (const [pattern, action] of Object.entries(rules)) {
11024
- filesystem[pattern] = mapWriteAction(action);
11034
+ addFilesystemRule({
11035
+ filesystem,
11036
+ projectRootFilesystem,
11037
+ pattern,
11038
+ access: mapWriteAction(action)
11039
+ });
11025
11040
  }
11026
11041
  continue;
11027
11042
  }
@@ -11041,6 +11056,12 @@ function convertRulesyncToCodexProfile({
11041
11056
  `Codex CLI permissions support only read/edit/write/webfetch categories. Skipping: ${toolName}`
11042
11057
  );
11043
11058
  }
11059
+ if (Object.keys(projectRootFilesystem).length > 0) {
11060
+ if (Object.keys(projectRootFilesystem).some((pattern) => pattern.includes("**"))) {
11061
+ filesystem.glob_scan_max_depth = CODEX_GLOB_SCAN_MAX_DEPTH;
11062
+ }
11063
+ filesystem[CODEX_PROJECT_ROOTS_KEY] = projectRootFilesystem;
11064
+ }
11044
11065
  return {
11045
11066
  ...Object.keys(filesystem).length > 0 ? { filesystem } : {},
11046
11067
  ...Object.keys(domains).length > 0 ? { network: { domains } } : {}
@@ -11052,13 +11073,14 @@ function convertCodexProfileToRulesync(profile) {
11052
11073
  permission.read = {};
11053
11074
  permission.edit = {};
11054
11075
  for (const [pattern, access] of Object.entries(profile.filesystem)) {
11055
- if (access === "none") {
11056
- permission.read[pattern] = "deny";
11057
- permission.edit[pattern] = "deny";
11058
- } else if (access === "read") {
11059
- permission.read[pattern] = "allow";
11060
- } else {
11061
- permission.edit[pattern] = "allow";
11076
+ if (isCodexFilesystemAccess(access)) {
11077
+ addRulesyncFilesystemRule(permission, pattern, access);
11078
+ continue;
11079
+ }
11080
+ if (isCodexFilesystemRuleTable(access)) {
11081
+ for (const [nestedPattern, nestedAccess] of Object.entries(access)) {
11082
+ addRulesyncFilesystemRule(permission, nestedPattern, nestedAccess);
11083
+ }
11062
11084
  }
11063
11085
  }
11064
11086
  }
@@ -11081,6 +11103,35 @@ function toCodexProfile(value) {
11081
11103
  ...domains ? { network: { domains } } : {}
11082
11104
  };
11083
11105
  }
11106
+ function addFilesystemRule({
11107
+ filesystem,
11108
+ projectRootFilesystem,
11109
+ pattern,
11110
+ access
11111
+ }) {
11112
+ if (canBeCodexFilesystemRoot(pattern)) {
11113
+ filesystem[pattern] = access;
11114
+ return;
11115
+ }
11116
+ projectRootFilesystem[pattern] = access;
11117
+ }
11118
+ function canBeCodexFilesystemRoot(pattern) {
11119
+ return isAbsolute3(pattern) || /^[A-Za-z]:[\\/]/.test(pattern) || pattern.startsWith("~/") || pattern === "~" || pattern.startsWith(":");
11120
+ }
11121
+ function addRulesyncFilesystemRule(permission, pattern, access) {
11122
+ if (access === "none") {
11123
+ permission.read ??= {};
11124
+ permission.edit ??= {};
11125
+ permission.read[pattern] = "deny";
11126
+ permission.edit[pattern] = "deny";
11127
+ } else if (access === "read") {
11128
+ permission.read ??= {};
11129
+ permission.read[pattern] = "allow";
11130
+ } else {
11131
+ permission.edit ??= {};
11132
+ permission.edit[pattern] = "allow";
11133
+ }
11134
+ }
11084
11135
  function toMutableTable(value) {
11085
11136
  if (!value || typeof value !== "object" || Array.isArray(value)) {
11086
11137
  return {};
@@ -11091,8 +11142,33 @@ function toFilesystemRecord(value) {
11091
11142
  if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
11092
11143
  const result = {};
11093
11144
  for (const [key, raw] of Object.entries(value)) {
11094
- if (typeof raw !== "string") continue;
11095
- if (raw === "read" || raw === "write" || raw === "none") {
11145
+ if (isCodexFilesystemAccess(raw)) {
11146
+ result[key] = raw;
11147
+ continue;
11148
+ }
11149
+ if (key === "glob_scan_max_depth" && typeof raw === "number") {
11150
+ result[key] = raw;
11151
+ continue;
11152
+ }
11153
+ const nested = toCodexFilesystemRuleTable(raw);
11154
+ if (nested) {
11155
+ result[key] = nested;
11156
+ }
11157
+ }
11158
+ return Object.keys(result).length > 0 ? result : void 0;
11159
+ }
11160
+ function isCodexFilesystemAccess(value) {
11161
+ return value === "read" || value === "write" || value === "none";
11162
+ }
11163
+ function isCodexFilesystemRuleTable(value) {
11164
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
11165
+ return Object.values(value).every(isCodexFilesystemAccess);
11166
+ }
11167
+ function toCodexFilesystemRuleTable(value) {
11168
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
11169
+ const result = {};
11170
+ for (const [key, raw] of Object.entries(value)) {
11171
+ if (isCodexFilesystemAccess(raw)) {
11096
11172
  result[key] = raw;
11097
11173
  }
11098
11174
  }
@@ -13306,7 +13382,8 @@ var RulesyncSkillFrontmatterSchemaInternal = z39.looseObject({
13306
13382
  "allowed-tools": z39.optional(z39.array(z39.string())),
13307
13383
  model: z39.optional(z39.string()),
13308
13384
  "disable-model-invocation": z39.optional(z39.boolean()),
13309
- "scheduled-task": z39.optional(z39.boolean())
13385
+ "scheduled-task": z39.optional(z39.boolean()),
13386
+ paths: z39.optional(z39.union([z39.string(), z39.array(z39.string())]))
13310
13387
  })
13311
13388
  ),
13312
13389
  codexcli: z39.optional(
@@ -14081,7 +14158,8 @@ var ClaudecodeSkillFrontmatterSchema = z43.looseObject({
14081
14158
  description: z43.string(),
14082
14159
  "allowed-tools": z43.optional(z43.array(z43.string())),
14083
14160
  model: z43.optional(z43.string()),
14084
- "disable-model-invocation": z43.optional(z43.boolean())
14161
+ "disable-model-invocation": z43.optional(z43.boolean()),
14162
+ paths: z43.optional(z43.union([z43.string(), z43.array(z43.string())]))
14085
14163
  });
14086
14164
  var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
14087
14165
  constructor({
@@ -14154,6 +14232,7 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
14154
14232
  ...frontmatter["disable-model-invocation"] !== void 0 && {
14155
14233
  "disable-model-invocation": frontmatter["disable-model-invocation"]
14156
14234
  },
14235
+ ...frontmatter.paths !== void 0 && { paths: frontmatter.paths },
14157
14236
  ...this.relativeDirPath === CLAUDE_SCHEDULED_TASKS_DIR_PATH && { "scheduled-task": true }
14158
14237
  };
14159
14238
  const rulesyncFrontmatter = {
@@ -14191,6 +14270,9 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
14191
14270
  },
14192
14271
  ...rulesyncFrontmatter.claudecode?.["disable-model-invocation"] !== void 0 && {
14193
14272
  "disable-model-invocation": rulesyncFrontmatter.claudecode["disable-model-invocation"]
14273
+ },
14274
+ ...rulesyncFrontmatter.claudecode?.paths !== void 0 && {
14275
+ paths: rulesyncFrontmatter.claudecode.paths
14194
14276
  }
14195
14277
  };
14196
14278
  const settablePaths = _ClaudecodeSkill.getSettablePaths({ global });
@@ -4859,7 +4859,9 @@ async function buildCodexConfigTomlContent({
4859
4859
  if (typeof configToml.features !== "object" || configToml.features === null) {
4860
4860
  configToml.features = {};
4861
4861
  }
4862
- configToml.features.codex_hooks = true;
4862
+ const features = configToml.features;
4863
+ delete features.codex_hooks;
4864
+ features.hooks = true;
4863
4865
  return smolToml2.stringify(configToml);
4864
4866
  }
4865
4867
  var CodexcliConfigToml = class _CodexcliConfigToml extends ToolFile {
@@ -10934,6 +10936,8 @@ var import_node_path71 = require("path");
10934
10936
  var smolToml4 = __toESM(require("smol-toml"), 1);
10935
10937
  var RULESYNC_PROFILE_NAME = "rulesync";
10936
10938
  var RULESYNC_BASH_RULES_FILE_NAME = "rulesync.rules";
10939
+ var CODEX_PROJECT_ROOTS_KEY = ":project_roots";
10940
+ var CODEX_GLOB_SCAN_MAX_DEPTH = 8;
10937
10941
  var CodexcliPermissions = class _CodexcliPermissions extends ToolPermissions {
10938
10942
  static getSettablePaths(_options = {}) {
10939
10943
  return {
@@ -11044,17 +11048,28 @@ function convertRulesyncToCodexProfile({
11044
11048
  logger: logger5
11045
11049
  }) {
11046
11050
  const filesystem = {};
11051
+ const projectRootFilesystem = {};
11047
11052
  const domains = {};
11048
11053
  for (const [toolName, rules] of Object.entries(config.permission)) {
11049
11054
  if (toolName === "read") {
11050
11055
  for (const [pattern, action] of Object.entries(rules)) {
11051
- filesystem[pattern] = mapReadAction(action);
11056
+ addFilesystemRule({
11057
+ filesystem,
11058
+ projectRootFilesystem,
11059
+ pattern,
11060
+ access: mapReadAction(action)
11061
+ });
11052
11062
  }
11053
11063
  continue;
11054
11064
  }
11055
11065
  if (toolName === "edit" || toolName === "write") {
11056
11066
  for (const [pattern, action] of Object.entries(rules)) {
11057
- filesystem[pattern] = mapWriteAction(action);
11067
+ addFilesystemRule({
11068
+ filesystem,
11069
+ projectRootFilesystem,
11070
+ pattern,
11071
+ access: mapWriteAction(action)
11072
+ });
11058
11073
  }
11059
11074
  continue;
11060
11075
  }
@@ -11074,6 +11089,12 @@ function convertRulesyncToCodexProfile({
11074
11089
  `Codex CLI permissions support only read/edit/write/webfetch categories. Skipping: ${toolName}`
11075
11090
  );
11076
11091
  }
11092
+ if (Object.keys(projectRootFilesystem).length > 0) {
11093
+ if (Object.keys(projectRootFilesystem).some((pattern) => pattern.includes("**"))) {
11094
+ filesystem.glob_scan_max_depth = CODEX_GLOB_SCAN_MAX_DEPTH;
11095
+ }
11096
+ filesystem[CODEX_PROJECT_ROOTS_KEY] = projectRootFilesystem;
11097
+ }
11077
11098
  return {
11078
11099
  ...Object.keys(filesystem).length > 0 ? { filesystem } : {},
11079
11100
  ...Object.keys(domains).length > 0 ? { network: { domains } } : {}
@@ -11085,13 +11106,14 @@ function convertCodexProfileToRulesync(profile) {
11085
11106
  permission.read = {};
11086
11107
  permission.edit = {};
11087
11108
  for (const [pattern, access] of Object.entries(profile.filesystem)) {
11088
- if (access === "none") {
11089
- permission.read[pattern] = "deny";
11090
- permission.edit[pattern] = "deny";
11091
- } else if (access === "read") {
11092
- permission.read[pattern] = "allow";
11093
- } else {
11094
- permission.edit[pattern] = "allow";
11109
+ if (isCodexFilesystemAccess(access)) {
11110
+ addRulesyncFilesystemRule(permission, pattern, access);
11111
+ continue;
11112
+ }
11113
+ if (isCodexFilesystemRuleTable(access)) {
11114
+ for (const [nestedPattern, nestedAccess] of Object.entries(access)) {
11115
+ addRulesyncFilesystemRule(permission, nestedPattern, nestedAccess);
11116
+ }
11095
11117
  }
11096
11118
  }
11097
11119
  }
@@ -11114,6 +11136,35 @@ function toCodexProfile(value) {
11114
11136
  ...domains ? { network: { domains } } : {}
11115
11137
  };
11116
11138
  }
11139
+ function addFilesystemRule({
11140
+ filesystem,
11141
+ projectRootFilesystem,
11142
+ pattern,
11143
+ access
11144
+ }) {
11145
+ if (canBeCodexFilesystemRoot(pattern)) {
11146
+ filesystem[pattern] = access;
11147
+ return;
11148
+ }
11149
+ projectRootFilesystem[pattern] = access;
11150
+ }
11151
+ function canBeCodexFilesystemRoot(pattern) {
11152
+ return (0, import_node_path71.isAbsolute)(pattern) || /^[A-Za-z]:[\\/]/.test(pattern) || pattern.startsWith("~/") || pattern === "~" || pattern.startsWith(":");
11153
+ }
11154
+ function addRulesyncFilesystemRule(permission, pattern, access) {
11155
+ if (access === "none") {
11156
+ permission.read ??= {};
11157
+ permission.edit ??= {};
11158
+ permission.read[pattern] = "deny";
11159
+ permission.edit[pattern] = "deny";
11160
+ } else if (access === "read") {
11161
+ permission.read ??= {};
11162
+ permission.read[pattern] = "allow";
11163
+ } else {
11164
+ permission.edit ??= {};
11165
+ permission.edit[pattern] = "allow";
11166
+ }
11167
+ }
11117
11168
  function toMutableTable(value) {
11118
11169
  if (!value || typeof value !== "object" || Array.isArray(value)) {
11119
11170
  return {};
@@ -11124,8 +11175,33 @@ function toFilesystemRecord(value) {
11124
11175
  if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
11125
11176
  const result = {};
11126
11177
  for (const [key, raw] of Object.entries(value)) {
11127
- if (typeof raw !== "string") continue;
11128
- if (raw === "read" || raw === "write" || raw === "none") {
11178
+ if (isCodexFilesystemAccess(raw)) {
11179
+ result[key] = raw;
11180
+ continue;
11181
+ }
11182
+ if (key === "glob_scan_max_depth" && typeof raw === "number") {
11183
+ result[key] = raw;
11184
+ continue;
11185
+ }
11186
+ const nested = toCodexFilesystemRuleTable(raw);
11187
+ if (nested) {
11188
+ result[key] = nested;
11189
+ }
11190
+ }
11191
+ return Object.keys(result).length > 0 ? result : void 0;
11192
+ }
11193
+ function isCodexFilesystemAccess(value) {
11194
+ return value === "read" || value === "write" || value === "none";
11195
+ }
11196
+ function isCodexFilesystemRuleTable(value) {
11197
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
11198
+ return Object.values(value).every(isCodexFilesystemAccess);
11199
+ }
11200
+ function toCodexFilesystemRuleTable(value) {
11201
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
11202
+ const result = {};
11203
+ for (const [key, raw] of Object.entries(value)) {
11204
+ if (isCodexFilesystemAccess(raw)) {
11129
11205
  result[key] = raw;
11130
11206
  }
11131
11207
  }
@@ -13339,7 +13415,8 @@ var RulesyncSkillFrontmatterSchemaInternal = import_mini39.z.looseObject({
13339
13415
  "allowed-tools": import_mini39.z.optional(import_mini39.z.array(import_mini39.z.string())),
13340
13416
  model: import_mini39.z.optional(import_mini39.z.string()),
13341
13417
  "disable-model-invocation": import_mini39.z.optional(import_mini39.z.boolean()),
13342
- "scheduled-task": import_mini39.z.optional(import_mini39.z.boolean())
13418
+ "scheduled-task": import_mini39.z.optional(import_mini39.z.boolean()),
13419
+ paths: import_mini39.z.optional(import_mini39.z.union([import_mini39.z.string(), import_mini39.z.array(import_mini39.z.string())]))
13343
13420
  })
13344
13421
  ),
13345
13422
  codexcli: import_mini39.z.optional(
@@ -14114,7 +14191,8 @@ var ClaudecodeSkillFrontmatterSchema = import_mini43.z.looseObject({
14114
14191
  description: import_mini43.z.string(),
14115
14192
  "allowed-tools": import_mini43.z.optional(import_mini43.z.array(import_mini43.z.string())),
14116
14193
  model: import_mini43.z.optional(import_mini43.z.string()),
14117
- "disable-model-invocation": import_mini43.z.optional(import_mini43.z.boolean())
14194
+ "disable-model-invocation": import_mini43.z.optional(import_mini43.z.boolean()),
14195
+ paths: import_mini43.z.optional(import_mini43.z.union([import_mini43.z.string(), import_mini43.z.array(import_mini43.z.string())]))
14118
14196
  });
14119
14197
  var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
14120
14198
  constructor({
@@ -14187,6 +14265,7 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
14187
14265
  ...frontmatter["disable-model-invocation"] !== void 0 && {
14188
14266
  "disable-model-invocation": frontmatter["disable-model-invocation"]
14189
14267
  },
14268
+ ...frontmatter.paths !== void 0 && { paths: frontmatter.paths },
14190
14269
  ...this.relativeDirPath === CLAUDE_SCHEDULED_TASKS_DIR_PATH && { "scheduled-task": true }
14191
14270
  };
14192
14271
  const rulesyncFrontmatter = {
@@ -14224,6 +14303,9 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
14224
14303
  },
14225
14304
  ...rulesyncFrontmatter.claudecode?.["disable-model-invocation"] !== void 0 && {
14226
14305
  "disable-model-invocation": rulesyncFrontmatter.claudecode["disable-model-invocation"]
14306
+ },
14307
+ ...rulesyncFrontmatter.claudecode?.paths !== void 0 && {
14308
+ paths: rulesyncFrontmatter.claudecode.paths
14227
14309
  }
14228
14310
  };
14229
14311
  const settablePaths = _ClaudecodeSkill.getSettablePaths({ global });
@@ -31629,7 +31711,7 @@ function wrapCommand({
31629
31711
  }
31630
31712
 
31631
31713
  // src/cli/index.ts
31632
- var getVersion = () => "8.15.1";
31714
+ var getVersion = () => "8.16.0";
31633
31715
  function wrapCommand2(name, errorCode, handler) {
31634
31716
  return wrapCommand({ name, errorCode, handler, getVersion });
31635
31717
  }
package/dist/cli/index.js CHANGED
@@ -79,7 +79,7 @@ import {
79
79
  stringifyFrontmatter,
80
80
  toPosixPath,
81
81
  writeFileContent
82
- } from "../chunk-3DM6NLND.js";
82
+ } from "../chunk-DOWXY74I.js";
83
83
 
84
84
  // src/cli/index.ts
85
85
  import { Command } from "commander";
@@ -6485,7 +6485,7 @@ function wrapCommand({
6485
6485
  }
6486
6486
 
6487
6487
  // src/cli/index.ts
6488
- var getVersion = () => "8.15.1";
6488
+ var getVersion = () => "8.16.0";
6489
6489
  function wrapCommand2(name, errorCode, handler) {
6490
6490
  return wrapCommand({ name, errorCode, handler, getVersion });
6491
6491
  }
package/dist/index.cjs CHANGED
@@ -4732,7 +4732,9 @@ async function buildCodexConfigTomlContent({
4732
4732
  if (typeof configToml.features !== "object" || configToml.features === null) {
4733
4733
  configToml.features = {};
4734
4734
  }
4735
- configToml.features.codex_hooks = true;
4735
+ const features = configToml.features;
4736
+ delete features.codex_hooks;
4737
+ features.hooks = true;
4736
4738
  return smolToml2.stringify(configToml);
4737
4739
  }
4738
4740
  var CodexcliConfigToml = class _CodexcliConfigToml extends ToolFile {
@@ -10807,6 +10809,8 @@ var import_node_path71 = require("path");
10807
10809
  var smolToml4 = __toESM(require("smol-toml"), 1);
10808
10810
  var RULESYNC_PROFILE_NAME = "rulesync";
10809
10811
  var RULESYNC_BASH_RULES_FILE_NAME = "rulesync.rules";
10812
+ var CODEX_PROJECT_ROOTS_KEY = ":project_roots";
10813
+ var CODEX_GLOB_SCAN_MAX_DEPTH = 8;
10810
10814
  var CodexcliPermissions = class _CodexcliPermissions extends ToolPermissions {
10811
10815
  static getSettablePaths(_options = {}) {
10812
10816
  return {
@@ -10917,17 +10921,28 @@ function convertRulesyncToCodexProfile({
10917
10921
  logger
10918
10922
  }) {
10919
10923
  const filesystem = {};
10924
+ const projectRootFilesystem = {};
10920
10925
  const domains = {};
10921
10926
  for (const [toolName, rules] of Object.entries(config.permission)) {
10922
10927
  if (toolName === "read") {
10923
10928
  for (const [pattern, action] of Object.entries(rules)) {
10924
- filesystem[pattern] = mapReadAction(action);
10929
+ addFilesystemRule({
10930
+ filesystem,
10931
+ projectRootFilesystem,
10932
+ pattern,
10933
+ access: mapReadAction(action)
10934
+ });
10925
10935
  }
10926
10936
  continue;
10927
10937
  }
10928
10938
  if (toolName === "edit" || toolName === "write") {
10929
10939
  for (const [pattern, action] of Object.entries(rules)) {
10930
- filesystem[pattern] = mapWriteAction(action);
10940
+ addFilesystemRule({
10941
+ filesystem,
10942
+ projectRootFilesystem,
10943
+ pattern,
10944
+ access: mapWriteAction(action)
10945
+ });
10931
10946
  }
10932
10947
  continue;
10933
10948
  }
@@ -10947,6 +10962,12 @@ function convertRulesyncToCodexProfile({
10947
10962
  `Codex CLI permissions support only read/edit/write/webfetch categories. Skipping: ${toolName}`
10948
10963
  );
10949
10964
  }
10965
+ if (Object.keys(projectRootFilesystem).length > 0) {
10966
+ if (Object.keys(projectRootFilesystem).some((pattern) => pattern.includes("**"))) {
10967
+ filesystem.glob_scan_max_depth = CODEX_GLOB_SCAN_MAX_DEPTH;
10968
+ }
10969
+ filesystem[CODEX_PROJECT_ROOTS_KEY] = projectRootFilesystem;
10970
+ }
10950
10971
  return {
10951
10972
  ...Object.keys(filesystem).length > 0 ? { filesystem } : {},
10952
10973
  ...Object.keys(domains).length > 0 ? { network: { domains } } : {}
@@ -10958,13 +10979,14 @@ function convertCodexProfileToRulesync(profile) {
10958
10979
  permission.read = {};
10959
10980
  permission.edit = {};
10960
10981
  for (const [pattern, access] of Object.entries(profile.filesystem)) {
10961
- if (access === "none") {
10962
- permission.read[pattern] = "deny";
10963
- permission.edit[pattern] = "deny";
10964
- } else if (access === "read") {
10965
- permission.read[pattern] = "allow";
10966
- } else {
10967
- permission.edit[pattern] = "allow";
10982
+ if (isCodexFilesystemAccess(access)) {
10983
+ addRulesyncFilesystemRule(permission, pattern, access);
10984
+ continue;
10985
+ }
10986
+ if (isCodexFilesystemRuleTable(access)) {
10987
+ for (const [nestedPattern, nestedAccess] of Object.entries(access)) {
10988
+ addRulesyncFilesystemRule(permission, nestedPattern, nestedAccess);
10989
+ }
10968
10990
  }
10969
10991
  }
10970
10992
  }
@@ -10987,6 +11009,35 @@ function toCodexProfile(value) {
10987
11009
  ...domains ? { network: { domains } } : {}
10988
11010
  };
10989
11011
  }
11012
+ function addFilesystemRule({
11013
+ filesystem,
11014
+ projectRootFilesystem,
11015
+ pattern,
11016
+ access
11017
+ }) {
11018
+ if (canBeCodexFilesystemRoot(pattern)) {
11019
+ filesystem[pattern] = access;
11020
+ return;
11021
+ }
11022
+ projectRootFilesystem[pattern] = access;
11023
+ }
11024
+ function canBeCodexFilesystemRoot(pattern) {
11025
+ return (0, import_node_path71.isAbsolute)(pattern) || /^[A-Za-z]:[\\/]/.test(pattern) || pattern.startsWith("~/") || pattern === "~" || pattern.startsWith(":");
11026
+ }
11027
+ function addRulesyncFilesystemRule(permission, pattern, access) {
11028
+ if (access === "none") {
11029
+ permission.read ??= {};
11030
+ permission.edit ??= {};
11031
+ permission.read[pattern] = "deny";
11032
+ permission.edit[pattern] = "deny";
11033
+ } else if (access === "read") {
11034
+ permission.read ??= {};
11035
+ permission.read[pattern] = "allow";
11036
+ } else {
11037
+ permission.edit ??= {};
11038
+ permission.edit[pattern] = "allow";
11039
+ }
11040
+ }
10990
11041
  function toMutableTable(value) {
10991
11042
  if (!value || typeof value !== "object" || Array.isArray(value)) {
10992
11043
  return {};
@@ -10997,8 +11048,33 @@ function toFilesystemRecord(value) {
10997
11048
  if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
10998
11049
  const result = {};
10999
11050
  for (const [key, raw] of Object.entries(value)) {
11000
- if (typeof raw !== "string") continue;
11001
- if (raw === "read" || raw === "write" || raw === "none") {
11051
+ if (isCodexFilesystemAccess(raw)) {
11052
+ result[key] = raw;
11053
+ continue;
11054
+ }
11055
+ if (key === "glob_scan_max_depth" && typeof raw === "number") {
11056
+ result[key] = raw;
11057
+ continue;
11058
+ }
11059
+ const nested = toCodexFilesystemRuleTable(raw);
11060
+ if (nested) {
11061
+ result[key] = nested;
11062
+ }
11063
+ }
11064
+ return Object.keys(result).length > 0 ? result : void 0;
11065
+ }
11066
+ function isCodexFilesystemAccess(value) {
11067
+ return value === "read" || value === "write" || value === "none";
11068
+ }
11069
+ function isCodexFilesystemRuleTable(value) {
11070
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
11071
+ return Object.values(value).every(isCodexFilesystemAccess);
11072
+ }
11073
+ function toCodexFilesystemRuleTable(value) {
11074
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
11075
+ const result = {};
11076
+ for (const [key, raw] of Object.entries(value)) {
11077
+ if (isCodexFilesystemAccess(raw)) {
11002
11078
  result[key] = raw;
11003
11079
  }
11004
11080
  }
@@ -13212,7 +13288,8 @@ var RulesyncSkillFrontmatterSchemaInternal = import_mini39.z.looseObject({
13212
13288
  "allowed-tools": import_mini39.z.optional(import_mini39.z.array(import_mini39.z.string())),
13213
13289
  model: import_mini39.z.optional(import_mini39.z.string()),
13214
13290
  "disable-model-invocation": import_mini39.z.optional(import_mini39.z.boolean()),
13215
- "scheduled-task": import_mini39.z.optional(import_mini39.z.boolean())
13291
+ "scheduled-task": import_mini39.z.optional(import_mini39.z.boolean()),
13292
+ paths: import_mini39.z.optional(import_mini39.z.union([import_mini39.z.string(), import_mini39.z.array(import_mini39.z.string())]))
13216
13293
  })
13217
13294
  ),
13218
13295
  codexcli: import_mini39.z.optional(
@@ -13987,7 +14064,8 @@ var ClaudecodeSkillFrontmatterSchema = import_mini43.z.looseObject({
13987
14064
  description: import_mini43.z.string(),
13988
14065
  "allowed-tools": import_mini43.z.optional(import_mini43.z.array(import_mini43.z.string())),
13989
14066
  model: import_mini43.z.optional(import_mini43.z.string()),
13990
- "disable-model-invocation": import_mini43.z.optional(import_mini43.z.boolean())
14067
+ "disable-model-invocation": import_mini43.z.optional(import_mini43.z.boolean()),
14068
+ paths: import_mini43.z.optional(import_mini43.z.union([import_mini43.z.string(), import_mini43.z.array(import_mini43.z.string())]))
13991
14069
  });
13992
14070
  var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
13993
14071
  constructor({
@@ -14060,6 +14138,7 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
14060
14138
  ...frontmatter["disable-model-invocation"] !== void 0 && {
14061
14139
  "disable-model-invocation": frontmatter["disable-model-invocation"]
14062
14140
  },
14141
+ ...frontmatter.paths !== void 0 && { paths: frontmatter.paths },
14063
14142
  ...this.relativeDirPath === CLAUDE_SCHEDULED_TASKS_DIR_PATH && { "scheduled-task": true }
14064
14143
  };
14065
14144
  const rulesyncFrontmatter = {
@@ -14097,6 +14176,9 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
14097
14176
  },
14098
14177
  ...rulesyncFrontmatter.claudecode?.["disable-model-invocation"] !== void 0 && {
14099
14178
  "disable-model-invocation": rulesyncFrontmatter.claudecode["disable-model-invocation"]
14179
+ },
14180
+ ...rulesyncFrontmatter.claudecode?.paths !== void 0 && {
14181
+ paths: rulesyncFrontmatter.claudecode.paths
14100
14182
  }
14101
14183
  };
14102
14184
  const settablePaths = _ClaudecodeSkill.getSettablePaths({ global });
package/dist/index.d.cts CHANGED
@@ -183,6 +183,7 @@ declare const RulesyncSkillFrontmatterSchemaInternal: z.ZodMiniObject<{
183
183
  model: z.ZodMiniOptional<z.ZodMiniString<string>>;
184
184
  "disable-model-invocation": z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
185
185
  "scheduled-task": z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
186
+ paths: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
186
187
  }, z.core.$loose>>;
187
188
  codexcli: z.ZodMiniOptional<z.ZodMiniObject<{
188
189
  "short-description": z.ZodMiniOptional<z.ZodMiniString<string>>;
@@ -214,6 +215,7 @@ type RulesyncSkillFrontmatterInput = {
214
215
  model?: string;
215
216
  "disable-model-invocation"?: boolean;
216
217
  "scheduled-task"?: boolean;
218
+ paths?: string | string[];
217
219
  };
218
220
  codexcli?: {
219
221
  "short-description"?: string;
package/dist/index.d.ts CHANGED
@@ -183,6 +183,7 @@ declare const RulesyncSkillFrontmatterSchemaInternal: z.ZodMiniObject<{
183
183
  model: z.ZodMiniOptional<z.ZodMiniString<string>>;
184
184
  "disable-model-invocation": z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
185
185
  "scheduled-task": z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
186
+ paths: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniArray<z.ZodMiniString<string>>]>>;
186
187
  }, z.core.$loose>>;
187
188
  codexcli: z.ZodMiniOptional<z.ZodMiniObject<{
188
189
  "short-description": z.ZodMiniOptional<z.ZodMiniString<string>>;
@@ -214,6 +215,7 @@ type RulesyncSkillFrontmatterInput = {
214
215
  model?: string;
215
216
  "disable-model-invocation"?: boolean;
216
217
  "scheduled-task"?: boolean;
218
+ paths?: string | string[];
217
219
  };
218
220
  codexcli?: {
219
221
  "short-description"?: string;
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  convertFromTool,
8
8
  generate,
9
9
  importFromTool
10
- } from "./chunk-3DM6NLND.js";
10
+ } from "./chunk-DOWXY74I.js";
11
11
 
12
12
  // src/index.ts
13
13
  async function generate2(options = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rulesync",
3
- "version": "8.15.1",
3
+ "version": "8.16.0",
4
4
  "description": "Unified AI rules management CLI tool that generates configuration files for various AI development tools",
5
5
  "keywords": [
6
6
  "ai",