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 +20 -11
- package/dist/agents/claude-reader.js +4 -4
- package/dist/agents/claude.js +15 -10
- package/dist/agents/codex-reader.js +1 -1
- package/dist/agents/codex.js +4 -5
- package/dist/agents/gemini-reader.js +3 -3
- package/dist/agents/gemini.js +13 -7
- package/dist/agents/opencode-permission-builder.d.ts +2 -2
- package/dist/agents/opencode-permission-builder.js +6 -13
- package/dist/agents/opencode-reader.js +9 -18
- package/dist/agents/opencode.js +3 -3
- package/dist/parse-permissions.js +2 -3
- package/dist/types.d.ts +2 -2
- package/package.json +11 -10
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,
|
|
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
|
-
|
|
|
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
|
-
|
|
|
60
|
-
|
|
|
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: "
|
|
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: "
|
|
21
|
-
WebSearch: "
|
|
20
|
+
WebFetch: "webfetch",
|
|
21
|
+
WebSearch: "webfetch",
|
|
22
22
|
};
|
|
23
23
|
/** Path-restricted tools (lowercase) */
|
|
24
|
-
const PATH_TOOLS = new Set(["read", "write"
|
|
24
|
+
const PATH_TOOLS = new Set(["read", "write"]);
|
|
25
25
|
/**
|
|
26
26
|
* Get the settings.json path for a config directory.
|
|
27
27
|
*/
|
package/dist/agents/claude.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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.
|
|
108
|
-
const denyRules = permissions.deny.
|
|
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" }
|
|
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" });
|
package/dist/agents/codex.js
CHANGED
|
@@ -26,11 +26,11 @@ const CAPABILITIES = {
|
|
|
26
26
|
/**
|
|
27
27
|
* Infer sandbox mode from permissions.
|
|
28
28
|
*
|
|
29
|
-
* - If 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" &&
|
|
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
|
|
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: "
|
|
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: "
|
|
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 (
|
|
114
|
+
if (modelObject?.name === undefined) {
|
|
115
115
|
return { ok: true, value: undefined };
|
|
116
116
|
}
|
|
117
117
|
if (typeof modelObject.name !== "string") {
|
package/dist/agents/gemini.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
.
|
|
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
|
-
.
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
124
|
-
const
|
|
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:
|
|
26
|
+
edit: "write", // OpenCode's "edit" maps to canonical "write"
|
|
27
27
|
glob: "glob",
|
|
28
28
|
grep: "grep",
|
|
29
|
-
webfetch: "
|
|
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
|
|
59
|
-
if (!
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
91
|
-
|
|
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
|
}
|
package/dist/agents/opencode.js
CHANGED
|
@@ -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: "
|
|
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: "
|
|
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:
|
|
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
|
-
"
|
|
33
|
+
"webfetch",
|
|
35
34
|
]);
|
|
36
35
|
/** Tools that support path restrictions */
|
|
37
|
-
const PATH_TOOLS = new Set(["read", "write"
|
|
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" | "
|
|
8
|
+
type CanonicalTool = "read" | "write" | "bash" | "glob" | "grep" | "webfetch";
|
|
9
9
|
/** Tools that support path restrictions */
|
|
10
|
-
type PathRestrictedTool = "read" | "write"
|
|
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.
|
|
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.
|
|
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": "^
|
|
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.
|
|
78
|
-
"@vitest/coverage-v8": "^4.0.
|
|
78
|
+
"@types/node": "^25.0.9",
|
|
79
|
+
"@vitest/coverage-v8": "^4.0.17",
|
|
79
80
|
"eslint": "^9.39.2",
|
|
80
|
-
"eslint-config-
|
|
81
|
+
"eslint-config-axkit": "^1.1.0",
|
|
81
82
|
"fta-check": "^1.5.1",
|
|
82
83
|
"fta-cli": "^3.0.0",
|
|
83
|
-
"knip": "^5.
|
|
84
|
-
"prettier": "3.
|
|
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.
|
|
88
|
+
"vitest": "^4.0.17"
|
|
88
89
|
}
|
|
89
90
|
}
|