<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Auto-Permission on ICE-ICE-BEAR-BLOG</title><link>https://ice-ice-bear.github.io/ko/tags/auto-permission/</link><description>Recent content in Auto-Permission on ICE-ICE-BEAR-BLOG</description><generator>Hugo -- gohugo.io</generator><language>ko</language><lastBuildDate>Fri, 10 Apr 2026 00:00:00 +0900</lastBuildDate><atom:link href="https://ice-ice-bear.github.io/ko/tags/auto-permission/index.xml" rel="self" type="application/rss+xml"/><item><title>Claude Auto-Permission 개발기 #1 — 훅 기반 자동 권한 승인 시스템</title><link>https://ice-ice-bear.github.io/ko/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/ko/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 개발기 #1 — 훅 기반 자동 권한 승인 시스템" /&gt;&lt;h2 id="개요"&gt;개요
&lt;/h2&gt;&lt;p&gt;Claude Code를 본격적으로 사용하다 보면, 한 세션에 수백 번씩 &amp;ldquo;Allow&amp;rdquo; 버튼을 누르게 됩니다. 파일 읽기, &lt;code&gt;git status&lt;/code&gt;, 테스트 실행 같은 안전한 작업에도 매번 승인이 필요하죠. 내장된 &lt;code&gt;settings.local.json&lt;/code&gt;은 개별 승인 이력이 쌓이면서 금세 관리 불가능한 상태가 됩니다. 이 문제를 해결하기 위해 hook 기반 자동 권한 승인 시스템인 &lt;strong&gt;claude-auto-permission&lt;/strong&gt;을 만들었습니다.&lt;/p&gt;
&lt;h2 id="문제-인식--수백-번의-allow-클릭"&gt;문제 인식 — 수백 번의 &amp;ldquo;Allow&amp;rdquo; 클릭
&lt;/h2&gt;&lt;p&gt;Claude Code는 보안을 위해 모든 tool use에 사용자 승인을 요구합니다. 원칙적으로는 옳은 설계지만, 실제 개발 세션에서는 불필요한 마찰이 됩니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Read&lt;/code&gt; 도구로 파일 열기 — 매번 승인&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Bash&lt;/code&gt;로 &lt;code&gt;git status&lt;/code&gt; 실행 — 매번 승인&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Bash&lt;/code&gt;로 &lt;code&gt;npm test&lt;/code&gt; 실행 — 매번 승인&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Grep&lt;/code&gt;으로 코드 검색 — 매번 승인&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;한 시간 코딩 세션이면 100~200번의 클릭이 나옵니다. 그리고 이걸 수동으로 하나씩 승인하다 보면 &lt;code&gt;settings.local.json&lt;/code&gt;에 이런 항목들이 쌓입니다:&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;정확히 일치하는 명령어만 기록되기 때문에, &lt;code&gt;git log --oneline -20&lt;/code&gt;과 &lt;code&gt;git log --oneline -10&lt;/code&gt;은 별개의 항목입니다. 패턴화가 안 되니까 끝없이 늘어납니다.&lt;/p&gt;
&lt;h2 id="설계--hook-아키텍처"&gt;설계 — Hook 아키텍처
&lt;/h2&gt;&lt;p&gt;Claude Code의 hook 시스템은 &lt;code&gt;PreToolUse&lt;/code&gt;, &lt;code&gt;PostToolUse&lt;/code&gt; 같은 이벤트에 외부 스크립트를 연결할 수 있게 해줍니다. 이 구조를 활용하면, tool이 실행되기 전에 우리가 먼저 판단해서 자동 승인하거나 차단할 수 있습니다.&lt;/p&gt;
&lt;p&gt;전체 아키텍처는 이렇게 생겼습니다:&lt;/p&gt;
&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TD
 A["Claude Code&amp;lt;br/&amp;gt;Tool Use 요청"] --&gt; B["PreToolUse Hook&amp;lt;br/&amp;gt;selective-auto-permission.mjs"]
 B --&gt; C{"auto-permission.json&amp;lt;br/&amp;gt;규칙 확인"}
 C --&gt;|deny 매칭| D["차단&amp;lt;br/&amp;gt;reason 반환"]
 C --&gt;|allow 매칭| E["자동 승인&amp;lt;br/&amp;gt;approve 반환"]
 C --&gt;|매칭 없음| F["사용자에게&amp;lt;br/&amp;gt;수동 승인 요청"]
 F --&gt;|승인| G["settings.local.json&amp;lt;br/&amp;gt;에 기록"]
 G --&gt; H["/learn-permissions&amp;lt;br/&amp;gt;skill 실행"]
 H --&gt; I["패턴화하여&amp;lt;br/&amp;gt;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;핵심 구성 요소는 세 가지입니다:&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; — PreToolUse hook. 매 tool use마다 &lt;code&gt;auto-permission.json&lt;/code&gt;의 allow/deny 목록을 확인하고 판단합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;permission-learner.mjs&lt;/code&gt;&lt;/strong&gt; — 수동 승인 이력을 분석해서 패턴을 추출합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;/learn-permissions&lt;/code&gt; skill&lt;/strong&gt; — 학습된 패턴을 &lt;code&gt;auto-permission.json&lt;/code&gt;에 병합하는 대화형 워크플로우입니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="preset-시스템"&gt;Preset 시스템
&lt;/h2&gt;&lt;p&gt;매번 규칙을 처음부터 작성하는 건 비현실적입니다. 그래서 개발 환경별로 5개의 preset을 제공합니다:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Preset&lt;/th&gt;
 &lt;th&gt;용도&lt;/th&gt;
 &lt;th&gt;자동 승인 범위&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;읽기 전용&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 개발&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 개발&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;풀스택&lt;/td&gt;
 &lt;td&gt;node-dev + python-dev 통합&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;전체 신뢰&lt;/td&gt;
 &lt;td&gt;거의 모든 tool (deny 목록 제외)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;모든 preset이 공통으로 &lt;strong&gt;절대 자동 승인하지 않는&lt;/strong&gt; 명령어가 있습니다:&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;&lt;code&gt;full-trust&lt;/code&gt; preset을 선택하더라도, 이 네 가지는 반드시 수동 승인을 거칩니다. 실수로 &lt;code&gt;rm -rf /&lt;/code&gt;가 자동 승인되는 일은 없어야 하니까요.&lt;/p&gt;
&lt;h2 id="auto-permissionjson-구조"&gt;auto-permission.json 구조
&lt;/h2&gt;&lt;p&gt;각 프로젝트 루트의 &lt;code&gt;.claude/auto-permission.json&lt;/code&gt;에 규칙을 정의합니다:&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;&lt;code&gt;preset&lt;/code&gt;으로 기본 규칙을 가져오고, &lt;code&gt;custom_allow&lt;/code&gt;와 &lt;code&gt;custom_deny&lt;/code&gt;로 프로젝트 특화 규칙을 추가합니다. 패턴은 glob 스타일 매칭을 지원하기 때문에, &lt;code&gt;docker compose *&lt;/code&gt;는 &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; 등을 모두 포함합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;규칙 우선순위&lt;/strong&gt;: deny가 항상 allow보다 우선합니다. 같은 명령어가 allow와 deny 양쪽에 매칭되면 차단됩니다. 안전 쪽으로 기울어지는 게 맞으니까요.&lt;/p&gt;
&lt;h2 id="permission-learner--승인-이력에서-패턴-추출"&gt;Permission Learner — 승인 이력에서 패턴 추출
&lt;/h2&gt;&lt;p&gt;수동 승인을 반복하다 보면 &lt;code&gt;settings.local.json&lt;/code&gt;에 비슷한 명령어들이 쌓입니다:&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;는 이런 항목들을 분석해서:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;공통 접두사를 추출하고 (&lt;code&gt;pytest&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;안전 분류를 수행하고 (read-only인지, 파일 시스템 변경이 있는지)&lt;/li&gt;
&lt;li&gt;패턴으로 일반화합니다 (&lt;code&gt;pytest *&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;/learn-permissions&lt;/code&gt; skill을 실행하면, 학습된 패턴을 보여주고 사용자 확인 후 &lt;code&gt;auto-permission.json&lt;/code&gt;의 &lt;code&gt;custom_allow&lt;/code&gt;에 추가합니다. 한 번 학습되면 같은 계열의 명령어는 더 이상 수동 승인이 필요 없습니다.&lt;/p&gt;
&lt;h2 id="구현에서-고민한-부분"&gt;구현에서 고민한 부분
&lt;/h2&gt;&lt;h3 id="hook의-응답-속도"&gt;Hook의 응답 속도
&lt;/h3&gt;&lt;p&gt;PreToolUse hook은 매 tool use마다 실행됩니다. Node.js 프로세스를 매번 새로 띄우면 cold start 오버헤드가 걱정되지만, 실제로 측정해보면 JSON 파일 하나 읽고 패턴 매칭하는 데 걸리는 시간은 수십 밀리초 수준입니다. 사용자가 체감할 수 있는 지연은 아닙니다.&lt;/p&gt;
&lt;h3 id="보안과-편의의-균형"&gt;보안과 편의의 균형
&lt;/h3&gt;&lt;p&gt;자동 권한 시스템에서 가장 중요한 건 &amp;ldquo;어디까지 자동으로 허용할 것인가&amp;quot;입니다. 너무 넓게 열면 위험하고, 너무 좁으면 쓸모가 없습니다.&lt;/p&gt;
&lt;p&gt;이 프로젝트에서는 세 가지 원칙을 세웠습니다:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deny가 항상 우선&lt;/strong&gt; — allow 목록이 아무리 넓어도, deny에 매칭되면 차단&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Universal deny는 preset 독립&lt;/strong&gt; — 어떤 preset을 쓰든 파괴적 명령어는 항상 차단&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;학습은 제안까지만&lt;/strong&gt; — permission learner가 패턴을 제안하지만, 실제 적용은 사용자가 확인&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="per-repo-설정"&gt;Per-repo 설정
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;auto-permission.json&lt;/code&gt;은 프로젝트 루트의 &lt;code&gt;.claude/&lt;/code&gt; 디렉토리에 위치합니다. 같은 개발자라도 프로젝트마다 필요한 권한이 다르기 때문입니다. 블로그 레포에서는 &lt;code&gt;hugo server *&lt;/code&gt;가 필요하지만, API 서버 레포에서는 &lt;code&gt;docker compose *&lt;/code&gt;가 필요하죠. 글로벌 설정이 아니라 프로젝트별 설정으로 가야 합니다.&lt;/p&gt;
&lt;h2 id="현재-상태와-다음-단계"&gt;현재 상태와 다음 단계
&lt;/h2&gt;&lt;p&gt;첫 번째 릴리스에서 구현한 것:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;5개 preset과 custom rule 시스템&lt;/li&gt;
&lt;li&gt;PreToolUse hook 기반 자동 승인/차단&lt;/li&gt;
&lt;li&gt;Permission learner와 &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;다음에 다룰 내용:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;실제 프로젝트에 적용하면서 발견한 edge case들&lt;/li&gt;
&lt;li&gt;Preset 커스터마이징 가이드&lt;/li&gt;
&lt;li&gt;다른 hook 이벤트(&lt;code&gt;PostToolUse&lt;/code&gt;, &lt;code&gt;Notification&lt;/code&gt;)와의 연계 가능성&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;GitHub 저장소: &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>