<?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: Denis Bakhoum</title>
    <description>The latest articles on DEV Community by Denis Bakhoum (@dionysos).</description>
    <link>https://dev.to/dionysos</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%2F236995%2Fdd2789fb-d8b6-4699-b9fc-d3c0b474b68b.jpeg</url>
      <title>DEV Community: Denis Bakhoum</title>
      <link>https://dev.to/dionysos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dionysos"/>
    <language>en</language>
    <item>
      <title>Claude Code stopped using its own tools</title>
      <dc:creator>Denis Bakhoum</dc:creator>
      <pubDate>Thu, 03 Sep 2026 10:00:00 +0000</pubDate>
      <link>https://dev.to/dionysos/claude-code-stopped-using-its-own-tools-3h8g</link>
      <guid>https://dev.to/dionysos/claude-code-stopped-using-its-own-tools-3h8g</guid>
      <description>&lt;p&gt;A week ago I installed the TypeScript LSP plugin for Claude Code. The pitch sold me. The agent works the way I do in an editor, navigating with go-to-definition and find-references instead of grepping around, and catching type errors as it writes instead of at the end of a task. I watched it work in that session and forgot about it.&lt;/p&gt;

&lt;p&gt;A week later I went back to check what it had bought me. Nine calls, all inside the session where I tested it, on August 25. Zero across the twenty-seven sessions since.&lt;/p&gt;

&lt;p&gt;That was annoying enough to go digging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Everything moved to Bash
&lt;/h2&gt;

&lt;p&gt;I pulled every session transcript from &lt;code&gt;~/.claude/projects&lt;/code&gt; for one repo, a large Next.js app I work in daily. 76 sessions, 8,343 tool calls, all on Opus 5, July 31 to September 1.&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffo96q6lsc882mlw9wnl1.png" 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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffo96q6lsc882mlw9wnl1.png" alt="Share of tool calls going to Bash vs. built-in file tools, by week. Bash rises from 46.3% in the week of July 31 to 84.2% by September 1, while Read, Edit, Grep, Glob and Write together fall from 37.6% to 7.2%." width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Across the whole period Bash took 70% of all tool calls. Over the last two weeks, 84%, while the built-in file tools fell to 7%.&lt;br&gt;
(&lt;code&gt;defaultMode: "auto"&lt;/code&gt; the whole window, so that didn't change.)&lt;/p&gt;
&lt;h2&gt;
  
  
  grep 1,281, Grep 0
&lt;/h2&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh1q46vt9ds3arylot35f.png" 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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh1q46vt9ds3arylot35f.png" alt="For each job, how often Claude reached for the shell versus the built-in tool. Searching the codebase went to grep or rg 1,281 times and to the Grep tool 0 times. Reading part of a file went to cat, sed -n or head 1,111 times and to Read 665 times. Finding files by name went to find or ls 317 times and to Glob 0 times. Rewriting a file went to python3 or perl 325 times and to Edit or Write 1,141 times." width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Grep&lt;/code&gt; and &lt;code&gt;Glob&lt;/code&gt; were called zero times in 8,343 tool calls. &lt;code&gt;grep&lt;/code&gt; ran 1,165 times through Bash and &lt;code&gt;rg&lt;/code&gt; another 116.&lt;/p&gt;

&lt;p&gt;Here's one from my transcripts, reading a file:&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;sed&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 269,352p src/domains/billing/server/database/read.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This one ran three times in a row across different files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;perl &lt;span class="nt"&gt;-pi&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'s{\bvendorContracts\b}{importedContracts}g'&lt;/span&gt; previewVendorContractsSyncFunction.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;perl -pi&lt;/code&gt; to rename a symbol. In a repo where the LSP plugin with&lt;br&gt;
find-references was installed and enabled. I stared at that one for a while, wondering if some phrasing of mine had nudged it toward the shell. No idea. There were 325 &lt;code&gt;python3&lt;/code&gt; and &lt;code&gt;perl&lt;/code&gt; rewrites doing what &lt;code&gt;Edit&lt;/code&gt; does natively.&lt;/p&gt;

&lt;p&gt;When Claude actually modified a file it mostly used &lt;code&gt;Edit&lt;/code&gt; and &lt;code&gt;Write&lt;/code&gt;. The swaps happen when it reads and searches.&lt;/p&gt;
&lt;h2&gt;
  
  
  Where my permission rules went
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://code.claude.com/docs/en/permissions#read-only-commands" rel="noopener noreferrer"&gt;permissions docs&lt;/a&gt; explain a big chunk of it. A fixed set of Bash commands runs with no permission prompt in every mode:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;These include &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;head&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;find&lt;/code&gt;, and read-only forms of&lt;br&gt;
&lt;code&gt;git&lt;/code&gt;. The set is not configurable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every shell command it reached for instead of a built-in is on that list. 22%of my 5,837 Bash calls used nothing but commands from that list, 31% counting &lt;code&gt;git&lt;/code&gt;. None of them ever prompted.&lt;/p&gt;

&lt;p&gt;Two of the rules in my deny list:&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="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;"Bash(rm -rf:*)"&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;Here is a command from my own transcripts, August 11:&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="nv"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-m1&lt;/span&gt; &lt;span class="s1"&gt;'^DATABASE_URL'&lt;/span&gt; .env | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/^DATABASE_URL=//; s/^"//; s/"$//'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; psql &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DB&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'select u.email, um."organizationId", o.name, um.role from "User" u ...'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Read(**/.env)&lt;/code&gt; is denied, but that call is not a &lt;code&gt;Read&lt;/code&gt;. It is a &lt;code&gt;grep&lt;/code&gt;, on the prompt-free list, so it never asked.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the changelog says
&lt;/h2&gt;

&lt;p&gt;The v2.1.116 changelog says Glob and Grep are deliberately removed on native macOS and Linux builds, "replaced by embedded &lt;code&gt;bfs&lt;/code&gt; and &lt;code&gt;ugrep&lt;/code&gt; available through the Bash tool — faster searches without a separate tool round-trip." On my machine, &lt;code&gt;which bfs ugrep&lt;/code&gt; finds neither. The tools reference still lists &lt;code&gt;Grep&lt;/code&gt; and &lt;code&gt;Glob&lt;/code&gt;. The native build ships neither them nor the replacements.&lt;/p&gt;

&lt;p&gt;I don't know whether that is deliberate or a build regression nobody caught.&lt;br&gt;
There are open issues either way.&lt;a href="https://github.com/anthropics/claude-code/issues/64136" rel="noopener noreferrer"&gt;#64136&lt;/a&gt; ties the missing tools to Bash storms and fabricated file paths.&lt;br&gt;
&lt;a href="https://github.com/anthropics/claude-code/issues/52121" rel="noopener noreferrer"&gt;#52121&lt;/a&gt; describes my exact setup, and calls it "particularly problematic for systems where bash grep/find are restricted by permission policies, as there's no alternative code-search path." And &lt;a href="https://github.com/anthropics/claude-code/issues/80267" rel="noopener noreferrer"&gt;#80267&lt;/a&gt;, labelled&lt;br&gt;
&lt;code&gt;reproduced&lt;/code&gt; by maintainers, treats shell-based file editing as normal: diagnostics go stale "because Claude Code likes to use &lt;code&gt;sed&lt;/code&gt;, &lt;code&gt;python&lt;/code&gt;, and similar tools to edit files in place".&lt;/p&gt;

&lt;h2&gt;
  
  
  What I tried
&lt;/h2&gt;

&lt;p&gt;An undocumented env var helped a little (&lt;code&gt;CLAUDE_CODE_THRIFTY_SONIC=false&lt;/code&gt;, mentioned in one of those issues, documented nowhere). &lt;code&gt;Read&lt;/code&gt; and &lt;code&gt;Edit&lt;/code&gt; came back, &lt;code&gt;grep&lt;/code&gt; still won. So I wrote a &lt;code&gt;PreToolUse&lt;/code&gt; hook that denies Bash for&lt;br&gt;
anything a built-in tool does better.&lt;/p&gt;

&lt;p&gt;Blocking &lt;code&gt;grep&lt;/code&gt; did not make Claude reach for &lt;code&gt;Grep&lt;/code&gt;. It reached for &lt;code&gt;git grep&lt;/code&gt;, then &lt;code&gt;git ls-files&lt;/code&gt;, and I had to close those specifically. With those closed, it finally uses the right tools. It costs a few calls at the start of every session while the model works out what's blocked.&lt;/p&gt;

&lt;p&gt;A hook that blocks &lt;code&gt;grep&lt;/code&gt; and &lt;code&gt;find&lt;/code&gt; leaves no search path at all. So the current setup allows &lt;code&gt;rg&lt;/code&gt;, &lt;code&gt;fd&lt;/code&gt;, &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt; and &lt;code&gt;find&lt;/code&gt; through and keeps denying the rest.&lt;/p&gt;

&lt;p&gt;The hook and the scripts are at &lt;a href="https://github.com/Dionysos5/claude-code-tool-mix" rel="noopener noreferrer"&gt;Dionysos5/claude-code-tool-mix&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part I can't get past
&lt;/h2&gt;

&lt;p&gt;Nothing in my settings changed. I only found out because a plugin got zero calls.&lt;/p&gt;

&lt;p&gt;The deny list is still sitting in my settings and I couldn't tell you what else it doesn't cover. Permission rules bind to tool names, and the harness picks the tool. Am I supposed to write a rule for every shell equivalent of every built-in, and keep them current against a build that changes weekly? That's roughly what my hook is now, and I don't think it should be my job.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>security</category>
      <category>devtools</category>
    </item>
    <item>
      <title>How Do You Actually Know If AI Is Working On Your Team?</title>
      <dc:creator>Denis Bakhoum</dc:creator>
      <pubDate>Fri, 27 Feb 2026 12:24:36 +0000</pubDate>
      <link>https://dev.to/dionysos/how-do-you-actually-know-if-ai-is-working-on-your-team-2b02</link>
      <guid>https://dev.to/dionysos/how-do-you-actually-know-if-ai-is-working-on-your-team-2b02</guid>
      <description>&lt;p&gt;A few months ago I started leading a team to explore AI and how it can improve developer experience and productivity at my company. I ran weekly meetings, tried experiments with my team, and after a few weeks I had a problem: I couldn't say for sure that AI was making us more productive or by how much.&lt;/p&gt;

&lt;p&gt;Engineers were giving mixed signals. Some were excited. Others said AI felt hit or miss — it would nail something obvious, then fall flat on anything touching our codebase conventions, and they'd spend more time correcting it than writing the code themselves. We wanted to show management that the investment was worth it but we had no good metric.&lt;/p&gt;

&lt;h2&gt;
  
  
  What everyone else is measuring
&lt;/h2&gt;

&lt;p&gt;You've probably seen headlines like "At Company X, all of our code is written by AI" or "AI made our engineers 50% more productive." They rarely explain what that means or how they measured it.&lt;/p&gt;

&lt;p&gt;Tool vendors measure lines of code generated and acceptance rate. An engineer can accept every suggestion and throw it all away, so these numbers tell you almost nothing about actual output quality. Productivity percentage sounds, but it's hard to measure varies across developers and even for the same person on similar tasks. It's not reproducible, and it doesn't tell you where to invest to get better.&lt;/p&gt;

&lt;h2&gt;
  
  
  A better question
&lt;/h2&gt;

&lt;p&gt;Instead of measuring speed, I started asking something more concrete: across a feature's lifecycle, in how many areas can AI reliably carry the work?&lt;/p&gt;

&lt;p&gt;Building a feature involves a lot of distinct areas: understanding requirements, system design, front-end components, back-end logic, tests, deployment. For each one, the question is simple: is this covered?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Covered&lt;/strong&gt; — a workflow exists, validated against your codebase's real patterns, that at least two people on the team have used successfully. The developer reviews the output, makes minor adjustments, and ships.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Partial&lt;/strong&gt; — the AI helps but can't carry the task alone. Something is documented but the workflow isn't complete, or only one person has validated it. Useful, but closer to pair programming than delegation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uncovered&lt;/strong&gt; — the AI goes in blind, drawing on general training knowledge with no grounding in your specific codebase, it might read your code extensively before starting or it might not. More often the developer ends up steering constantly, like explaining a task to an intern rather than just doing it themselves.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this framework, new areas start as Partial: one person documents and tests a workflow. When a second person can use it without tweaking, it gets promoted to Covered. Criteria can be adjusted, and over time you can layer in observability to make promotions more data-driven. &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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxh4x7889ummjnsm93hu6.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxh4x7889ummjnsm93hu6.png" alt="AI Functional Coverage Map" width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Coverage is infrastructure, not intuition
&lt;/h2&gt;

&lt;p&gt;The reason this metric holds up where productivity percentages don't is that coverage describes your team's system, not a feeling about AI's general capability.&lt;/p&gt;

&lt;p&gt;When I say forms are covered on my team, I mean a specific workflow exists that clarifies requirements, delegates to a subagent following our codebase's exact patterns, then runs a second subagent that validates the output against a checklist and corrects mistakes. Two developers with no particular prompting experience can create a form and get consistent, good results — not because AI is magically good at forms, but because the workflow is documented and the standards are encoded.&lt;/p&gt;

&lt;p&gt;If an area is partial or uncovered today, the path forward is clear: document the patterns, build the workflow, get teammates to validate it through real usage. No need to wait for smarter models.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three areas from our codebase
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Forms (Covered).&lt;/strong&gt; A dedicated skill, a subagent trained on our patterns, and a review subagent that catches and fixes problems. Multiple people have used it on production forms. The developer reviews the output and ships.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scheduled tasks (Partial).&lt;/strong&gt; Patterns are documented and the AI has something to work from, but there's no complete workflow and only one person has validated it in practice. It helps, but the developer still carries a meaningful share.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bug investigation (Uncovered).&lt;/strong&gt; Debugging well means having a method: form a hypothesis, write a failing test to confirm it, trace data. Experienced developers do this intuitively. AI tries things and you end up evaluating random attempts rather than narrowing down. Most people on my team stopped reaching for AI here and just debugged themselves — which is the kind of signal a coverage map is designed to surface.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you can do with it
&lt;/h2&gt;

&lt;p&gt;A coverage map lets you route work deliberately. Covered areas get delegated. Uncovered areas stop wasting people's time. And when someone asks where to invest, you have a specific answer — not "we need a better model" but "we need to build the workflow for this area."&lt;br&gt;
When making the case for AI adoption, it's the difference between "I think it's working" and being able to show exactly where it's working, where it isn't, and what the team is doing about it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>engineering</category>
      <category>productivity</category>
      <category>dx</category>
    </item>
  </channel>
</rss>
