<?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: Gabriele Mariotti</title>
    <description>The latest articles on DEV Community by Gabriele Mariotti (@gabriele_mariotti_0596f87).</description>
    <link>https://dev.to/gabriele_mariotti_0596f87</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3874108%2F2f8f27f6-a2d3-4510-9b42-a12134680c2d.jpg</url>
      <title>DEV Community: Gabriele Mariotti</title>
      <link>https://dev.to/gabriele_mariotti_0596f87</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gabriele_mariotti_0596f87"/>
    <language>en</language>
    <item>
      <title>Claude Code hooks: how to protect your prod environments without blocking every command</title>
      <dc:creator>Gabriele Mariotti</dc:creator>
      <pubDate>Fri, 24 Apr 2026 10:50:35 +0000</pubDate>
      <link>https://dev.to/gabriele_mariotti_0596f87/claude-code-hooks-how-to-protect-your-prod-environments-without-blocking-every-command-5b9h</link>
      <guid>https://dev.to/gabriele_mariotti_0596f87/claude-code-hooks-how-to-protect-your-prod-environments-without-blocking-every-command-5b9h</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/gabriele_mariotti_0596f87/guardrails-with-hooks-how-i-protect-aws-production-profiles-in-claude-code-3pbl" class="crayons-story__hidden-navigation-link"&gt;Guardrails with hooks: how I protect AWS production profiles in Claude Code&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/gabriele_mariotti_0596f87" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3874108%2F2f8f27f6-a2d3-4510-9b42-a12134680c2d.jpg" alt="gabriele_mariotti_0596f87 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/gabriele_mariotti_0596f87" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Gabriele Mariotti
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Gabriele Mariotti
                
              
              &lt;div id="story-author-preview-content-3545720" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/gabriele_mariotti_0596f87" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3874108%2F2f8f27f6-a2d3-4510-9b42-a12134680c2d.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Gabriele Mariotti&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/gabriele_mariotti_0596f87/guardrails-with-hooks-how-i-protect-aws-production-profiles-in-claude-code-3pbl" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 24&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/gabriele_mariotti_0596f87/guardrails-with-hooks-how-i-protect-aws-production-profiles-in-claude-code-3pbl" id="article-link-3545720"&gt;
          Guardrails with hooks: how I protect AWS production profiles in Claude Code
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/claude"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;claude&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/aws"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;aws&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/security"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;security&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devops"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devops&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/gabriele_mariotti_0596f87/guardrails-with-hooks-how-i-protect-aws-production-profiles-in-claude-code-3pbl#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              1&lt;span class="hidden s:inline"&gt; comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Guardrails with hooks: how I protect AWS production profiles in Claude Code</title>
      <dc:creator>Gabriele Mariotti</dc:creator>
      <pubDate>Fri, 24 Apr 2026 10:44:11 +0000</pubDate>
      <link>https://dev.to/gabriele_mariotti_0596f87/guardrails-with-hooks-how-i-protect-aws-production-profiles-in-claude-code-3pbl</link>
      <guid>https://dev.to/gabriele_mariotti_0596f87/guardrails-with-hooks-how-i-protect-aws-production-profiles-in-claude-code-3pbl</guid>
      <description>&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;When Claude Code runs a Bash command, it checks permissions before executing. You have two broad options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Approve every AWS command manually&lt;/strong&gt; — safe, but you'll be clicking "Allow" dozens of times a day, even for harmless &lt;code&gt;aws s3 ls&lt;/code&gt; calls on dev buckets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add &lt;code&gt;Bash(aws *)&lt;/code&gt; to the allow list&lt;/strong&gt; — zero friction, but now every production command runs without any confirmation gate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neither is great. You want Claude to move fast on dev and staging, but you need a hard stop before anything touches production.&lt;/p&gt;

&lt;h2&gt;
  
  
  The goal
&lt;/h2&gt;

&lt;p&gt;Allow all AWS CLI commands by default. Force an explicit confirmation only when a command targets a specific production profile. No changes to the daily workflow — prod is the only thing that needs friction.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is &lt;code&gt;settings.json&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;Claude Code reads a &lt;code&gt;settings.json&lt;/code&gt; file (global at &lt;code&gt;~/.claude/settings.json&lt;/code&gt;, or per-project at &lt;code&gt;.claude/settings.json&lt;/code&gt;) that controls permissions, hooks, environment variables, and more. The permissions section lets you define which tool calls are allowed, denied, or always require confirmation.&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(aws *)"&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;This blanket rule tells Claude: run any &lt;code&gt;aws&lt;/code&gt; command without asking. That's the starting point — broad permission, then we layer in selective protection via a hook.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Official docs: &lt;a href="https://docs.anthropic.com/en/docs/claude-code/settings" rel="noopener noreferrer"&gt;Settings &amp;amp; Permissions&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  What is a hook?
&lt;/h3&gt;

&lt;p&gt;Hooks are shell commands that Claude Code fires at specific lifecycle events. The most useful for this case is &lt;code&gt;PreToolUse&lt;/code&gt;: it runs &lt;em&gt;before&lt;/em&gt; Claude executes a tool call, and can influence what happens next.&lt;/p&gt;

&lt;p&gt;Claude passes the tool input as JSON on stdin. Your hook reads it, inspects it, and can return a JSON response that tells Claude to allow, deny, or ask the user for confirmation.&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="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;"if"&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(aws *)"&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/aws-prod-guard.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;Two filters work together here. The outer &lt;code&gt;matcher: "Bash"&lt;/code&gt; selects the tool type. The inner &lt;code&gt;"if": "Bash(aws *)"&lt;/code&gt; is a pre-filter that only invokes the script when the actual command starts with &lt;code&gt;aws&lt;/code&gt; — so Claude doesn't spawn the shell script on every single Bash call (git, npm, make, etc.). Only AWS commands reach the guard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IFRECiAgICBBKFsiQmFzaCBjb21tYW5kIl0pIC0tPiBCeyJhd3MgY29tbWFuZD8ifQogICAgQiAtLSAibm8iIC0tPiBDKFsi4pyFIFRvb2wgY2FsbCBhbGxvd2VkIl0pCiAgICBCIC0tICJ5ZXMiIC0tPiBEWyJhd3MtcHJvZC1ndWFyZC5zaCJdCiAgICBEIC0tICJub24tcHJvZCBwcm9maWxlIiAtLT4gQwogICAgRCAtLSAicHJvZHVjdGlvbiBwcm9maWxlIGRldGVjdGVkIiAtLT4gRXsiVXNlciBwcm9tcHQifQogICAgRSAtLSAiQWxsb3ciIC0tPiBDCiAgICBFIC0tICJEZW55IiAtLT4gRihbIvCfmqsgVG9vbCBjYWxsIGJsb2NrZWQiXSkKCiAgICBzdHlsZSBDIGZpbGw6I2Q0ZWRkYSxzdHJva2U6IzI4YTc0NSxjb2xvcjojMDAwCiAgICBzdHlsZSBGIGZpbGw6I2Y4ZDdkYSxzdHJva2U6I2RjMzU0NSxjb2xvcjojMDAw" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2FZmxvd2NoYXJ0IFRECiAgICBBKFsiQmFzaCBjb21tYW5kIl0pIC0tPiBCeyJhd3MgY29tbWFuZD8ifQogICAgQiAtLSAibm8iIC0tPiBDKFsi4pyFIFRvb2wgY2FsbCBhbGxvd2VkIl0pCiAgICBCIC0tICJ5ZXMiIC0tPiBEWyJhd3MtcHJvZC1ndWFyZC5zaCJdCiAgICBEIC0tICJub24tcHJvZCBwcm9maWxlIiAtLT4gQwogICAgRCAtLSAicHJvZHVjdGlvbiBwcm9maWxlIGRldGVjdGVkIiAtLT4gRXsiVXNlciBwcm9tcHQifQogICAgRSAtLSAiQWxsb3ciIC0tPiBDCiAgICBFIC0tICJEZW55IiAtLT4gRihbIvCfmqsgVG9vbCBjYWxsIGJsb2NrZWQiXSkKCiAgICBzdHlsZSBDIGZpbGw6I2Q0ZWRkYSxzdHJva2U6IzI4YTc0NSxjb2xvcjojMDAwCiAgICBzdHlsZSBGIGZpbGw6I2Y4ZDdkYSxzdHJva2U6I2RjMzU0NSxjb2xvcjojMDAw" alt="Hook resolution flow" width="430" height="728"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Official docs: &lt;a href="https://docs.anthropic.com/en/docs/claude-code/hooks" rel="noopener noreferrer"&gt;Hooks&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  The guard script
&lt;/h3&gt;

&lt;p&gt;The script reads the command Claude is about to run, checks whether it targets a protected profile, and responds accordingly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;~/.claude/hooks/aws-prod-guard.sh&lt;/code&gt;&lt;/strong&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;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# Intercepts Bash tool calls and asks for confirmation when an AWS command&lt;/span&gt;
&lt;span class="c"&gt;# targets a production profile. Edit aws-prod-profiles.json to add/remove profiles.&lt;/span&gt;

&lt;span class="nv"&gt;PROFILES_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/aws-prod-profiles.json"&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PROFILES_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;0

&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;while &lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; entry&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nv"&gt;profile&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;$entry&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;'.profile'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nv"&gt;account&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;$entry&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;'.account'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nv"&gt;description&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;$entry&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;'.description'&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;-qE&lt;/span&gt; &lt;span class="s2"&gt;"(--profile[[:space:]=]+&lt;/span&gt;&lt;span class="nv"&gt;$profile&lt;/span&gt;&lt;span class="s2"&gt;|AWS_PROFILE[[:space:]]*=[[:space:]]*&lt;/span&gt;&lt;span class="nv"&gt;$profile&lt;/span&gt;&lt;span class="s2"&gt;|AWS_DEFAULT_PROFILE[[:space:]]*=[[:space:]]*&lt;/span&gt;&lt;span class="nv"&gt;$profile&lt;/span&gt;&lt;span class="s2"&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;printf&lt;/span&gt; &lt;span class="s1"&gt;'{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"ask","permissionDecisionReason":"Production profile detected: %s — %s (account %s)"}}\n'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$profile&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$description&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$account&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;0
  &lt;span class="k"&gt;fi
done&lt;/span&gt; &amp;lt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;jq &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'.[]'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PROFILES_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;)&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;The key detail: when a production profile is detected, the hook returns &lt;code&gt;permissionDecision: "ask"&lt;/code&gt; — which tells Claude to pause and prompt the user for explicit approval, overriding the blanket &lt;code&gt;allow&lt;/code&gt; rule from &lt;code&gt;settings.json&lt;/code&gt;. If no protected profile is matched, the hook exits 0 with no output and Claude proceeds normally.&lt;/p&gt;




&lt;h3&gt;
  
  
  The profiles file
&lt;/h3&gt;

&lt;p&gt;Protected profiles live in a separate JSON file, so you can add or remove entries without touching the script.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;~/.claude/hooks/aws-prod-profiles.json&lt;/code&gt;&lt;/strong&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"profile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-production"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"account"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"000000000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Main production account"&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;Add as many profiles as you need. The &lt;code&gt;account&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt; fields are included in the confirmation message Claude shows the user, making it clear exactly what is about to be touched.&lt;/p&gt;




&lt;h2&gt;
  
  
  The key insight
&lt;/h2&gt;

&lt;p&gt;The real value of hooks is not blanket blocking — it is &lt;strong&gt;interception at the right boundary&lt;/strong&gt;. You let everything through until it reaches a dangerous environment, then you step in with an &lt;code&gt;ask&lt;/code&gt; (or a hard &lt;code&gt;deny&lt;/code&gt; if you prefer zero tolerance).&lt;/p&gt;

&lt;p&gt;This gives you surgical control: Claude moves freely across dev and staging, but the moment a production profile appears in a command, the hook fires and puts a human back in the loop. The dangerous part gets flagged; everything else stays frictionless.&lt;/p&gt;




&lt;h2&gt;
  
  
  File structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.claude/
├── settings.json          # permissions + hook registration
└── hooks/
    ├── aws-prod-guard.sh  # the guard script (chmod +x)
    └── aws-prod-profiles.json  # list of protected profiles
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;~/.claude/settings.json&lt;/code&gt;&lt;/strong&gt; — registers the hook and grants the broad AWS permission:&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(aws *)"&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="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="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;"if"&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(aws *)"&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/aws-prod-guard.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;&lt;strong&gt;&lt;code&gt;~/.claude/hooks/aws-prod-profiles.json&lt;/code&gt;&lt;/strong&gt; — the only file you need to edit to add or remove protected profiles:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"profile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-production"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"account"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"000000000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Main production account"&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;&lt;strong&gt;&lt;code&gt;~/.claude/hooks/aws-prod-guard.sh&lt;/code&gt;&lt;/strong&gt; — the guard script (see above).&lt;/p&gt;

</description>
      <category>claude</category>
      <category>aws</category>
      <category>security</category>
      <category>devops</category>
    </item>
    <item>
      <title>One repo, multiple AI agents: a tool-agnostic pattern for shared AI guidelines</title>
      <dc:creator>Gabriele Mariotti</dc:creator>
      <pubDate>Sat, 11 Apr 2026 21:02:11 +0000</pubDate>
      <link>https://dev.to/gabriele_mariotti_0596f87/one-repo-multiple-ai-agents-a-tool-agnostic-pattern-for-shared-ai-guidelines-4k82</link>
      <guid>https://dev.to/gabriele_mariotti_0596f87/one-repo-multiple-ai-agents-a-tool-agnostic-pattern-for-shared-ai-guidelines-4k82</guid>
      <description>&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Every AI coding tool has its own way to receive project context:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kiro&lt;/strong&gt; → &lt;code&gt;.kiro/steering/*.md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude Code&lt;/strong&gt; → &lt;code&gt;CLAUDE.md&lt;/code&gt; + &lt;code&gt;.claude/rules/*.md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cursor&lt;/strong&gt; → &lt;code&gt;.cursor/rules/*.md&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your team uses different tools — or if you want to switch without rewriting everything — you have a problem. You either:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Duplicate&lt;/strong&gt; the same rules in every format → they diverge within days&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick one tool&lt;/strong&gt; and lock everyone in → someone is always excluded&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Put rules in README&lt;/strong&gt; and hope agents read it → they don't, reliably&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of these scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern
&lt;/h2&gt;

&lt;p&gt;Apply &lt;strong&gt;separation of concerns&lt;/strong&gt; to AI agent configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-project/
├── ai/                          ← Knowledge (tool-agnostic, in git)
│   ├── README.md
│   └── terraform.md
├── .kiro/steering/              ← Kiro adapter (in git)
│   ├── ai-guidelines.md
│   └── use-terraform.md
├── .kiro/steering/local/        ← Kiro personal overrides (gitignored)
│   └── status.md
├── .claude/rules/               ← Claude adapter (in git)
│   └── tech-use-terraform.md
├── CLAUDE.md                    ← Claude shared instructions (in git)
└── CLAUDE.local.md              ← Claude personal overrides (gitignored)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three layers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;In git?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ai/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;What to do (knowledge)&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;.kiro/steering/&lt;/code&gt;, &lt;code&gt;.claude/rules/&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;How to load it (adapters)&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;local/&lt;/code&gt;, &lt;code&gt;CLAUDE.local.md&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Personal context (overrides)&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The knowledge layer: &lt;code&gt;ai/&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This is the single source of truth. Files here are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tool-agnostic&lt;/strong&gt; — no references to Kiro, Claude, or any specific agent&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human-readable&lt;/strong&gt; — standard markdown, useful even without an AI tool&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain-focused&lt;/strong&gt; — one file per topic (Terraform, security, API design, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example — &lt;code&gt;ai/terraform.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="gh"&gt;# Terraform — Steering rules&lt;/span&gt;

&lt;span class="gu"&gt;## Folder structure&lt;/span&gt;
Each folder is an independent Terraform root module...

&lt;span class="gu"&gt;## Standard files per module&lt;/span&gt;
Every module must contain: main.tf, variables.tf, outputs.tf, versions.tf, README.md...

&lt;span class="gu"&gt;## Security rules&lt;/span&gt;
&lt;span class="gu"&gt;### IAM — least privilege&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Scope resource ARNs to the specific project/environment — never "&lt;span class="err"&gt;*&lt;/span&gt;" unless the API requires it...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No tool-specific syntax. No frontmatter. Just knowledge.&lt;/p&gt;

&lt;h2&gt;
  
  
  The adapter layer
&lt;/h2&gt;

&lt;p&gt;Adapters are minimal files — 3-5 lines — that tell each tool &lt;em&gt;when&lt;/em&gt; and &lt;em&gt;where&lt;/em&gt; to load the knowledge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kiro adapter (&lt;code&gt;.kiro/steering/use-terraform.md&lt;/code&gt;)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;inclusion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fileMatch&lt;/span&gt;
&lt;span class="na"&gt;fileMatchPattern&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;**/*.tf"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;**/*.tfvars"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="c1"&gt;# Terraform rules&lt;/span&gt;

&lt;span class="s"&gt;Read and apply the rules in `ai/terraform.md` for all Terraform-related work.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kiro loads this only when you're working on &lt;code&gt;.tf&lt;/code&gt; files. The actual rules live in &lt;code&gt;ai/terraform.md&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Claude adapter (&lt;code&gt;.claude/rules/tech-use-terraform.md&lt;/code&gt;)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;globs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;**/*.tf"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;**/*.tfvars"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="c1"&gt;# Terraform Rules&lt;/span&gt;

&lt;span class="s"&gt;Read and follow the guidelines in `ai/terraform.md` before doing any Terraform work.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same concept, different syntax. Both point to the same source.&lt;/p&gt;

&lt;h3&gt;
  
  
  Meta-adapter: teaching agents the pattern
&lt;/h3&gt;

&lt;p&gt;One file tells each agent how the system works:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kiro&lt;/strong&gt; (&lt;code&gt;.kiro/steering/ai-guidelines.md&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;inclusion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="c1"&gt;# AI Guidelines Convention&lt;/span&gt;

&lt;span class="s"&gt;Technical guidelines are in `ai/` — tool-agnostic, single source of truth.&lt;/span&gt;

&lt;span class="c1"&gt;## Structure&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="s"&gt;ai/&amp;lt;topic&amp;gt;.md` ← domain knowledge&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="s"&gt;.kiro/steering/` ← Kiro adapters (in git)&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="s"&gt;.kiro/steering/local/` ← personal overrides (gitignored)&lt;/span&gt;

&lt;span class="s"&gt;When updating a guideline, modify only `ai/&amp;lt;topic&amp;gt;.md`.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Claude&lt;/strong&gt; (&lt;code&gt;CLAUDE.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="gh"&gt;# My Project&lt;/span&gt;

&lt;span class="gu"&gt;## AI Guidelines Convention&lt;/span&gt;
Technical guidelines are in &lt;span class="sb"&gt;`ai/`&lt;/span&gt; — tool-agnostic, single source of truth.
Adapters in &lt;span class="sb"&gt;`.kiro/steering/`&lt;/span&gt; (Kiro) and &lt;span class="sb"&gt;`.claude/rules/`&lt;/span&gt; (Claude Code).
Personal overrides: &lt;span class="sb"&gt;`.kiro/steering/local/`&lt;/span&gt; and &lt;span class="sb"&gt;`CLAUDE.local.md`&lt;/span&gt; — not in git.

When updating a guideline, modify only &lt;span class="sb"&gt;`ai/&amp;lt;topic&amp;gt;.md`&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The personal layer
&lt;/h2&gt;

&lt;p&gt;Some context is personal or sensitive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project status and TODOs&lt;/li&gt;
&lt;li&gt;Credentials and environment config&lt;/li&gt;
&lt;li&gt;Personal preferences and workflow notes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This goes in tool-specific locations that are gitignored:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Personal location&lt;/th&gt;
&lt;th&gt;Gitignore rule&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Kiro&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.kiro/steering/local/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.kiro/steering/local/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CLAUDE.local.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CLAUDE.local.md&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;.gitignore&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Kiro
.kiro/*
!.kiro/steering/
.kiro/steering/local/

# Claude
CLAUDE.local.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tracks &lt;code&gt;.kiro/steering/&lt;/code&gt; (adapters) but ignores &lt;code&gt;.kiro/steering/local/&lt;/code&gt; (personal).&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Single source of truth
&lt;/h3&gt;

&lt;p&gt;Change &lt;code&gt;ai/terraform.md&lt;/code&gt; once → every agent picks it up. No drift, no sync issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  No vendor lock-in
&lt;/h3&gt;

&lt;p&gt;Switch from Kiro to Claude? The knowledge stays. Add Cursor tomorrow? Write a 3-line adapter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Team-friendly
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Everyone sees the same rules&lt;/li&gt;
&lt;li&gt;New team member clones the repo → gets all the knowledge immediately&lt;/li&gt;
&lt;li&gt;Personal overrides don't pollute the shared config&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Progressive adoption
&lt;/h3&gt;

&lt;p&gt;Start with one file in &lt;code&gt;ai/&lt;/code&gt;. Add adapters as needed. The pattern scales from 1 file to 50.&lt;/p&gt;

&lt;h3&gt;
  
  
  Human-readable
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ai/&lt;/code&gt; is just markdown. No frontmatter, no tool syntax. A developer without any AI tool can read it and follow the same conventions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding a new domain
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;ai/new-topic.md&lt;/code&gt; with the rules&lt;/li&gt;
&lt;li&gt;Create adapter for each tool:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.kiro/steering/use-new-topic.md&lt;/code&gt; (with appropriate &lt;code&gt;inclusion&lt;/code&gt; mode)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.claude/rules/tech-use-new-topic.md&lt;/code&gt; (with appropriate &lt;code&gt;globs&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Commit all three files&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Time: 2 minutes. The knowledge is written once, loaded everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The insight is simple: &lt;strong&gt;knowledge and configuration are different concerns&lt;/strong&gt;. Knowledge is what your project needs. Configuration is how a specific tool loads it.&lt;/p&gt;

&lt;p&gt;Separate them, and you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One place to maintain rules&lt;/li&gt;
&lt;li&gt;Freedom to use any AI tool&lt;/li&gt;
&lt;li&gt;Clean git history (knowledge changes are meaningful, adapter changes are rare)&lt;/li&gt;
&lt;li&gt;Team alignment without tool alignment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;ai/&lt;/code&gt; folder is your project's brain. The adapters are just plugs.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devtools</category>
      <category>claude</category>
      <category>kiro</category>
    </item>
  </channel>
</rss>
