<?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: Masa Hebi</title>
    <description>The latest articles on DEV Community by Masa Hebi (@masahito_hebi).</description>
    <link>https://dev.to/masahito_hebi</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%2F4013340%2F9c3e9d83-0503-4a0c-ba91-6fd0b75b8fad.png</url>
      <title>DEV Community: Masa Hebi</title>
      <link>https://dev.to/masahito_hebi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/masahito_hebi"/>
    <language>en</language>
    <item>
      <title>Your AI coding agent will eventually run rm -rf — so I built a fuse for it</title>
      <dc:creator>Masa Hebi</dc:creator>
      <pubDate>Sat, 04 Jul 2026 12:18:06 +0000</pubDate>
      <link>https://dev.to/masahito_hebi/your-ai-coding-agent-will-eventually-run-rm-rf-so-i-built-a-fuse-for-it-24h0</link>
      <guid>https://dev.to/masahito_hebi/your-ai-coding-agent-will-eventually-run-rm-rf-so-i-built-a-fuse-for-it-24h0</guid>
      <description>&lt;p&gt;AI coding agents are great until the moment they aren't.&lt;/p&gt;

&lt;p&gt;They don't just write text — they run real commands in your terminal, with your permissions. Most of the time that's the whole point of using one. But every so often an agent hits an error, decides the fix is to "clean things up," and runs something like:&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="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No malice, it genuinely thinks it's helping. That's actually what makes it dangerous: a human would freeze the second they realized "wait, that's the prod folder," but the agent just keeps going.&lt;/p&gt;

&lt;p&gt;I got tired of babysitting mine, so I ended up building a fuse for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Telling it to "be careful" doesn't work
&lt;/h2&gt;

&lt;p&gt;The obvious first move is to tell the agent to behave: &lt;em&gt;"Never run destructive commands."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But that's just a request, not a control. The model forgets it halfway through a task, and honestly, if it could reliably tell what counts as destructive in context, you wouldn't need the rule at all. What you actually need is something that doesn't rely on the agent's judgment, or its mood that day.&lt;/p&gt;

&lt;h2&gt;
  
  
  A hook that checks the command before it runs
&lt;/h2&gt;

&lt;p&gt;Claude Code has a &lt;a href="https://code.claude.com/docs/en/hooks" rel="noopener noreferrer"&gt;&lt;code&gt;PreToolUse&lt;/code&gt; hook&lt;/a&gt; that fires before a tool call actually executes, and it can block that call. That's really the whole trick.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;agent-fuse&lt;/code&gt; is a small script wired into that hook. Before your agent runs any shell command, the fuse looks at the command text and returns one of three decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;deny&lt;/code&gt;&lt;/strong&gt; — irreversible damage, blocked outright&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ask&lt;/code&gt;&lt;/strong&gt; — risky but sometimes intended, so it pauses for a human&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;allow&lt;/code&gt;&lt;/strong&gt; — normal work, passes straight through&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It talks to Claude Code using its JSON protocol. Input on stdin looks like:&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;"tool_name"&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;"tool_input"&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;"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;"rm -rf /"&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;And the output:&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;"hookSpecificOutput"&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;"hookEventName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PreToolUse"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"permissionDecision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"permissionDecisionReason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[agent-fuse:rm-rf-root-or-home] rm -rf targeting / , ~ , $HOME or a top-level path."&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 rules themselves are just JSON: a pattern, a severity, and a message.&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gcloud-delete-infra"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"severity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"block"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"pattern"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gcloud&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;s+(sql&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;s+instances&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;s+delete|firestore&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;s+databases&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;s+delete|run&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;s+services&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;s+delete|projects&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;s+delete|secrets&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;s+delete)&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Deleting managed cloud infrastructure. Almost always irreversible."&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 default set covers the usual footguns: &lt;code&gt;rm -rf&lt;/code&gt; on &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;~&lt;/code&gt;, or &lt;code&gt;$HOME&lt;/code&gt;; &lt;code&gt;DROP&lt;/code&gt;/&lt;code&gt;TRUNCATE&lt;/code&gt;; &lt;code&gt;DELETE&lt;/code&gt;/&lt;code&gt;UPDATE&lt;/code&gt; with no &lt;code&gt;WHERE&lt;/code&gt;; &lt;code&gt;git push --force&lt;/code&gt; to &lt;code&gt;main&lt;/code&gt;; &lt;code&gt;terraform destroy&lt;/code&gt;; &lt;code&gt;gcloud … delete&lt;/code&gt;; recursive bucket deletes; &lt;code&gt;dd of=/dev/…&lt;/code&gt;; &lt;code&gt;mkfs&lt;/code&gt;; &lt;code&gt;curl … | bash&lt;/code&gt;. You can add your own by pointing &lt;code&gt;AGENT_FUSE_RULES&lt;/code&gt; at a file.&lt;/p&gt;

&lt;p&gt;It judges the command itself, not how confident the agent sounds, so it doesn't matter how sure the agent is that this time it's fine.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part I'd rather admit up front
&lt;/h2&gt;

&lt;p&gt;You're a developer, you'd spot this in five seconds anyway, so I'll just say it directly: this matches command text with regex. It's not a shell parser.&lt;/p&gt;

&lt;p&gt;Which means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;echo "DROP TABLE"&lt;/code&gt; trips the SQL rule (a false positive).&lt;/li&gt;
&lt;li&gt;a deliberately obfuscated command — &lt;code&gt;r""m -rf&lt;/code&gt;, or something base64-decoded and built up through variables — can slip past it (a false negative).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What it does stop is the far more common problem: an agent acting in good faith that runs a plainly-written destructive command. Think of it as a seatbelt, not armor plating, and it's no substitute for backups. If you're worried about a determined adversary, this isn't the tool for that. If you're worried about your agent enthusiastically deleting something at 2am, it is.&lt;/p&gt;

&lt;p&gt;Right now it also only hooks Claude Code's &lt;code&gt;Bash&lt;/code&gt; tool specifically. Cursor/Codex support and file-write coverage are next on the list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build it yourself, or just grab mine
&lt;/h2&gt;

&lt;p&gt;You can absolutely build this yourself, the hook part isn't hard.&lt;/p&gt;

&lt;p&gt;What takes actual time is the rest of it: sitting down to list out every destructive pattern you can think of, deciding block vs. ask for each one, testing that you haven't broken normal usage, and writing an installer that backs up existing settings and can be run more than once safely. That's basically the afternoon I spent on this.&lt;/p&gt;

&lt;p&gt;The code itself is open to read, one Python file, no dependencies, so you can check the "no network calls" claim yourself. I also sell a packaged, curated, kept-updated version for &lt;strong&gt;$8&lt;/strong&gt;: &lt;a href="https://hebiishi.gumroad.com/l/vxidol" rel="noopener noreferrer"&gt;agent-fuse on Gumroad&lt;/a&gt;. If you'd rather just take the idea and build your own version, that's a perfectly good outcome too.&lt;/p&gt;

&lt;p&gt;Either way, put something between your agent and the commands you can't undo. Giving an autonomous process root access on your machine probably deserves at least as much safety as we give a household circuit breaker.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Do you already guard your agents somehow, allowlists, sandboxes, a devcontainer? Curious what's actually working for people, drop it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devtools</category>
      <category>cli</category>
      <category>security</category>
    </item>
  </channel>
</rss>
