<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://mahditilab.github.io/claude-dev-daily/feed.xml" rel="self" type="application/atom+xml" /><link href="https://mahditilab.github.io/claude-dev-daily/" rel="alternate" type="text/html" /><updated>2026-10-21T12:48:18+00:00</updated><id>https://mahditilab.github.io/claude-dev-daily/feed.xml</id><title type="html">Claude Dev Daily</title><subtitle>A 10-minute lesson every weekday on what&apos;s new in Claude and Claude Code, for developers.</subtitle><entry><title type="html">Rules, permissions, hooks, mods: which one to use</title><link href="https://mahditilab.github.io/claude-dev-daily/2026/10/21/rules-permissions-hooks-mods/" rel="alternate" type="text/html" title="Rules, permissions, hooks, mods: which one to use" /><published>2026-10-21T06:30:00+00:00</published><updated>2026-10-21T06:30:00+00:00</updated><id>https://mahditilab.github.io/claude-dev-daily/2026/10/21/rules-permissions-hooks-mods</id><content type="html" xml:base="https://mahditilab.github.io/claude-dev-daily/2026/10/21/rules-permissions-hooks-mods/"><![CDATA[<p><strong>⏱ 10 min · Level: beginner → intermediate</strong></p>

<h2 id="1-the-idea-2-min">1. The idea (2 min)</h2>

<p>Claude Code gives you four ways to shape its behaviour. They differ in one thing: <strong>how sure you can be that it happens.</strong></p>

<table>
  <thead>
    <tr>
      <th>Tool</th>
      <th>What it is</th>
      <th>Guaranteed?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>CLAUDE.md</strong></td>
      <td>Instructions Claude reads at the start of every session</td>
      <td>No, it’s a strong suggestion</td>
    </tr>
    <tr>
      <td><strong>Permissions</strong></td>
      <td>Allow/deny rules in <code class="language-plaintext highlighter-rouge">settings.json</code></td>
      <td>Yes, always enforced</td>
    </tr>
    <tr>
      <td><strong>Hooks</strong></td>
      <td>Your shell command runs on fixed events (before/after a tool call, at the end of a turn…)</td>
      <td>Yes, they always fire</td>
    </tr>
    <tr>
      <td><strong>Mods</strong></td>
      <td>Functions loaded <em>into</em> Claude Code that change what it shows, what goes into the prompt and which tool calls it makes</td>
      <td>Yes, and they can rewrite behaviour</td>
    </tr>
  </tbody>
</table>

<p>Rule of thumb: <strong>use the weakest tool that does the job.</strong> Most things belong in CLAUDE.md. Move to permissions or hooks only when “usually” isn’t good enough.</p>

<h2 id="2-why-it-matters-1-min">2. Why it matters (1 min)</h2>

<p>Claude is non-deterministic. As a session grows, early instructions get buried. Thomas Schilling (Spring I/O 2026) said it clearly: <em>“Skills and CLAUDE.md can be skipped. Hooks can’t.”</em> Your guardrails (prod config, git history, build checks) should not depend on Claude remembering.</p>

<h2 id="3-example-a-spring-boot-project-3-min">3. Example: a Spring Boot project (3 min)</h2>

<p><strong>CLAUDE.md</strong> for conventions:</p>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">-</span> Build with ./mvnw, never mvn.
<span class="p">-</span> HTTP clients: RestClient, not RestTemplate.
<span class="p">-</span> Tests: JUnit 5 + AssertJ.
</code></pre></div></div>

<p><strong><code class="language-plaintext highlighter-rouge">.claude/settings.json</code></strong> with a hard rule and a hook:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"permissions"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"deny"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"Edit(**/application-prod.yml)"</span><span class="p">]</span><span class="w">
  </span><span class="p">},</span><span class="w">
  </span><span class="nl">"hooks"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"Stop"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
      </span><span class="p">{</span><span class="w"> </span><span class="nl">"hooks"</span><span class="p">:</span><span class="w"> </span><span class="p">[{</span><span class="w"> </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"command"</span><span class="p">,</span><span class="w"> </span><span class="nl">"command"</span><span class="p">:</span><span class="w"> </span><span class="s2">"./mvnw -q test || exit 2"</span><span class="w"> </span><span class="p">}]</span><span class="w"> </span><span class="p">}</span><span class="w">
    </span><span class="p">]</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<ul>
  <li>The deny rule means Claude <strong>cannot</strong> edit prod config.</li>
  <li>The <code class="language-plaintext highlighter-rouge">Stop</code> hook runs the tests when Claude thinks it’s done. Exit code <code class="language-plaintext highlighter-rouge">2</code> sends the failure back, and Claude keeps working.</li>
</ul>

<p>In Spring terms: CLAUDE.md is the team wiki, permissions are Spring Security, hooks are AOP advice, and mods are a <code class="language-plaintext highlighter-rouge">BeanPostProcessor</code> for Claude Code itself.</p>

<h2 id="4-try-it-3-min">4. Try it (3 min)</h2>

<ol>
  <li>In a Spring project, run <code class="language-plaintext highlighter-rouge">claude</code> and type <code class="language-plaintext highlighter-rouge">/init</code> to create a CLAUDE.md.</li>
  <li>Add the three lines above.</li>
  <li>Add the deny rule to <code class="language-plaintext highlighter-rouge">.claude/settings.json</code>.</li>
  <li>Ask Claude: <em>“Change the datasource URL in application-prod.yml.”</em> Watch it get blocked and explain why.</li>
</ol>

<h2 id="5-quick-check-1-min">5. Quick check (1 min)</h2>

<ol>
  <li>You want Claude to <em>prefer</em> records over classes for DTOs. Which tool?</li>
  <li>You must make sure Claude never runs <code class="language-plaintext highlighter-rouge">git push --force</code>. Which tool?</li>
  <li>You want a status line showing whether the last Maven build failed. Which tool?</li>
</ol>

<details><summary>Answers</summary>

1. CLAUDE.md, because it's a preference.
2. A permission deny rule (or a `PreToolUse` hook), because it must be guaranteed.
3. A mod (or the `statusLine` setting), because rules and hooks can't change the UI.

</details>

<h2 id="sources">Sources</h2>

<ul>
  <li><a href="https://code.claude.com/docs/en/hooks">Claude Code docs: hooks</a></li>
  <li><a href="https://code.claude.com/docs/en/settings">Claude Code docs: settings and permissions</a></li>
  <li><a href="https://www.youtube.com/watch?v=yUuFvL1lK4k">Mods in Claude Code (video)</a></li>
  <li><a href="https://www.youtube.com/watch?v=PmW4-tcMQbc">Claude Code for Spring Developers, Spring I/O 2026 (video)</a></li>
</ul>]]></content><author><name></name></author><category term="claude-code" /><category term="hooks" /><category term="mods" /><category term="claude-md" /><summary type="html"><![CDATA[⏱ 10 min · Level: beginner → intermediate]]></summary></entry></feed>