<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vildanden</title>
    <description>The latest articles on DEV Community by Vildanden (@vildandenai).</description>
    <link>https://dev.to/vildandenai</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4128566%2Faf126918-50e5-4f9d-9586-c96c758ecb77.png</url>
      <title>DEV Community: Vildanden</title>
      <link>https://dev.to/vildandenai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vildandenai"/>
    <language>en</language>
    <item>
      <title>Show the model and git branch in Claude Code with a 6-line status line script</title>
      <dc:creator>Vildanden</dc:creator>
      <pubDate>Thu, 29 Oct 2026 01:14:55 +0000</pubDate>
      <link>https://dev.to/vildandenai/show-the-model-and-git-branch-in-claude-code-with-a-6-line-status-line-script-1fc1</link>
      <guid>https://dev.to/vildandenai/show-the-model-and-git-branch-in-claude-code-with-a-6-line-status-line-script-1fc1</guid>
      <description>&lt;p&gt;When you run Claude Code in a few repos at once, it's easy to lose track of which branch you're on and which model is answering. Claude Code has a configurable status line for exactly this: a small script whose output shows up under the prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;You point &lt;code&gt;statusLine&lt;/code&gt; in your settings at a command. Claude Code runs it, passes session details as JSON on stdin, and shows the first line the script prints.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;~/.claude/settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"statusLine"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~/.claude/statusline.sh"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The script
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;~/.claude/statusline.sh&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="nv"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.model.display_name'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.workspace.current_dir'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;branch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$dir&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; branch &lt;span class="nt"&gt;--show-current&lt;/span&gt; 2&amp;gt;/dev/null&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"[&lt;/span&gt;&lt;span class="nv"&gt;$model&lt;/span&gt;&lt;span class="s2"&gt;] &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;##*/&lt;/span&gt;&lt;span class="k"&gt;}${&lt;/span&gt;&lt;span class="nv"&gt;branch&lt;/span&gt;:+&lt;span class="p"&gt; on &lt;/span&gt;&lt;span class="nv"&gt;$branch&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make it executable with &lt;code&gt;chmod +x ~/.claude/statusline.sh&lt;/code&gt;, and you'll see something like &lt;code&gt;[Sonnet] api on fix/login-timeout&lt;/code&gt; under the prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Keep it fast. It runs often, so avoid network calls or slow git commands.&lt;/li&gt;
&lt;li&gt;It needs &lt;code&gt;jq&lt;/code&gt;. If you'd rather not install it, the same script works in a few lines of Python reading &lt;code&gt;sys.stdin&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Put it in your user settings, not the project file, since it's a personal preference rather than a team rule.&lt;/li&gt;
&lt;li&gt;Type &lt;code&gt;/statusline&lt;/code&gt; in Claude Code if you'd like it to draft a script for you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The team-side setup that goes with this (a short &lt;code&gt;CLAUDE.md&lt;/code&gt;, shared permissions, a risky-git hook and a read-only reviewer subagent) ships in &lt;a href="https://justly-mia-429.rehost.page/" rel="noopener noreferrer"&gt;Vildanden Agent Config&lt;/a&gt;. The free sample is enough to get started today.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>git</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Keep personal Claude Code settings out of git with settings.local.json</title>
      <dc:creator>Vildanden</dc:creator>
      <pubDate>Wed, 28 Oct 2026 01:10:49 +0000</pubDate>
      <link>https://dev.to/vildandenai/keep-personal-claude-code-settings-out-of-git-with-settingslocaljson-3hld</link>
      <guid>https://dev.to/vildandenai/keep-personal-claude-code-settings-out-of-git-with-settingslocaljson-3hld</guid>
      <description>&lt;p&gt;Claude Code reads settings from more than one file, and most teams only use one of them. If you've ever committed your own allow-list tweak by accident, or argued about whose model choice goes in the repo, the fix is to split shared rules from personal ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three files
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;~/.claude/settings.json&lt;/code&gt; holds your user settings, applied in every project on your machine.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.claude/settings.json&lt;/code&gt; holds project settings. Commit this one so the whole team gets the same rules.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.claude/settings.local.json&lt;/code&gt; holds your personal settings for this project. Claude Code configures git to ignore it when it creates the file, so it stays on your machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the same setting appears in more than one file, the more specific one wins: local beats project, and project beats user. Managed enterprise policy, if your company uses it, sits above all three.&lt;/p&gt;

&lt;h2&gt;
  
  
  A split that works
&lt;/h2&gt;

&lt;p&gt;Shared, in &lt;code&gt;.claude/settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Bash(npm test:*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bash(git diff:*)"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ask"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Bash(git push:*)"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Read(./.env)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Read(./.env.*)"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Personal, in &lt;code&gt;.claude/settings.local.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Bash(docker compose up:*)"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The team keeps the safety rails, and you get your extra command without a pull request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Put deny rules in the project file. A teammate's local file shouldn't be where &lt;code&gt;.env&lt;/code&gt; protection lives.&lt;/li&gt;
&lt;li&gt;Check &lt;code&gt;.gitignore&lt;/code&gt; once if you created &lt;code&gt;settings.local.json&lt;/code&gt; by hand rather than through Claude Code.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;/permissions&lt;/code&gt; inside Claude Code to see which rules are active and where each one came from.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project-side file, plus a short &lt;code&gt;CLAUDE.md&lt;/code&gt;, a risky-git hook and a read-only reviewer subagent, ships in &lt;a href="https://justly-mia-429.rehost.page/" rel="noopener noreferrer"&gt;Vildanden Agent Config&lt;/a&gt;. The free sample is enough to set this up today.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>git</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Make Claude Code ask before git push with one "ask" rule</title>
      <dc:creator>Vildanden</dc:creator>
      <pubDate>Tue, 27 Oct 2026 01:13:37 +0000</pubDate>
      <link>https://dev.to/vildandenai/make-claude-code-ask-before-git-push-with-one-ask-rule-2oe2</link>
      <guid>https://dev.to/vildandenai/make-claude-code-ask-before-git-push-with-one-ask-rule-2oe2</guid>
      <description>&lt;p&gt;Allow-lists and deny-lists get most of the attention, but Claude Code's &lt;code&gt;settings.json&lt;/code&gt; has a third list that is often the most useful: &lt;code&gt;ask&lt;/code&gt;. A command on it isn't blocked and isn't silently allowed. Claude stops and asks you first, every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The settings
&lt;/h2&gt;

&lt;p&gt;Put this in &lt;code&gt;.claude/settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Bash(git status)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Bash(git diff:*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Bash(npm test:*)"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ask"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Bash(git push:*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Bash(git commit:*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Bash(npm publish:*)"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Read(./.env)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Read(./.env.*)"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why "ask" beats "deny" for push
&lt;/h2&gt;

&lt;p&gt;If you deny &lt;code&gt;git push&lt;/code&gt;, the agent can never finish a task end to end, and people end up deleting the rule. If you allow it, one bad loop can push a half-finished branch. &lt;code&gt;ask&lt;/code&gt; keeps the agent fast on everything local and puts you in front of the one step that leaves your machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Deny rules win over ask, and ask wins over allow, so you can be broad in &lt;code&gt;allow&lt;/code&gt; and still catch the risky cases.&lt;/li&gt;
&lt;li&gt;Commit &lt;code&gt;.claude/settings.json&lt;/code&gt; so teammates get the same prompts; keep personal tweaks in &lt;code&gt;.claude/settings.local.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;git commit&lt;/code&gt; to &lt;code&gt;ask&lt;/code&gt; only if you want to read every message; many people keep just &lt;code&gt;push&lt;/code&gt; and &lt;code&gt;publish&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same three lists ship with a short &lt;code&gt;CLAUDE.md&lt;/code&gt;, a risky-git hook and a read-only reviewer subagent in &lt;a href="https://justly-mia-429.rehost.page/" rel="noopener noreferrer"&gt;Vildanden Agent Config&lt;/a&gt;. The free sample is enough to set this up today.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>git</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Give Claude Code a read-only reviewer subagent in one file</title>
      <dc:creator>Vildanden</dc:creator>
      <pubDate>Mon, 26 Oct 2026 01:17:08 +0000</pubDate>
      <link>https://dev.to/vildandenai/give-claude-code-a-read-only-reviewer-subagent-in-one-file-28a5</link>
      <guid>https://dev.to/vildandenai/give-claude-code-a-read-only-reviewer-subagent-in-one-file-28a5</guid>
      <description>&lt;p&gt;The agent that wrote the code is a poor judge of it. Claude Code lets you define subagents with their own prompt and their own tool list, so you can keep a reviewer around that can read everything and change nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The file
&lt;/h2&gt;

&lt;p&gt;Save this as &lt;code&gt;.claude/agents/reviewer.md&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;reviewer&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Reviews&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;current&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;diff&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;bugs,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;missing&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tests&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;risky&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;changes.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Use&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;after&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;finishing&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;task&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;before&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;committing."&lt;/span&gt;
&lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Read, Grep, Glob, Bash(git diff:*)&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

You are a strict code reviewer. You cannot edit files.
&lt;span class="p"&gt;
1.&lt;/span&gt; Run &lt;span class="sb"&gt;`git diff`&lt;/span&gt; and read every changed file in full, not just the hunks.
&lt;span class="p"&gt;2.&lt;/span&gt; List real problems only: bugs, unhandled errors, missing tests, secrets, breaking API changes.
&lt;span class="p"&gt;3.&lt;/span&gt; For each one give the file, the line, and a one-sentence fix.
&lt;span class="p"&gt;4.&lt;/span&gt; If nothing is wrong, say "No blocking issues" and stop.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using it
&lt;/h2&gt;

&lt;p&gt;Ask "use the reviewer subagent on my changes", or add a line to &lt;code&gt;CLAUDE.md&lt;/code&gt; telling the main agent to call it before every commit. The reviewer runs in its own context, so a long review doesn't eat the main session's memory, and its limited tools mean it can't "fix" things behind your back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Keep the tool list tight. Read, Grep and Glob plus &lt;code&gt;git diff&lt;/code&gt; covers almost every review.&lt;/li&gt;
&lt;li&gt;Commit &lt;code&gt;.claude/agents/&lt;/code&gt; so the whole team gets the same reviewer.&lt;/li&gt;
&lt;li&gt;Pair it with a &lt;code&gt;/review&lt;/code&gt; slash command if you prefer to trigger it by hand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I ship this reviewer with a short &lt;code&gt;CLAUDE.md&lt;/code&gt;, a risky-git hook, &lt;code&gt;.env&lt;/code&gt; deny rules and a Bash allow-list in &lt;a href="https://justly-mia-429.rehost.page/" rel="noopener noreferrer"&gt;Vildanden Agent Config&lt;/a&gt;. The free sample is enough to try the setup today.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>codereview</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Block risky git commands in Claude Code with one PreToolUse hook</title>
      <dc:creator>Vildanden</dc:creator>
      <pubDate>Fri, 23 Oct 2026 01:13:38 +0000</pubDate>
      <link>https://dev.to/vildandenai/block-risky-git-commands-in-claude-code-with-one-pretooluse-hook-3006</link>
      <guid>https://dev.to/vildandenai/block-risky-git-commands-in-claude-code-with-one-pretooluse-hook-3006</guid>
      <description>&lt;p&gt;An agent with shell access will eventually try &lt;code&gt;git push --force&lt;/code&gt; or &lt;code&gt;git reset --hard&lt;/code&gt; when it gets confused. You don't need to watch every command. A small PreToolUse hook can stop the dangerous ones before they run.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hook
&lt;/h2&gt;

&lt;p&gt;Save this as &lt;code&gt;.claude/hooks/block-risky-git.sh&lt;/code&gt; and make it executable (&lt;code&gt;chmod +x&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# Reads the tool call as JSON on stdin; exit code 2 blocks it.&lt;/span&gt;
&lt;span class="nv"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.tool_input.command // ""'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$cmd&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-Eq&lt;/span&gt; &lt;span class="s1"&gt;'git (push .*(--force|-f)|reset --hard|clean -fd|branch -D|checkout -- \.)'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Blocked: '&lt;/span&gt;&lt;span class="nv"&gt;$cmd&lt;/span&gt;&lt;span class="s2"&gt;' can destroy work. Ask the user to run it themselves."&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
  &lt;span class="nb"&gt;exit &lt;/span&gt;2
&lt;span class="k"&gt;fi
&lt;/span&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then register it in &lt;code&gt;.claude/settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"PreToolUse"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"matcher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".claude/hooks/block-risky-git.sh"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What happens
&lt;/h2&gt;

&lt;p&gt;When Claude tries one of those commands, the hook exits with code 2. The command never runs, and the message on stderr goes back to Claude, so it explains the situation to you instead of retrying blindly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Keep the pattern list short and specific. Blocking all of &lt;code&gt;git push&lt;/code&gt; just trains you to turn the hook off.&lt;/li&gt;
&lt;li&gt;Commit the hook so everyone on the repo gets the same guardrail.&lt;/li&gt;
&lt;li&gt;Pair it with a Bash allow-list so ordinary commands don't prompt you every time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I ship this hook alongside a Bash allow-list, &lt;code&gt;.env&lt;/code&gt; deny rules, a &lt;code&gt;/review&lt;/code&gt; command, and a short &lt;code&gt;CLAUDE.md&lt;/code&gt; in &lt;a href="https://justly-mia-429.rehost.page/" rel="noopener noreferrer"&gt;Vildanden Agent Config&lt;/a&gt;. The free sample is enough to try the pattern today.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>git</category>
      <category>devtools</category>
    </item>
    <item>
      <title>A /review slash command that makes Claude Code check its own diff before you commit</title>
      <dc:creator>Vildanden</dc:creator>
      <pubDate>Thu, 22 Oct 2026 01:08:52 +0000</pubDate>
      <link>https://dev.to/vildandenai/a-review-slash-command-that-makes-claude-code-check-its-own-diff-before-you-commit-823</link>
      <guid>https://dev.to/vildandenai/a-review-slash-command-that-makes-claude-code-check-its-own-diff-before-you-commit-823</guid>
      <description>&lt;p&gt;Most bad commits from an agent aren't wrong code. They're leftover debug prints, a half-renamed variable, or a test that got skipped "for now". A one-file custom slash command catches most of that before it lands.&lt;/p&gt;

&lt;h2&gt;
  
  
  The command
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;.claude/commands/review.md&lt;/code&gt; in your repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Review the staged diff before committing&lt;/span&gt;
&lt;span class="na"&gt;allowed-tools&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Bash(git diff:*), Bash(git status:*)&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

Run &lt;span class="sb"&gt;`git diff --staged`&lt;/span&gt; and review only what changed.

Report, in this order:
&lt;span class="p"&gt;1.&lt;/span&gt; Leftover debug output, commented-out code, or TODOs added in this diff.
&lt;span class="p"&gt;2.&lt;/span&gt; Renames or signature changes that weren't applied everywhere.
&lt;span class="p"&gt;3.&lt;/span&gt; Tests that were skipped, deleted, or weakened.
&lt;span class="p"&gt;4.&lt;/span&gt; Anything that touches secrets, auth, or config files.

Do not edit files. End with "OK to commit" or a short list of what to fix.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;/review&lt;/code&gt; in a session runs it. Because &lt;code&gt;allowed-tools&lt;/code&gt; only lists read-only git commands, the review can't quietly "fix" things behind your back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scoped input.&lt;/strong&gt; It only looks at the staged diff, so the answer stays short and specific.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fixed checklist.&lt;/strong&gt; The same four questions every time beats "does this look good?".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No edits.&lt;/strong&gt; You decide what to change, and the agent re-runs &lt;code&gt;/review&lt;/code&gt; after.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Make it a habit
&lt;/h2&gt;

&lt;p&gt;Commit the &lt;code&gt;.claude/commands/&lt;/code&gt; folder so the whole team gets the same command. Pair it with a Stop hook that reminds you to run &lt;code&gt;/review&lt;/code&gt; when a session ends with uncommitted changes.&lt;/p&gt;

&lt;p&gt;I ship this command alongside a Bash allow-list, &lt;code&gt;.env&lt;/code&gt; deny rules, safety hooks, and a short &lt;code&gt;CLAUDE.md&lt;/code&gt; in &lt;a href="https://justly-mia-429.rehost.page/" rel="noopener noreferrer"&gt;Vildanden Agent Config&lt;/a&gt;. The free sample is enough to try the pattern today.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>productivity</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Stop Claude Code from reading your .env with three deny rules</title>
      <dc:creator>Vildanden</dc:creator>
      <pubDate>Wed, 21 Oct 2026 01:07:57 +0000</pubDate>
      <link>https://dev.to/vildandenai/stop-claude-code-from-reading-your-env-with-three-deny-rules-24bl</link>
      <guid>https://dev.to/vildandenai/stop-claude-code-from-reading-your-env-with-three-deny-rules-24bl</guid>
      <description>&lt;p&gt;An agent that can read any file in your repo can also read &lt;code&gt;.env&lt;/code&gt;, and whatever it reads can end up in a prompt, a log, or a commit message. You don't need to trust it to behave. You can just say no in &lt;code&gt;settings.json&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rules
&lt;/h2&gt;

&lt;p&gt;Put this in &lt;code&gt;.claude/settings.json&lt;/code&gt; at the repo root so it applies to everyone who opens the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Read(./.env)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Read(./.env.*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Read(./secrets/**)"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deny rules win over allow rules, so even if someone later adds a broad &lt;code&gt;Read&lt;/code&gt; allow, these files stay off limits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things people miss
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example files are fine.&lt;/strong&gt; If you keep a &lt;code&gt;.env.example&lt;/code&gt;, it's caught by &lt;code&gt;./.env.*&lt;/code&gt; too. Rename it to &lt;code&gt;env.example&lt;/code&gt; or add it back with a narrower pattern.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shell is a side door.&lt;/strong&gt; A deny on &lt;code&gt;Read&lt;/code&gt; doesn't stop &lt;code&gt;cat .env&lt;/code&gt; through Bash. Keep Bash on an allow-list of specific commands instead of allowing everything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commit the file.&lt;/strong&gt; &lt;code&gt;.claude/settings.json&lt;/code&gt; is meant to be checked in. Personal overrides go in &lt;code&gt;.claude/settings.local.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check your version.&lt;/strong&gt; Permission rule syntax has changed between Claude Code releases, so confirm against the settings docs for the version you run.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Test it
&lt;/h2&gt;

&lt;p&gt;Ask the agent to "show me the contents of .env". It should refuse with a permission message rather than print anything. If it prints, your rule path doesn't match.&lt;/p&gt;

&lt;p&gt;I ship this deny list together with a Bash allow-list, safety hooks, and a short &lt;code&gt;CLAUDE.md&lt;/code&gt; in &lt;a href="https://justly-mia-429.rehost.page/" rel="noopener noreferrer"&gt;Vildanden Agent Config&lt;/a&gt;. The free sample is enough to try the pattern today.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>security</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Keep your CLAUDE.md under 40 lines so Claude Code actually follows it</title>
      <dc:creator>Vildanden</dc:creator>
      <pubDate>Tue, 20 Oct 2026 01:10:34 +0000</pubDate>
      <link>https://dev.to/vildandenai/keep-your-claudemd-under-40-lines-so-claude-code-actually-follows-it-2hhf</link>
      <guid>https://dev.to/vildandenai/keep-your-claudemd-under-40-lines-so-claude-code-actually-follows-it-2hhf</guid>
      <description>&lt;p&gt;Most &lt;code&gt;CLAUDE.md&lt;/code&gt; files I see grow into a wiki: architecture notes, style essays, a changelog, three pasted READMEs. Then people wonder why the agent ignores the one rule that mattered.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt; is loaded into context at the start of a session, so every line competes with your actual task. Short, concrete house rules beat long explanations.&lt;/p&gt;

&lt;h2&gt;
  
  
  A shape that works
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# House rules&lt;/span&gt;

&lt;span class="gu"&gt;## Before you edit&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Read the file and its tests before changing it.
&lt;span class="p"&gt;-&lt;/span&gt; Ask before adding a new dependency.

&lt;span class="gu"&gt;## Commands&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Test: &lt;span class="sb"&gt;`npm test`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Lint: &lt;span class="sb"&gt;`npm run lint -- --fix`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Never run: &lt;span class="sb"&gt;`git push --force`&lt;/span&gt;, &lt;span class="sb"&gt;`rm -rf`&lt;/span&gt;, database migrations.

&lt;span class="gu"&gt;## Done means&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Tests and lint pass locally.
&lt;span class="p"&gt;-&lt;/span&gt; You list the files you changed and why, in one line each.

&lt;span class="gu"&gt;## Style&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Match the surrounding code. No drive-by refactors.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the whole file. Each line is something you could check in a diff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rules of thumb
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Commands over prose.&lt;/strong&gt; "Test: &lt;code&gt;npm test&lt;/code&gt;" is better than a paragraph about the test philosophy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enforce, don't plead.&lt;/strong&gt; If a rule really must hold (no force-push, tests after edits), put it in a hook or the allow-list in &lt;code&gt;settings.json&lt;/code&gt;. &lt;code&gt;CLAUDE.md&lt;/code&gt; is guidance; hooks are guarantees.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Move reference material out.&lt;/strong&gt; Link to &lt;code&gt;docs/architecture.md&lt;/code&gt; and let the agent read it when needed instead of loading it every session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prune monthly.&lt;/strong&gt; If a rule never changed a diff, delete it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check the memory docs for your installed Claude Code version; how nested and user-level files are loaded can change between releases.&lt;/p&gt;

&lt;p&gt;I ship this short house-rules file together with the allow-list and the safety hooks in &lt;a href="https://justly-mia-429.rehost.page/" rel="noopener noreferrer"&gt;Vildanden Agent Config&lt;/a&gt;. The free sample is enough to try the pattern today.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>devtools</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Get a desktop ping when Claude Code is waiting on you, with a Notification hook</title>
      <dc:creator>Vildanden</dc:creator>
      <pubDate>Mon, 19 Oct 2026 01:08:01 +0000</pubDate>
      <link>https://dev.to/vildandenai/get-a-desktop-ping-when-claude-code-is-waiting-on-you-with-a-notification-hook-4i4j</link>
      <guid>https://dev.to/vildandenai/get-a-desktop-ping-when-claude-code-is-waiting-on-you-with-a-notification-hook-4i4j</guid>
      <description>&lt;p&gt;You kick off a long Claude Code task, switch to another window, and come back twenty minutes later to find it stopped after two minutes, waiting for you to approve one command.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;Notification&lt;/code&gt; hook fixes that. Claude Code fires it when it needs your attention, such as a permission prompt or an idle wait for input, and the hook receives a small JSON payload on stdin with a &lt;code&gt;message&lt;/code&gt; field.&lt;/p&gt;

&lt;h2&gt;
  
  
  The script
&lt;/h2&gt;

&lt;p&gt;Save as &lt;code&gt;.claude/hooks/notify.sh&lt;/code&gt; and &lt;code&gt;chmod +x&lt;/code&gt; it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# notify.sh: desktop ping when Claude Code needs you&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-uo&lt;/span&gt; pipefail
&lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'import sys,json; print(json.load(sys.stdin).get("message","Claude Code needs you"))'&lt;/span&gt; 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Claude Code needs you"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; osascript &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;osascript &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"display notification &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;//\&lt;/span&gt;&lt;span class="s2"&gt;"/}&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; with title &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Claude Code&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;
elif command -v notify-send &amp;gt;/dev/null; then
  notify-send &lt;/span&gt;&lt;span class="s2"&gt;"Claude Code"&lt;/span&gt;&lt;span class="p"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$msg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;
else
  printf &lt;/span&gt;&lt;span class="s1"&gt;'\a'&lt;/span&gt;&lt;span class="p"&gt;  # terminal bell as a last resort
fi
exit 0
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Register it
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;.claude/settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Notification"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".claude/hooks/notify.sh"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the hooks page for your installed Claude Code version; payload fields and matcher options can change between releases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep it useful
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Always &lt;code&gt;exit 0&lt;/code&gt;. A notification hook should never block the session.&lt;/li&gt;
&lt;li&gt;Pair it with a sensible allow-list in &lt;code&gt;settings.json&lt;/code&gt;, so you get pinged for decisions that matter, not for every &lt;code&gt;ls&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Keep the message short. You want to know which repo is waiting, not read a log.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I keep this hook alongside the allow-list, the safety hooks, and a short house-rules file in &lt;a href="https://justly-mia-429.rehost.page/" rel="noopener noreferrer"&gt;Vildanden Agent Config&lt;/a&gt;. The free sample has enough to try the pattern today.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>devtools</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Give Claude Code a fresh repo briefing on every session with a SessionStart hook</title>
      <dc:creator>Vildanden</dc:creator>
      <pubDate>Fri, 16 Oct 2026 01:08:20 +0000</pubDate>
      <link>https://dev.to/vildandenai/give-claude-code-a-fresh-repo-briefing-on-every-session-with-a-sessionstart-hook-3334</link>
      <guid>https://dev.to/vildandenai/give-claude-code-a-fresh-repo-briefing-on-every-session-with-a-sessionstart-hook-3334</guid>
      <description>&lt;p&gt;Every new Claude Code session starts cold. It doesn't know which branch you're on, what's uncommitted, or that CI went red an hour ago, so the first few turns get spent rediscovering it.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;SessionStart&lt;/code&gt; hook fixes that. It runs when a session starts (or resumes), and whatever the command prints to stdout is added to the session context.&lt;/p&gt;

&lt;h2&gt;
  
  
  The script
&lt;/h2&gt;

&lt;p&gt;Save as &lt;code&gt;.claude/hooks/session-brief.sh&lt;/code&gt; and &lt;code&gt;chmod +x&lt;/code&gt; it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# session-brief.sh: short repo briefing for a new Claude Code session&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-uo&lt;/span&gt; pipefail
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"[repo briefing]"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"branch: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;--abbrev-ref&lt;/span&gt; HEAD 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'not a git repo'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"uncommitted files: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git status &lt;span class="nt"&gt;--porcelain&lt;/span&gt; 2&amp;gt;/dev/null | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"last 3 commits:"&lt;/span&gt;
git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; &lt;span class="nt"&gt;-3&lt;/span&gt; 2&amp;gt;/dev/null | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/^/  /'&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; TODO.md &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"open TODOs (first 5):"&lt;/span&gt;
  &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-m5&lt;/span&gt; &lt;span class="s1"&gt;'^- \[ \]'&lt;/span&gt; TODO.md | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/^/  /'&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Register it
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;.claude/settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"SessionStart"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".claude/hooks/session-brief.sh"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the hooks page for your installed Claude Code version; matcher options (startup, resume, clear) and exact fields can change between releases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep it small
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ten lines of briefing beats a hundred. The goal is orientation, not a dump of &lt;code&gt;git diff&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Don't print secrets or &lt;code&gt;.env&lt;/code&gt; values. Anything on stdout goes into the model's context.&lt;/li&gt;
&lt;li&gt;Pair it with a short &lt;code&gt;CLAUDE.md&lt;/code&gt; for standing house rules and deny/ask rules in &lt;code&gt;settings.json&lt;/code&gt;, so each piece does one job.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I keep the session hook, the settings file, and the short house-rules file together in &lt;a href="https://justly-mia-429.rehost.page/" rel="noopener noreferrer"&gt;Vildanden Agent Config&lt;/a&gt;. The free sample has enough to try the pattern today.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>devtools</category>
      <category>git</category>
    </item>
    <item>
      <title>Inject a budget line into every Claude Code prompt with UserPromptSubmit</title>
      <dc:creator>Vildanden</dc:creator>
      <pubDate>Thu, 15 Oct 2026 01:20:24 +0000</pubDate>
      <link>https://dev.to/vildandenai/inject-a-budget-line-into-every-claude-code-prompt-with-userpromptsubmit-f3f</link>
      <guid>https://dev.to/vildandenai/inject-a-budget-line-into-every-claude-code-prompt-with-userpromptsubmit-f3f</guid>
      <description>&lt;p&gt;Hooks are not only for blocking bad tool calls. &lt;code&gt;UserPromptSubmit&lt;/code&gt; runs when you send a message, before the model sees it — so you can inject a short context block every turn without bloating &lt;code&gt;CLAUDE.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Use it for a standing budget reminder: context window, spend ceiling, or “prefer local tools over network.”&lt;/p&gt;

&lt;h2&gt;
  
  
  Minimal hook
&lt;/h2&gt;

&lt;p&gt;Put this under &lt;code&gt;.claude/hooks/&lt;/code&gt; (exact registration path can vary by Claude Code version — confirm against your installed docs):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# user-prompt-submit.sh — stdout is appended into the turn context&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;CTX&lt;/span&gt;&lt;span class="sh"&gt;'
[session budget]
- Prefer tools already in the repo; do not install packages unless asked.
- Keep diffs small; one concern per turn.
- If the task needs secrets or spend, stop and ask.
&lt;/span&gt;&lt;span class="no"&gt;CTX
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wire it so Claude Code runs the script on &lt;code&gt;UserPromptSubmit&lt;/code&gt;. Keep the injected text short (a few lines). Long dumps here fight the same context limit you are trying to protect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not put this in CLAUDE.md?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CLAUDE.md&lt;/code&gt; is loaded once and drifts into a novel. A hook stays one focused reminder.&lt;/li&gt;
&lt;li&gt;You can change the budget file without rewriting house rules.&lt;/li&gt;
&lt;li&gt;Pair with a short stack map in &lt;code&gt;CLAUDE.md&lt;/code&gt; (under ~80 lines) and put deny/ask policy in &lt;code&gt;.claude/settings.json&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I keep the hooks, settings, and short house-rules file together in &lt;a href="https://justly-mia-429.rehost.page/" rel="noopener noreferrer"&gt;Vildanden Agent Config&lt;/a&gt;. The free sample is enough to try the pattern.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>devtools</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Put your Claude Code shell allow-list in settings.json, not in the prompt</title>
      <dc:creator>Vildanden</dc:creator>
      <pubDate>Wed, 14 Oct 2026 01:13:31 +0000</pubDate>
      <link>https://dev.to/vildandenai/put-your-claude-code-shell-allow-list-in-settingsjson-not-in-the-prompt-18hc</link>
      <guid>https://dev.to/vildandenai/put-your-claude-code-shell-allow-list-in-settingsjson-not-in-the-prompt-18hc</guid>
      <description>&lt;p&gt;Prompts are suggestions. Settings are rules.&lt;/p&gt;

&lt;p&gt;If you only write "never run dangerous shell commands" in &lt;code&gt;CLAUDE.md&lt;/code&gt;, the model can still try them. Claude Code lets you put an explicit allow / deny list in &lt;code&gt;.claude/settings.json&lt;/code&gt; so the runtime blocks the tool call before it runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Minimal example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Bash(rm -rf *)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Bash(git push --force*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Bash(git reset --hard*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Bash(sudo *)"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ask"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Bash(npm publish*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Bash(gh pr merge*)"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exact matcher syntax can vary by Claude Code version — treat this as the shape, then confirm against your installed docs. The point is: put the policy where the tool layer enforces it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this beats a longer prompt
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A deny in settings fails closed. A sentence in &lt;code&gt;AGENTS.md&lt;/code&gt; is soft.&lt;/li&gt;
&lt;li&gt;You can keep &lt;code&gt;CLAUDE.md&lt;/code&gt; short (house rules + stack map) and still be strict on shell.&lt;/li&gt;
&lt;li&gt;Pair with a &lt;code&gt;PreToolUse&lt;/code&gt; hook for patterns settings cannot express, and a &lt;code&gt;Stop&lt;/code&gt; hook so the agent cannot say "done" while &lt;code&gt;tsc&lt;/code&gt; is red.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I keep the deny list, hooks, and short house-rules file together in &lt;a href="https://justly-mia-429.rehost.page/" rel="noopener noreferrer"&gt;Vildanden Agent Config&lt;/a&gt;. The free sample is enough to try the pattern.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>devtools</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
