{"_id":"@aprimediet/permission-modes","_rev":"8-9a261a4c875ebca6ef303de4f2c5db48","name":"@aprimediet/permission-modes","dist-tags":{"latest":"1.2.2"},"versions":{"1.0.0":{"name":"@aprimediet/permission-modes","version":"1.0.0","keywords":["pi-package"],"license":"MIT","_id":"@aprimediet/permission-modes@1.0.0","maintainers":[{"name":"aditya.prima","email":"aprimediet@gmail.com"}],"homepage":"https://github.com/aprimediet/pi-permission-modes#readme","bugs":{"url":"https://github.com/aprimediet/pi-permission-modes/issues"},"pi":{"extensions":["./index.ts"]},"dist":{"shasum":"f8e0a0c3ab01c0497ce1d3f5bed7140597694a0b","tarball":"https://registry.npmjs.org/@aprimediet/permission-modes/-/permission-modes-1.0.0.tgz","fileCount":5,"integrity":"sha512-U2IZziQVDap+u15Id0IEsR0Tuc7ogsF9TRQdPlWdDaEtYtD/pTPtrZEFmhvKe8Y5FScLP0TBjIXnCcYtWotRxw==","signatures":[{"sig":"MEUCIQC4ucjCJ7SkxMlLRvYIyPHS1dkHSJK/QyiRFN/tb+lGwAIgX4JozKvMkNzMMDA9o6ZLbX7NFA0NygCUTKnSO6cplYI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":33809},"type":"module","gitHead":"529540eeff80656144bdc05f2a99fde94af42850","scripts":{"pack:dry":"npm pack --dry-run","prepublishOnly":"node -e \"const pkg=require('./package.json'); if(!pkg.files||pkg.files.length===0){console.error('files field empty — abort');process.exit(1)}; console.log('Publishing '+pkg.name+'@'+pkg.version+' with files:', pkg.files)\""},"_npmUser":{"name":"aditya.prima","email":"aprimediet@gmail.com"},"repository":{"url":"git+https://github.com/aprimediet/pi-permission-modes.git","type":"git"},"_npmVersion":"11.17.0","description":"Claude-Code-style permission modes (default / plan / accept-edits / auto) for the pi coding agent.","directories":{},"_nodeVersion":"24.18.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"peerDependencies":{"typebox":"*","@earendil-works/pi-ai":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"_npmOperationalInternal":{"tmp":"tmp/permission-modes_1.0.0_1782399546647_0.8008426112486318","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@aprimediet/permission-modes","version":"1.1.0","keywords":["pi-package"],"license":"MIT","_id":"@aprimediet/permission-modes@1.1.0","maintainers":[{"name":"aditya.prima","email":"aprimediet@gmail.com"}],"homepage":"https://github.com/aprimediet/pi-permission-modes#readme","bugs":{"url":"https://github.com/aprimediet/pi-permission-modes/issues"},"pi":{"extensions":["./index.ts"]},"dist":{"shasum":"aea7079795750c7350bba66f5b31961f7aeef264","tarball":"https://registry.npmjs.org/@aprimediet/permission-modes/-/permission-modes-1.1.0.tgz","fileCount":8,"integrity":"sha512-iNqfHwJExIdGa56XOxRGdpT5cRbLWLvmbQ4kN3m9OHDkSIiIcC9ivGiRA5EUbq1q1RylMEuLNvgfhOE4+wpAsw==","signatures":[{"sig":"MEUCIQChJ5ZgqeRJce0MaB/TjSBnDpYSHUtrttFKbwKVVwFASgIgbeC+qMOkXz6WD4SGkT2WSabFo26J1mje9YxmxSTgN9Q=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":63460},"type":"module","gitHead":"92c8f8c7d0c04fdb000703e3975949ca96b54da7","scripts":{"test":"vitest run","pack:dry":"npm pack --dry-run","test:watch":"vitest","prepublishOnly":"node -e \"const pkg=require('./package.json'); if(!pkg.files||pkg.files.length===0){console.error('files field empty — abort');process.exit(1)}; console.log('Publishing '+pkg.name+'@'+pkg.version+' with files:', pkg.files)\""},"_npmUser":{"name":"aditya.prima","email":"aprimediet@gmail.com"},"repository":{"url":"git+https://github.com/aprimediet/pi-permission-modes.git","type":"git"},"_npmVersion":"11.17.0","description":"Claude-Code-style permission modes (ask / plan / auto) for the pi coding agent — with outside-cwd guarding and project-root detection.","directories":{},"_nodeVersion":"24.18.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.6.0"},"peerDependencies":{"typebox":"*","@earendil-works/pi-ai":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"_npmOperationalInternal":{"tmp":"tmp/permission-modes_1.1.0_1782635093066_0.9145851350328389","host":"s3://npm-registry-packages-npm-production"}},"1.1.2":{"name":"@aprimediet/permission-modes","version":"1.1.2","keywords":["pi-package"],"license":"MIT","_id":"@aprimediet/permission-modes@1.1.2","maintainers":[{"name":"aditya.prima","email":"aprimediet@gmail.com"}],"homepage":"https://github.com/aprimediet/pi-permission-modes#readme","bugs":{"url":"https://github.com/aprimediet/pi-permission-modes/issues"},"pi":{"extensions":["./index.ts"]},"dist":{"shasum":"0cc553425e0fa7bbcafe27884df0230af80e954c","tarball":"https://registry.npmjs.org/@aprimediet/permission-modes/-/permission-modes-1.1.2.tgz","fileCount":10,"integrity":"sha512-/EKbQcjNMvZBo8MN5pNOdaitg3+NyF0xxaIk/4CajlcbHnQH07SBYLV6IvCkxqzD9lixipsZvLFpU81T/ABsOQ==","signatures":[{"sig":"MEUCIAanDUBfKbzzUqbAATa4M3krNugHJaL7RIgd9v/TQaDJAiEAy5iPg4o7uaUeBNlpS8a4UrVvrmt+dHgEuGhk2CRbRts=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":107416},"type":"module","gitHead":"a4b3c664675965b30ba1c1379f7abbf6abf8c461","scripts":{"test":"vitest run","pack:dry":"npm pack --dry-run","test:watch":"vitest","prepublishOnly":"node -e \"const pkg=require('./package.json'); if(!pkg.files||pkg.files.length===0){console.error('files field empty — abort');process.exit(1)}; console.log('Publishing '+pkg.name+'@'+pkg.version+' with files:', pkg.files)\""},"_npmUser":{"name":"aditya.prima","email":"aprimediet@gmail.com"},"repository":{"url":"git+https://github.com/aprimediet/pi-permission-modes.git","type":"git"},"_npmVersion":"11.17.0","description":"Claude-Code-style permission modes (ask / plan / auto) for the pi coding agent — with per-mode model profiles.","directories":{},"_nodeVersion":"24.18.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.6.0"},"peerDependencies":{"typebox":"*","@earendil-works/pi-ai":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"_npmOperationalInternal":{"tmp":"tmp/permission-modes_1.1.2_1782639904006_0.6664815346938107","host":"s3://npm-registry-packages-npm-production"}},"1.1.3":{"name":"@aprimediet/permission-modes","version":"1.1.3","keywords":["pi-package"],"license":"MIT","_id":"@aprimediet/permission-modes@1.1.3","maintainers":[{"name":"aditya.prima","email":"aprimediet@gmail.com"}],"homepage":"https://github.com/aprimediet/pi-permission-modes#readme","bugs":{"url":"https://github.com/aprimediet/pi-permission-modes/issues"},"pi":{"extensions":["./index.ts"]},"dist":{"shasum":"b53c3a3592664a57a236300b70b3753230e9ed6e","tarball":"https://registry.npmjs.org/@aprimediet/permission-modes/-/permission-modes-1.1.3.tgz","fileCount":10,"integrity":"sha512-AWCyU2GRV0XTQ7kq5qf6uQ73/xhJ4Eq6g3vDFDQ3pZ2uvsd26lVn3ELe42KJ80Do+d5+7Kvq/GzSgKqSRqkPNg==","signatures":[{"sig":"MEQCIDL9AFeYPzq0RPwvWORr3/qdMlBwU05kUQCZJGG0oAA2AiBfcOAz67l44L2r+MG2nPtEJbeS+TfEbkpnctFZE+8qfQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":138175},"type":"module","gitHead":"81d76777a3a6a9aee4e161a808332c5fb03a1428","scripts":{"test":"vitest run","pack:dry":"npm pack --dry-run","test:watch":"vitest","prepublishOnly":"node -e \"const pkg=require('./package.json'); if(!pkg.files||pkg.files.length===0){console.error('files field empty — abort');process.exit(1)}; console.log('Publishing '+pkg.name+'@'+pkg.version+' with files:', pkg.files)\""},"_npmUser":{"name":"aditya.prima","email":"aprimediet@gmail.com"},"repository":{"url":"git+https://github.com/aprimediet/pi-permission-modes.git","type":"git"},"_npmVersion":"11.17.0","description":"Claude-Code-style permission modes (ask / plan / auto) for the pi coding agent — with per-mode model profiles and outside-cwd write tracking.","directories":{},"_nodeVersion":"24.18.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.6.0"},"peerDependencies":{"typebox":"*","@earendil-works/pi-ai":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"_npmOperationalInternal":{"tmp":"tmp/permission-modes_1.1.3_1782709214165_0.12101331244491442","host":"s3://npm-registry-packages-npm-production"}},"1.1.5":{"name":"@aprimediet/permission-modes","version":"1.1.5","keywords":["pi-package"],"license":"MIT","_id":"@aprimediet/permission-modes@1.1.5","maintainers":[{"name":"aditya.prima","email":"aprimediet@gmail.com"}],"homepage":"https://github.com/aprimediet/pi-permission-modes#readme","bugs":{"url":"https://github.com/aprimediet/pi-permission-modes/issues"},"pi":{"extensions":["./index.ts"]},"dist":{"shasum":"266073f37d1d63e589214c1d2400b07a802d6756","tarball":"https://registry.npmjs.org/@aprimediet/permission-modes/-/permission-modes-1.1.5.tgz","fileCount":10,"integrity":"sha512-YG2xS/RTLhkHifFRq53O3aaDiJpYQXhA6yVnW5kGW+OuXnIvB2TXYdvO7VeSgRkF20GMcCzlZItKCFquynHm9g==","signatures":[{"sig":"MEQCIC9sAnwl31Kv5PH/kIxUMv9Fx2nz+/4EL1iGacmEvPTPAiBbJCRX8esCt8cLLSaHwBNrC/8HzaWF74MQWdmTLkJ/jQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":172194},"type":"module","gitHead":"08cc94caac9a82efdc27fab682eefac59b2c70f5","scripts":{"test":"vitest run","pack:dry":"npm pack --dry-run","test:watch":"vitest","prepublishOnly":"node -e \"const pkg=require('./package.json'); if(!pkg.files||pkg.files.length===0){console.error('files field empty — abort');process.exit(1)}; console.log('Publishing '+pkg.name+'@'+pkg.version+' with files:', pkg.files)\""},"_npmUser":{"name":"aditya.prima","email":"aprimediet@gmail.com"},"repository":{"url":"git+https://github.com/aprimediet/pi-permission-modes.git","type":"git"},"_npmVersion":"11.17.0","description":"Claude-Code-style permission modes (ask / plan / auto) for the pi coding agent — with per-mode model profiles, outside-cwd write tracking, and per-mode skill filtering.","directories":{},"_nodeVersion":"24.18.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.6.0"},"peerDependencies":{"typebox":"*","@earendil-works/pi-ai":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"_npmOperationalInternal":{"tmp":"tmp/permission-modes_1.1.5_1782722621635_0.35604143371499664","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@aprimediet/permission-modes","version":"1.2.0","keywords":["pi-package"],"_id":"@aprimediet/permission-modes@1.2.0","maintainers":[{"name":"aditya.prima","email":"aprimediet@gmail.com"}],"pi":{"extensions":["./index.ts"]},"dist":{"shasum":"f19668493d66d4cb6e33856c8f2273712831b5d8","tarball":"https://registry.npmjs.org/@aprimediet/permission-modes/-/permission-modes-1.2.0.tgz","fileCount":8,"integrity":"sha512-EGajmagV8NyP8ato0xcn9vcVV3WFgd2mpsUXwtW1EvzDL1gZXk1rRbLoj8+Z/H8DEuSH6PPzLarrCEsxHdPW0A==","signatures":[{"sig":"MEUCIQDvdBeqZantcYSE99AlhrqTl87Uf3zEAX0u5tTbRB1gkgIgNpirIYm+EY2r5mAEeZFxWevxNNSDg0voqkMkP8fK0CM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":75184},"type":"module","gitHead":"f7047c1152781c3a661afd37ced4c19697a320c4","scripts":{"test":"vitest run"},"_npmUser":{"name":"aditya.prima","email":"aprimediet@gmail.com"},"_npmVersion":"11.17.0","description":"A Claude-Code-style **Shift+Tab mode cycle** for the [pi coding agent](https://pi.dev).","directories":{},"_nodeVersion":"24.18.0","_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.6.0","typescript":"^5.9.3"},"peerDependencies":{"typebox":"*","@earendil-works/pi-ai":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-agent-core":"*","@earendil-works/pi-coding-agent":"*"},"_npmOperationalInternal":{"tmp":"tmp/permission-modes_1.2.0_1782887922999_0.8440347343262355","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"@aprimediet/permission-modes","version":"1.2.1","keywords":["pi-package"],"_id":"@aprimediet/permission-modes@1.2.1","maintainers":[{"name":"aditya.prima","email":"aprimediet@gmail.com"}],"pi":{"extensions":["./index.ts"]},"dist":{"shasum":"856af2c88aad78af1a8bce201218cff6bc188dee","tarball":"https://registry.npmjs.org/@aprimediet/permission-modes/-/permission-modes-1.2.1.tgz","fileCount":9,"integrity":"sha512-bANlkkYsbRX41/HAqWfG1p3UA21jxeJoAZXNMWhgCaAUjLZyMBlSF54Jv1F2vlehoVaN44l3NqtDflnQbD5ttg==","signatures":[{"sig":"MEQCIGwhh8k2ncH1z5cJQKSDTRwYzwza+mq0eNCUlratt7QoAiBLW9IpZNui0TxLN/507O2tpOScVsYyVHenk6J9JVvFHA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":82546},"type":"module","gitHead":"df45aabf29cf51c873bce895efac9af4a07df3bc","scripts":{"test":"vitest run"},"_npmUser":{"name":"aditya.prima","email":"aprimediet@gmail.com"},"_npmVersion":"11.17.0","description":"A Claude-Code-style **Shift+Tab mode cycle** for the [pi coding agent](https://pi.dev).","directories":{},"_nodeVersion":"24.18.0","_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.6.0","typescript":"^5.9.3"},"peerDependencies":{"typebox":"*","@earendil-works/pi-ai":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-agent-core":"*","@earendil-works/pi-coding-agent":"*"},"_npmOperationalInternal":{"tmp":"tmp/permission-modes_1.2.1_1782891191444_0.3162329073019028","host":"s3://npm-registry-packages-npm-production"}},"1.2.2":{"name":"@aprimediet/permission-modes","version":"1.2.2","type":"module","keywords":["pi-package"],"pi":{"extensions":["./index.ts"]},"scripts":{"test":"vitest run"},"peerDependencies":{"@earendil-works/pi-agent-core":"*","@earendil-works/pi-ai":"*","@earendil-works/pi-coding-agent":"*","@earendil-works/pi-tui":"*","typebox":"*"},"devDependencies":{"typescript":"^5.9.3","vitest":"^1.6.0"},"gitHead":"366034fbcd35caa8bfea24606f7c8efc4c03886a","_id":"@aprimediet/permission-modes@1.2.2","description":"A Claude-Code-style **Shift+Tab mode cycle** for the [pi coding agent](https://pi.dev).","_nodeVersion":"24.18.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-BEem1RZJZPx/RkmYiDuAD+27j8mf6tLhBTpAWpbf4PSgzwTJjzeXg9el0/PwwGX+teHLXcCBbYoZ0eNlfgZrsw==","shasum":"b5c5de30ccbc5dceedc63e18838714068fa0e2f7","tarball":"https://registry.npmjs.org/@aprimediet/permission-modes/-/permission-modes-1.2.2.tgz","fileCount":9,"unpackedSize":86029,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDQZS3ekfue8I5YfK5kybz/NalDMMc+jucdRT5GAW4+HAiEAiXF11emN2BQfP7uLApOlkjnmt8hDeGHg5Dy/qrlzsNA="}]},"_npmUser":{"name":"aditya.prima","email":"aprimediet@gmail.com"},"directories":{},"maintainers":[{"name":"aditya.prima","email":"aprimediet@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/permission-modes_1.2.2_1782936568621_0.578588153430784"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-25T14:59:06.479Z","modified":"2026-07-01T20:09:28.898Z","1.0.0":"2026-06-25T14:59:06.771Z","1.1.0":"2026-06-28T08:24:53.201Z","1.1.2":"2026-06-28T09:45:04.146Z","1.1.3":"2026-06-29T05:00:14.313Z","1.1.5":"2026-06-29T08:43:41.759Z","1.2.0":"2026-07-01T06:38:43.159Z","1.2.1":"2026-07-01T07:33:11.619Z","1.2.2":"2026-07-01T20:09:28.759Z"},"keywords":["pi-package"],"description":"A Claude-Code-style **Shift+Tab mode cycle** for the [pi coding agent](https://pi.dev).","maintainers":[{"name":"aditya.prima","email":"aprimediet@gmail.com"}],"readme":"# permission-modes\n\nA Claude-Code-style **Shift+Tab mode cycle** for the [pi coding agent](https://pi.dev).\n\nThree modes, cycled with `Shift+Tab` (or via commands):\n\n| Mode    | Edit/Write             | Mutating bash | Read-only bash | Reads  | Behavior                                              |\n| ------- | ---------------------- | ------------- | -------------- | ------ | ----------------------------------------------------- |\n| default | prompt each call       | prompt        | allow          | allow  | Standard \"ask before mutating\" workflow               |\n| plan    | **disabled**           | **blocked**   | allow          | allow  | Read-only exploration; produce a `Plan:` and execute  |\n| auto    | auto-approve           | auto-approve  | auto-approve   | allow  | Auto-approve everything; auto-follow-up until done    |\n\nCycle order: **default → plan → auto → default**.\n\n## Install\n\n```bash\npi install npm:permission-modes\n```\n\nOr load directly for a one-off run:\n\n```bash\npi -e ./index.ts\n```\n\n## Usage\n\n### Keyboard\n\n- **`Shift+Tab`** — cycle to the next mode (default → plan → auto → default)\n\n### Commands\n\n- `/default` — switch to default mode\n- `/plan` — switch to plan mode (read-only)\n- `/auto` — switch to auto mode\n- `/mode [name]` — with no arg, opens a selector; with `default`/`plan`/`auto`, switches directly\n- `/auto-depth <n>` — set the auto-follow-up cap (`0` = unlimited, default `20`)\n- `/done` — stop auto-follow-up immediately. No more \"Continue\" will be sent in this session until you manually switch back to auto mode.\n  Useful when you're satisfied with the result and want pi to stop.\n\n### Flag\n\n- `--permission-mode <mode>` — start in `default`, `plan`, or `auto`\n\n> The flag is named `--permission-mode` (not `--mode`) because pi has a built-in `--mode` flag for output mode (text/json/rpc).\n\n## Plan mode flow\n\n1. Run `/plan` (or use `Shift+Tab` to cycle into plan mode).\n2. The agent reads your code, asks clarifying questions, and produces a numbered `Plan:` block.\n3. pi prompts you with three options:\n   - **Execute the plan** — switches out of plan mode, restores `edit`/`write` tools, posts the steps to the agent, and tracks progress with a `☐/☑` widget. The agent emits `[DONE:n]` tags as it finishes each step; pi marks them and posts **Plan Complete ✓** when all are done. If the plan has more than 2 steps, pi also exposes the `todo` tool and tells the agent to use it for step tracking.\n   - **Stay in plan mode** — keep exploring.\n   - **Refine the plan** — open an editor, type feedback, and the agent iterates.\n\n## Auto mode\n\nIn auto mode, every tool call is auto-approved. After each turn, if the assistant's last message **made tool calls** and does **not** look like a completion signal, pi auto-feeds a \"Continue. Auto mode is active — proceed without asking.\" follow-up message. This loops until:\n\n- the agent stops making tool calls (and emits a completion signal like \"all done\" / \"task complete\" / \"finished\" / \"all tests pass\" / \"fixed the issue\"), or\n- the cap (`/auto-depth <n>`, default `20`) is reached, or\n- the user runs `/done`, or\n- the user manually changes mode.\n\n> Completion detection supports Indonesian phrases like \"selesai\", \"sudah selesai\", \"beres\".\n> If pi keeps going when you're done, run `/done` to stop it.\n\n> Auto mode is intentionally permissive: it auto-approves **everything**, including outside-cwd writes. That's the design.\n\n## Headless / no-UI safety\n\nIn any mode where a UI prompt would normally appear, if `ctx.hasUI === false` (e.g. `pi -p` or RPC mode without a terminal), the tool call is **blocked** with a clear reason — never silently allowed.\n\n## State persistence\n\nThe current mode and `autoFollowUpDepth` are persisted to the session via `pi.appendEntry(\"modes\", {...})`. On `/reload`, `/resume`, or tree navigation, the last entry is restored (with legacy value mapping: `\"ask\"`/`\"normal\"` → `default`, `\"accept-edits\"` → `auto`).\n\nIf you were mid-plan-execution, the latest `modes-execute` marker is detected and the plan is rebuilt from assistant messages after it, with `[DONE:n]` tags re-applied so the widget reflects the actual state.\n\n## Files\n\n```\npermission-modes/\n├── package.json\n├── README.md\n├── index.ts          # main factory\n├── utils.ts          # isSafeCommand, plan extraction, completion signal, formatCount\n├── vitest.config.ts\n├── utils.test.ts\n└── index.test.ts\n```\n\n## Tests\n\n```bash\nnpm test\n```\n\n`utils.test.ts` covers the bash safety classifier, plan extraction, `[DONE:n]` marking, and completion-signal detection.\n","readmeFilename":"README.md"}