@gotgenes/pi-permission-system 3.11.0 → 4.0.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.
- package/CHANGELOG.md +35 -0
- package/README.md +135 -168
- package/config/config.example.json +11 -21
- package/package.json +1 -1
- package/schemas/permissions.schema.json +34 -102
- package/src/config-loader.ts +87 -118
- package/src/defaults.ts +6 -62
- package/src/extension-config.ts +3 -4
- package/src/normalize.ts +22 -60
- package/src/permission-manager.ts +244 -348
- package/src/synthesize.ts +17 -82
- package/src/types.ts +12 -18
- package/tests/config-loader.test.ts +113 -63
- package/tests/defaults.test.ts +8 -101
- package/tests/extension-config.test.ts +12 -4
- package/tests/normalize.test.ts +67 -64
- package/tests/permission-system.test.ts +153 -714
- package/tests/session-start.test.ts +1 -7
- package/tests/synthesize.test.ts +46 -219
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,41 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [4.0.0](https://github.com/gotgenes/pi-permission-system/compare/v3.11.0...v4.0.0) (2026-05-04)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### ⚠ BREAKING CHANGES
|
|
12
|
+
|
|
13
|
+
* permissions.schema.json replaces defaultPolicy/tools/bash/mcp/ skills/special with a single 'permission' object where each key is a surface name and the value is a PermissionState string or pattern-action map. config.example.json updated to use flat format.
|
|
14
|
+
* warning message now directs users to the flat permission format ({ "permission": { ... } }) instead of the legacy pi-permissions.jsonc paths. The set of detected misplaced keys is unchanged (legacy keys still warned). The flat-format "permission" key is explicitly not flagged.
|
|
15
|
+
* PermissionManager now reads policy from permission.permission (FlatPermissionConfig) instead of defaultPolicy/tools/bash/mcp/skills/special.
|
|
16
|
+
* PermissionDefaultPolicy type is removed from types.ts. ScopeConfig is simplified to { permission?: FlatPermissionConfig }. defaults.ts is stubbed out pending full PermissionManager migration (step 5).
|
|
17
|
+
* UnifiedPermissionConfig now has permission?: FlatPermissionConfig instead of defaultPolicy/tools/bash/mcp/skills/special fields. Legacy files parsed with the flat-format parser produce no permission rules (old-format keys are not translated). Migration warnings are still emitted for legacy file paths.
|
|
18
|
+
* synthesizeDefaults() now accepts PermissionState (the universal default) instead of PermissionDefaultPolicy. synthesizeOverrides() and OverrideScope are removed. composeRuleset() signature reduced from 4 parameters to 3 (no overrides layer). PermissionManager is updated in a follow-up step.
|
|
19
|
+
* introduces FlatPermissionConfig type and normalizeFlatConfig(). The legacy normalizeConfig() remains temporarily until PermissionManager is updated in a follow-up step.
|
|
20
|
+
|
|
21
|
+
### Features
|
|
22
|
+
|
|
23
|
+
* add normalizeFlatConfig for flat permission format ([#66](https://github.com/gotgenes/pi-permission-system/issues/66)) ([c8f6177](https://github.com/gotgenes/pi-permission-system/commit/c8f61770e081447801fa301c661cacd591a4368f))
|
|
24
|
+
* remove PermissionDefaultPolicy and legacy defaults ([#66](https://github.com/gotgenes/pi-permission-system/issues/66)) ([404ffa1](https://github.com/gotgenes/pi-permission-system/commit/404ffa115708b8c6cf02df79910adb0cd0b0ce2f))
|
|
25
|
+
* replace config-loader with flat permission format ([#66](https://github.com/gotgenes/pi-permission-system/issues/66)) ([0bd8d71](https://github.com/gotgenes/pi-permission-system/commit/0bd8d71fa770a290fa3834aa598aa75d71fe6cfc))
|
|
26
|
+
* simplify synthesize layer for flat config ([#66](https://github.com/gotgenes/pi-permission-system/issues/66)) ([c9a73a4](https://github.com/gotgenes/pi-permission-system/commit/c9a73a4d393a36a21e5d0617c1d803806da569e0))
|
|
27
|
+
* update misplaced-key detection for flat format ([#66](https://github.com/gotgenes/pi-permission-system/issues/66)) ([5b8e9da](https://github.com/gotgenes/pi-permission-system/commit/5b8e9da475c056c621759e32d58ba36a67b35174))
|
|
28
|
+
* update PermissionManager for flat permission config ([#66](https://github.com/gotgenes/pi-permission-system/issues/66)) ([eb578b0](https://github.com/gotgenes/pi-permission-system/commit/eb578b0585c7081a703254cf404bb2a6e81a5e06))
|
|
29
|
+
* update schema and example for flat permission format ([#66](https://github.com/gotgenes/pi-permission-system/issues/66)) ([32dd44d](https://github.com/gotgenes/pi-permission-system/commit/32dd44da1ee7498633c22858675f65e4ed36a8e2))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### Documentation
|
|
33
|
+
|
|
34
|
+
* acknowledge MasuRii/pi-permission-system as the upstream origin ([fe8b642](https://github.com/gotgenes/pi-permission-system/commit/fe8b642ba83e2cacfc2f42e460b62d3270f62354))
|
|
35
|
+
* add legacy-to-flat migration guide ([#66](https://github.com/gotgenes/pi-permission-system/issues/66)) ([d415cc4](https://github.com/gotgenes/pi-permission-system/commit/d415cc451c06cf8b580e9924aac0e73fc537872b))
|
|
36
|
+
* add migration guide and fork-language revision to plan ([#66](https://github.com/gotgenes/pi-permission-system/issues/66)) ([be58dd1](https://github.com/gotgenes/pi-permission-system/commit/be58dd18ae85ddbe058f9075244fd36e4538c842))
|
|
37
|
+
* link MasuRii profile and acknowledge OpenCode inspiration ([21e5bc7](https://github.com/gotgenes/pi-permission-system/commit/21e5bc765db26a0cf9109dc396f969bb0c414c02))
|
|
38
|
+
* plan flat permission config format ([#66](https://github.com/gotgenes/pi-permission-system/issues/66)) ([b5e0657](https://github.com/gotgenes/pi-permission-system/commit/b5e0657ab2925c569eac167a604def34b9473284))
|
|
39
|
+
* remove unrelated pi extensions section from README ([22d0057](https://github.com/gotgenes/pi-permission-system/commit/22d0057d8feee6a3ae425e8f19d1dffec4387580))
|
|
40
|
+
* **retro:** add retro notes for issue [#65](https://github.com/gotgenes/pi-permission-system/issues/65) ([9e85dcb](https://github.com/gotgenes/pi-permission-system/commit/9e85dcb8efe95daadb1aaf1704eb0536b91d8d31))
|
|
41
|
+
* revise fork language from friendly to full fork ([#66](https://github.com/gotgenes/pi-permission-system/issues/66)) ([bcea397](https://github.com/gotgenes/pi-permission-system/commit/bcea3973cb2e6bad7a49c594f85418f292a30d23))
|
|
42
|
+
|
|
8
43
|
## [3.11.0](https://github.com/gotgenes/pi-permission-system/compare/v3.10.0...v3.11.0) (2026-05-04)
|
|
9
44
|
|
|
10
45
|
|
package/README.md
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
Permission enforcement extension for the Pi coding agent that provides centralized, deterministic permission gates for tool, bash, MCP, skill, and special operations.
|
|
6
6
|
|
|
7
|
-
> **Fork notice:** This package is a
|
|
8
|
-
>
|
|
9
|
-
> The `/permission-system` slash command name is
|
|
7
|
+
> **Fork notice:** This package is a full fork of [MasuRii/pi-permission-system](https://github.com/MasuRii/pi-permission-system), published to npm as `@gotgenes/pi-permission-system`.
|
|
8
|
+
> It has diverged substantially from upstream in config format, internal architecture, and permission model.
|
|
9
|
+
> The `/permission-system` slash command name is the only upstream identity preserved.
|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
@@ -52,14 +52,8 @@ Pi auto-discovers extensions in these paths.
|
|
|
52
52
|
|
|
53
53
|
```jsonc
|
|
54
54
|
{
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"bash": "ask",
|
|
58
|
-
"mcp": "ask",
|
|
59
|
-
"skills": "ask",
|
|
60
|
-
"special": "ask"
|
|
61
|
-
},
|
|
62
|
-
"tools": {
|
|
55
|
+
"permission": {
|
|
56
|
+
"*": "ask",
|
|
63
57
|
"read": "allow",
|
|
64
58
|
"write": "deny"
|
|
65
59
|
}
|
|
@@ -96,8 +90,8 @@ The extension integrates via Pi's lifecycle hooks:
|
|
|
96
90
|
- When a subagent hits an `ask` permission without direct UI access, the request can be forwarded to the main interactive session for confirmation
|
|
97
91
|
- Generic extension-tool approval prompts include a bounded input preview; built-in file tools use concise human-readable summaries instead of raw multiline JSON
|
|
98
92
|
- Permission review logs include bounded `toolInputPreview` values for non-bash/non-MCP tool calls so approvals can be audited without writing raw full payloads
|
|
99
|
-
- Path-bearing file tools (`read`, `write`, `edit`, `find`, `grep`, `ls`) evaluate `
|
|
100
|
-
- Bash commands are scanned for path tokens (absolute, `~/`, or `..`-relative) that resolve outside `ctx.cwd`; matching commands trigger the same `
|
|
93
|
+
- Path-bearing file tools (`read`, `write`, `edit`, `find`, `grep`, `ls`) evaluate `permission.external_directory` before their normal tool permission when an explicit path points outside `ctx.cwd`
|
|
94
|
+
- Bash commands are scanned for path tokens (absolute, `~/`, or `..`-relative) that resolve outside `ctx.cwd`; matching commands trigger the same `permission.external_directory` gate before the normal bash pattern check
|
|
101
95
|
|
|
102
96
|
## Configuration
|
|
103
97
|
|
|
@@ -111,7 +105,7 @@ The extension integrates via Pi's lifecycle hooks:
|
|
|
111
105
|
| Project | `<cwd>/.pi/extensions/pi-permission-system/config.json` |
|
|
112
106
|
|
|
113
107
|
Project config overrides global config; per-agent frontmatter overrides both.
|
|
114
|
-
|
|
108
|
+
The `permission` object uses deep-shallow merge: string-vs-string replaces; both-object shallow-merges pattern maps; string-vs-object the override wins entirely.
|
|
115
109
|
Scalar fields (`debugLog`, `permissionReviewLog`, `yoloMode`) use simple replacement.
|
|
116
110
|
|
|
117
111
|
The config file combines runtime knobs and permission policy in one object:
|
|
@@ -125,19 +119,16 @@ The config file combines runtime knobs and permission policy in one object:
|
|
|
125
119
|
"permissionReviewLog": true,
|
|
126
120
|
"yoloMode": false,
|
|
127
121
|
|
|
128
|
-
//
|
|
129
|
-
"
|
|
130
|
-
"
|
|
131
|
-
"
|
|
132
|
-
"
|
|
133
|
-
"
|
|
134
|
-
"
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
"mcp": { "mcp_status": "allow" },
|
|
139
|
-
"skills": { "*": "ask" },
|
|
140
|
-
"special": { "external_directory": "ask" }
|
|
122
|
+
// Flat permission policy
|
|
123
|
+
"permission": {
|
|
124
|
+
"*": "ask", // universal fallback
|
|
125
|
+
"read": "allow",
|
|
126
|
+
"write": "deny",
|
|
127
|
+
"bash": { "git status": "allow", "git *": "ask" },
|
|
128
|
+
"mcp": { "mcp_status": "allow" },
|
|
129
|
+
"skill": { "*": "ask" },
|
|
130
|
+
"external_directory": "ask"
|
|
131
|
+
}
|
|
141
132
|
}
|
|
142
133
|
```
|
|
143
134
|
|
|
@@ -156,14 +147,16 @@ No debug output is printed to the terminal.
|
|
|
156
147
|
|
|
157
148
|
The config file is a JSON object with these policy sections:
|
|
158
149
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
|
162
|
-
|
|
|
163
|
-
| `
|
|
164
|
-
| `
|
|
165
|
-
| `
|
|
166
|
-
| `
|
|
150
|
+
The `permission` object maps surface names to actions:
|
|
151
|
+
|
|
152
|
+
| Key | Value type | Description |
|
|
153
|
+
| --- | ---------- | ----------- |
|
|
154
|
+
| `"*"` | string | Universal fallback — applies when no surface-specific rule matches |
|
|
155
|
+
| tool name (e.g. `read`) | string | Catch-all for that tool surface |
|
|
156
|
+
| `bash` | string or object | Bash catch-all or `{ pattern: action }` map |
|
|
157
|
+
| `mcp` | string or object | MCP catch-all or `{ pattern: action }` map |
|
|
158
|
+
| `skill` | string or object | Skill catch-all or `{ pattern: action }` map |
|
|
159
|
+
| `external_directory` | string | Controls access to paths outside `cwd` |
|
|
167
160
|
|
|
168
161
|
> **Note:** Trailing commas are **not** supported. If parsing fails, the extension falls back to `ask` for all categories.
|
|
169
162
|
|
|
@@ -213,159 +206,149 @@ These project files are resolved from Pi's current session `cwd`, so they are wo
|
|
|
213
206
|
3. Global agent frontmatter
|
|
214
207
|
4. Project agent frontmatter
|
|
215
208
|
|
|
216
|
-
Later layers override earlier layers
|
|
209
|
+
Later layers override earlier layers. Within a surface map like `bash` or `mcp`, matching follows **last matching rule wins** — put broad catch-alls first and specific overrides after. The recommended convention is also used by [OpenCode's permission model](https://opencode.ai/docs/permissions/#granular-rules-object-syntax).
|
|
217
210
|
|
|
218
211
|
---
|
|
219
212
|
|
|
220
213
|
## Policy Reference
|
|
221
214
|
|
|
222
|
-
### `
|
|
215
|
+
### `permission["*"]` — universal fallback
|
|
223
216
|
|
|
224
|
-
|
|
217
|
+
The `"*"` key sets the action used when no surface-specific rule matches:
|
|
225
218
|
|
|
226
219
|
```jsonc
|
|
227
220
|
{
|
|
228
|
-
"
|
|
229
|
-
"
|
|
230
|
-
|
|
231
|
-
"mcp": "ask",
|
|
232
|
-
"skills": "ask",
|
|
233
|
-
"special": "ask",
|
|
234
|
-
},
|
|
221
|
+
"permission": {
|
|
222
|
+
"*": "ask"
|
|
223
|
+
}
|
|
235
224
|
}
|
|
236
225
|
```
|
|
237
226
|
|
|
238
|
-
|
|
227
|
+
Omitting `"*"` defaults to `"ask"` (least privilege).
|
|
239
228
|
|
|
240
|
-
|
|
229
|
+
### Tool surfaces
|
|
241
230
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
|
245
|
-
|
|
|
246
|
-
| `
|
|
247
|
-
| `
|
|
248
|
-
| `
|
|
231
|
+
Any registered tool name can be a surface key. A string value is a catch-all for that surface.
|
|
232
|
+
|
|
233
|
+
| Surface example | Description |
|
|
234
|
+
| --------------- | ----------- |
|
|
235
|
+
| `read`, `write`, `edit`, `grep`, `find`, `ls` | Canonical Pi built-in file tools |
|
|
236
|
+
| `bash` | Shell command execution |
|
|
237
|
+
| `mcp` | Registered MCP proxy tool |
|
|
238
|
+
| `task` | Delegation tool |
|
|
239
|
+
| `third_party_tool` | Any other registered extension tool |
|
|
249
240
|
|
|
250
241
|
```jsonc
|
|
251
242
|
{
|
|
252
|
-
"
|
|
243
|
+
"permission": {
|
|
253
244
|
"read": "allow",
|
|
254
245
|
"write": "deny",
|
|
255
|
-
"
|
|
256
|
-
|
|
257
|
-
},
|
|
246
|
+
"third_party_tool": "ask"
|
|
247
|
+
}
|
|
258
248
|
}
|
|
259
249
|
```
|
|
260
250
|
|
|
261
|
-
Unknown or absent tools are not required in the config. If
|
|
251
|
+
Unknown or absent tools are not required in the config. If a tool is not registered at runtime, this extension blocks it before permission checks run.
|
|
262
252
|
|
|
263
|
-
|
|
264
|
-
>
|
|
265
|
-
> **Note:** Setting `tools.mcp` controls coarse access to a registered `mcp` tool when one is available. Specific `mcp` rules still override it when a target pattern matches.
|
|
266
|
-
>
|
|
267
|
-
> **Note:** Top-level shorthand is only supported for the canonical Pi built-ins (`bash`, `read`, `write`, `edit`, `grep`, `find`, `ls`) in agent frontmatter. Use `permission.tools.<name>` for `mcp`, `task`, and any third-party tool.
|
|
253
|
+
### `bash` surface
|
|
268
254
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
Command patterns use `*` wildcards and match against the full command string. If multiple patterns match, the **last matching rule wins**, so put broad fallback rules first and specific overrides after them.
|
|
255
|
+
Command patterns use `*` wildcards matched against the full command string. **Last matching rule wins** — put broad catch-alls first, specific overrides after.
|
|
272
256
|
|
|
273
257
|
```jsonc
|
|
274
258
|
{
|
|
275
|
-
"
|
|
276
|
-
"
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
259
|
+
"permission": {
|
|
260
|
+
"bash": {
|
|
261
|
+
"*": "ask",
|
|
262
|
+
"git status": "allow",
|
|
263
|
+
"git diff": "allow",
|
|
264
|
+
"git *": "ask",
|
|
265
|
+
"rm -rf *": "deny"
|
|
266
|
+
}
|
|
267
|
+
}
|
|
280
268
|
}
|
|
281
269
|
```
|
|
282
270
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
MCP permissions match against derived targets from tool input. These rules are more specific than `tools.mcp` and override that fallback when a pattern matches:
|
|
286
|
-
|
|
287
|
-
| Target Type | Examples |
|
|
288
|
-
| ----------------- | --------------------------------------------------------------------- |
|
|
289
|
-
| Baseline ops | `mcp_status`, `mcp_list`, `mcp_search`, `mcp_describe`, `mcp_connect` |
|
|
290
|
-
| Server name | `myServer` |
|
|
291
|
-
| Server/tool combo | `myServer:search`, `myServer_search` |
|
|
292
|
-
| Generic | `mcp_call` |
|
|
271
|
+
String shorthand sets a catch-all for all bash commands:
|
|
293
272
|
|
|
294
273
|
```jsonc
|
|
295
274
|
{
|
|
296
|
-
"
|
|
297
|
-
"mcp_status": "allow",
|
|
298
|
-
"mcp_list": "allow",
|
|
299
|
-
"myServer:*": "ask",
|
|
300
|
-
"dangerousServer": "deny",
|
|
301
|
-
},
|
|
275
|
+
"permission": { "bash": "allow" }
|
|
302
276
|
}
|
|
303
277
|
```
|
|
304
278
|
|
|
305
|
-
|
|
279
|
+
### `mcp` surface
|
|
306
280
|
|
|
307
|
-
|
|
281
|
+
MCP permissions match against derived targets from tool input:
|
|
308
282
|
|
|
309
|
-
|
|
283
|
+
| Target type | Examples |
|
|
284
|
+
| ----------- | -------- |
|
|
285
|
+
| Baseline ops | `mcp_status`, `mcp_list`, `mcp_search`, `mcp_describe`, `mcp_connect` |
|
|
286
|
+
| Server name | `myServer` |
|
|
287
|
+
| Server/tool combo | `myServer:search`, `myServer_search` |
|
|
288
|
+
| Generic | `mcp_call` |
|
|
310
289
|
|
|
311
290
|
```jsonc
|
|
312
291
|
{
|
|
313
|
-
"
|
|
314
|
-
"mcp":
|
|
315
|
-
|
|
292
|
+
"permission": {
|
|
293
|
+
"mcp": {
|
|
294
|
+
"*": "ask",
|
|
295
|
+
"mcp_status": "allow",
|
|
296
|
+
"mcp_list": "allow",
|
|
297
|
+
"myServer:*": "ask",
|
|
298
|
+
"dangerousServer": "deny"
|
|
299
|
+
}
|
|
300
|
+
}
|
|
316
301
|
}
|
|
317
302
|
```
|
|
318
303
|
|
|
319
|
-
|
|
304
|
+
> **Note:** Baseline discovery targets auto-allow when any explicit `mcp: allow` rule exists.
|
|
305
|
+
|
|
306
|
+
String shorthand grants broad MCP access — useful for per-agent overrides:
|
|
320
307
|
|
|
321
308
|
```yaml
|
|
322
|
-
#
|
|
309
|
+
# ~/.pi/agent/agents/researcher.md (respects PI_CODING_AGENT_DIR)
|
|
323
310
|
---
|
|
324
311
|
name: researcher
|
|
325
312
|
permission:
|
|
326
|
-
|
|
327
|
-
mcp: allow
|
|
313
|
+
mcp: allow
|
|
328
314
|
---
|
|
329
315
|
```
|
|
330
316
|
|
|
331
|
-
|
|
317
|
+
### `skill` surface
|
|
332
318
|
|
|
333
|
-
|
|
334
|
-
2. `tools.mcp` fallback (if set)
|
|
335
|
-
3. `defaultPolicy.mcp`
|
|
336
|
-
|
|
337
|
-
### `skills`
|
|
338
|
-
|
|
339
|
-
Skill name patterns use `*` wildcards:
|
|
319
|
+
Skill name patterns use `*` wildcards (note: surface is `skill`, not `skills`):
|
|
340
320
|
|
|
341
321
|
```jsonc
|
|
342
322
|
{
|
|
343
|
-
"
|
|
344
|
-
"
|
|
345
|
-
|
|
346
|
-
|
|
323
|
+
"permission": {
|
|
324
|
+
"skill": {
|
|
325
|
+
"*": "ask",
|
|
326
|
+
"dangerous-*": "deny",
|
|
327
|
+
"librarian": "allow"
|
|
328
|
+
}
|
|
329
|
+
}
|
|
347
330
|
}
|
|
348
331
|
```
|
|
349
332
|
|
|
350
|
-
### `
|
|
333
|
+
### `external_directory` surface
|
|
351
334
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
| Key | Description |
|
|
355
|
-
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
356
|
-
| `external_directory` | Enforces ask/allow/deny decisions for path-bearing tools and bash commands that reference paths outside the active working directory |
|
|
335
|
+
Controls access to paths outside the active working directory:
|
|
357
336
|
|
|
358
337
|
```jsonc
|
|
359
338
|
{
|
|
360
|
-
"
|
|
361
|
-
"external_directory": "ask"
|
|
362
|
-
}
|
|
339
|
+
"permission": {
|
|
340
|
+
"external_directory": "ask"
|
|
341
|
+
}
|
|
363
342
|
}
|
|
364
343
|
```
|
|
365
344
|
|
|
366
|
-
`external_directory` is evaluated before the normal tool permission check. For example, `
|
|
345
|
+
`external_directory` is evaluated before the normal tool permission check. For example, `read: "allow"` can permit ordinary reads while `external_directory: "ask"` still requires confirmation before reading `../outside.txt` or an absolute path outside `ctx.cwd`.
|
|
346
|
+
Optional-path search tools (`find`, `grep`, `ls`) skip this check when no `path` is provided.
|
|
367
347
|
|
|
368
|
-
Bash commands are also covered: the extension extracts path-like tokens from the command string and applies the same gate when any resolve outside `ctx.cwd`.
|
|
348
|
+
Bash commands are also covered: the extension extracts path-like tokens from the command string and applies the same gate when any resolve outside `ctx.cwd`.
|
|
349
|
+
Quoted strings are stripped first to reduce false positives.
|
|
350
|
+
This is a best-effort heuristic — variable expansion, subshells, and escaped quotes are not parsed.
|
|
351
|
+
OS device paths (`/dev/null`, `/dev/stdin`, `/dev/stdout`, `/dev/stderr`) are always excluded.
|
|
369
352
|
|
|
370
353
|
---
|
|
371
354
|
|
|
@@ -375,21 +358,15 @@ Bash commands are also covered: the extension extracts path-like tokens from the
|
|
|
375
358
|
|
|
376
359
|
```jsonc
|
|
377
360
|
{
|
|
378
|
-
"
|
|
379
|
-
"
|
|
380
|
-
"bash": "ask",
|
|
381
|
-
"mcp": "ask",
|
|
382
|
-
"skills": "ask",
|
|
383
|
-
"special": "ask",
|
|
384
|
-
},
|
|
385
|
-
"tools": {
|
|
361
|
+
"permission": {
|
|
362
|
+
"*": "ask",
|
|
386
363
|
"read": "allow",
|
|
387
364
|
"grep": "allow",
|
|
388
365
|
"find": "allow",
|
|
389
366
|
"ls": "allow",
|
|
390
367
|
"write": "deny",
|
|
391
|
-
"edit": "deny"
|
|
392
|
-
}
|
|
368
|
+
"edit": "deny"
|
|
369
|
+
}
|
|
393
370
|
}
|
|
394
371
|
```
|
|
395
372
|
|
|
@@ -397,19 +374,15 @@ Bash commands are also covered: the extension extracts path-like tokens from the
|
|
|
397
374
|
|
|
398
375
|
```jsonc
|
|
399
376
|
{
|
|
400
|
-
"
|
|
401
|
-
"
|
|
402
|
-
"bash":
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
"git status": "allow",
|
|
410
|
-
"git diff": "allow",
|
|
411
|
-
"git log *": "allow",
|
|
412
|
-
},
|
|
377
|
+
"permission": {
|
|
378
|
+
"*": "ask",
|
|
379
|
+
"bash": {
|
|
380
|
+
"*": "deny",
|
|
381
|
+
"git status": "allow",
|
|
382
|
+
"git diff": "allow",
|
|
383
|
+
"git log *": "allow"
|
|
384
|
+
}
|
|
385
|
+
}
|
|
413
386
|
}
|
|
414
387
|
```
|
|
415
388
|
|
|
@@ -417,20 +390,16 @@ Bash commands are also covered: the extension extracts path-like tokens from the
|
|
|
417
390
|
|
|
418
391
|
```jsonc
|
|
419
392
|
{
|
|
420
|
-
"
|
|
421
|
-
"tools": "ask",
|
|
422
|
-
"bash": "ask",
|
|
423
|
-
"mcp": "ask",
|
|
424
|
-
"skills": "ask",
|
|
425
|
-
"special": "ask",
|
|
426
|
-
},
|
|
427
|
-
"mcp": {
|
|
393
|
+
"permission": {
|
|
428
394
|
"*": "ask",
|
|
429
|
-
"
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
395
|
+
"mcp": {
|
|
396
|
+
"*": "ask",
|
|
397
|
+
"mcp_status": "allow",
|
|
398
|
+
"mcp_list": "allow",
|
|
399
|
+
"mcp_search": "allow",
|
|
400
|
+
"mcp_describe": "allow"
|
|
401
|
+
}
|
|
402
|
+
}
|
|
434
403
|
}
|
|
435
404
|
```
|
|
436
405
|
|
|
@@ -441,11 +410,9 @@ In the global Pi agents directory (default: `~/.pi/agent/agents/reviewer.md`, re
|
|
|
441
410
|
```yaml
|
|
442
411
|
---
|
|
443
412
|
permission:
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
bash:
|
|
448
|
-
"*": deny
|
|
413
|
+
write: deny
|
|
414
|
+
edit: deny
|
|
415
|
+
bash: deny
|
|
449
416
|
---
|
|
450
417
|
```
|
|
451
418
|
|
|
@@ -470,7 +437,7 @@ Current agent requested tool 'edit' for '.gitignore' (1 replacement: edit #1 rep
|
|
|
470
437
|
|
|
471
438
|
### Session-Scoped Approvals
|
|
472
439
|
|
|
473
|
-
When `
|
|
440
|
+
When `external_directory` resolves to `ask`, the permission dialog offers four options:
|
|
474
441
|
|
|
475
442
|
```text
|
|
476
443
|
Yes | Yes, for this session | No | No, provide reason
|
|
@@ -670,12 +637,12 @@ The hook configuration lives in `prek.toml` at the repo root.
|
|
|
670
637
|
|
|
671
638
|
---
|
|
672
639
|
|
|
673
|
-
##
|
|
640
|
+
## Acknowledgments
|
|
641
|
+
|
|
642
|
+
This project began as a fork of [MasuRii/pi-permission-system](https://github.com/MasuRii/pi-permission-system).
|
|
643
|
+
Thank you to [MasuRii](https://github.com/MasuRii) for the original work that made this possible.
|
|
674
644
|
|
|
675
|
-
|
|
676
|
-
- [pi-tool-display](https://github.com/MasuRii/pi-tool-display) — Compact tool rendering and diff visualization
|
|
677
|
-
- [pi-rtk-optimizer](https://github.com/MasuRii/pi-rtk-optimizer) — RTK command rewriting and output compaction
|
|
678
|
-
- [pi-MUST-have-extension](https://github.com/MasuRii/pi-MUST-have-extension) — RFC 2119 keyword normalization for prompts
|
|
645
|
+
Thank you to the [OpenCode](https://opencode.ai) team for the permission model design that inspired the flat config format and evaluation semantics used in this extension.
|
|
679
646
|
|
|
680
647
|
## License
|
|
681
648
|
|
|
@@ -5,28 +5,18 @@
|
|
|
5
5
|
"permissionReviewLog": true,
|
|
6
6
|
"yoloMode": false,
|
|
7
7
|
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"bash": "ask",
|
|
11
|
-
"mcp": "ask",
|
|
12
|
-
"skills": "ask",
|
|
13
|
-
"special": "ask"
|
|
14
|
-
},
|
|
15
|
-
"tools": {
|
|
8
|
+
"permission": {
|
|
9
|
+
"*": "ask",
|
|
16
10
|
"read": "allow",
|
|
17
|
-
"write": "deny"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"mcp_status": "allow"
|
|
25
|
-
|
|
26
|
-
"skills": {
|
|
27
|
-
"*": "ask"
|
|
28
|
-
},
|
|
29
|
-
"special": {
|
|
11
|
+
"write": "deny",
|
|
12
|
+
"bash": {
|
|
13
|
+
"*": "ask",
|
|
14
|
+
"git status": "allow",
|
|
15
|
+
"git diff": "allow",
|
|
16
|
+
"git *": "ask"
|
|
17
|
+
},
|
|
18
|
+
"mcp": { "*": "ask", "mcp_status": "allow", "mcp_list": "allow" },
|
|
19
|
+
"skill": { "*": "ask" },
|
|
30
20
|
"external_directory": "ask"
|
|
31
21
|
}
|
|
32
22
|
}
|