axconfig 3.6.0 → 3.6.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # axconfig
2
2
 
3
- Unified configuration management for AI coding agents — common API for permissions, settings, and config across Claude Code, Codex, Gemini CLI, and OpenCode.
3
+ Unified configuration management for AI coding agents — common API for permissions, settings, and config across Claude Code, Codex, Gemini CLI, GitHub Copilot CLI, and OpenCode.
4
4
 
5
5
  ## Overview
6
6
 
@@ -26,11 +26,11 @@ Unified syntax for all agents:
26
26
 
27
27
  ```bash
28
28
  # Tool permissions
29
- read, write, edit, bash, glob, grep, web
29
+ read, write, bash, glob, grep, webfetch
30
30
 
31
31
  # Bash command patterns
32
32
  bash:git *
33
- bash:npm run build
33
+ bash:npm run build*
34
34
 
35
35
  # Path restrictions (agent-dependent)
36
36
  read:src/**
@@ -45,19 +45,27 @@ Translates unified permissions to agent-specific formats:
45
45
  | -------- | --------------------------------------------------------- |
46
46
  | claude | JSON `settings.json` with `permissions.allow/deny` arrays |
47
47
  | codex | TOML `config.toml` + Starlark `.rules` files |
48
- | gemini | TOML policy files with `[[rule]]` entries |
48
+ | copilot | JSON `config.json` (no pre-configured permissions) |
49
+ | gemini | JSON `settings.json` + TOML policy files in `policies/` |
49
50
  | opencode | JSON with `permission.{edit,bash,webfetch}` |
50
51
 
51
52
  ### Capability Validation
52
53
 
53
54
  Each agent has different capabilities:
54
55
 
55
- | Agent | Tool Perms | Bash Patterns | Path Restrictions | Can Deny Read |
56
- | -------- | ----------- | ------------- | ----------------- | ------------- |
57
- | claude | ✓ | ✓ | ✓ | ✓ |
58
- | codex | ✗ (sandbox) | ✓ | ✗ | ✗ |
59
- | gemini | | | ✗ | |
60
- | opencode | ✓ | ✓ | ✗ | ✓ |
56
+ | Agent | Tool Perms | Bash Patterns | Path Restrictions | Can Deny Read | Notes |
57
+ | -------- | ----------- | ------------- | ----------------- | ------------- | -------------------------------------------- |
58
+ | claude | ✓ | ✓ | ✓ | ✓ | Permissions + OS-level sandbox |
59
+ | codex | ✗ (sandbox) | ✓ | ✗ | ✗ | OS-level sandbox (Landlock+seccomp/Seatbelt) |
60
+ | copilot | | | ✗ | | Runtime prompts only (no pre-config) |
61
+ | gemini | ✓ | ✓ | ✗ | ✓ | Permissions only (no sandbox) |
62
+ | opencode | ✓ | ✓ | ✓ | ✓ | UX-only permissions (no sandbox) |
63
+
64
+ **Security notes:**
65
+
66
+ - **Claude Code** manages application-level permissions; OS-level sandbox settings (network filtering, filesystem isolation) are configured separately
67
+ - **Copilot CLI** does not support pre-configured permissions; all actions require runtime approval prompts
68
+ - **OpenCode** permissions are UX-only to keep users informed; they do not provide security isolation
61
69
 
62
70
  axconfig validates permissions against agent capabilities:
63
71
 
@@ -217,6 +225,7 @@ src/
217
225
  └── agents/
218
226
  ├── claude.ts # Claude Code config builder + reader
219
227
  ├── codex.ts # Codex config builder + reader
228
+ ├── copilot.ts # GitHub Copilot CLI config builder + reader
220
229
  ├── gemini.ts # Gemini CLI config builder + reader
221
230
  └── opencode.ts # OpenCode config builder + reader
222
231
  ```
@@ -232,7 +241,7 @@ Run `npx -y axconfig --help` to learn available options.
232
241
 
233
242
  Use `axconfig` to manage AI agent configurations with unified permission syntax.
234
243
  It translates `--allow` and `--deny` rules to agent-specific formats (Claude Code,
235
- Codex, Gemini CLI, OpenCode).
244
+ Codex, Gemini CLI, GitHub Copilot CLI, OpenCode).
236
245
  ```
237
246
 
238
247
  ## License
@@ -13,15 +13,15 @@ import { createJsonConfigOperations, readJsonConfig, } from "../read-write-json-
13
13
  const REVERSE_TOOL_MAP = {
14
14
  Read: "read",
15
15
  Write: "write",
16
- Edit: "edit",
16
+ Edit: "write", // Claude's Edit tool maps to canonical "write"
17
17
  Bash: "bash",
18
18
  Glob: "glob",
19
19
  Grep: "grep",
20
- WebFetch: "web",
21
- WebSearch: "web",
20
+ WebFetch: "webfetch",
21
+ WebSearch: "webfetch",
22
22
  };
23
23
  /** Path-restricted tools (lowercase) */
24
- const PATH_TOOLS = new Set(["read", "write", "edit"]);
24
+ const PATH_TOOLS = new Set(["read", "write"]);
25
25
  /**
26
26
  * Get the settings.json path for a config directory.
27
27
  */
@@ -17,12 +17,11 @@ export { claudeCodeConfigReader } from "./claude-reader.js";
17
17
  /** Claude Code tool name mapping */
18
18
  const TOOL_MAP = {
19
19
  read: "Read",
20
- write: "Write",
21
- edit: "Edit",
20
+ write: ["Write", "Edit"], // Canonical "write" maps to both Claude's Write and Edit tools
22
21
  bash: "Bash",
23
22
  glob: "Glob",
24
23
  grep: "Grep",
25
- web: "WebFetch",
24
+ webfetch: "WebFetch",
26
25
  };
27
26
  /** Claude Code capabilities */
28
27
  const CAPABILITIES = {
@@ -33,11 +32,13 @@ const CAPABILITIES = {
33
32
  };
34
33
  /**
35
34
  * Translate a permission rule to Claude Code format.
35
+ * Returns an array since some canonical tools map to multiple Claude tools.
36
36
  */
37
37
  function translateRule(rule) {
38
38
  switch (rule.type) {
39
39
  case "tool": {
40
- return TOOL_MAP[rule.name];
40
+ const mapped = TOOL_MAP[rule.name];
41
+ return Array.isArray(mapped) ? mapped : [mapped];
41
42
  }
42
43
  case "bash": {
43
44
  // User provides pattern with explicit trailing *
@@ -46,14 +47,18 @@ function translateRule(rule) {
46
47
  // bash:* (all commands) → Bash (without parentheses)
47
48
  // bash:git* → Bash(git:*)
48
49
  if (prefix === "" || prefix.trim() === "") {
49
- return "Bash";
50
+ return ["Bash"];
50
51
  }
51
- return `Bash(${prefix}:*)`;
52
+ return [`Bash(${prefix}:*)`];
52
53
  }
53
54
  case "path": {
54
55
  // Claude Code uses "Tool(path/**)" for path patterns
56
+ // write:pattern maps to both Write(pattern) and Edit(pattern)
57
+ if (rule.tool === "write") {
58
+ return [`Write(${rule.pattern})`, `Edit(${rule.pattern})`];
59
+ }
55
60
  const toolName = rule.tool.charAt(0).toUpperCase() + rule.tool.slice(1);
56
- return `${toolName}(${rule.pattern})`;
61
+ return [`${toolName}(${rule.pattern})`];
57
62
  }
58
63
  }
59
64
  }
@@ -103,9 +108,9 @@ function build(config, output) {
103
108
  };
104
109
  }
105
110
  // Claude Code supports all permission types, so no warnings/errors needed
106
- // All rules can be translated directly
107
- const allowRules = permissions.allow.map((rule) => translateRule(rule));
108
- const denyRules = permissions.deny.map((rule) => translateRule(rule));
111
+ // All rules can be translated directly (flatMap since translateRule returns arrays)
112
+ const allowRules = permissions.allow.flatMap((rule) => translateRule(rule));
113
+ const denyRules = permissions.deny.flatMap((rule) => translateRule(rule));
109
114
  const settings = {
110
115
  ...existingSettings,
111
116
  permissions: {
@@ -85,7 +85,7 @@ function readPermissions(configDirectory) {
85
85
  const sandboxMode = config.sandbox_mode;
86
86
  if (sandboxMode === "workspace-write" ||
87
87
  sandboxMode === "danger-full-access") {
88
- allowRules.push({ type: "tool", name: "write" }, { type: "tool", name: "edit" });
88
+ allowRules.push({ type: "tool", name: "write" });
89
89
  }
90
90
  // Read is always allowed in Codex sandbox
91
91
  allowRules.push({ type: "tool", name: "read" });
@@ -26,11 +26,11 @@ const CAPABILITIES = {
26
26
  /**
27
27
  * Infer sandbox mode from permissions.
28
28
  *
29
- * - If write or edit is allowed → workspace-write
29
+ * - If write is allowed → workspace-write
30
30
  * - Otherwise → read-only
31
31
  */
32
32
  function inferSandboxMode(permissions) {
33
- const allowsWrite = permissions.allow.some((r) => r.type === "tool" && (r.name === "write" || r.name === "edit"));
33
+ const allowsWrite = permissions.allow.some((r) => r.type === "tool" && r.name === "write");
34
34
  return allowsWrite ? "workspace-write" : "read-only";
35
35
  }
36
36
  /**
@@ -98,9 +98,8 @@ function build(config, output) {
98
98
  });
99
99
  }
100
100
  }
101
- // Tool permissions other than read/write/edit - warn as Codex uses sandbox
102
- const nonFileTools = permissions.allow.filter((r) => r.type === "tool" &&
103
- !["read", "write", "edit", "bash"].includes(r.name));
101
+ // Tool permissions other than read/write - warn as Codex uses sandbox
102
+ const nonFileTools = permissions.allow.filter((r) => r.type === "tool" && !["read", "write", "bash"].includes(r.name));
104
103
  for (const rule of nonFileTools) {
105
104
  if (rule.type === "tool") {
106
105
  warnings.push({
@@ -14,11 +14,11 @@ import { createJsonConfigOperations, readJsonConfig, } from "../read-write-json-
14
14
  const REVERSE_TOOL_MAP = {
15
15
  read_file: "read",
16
16
  write_file: "write",
17
- edit_file: "edit",
17
+ edit_file: "write", // Gemini's edit_file maps to canonical "write"
18
18
  run_shell_command: "bash",
19
19
  glob: "glob",
20
20
  grep: "grep",
21
- web_fetch: "web",
21
+ web_fetch: "webfetch",
22
22
  };
23
23
  /**
24
24
  * Get the settings.json path for a config directory.
@@ -111,7 +111,7 @@ function readModel(configDirectory) {
111
111
  try {
112
112
  const settings = readSettings(configDirectory);
113
113
  const modelObject = settings.model;
114
- if (!modelObject || modelObject.name === undefined) {
114
+ if (modelObject?.name === undefined) {
115
115
  return { ok: true, value: undefined };
116
116
  }
117
117
  if (typeof modelObject.name !== "string") {
@@ -18,12 +18,11 @@ import { readExistingSettings } from "./gemini-settings.js";
18
18
  /** Gemini CLI tool name mapping */
19
19
  const TOOL_MAP = {
20
20
  read: "read_file",
21
- write: "write_file",
22
- edit: "edit_file",
21
+ write: ["write_file", "edit_file"], // Canonical "write" maps to both Gemini's write_file and edit_file
23
22
  bash: "run_shell_command",
24
23
  glob: "glob",
25
24
  grep: "grep",
26
- web: "web_fetch",
25
+ webfetch: "web_fetch",
27
26
  };
28
27
  /** Gemini CLI capabilities */
29
28
  const CAPABILITIES = {
@@ -106,12 +105,19 @@ function build(config, output) {
106
105
  const rules = [];
107
106
  if (permissions) {
108
107
  // Collect tool permissions (excluding path rules which were warned about)
108
+ // Use flatMap since canonical "write" maps to both write_file and edit_file
109
109
  const allowTools = permissions.allow
110
110
  .filter((r) => r.type === "tool")
111
- .map((r) => TOOL_MAP[r.name]);
111
+ .flatMap((r) => {
112
+ const mapped = TOOL_MAP[r.name];
113
+ return Array.isArray(mapped) ? mapped : [mapped];
114
+ });
112
115
  const denyTools = permissions.deny
113
116
  .filter((r) => r.type === "tool")
114
- .map((r) => TOOL_MAP[r.name]);
117
+ .flatMap((r) => {
118
+ const mapped = TOOL_MAP[r.name];
119
+ return Array.isArray(mapped) ? mapped : [mapped];
120
+ });
115
121
  // Collect bash patterns, stripping trailing * since Gemini does prefix matching natively
116
122
  // bash:* (empty prefix after strip) → allow run_shell_command tool entirely
117
123
  // bash:git* → commandPrefix = "git"
@@ -129,7 +135,7 @@ function build(config, output) {
129
135
  // Generate allow rules (high priority)
130
136
  // Include run_shell_command if bash:* is in allow list
131
137
  const effectiveAllowTools = allowAllBash
132
- ? [...allowTools, TOOL_MAP.bash]
138
+ ? [...allowTools, "run_shell_command"]
133
139
  : allowTools;
134
140
  if (effectiveAllowTools.length > 0) {
135
141
  rules.push(generateToolRule(effectiveAllowTools, "allow", 999));
@@ -140,7 +146,7 @@ function build(config, output) {
140
146
  // Generate deny rules (medium priority)
141
147
  // Include run_shell_command if bash:* is in deny list
142
148
  const effectiveDenyTools = denyAllBash
143
- ? [...denyTools, TOOL_MAP.bash]
149
+ ? [...denyTools, "run_shell_command"]
144
150
  : denyTools;
145
151
  if (effectiveDenyTools.length > 0) {
146
152
  rules.push(generateToolRule(effectiveDenyTools, "deny", 500));
@@ -32,9 +32,9 @@ export declare const BASE_PERMISSION_OVERRIDES: Record<string, OpenCodePermissio
32
32
  /**
33
33
  * Collect path patterns from permission rules, grouped by OpenCode permission name.
34
34
  *
35
- * Note: Only read/write/edit rules can have path patterns per the PathPatternRule type.
35
+ * Note: Only read/write rules can have path patterns per the PathPatternRule type.
36
36
  * The TOOL_TO_OPENCODE mapping includes glob/grep for tool-level permissions, but these
37
- * will never appear here since PathRestrictedTool is limited to read/write/edit.
37
+ * will never appear here since PathRestrictedTool is limited to read/write.
38
38
  */
39
39
  export declare function collectPathPatterns(rules: PermissionRule[]): Map<string, string[]>;
40
40
  /**
@@ -8,11 +8,10 @@
8
8
  */
9
9
  const TOOL_TO_OPENCODE = {
10
10
  read: "read",
11
- edit: "edit",
12
- write: "edit", // OpenCode uses single "edit" for both
11
+ write: "edit", // OpenCode uses single "edit" for write operations
13
12
  glob: "glob",
14
13
  grep: "grep",
15
- web: "webfetch",
14
+ webfetch: "webfetch",
16
15
  bash: "bash",
17
16
  };
18
17
  /**
@@ -42,9 +41,9 @@ export const BASE_PERMISSION_OVERRIDES = {
42
41
  /**
43
42
  * Collect path patterns from permission rules, grouped by OpenCode permission name.
44
43
  *
45
- * Note: Only read/write/edit rules can have path patterns per the PathPatternRule type.
44
+ * Note: Only read/write rules can have path patterns per the PathPatternRule type.
46
45
  * The TOOL_TO_OPENCODE mapping includes glob/grep for tool-level permissions, but these
47
- * will never appear here since PathRestrictedTool is limited to read/write/edit.
46
+ * will never appear here since PathRestrictedTool is limited to read/write.
48
47
  */
49
48
  export function collectPathPatterns(rules) {
50
49
  const patterns = new Map();
@@ -120,14 +119,8 @@ export function buildBashPermission(allowPatterns, denyPatterns, bashAllowed, ba
120
119
  export function buildToolPermission(canonicalName, opencodeName, allowedTools, deniedTools, allowPathPatterns, denyPathPatterns) {
121
120
  const hasAllowPatterns = allowPathPatterns.has(opencodeName);
122
121
  const hasDenyPatterns = denyPathPatterns.has(opencodeName);
123
- // Handle write -> edit mapping (both map to same OpenCode permission)
124
- const isEditOrWrite = canonicalName === "edit" || canonicalName === "write";
125
- const effectiveAllowed = isEditOrWrite
126
- ? allowedTools.has("edit") || allowedTools.has("write")
127
- : allowedTools.has(canonicalName);
128
- const effectiveDenied = isEditOrWrite
129
- ? deniedTools.has("edit") || deniedTools.has("write")
130
- : deniedTools.has(canonicalName);
122
+ const effectiveAllowed = allowedTools.has(canonicalName);
123
+ const effectiveDenied = deniedTools.has(canonicalName);
131
124
  if (effectiveDenied && !hasDenyPatterns && !hasAllowPatterns) {
132
125
  return "deny";
133
126
  }
@@ -23,10 +23,10 @@ import { createJsonConfigOperations, readJsonConfig, } from "../read-write-json-
23
23
  */
24
24
  const OPENCODE_TO_TOOL = {
25
25
  read: "read",
26
- edit: ["edit", "write"], // OpenCode's "edit" maps to both canonical tools
26
+ edit: "write", // OpenCode's "edit" maps to canonical "write"
27
27
  glob: "glob",
28
28
  grep: "grep",
29
- webfetch: "web",
29
+ webfetch: "webfetch",
30
30
  bash: "bash",
31
31
  };
32
32
  /**
@@ -55,18 +55,13 @@ function isAllowAction(action) {
55
55
  * Parse a permission value (simple or object-based) and add rules to the arrays.
56
56
  */
57
57
  function parsePermissionValue(opencodeName, value, allowRules, denyRules) {
58
- const canonicalTools = OPENCODE_TO_TOOL[opencodeName];
59
- if (!canonicalTools)
58
+ const canonicalTool = OPENCODE_TO_TOOL[opencodeName];
59
+ if (!canonicalTool)
60
60
  return; // Unknown permission, skip
61
- const tools = Array.isArray(canonicalTools)
62
- ? canonicalTools
63
- : [canonicalTools];
64
61
  if (typeof value === "string") {
65
62
  // Simple value: "allow", "deny", or "ask"
66
63
  const rules = isAllowAction(value) ? allowRules : denyRules;
67
- for (const tool of tools) {
68
- rules.push({ type: "tool", name: tool });
69
- }
64
+ rules.push({ type: "tool", name: canonicalTool });
70
65
  }
71
66
  else if (typeof value === "object") {
72
67
  // Object with patterns
@@ -74,9 +69,7 @@ function parsePermissionValue(opencodeName, value, allowRules, denyRules) {
74
69
  const rules = isAllowAction(action) ? allowRules : denyRules;
75
70
  if (pattern === "*") {
76
71
  // Catch-all represents tool-level permission
77
- for (const tool of tools) {
78
- rules.push({ type: "tool", name: tool });
79
- }
72
+ rules.push({ type: "tool", name: canonicalTool });
80
73
  continue;
81
74
  }
82
75
  if (opencodeName === "bash") {
@@ -84,13 +77,11 @@ function parsePermissionValue(opencodeName, value, allowRules, denyRules) {
84
77
  rules.push({ type: "bash", pattern });
85
78
  }
86
79
  else {
87
- // Only read/write/edit support path patterns in axconfig's type system.
80
+ // Only read/write support path patterns in axconfig's type system.
88
81
  // OpenCode's glob/grep patterns match against glob patterns or regexes,
89
82
  // not file paths, so they're intentionally excluded here.
90
- for (const tool of tools) {
91
- if (tool === "read" || tool === "write" || tool === "edit") {
92
- rules.push({ type: "path", tool, pattern });
93
- }
83
+ if (canonicalTool === "read" || canonicalTool === "write") {
84
+ rules.push({ type: "path", tool: canonicalTool, pattern });
94
85
  }
95
86
  }
96
87
  }
@@ -40,10 +40,10 @@ function buildPermissionConfig(permissions) {
40
40
  // Set permissions for standard tools
41
41
  const tools = [
42
42
  { canonical: "read", opencode: "read" },
43
- { canonical: "edit", opencode: "edit" },
43
+ { canonical: "write", opencode: "edit" }, // OpenCode uses "edit" for write operations
44
44
  { canonical: "glob", opencode: "glob" },
45
45
  { canonical: "grep", opencode: "grep" },
46
- { canonical: "web", opencode: "webfetch" },
46
+ { canonical: "webfetch", opencode: "webfetch" },
47
47
  ];
48
48
  for (const { canonical, opencode } of tools) {
49
49
  permissionConfig[opencode] = buildToolPermission(canonical, opencode, allowedTools, deniedTools, allowPathPatterns, denyPathPatterns);
@@ -85,7 +85,7 @@ function build(config, output) {
85
85
  };
86
86
  atomicWriteFileSync(configPath, JSON.stringify(openCodeConfig, undefined, 2));
87
87
  // Build environment variables:
88
- // - OPENCODE_CONFIG_DIR: axpoint convention for config directory
88
+ // - OPENCODE_CONFIG_DIR: axkit convention for config directory
89
89
  // - XDG_DATA_HOME/XDG_CONFIG_HOME: OpenCode uses these for auth and other XDG-based paths
90
90
  const runtimeEnvironment = buildAgentRuntimeEnvironment("opencode", output);
91
91
  return {
@@ -27,14 +27,13 @@
27
27
  const CANONICAL_TOOLS = new Set([
28
28
  "read",
29
29
  "write",
30
- "edit",
31
30
  "bash",
32
31
  "glob",
33
32
  "grep",
34
- "web",
33
+ "webfetch",
35
34
  ]);
36
35
  /** Tools that support path restrictions */
37
- const PATH_TOOLS = new Set(["read", "write", "edit"]);
36
+ const PATH_TOOLS = new Set(["read", "write"]);
38
37
  /**
39
38
  * Parse a single permission rule string.
40
39
  *
package/dist/types.d.ts CHANGED
@@ -5,9 +5,9 @@
5
5
  */
6
6
  import type { AgentCli } from "axshared";
7
7
  /** Canonical tool names used in axrun permissions */
8
- type CanonicalTool = "read" | "write" | "edit" | "bash" | "glob" | "grep" | "web";
8
+ type CanonicalTool = "read" | "write" | "bash" | "glob" | "grep" | "webfetch";
9
9
  /** Tools that support path restrictions */
10
- type PathRestrictedTool = "read" | "write" | "edit";
10
+ type PathRestrictedTool = "read" | "write";
11
11
  /** Permission rule for a tool (e.g., "read", "bash") */
12
12
  interface ToolPermissionRule {
13
13
  type: "tool";
package/package.json CHANGED
@@ -2,8 +2,8 @@
2
2
  "name": "axconfig",
3
3
  "author": "Łukasz Jerciński",
4
4
  "license": "MIT",
5
- "version": "3.6.0",
6
- "description": "Unified configuration management for AI coding agents - common API for permissions, settings, and config across Claude Code, Codex, Gemini CLI, and OpenCode",
5
+ "version": "3.6.2",
6
+ "description": "Unified configuration management for AI coding agents - common API for permissions, settings, and config across Claude Code, Codex, Gemini CLI, GitHub Copilot CLI, and OpenCode",
7
7
  "repository": {
8
8
  "type": "git",
9
9
  "url": "git+https://github.com/Jercik/axconfig.git"
@@ -55,35 +55,36 @@
55
55
  "configuration",
56
56
  "claude-code",
57
57
  "codex",
58
+ "copilot-cli",
58
59
  "gemini",
59
60
  "opencode",
60
61
  "llm",
61
62
  "automation",
62
63
  "coding-assistant"
63
64
  ],
64
- "packageManager": "pnpm@10.26.1",
65
+ "packageManager": "pnpm@10.28.0",
65
66
  "engines": {
66
67
  "node": ">=22.14.0"
67
68
  },
68
69
  "dependencies": {
69
70
  "@commander-js/extra-typings": "^14.0.0",
70
71
  "@iarna/toml": "^2.2.5",
71
- "axshared": "^1.7.1",
72
+ "axshared": "^4.0.0",
72
73
  "commander": "^14.0.2"
73
74
  },
74
75
  "devDependencies": {
75
76
  "@total-typescript/ts-reset": "^0.6.1",
76
77
  "@types/iarna__toml": "^2.0.5",
77
- "@types/node": "^25.0.3",
78
- "@vitest/coverage-v8": "^4.0.16",
78
+ "@types/node": "^25.0.9",
79
+ "@vitest/coverage-v8": "^4.0.17",
79
80
  "eslint": "^9.39.2",
80
- "eslint-config-axpoint": "^1.0.0",
81
+ "eslint-config-axkit": "^1.1.0",
81
82
  "fta-check": "^1.5.1",
82
83
  "fta-cli": "^3.0.0",
83
- "knip": "^5.79.0",
84
- "prettier": "3.7.4",
84
+ "knip": "^5.82.0",
85
+ "prettier": "3.8.0",
85
86
  "semantic-release": "^25.0.2",
86
87
  "typescript": "^5.9.3",
87
- "vitest": "^4.0.16"
88
+ "vitest": "^4.0.17"
88
89
  }
89
90
  }