<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Javascript on ICE-ICE-BEAR-BLOG</title><link>https://ice-ice-bear.github.io/tags/javascript/</link><description>Recent content in Javascript on ICE-ICE-BEAR-BLOG</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Fri, 10 Apr 2026 00:00:00 +0900</lastBuildDate><atom:link href="https://ice-ice-bear.github.io/tags/javascript/index.xml" rel="self" type="application/rss+xml"/><item><title>Claude Auto-Permission Dev Log #1 — Hook-Based Auto-Permission System</title><link>https://ice-ice-bear.github.io/posts/2026-04-10-claude-auto-permission/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0900</pubDate><guid>https://ice-ice-bear.github.io/posts/2026-04-10-claude-auto-permission/</guid><description>&lt;img src="https://ice-ice-bear.github.io/" alt="Featured image of post Claude Auto-Permission Dev Log #1 — Hook-Based Auto-Permission System" /&gt;&lt;h2 id="overview"&gt;Overview
&lt;/h2&gt;&lt;p&gt;If you use Claude Code heavily, you know the pain: hundreds of &amp;ldquo;Allow&amp;rdquo; clicks per session. Reading a file? Allow. Running &lt;code&gt;git status&lt;/code&gt;? Allow. Running tests? Allow. The built-in &lt;code&gt;settings.local.json&lt;/code&gt; accumulates one-off approvals that quickly become unmanageable. To solve this, I built &lt;strong&gt;claude-auto-permission&lt;/strong&gt; — a hook-based auto-permission system with preset-driven configs and a learning mechanism.&lt;/p&gt;
&lt;h2 id="the-problem--hundreds-of-allow-clicks"&gt;The Problem — Hundreds of &amp;ldquo;Allow&amp;rdquo; Clicks
&lt;/h2&gt;&lt;p&gt;Claude Code requires user approval for every tool use. This is the right default for security, but in practice it creates significant friction during development:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Read&lt;/code&gt; tool to open a file — approve&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Bash&lt;/code&gt; to run &lt;code&gt;git status&lt;/code&gt; — approve&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Bash&lt;/code&gt; to run &lt;code&gt;npm test&lt;/code&gt; — approve&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Grep&lt;/code&gt; to search code — approve&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A one-hour coding session easily generates 100-200 approval prompts. And as you approve them one by one, &lt;code&gt;settings.local.json&lt;/code&gt; accumulates entries like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;permissions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;allow&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Bash(git status)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Bash(git diff)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Bash(git log --oneline -20)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Bash(git log --oneline -10)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Bash(npm test)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Bash(npm run test)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Bash(npx jest)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since it records exact command strings, &lt;code&gt;git log --oneline -20&lt;/code&gt; and &lt;code&gt;git log --oneline -10&lt;/code&gt; are separate entries. No pattern generalization means the list grows endlessly.&lt;/p&gt;
&lt;h2 id="design--hook-architecture"&gt;Design — Hook Architecture
&lt;/h2&gt;&lt;p&gt;Claude Code&amp;rsquo;s hook system lets you attach external scripts to events like &lt;code&gt;PreToolUse&lt;/code&gt; and &lt;code&gt;PostToolUse&lt;/code&gt;. By hooking into &lt;code&gt;PreToolUse&lt;/code&gt;, we can intercept every tool invocation and decide whether to auto-approve, block, or pass through to the user.&lt;/p&gt;
&lt;p&gt;Here is the overall architecture:&lt;/p&gt;
&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TD
 A["Claude Code&amp;lt;br/&amp;gt;Tool Use Request"] --&gt; B["PreToolUse Hook&amp;lt;br/&amp;gt;selective-auto-permission.mjs"]
 B --&gt; C{"auto-permission.json&amp;lt;br/&amp;gt;Check Rules"}
 C --&gt;|deny match| D["Block&amp;lt;br/&amp;gt;Return reason"]
 C --&gt;|allow match| E["Auto-approve&amp;lt;br/&amp;gt;Return approve"]
 C --&gt;|no match| F["Pass to User&amp;lt;br/&amp;gt;Manual Approval"]
 F --&gt;|approved| G["Recorded in&amp;lt;br/&amp;gt;settings.local.json"]
 G --&gt; H["/learn-permissions&amp;lt;br/&amp;gt;Skill Invoked"]
 H --&gt; I["Generalize Pattern&amp;lt;br/&amp;gt;Merge into auto-permission.json"]
 I --&gt; C

 style D fill:#ff6b6b,color:#fff
 style E fill:#51cf66,color:#fff
 style I fill:#339af0,color:#fff&lt;/pre&gt;&lt;p&gt;Three core components make this work:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;selective-auto-permission.mjs&lt;/code&gt;&lt;/strong&gt; — The PreToolUse hook. On every tool use, it checks the allow/deny lists in &lt;code&gt;auto-permission.json&lt;/code&gt; and returns a verdict.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;permission-learner.mjs&lt;/code&gt;&lt;/strong&gt; — Analyzes manual approval history and extracts patterns.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;/learn-permissions&lt;/code&gt; skill&lt;/strong&gt; — An interactive workflow that merges learned patterns into &lt;code&gt;auto-permission.json&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="preset-system"&gt;Preset System
&lt;/h2&gt;&lt;p&gt;Writing rules from scratch for every project is impractical. So the system ships with five presets for common development environments:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Preset&lt;/th&gt;
 &lt;th&gt;Use Case&lt;/th&gt;
 &lt;th&gt;Auto-Approve Scope&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;safe-read&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Read-only&lt;/td&gt;
 &lt;td&gt;Read, Grep, Glob, git status/log/diff&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;node-dev&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Node.js development&lt;/td&gt;
 &lt;td&gt;+ npm/npx, jest, eslint, tsc&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;python-dev&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Python development&lt;/td&gt;
 &lt;td&gt;+ uv, pytest, ruff, mypy, pip&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;fullstack-dev&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Full-stack&lt;/td&gt;
 &lt;td&gt;node-dev + python-dev combined&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;full-trust&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Full trust&lt;/td&gt;
 &lt;td&gt;Nearly all tools (except deny list)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Every preset shares a &lt;strong&gt;universal deny list&lt;/strong&gt; that is never auto-approved:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UNIVERSAL_DENY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;rm -rf&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;git push --force&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;git reset --hard&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;git clean -f&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Even with the &lt;code&gt;full-trust&lt;/code&gt; preset, these four commands always require manual approval. An accidental &lt;code&gt;rm -rf /&lt;/code&gt; should never be auto-approved.&lt;/p&gt;
&lt;h2 id="auto-permissionjson-structure"&gt;auto-permission.json Structure
&lt;/h2&gt;&lt;p&gt;Rules are defined in &lt;code&gt;.claude/auto-permission.json&lt;/code&gt; at each project root:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;preset&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;python-dev&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;custom_allow&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;tool&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Bash&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;pattern&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;docker compose *&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;tool&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Bash&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;pattern&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;hugo server *&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;custom_deny&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;tool&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Bash&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;pattern&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;docker system prune *&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;preset&lt;/code&gt; provides baseline rules, while &lt;code&gt;custom_allow&lt;/code&gt; and &lt;code&gt;custom_deny&lt;/code&gt; add project-specific overrides. Patterns support glob-style matching, so &lt;code&gt;docker compose *&lt;/code&gt; covers &lt;code&gt;docker compose up&lt;/code&gt;, &lt;code&gt;docker compose down&lt;/code&gt;, &lt;code&gt;docker compose logs -f&lt;/code&gt;, and so on.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rule priority&lt;/strong&gt;: deny always takes precedence over allow. If a command matches both lists, it is blocked. When in doubt, err on the side of safety.&lt;/p&gt;
&lt;h2 id="permission-learner--extracting-patterns-from-approval-history"&gt;Permission Learner — Extracting Patterns from Approval History
&lt;/h2&gt;&lt;p&gt;As you manually approve commands, &lt;code&gt;settings.local.json&lt;/code&gt; accumulates similar entries:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Bash(pytest tests/test_auth.py)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Bash(pytest tests/test_api.py)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Bash(pytest tests/test_models.py -v)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Bash(pytest --tb=short)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;permission-learner.mjs&lt;/code&gt; analyzes these entries by:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Extracting common prefixes (&lt;code&gt;pytest&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Classifying safety (read-only vs. filesystem-modifying)&lt;/li&gt;
&lt;li&gt;Generalizing into patterns (&lt;code&gt;pytest *&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When you run the &lt;code&gt;/learn-permissions&lt;/code&gt; skill, it presents the learned patterns for review and, upon confirmation, adds them to &lt;code&gt;custom_allow&lt;/code&gt; in &lt;code&gt;auto-permission.json&lt;/code&gt;. Once learned, the entire family of similar commands is auto-approved going forward.&lt;/p&gt;
&lt;h2 id="design-decisions"&gt;Design Decisions
&lt;/h2&gt;&lt;h3 id="hook-response-time"&gt;Hook Response Time
&lt;/h3&gt;&lt;p&gt;The PreToolUse hook runs on every single tool use. Spawning a new Node.js process each time could be a concern, but in practice, reading one JSON file and running pattern matching takes only tens of milliseconds — well below any perceptible delay.&lt;/p&gt;
&lt;h3 id="balancing-security-and-convenience"&gt;Balancing Security and Convenience
&lt;/h3&gt;&lt;p&gt;The most important question in an auto-permission system is &amp;ldquo;how much should be auto-approved?&amp;rdquo; Too permissive is dangerous; too restrictive is useless.&lt;/p&gt;
&lt;p&gt;This project follows three principles:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deny always wins&lt;/strong&gt; — no matter how broad the allow list, a deny match blocks the action&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Universal deny is preset-independent&lt;/strong&gt; — destructive commands are blocked regardless of which preset is active&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Learning only suggests&lt;/strong&gt; — the permission learner proposes patterns, but the user must confirm before they take effect&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="per-repo-configuration"&gt;Per-Repo Configuration
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;auto-permission.json&lt;/code&gt; lives in the &lt;code&gt;.claude/&lt;/code&gt; directory at the project root. Different projects need different permissions even for the same developer. A blog repo needs &lt;code&gt;hugo server *&lt;/code&gt;, while an API server repo needs &lt;code&gt;docker compose *&lt;/code&gt;. This has to be per-project, not global.&lt;/p&gt;
&lt;h2 id="current-state-and-next-steps"&gt;Current State and Next Steps
&lt;/h2&gt;&lt;p&gt;What the first release includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Five presets with custom rule support&lt;/li&gt;
&lt;li&gt;PreToolUse hook-based auto-approve and block&lt;/li&gt;
&lt;li&gt;Permission learner and &lt;code&gt;/learn-permissions&lt;/code&gt; skill&lt;/li&gt;
&lt;li&gt;Universal deny list&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What comes next:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Edge cases discovered while applying to real projects&lt;/li&gt;
&lt;li&gt;Guide for customizing and creating new presets&lt;/li&gt;
&lt;li&gt;Potential integration with other hook events (&lt;code&gt;PostToolUse&lt;/code&gt;, &lt;code&gt;Notification&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;GitHub repository: &lt;a class="link" href="https://github.com/ice-ice-bear/claude-auto-permission" target="_blank" rel="noopener"
 &gt;ice-ice-bear/claude-auto-permission&lt;/a&gt;&lt;/p&gt;</description></item></channel></rss>