<?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: Zhengxin</title>
    <description>The latest articles on DEV Community by Zhengxin (@_94be737e156beb4d74df2).</description>
    <link>https://dev.to/_94be737e156beb4d74df2</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%2F4043494%2F624f59c0-0fbb-4fb6-a54b-92fb2d93c548.jpg</url>
      <title>DEV Community: Zhengxin</title>
      <link>https://dev.to/_94be737e156beb4d74df2</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/_94be737e156beb4d74df2"/>
    <language>en</language>
    <item>
      <title>Claude Code Tools Deep Dive (4): Grep + Glob</title>
      <dc:creator>Zhengxin</dc:creator>
      <pubDate>Tue, 04 Aug 2026 14:26:28 +0000</pubDate>
      <link>https://dev.to/_94be737e156beb4d74df2/claude-code-tools-deep-dive-4-grep-glob-3fh4</link>
      <guid>https://dev.to/_94be737e156beb4d74df2/claude-code-tools-deep-dive-4-grep-glob-3fh4</guid>
      <description>&lt;p&gt;This is the fourth article in my series on Claude Code tools. The first three covered the “interaction primitive trio”: AskUserQuestion, EnterPlanMode, and ExitPlanMode. Together, those tools solve one problem: &lt;strong&gt;how the AI and the user align with each other&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Starting with this article, we enter the world of &lt;strong&gt;execution primitives&lt;/strong&gt;—how Claude turns an agreed-upon plan into actual code changes. But before it can read, edit, or write anything, it first needs to &lt;strong&gt;know where to look&lt;/strong&gt;. That makes the first execution primitives worth examining the &lt;strong&gt;search duo&lt;/strong&gt;: Glob finds by path; Grep finds by content.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This series begins with a prerequisite article explaining what tools are and how Claude uses them. Like the other articles, this one follows the four-layer framework introduced there.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Grep + Glob
&lt;/h2&gt;

&lt;p&gt;When Claude enters a new project, it does not know the file paths. Questions such as “Where is the authentication code?”, “Which files use &lt;code&gt;useState&lt;/code&gt;?”, and “Which files changed recently?” are impossible to answer reliably without search tools. Claude would otherwise have to guess from its training data—which is unreliable—or ask the user to list files manually—which is tedious.&lt;/p&gt;

&lt;p&gt;Claude Code provides two complementary search tools: &lt;strong&gt;Glob searches by path; Grep searches by content&lt;/strong&gt;. I am covering them together because their roles are tightly coupled, they are frequently used in combination, and treating them separately would create a lot of repetition.&lt;/p&gt;

&lt;p&gt;They share one central philosophy: &lt;strong&gt;perceive on demand, and send only what Claude truly needs into the context window&lt;/strong&gt;. They are also the prerequisites for the next three file-operation primitives: Read, Edit, and Write.&lt;/p&gt;

&lt;h3&gt;
  
  
  What they do
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Glob&lt;/strong&gt; finds files using a &lt;strong&gt;path pattern&lt;/strong&gt;. It accepts a shell glob such as &lt;code&gt;**/*.ts&lt;/code&gt; or &lt;code&gt;src/**/api-*.js&lt;/code&gt;, then returns matching file paths sorted by modification time in descending order.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Grep&lt;/strong&gt; finds &lt;strong&gt;files or lines by content&lt;/strong&gt;. It is powered by ripgrep, accepts a regular expression, and can return matching file paths, matching lines, or match counts, depending on the selected output mode.&lt;/p&gt;

&lt;p&gt;Together, they solve the core problem of helping Claude &lt;strong&gt;locate the files it needs inside a large codebase&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;No need to read the entire project&lt;/strong&gt;—locate relevant files first, then use Read, saving context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No need to guess where files are&lt;/strong&gt;—search exposes the truth on disk rather than relying on training-time assumptions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No need to construct Bash commands&lt;/strong&gt;—dedicated tools avoid shell escaping, path dependencies, and permission issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controllable output&lt;/strong&gt;—Grep in particular offers three output modes so Claude can request only the level of detail it needs.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  A concrete example
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; The user says, &lt;strong&gt;“Help me understand how the auth code is organized. I want to refactor it.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Claude has no idea where the auth code lives. It could be under &lt;code&gt;src/auth/&lt;/code&gt;, &lt;code&gt;server/middleware/&lt;/code&gt;, or &lt;code&gt;lib/security/&lt;/code&gt;, or scattered inside files such as &lt;code&gt;pages/api/login.ts&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  The bad alternative: Read alone
&lt;/h4&gt;

&lt;p&gt;Without search tools, Claude would have only a few poor options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Guess from training-time patterns&lt;/strong&gt;—“Auth middleware in a Node.js project is probably at &lt;code&gt;src/middleware/auth.js&lt;/code&gt;.” It tries to read the file and discovers that it does not exist.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask the user to list files&lt;/strong&gt;—“Can you tell me the paths of all auth-related files?” The user has to do tedious manual work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read the entire &lt;code&gt;src/&lt;/code&gt; directory&lt;/strong&gt;—a medium-sized project may contain 200 files and hundreds of thousands of tokens, overwhelming the context window.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The core problem is simple: without search, Claude &lt;strong&gt;cannot see the shape of the codebase&lt;/strong&gt;. It must rely on indirect information or brute-force reading.&lt;/p&gt;

&lt;h4&gt;
  
  
  How Grep + Glob solve it
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Use Glob to sketch the file landscape&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Claude calls Glob with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pattern&lt;/code&gt;: &lt;code&gt;**/*{auth,login,session,jwt}*&lt;/code&gt; (matching paths or filenames containing those keywords)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/auth/middleware.ts    (2h ago)
src/auth/routes.ts        (2h ago)
src/lib/session-store.ts  (3d ago)
src/pages/api/login.ts    (1w ago)
tests/auth.test.ts        (2h ago)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The results are ordered by modification time, so &lt;strong&gt;recently modified files appear first&lt;/strong&gt;. Those files are often where the active work is happening.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Use Grep to investigate specific calls&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Claude now wants to know where &lt;code&gt;jwt.verify&lt;/code&gt; is used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pattern&lt;/code&gt;: &lt;code&gt;jwt\.verify&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;output_mode&lt;/code&gt;: &lt;code&gt;content&lt;/code&gt; (return matching lines, file paths, and line numbers)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-C&lt;/code&gt;: &lt;code&gt;2&lt;/code&gt; (include two lines of context before and after each match)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;type&lt;/code&gt;: &lt;code&gt;ts&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/auth/middleware.ts:8:      const decoded = jwt.verify(token, process.env.JWT_SECRET);
src/auth/middleware.ts:9:      req.user = decoded;
--
src/services/api-client.ts:42:  return jwt.verify(token, PUBLIC_KEY);
--
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Every result is a precise coordinate that Claude can immediately pass to Read or Edit.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Combine modes according to the question&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If Claude only wants to know &lt;strong&gt;how many files use &lt;code&gt;jwt.verify&lt;/code&gt;&lt;/strong&gt;, rather than the exact locations, it can use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pattern&lt;/code&gt;: &lt;code&gt;jwt\.verify&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;output_mode&lt;/code&gt;: &lt;code&gt;count&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result might be &lt;code&gt;4 files&lt;/code&gt;. This call uses only a few dozen tokens because it does not pull every matching line into the context window.&lt;/p&gt;

&lt;p&gt;If it only wants to know &lt;strong&gt;which files contain the call&lt;/strong&gt;, without seeing the lines themselves, it can use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pattern&lt;/code&gt;: &lt;code&gt;jwt\.verify&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;output_mode&lt;/code&gt;: &lt;code&gt;files_with_matches&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is simply a list of file paths.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key insight:&lt;/strong&gt; Grep’s three output modes—&lt;strong&gt;content, files_with_matches, and count&lt;/strong&gt;—let Claude choose the right precision on demand. It can fetch matching lines for deep investigation, paths for narrowing the scope, or a count for estimating impact.&lt;/p&gt;

&lt;h3&gt;
  
  
  When they are triggered
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Use Glob when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Searching by filename or path&lt;/strong&gt;—“all &lt;code&gt;.tsx&lt;/code&gt; files,” “everything under &lt;code&gt;src/api/&lt;/code&gt;,” or “where are the tests?”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Looking for recently modified files&lt;/strong&gt;—Glob sorts results by modification time in descending order.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Narrowing the scope before Grep&lt;/strong&gt;—first identify relevant files, then search their contents.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use Grep when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Searching files or lines by content&lt;/strong&gt;—“where is &lt;code&gt;useEffect&lt;/code&gt; used?” or “where is &lt;code&gt;UserBadge&lt;/code&gt; defined?”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Investigating API usage&lt;/strong&gt;—“every place that calls &lt;code&gt;db.query&lt;/code&gt;.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tracing an error message&lt;/strong&gt;—when a user supplies an error, search the codebase for the place that may throw it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use both when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Locating a module in a large codebase&lt;/strong&gt;—first Glob for &lt;code&gt;**/*auth*&lt;/code&gt;, then Grep for a specific call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restricting by language or file type&lt;/strong&gt;—if you only need to search &lt;code&gt;.ts&lt;/code&gt; files, Grep’s &lt;code&gt;type: "ts"&lt;/code&gt; can do that directly without a preceding Glob call.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Do not use them when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You already know the exact path&lt;/strong&gt;—use Read directly instead of taking a detour through Grep or Glob.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You merely need to list a directory&lt;/strong&gt;—use &lt;code&gt;ls&lt;/code&gt;; Glob matches patterns rather than browsing directories.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You need fuzzy semantic search&lt;/strong&gt;—for a request such as “find all code that performs authentication,” Grep can only perform literal or regex matching. It does not understand semantics; an Agent should investigate instead.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Technical design
&lt;/h3&gt;

&lt;p&gt;Grep and Glob are &lt;strong&gt;sibling tools&lt;/strong&gt;. Their responsibilities are distinct, but their design philosophies are shared. Let us examine each through the four layers, then compare their symmetry.&lt;/p&gt;




&lt;h2&gt;
  
  
  Glob
&lt;/h2&gt;

&lt;h4&gt;
  
  
  1. Naming
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;Glob&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The name comes directly from the convention used by shells and Python’s glob library. “Glob” is the standard term for finding files with path patterns. The fields &lt;code&gt;pattern&lt;/code&gt; and &lt;code&gt;path&lt;/code&gt; are immediately intuitive to anyone familiar with a shell.&lt;/p&gt;

&lt;p&gt;Calling it &lt;code&gt;FindByPath&lt;/code&gt; or &lt;code&gt;SearchFiles&lt;/code&gt; would actually weaken its central promise: &lt;strong&gt;the input uses glob syntax, not regular expressions&lt;/strong&gt;. The name itself signals the syntax.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Tool-level description
&lt;/h4&gt;

&lt;p&gt;Glob’s description is extremely short—only five bullet points—centered on two concerns: &lt;strong&gt;usage constraints and delegation at the boundary&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The pattern uses glob syntax, not regex&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Supports glob patterns like &lt;code&gt;**/*.js&lt;/code&gt; or &lt;code&gt;src/**/*.ts&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It provides two examples and no regex examples. This is &lt;strong&gt;demonstration instead of prohibition&lt;/strong&gt;. Rather than saying “do not use regex,” it shows Claude canonical glob shapes such as &lt;code&gt;**/*.js&lt;/code&gt;, preventing it from passing something like &lt;code&gt;.*\.ts&lt;/code&gt; as the pattern.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Results are sorted by modification time&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Returns matching file paths sorted by modification time&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This declares a total ordering for the output. It gives Claude a useful intuition: &lt;strong&gt;the first file returned by Glob is the most recently modified&lt;/strong&gt;. For questions such as “where is the project’s active work?” or “which module was just refactored?”, inspecting the first few results may be enough.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The explicit purpose is filename search&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use this tool when you need to find files by name patterns&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Grep also has a &lt;code&gt;glob&lt;/code&gt; field, but that field is a &lt;strong&gt;filter&lt;/strong&gt;, not a search operation. Glob treats the filename as the primary search target.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open-ended searches are delegated to Agent&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When you are doing an open-ended search that may require multiple rounds of globbing and grepping, use the Agent tool instead&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the most interesting part: &lt;strong&gt;the tool explicitly acknowledges its own boundary&lt;/strong&gt;. If a task needs repeated cycles of Glob and Grep—for example, “find which module a recent change broke”—the description tells Claude to switch to Agent rather than forcing the task into a single Glob call.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Field-level descriptions
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pattern&lt;/code&gt;—a shell glob expression such as &lt;code&gt;**/*.js&lt;/code&gt; or &lt;code&gt;src/**/*.{ts,tsx}&lt;/code&gt;, not a regular expression.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;path&lt;/code&gt;—an optional search directory; defaults to the current working directory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The field set is minimal. The modification-time ordering is a subtle but valuable design choice. When developers want to know which area is currently active, their instinct is often to run &lt;code&gt;ls -lt&lt;/code&gt;. Glob effectively provides the same signal by default: &lt;strong&gt;cold code sinks, hot code rises&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Schema validation
&lt;/h4&gt;

&lt;p&gt;The schema is &lt;strong&gt;minimal&lt;/strong&gt;. Only &lt;code&gt;pattern&lt;/code&gt; is required; &lt;code&gt;path&lt;/code&gt; is optional, and there are no additional numeric constraints.&lt;/p&gt;

&lt;p&gt;Almost all of Glob’s behavioral signals live in its &lt;strong&gt;name and tool description&lt;/strong&gt;. The schema adds little restriction because glob syntax is already narrow enough.&lt;/p&gt;




&lt;h2&gt;
  
  
  Grep
&lt;/h2&gt;

&lt;h4&gt;
  
  
  1. Naming
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;Grep&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This name also borrows an industry convention. In the Unix world, “grep” universally means “match by content.” Under the hood, however, the tool uses &lt;strong&gt;ripgrep&lt;/strong&gt; (&lt;code&gt;rg&lt;/code&gt;) rather than traditional grep. The familiar name reduces cognitive load while the implementation uses a faster engine.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Tool-level description
&lt;/h4&gt;

&lt;p&gt;Grep’s description is one level more detailed than Glob’s: seven bullet points plus a declaration, centered on four concerns—&lt;strong&gt;locking in correct usage, explaining syntax, exposing filter dimensions, and delegating at the boundary&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ALWAYS + NEVER: locking usage from both directions&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ALWAYS use Grep for search tasks. NEVER invoke &lt;code&gt;grep&lt;/code&gt; or &lt;code&gt;rg&lt;/code&gt; as a Bash command. The Grep tool has been optimized for correct permissions and access.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the strongest sentence in the entire description. “ALWAYS” and “NEVER” constrain behavior from both directions: it says what to use, forbids the tempting shortcut, and explains why with “optimized for correct permissions and access.” It prevents Claude—already comfortable with the shell—from instinctively running &lt;code&gt;rg&lt;/code&gt; through Bash, where output is unstructured and permission handling may differ.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The pattern uses ripgrep regex syntax&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Supports full regex syntax (e.g., &lt;code&gt;log.*Error&lt;/code&gt;, &lt;code&gt;function\s+\w+&lt;/code&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the direct opposite of Glob. Grep’s pattern &lt;strong&gt;is a regular expression&lt;/strong&gt;. Two realistic examples—searching for logged errors and function declarations—immediately communicate the syntax.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two filtering dimensions: glob vs. type&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Filter files with glob parameter (e.g., &lt;code&gt;*.js&lt;/code&gt;, &lt;code&gt;**/*.tsx&lt;/code&gt;) or type parameter (e.g., &lt;code&gt;js&lt;/code&gt;, &lt;code&gt;py&lt;/code&gt;, &lt;code&gt;rust&lt;/code&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude gets two parallel options: use &lt;code&gt;glob&lt;/code&gt; for a precise path pattern or &lt;code&gt;type&lt;/code&gt; for a language shortcut from ripgrep’s built-in type table. One &lt;code&gt;type: rust&lt;/code&gt; is far more concise than spelling out a collection of extensions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The default output mode is files_with_matches&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Output modes: &lt;code&gt;content&lt;/code&gt; shows matching lines, &lt;code&gt;files_with_matches&lt;/code&gt; shows only file paths (default), &lt;code&gt;count&lt;/code&gt; shows match counts&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice that “default” is attached to &lt;code&gt;files_with_matches&lt;/code&gt;, not &lt;code&gt;content&lt;/code&gt;. Why? Because &lt;strong&gt;content consumes the most context&lt;/strong&gt;. Making it the default could flood the context window. A path list lets Claude decide whether a deeper read is necessary. This is a default designed around the token budget.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open-ended search is delegated to Agent&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use Agent tool for open-ended searches requiring multiple rounds&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This mirrors Glob. Both tools &lt;strong&gt;declare their own boundary&lt;/strong&gt;: if the task requires repeated iterations, use Agent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ripgrep is not grep; literals may need escaping&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pattern syntax: Uses ripgrep (not grep)—literal braces need escaping (use &lt;code&gt;interface\{\}&lt;/code&gt; to find &lt;code&gt;interface{}&lt;/code&gt; in Go code)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a concrete example of a real failure mode. In a regular expression, braces express repetition ranges—&lt;code&gt;a{2,3}&lt;/code&gt; means two or three occurrences—so searching for Go’s &lt;code&gt;interface{}&lt;/code&gt; syntax requires escaping the braces. &lt;strong&gt;One realistic example replaces a long syntax lecture.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multiline mode is off by default and must be enabled explicitly&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Multiline matching: By default patterns match within single lines only. For cross-line patterns like &lt;code&gt;struct \{[\s\S]*?field&lt;/code&gt;, use &lt;code&gt;multiline: true&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This prevents Claude from writing a cross-line expression, receiving no matches, and not understanding why. It also illustrates a recurring design pattern: &lt;strong&gt;expensive behavior stays off by default and requires an explicit switch&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Field-level descriptions
&lt;/h4&gt;

&lt;p&gt;Grep has far more fields than Glob:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pattern&lt;/code&gt;—a regular expression using ripgrep syntax.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;path&lt;/code&gt;—an optional directory in which to search.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;glob&lt;/code&gt;—an optional file glob, such as &lt;code&gt;*.ts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;type&lt;/code&gt;—an optional language filter such as &lt;code&gt;ts&lt;/code&gt;, &lt;code&gt;py&lt;/code&gt;, or &lt;code&gt;rust&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;output_mode&lt;/code&gt;—&lt;code&gt;content&lt;/code&gt;, &lt;code&gt;files_with_matches&lt;/code&gt; (default), or &lt;code&gt;count&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;head_limit&lt;/code&gt;—limits the number of output entries.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-i&lt;/code&gt;—case-insensitive matching.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-n&lt;/code&gt;—shows line numbers; enabled by default in content mode.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-A&lt;/code&gt;, &lt;code&gt;-B&lt;/code&gt;, and &lt;code&gt;-C&lt;/code&gt;—lines of context after, before, or around a match; only relevant in content mode.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;multiline&lt;/code&gt;—allows patterns to match across lines.&lt;/li&gt;
&lt;li&gt;Format flags such as &lt;code&gt;-c&lt;/code&gt;, &lt;code&gt;-l&lt;/code&gt;, &lt;code&gt;-L&lt;/code&gt;, &lt;code&gt;-o&lt;/code&gt;, and &lt;code&gt;-Z&lt;/code&gt;—pass output handling through to native grep behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Several design choices stand out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three output modes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is Grep’s most elegant feature. A single search can return three levels of precision:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;content&lt;/code&gt;—all matching lines, when you need to inspect or fix exact locations.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;files_with_matches&lt;/code&gt;—file paths only, when you are scoping a refactor.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;count&lt;/code&gt;—counts only, when you are estimating impact.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These map to three common intents: “I need to fix it,” “I need to refactor it,” and “I need to assess it.” Grep lets Claude choose precision according to intent instead of always retrieving the maximum amount of data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;head_limit as a safety net&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A search for &lt;code&gt;console.log&lt;/code&gt; might return 1,000 lines. Without a limit, that could overwhelm the context window. &lt;code&gt;head_limit: 50&lt;/code&gt; returns only the first 50 entries—enough to work with without flooding the model.&lt;/p&gt;

&lt;p&gt;One subtle detail: Grep orders by file-path lexicographic order, whereas Glob orders by modification time. Neither is a relevance ranking; the limit simply truncates that ordering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;type vs. glob for narrowing scope&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;type&lt;/code&gt; uses ripgrep’s language recognition based on extensions and file types, covering common languages such as Python, Rust, and TypeScript. &lt;code&gt;glob&lt;/code&gt; is pure path matching and can express special layouts such as &lt;code&gt;**/legacy/**/*.js&lt;/code&gt;. &lt;code&gt;type&lt;/code&gt; is more concise; &lt;code&gt;glob&lt;/code&gt; is more flexible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Native format flags as an escape hatch&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When the normalized tool output is not enough, Claude can fall back to native ripgrep capabilities. The designers recognize that no wrapper can cover every use case, so they leave an escape hatch.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Schema validation
&lt;/h4&gt;

&lt;p&gt;Grep’s schema also has &lt;strong&gt;almost no hard constraints&lt;/strong&gt; such as numeric ranges or string-length limits. Most constraints are enums or types:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Constraint&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;output_mode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;content&lt;/code&gt;, &lt;code&gt;files_with_matches&lt;/code&gt;, or &lt;code&gt;count&lt;/code&gt;; defaults to &lt;code&gt;files_with_matches&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;-i&lt;/code&gt;, &lt;code&gt;-n&lt;/code&gt;, &lt;code&gt;multiline&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;default to &lt;code&gt;false&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;-A&lt;/code&gt;, &lt;code&gt;-B&lt;/code&gt;, &lt;code&gt;-C&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;integer&lt;/td&gt;
&lt;td&gt;only apply when &lt;code&gt;output_mode&lt;/code&gt; is &lt;code&gt;content&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;head_limit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;integer&lt;/td&gt;
&lt;td&gt;no default; unlimited when omitted&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Defaults are central to Grep’s design.&lt;/strong&gt; The output mode defaults to &lt;code&gt;files_with_matches&lt;/code&gt;, multiline mode is off, and the flags are off unless requested. Every default leans toward &lt;strong&gt;less output and simpler behavior&lt;/strong&gt;, making the tool context-efficient even when Claude accepts all defaults.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why dedicated Grep and Glob tools instead of Bash + rg?
&lt;/h3&gt;

&lt;p&gt;Bash is a catch-all: in theory, it can do everything. But invoking &lt;code&gt;rg&lt;/code&gt; directly creates several problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shell escaping&lt;/strong&gt;—characters such as &lt;code&gt;$&lt;/code&gt;, &lt;code&gt;!&lt;/code&gt;, and &lt;code&gt;(&lt;/code&gt; inside regular expressions may be interpreted by the shell.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Path dependencies&lt;/strong&gt;—is &lt;code&gt;rg&lt;/code&gt; installed, and which version is available?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output parsing&lt;/strong&gt;—Bash returns a large text blob that Claude must parse itself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No output-mode abstraction&lt;/strong&gt;—Claude has to remember and combine raw &lt;code&gt;rg&lt;/code&gt; flags.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dedicated tools solve these problems with typed parameters, normalized output, no shell quoting traps, and a single structured call. That is the technical foundation behind the instruction: “ALWAYS use Grep… NEVER invoke grep or rg as a Bash command.”&lt;/p&gt;




&lt;h3&gt;
  
  
  Division of responsibility among neighboring tools
&lt;/h3&gt;

&lt;p&gt;Here is where Grep + Glob sit within Claude Code’s execution primitives. Later articles will fill in the rest of the map:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Interaction trio&lt;/th&gt;
&lt;th&gt;Grep + Glob&lt;/th&gt;
&lt;th&gt;Read&lt;/th&gt;
&lt;th&gt;Edit&lt;/th&gt;
&lt;th&gt;Write&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Role&lt;/td&gt;
&lt;td&gt;Collaborative alignment&lt;/td&gt;
&lt;td&gt;Locate coordinates&lt;/td&gt;
&lt;td&gt;Perceive content&lt;/td&gt;
&lt;td&gt;Precise execution&lt;/td&gt;
&lt;td&gt;Full execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frequency&lt;/td&gt;
&lt;td&gt;Key moments&lt;/td&gt;
&lt;td&gt;High-frequency&lt;/td&gt;
&lt;td&gt;High-frequency&lt;/td&gt;
&lt;td&gt;High-frequency&lt;/td&gt;
&lt;td&gt;Medium-frequency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Input&lt;/td&gt;
&lt;td&gt;Structured / empty&lt;/td&gt;
&lt;td&gt;Pattern; path need not be known&lt;/td&gt;
&lt;td&gt;Known path&lt;/td&gt;
&lt;td&gt;Known path + &lt;code&gt;old_string&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Known path + full content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output&lt;/td&gt;
&lt;td&gt;User decision&lt;/td&gt;
&lt;td&gt;Paths / matching lines / counts&lt;/td&gt;
&lt;td&gt;Complete file content&lt;/td&gt;
&lt;td&gt;Modified diff&lt;/td&gt;
&lt;td&gt;New or overwritten file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Conservative bias&lt;/td&gt;
&lt;td&gt;“When uncertain, plan”&lt;/td&gt;
&lt;td&gt;“Search on demand before reading everything”&lt;/td&gt;
&lt;td&gt;“When uncertain, read”&lt;/td&gt;
&lt;td&gt;“When uncertain, read first”&lt;/td&gt;
&lt;td&gt;“Prefer Edit when possible”&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;A complete investigation chain:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User: Help me refactor the auth-related code
    ↓
Glob (**/*{auth,login,session}*)                 ← This article
    → Relevant file paths, ordered by mtime
    ↓
Grep (pattern: "jwt\.verify", output_mode: files_with_matches)  ← This article
    → Files that actually use the API
    ↓
Read (each relevant file)                       ← Next article
    → Full contents establish a perception commitment
    ↓
Edit / Write                                    ← Later articles
    → Precise or full changes based on that perception
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The trust chain of execution primitives:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Glob / Grep—location:&lt;/strong&gt; Which files are relevant to this task?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read—perception:&lt;/strong&gt; What do those files look like right now?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edit / Write—execution:&lt;/strong&gt; How should they be changed, precisely or in full, based on that perception?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every step is enforced at runtime, accepts typed parameters, and produces normalized output. &lt;strong&gt;A vague user request gradually converges into a precise file change&lt;/strong&gt;, and the entire process remains predictable, reviewable, and composable.&lt;/p&gt;




&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;The elegance of Grep + Glob is not merely that they let an AI search. It lies in how their signals are &lt;strong&gt;highly symmetrical yet deliberately different&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Glob&lt;/strong&gt; relies on its industry-standard name for the core semantics, uses a minimal field set, and imposes almost no schema constraints. Its entire complexity is contained in one job: finding paths with glob syntax.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grep&lt;/strong&gt; has a much richer set of fields and flags, yet almost no numeric hard constraints. Instead, its &lt;strong&gt;defaults converge on the most context-efficient behavior&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Their most compelling symmetry is that &lt;strong&gt;both tools explicitly acknowledge their limits in their descriptions&lt;/strong&gt;. When a task requires repeated rounds of globbing and grepping, they tell Claude to switch to Agent. &lt;strong&gt;The tools know what they are good at—and what they are not.&lt;/strong&gt; That restraint is a sign of a mature tool ecosystem.&lt;/p&gt;

&lt;p&gt;This reflects a core philosophy of Claude Code: &lt;strong&gt;do not give the AI one universal shell and ask it to improvise; turn each step into a primitive that is sufficient, safe, and composable.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The next article will examine Read: once Claude has the coordinates, how does it accurately perceive the current state of a file and establish the “perception commitment” that makes Edit and Write trustworthy?&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Claude Code Tools Deep Dive #3 — ExitPlanMode: The Small Signal That Closes the Loop</title>
      <dc:creator>Zhengxin</dc:creator>
      <pubDate>Mon, 03 Aug 2026 11:58:42 +0000</pubDate>
      <link>https://dev.to/_94be737e156beb4d74df2/claude-code-tools-deep-dive-3-exitplanmode-the-small-signal-that-closes-the-loop-1h0p</link>
      <guid>https://dev.to/_94be737e156beb4d74df2/claude-code-tools-deep-dive-3-exitplanmode-the-small-signal-that-closes-the-loop-1h0p</guid>
      <description>&lt;p&gt;This is the third post in my Claude Code Tools Deep Dive series. The first two unpacked &lt;a href="https://dev.to/_94be737e156beb4d74df2/claude-code-tools-deep-dive-1-askuserquestion-4ck1"&gt;AskUserQuestion&lt;/a&gt; and &lt;a href="https://dev.to/_94be737e156beb4d74df2/claude-code-tools-deep-dive-2-enterplanmode-why-an-empty-schema-is-a-design-choice-51d1"&gt;EnterPlanMode&lt;/a&gt;—the first two stages of the decision pipeline: &lt;strong&gt;clarify, then expand&lt;/strong&gt;. This post covers the final stage: &lt;strong&gt;submit the plan for user approval&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Before reading this post, it may help to read the &lt;a href="https://dev.to/_94be737e156beb4d74df2/claude-code-tools-deep-dive-0-how-the-tool-mechanism-actually-works-59p6"&gt;series prelude&lt;/a&gt; on how Claude Code's tool mechanism works. This article follows the same four-layer framework introduced there.&lt;/p&gt;

&lt;h2&gt;
  
  
  ExitPlanMode
&lt;/h2&gt;

&lt;p&gt;On the surface, ExitPlanMode may be the least conspicuous of Claude Code's three interaction tools. It has none of AskUserQuestion's option cards and none of EnterPlanMode's dramatic mode switch. It does exactly one thing: &lt;strong&gt;trigger an approve-or-reject confirmation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But that restraint—doing almost nothing—is precisely what closes the three-tool workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  What It Does
&lt;/h2&gt;

&lt;p&gt;ExitPlanMode is Claude Code's built-in &lt;strong&gt;“leave planning mode and request approval” tool&lt;/strong&gt;. Its responsibility fits in one sentence: after Claude has written a complete plan in plan mode, it calls this tool so the user can review the entire plan and decide whether to &lt;strong&gt;approve execution, request revisions, or reject the direction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It solves the core problem of &lt;strong&gt;obtaining explicit user approval when the AI moves from planning back to implementation&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Make the proposal visible&lt;/strong&gt; — the UI displays the complete plan file instead of letting it disappear inside a chat message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Require an explicit decision&lt;/strong&gt; — the user must approve or reject; Claude cannot continue by default or jump the gun.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Switch back to implementation in one action&lt;/strong&gt; — after approval, Claude automatically returns to the default mode where Edit and Write are available.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Preserve a feedback channel&lt;/strong&gt; — the user can reject the current version and ask for changes instead of choosing between “accept everything” and “throw everything away.”&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A Concrete Example
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; continuing the authentication refactor from the &lt;a href="https://dev.to/_94be737e156beb4d74df2/claude-code-tools-deep-dive-2-enterplanmode-why-an-empty-schema-is-a-design-choice-51d1"&gt;EnterPlanMode post&lt;/a&gt;. The user asked Claude to replace JWT with session cookies. Claude entered plan mode, explored the codebase, clarified that only the web flow should change and that Redis should hold session state, then wrote the plan file. It is now ready to implement.&lt;/p&gt;

&lt;p&gt;One question remains: &lt;strong&gt;how does Claude tell the user that the plan is complete and implementation can begin?&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Anti-Pattern: Life Without ExitPlanMode
&lt;/h3&gt;

&lt;p&gt;Claude could only say something like this in chat:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I've finished the plan. It looks roughly like this... [several hundred words] ... May I start?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That creates several problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The plan gets buried in the conversation&lt;/strong&gt; — hundreds of words mix with exploration logs and clarification messages, making the proposal difficult to review.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;There is no explicit approval action&lt;/strong&gt; — “OK,” “sure,” “go ahead,” and “👍” may all mean approval, but their semantics are not identical.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude must interpret approval language&lt;/strong&gt; — a reply such as “Looks good, but can we add a &lt;code&gt;device_id&lt;/code&gt; field to the sessions table?” is half approval and half revision request. Should Claude implement or revise the plan?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The mode transition has no boundary&lt;/strong&gt; — Claude can gradually slide from planning into implementation and start writing code before the user realizes the transition occurred.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rejection is expensive&lt;/strong&gt; — if the proposal is wrong, the user must type an explanation instead of using a first-class “reject and explain” channel.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The deepest problem appears if Claude tries to solve this with AskUserQuestion by asking, “Is the plan OK?” As the previous post explained, &lt;strong&gt;the user cannot see the full plan before ExitPlanMode presents it&lt;/strong&gt;. Asking for approval before showing the document is asking the user to vote in a vacuum.&lt;/p&gt;

&lt;h3&gt;
  
  
  How ExitPlanMode Fixes It
&lt;/h3&gt;

&lt;p&gt;After finishing the plan file, Claude calls ExitPlanMode. &lt;strong&gt;The call takes no meaningful arguments&lt;/strong&gt;—more on that below. The UI then handles three steps.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1: Display the Complete Plan
&lt;/h4&gt;

&lt;p&gt;The interface reads the file at the path maintained by plan mode and renders it as a &lt;strong&gt;separate, structured, scrollable proposal&lt;/strong&gt;. The user sees a formal plan—scope, affected files, migration steps, risks, and rollback—not a paragraph floating through chat.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2: Provide Explicit Response Paths
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Approve&lt;/strong&gt; — return Claude to default mode and execute the plan.&lt;/li&gt;
&lt;li&gt;✏️ &lt;strong&gt;Request changes&lt;/strong&gt; — give feedback and keep Claude in plan mode so it can revise the proposal.&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;Reject&lt;/strong&gt; — stop and change direction.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Step 3: Make the Transition Atomic
&lt;/h4&gt;

&lt;p&gt;The moment the user approves, the runtime performs several actions together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Edit, Write, and NotebookEdit become available again.&lt;/li&gt;
&lt;li&gt;CWD-dependent caches are refreshed.&lt;/li&gt;
&lt;li&gt;Claude receives an explicit “user approved” signal and begins implementation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is &lt;strong&gt;no semantic ambiguity, no gradual slide, and no opportunity for Claude to jump the gun&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Side-by-Side Comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Anti-pattern pain&lt;/th&gt;
&lt;th&gt;ExitPlanMode's solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The plan gets buried in chat&lt;/td&gt;
&lt;td&gt;The UI independently renders the complete plan file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No explicit approval action&lt;/td&gt;
&lt;td&gt;The user must choose approve, revise, or reject&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude must interpret agreement&lt;/td&gt;
&lt;td&gt;The result is a structured state, not ambiguous natural language&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The mode transition has no boundary&lt;/td&gt;
&lt;td&gt;Approval atomically changes the tool allowlist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rejection is expensive&lt;/td&gt;
&lt;td&gt;Revision is a first-class path rather than an improvised reply&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  When to Fire It
&lt;/h2&gt;

&lt;p&gt;The tool description gives a very strict rule: &lt;strong&gt;use ExitPlanMode only when Claude is in plan mode, has finished writing the plan file, and is ready for user approval&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The One Valid Situation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Claude is in plan mode and the plan file is complete.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Situations That Do Not Qualify
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pure research&lt;/strong&gt; — a task such as “search for and understand the Vim mode implementation” does not need ExitPlanMode because no implementation plan is being submitted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An unfinished plan&lt;/strong&gt; — do not submit a partial proposal for approval. Finish it first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A general-purpose permission question&lt;/strong&gt; — do not use this tool as a fancy “May I continue?” prompt. If a real implementation fork needs clarification, use AskUserQuestion to ask about that fork rather than asking a meta-question.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A useful dividing line is: &lt;strong&gt;only a citable plan deserves ExitPlanMode&lt;/strong&gt;. If the proposal is not yet a readable, reviewable, refutable document, keep exploring in plan mode instead of rushing to exit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Design
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Naming
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ExitPlanMode&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The name is perfectly dual to &lt;code&gt;EnterPlanMode&lt;/code&gt;. The Enter/Exit pair signals a stateful operation with a beginning and an end, following familiar pairs such as opening/closing a file descriptor or acquiring/releasing a lock. The semantics need almost no explanation.&lt;/p&gt;

&lt;p&gt;Names such as &lt;code&gt;SubmitPlan&lt;/code&gt; or &lt;code&gt;RequestApproval&lt;/code&gt; would shift attention toward submitting data or requesting permission. They would weaken the tool's core meaning as a &lt;strong&gt;signal that ends a mode&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Tool-Level Description
&lt;/h3&gt;

&lt;p&gt;ExitPlanMode's description focuses on three things: &lt;strong&gt;when to use it, why the plan content is not an argument, and why AskUserQuestion must not be used for the same meta-question&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Strict Applicability Boundary
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Use this tool when you are in plan mode and have finished writing your plan to the plan file and are ready for user approval.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Three conditions are stacked together: &lt;strong&gt;Claude is in plan mode, the plan file is complete, and the proposal is ready for approval&lt;/strong&gt;. If any one is false, the tool should not be called.&lt;/p&gt;

&lt;h4&gt;
  
  
  Transparent Parameter Mechanism
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;This tool does NOT take the plan content as a parameter - it will read the plan from the file you wrote&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The instruction tells Claude not to copy the plan into the tool call. The UI reads the file directly. This saves tokens and, more importantly, guarantees that &lt;strong&gt;the plan the UI displays is the same plan stored in the file&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Approval as an Implied Signal
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;This tool simply signals that you're done planning and ready for the user to review and approve&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The key word is &lt;strong&gt;signals&lt;/strong&gt;. The tool itself does not render the document or decide whether it was approved. It only emits an event. The runtime handles rendering, user input, and the state transition.&lt;/p&gt;

&lt;p&gt;The tool call is therefore the lightest possible &lt;strong&gt;signal emitter&lt;/strong&gt;—a distinctly Unix-like design.&lt;/p&gt;

&lt;h4&gt;
  
  
  Boundary with Research Tasks
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;IMPORTANT: Only use this tool when the task requires planning the implementation steps of a task that requires writing code. For research tasks where you're gathering information, searching files, reading files or in general trying to understand the codebase - do NOT use this tool.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This mirrors the boundary described for EnterPlanMode: &lt;strong&gt;plan mode exists for planning implementation, not for understanding an existing codebase as an end in itself&lt;/strong&gt;. A pure investigation belongs in a research workflow rather than an implementation-approval workflow.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Forbidden Meta-Question
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Do NOT use AskUserQuestion to ask “Is this plan okay?” or “Should I proceed?” - that's exactly what THIS tool does. ExitPlanMode inherently requests user approval of your plan.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is especially elegant. It does not merely say “use ExitPlanMode instead of AskUserQuestion.” It identifies the two actions as &lt;strong&gt;semantically equivalent&lt;/strong&gt; and declares that ExitPlanMode is the correct representation of that intent.&lt;/p&gt;

&lt;p&gt;The earlier posts noted this anti-pattern. Here, the tool description bans it at the source.&lt;/p&gt;

&lt;h4&gt;
  
  
  Clarification Before Approval
&lt;/h4&gt;

&lt;p&gt;One official example says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Initial task: “Add a new feature to handle user authentication” - If unsure about auth method (OAuth, JWT, etc.), use AskUserQuestion first, then use exit plan mode tool after clarifying the approach.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This establishes the ordering between AskUserQuestion and ExitPlanMode while planning: clarify concrete forks first, then request approval for the complete proposal. &lt;strong&gt;Do not clarify and approve at the same time.&lt;/strong&gt; Let the process converge linearly.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Field-Level Descriptions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Effectively none.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is an &lt;code&gt;allowedPrompts&lt;/code&gt; field, but it is marked deprecated: “Deprecated: no longer used.” In practice, the tool accepts no useful input.&lt;/p&gt;

&lt;p&gt;That historical trace is interesting. Judging by the field name, an earlier version may have allowed Claude to declare a set of operation types that would become automatically permitted after approval—for example, &lt;code&gt;run tests&lt;/code&gt; or &lt;code&gt;install dependencies&lt;/code&gt;. Its deprecation suggests that the design moved toward a more conservative separation: &lt;strong&gt;approving the plan and granting additional permissions are different decisions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In other words, it hints at an evolution from “approval implies authorization” toward “approval is approval; authorization is authorization.”&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Schema Validation Rules
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Effectively none.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Like EnterPlanMode, the input schema has no active constraints. Calling the tool is itself the intent to submit the plan; there is no data Claude needs to pass.&lt;/p&gt;

&lt;p&gt;The empty schema leaves four responsibilities to the runtime:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make the tool available only in plan mode.&lt;/li&gt;
&lt;li&gt;Read and render the plan using the file path stored in the plan-mode state.&lt;/li&gt;
&lt;li&gt;Block until the user explicitly responds; there is no automatic continuation.&lt;/li&gt;
&lt;li&gt;On approval, atomically restore the tool allowlist, refresh caches, and send Claude the approval signal.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of that requires an argument. This echoes EnterPlanMode's empty-schema design: &lt;strong&gt;permissions and state belong to the runtime; Claude only emits a signal&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Division of Responsibility with Neighboring Tools
&lt;/h2&gt;

&lt;p&gt;ExitPlanMode is the final stage of the decision pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User: “Refactor auth and replace JWT with sessions.”
    ↓
Claude: Several forks need clarification.
    ↓
AskUserQuestion: clarify web-only scope and Redis session storage
    ↓
Claude: Let me develop a plan first.
    ↓
EnterPlanMode: user approves entry
    ├─ Explore with Grep / Read / Glob
    ├─ Clarify sub-decisions with AskUserQuestion as needed
    └─ Write the plan file
    ↓
ExitPlanMode: user sees the complete plan
    ├─ Approve → return to default mode and execute
    ├─ Request changes → revise in plan mode, then call ExitPlanMode again
    └─ Reject → stop or change direction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each of the three tools has exactly one job. Together, they create a complete &lt;strong&gt;collaborative alignment loop&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AskUserQuestion&lt;/strong&gt; — clarify: “A or B?” A single-point decision.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EnterPlanMode&lt;/strong&gt; — expand: explore read-only and turn the approach into a document.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ExitPlanMode&lt;/strong&gt; — commit: let the user approve, revise, or reject the entire proposal.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;ExitPlanMode's elegance is not simply that it “lets the user approve the plan.” It comes from how closely its signals mirror EnterPlanMode: dual naming, behavior concentrated in the tool description, and effectively empty field and schema layers.&lt;/p&gt;

&lt;p&gt;If AskUserQuestion lets the user choose, and EnterPlanMode opens a protected planning state, then ExitPlanMode is the humblest part of the system: &lt;strong&gt;it does nothing but emit a signal&lt;/strong&gt;. Yet that signal gives the workflow an endpoint and gives collaboration a ceremonial moment of commitment.&lt;/p&gt;

&lt;p&gt;The three-tool pipeline is now complete:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Claude Code decomposes AI–human collaboration into three composable, orchestratable, predictable interaction primitives: &lt;strong&gt;clarify, expand, commit&lt;/strong&gt;. Each primitive is deliberately restrained—it does one small thing—but together they can express a complete collaborative workflow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The next post will move from collaborative alignment to code exploration with &lt;strong&gt;Grep + Glob&lt;/strong&gt;, examining how information-retrieval tools encode what to search, how to search, and how much to return.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>agents</category>
      <category>promptengineering</category>
    </item>
    <item>
      <title>Claude Code Tools Deep Dive #2 — EnterPlanMode: Why an Empty Schema Is a Design Choice</title>
      <dc:creator>Zhengxin</dc:creator>
      <pubDate>Sun, 02 Aug 2026 14:49:25 +0000</pubDate>
      <link>https://dev.to/_94be737e156beb4d74df2/claude-code-tools-deep-dive-2-enterplanmode-why-an-empty-schema-is-a-design-choice-51d1</link>
      <guid>https://dev.to/_94be737e156beb4d74df2/claude-code-tools-deep-dive-2-enterplanmode-why-an-empty-schema-is-a-design-choice-51d1</guid>
      <description>&lt;p&gt;This is the second post in my Claude Code Tools Deep Dive series. The &lt;a href="https://dev.to/_94be737e156beb4d74df2/claude-code-tools-deep-dive-1-askuserquestion-4ck1"&gt;previous post&lt;/a&gt; unpacked &lt;strong&gt;AskUserQuestion&lt;/strong&gt;, a structured tool that lets users choose from concrete options. This time, we're looking at its sibling: &lt;strong&gt;EnterPlanMode&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Before reading this post, it may help to read the &lt;a href="https://dev.to/_94be737e156beb4d74df2/claude-code-tools-deep-dive-0-how-the-tool-mechanism-actually-works-59p6"&gt;series prelude&lt;/a&gt; on how Claude Code's tool mechanism works. This article follows the same four-layer framework introduced there.&lt;/p&gt;

&lt;h2&gt;
  
  
  EnterPlanMode
&lt;/h2&gt;

&lt;p&gt;Like AskUserQuestion, EnterPlanMode is a tool you may encounter almost every day. But its design is much heavier. It does not merely ask a question; it &lt;strong&gt;switches Claude into an entirely different mode of operation&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What It Does
&lt;/h2&gt;

&lt;p&gt;EnterPlanMode is Claude Code's built-in &lt;strong&gt;entry point into planning mode&lt;/strong&gt;. Its job is simple but forceful: move Claude from the default "think while writing" workflow into a planning workflow built around &lt;strong&gt;read-only exploration and solution design&lt;/strong&gt;. Claude returns to implementation only after the user explicitly approves the plan.&lt;/p&gt;

&lt;p&gt;The core problem it solves is &lt;strong&gt;alignment between the AI and the user&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Prevent work from drifting in the wrong direction&lt;/strong&gt; — Claude aligns on the approach before modifying a single file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enforce read-only exploration&lt;/strong&gt; — once plan mode is active, Edit, Write, and NotebookEdit are disabled. Claude cannot quietly make changes while it explores.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create an explicit decision boundary&lt;/strong&gt; — the user can approve, reject, or request changes to a complete proposal instead of discovering a wrong direction only after seeing the pull request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Produce a traceable planning artifact&lt;/strong&gt; — plan mode creates a written plan that can be referenced and revised, rather than a paragraph that disappears into the chat history.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A Concrete Example
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; the user tells Claude, &lt;strong&gt;"Refactor this authentication module and replace JWT with session cookies."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The request sounds clear, but it actually spans login routes, token-generation middleware, frontend storage, session-expiration policy, database schema decisions, and backward compatibility for existing API consumers. It is a &lt;strong&gt;multi-file, multi-decision, dependency-heavy change&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Anti-Pattern: Working Without EnterPlanMode
&lt;/h3&gt;

&lt;p&gt;Without a planning boundary, Claude has to infer an approach from the available context and start editing immediately:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open &lt;code&gt;auth/middleware.ts&lt;/code&gt; and switch it to reading a session cookie.&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;auth/routes.ts&lt;/code&gt;, remove JWT issuance, and replace it with &lt;code&gt;req.session&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;frontend/api.ts&lt;/code&gt; and remove the &lt;code&gt;Authorization&lt;/code&gt; header logic.&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;models/user.ts&lt;/code&gt; and add a &lt;code&gt;sessionId&lt;/code&gt; field.&lt;/li&gt;
&lt;li&gt;Halfway through the refactor, discover that three other services authenticate against the same API with JWTs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The user sees the diff and says: "I only wanted sessions for the web app. The backend services still need JWT. Why did you replace authentication for the entire API?"&lt;/p&gt;

&lt;p&gt;Several things went wrong:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The directional error surfaced five steps too late&lt;/strong&gt; — four files have already changed, so rollback is painful.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The decision boundary was unclear&lt;/strong&gt; — "replace all authentication or only the web flow?" was a critical fork, but Claude guessed without asking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The user never saw the whole picture&lt;/strong&gt; — they received a pile of diffs and had to reverse-engineer the intended design.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Important side effects were never surfaced&lt;/strong&gt; — should the system create a sessions table? Should session state live in memory, Redis, or the database? Claude may have considered these questions, but never turned them into an explicit proposal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rollback is expensive&lt;/strong&gt; — every edit consumes tokens and attention; discarding the implementation wastes both.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The core pain:&lt;/strong&gt; "think while writing" lets Claude generate diffs before the approach is stable, while the user cannot see the full design until the end.&lt;/p&gt;

&lt;h3&gt;
  
  
  How EnterPlanMode Fixes It
&lt;/h3&gt;

&lt;p&gt;Claude first declares that it wants to enter plan mode and asks for the user's approval. &lt;strong&gt;That transition is itself an interactive confirmation.&lt;/strong&gt; If the user declines, Claude remains in the default mode.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1: Enter Read-Only Exploration
&lt;/h4&gt;

&lt;p&gt;Claude's toolset becomes narrower:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Available: Read, Glob, Grep, Agent, AskUserQuestion, and ExitPlanMode&lt;/li&gt;
&lt;li&gt;❌ Disabled: Edit, Write, and NotebookEdit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Claude physically cannot modify project files. Every exploration action is read-only.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2: Understand the Current System
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Use Grep to find every JWT reference and discover the three internal services.&lt;/li&gt;
&lt;li&gt;Use Read to inspect the current validation logic in &lt;code&gt;auth/middleware.ts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use Glob to locate authentication-related tests.&lt;/li&gt;
&lt;li&gt;Use Agent to assign a general-purpose subagent to investigate whether the project already has a session-store convention.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Step 3: Clarify Critical Forks with AskUserQuestion
&lt;/h4&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace JWT only for the web app, or everywhere?&lt;/li&gt;
&lt;li&gt;Store sessions in memory, Redis, or the database?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is exactly the clarification pattern discussed in the previous post. &lt;strong&gt;AskUserQuestion and EnterPlanMode are natural partners.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 4: Write the Plan
&lt;/h4&gt;

&lt;p&gt;Claude writes the complete proposal to a plan file: scope, affected files, migration steps, risks, and rollback strategy. &lt;strong&gt;This is a revisable, referenceable artifact—not a transient chat message.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 5: Request Approval with ExitPlanMode
&lt;/h4&gt;

&lt;p&gt;The user sees the complete plan and chooses what happens next:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Approve&lt;/strong&gt; → Claude returns to implementation mode and executes the plan.&lt;/li&gt;
&lt;li&gt;✏️ &lt;strong&gt;Request changes&lt;/strong&gt; → Claude revises the plan using the feedback.&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;Reject&lt;/strong&gt; → Claude changes direction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Not a single project file is modified before approval.&lt;/strong&gt; The user's tokens, time, and attention are not spent implementing the wrong approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  Side-by-Side Comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Anti-pattern pain&lt;/th&gt;
&lt;th&gt;EnterPlanMode's solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Directional error discovered five steps too late&lt;/td&gt;
&lt;td&gt;No project files can be changed before ExitPlanMode approval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unclear decision boundaries&lt;/td&gt;
&lt;td&gt;AskUserQuestion clarifies critical forks inside plan mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User cannot see the big picture&lt;/td&gt;
&lt;td&gt;The plan file presents a complete proposal instead of scattered diffs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Important side effects are not surfaced&lt;/td&gt;
&lt;td&gt;The enforced explore → design → present sequence gives Claude time to reason through them&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High rollback cost&lt;/td&gt;
&lt;td&gt;Exploration is read-only, so rejecting a plan requires no code rollback&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  When to Use It
&lt;/h2&gt;

&lt;p&gt;The tool's official description contains an interesting rule: &lt;strong&gt;non-trivial implementation tasks should default to planning.&lt;/strong&gt; This is a deliberately conservative bias.&lt;/p&gt;

&lt;h3&gt;
  
  
  Seven Situations That Call for Plan Mode
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Implementing a new feature&lt;/strong&gt; — even small features hide decisions: where should the code live, what should the button do, and how should errors be handled?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple reasonable approaches&lt;/strong&gt; — "add caching" may mean Redis, memory, or files; "real-time updates" may mean WebSockets, SSE, or polling. The choice itself is design work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Changing existing behavior&lt;/strong&gt; — "update the login flow" is ambiguous. Define the change before touching the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Making architectural decisions&lt;/strong&gt; — patterns, dependencies, and data-flow direction should be agreed upon.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Changes spanning more than two or three files&lt;/strong&gt; — the impact is large enough that a diff no longer communicates the whole design.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unclear requirements&lt;/strong&gt; — "make the app faster" requires profiling and a discussion of optimization priorities first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implementation shaped by user preferences&lt;/strong&gt; — if you need AskUserQuestion to clarify the approach, you probably need EnterPlanMode to develop it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Four Situations That Do Not
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A one-line fix&lt;/strong&gt; — correcting a typo or an obvious off-by-one error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adding one clearly specified function&lt;/strong&gt; — implement it directly; there is no need for ceremony.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The user already supplied precise, detailed instructions&lt;/strong&gt; — the user has already done the planning, so repeating it adds friction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pure research or exploration&lt;/strong&gt; — use the Agent tool with an explore agent when no implementation will follow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One phrase in the original description is especially revealing: &lt;strong&gt;"err on the side of planning."&lt;/strong&gt; When uncertain, plan first. The default itself exposes the designers' preference: &lt;strong&gt;bias toward alignment over speed&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Design
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Naming
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;EnterPlanMode&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;AskUserQuestion carries signals across all four design layers. EnterPlanMode distributes them very differently: &lt;strong&gt;the name performs work that a schema might otherwise do.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Enter&lt;/code&gt; is a verb that implies moving into a state—not fetching data or performing a one-off action.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PlanMode&lt;/code&gt; names that state and forms a natural pair with &lt;code&gt;ExitPlanMode&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Consider a counterfactual design: &lt;code&gt;SetMode(mode: "plan")&lt;/code&gt;. The model might interpret that as setting a property and switch modes casually. The current name encodes a &lt;strong&gt;ceremonial state transition&lt;/strong&gt;: entering is explicit, and exiting is explicit. Its semantics are much stronger than a parameterized SetMode.&lt;/p&gt;

&lt;p&gt;That is why the schema can be empty. The name has already locked down the meaning, so the schema does not need to rescue it.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Tool-Level Description
&lt;/h3&gt;

&lt;p&gt;EnterPlanMode's description revolves around four questions: &lt;strong&gt;when to use it, when not to use it, how it divides work with neighboring tools, and what happens at runtime.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  A Conservative Opening Bias
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Prefer using EnterPlanMode for implementation tasks unless they're simple.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One sentence reshapes Claude's behavior. When uncertain, plan instead of immediately acting. The tool starts by moving the default setting toward caution.&lt;/p&gt;

&lt;h4&gt;
  
  
  Quantified Thresholds for Seven Use Cases
&lt;/h4&gt;

&lt;p&gt;The "When to Use This Tool" section lists seven numbered cases, each with concrete signals. A representative example is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Multi-File Changes: The task will likely touch more than 2-3 files&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This supplies a &lt;strong&gt;quantified threshold&lt;/strong&gt; instead of asking Claude to trust a subjective feeling. Intuition becomes an operational rule, reducing inconsistency around whether plan mode is warranted.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Boundary with AskUserQuestion
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;If you would use AskUserQuestion to clarify the approach, use EnterPlanMode instead&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This turns a fuzzy boundary into a direct rule: &lt;strong&gt;AskUserQuestion handles isolated clarification, while approach-level forks call for plan mode.&lt;/strong&gt; It prevents the anti-pattern of repeatedly asking disconnected questions and trying to assemble the answers into a plan afterward.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Boundary with Agent
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Pure research/exploration tasks (use the Agent tool with explore agent instead)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This defines another boundary: &lt;strong&gt;do not use EnterPlanMode for research that will not lead to implementation.&lt;/strong&gt; Plan mode exists for planning before implementation. If implementation is not the goal, entering it is wasted motion; delegate the investigation to an explore agent instead.&lt;/p&gt;

&lt;h4&gt;
  
  
  User Approval Is Mandatory
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;This tool REQUIRES user approval - they must consent to entering plan mode&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The AI cannot unilaterally change the workflow. The user guards the transition. This also explains why the tool accepts no arguments: the call itself is a request, not the execution of a parameterized operation.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Default Under Uncertainty
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;If unsure whether to use it, err on the side of planning - it's better to get alignment upfront than to redo work&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the description's &lt;strong&gt;statement of values&lt;/strong&gt;: a round of alignment is cheaper than an incorrect implementation and rollback. The same philosophy appeared in AskUserQuestion. Claude Code's tool ecosystem consistently favors alignment.&lt;/p&gt;

&lt;h4&gt;
  
  
  Planning as Collaboration Etiquette
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Users appreciate being consulted before significant changes are made to their codebase&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This sentence trains Claude's &lt;strong&gt;social intuition&lt;/strong&gt;. Planning is not merely an efficiency mechanism; it respects the user's ownership of the codebase. The framing encourages Claude to treat consultation as good collaboration rather than an interruption.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Field-Level Descriptions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;None.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;EnterPlanMode has no input fields. Its schema is the empty object &lt;code&gt;{}&lt;/code&gt;, so this layer does not exist. Every behavioral signal moves up into the tool-level description.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Schema Validation Rules
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;None.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;input_schema&lt;/code&gt; is empty: no fields, no types, and no constraints. Calling the tool is itself the intention to change state; there is no data to pass.&lt;/p&gt;

&lt;p&gt;That absence is a design signal in its own right: &lt;strong&gt;permission is enforced at the tool and runtime layers, not the parameter layer.&lt;/strong&gt; Claude does not need to request individual permissions or specify a target mode. After Claude calls EnterPlanMode, the runtime automatically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Requires user approval, just as AskUserQuestion requires user interaction.&lt;/li&gt;
&lt;li&gt;Narrows the tool allowlist by disabling Edit, Write, and NotebookEdit.&lt;/li&gt;
&lt;li&gt;Refreshes CWD-dependent caches, including system-prompt sections, memory files, and the plans directory, so plan mode starts with clean context.&lt;/li&gt;
&lt;li&gt;Keeps the state active until Claude explicitly calls ExitPlanMode.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Unlike AskUserQuestion, which ends after the answer arrives, plan mode is a &lt;strong&gt;persistent state&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Division of Responsibility with Neighboring Tools
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AskUserQuestion&lt;/strong&gt; — clarify one decision: "A or B?"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EnterPlanMode&lt;/strong&gt; — develop the complete proposal; AskUserQuestion remains available while planning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ExitPlanMode&lt;/strong&gt; — submit the proposal for user approval.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, the three tools form a complete decision pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Encounter an unclear fork
    ↓
AskUserQuestion: clarify A vs. B
    ↓
EnterPlanMode: enter planning mode
    ├─ Explore with Grep / Read / Glob / Agent
    ├─ Clarify sub-decisions with AskUserQuestion as needed
    └─ Write the plan file
    ↓
ExitPlanMode: submit the plan
    ├─ User approves → return to default mode and implement
    ├─ User requests changes → revise in plan mode
    └─ User rejects → stop or change direction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As discussed in the AskUserQuestion post, Claude should not use AskUserQuestion inside plan mode for the meta-question, "Is this plan OK?" The reason is temporal: &lt;strong&gt;the user cannot see the plan until ExitPlanMode presents it for approval.&lt;/strong&gt; Asking whether an invisible plan is acceptable is meaningless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;EnterPlanMode's elegance is not simply that it "makes the AI think before acting." It comes from an &lt;strong&gt;extremely uneven distribution of design signals&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The name carries the core semantics through the Enter/Exit pairing.&lt;/li&gt;
&lt;li&gt;The tool-level description carries a dense set of behavioral constraints: seven use cases, a conservative default, neighboring-tool boundaries, and collaboration etiquette.&lt;/li&gt;
&lt;li&gt;The field-description and schema-validation layers are empty.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That reveals a deeper principle: &lt;strong&gt;an empty schema is itself a design choice.&lt;/strong&gt; When a tool's meaning is "transition into a state," parameterizing it can weaken the meaning. &lt;code&gt;SetMode&lt;/code&gt; invites casual switching. A zero-argument &lt;code&gt;EnterPlanMode&lt;/code&gt; is a deliberate, ceremonial request.&lt;/p&gt;

&lt;p&gt;The next post will examine &lt;strong&gt;ExitPlanMode&lt;/strong&gt;, the final stage of this three-tool decision pipeline, and unpack how "submit a plan for approval" is designed.&lt;/p&gt;

</description>
      <category>promptengineering</category>
      <category>ai</category>
      <category>claudecode</category>
      <category>agents</category>
    </item>
    <item>
      <title>Claude Code Tools Deep Dive #0 — How the Tool Mechanism Actually Works</title>
      <dc:creator>Zhengxin</dc:creator>
      <pubDate>Sat, 01 Aug 2026 17:58:41 +0000</pubDate>
      <link>https://dev.to/_94be737e156beb4d74df2/claude-code-tools-deep-dive-0-how-the-tool-mechanism-actually-works-59p6</link>
      <guid>https://dev.to/_94be737e156beb4d74df2/claude-code-tools-deep-dive-0-how-the-tool-mechanism-actually-works-59p6</guid>
      <description>&lt;p&gt;Each post in this series will dissect one specific Claude Code tool. But first, we need a shared foundation: &lt;strong&gt;What is a tool, and how does Claude use one?&lt;/strong&gt; Every later deep dive builds on this mechanism.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Tools Exist
&lt;/h2&gt;

&lt;p&gt;An LLM, by itself, can only &lt;strong&gt;generate text&lt;/strong&gt;. That creates two fundamental limitations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;It cannot act on the outside world.&lt;/strong&gt; Generating the sentence “I deleted the file” does not actually delete anything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Its output is not inherently reliable.&lt;/strong&gt; A model may return malformed structures, omit fields, or hallucinate content, making the result unsafe for downstream programs to consume.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Tools fill both gaps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Actions&lt;/strong&gt; — a tool declares an executable function. When the model calls it, the harness performs the real operation: reading a file, sending a request, switching modes, and so on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structure&lt;/strong&gt; — a JSON Schema defines the input. The model must produce arguments that conform to that schema; invalid input can be rejected before execution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From this perspective, a tool does not simply “make the LLM more powerful.” It creates a &lt;strong&gt;trusted channel between the LLM and the outside world&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Tool Definition Looks Like
&lt;/h2&gt;

&lt;p&gt;In the Anthropic API, a tool definition is a JSON object. Here is a simplified version of &lt;code&gt;AskUserQuestion&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;"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;"AskUserQuestion"&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;"Use this tool only when you are blocked on a decision that is genuinely the user's to make: one you cannot resolve from the request, the code, or sensible defaults. ..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"input_schema"&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;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"properties"&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;"questions"&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;"array"&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;"Questions to ask the user (1-4 questions)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"minItems"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"maxItems"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"items"&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;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"properties"&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;"question"&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;"string"&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;"The complete question to ask the user. Should be clear, specific, and end with a question mark. Example: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Which library should we use for date formatting?&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&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;"header"&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;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"maxLength"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&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;"Very short label displayed as a chip/tag (max 12 chars). Examples: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Auth method&lt;/span&gt;&lt;span class="se"&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;Library&lt;/span&gt;&lt;span class="se"&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;Approach&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&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;"multiSelect"&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;"boolean"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&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;"Set to true to allow the user to select multiple options ..."&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;"options"&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;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"minItems"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"maxItems"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"items"&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;"..."&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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="nl"&gt;"required"&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;"question"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"header"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"options"&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="nl"&gt;"required"&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;"questions"&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;There are three top-level fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;name&lt;/code&gt;&lt;/strong&gt; — the tool's unique identifier and a naming signal the model can interpret&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;description&lt;/code&gt;&lt;/strong&gt; — natural-language guidance explaining what the tool does, when to use it, and when not to use it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;input_schema&lt;/code&gt;&lt;/strong&gt; — a JSON Schema defining the argument structure, field-level descriptions, and validation rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the entire tool definition. There is no hidden configuration inside the definition itself. Every design intention must be encoded in these three fields.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Four Layers of a Tool Definition
&lt;/h2&gt;

&lt;p&gt;Later posts will analyze each tool through four layers. These layers are simply an expanded view of the three top-level fields:&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;Location&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1. Naming&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;name&lt;/code&gt; and field names inside the schema&lt;/td&gt;
&lt;td&gt;Communicates meaning through names&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. Tool-level description&lt;/td&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Helps the model decide, “Is this the tool I should use?”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. Field-level descriptions&lt;/td&gt;
&lt;td&gt;Each field's &lt;code&gt;description&lt;/code&gt; inside &lt;code&gt;input_schema&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Tells the model what belongs in each field&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4. Schema validation&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;type&lt;/code&gt;, &lt;code&gt;minItems&lt;/code&gt;, &lt;code&gt;maxLength&lt;/code&gt;, &lt;code&gt;enum&lt;/code&gt;, and so on&lt;/td&gt;
&lt;td&gt;Hard-blocks invalid input&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;signal density decreases while coverage increases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Naming&lt;/strong&gt; — understood from a single word and reinforced every time the model encounters the field&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool description&lt;/strong&gt; — available whenever the model considers using the tool; defines the broad behavioral boundary&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Field description&lt;/strong&gt; — becomes most relevant while the model is filling that field; provides a precise hint&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schema validation&lt;/strong&gt; — becomes visible when the model gets something wrong; acts as a hard guardrail&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, these four layers form the complete prompting surface of a tool definition.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Claude “Reads” Tool Definitions
&lt;/h2&gt;

&lt;p&gt;The important point is that &lt;strong&gt;the available tool definitions are sent with the model request&lt;/strong&gt;, rather than appearing only after a tool has been selected.&lt;/p&gt;

&lt;p&gt;The flow looks roughly like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The harness collects all available tool definitions.&lt;/li&gt;
&lt;li&gt;On each request to Claude, it includes the tool list in the API's &lt;code&gt;tools&lt;/code&gt; parameter.&lt;/li&gt;
&lt;li&gt;Claude receives the system instructions, the available tool definitions, and the conversation history as part of the request context.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This has two direct consequences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Every word in a description costs tokens.&lt;/strong&gt; If your tool definitions total 20 KB, that payload must be processed across requests, and the cost compounds over a long conversation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A tool description can reference neighboring tools.&lt;/strong&gt; Because the model sees the available definitions together, &lt;code&gt;AskUserQuestion&lt;/code&gt; can say, for example, “Do not use this to ask whether the plan is OK; that is &lt;code&gt;ExitPlanMode&lt;/code&gt;'s responsibility.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is why a good tool description must be both &lt;strong&gt;short and precise&lt;/strong&gt;. Short saves tokens; precise ensures that every sentence defines a responsibility, boundary, or collaboration contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Claude Calls a Tool
&lt;/h2&gt;

&lt;p&gt;A tool call is a &lt;strong&gt;message round trip&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: The Model Emits a &lt;code&gt;tool_use&lt;/code&gt; Block
&lt;/h3&gt;

&lt;p&gt;When Claude decides to use a tool, it does not execute the tool directly. Instead, it emits a special block in its response:&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;"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;"tool_use"&lt;/span&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;"toolu_01A09q90qw90lq917835lq9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"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;"AskUserQuestion"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"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;"questions"&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;"question"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Which authentication method should we use?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"header"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Auth method"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"options"&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;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"JWT (Recommended)"&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;"Stateless and easy to scale horizontally"&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;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Session cookie"&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;"Uses a server-side session store"&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;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"OAuth"&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;"Connects to a third-party identity provider"&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;h3&gt;
  
  
  Step 2: The Harness Intercepts and Executes It
&lt;/h3&gt;

&lt;p&gt;The harness intercepts the model's output, finds the implementation associated with &lt;code&gt;name&lt;/code&gt;, and passes it the &lt;code&gt;input&lt;/code&gt;. That implementation might be a local function, an external service, or a UI interaction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: The Harness Returns a &lt;code&gt;tool_result&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;After execution, the harness sends the result back to the model:&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;"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;"tool_result"&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_use_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;"toolu_01A09q90qw90lq917835lq9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The user selected: JWT (Recommended)"&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 block is included in the next message sent to Claude. Claude then continues: it may call another tool based on the result, or it may respond to the user in plain text.&lt;/p&gt;

&lt;p&gt;Throughout the process, the model is the &lt;strong&gt;decision-maker&lt;/strong&gt;. It decides when to call a tool, which tool to call, what arguments to pass, and how to use the result. The harness is responsible for execution and for carrying messages between the model and the tool implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two Tool-Result Modes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Success
&lt;/h3&gt;

&lt;p&gt;A successful &lt;code&gt;tool_result&lt;/code&gt; carries content:&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;"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;"tool_result"&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_use_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;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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 content may be plain text or structured content blocks, such as multiple text segments and images.&lt;/p&gt;

&lt;h3&gt;
  
  
  Failure
&lt;/h3&gt;

&lt;p&gt;A failed result adds &lt;code&gt;is_error: true&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;"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;"tool_result"&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_use_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;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Error: file not found"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"is_error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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 is a &lt;strong&gt;loud failure&lt;/strong&gt;: the error is not silently swallowed. The model can see the failure and decide what to do next—retry, choose a different approach, or ask the user.&lt;/p&gt;

&lt;p&gt;This is also why strict schema validation matters. A harness can reject invalid input explicitly instead of allowing the model to continue with an empty or semantically ambiguous result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tool Results Consume Context Too
&lt;/h2&gt;

&lt;p&gt;Every &lt;code&gt;tool_result&lt;/code&gt; returned to the model becomes part of the conversation context. That means result size &lt;strong&gt;must be controlled&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;grep&lt;/code&gt; result containing 100,000 lines can exhaust the context window almost instantly.&lt;/li&gt;
&lt;li&gt;Good tools summarize, truncate, or paginate their output before returning it.&lt;/li&gt;
&lt;li&gt;A read tool might default to a fixed number of lines; a search tool might expose a result limit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This explains why many of Claude Code's read-oriented tools return deliberately compact results. It is not a lack of capability; it is intentional &lt;strong&gt;context-budget management&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools Are Structured Prompt Engineering
&lt;/h2&gt;

&lt;p&gt;Compare two approaches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free-form prompt version:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can call a function named AskUserQuestion to ask the user a question. After the user chooses, you will receive the answer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Tool version:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt; = &lt;code&gt;AskUserQuestion&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;description&lt;/code&gt; = detailed behavioral constraints&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;input_schema&lt;/code&gt; = exact field types, validation rules, and examples&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The difference is not whether the function can be implemented. The difference is whether it can behave &lt;strong&gt;reliably&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Free-form prompt&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Structure&lt;/td&gt;
&lt;td&gt;The model improvises&lt;/td&gt;
&lt;td&gt;JSON Schema provides hard constraints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failure&lt;/td&gt;
&lt;td&gt;Malformed output may fail silently or produce a bad value&lt;/td&gt;
&lt;td&gt;Schema validation rejects it explicitly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Boundaries&lt;/td&gt;
&lt;td&gt;The model decides based on intuition&lt;/td&gt;
&lt;td&gt;The description states when to use and not use it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Composition&lt;/td&gt;
&lt;td&gt;The model must remember how several functions relate&lt;/td&gt;
&lt;td&gt;Tool descriptions can reference neighboring tools directly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Main-loop visibility&lt;/td&gt;
&lt;td&gt;Results are mixed into conversational text&lt;/td&gt;
&lt;td&gt;Structured &lt;code&gt;tool_use&lt;/code&gt; and &lt;code&gt;tool_result&lt;/code&gt; blocks can be intercepted by the harness&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A tool is, fundamentally, &lt;strong&gt;structured prompt engineering&lt;/strong&gt;. It turns the soft requirement “make the model do this reliably” into a specification that is validatable, composable, and maintainable.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Comes Next
&lt;/h2&gt;

&lt;p&gt;With the mechanism established, every later post in this series will use the same outline to dissect one concrete tool:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Purpose&lt;/li&gt;
&lt;li&gt;A concrete example, including a counterexample&lt;/li&gt;
&lt;li&gt;Trigger conditions&lt;/li&gt;
&lt;li&gt;Technical implementation across four layers

&lt;ul&gt;
&lt;li&gt;Naming&lt;/li&gt;
&lt;li&gt;Tool-level description&lt;/li&gt;
&lt;li&gt;Field-level descriptions&lt;/li&gt;
&lt;li&gt;Schema validation rules&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Division of responsibility with neighboring tools&lt;/li&gt;
&lt;li&gt;Takeaway&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This prelude explains the &lt;strong&gt;mechanism&lt;/strong&gt;: what tools are and how Claude uses them. The rest of the series focuses on &lt;strong&gt;design&lt;/strong&gt;: how a specific tool uses all four layers to turn a capability from merely “possible” into something stable, predictable, and composable.&lt;/p&gt;

&lt;p&gt;Next: &lt;strong&gt;AskUserQuestion&lt;/strong&gt;—how Claude Code turns “AI asking a question” into a structured interaction primitive.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>claudecode</category>
      <category>programming</category>
    </item>
    <item>
      <title>Claude Code Tools Deep Dive #1 — AskUserQuestion</title>
      <dc:creator>Zhengxin</dc:creator>
      <pubDate>Tue, 28 Jul 2026 15:20:18 +0000</pubDate>
      <link>https://dev.to/_94be737e156beb4d74df2/claude-code-tools-deep-dive-1-askuserquestion-4ck1</link>
      <guid>https://dev.to/_94be737e156beb4d74df2/claude-code-tools-deep-dive-1-askuserquestion-4ck1</guid>
      <description>&lt;p&gt;I've spent some time reverse-engineering the design of &lt;a href="https://www.anthropic.com/claude-code" rel="noopener noreferrer"&gt;Claude Code&lt;/a&gt; and even wrote a stripped-down Java clone — open source at &lt;a href="https://github.com/diaozxin007/jooj" rel="noopener noreferrer"&gt;jooj&lt;/a&gt;. One thing that keeps striking me: &lt;strong&gt;every tool Claude Code ships with is carefully designed.&lt;/strong&gt; So I'm starting a series to unpack them one by one.&lt;/p&gt;

&lt;p&gt;This first post is about &lt;strong&gt;AskUserQuestion&lt;/strong&gt; — one of the most commonly seen tools, and one whose design is easy to underestimate.&lt;/p&gt;

&lt;h2&gt;
  
  
  What AskUserQuestion Actually Is
&lt;/h2&gt;

&lt;p&gt;AskUserQuestion is Claude Code's built-in &lt;strong&gt;structured question tool&lt;/strong&gt;. Instead of Claude emitting a plain-text question and waiting for the user to type back, this tool renders the question as an &lt;strong&gt;interactive selection panel&lt;/strong&gt; — the user sees a set of predefined options (as cards), not a wall of text.&lt;/p&gt;

&lt;p&gt;The core problem it solves is &lt;strong&gt;efficient alignment between AI and user&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Lowers user effort&lt;/strong&gt; — clicking an option is faster than typing a reply&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured input&lt;/strong&gt; — Claude gets an unambiguous enum value, no natural-language parsing needed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Converges ambiguity&lt;/strong&gt; — the preset options force a choice among concrete alternatives instead of a vague "you decide"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escape hatch&lt;/strong&gt; — the system always appends an implicit "Other" option so users are never boxed in&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A Concrete Example
&lt;/h2&gt;

&lt;p&gt;Before diving into triggers, implementation, and prompt details, let's ground everything with a real scenario. Compare "life without AskUserQuestion" vs "life with it."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; the user tells Claude &lt;strong&gt;"help me add user login to this app."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That request is severely under-specified — no decision on auth method, no decision on where to store the credential. Claude can't just guess (the team might have conventions), and it can't infer from the code either (it's a new feature with no precedent).&lt;/p&gt;

&lt;h3&gt;
  
  
  The Anti-Pattern: What Happens Without AskUserQuestion
&lt;/h3&gt;

&lt;p&gt;Claude can only throw the question back as a plain-text prompt, something like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Which auth method do you want? I'd suggest JWT, but session cookies or OAuth also work. Also, where should we store the credential — httpOnly cookie or localStorage?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The user immediately hits several problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;High cognitive load&lt;/strong&gt; — one paragraph packs in 2 decisions and 5 options; the user has to parse the question before answering&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High answer cost&lt;/strong&gt; — they either type a reply ("JWT + httpOnly") or spend two hours Googling "JWT vs session cookies" before coming back&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High parsing cost for Claude&lt;/strong&gt; — a reply like "let's go with JWT, and the cookie one" forces Claude to figure out which option the user actually picked, with room for misinterpretation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recommendation drowns in text&lt;/strong&gt; — Claude says "I'd suggest JWT" but it's blended into the paragraph, easy to miss&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No fallback&lt;/strong&gt; — if the user wants an option Claude didn't list (e.g. magic email links), they have to break out with a separate explanation or accept being funneled into a three-way choice&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The core pain:&lt;/strong&gt; free-text form turns "collaborative alignment" into an expensive natural-language round-trip.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix: How AskUserQuestion Solves It
&lt;/h3&gt;

&lt;p&gt;Claude constructs a single call containing &lt;strong&gt;two questions&lt;/strong&gt;. The user sees two cards like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question 1&lt;/strong&gt; — Auth method&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%2Fjxh20b3oeknnmykpvrs1.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%2Fjxh20b3oeknnmykpvrs1.png" alt="Question 1" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question 2&lt;/strong&gt; — Credential storage&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%2Fohy71em7p1l3asccjpg4.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%2Fohy71em7p1l3asccjpg4.png" alt="Question 2" width="800" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each card has a short chip label at the top ("Auth method" / "Token storage"), followed by 3 / 2 options, plus an automatically appended "Other". Two clicks and Claude receives roughly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Question 1 → user picked &lt;strong&gt;JWT (Recommended)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Question 2 → user picked &lt;strong&gt;httpOnly cookie (Recommended)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Decision time compressed from minutes to seconds.&lt;/strong&gt; That's the point of AskUserQuestion — not "let the AI ask a question," but "make every clarification in the collaboration cheap."&lt;/p&gt;

&lt;h3&gt;
  
  
  Side-by-Side: Each Pain Point Solved
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Anti-pattern pain&lt;/th&gt;
&lt;th&gt;AskUserQuestion's fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;High cognitive load&lt;/td&gt;
&lt;td&gt;Split into 2 independent cards, one decision at a time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High answer cost&lt;/td&gt;
&lt;td&gt;Click instead of type; trade-offs sit right under each option&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High parsing cost for Claude&lt;/td&gt;
&lt;td&gt;Return value is an explicit label — no NL parsing needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recommendation drowns in text&lt;/td&gt;
&lt;td&gt;"(Recommended)" suffix + first position — impossible to miss&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No fallback&lt;/td&gt;
&lt;td&gt;"Other" is auto-appended; a custom answer is always one field away&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every design decision below traces back to exactly one of these pains. Keep this mapping in mind — you'll see each constraint in the tool description addressing a specific row in this table.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Fire It
&lt;/h2&gt;

&lt;p&gt;The tool description spells out the boundary: &lt;strong&gt;only when you're blocked, and only when the decision is genuinely the user's.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three "yes, ask" situations:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Can't infer from the request&lt;/strong&gt; — the requirement itself is vague (e.g. "add login" with no auth method specified)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can't infer from the code&lt;/strong&gt; — there's no existing pattern to mimic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No sensible default&lt;/strong&gt; — the choice involves taste, business rules, or architectural forks that AI shouldn't decide unilaterally&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Three "no, don't ask" situations:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The answer is in the code&lt;/strong&gt; — spend time reading, don't interrupt the user&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only one obviously reasonable path&lt;/strong&gt; — just do it, explain in the commit message&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In plan mode asking "is my plan OK?"&lt;/strong&gt; — that's ExitPlanMode's job, using Ask here is a duplication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A canonical anti-pattern: &lt;strong&gt;avoid meta-questions like "does this plan look good?" or "can I proceed?"&lt;/strong&gt;. ExitPlanMode already exists to request approval — using Ask for the same purpose is pure redundancy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Schema Design
&lt;/h2&gt;

&lt;p&gt;Reverse-engineering from the tool's input schema, the core structure looks like this:&lt;/p&gt;

&lt;p&gt;Claude passes in a &lt;strong&gt;list of questions&lt;/strong&gt; (1 to 4). Each question object has four parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;question&lt;/strong&gt; — the full question text, ending with a &lt;code&gt;?&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;header&lt;/strong&gt; — a very short chip label displayed at the top of the card (max 12 chars)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;multiSelect&lt;/strong&gt; — boolean; whether multiple options can be selected (default false)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;options&lt;/strong&gt; — a list of 2 to 4 options&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each option object has three fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;label&lt;/strong&gt; — the display text the user sees (1 to 5 words)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;description&lt;/strong&gt; — an explanation of what the option means / the trade-off&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;preview&lt;/strong&gt; — optional; when the difference between options needs visual comparison (mockups, code snippets), this content is rendered when the option is focused&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few key design choices:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;1–4 questions per call&lt;/strong&gt; — supports batched decisions (like "auth method + token storage" in one call), but prevents Claude from bombarding the user with 10 questions at once&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2–4 options per question&lt;/strong&gt; — forces Claude to pre-categorize, converging N possibilities into a small set of clickable choices instead of dumping a long list&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Other" is implicit&lt;/strong&gt; — auto-appended by the UI, Claude doesn't hand-list it. This guarantees "options Claude thought of ≠ complete space" doesn't trap the user&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recommendation mechanism&lt;/strong&gt; — if Claude has a preference, put it first + append "(Recommended)" to the label. The user spots it at a glance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Return value shape&lt;/strong&gt; — keyed by question text, mapped to the selected label; a separate &lt;code&gt;annotations&lt;/code&gt; field carries user notes for preview-based options&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The preview field&lt;/strong&gt; is a subtle-but-powerful escalation — when options differ visually (two UI mockups, two code styles), embedding the visual in &lt;code&gt;preview&lt;/code&gt; lets the UI render it live as the option gets focus. Perfect for "which API shape" or "which layout" questions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Division of labor with EnterPlanMode / ExitPlanMode:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In plan mode: use AskUserQuestion to clarify "which approach" (before finalizing)&lt;/li&gt;
&lt;li&gt;In plan mode: do NOT use AskUserQuestion to ask "is my plan ready?" (use ExitPlanMode)&lt;/li&gt;
&lt;li&gt;Outside plan mode: use AskUserQuestion for any technical fork that needs user judgment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The three tools form a complete decision pipeline: &lt;strong&gt;Ask clarifies → EnterPlanMode expands → ExitPlanMode commits.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prompt Breakdown
&lt;/h2&gt;

&lt;p&gt;Every sentence in the tool description encodes a behavior constraint. Let's decompose them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constraint 1: Strict applicability boundary (opening sentence)&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use this tool only when you are blocked on a decision that is genuinely the user's to make: one you cannot resolve from the request, the code, or sensible defaults.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This trains Claude to &lt;strong&gt;not interrupt&lt;/strong&gt; — when uncertain, the first move should be to check the code and try sensible defaults, not throw a question at the user.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constraint 2: Making the "Other" escape hatch transparent&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Users will always be able to select "Other" to provide custom text input&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of hiding "Other" from Claude and letting it invent a custom option, the tool description states outright: "Other is auto-added; you don't list it." This prevents Claude from wasting one of its 2–4 option slots on a hand-rolled "custom" entry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constraint 3: multiSelect semantics&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use multiSelect: true to allow multiple answers to be selected for a question&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Use cases: pick multiple feature flags / multiple environments / multiple files to modify. Defaulting to &lt;code&gt;false&lt;/code&gt; protects users from decision paralysis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constraint 4: How to express a recommendation&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Interesting design point: &lt;strong&gt;the recommendation isn't a separate field — it's encoded via convention (position + suffix).&lt;/strong&gt; The benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keeps the schema simple; no &lt;code&gt;recommended: true&lt;/code&gt; boolean field&lt;/li&gt;
&lt;li&gt;The UI just renders the label; no special-case handling&lt;/li&gt;
&lt;li&gt;Claude's endorsement must be &lt;strong&gt;visible in the label&lt;/strong&gt; — impossible to hide in metadata, the user sees it immediately&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Constraint 5: Temporal ordering with plan mode&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Plan mode note: To switch into plan mode, use EnterPlanMode (not this tool). Once in plan mode, use this tool to clarify requirements or choose between approaches BEFORE finalizing your plan. Do NOT use this tool to ask "Is my plan ready?", "Should I proceed?", or otherwise reference "the plan" in questions — the user cannot see the plan until you call ExitPlanMode for approval.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the most instructive passage — it locks in the &lt;strong&gt;temporal ordering&lt;/strong&gt; of the workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In plan mode: use Ask to clarify approach forks (e.g. "A or B?")&lt;/li&gt;
&lt;li&gt;Once clarified: use EnterPlanMode to draft a full plan&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Finally&lt;/strong&gt;: use ExitPlanMode to request approval — &lt;strong&gt;do NOT&lt;/strong&gt; loop back to Ask with "OK to proceed?"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Especially note the last clause — &lt;strong&gt;"the user cannot see the plan until you call ExitPlanMode for approval"&lt;/strong&gt; — this is the &lt;em&gt;real reason&lt;/em&gt; you shouldn't ask "is my plan OK?" in plan mode. It's not just redundancy: the user literally has nothing to approve until ExitPlanMode fires.&lt;/p&gt;

&lt;p&gt;Three tools, each with a distinct role: &lt;strong&gt;Ask (clarify) / EnterPlanMode (expand) / ExitPlanMode (commit)&lt;/strong&gt;. The constraint fundamentally prevents Claude from looping back into Ask to serve as its own approval mechanism.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constraint 6: The &lt;code&gt;header&lt;/code&gt; chip is mandatory (enforced at the schema layer)&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Very short label displayed as a chip/tag (max 12 chars). Examples: "Auth method", "Library", "Approach".&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A UX constraint — the UI renders each question as a card with a chip at the top. The chip uses &lt;code&gt;header&lt;/code&gt;, not the full question text. This forces Claude to condense a long question ("Which authentication method should we use for the login flow?") into a tight chip ("Auth method").&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constraint 7: Questions must end with a question mark&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Should be clear, specific, and end with a question mark.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Looks trivial, but it shapes the UI's tone — a question form vs a statement form triggers a completely different psychological response. Indirectly, this forces Claude to phrase the content as a &lt;strong&gt;genuine query&lt;/strong&gt;, not a disguised instruction.&lt;/p&gt;




&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;The elegance of AskUserQuestion isn't in the surface feature "let the AI ask users questions." It's in how the schema constraints + prompt constraints together lock down &lt;strong&gt;when to ask / how to ask / how it's rendered / how it composes with other tools&lt;/strong&gt;. It takes the general-purpose capability "AI asking questions" and refines it into a &lt;strong&gt;predictable, composable, maintainable interaction primitive&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How can I do，let more people read My post?</title>
      <dc:creator>Zhengxin</dc:creator>
      <pubDate>Sat, 25 Jul 2026 17:06:23 +0000</pubDate>
      <link>https://dev.to/_94be737e156beb4d74df2/how-can-i-dolet-more-people-read-my-post-13nc</link>
      <guid>https://dev.to/_94be737e156beb4d74df2/how-can-i-dolet-more-people-read-my-post-13nc</guid>
      <description></description>
    </item>
    <item>
      <title>From One-Shot LLM to Multi-Turn Agent: How I Rebuilt My Text-to-Diagram Tool</title>
      <dc:creator>Zhengxin</dc:creator>
      <pubDate>Sat, 25 Jul 2026 16:57:24 +0000</pubDate>
      <link>https://dev.to/_94be737e156beb4d74df2/from-one-shot-llm-to-multi-turn-agent-how-i-rebuilt-my-text-to-diagram-tool-204l</link>
      <guid>https://dev.to/_94be737e156beb4d74df2/from-one-shot-llm-to-multi-turn-agent-how-i-rebuilt-my-text-to-diagram-tool-204l</guid>
      <description>&lt;h2&gt;
  
  
  The problem: one LLM call isn't enough
&lt;/h2&gt;

&lt;p&gt;I built an AI tool that turns natural language into editable diagrams. You describe a flow, an LLM generates Mermaid code, and the result renders in real time.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;v1&lt;/strong&gt; was a single LLM call: &lt;code&gt;user input → LLM → diagram&lt;/code&gt;. After a few days in production, two failure modes kept showing up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Syntax errors with no recovery.&lt;/strong&gt; The generated Mermaid code &lt;em&gt;looks&lt;/em&gt; correct, but Mermaid throws a &lt;code&gt;Parse error&lt;/code&gt; and the user sees a red stack trace. They leave.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Silent semantic drift.&lt;/strong&gt; The user asks for "a login flow" — the LLM helpfully adds a "send verification code" actor. It doesn't ask. It doesn't tell you it added anything.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neither problem can be reliably fixed by "tweaking the prompt." The first needs &lt;strong&gt;a second chance&lt;/strong&gt;; the second needs &lt;strong&gt;an audit trail&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So v2 became an &lt;strong&gt;agent&lt;/strong&gt;: multi-turn dialogue, self-correction, and — critically — a memory of what the user said and didn't say. This post is about what that agent actually looks like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core insight: this isn't one loop, it's two
&lt;/h2&gt;

&lt;p&gt;What looks like "a multi-turn diagram generator" is actually two loops with different goals:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Outer loop · Understand the request
User speaks → extract facts → detect gaps → ask → refine

Inner loop · Generate and repair
Structured spec → generate code → validate → fix → output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The outer loop asks, &lt;strong&gt;"Do I understand the request well enough?"&lt;/strong&gt; The inner loop asks, &lt;strong&gt;"Is the generated code correct?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Trying to do both in one loop leads to the question &lt;strong&gt;"should the agent ask the user about this ambiguity?"&lt;/strong&gt; — a question with no answer, because outer-loop ambiguity (user hasn't specified) and inner-loop ambiguity (generation went off-script) are fundamentally different.&lt;/p&gt;

&lt;h2&gt;
  
  
  The agent is a team — divide the work
&lt;/h2&gt;

&lt;p&gt;I model the agent as &lt;strong&gt;a law firm handling a case&lt;/strong&gt;. Each role does exactly one thing:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Does&lt;/th&gt;
&lt;th&gt;Does NOT&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Clerk&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Records facts the user explicitly stated&lt;/td&gt;
&lt;td&gt;Never guesses or infers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auditor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Notes which fields in the record are empty&lt;/td&gt;
&lt;td&gt;Doesn't decide whether to ask&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Planner&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Decides whether/what to ask the user&lt;/td&gt;
&lt;td&gt;Doesn't ask directly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lawyer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Drafts Mermaid, filling reasonable gaps&lt;/td&gt;
&lt;td&gt;Leaves assumptions unrecorded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reviewer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Checks syntax + flags unauthorized additions&lt;/td&gt;
&lt;td&gt;Rewrites the user's requirements&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Front Desk&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Sequences the roles, maintains the case file&lt;/td&gt;
&lt;td&gt;Makes no judgment calls&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Initially I stuffed all of this into a single mega-prompt. Debugging was hell — I couldn't tell whether the &lt;strong&gt;Clerk hallucinated a fact&lt;/strong&gt; or whether the &lt;strong&gt;Lawyer improvised a character&lt;/strong&gt;. Splitting them out means each role is a pure function: same input → same output, testable in isolation.&lt;/p&gt;

&lt;h3&gt;
  
  
  The call graph: Front Desk orchestrates everyone
&lt;/h3&gt;

&lt;p&gt;The six roles don't operate in parallel — they're a pipeline, and &lt;strong&gt;Front Desk is the sole orchestrator&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User message
    ↓
  Front Desk  (append to conversation history)
    ↓
  Clerk    ──→ extract facts from history, populate the case file
    ↓
  Auditor  ──→ list which fields are still empty
    ↓
  Planner  ──→ decide next action using (missing list + budget + past questions)
    │
    ├─ "Ask one"     ──→ Front Desk renders question ──→ User
    │                                 ↑  (next turn loops back to top)
    │
    └─ "We have enough" ──→ Lawyer  ──→ generate Mermaid code
                                          ↓
                                    Reviewer · syntax check
                                          │
                                          ├─ FAIL ──→ inner repair loop (back to Lawyer)
                                          │
                                          └─ OK   ──→ Reviewer · semantic check
                                                          ↓
                                                    Unauthorized additions?
                                                          │
                                                    ├─ Yes → diagram + follow-up question
                                                    │
                                                    └─ No  → diagram only
                                                              ↓
                                                             User
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few points worth noting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Front Desk is the only stateful component.&lt;/strong&gt; Every other role is a pure function. Multi-turn memory lives entirely in the case file that Front Desk maintains.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Planner is the only branching point.&lt;/strong&gt; The agent's "ask vs draw" decision happens in one function, nowhere else.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The inner repair loop runs between Lawyer and Reviewer&lt;/strong&gt; without bothering the user. Mermaid syntax self-healing lives here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Semantic issues don't block output&lt;/strong&gt; — they're delivered &lt;em&gt;alongside&lt;/em&gt; the diagram ("here's your diagram, by the way, I added this thing — want to keep it?"). Users find it easier to judge with the picture in front of them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The foundation rule: Clerk is conservative, Lawyer can improvise
&lt;/h3&gt;

&lt;p&gt;If you take one thing away from this post, take this.&lt;/p&gt;

&lt;p&gt;User says: &lt;em&gt;"Draw a login flow. User enters password, system verifies, returns result."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Clerk&lt;/strong&gt; outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;actors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;enter password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;return result&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="nx"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unknown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;    &lt;span class="c1"&gt;// ← user didn't say sync/async. NEVER guess.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;sync: "unknown"&lt;/code&gt; is the &lt;strong&gt;signal that triggers a question&lt;/strong&gt; — the Auditor flags it, the Planner decides whether to ask.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If the Clerk "helpfully" fills it in&lt;/strong&gt; ("login is usually sync"), that signal is destroyed. The agent can no longer distinguish "user actually said sync" from "I made it up." Every follow-up decision downstream is corrupted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Lawyer operates under a different constraint:&lt;/strong&gt; it may fill in a "verification service" as a reasonable assumption, but that assumption &lt;strong&gt;must be written to the case file's &lt;code&gt;assumptions&lt;/code&gt; slot&lt;/strong&gt;. Later the Reviewer reconciles every element in the diagram: it must trace back to either "the user said this" or "the Lawyer assumed this." Anything that traces to neither is called an &lt;strong&gt;unauthorized addition&lt;/strong&gt;, and it becomes a follow-up question ("I added X. Keep it?").&lt;/p&gt;

&lt;p&gt;This one rule solves a class of nasty bugs by itself — including the classic "user said 'no X', LLM keeps re-adding X on regeneration." Because unauthorized additions are &lt;em&gt;detectable&lt;/em&gt;, the agent surfaces them proactively instead of leaving the user to catch them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Planner: one function, one decision
&lt;/h2&gt;

&lt;p&gt;My favorite architectural decision: &lt;strong&gt;every "should we ask the user?" judgment lives in a single pure function&lt;/strong&gt; — the Planner.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auditor and Reviewer &lt;strong&gt;only identify problems&lt;/strong&gt; — what's missing, what's wrong.&lt;/li&gt;
&lt;li&gt;Planner &lt;strong&gt;takes three inputs&lt;/strong&gt;: candidate question pool, remaining budget, and past questions asked.&lt;/li&gt;
&lt;li&gt;Planner &lt;strong&gt;outputs one of three&lt;/strong&gt;: &lt;code&gt;AskOne&lt;/code&gt; / &lt;code&gt;ProceedToDraw&lt;/code&gt; / &lt;code&gt;AskConfirm&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each session has a &lt;strong&gt;global budget&lt;/strong&gt; (say, 5 agent-initiated questions). Note the framing: &lt;strong&gt;only the agent's proactive questions consume the budget.&lt;/strong&gt; User-initiated changes — modifying the spec, tweaking the diagram, requesting a redraw — do not consume it. This prevents the kind of UX where users become more reluctant to speak the longer they use the tool.&lt;/p&gt;

&lt;p&gt;The practical payoff: &lt;strong&gt;want to change ask frequency or budget policy? Edit one function.&lt;/strong&gt; No other component moves.&lt;/p&gt;

&lt;h2&gt;
  
  
  A walkthrough — 4 turns of dialogue
&lt;/h2&gt;

&lt;p&gt;Architecture is easier when you see it in motion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Turn 1  User: "Draw a user registration sequence diagram"
        Clerk    → { actors: ["user"], events: [], sync: unknown }
        Auditor  → missing: actors / events / sync
        Planner (budget=5) → ask actors
        Agent: "Besides the user, which other roles are involved?"
        [budget: 5 → 4]

Turn 2-3  User: frontend / backend / database, plus each step
          Planner asks per turn, budget: 4 → 3 → 2

Turn 4  User: "Just draw it and see"  ← skip clarification, no budget cost
        Lawyer  gen #1 → helpfully adds "send email notification" (never mentioned)
        Reviewer syntax check → FAIL (undeclared email actor)
        Inner repair loop → Lawyer gen #2, drops email → syntax OK
        Reviewer semantic check → 3 response arrows not grounded in the case file
                                → unauthorized additions
        Output: diagram + prompt "I added a full response flow. Keep it?"

Turn 5  User: "No responses. Just draw up to the database write."
        Agent records "response flow" as a negative fact (explicitly rejected)
        Regenerate → no response arrows
        [budget unchanged — this is user reviewing output, not agent asking]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5-unit budget, 3 agent-initiated questions used, 2 in reserve.&lt;/strong&gt; That's the flexibility of a global budget with clean semantics.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it takes to add a new diagram type
&lt;/h2&gt;

&lt;p&gt;The system supports 8 diagram types: Sequence · Flowchart · ERD · State · Class · Mindmap · Gantt · Architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding a new type&lt;/strong&gt; means implementing four type-specific pieces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Clerk&lt;/strong&gt; — how to extract facts from natural language for this type&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auditor&lt;/strong&gt; — which fields are required vs optional&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reviewer&lt;/strong&gt; — what counts as an unauthorized addition&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Question templates&lt;/strong&gt; — how to phrase prompts (a sequence diagram asks about "actors", a class diagram asks about "entities")&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Planner / Front Desk / state store don't move&lt;/strong&gt; — they don't care what type of diagram is being drawn.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three takeaways worth stealing
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Split the two loops.&lt;/strong&gt; "Understand the request" and "generate the code" are different problems that happen to share state. Fusing them creates the unanswerable "should we ask about this ambiguity?" trap.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clerk conservative + Lawyer improvises, strictly separated.&lt;/strong&gt; If your Clerk fills in gaps, you've handed the agent's judgment to the LLM's intuition. Every Lawyer assumption must be written down so the Reviewer can audit it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;All policy lives in one Planner function.&lt;/strong&gt; Want to change ask cadence, budget policy, or the "when to confirm" heuristic? One file. Zero downstream ripples.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;I'm currently working on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auto-classification confidence calibration (when the user doesn't state the diagram type, how often does the LLM guess wrong?)&lt;/li&gt;
&lt;li&gt;Extending the "unauthorized addition" rule set for each diagram type&lt;/li&gt;
&lt;li&gt;One-click session replay: serialize &lt;code&gt;prompt + spec + generated diagram&lt;/code&gt; into a shareable link, so bug reports can replay the entire agent state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building a similar multi-turn LLM agent — whether for diagrams, SQL, API mocks, or something else — these three principles saved me weeks of pain. &lt;strong&gt;An agent is not just "call the LLM more times."&lt;/strong&gt; It's a team designed to self-correct, remember negative feedback, and produce an audit trail for every decision.&lt;/p&gt;

&lt;p&gt;Try it: &lt;a href="https://text2everything.vip/" rel="noopener noreferrer"&gt;text2everything.vip&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
    </item>
    <item>
      <title>Beyond the IDE: Building an AI-Native Development Workflow with Obsidian</title>
      <dc:creator>Zhengxin</dc:creator>
      <pubDate>Thu, 23 Jul 2026 10:23:52 +0000</pubDate>
      <link>https://dev.to/_94be737e156beb4d74df2/beyond-the-ide-building-an-ai-native-development-workflow-with-obsidian-14mp</link>
      <guid>https://dev.to/_94be737e156beb4d74df2/beyond-the-ide-building-an-ai-native-development-workflow-with-obsidian-14mp</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Code is no longer the primary artifact. Context is.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  1. AI Has Outgrown the IDE: From an IDE to a "Cognitive Layer"
&lt;/h2&gt;

&lt;p&gt;Using IntelliJ IDEA with AI plugins exposes several limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You ask a question, AI generates a code snippet, and you manually review the result.&lt;/li&gt;
&lt;li&gt;Previous conversations with AI are difficult to search.&lt;/li&gt;
&lt;li&gt;As conversations grow longer, the AI loses focus due to accumulated context. Start a new session, and its memory resets—you have to teach it the project all over again.&lt;/li&gt;
&lt;li&gt;A single feature often spans multiple microservices, meaning the implementation lives across several codebases.&lt;/li&gt;
&lt;li&gt;From IDEA's perspective, there's only code. It has no awareness of database schemas, middleware, infrastructure, or architecture documentation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Traditional IDEs are no longer sufficient for AI-assisted software development.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. What Is Obsidian? A Local-First Markdown Knowledge Base
&lt;/h2&gt;

&lt;p&gt;Official website: &lt;a href="https://obsidian.md/" rel="noopener noreferrer"&gt;https://obsidian.md/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Obsidian is a &lt;strong&gt;local-first knowledge management tool built entirely on plain Markdown files&lt;/strong&gt;. Its core strengths include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Local ownership.&lt;/strong&gt; Every note is simply a &lt;code&gt;.md&lt;/code&gt; file stored on your disk. Nothing is locked inside a proprietary cloud service. Everything works offline and remains fully under your control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bidirectional links (Wiki-links).&lt;/strong&gt; &lt;code&gt;[[note-name]]&lt;/code&gt; connects notes into a knowledge graph, while backlinks automatically show every page that references the current one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Graph View.&lt;/strong&gt; Visualize the relationships between notes to understand the structure of your knowledge base at a glance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich plugin ecosystem.&lt;/strong&gt; Community plugins extend Obsidian into a task manager, calendar, Dataview database, AI workspace, and much more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-friendly plain text.&lt;/strong&gt; Since everything is UTF-8 Markdown, AI models can read, write, diff, and edit notes directly—without requiring the specialized plugin bridges typical IDEs need.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Looking back at the pain points of using IDEA with AI, Obsidian addresses every one of them:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;IDEA + AI Problem&lt;/th&gt;
&lt;th&gt;Obsidian Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AI conversations become disposable and difficult to review&lt;/td&gt;
&lt;td&gt;Notes are persistent documents. Every AI edit is preserved, traceable, and reviewable.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Conversation history is hard to search&lt;/td&gt;
&lt;td&gt;Full-text search, backlinks, and tags turn conversations into searchable knowledge assets.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context grows too large, while new sessions lose memory&lt;/td&gt;
&lt;td&gt;Project context is explicitly stored in notes. Simply have the AI read the notes to restore context.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One feature spans multiple microservices&lt;/td&gt;
&lt;td&gt;A single vault can contain documentation for Services A, B, and C, with links connecting them.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IDEA only understands source code&lt;/td&gt;
&lt;td&gt;The vault can hold architecture notes, database schemas, Kafka topics, deployment diagrams, and more alongside the code.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In other words, Obsidian is &lt;strong&gt;not replacing IDEA as your code editor&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It replaces IDEA as your &lt;strong&gt;cognitive layer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You continue writing code inside IDEA, while &lt;strong&gt;everything surrounding the code&lt;/strong&gt;—design decisions, AI conversations, database schemas, architectural diagrams, and cross-service relationships—lives permanently inside Obsidian.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Environment Setup: Obsidian + Claudian
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Install Obsidian and enable community plugins.&lt;/li&gt;
&lt;li&gt;Install the &lt;strong&gt;Claudian&lt;/strong&gt; plugin from GitHub,&lt;a href="https://github.com/YishenTu/claudian" rel="noopener noreferrer"&gt;https://github.com/YishenTu/claudian&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. The Theory: Karpathy's "Wiki as Codebase"
&lt;/h2&gt;

&lt;p&gt;Source: &lt;a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f" rel="noopener noreferrer"&gt;https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f&lt;/a&gt;&lt;br&gt;
Andrej Karpathy's &lt;em&gt;Wiki as Codebase&lt;/em&gt; gist.&lt;/p&gt;

&lt;p&gt;He summarizes the idea in a single sentence:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Obsidian is the IDE; the LLM is the programmer; the wiki is the codebase."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every note you write is no longer just documentation.&lt;/p&gt;

&lt;p&gt;Instead, it becomes part of the &lt;strong&gt;codebase maintained by an LLM&lt;/strong&gt;—except that instead of executable instructions, it stores structured knowledge about your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1 The Three-Layer Architecture
&lt;/h3&gt;

&lt;p&gt;Karpathy divides the system into three layers, corresponding to three types of files inside your vault.&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;Definition&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Raw Sources&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Immutable source material. Read-only for the LLM.&lt;/td&gt;
&lt;td&gt;Meeting notes, PDFs, code diffs, web clippings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;The Wiki&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Markdown pages generated and maintained by the LLM&lt;/td&gt;
&lt;td&gt;Analysis notes, architecture documentation, ADRs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;The Schema&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Rules that make the LLM a disciplined maintainer&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;CLAUDE.md&lt;/code&gt; at the vault root&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The important insight is that &lt;strong&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt; is much more than project instructions.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It acts as the &lt;strong&gt;schema&lt;/strong&gt; governing the knowledge base.&lt;/p&gt;

&lt;p&gt;The schema determines whether the LLM behaves like an ordinary chatbot—or like a disciplined maintainer of a living wiki.&lt;/p&gt;




&lt;h3&gt;
  
  
  4.2 Three Core Operations
&lt;/h3&gt;

&lt;p&gt;Within this wiki, the LLM performs three kinds of work.&lt;/p&gt;

&lt;h4&gt;
  
  
  Ingest
&lt;/h4&gt;

&lt;p&gt;Consume new raw materials, update multiple wiki pages, and maintain cross-references.&lt;/p&gt;

&lt;h4&gt;
  
  
  Query
&lt;/h4&gt;

&lt;p&gt;Search the wiki, synthesize answers, and write valuable results back as new knowledge pages.&lt;/p&gt;

&lt;h4&gt;
  
  
  Lint
&lt;/h4&gt;

&lt;p&gt;Detect inconsistencies, outdated information, orphan pages, and missing links.&lt;/p&gt;

&lt;p&gt;Most people already perform the first two.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Linting is the new capability.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Just as source code benefits from linting, so does your knowledge base.&lt;/p&gt;




&lt;h3&gt;
  
  
  4.3 Why This Is Finally Practical
&lt;/h3&gt;

&lt;p&gt;Organizations have long abandoned internal wikis because &lt;strong&gt;the maintenance cost exceeded the benefit&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Keeping links updated, eliminating contradictions, and maintaining structure simply required too much human effort.&lt;/p&gt;

&lt;p&gt;LLMs remove that bottleneck.&lt;/p&gt;

&lt;p&gt;Humans now focus on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;selecting high-quality source material,&lt;/li&gt;
&lt;li&gt;directing the analysis,&lt;/li&gt;
&lt;li&gt;asking good questions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Meanwhile, the LLM performs all the bookkeeping:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;updating dozens of pages,&lt;/li&gt;
&lt;li&gt;maintaining links,&lt;/li&gt;
&lt;li&gt;synchronizing knowledge,&lt;/li&gt;
&lt;li&gt;resolving inconsistencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The breakthrough isn't that Obsidian became more powerful.&lt;/p&gt;

&lt;p&gt;It's that &lt;strong&gt;the cost of maintaining a wiki has shifted from humans to LLMs.&lt;/strong&gt;&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%2Fopkk45rqt048pxa1c7dj.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%2Fopkk45rqt048pxa1c7dj.png" alt="Three-Layer Architecture" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Workflow: One Vault, One &lt;code&gt;CLAUDE.md&lt;/code&gt;, Four Everyday Habits
&lt;/h2&gt;

&lt;h3&gt;
  
  
  5.1 One Vault per Project
&lt;/h3&gt;

&lt;p&gt;Instead of storing everything in one giant vault, create one vault for each project.&lt;/p&gt;

&lt;p&gt;Place a &lt;code&gt;CLAUDE.md&lt;/code&gt; file at the root containing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;technology stack&lt;/li&gt;
&lt;li&gt;repository structure&lt;/li&gt;
&lt;li&gt;commit conventions&lt;/li&gt;
&lt;li&gt;common pitfalls&lt;/li&gt;
&lt;li&gt;recurring project context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Claudian automatically loads this file whenever a new session starts, eliminating the need to repeatedly explain your project.&lt;/p&gt;




&lt;h3&gt;
  
  
  5.2 Typical Development Workflow
&lt;/h3&gt;

&lt;p&gt;The traditional workflow looked like this:&lt;/p&gt;

&lt;p&gt;Open AI sidebar → Ask a question → Copy code → Close sidebar → Lose context.&lt;/p&gt;

&lt;p&gt;The new workflow becomes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a requirement note containing the background, objectives, and constraints.&lt;/li&gt;
&lt;li&gt;Have the AI read the relevant context by linking architecture docs, database schemas, and previous requirement notes with &lt;code&gt;[[...]]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Collaboratively analyze the problem through conversation.&lt;/li&gt;
&lt;li&gt;Let the AI write important decisions back into the notes.&lt;/li&gt;
&lt;li&gt;Return to IDEA and implement the code.&lt;/li&gt;
&lt;li&gt;Once implementation is complete, record:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;why the design changed,&lt;/li&gt;
&lt;li&gt;lessons learned,&lt;/li&gt;
&lt;li&gt;commit hash.

&lt;ol&gt;
&lt;li&gt;Future work simply reuses these notes as project context.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The mindset changes fundamentally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI output is no longer disposable conversation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It becomes permanent project documentation.&lt;/p&gt;




&lt;h3&gt;
  
  
  5.3 High-Frequency Workflows
&lt;/h3&gt;

&lt;p&gt;Some particularly useful habits include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;@&lt;/code&gt;-reference notes&lt;/strong&gt; to inject documents directly into AI conversations, especially for coordinating across services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Paste code into notes&lt;/strong&gt; and let AI edit it, preserving the entire discussion history.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architecture Decision Records (ADRs)&lt;/strong&gt; with one note per architectural decision, linked together via wiki links.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily Notes&lt;/strong&gt; for debugging and investigation, allowing AI to follow your reasoning process over time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Graph View&lt;/strong&gt; to quickly identify densely connected core modules and isolated knowledge gaps.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  5.4 Division of Responsibilities
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;IntelliJ IDEA&lt;/th&gt;
&lt;th&gt;Obsidian + Claudian&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Coding, debugging, testing&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Breakpoint debugging, profiling&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Requirements analysis&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Architecture design&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database documentation&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long AI conversations&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-service context&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team knowledge sharing&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In short:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IDEA writes the code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Obsidian manages the brain.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Case Study: A Two-Week Refactoring Project
&lt;/h2&gt;

&lt;p&gt;One local project involved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Six implementation phases (P1–P6)&lt;/li&gt;
&lt;li&gt;Four rounds of architectural refactoring&lt;/li&gt;
&lt;li&gt;Fifteen technical decisions (D1–D15)&lt;/li&gt;
&lt;li&gt;Thirteen commits&lt;/li&gt;
&lt;li&gt;Two weeks of continuous work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Managing this entirely inside an IDE would have been nearly impossible.&lt;/p&gt;

&lt;p&gt;Each new AI session would require reconstructing the project's context from scratch.&lt;/p&gt;

&lt;p&gt;Obsidian solved this in five ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A master planning note&lt;/strong&gt; guided every conversation and was continuously updated by the AI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;All fifteen architectural decisions&lt;/strong&gt; were documented, including background, alternatives, final choice, and rationale.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session continuity&lt;/strong&gt; became effortless. On day seven, a simple "Read this note and continue" restored the entire project context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commit hashes&lt;/strong&gt; were written back into the notes, turning them into a living changelog.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lessons learned&lt;/strong&gt; were ultimately incorporated into &lt;code&gt;CLAUDE.md&lt;/code&gt;, allowing future sessions to begin with full project knowledge.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Without this workflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Design decisions would be scattered across dozens of conversations.&lt;/li&gt;
&lt;li&gt;Every new AI session would waste twenty minutes rebuilding context.&lt;/li&gt;
&lt;li&gt;The architectural intent behind each commit would be forgotten within a few months.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The larger and longer a project becomes, the more valuable the Obsidian + Claudian workflow proves to be.&lt;/p&gt;

&lt;p&gt;It isn't just a productivity enhancement.&lt;/p&gt;

&lt;p&gt;It is the infrastructure that makes &lt;strong&gt;long-running, AI-assisted software engineering&lt;/strong&gt; practical.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Practice: Linting Your Obsidian Vault
&lt;/h2&gt;

&lt;p&gt;The most practical habit is to &lt;strong&gt;regularly let AI lint your vault&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Treat your knowledge base the same way you treat your source code.&lt;/p&gt;

&lt;p&gt;Two simple linting tasks provide enormous value.&lt;/p&gt;




&lt;h3&gt;
  
  
  7.1 Dead-Link Scan
&lt;/h3&gt;

&lt;p&gt;Prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Scan the entire vault and find every &lt;code&gt;[[wiki-link]]&lt;/code&gt; whose target file does not exist. Sort the results by reference count. Output the top 30. Ignore image embeds, code blocks, and Templater variables.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The results generally fall into six categories.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Daily note navigation&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[[2026-05-14]]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Usually harmless&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Template placeholders&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[[&amp;lt;% after_date %&amp;gt;]]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ignore&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web clipping artifacts&lt;/td&gt;
&lt;td&gt;URLs or usernames converted into wiki links&lt;/td&gt;
&lt;td&gt;Batch cleanup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Missing concept pages&lt;/td&gt;
&lt;td&gt;Frequently referenced but nonexistent notes&lt;/td&gt;
&lt;td&gt;Create the missing note&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typos&lt;/td&gt;
&lt;td&gt;Incorrect capitalization or trailing characters&lt;/td&gt;
&lt;td&gt;Fix immediately&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Missing MOC pages&lt;/td&gt;
&lt;td&gt;Referenced index pages that don't exist&lt;/td&gt;
&lt;td&gt;Create an index page&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The most valuable category is the fourth.&lt;/p&gt;

&lt;p&gt;Frequently referenced dead links reveal concepts you've repeatedly intended to document—but never actually did.&lt;/p&gt;

&lt;p&gt;They become a concrete to-do list generated by your own knowledge graph.&lt;/p&gt;




&lt;h3&gt;
  
  
  7.2 Orphan Page Scan
&lt;/h3&gt;

&lt;p&gt;Prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Find every note that is never referenced by another note via wiki links. Exclude daily notes, entry pages, &lt;code&gt;CLAUDE.md&lt;/code&gt;, and empty notes. Sort by file size, largest first.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Typical results include:&lt;/p&gt;

&lt;h4&gt;
  
  
  Large orphan clusters
&lt;/h4&gt;

&lt;p&gt;Entire collections—such as book notes or article series—remain disconnected.&lt;/p&gt;

&lt;p&gt;The solution isn't adding one link.&lt;/p&gt;

&lt;p&gt;You likely need a &lt;strong&gt;Map of Content (MOC)&lt;/strong&gt; to organize the entire collection.&lt;/p&gt;

&lt;h4&gt;
  
  
  Orphan entry pages
&lt;/h4&gt;

&lt;p&gt;Pages intended as dashboards or indexes receive no incoming links.&lt;/p&gt;

&lt;p&gt;An entrance nobody reaches isn't an entrance at all.&lt;/p&gt;

&lt;h4&gt;
  
  
  Empty notes
&lt;/h4&gt;

&lt;p&gt;Drafts containing only a title should simply be deleted.&lt;/p&gt;




&lt;h3&gt;
  
  
  7.3 Why Regular Linting Matters
&lt;/h3&gt;

&lt;p&gt;A single lint run provides four concrete benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A prioritized list of missing core notes&lt;/li&gt;
&lt;li&gt;Discovery of structural weaknesses in your knowledge organization&lt;/li&gt;
&lt;li&gt;Cleanup of stale data, typos, and clipping artifacts&lt;/li&gt;
&lt;li&gt;Validation that important entry pages are actually reachable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A practical cadence is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;once per month, or&lt;/li&gt;
&lt;li&gt;after importing a large amount of new material into your vault.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without periodic linting, most vaults eventually become graveyards of broken links and isolated notes.&lt;/p&gt;

&lt;p&gt;With regular linting, every page remains connected, discoverable, and useful.&lt;/p&gt;

&lt;p&gt;This is precisely what Karpathy means by treating a wiki like a codebase.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Conclusion: IDEA Handles the Code; Obsidian + Claudian Handle the Thinking
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IntelliJ IDEA&lt;/strong&gt; remains an excellent code editor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Obsidian&lt;/strong&gt; provides the missing cognitive layer, preserving design intent, AI conversations, architecture, database knowledge, and cross-service context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claudian&lt;/strong&gt; serves as the bridge, allowing AI to directly maintain your knowledge graph rather than acting as a disposable question-and-answer tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt;&lt;/strong&gt; functions as the schema that transforms an LLM from a chatbot into a disciplined knowledge-base maintainer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linting&lt;/strong&gt; is the essential maintenance routine that keeps your vault healthy over the long term.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, they form what can truly be called an &lt;strong&gt;AI-native development environment&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of simply embedding AI into an IDE sidebar, this workflow &lt;strong&gt;reimagines software development around knowledge organization&lt;/strong&gt;, making AI a first-class participant in long-term, complex engineering projects.&lt;/p&gt;

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