@gotgenes/pi-permission-system 3.11.0 → 4.0.1

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 CHANGED
@@ -5,6 +5,55 @@ 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.1](https://github.com/gotgenes/pi-permission-system/compare/v4.0.0...v4.0.1) (2026-05-04)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * skip bare-slash tokens in bash external-directory extraction ([#68](https://github.com/gotgenes/pi-permission-system/issues/68)) ([84f9a88](https://github.com/gotgenes/pi-permission-system/commit/84f9a88243c0033ddf1ca72894ceb42eb0f5f298))
14
+
15
+
16
+ ### Documentation
17
+
18
+ * plan skip bare-slash tokens in external-directory extraction ([#68](https://github.com/gotgenes/pi-permission-system/issues/68)) ([f4fded8](https://github.com/gotgenes/pi-permission-system/commit/f4fded847ab7f4c8b82ebcd08edb0cb640d18fa7))
19
+ * plan skip bare-slash tokens in external-directory extraction ([#68](https://github.com/gotgenes/pi-permission-system/issues/68)) ([f33964a](https://github.com/gotgenes/pi-permission-system/commit/f33964a34da726e3667319bf2015193de171767c))
20
+ * **retro:** add retro notes for issue [#66](https://github.com/gotgenes/pi-permission-system/issues/66) ([61d7e5c](https://github.com/gotgenes/pi-permission-system/commit/61d7e5ca30c20c48f52152f9443ede1900010410))
21
+
22
+ ## [4.0.0](https://github.com/gotgenes/pi-permission-system/compare/v3.11.0...v4.0.0) (2026-05-04)
23
+
24
+
25
+ ### ⚠ BREAKING CHANGES
26
+
27
+ * 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.
28
+ * 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.
29
+ * PermissionManager now reads policy from permission.permission (FlatPermissionConfig) instead of defaultPolicy/tools/bash/mcp/skills/special.
30
+ * PermissionDefaultPolicy type is removed from types.ts. ScopeConfig is simplified to { permission?: FlatPermissionConfig }. defaults.ts is stubbed out pending full PermissionManager migration (step 5).
31
+ * 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.
32
+ * 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.
33
+ * introduces FlatPermissionConfig type and normalizeFlatConfig(). The legacy normalizeConfig() remains temporarily until PermissionManager is updated in a follow-up step.
34
+
35
+ ### Features
36
+
37
+ * 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))
38
+ * 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))
39
+ * 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))
40
+ * 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))
41
+ * 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))
42
+ * 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))
43
+ * 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))
44
+
45
+
46
+ ### Documentation
47
+
48
+ * acknowledge MasuRii/pi-permission-system as the upstream origin ([fe8b642](https://github.com/gotgenes/pi-permission-system/commit/fe8b642ba83e2cacfc2f42e460b62d3270f62354))
49
+ * 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))
50
+ * 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))
51
+ * link MasuRii profile and acknowledge OpenCode inspiration ([21e5bc7](https://github.com/gotgenes/pi-permission-system/commit/21e5bc765db26a0cf9109dc396f969bb0c414c02))
52
+ * 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))
53
+ * remove unrelated pi extensions section from README ([22d0057](https://github.com/gotgenes/pi-permission-system/commit/22d0057d8feee6a3ae425e8f19d1dffec4387580))
54
+ * **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))
55
+ * 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))
56
+
8
57
  ## [3.11.0](https://github.com/gotgenes/pi-permission-system/compare/v3.10.0...v3.11.0) (2026-05-04)
9
58
 
10
59
 
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 friendly fork of [MasuRii/pi-permission-system](https://github.com/MasuRii/pi-permission-system), published to npm as `@gotgenes/pi-permission-system`.
8
- > This fork diverges from upstream in config layout (#10).
9
- > The `/permission-system` slash command name is preserved; the config and log paths are not.
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
- "defaultPolicy": {
56
- "tools": "ask",
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 `special.external_directory` before their normal tool permission when an explicit path points outside `ctx.cwd`
100
- - Bash commands are scanned for path tokens (absolute, `~/`, or `..`-relative) that resolve outside `ctx.cwd`; matching commands trigger the same `special.external_directory` gate before the normal bash pattern check
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
- Object-shaped fields (`defaultPolicy`, `tools`, `bash`, `mcp`, `skills`, `special`) use shallow-merge (later source wins per-key).
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
- // Policy
129
- "defaultPolicy": {
130
- "tools": "ask",
131
- "bash": "ask",
132
- "mcp": "ask",
133
- "skills": "ask",
134
- "special": "ask"
135
- },
136
- "tools": { "read": "allow", "write": "deny" },
137
- "bash": { "git status": "allow", "git *": "ask" },
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
- | Section | Description |
160
- | --------------- | ---------------------------------------------------------------------------- |
161
- | `defaultPolicy` | Fallback permissions per category |
162
- | `tools` | Exact-name tool permissions for registered tools |
163
- | `bash` | Command pattern permissions |
164
- | `mcp` | MCP server/tool permissions for calls routed through a registered `mcp` tool |
165
- | `skills` | Skill name pattern permissions |
166
- | `special` | Reserved permission checks such as external directory access |
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 within the same permission category. For wildcard-based sections like `bash`, `mcp`, `skills`, and `special`, matching still follows the extension's existing **last matching rule wins** behavior after the layers are combined. The recommended convention also used by [OpenCode's permission model](https://opencode.ai/docs/permissions/#granular-rules-object-syntax) — is to put the broad catch-all rule first and specific overrides after it.
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
- ### `defaultPolicy`
215
+ ### `permission["*"]` — universal fallback
223
216
 
224
- Sets fallback permissions when no specific rule matches:
217
+ The `"*"` key sets the action used when no surface-specific rule matches:
225
218
 
226
219
  ```jsonc
227
220
  {
228
- "defaultPolicy": {
229
- "tools": "ask",
230
- "bash": "ask",
231
- "mcp": "ask",
232
- "skills": "ask",
233
- "special": "ask",
234
- },
221
+ "permission": {
222
+ "*": "ask"
223
+ }
235
224
  }
236
225
  ```
237
226
 
238
- ### `tools`
227
+ Omitting `"*"` defaults to `"ask"` (least privilege).
239
228
 
240
- Controls tools by exact registered name (no wildcards). This is the recommended standalone format for **all** tool entries, including Pi built-ins and arbitrary third-party extension tools.
229
+ ### Tool surfaces
241
230
 
242
- | Tool name example | Description |
243
- | ------------------ | ------------------------------------------------------------------------- |
244
- | `bash` | Shell command execution (tool-level fallback before `bash` pattern rules) |
245
- | `read` / `write` | Canonical Pi built-in file tools |
246
- | `mcp` | Registered MCP proxy tool entry/fallback when available |
247
- | `task` | Delegation tool handled like any other registered extension tool |
248
- | `third_party_tool` | Arbitrary registered extension tool |
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
- "tools": {
243
+ "permission": {
253
244
  "read": "allow",
254
245
  "write": "deny",
255
- "mcp": "allow",
256
- "third_party_tool": "ask",
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 another extension is not installed, its tool simply will not be registered at runtime, and this extension will block attempts to call that missing tool before permission checks run.
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
- > **Note:** Setting `tools.bash` affects the _default_ for bash commands, but `bash` patterns can provide command-level overrides.
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
- ### `bash`
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
- "bash": {
276
- "git *": "ask",
277
- "git status": "allow",
278
- "rm -rf *": "deny",
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
- ### `mcp`
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
- "mcp": {
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
- > **Note:** Baseline discovery targets may auto-allow when you permit any MCP rule.
279
+ ### `mcp` surface
306
280
 
307
- #### MCP Tool Fallback via `tools.mcp`
281
+ MCP permissions match against derived targets from tool input:
308
282
 
309
- A registered `mcp` tool can use `tools.mcp` as an entry permission point. This provides a fallback when no specific MCP pattern matches:
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
- "tools": {
314
- "mcp": "allow",
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
- This is useful for per-agent configurations where you want to grant MCP access broadly:
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
- # In the global Pi agents directory (default: ~/.pi/agent/agents/researcher.md; respects PI_CODING_AGENT_DIR)
309
+ # ~/.pi/agent/agents/researcher.md (respects PI_CODING_AGENT_DIR)
323
310
  ---
324
311
  name: researcher
325
312
  permission:
326
- tools:
327
- mcp: allow
313
+ mcp: allow
328
314
  ---
329
315
  ```
330
316
 
331
- The permission resolution order for MCP operations:
317
+ ### `skill` surface
332
318
 
333
- 1. Specific `mcp` patterns (e.g., `myServer:toolName`, `myServer_*`)
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
- "skills": {
344
- "*": "ask",
345
- "dangerous-*": "deny",
346
- },
323
+ "permission": {
324
+ "skill": {
325
+ "*": "ask",
326
+ "dangerous-*": "deny",
327
+ "librarian": "allow"
328
+ }
329
+ }
347
330
  }
348
331
  ```
349
332
 
350
- ### `special`
333
+ ### `external_directory` surface
351
334
 
352
- Reserved permission checks:
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
- "special": {
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, `tools.read: "allow"` can permit ordinary reads while `special.external_directory: "ask"` still requires confirmation before reading `../outside.txt` or an absolute path outside `ctx.cwd`. Optional-path search tools (`find`, `grep`, `ls`) skip this check when no `path` is provided because they default to the active working directory.
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`. Quoted strings are stripped first to reduce false positives (e.g., paths inside `git commit -m "..."` messages). This is a best-effort heuristic — variable expansion, subshells, and escaped quotes are not parsed. OS device paths (`/dev/null`, `/dev/stdin`, `/dev/stdout`, `/dev/stderr`) are always excluded from this check — they cannot hold or leak data and commonly appear in stderr-redirect idioms such as `command 2>/dev/null`.
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
- "defaultPolicy": {
379
- "tools": "ask",
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
- "defaultPolicy": {
401
- "tools": "ask",
402
- "bash": "deny",
403
- "mcp": "ask",
404
- "skills": "ask",
405
- "special": "ask",
406
- },
407
- "bash": {
408
- "git *": "ask",
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
- "defaultPolicy": {
421
- "tools": "ask",
422
- "bash": "ask",
423
- "mcp": "ask",
424
- "skills": "ask",
425
- "special": "ask",
426
- },
427
- "mcp": {
393
+ "permission": {
428
394
  "*": "ask",
429
- "mcp_status": "allow",
430
- "mcp_list": "allow",
431
- "mcp_search": "allow",
432
- "mcp_describe": "allow",
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
- tools:
445
- write: deny
446
- edit: deny
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 `special.external_directory` resolves to `ask`, the permission dialog offers four options:
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
- ## Related Pi Extensions
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
- - [pi-multi-auth](https://github.com/MasuRii/pi-multi-auth) Multi-provider credential management and quota-aware rotation
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
- "defaultPolicy": {
9
- "tools": "ask",
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
- "bash": {
20
- "git status": "allow",
21
- "git *": "ask"
22
- },
23
- "mcp": {
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gotgenes/pi-permission-system",
3
- "version": "3.11.0",
3
+ "version": "4.0.1",
4
4
  "description": "Permission enforcement extension for the Pi coding agent.",
5
5
  "type": "module",
6
6
  "files": [