<?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: Nishil Bhave</title>
    <description>The latest articles on DEV Community by Nishil Bhave (@nishilbhave).</description>
    <link>https://dev.to/nishilbhave</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%2F2844683%2F408d2867-a0c1-4208-a8ef-1c2149ec8569.jpg</url>
      <title>DEV Community: Nishil Bhave</title>
      <link>https://dev.to/nishilbhave</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nishilbhave"/>
    <language>en</language>
    <item>
      <title>Claude Code Context Window Size: 200K vs 1M, What Fills It</title>
      <dc:creator>Nishil Bhave</dc:creator>
      <pubDate>Tue, 04 Aug 2026 15:49:42 +0000</pubDate>
      <link>https://dev.to/nishilbhave/claude-code-context-window-size-200k-vs-1m-what-fills-it-193m</link>
      <guid>https://dev.to/nishilbhave/claude-code-context-window-size-200k-vs-1m-what-fills-it-193m</guid>
      <description>&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%2Fvigx46mqhkjlp1cs3ul5.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%2Fvigx46mqhkjlp1cs3ul5.png" alt="Two bars comparing Claude Code context windows. The same 18,349 tokens of startup configuration fills 9.2 percent of a 200,000 token window and 1.8 percent of a 1,000,000 token window."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first time I paid attention to my context window, it was because Claude Code compacted itself in the middle of a refactor and forgot a convention I had explained twenty minutes earlier. My first instinct was to blame the model. My second was to actually look.&lt;/p&gt;

&lt;p&gt;What I found was worse and more useful: a meaningful slice of the window was already spent before I typed a single character. Not on my code. On my own configuration.&lt;/p&gt;

&lt;p&gt;That is the part nobody puts in the answer. Search for "Claude Code context window size" and you get a number. The number is the least interesting thing about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Claude Code's context window is &lt;strong&gt;200,000 tokens&lt;/strong&gt; on most models and &lt;strong&gt;1,000,000 tokens&lt;/strong&gt; on Sonnet 5, Opus 4.6 and later, Sonnet 4.6, and Fable 5. On the Anthropic API, Sonnet 5 always runs at 1M with nothing to configure, and it is what the &lt;code&gt;sonnet&lt;/code&gt; alias resolves to. The ceiling is rarely your problem. Your startup footprint is: in my own install, roughly &lt;strong&gt;18,000 tokens&lt;/strong&gt; of system prompt, CLAUDE.md, memory, and skill descriptions load before my first prompt. Run &lt;code&gt;/context&lt;/code&gt; to see yours, and treat installed skills as a recurring tax rather than free capability.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How big is the Claude Code context window?
&lt;/h2&gt;

&lt;p&gt;Claude Code's context window is &lt;strong&gt;200,000 tokens by default&lt;/strong&gt;, and &lt;strong&gt;1,000,000 tokens&lt;/strong&gt; on Fable 5, Sonnet 5, Opus 4.6 and later, and Sonnet 4.6.&lt;/p&gt;

&lt;p&gt;Anthropic's own framing is the useful one here: more context is not automatically better. As token count grows, accuracy and recall degrade, a failure mode &lt;a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents" rel="noopener noreferrer"&gt;Anthropic calls &lt;em&gt;context rot&lt;/em&gt;&lt;/a&gt;. Curating what sits in the window matters at least as much as how much room it has.&lt;/p&gt;

&lt;p&gt;Three details matter more than the headline number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On the Anthropic API, several models are always at 1M.&lt;/strong&gt; Fable 5, Sonnet 5, and Opus 4.7 and later run with the million-token window as their normal state, not as an upgrade you enable. Sonnet 5 is the sharpest case: there is no 200K variant, no &lt;code&gt;[1m]&lt;/code&gt; suffix to select, and no usage credits required on any plan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Auto-compaction fires before the window fills, not when it does.&lt;/strong&gt; Sonnet 5 sessions compact at about 967,000 tokens by default. You can move that with the &lt;a href="https://code.claude.com/docs/en/model-config#sonnet-5-context-window" rel="noopener noreferrer"&gt;&lt;code&gt;CLAUDE_CODE_AUTO_COMPACT_WINDOW&lt;/code&gt;&lt;/a&gt; environment variable. The gap between the ceiling and the trigger is the reserved buffer, and &lt;code&gt;/context&lt;/code&gt; shows it to you as its own slice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two configurations quietly drop Sonnet 5 back to 200K.&lt;/strong&gt; If &lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt; points at an LLM gateway, Claude Code cannot verify 1M support, so it budgets 200K and compacts there instead. Select "Sonnet 5 (1M context)" in the model picker to get the full window back. Setting &lt;code&gt;CLAUDE_CODE_DISABLE_1M_CONTEXT=1&lt;/code&gt; does the same thing on purpose, for deployments that need a hard cap.&lt;/p&gt;

&lt;p&gt;Haiku 4.5 is the outlier that stays at 200K with no extended option.&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%2Flebyd5yitk2gtda67hqi.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%2Flebyd5yitk2gtda67hqi.png" alt="Grouped bar chart of Claude Code context windows by model: Haiku 4.5 is 200K with no upgrade, Sonnet 4.6 and Opus 4.6 default to 200K but reach 1M, and Sonnet 5 and Opus 5 run at 1M by default"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What model does Claude Code use by default?
&lt;/h2&gt;

&lt;p&gt;For most accounts, Claude Code's recommended model is &lt;strong&gt;Sonnet&lt;/strong&gt;, and on the Anthropic API that alias resolves to &lt;strong&gt;Sonnet 5&lt;/strong&gt;. That is the practical answer to the question people actually search for, and it is why the 1M window is now the common case rather than the exception.&lt;/p&gt;

&lt;p&gt;The mechanics underneath are worth knowing, because "default" means two different things in Claude Code. The &lt;code&gt;default&lt;/code&gt; option in the model picker is not itself a model. It is a special value that clears any override and reverts to the recommended model for your account type, or to an organization default if an admin has set one. The &lt;code&gt;sonnet&lt;/code&gt; alias, by contrast, always points at the newest Sonnet your provider offers.&lt;/p&gt;

&lt;p&gt;The full alias list:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Alias&lt;/th&gt;
&lt;th&gt;What it selects&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;default&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Clears overrides, reverts to the account or organization default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;best&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fable 5 where your org has access, otherwise the latest Opus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fable&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Claude Fable 5, for the hardest and longest-running tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sonnet&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Latest Sonnet, for daily coding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;opus&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Latest Opus, for complex reasoning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;haiku&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fast and cheap, for simple tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;sonnet[1m]&lt;/code&gt; / &lt;code&gt;opus[1m]&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;The 1M context variant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;opusplan&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Opus during plan mode, then Sonnet for execution&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Alias resolution is provider-specific, which trips people up more than it should:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;&lt;code&gt;opus&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;sonnet&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Anthropic API&lt;/td&gt;
&lt;td&gt;Opus 5&lt;/td&gt;
&lt;td&gt;Sonnet 5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Platform on AWS&lt;/td&gt;
&lt;td&gt;Opus 5&lt;/td&gt;
&lt;td&gt;Sonnet 4.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Amazon Bedrock, Google Cloud&lt;/td&gt;
&lt;td&gt;Opus 5&lt;/td&gt;
&lt;td&gt;Sonnet 4.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft Foundry&lt;/td&gt;
&lt;td&gt;Opus 4.6&lt;/td&gt;
&lt;td&gt;Sonnet 4.5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So the same &lt;code&gt;/model sonnet&lt;/code&gt; gives you a 1M window on the Anthropic API and a 200K default on Bedrock. If your context math suddenly stops adding up after a provider change, start here.&lt;/p&gt;

&lt;p&gt;Version floors bite too. Opus 5 needs Claude Code v2.1.219 or later, and Sonnet 5 needs v2.1.197. If a model is missing from your picker, run &lt;code&gt;claude update&lt;/code&gt; before debugging anything else.&lt;/p&gt;

&lt;p&gt;You can set the model four ways, in precedence order: &lt;code&gt;/model &amp;lt;alias&amp;gt;&lt;/code&gt; during a session, &lt;code&gt;claude --model &amp;lt;alias&amp;gt;&lt;/code&gt; at startup, the &lt;code&gt;ANTHROPIC_MODEL&lt;/code&gt; environment variable, or the &lt;code&gt;model&lt;/code&gt; field in your settings file. Since v2.1.153, picking in &lt;code&gt;/model&lt;/code&gt; saves your choice as the default for new sessions; press &lt;code&gt;s&lt;/code&gt; in the picker to change it for the current session only.&lt;/p&gt;

&lt;p&gt;One correction worth making, because it circulates constantly: none of this requires a Max plan. Claude Code's entry point is Claude Pro at $20 per month, and the ladder runs Pro $20, Max 5x $100, Max 20x $200.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://maketocreate.com/claude-code-cost-in-2026-honest-pro-vs-max-vs-api-guide/" rel="noopener noreferrer"&gt;the full plan and rate-limit breakdown, including which tier suits sustained agentic work&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually fills the window before you type
&lt;/h2&gt;

&lt;p&gt;Here is the part I care about. Before your first prompt, Claude Code has already loaded the system prompt, your CLAUDE.md files, auto memory, MCP tool names, and a description for every installed skill.&lt;/p&gt;

&lt;p&gt;Anthropic publishes a reference session with representative token counts, and they label those numbers as representative rather than measured, so treat them as a shape rather than a spec: system prompt 4,200, project CLAUDE.md 1,800, auto memory 680, user CLAUDE.md 320, skill descriptions 450, environment info 280, MCP tool names 120. That is roughly 7,850 tokens before anything happens.&lt;/p&gt;

&lt;p&gt;Then I measured my own install, on the machine I write these posts on. Character count divided by four, which is a rough English approximation rather than a real tokenizer pass, so read these as the right order of magnitude and not to the digit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;78 installed skills&lt;/strong&gt; (74 user-level, 4 repo-level): about &lt;strong&gt;9,200 tokens&lt;/strong&gt; of names and descriptions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project CLAUDE.md&lt;/strong&gt;: about &lt;strong&gt;2,338 tokens&lt;/strong&gt; across 103 lines&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto memory (MEMORY.md)&lt;/strong&gt;: about &lt;strong&gt;2,205 tokens&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seven configured MCP servers&lt;/strong&gt;, contributing tool names only, because full schemas are deferred by default&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add Anthropic's figure for the system prompt and environment block and my startup footprint lands near &lt;strong&gt;18,000 tokens&lt;/strong&gt;. On a 200K window that is roughly 9% gone before I say hello. On 1M it is under 2%, which is genuinely the strongest practical argument for the bigger window.&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%2Fq3ybu5cikhw2cclc5aj7.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%2Fq3ybu5cikhw2cclc5aj7.png" alt="Stacked bar chart comparing startup context: Anthropic's reference session uses about 7,850 tokens while the author's install uses about 18,349, with skill descriptions the largest single difference"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The skill count is the lever almost nobody pulls. Every installed skill puts its description into context at session start so the model knows the skill exists, whether or not you ever invoke it. Going from eight skills to seventy-eight is not a free expansion of capability; it is a standing charge on every session you will ever start.&lt;/p&gt;

&lt;p&gt;Two documented fixes exist and both are underused. For skills you invoke by name and never want auto-triggered, set &lt;code&gt;disable-model-invocation: true&lt;/code&gt; in the skill's frontmatter. For skills you did not write and cannot edit, &lt;code&gt;skillOverrides&lt;/code&gt; in settings does the same thing. Either way the description stops loading until you ask for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I check my own context usage?
&lt;/h2&gt;

&lt;p&gt;Everything above is a shape. Your install is the only thing that matters, and &lt;code&gt;/context&lt;/code&gt; is the command that tells you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/context
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It prints a &lt;a href="https://code.claude.com/docs/en/context-window" rel="noopener noreferrer"&gt;live breakdown by category&lt;/a&gt;, names which CLAUDE.md and auto memory files actually loaded, offers optimization suggestions, and shows the reserved autocompact buffer as its own slice. It is the single highest-value command in Claude Code that most people have never run.&lt;/p&gt;

&lt;p&gt;Three companions are worth the muscle memory. &lt;code&gt;/usage&lt;/code&gt; reports session cost and, on a paid plan, attributes recent usage to skills, subagents, plugins, and individual MCP servers, flagging anything that accounts for 10% or more. &lt;code&gt;/mcp&lt;/code&gt; shows per-server cost and lets you disable servers you are not using. &lt;code&gt;/memory&lt;/code&gt; opens the memory files for editing.&lt;/p&gt;

&lt;p&gt;If you want the number in front of you permanently, the status line can display context usage continuously, which beats remembering to check.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does a real session consume the window?
&lt;/h2&gt;

&lt;p&gt;Anthropic's reference session is a useful walkthrough because it accounts for the things you never see. Four file reads, two path-scoped rules loading automatically alongside matching files, a grep, two edits, a prettier hook firing after each one, a test run, a subagent, and a couple of slash commands. Total: about 22,225 tokens.&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%2F65slpg4obiua0ict8g4a.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%2F65slpg4obiua0ict8g4a.png" alt="Waterfall chart of a Claude Code session consuming about 22,225 tokens, with 7,850 loaded automatically at startup before any user prompt and file reads adding a further 6,900"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two things jump out of that shape.&lt;/p&gt;

&lt;p&gt;The first bar is the biggest single contributor and you did not cause it. Startup is 35% of the session's total context here, and in my own install it would be closer to half.&lt;/p&gt;

&lt;p&gt;The subagent bar is almost invisible, and that is the point. It read three files in its own context window and returned a 420-token summary. Had those reads happened in the main conversation they would have cost several thousand tokens that never come back. This is the single most effective context lever Claude Code gives you.&lt;/p&gt;

&lt;p&gt;how to structure subagent delegation so verbose work stays out of your main context&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens when the context window fills up
&lt;/h2&gt;

&lt;p&gt;Claude Code does not fail when you hit the limit. It clears older tool outputs first, then summarizes the conversation if that is not enough. Your requests and key code snippets survive. Detailed instructions from early in the conversation frequently do not, which is exactly the failure I opened this post with.&lt;/p&gt;

&lt;p&gt;There is a wrinkle here that explains a lot of model-to-model difference in long sessions. Sonnet 5, Sonnet 4.6, Sonnet 4.5, and Haiku 4.5 have &lt;a href="https://platform.claude.com/docs/en/build-with-claude/context-windows#context-awareness" rel="noopener noreferrer"&gt;&lt;strong&gt;context awareness&lt;/strong&gt;&lt;/a&gt;: the API injects their remaining token budget into every request, so they can pace a long task against the room that is actually left. Opus 4.7 and later, plus Fable 5, do not get those injected tags. If a Sonnet session feels like it starts wrapping up as the window fills while an Opus session keeps going regardless, that is why, and it is automatic on both sides rather than anything you configure.&lt;/p&gt;

&lt;p&gt;What survives compaction is documented precisely, and the table is worth memorizing:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mechanism&lt;/th&gt;
&lt;th&gt;After compaction&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;System prompt and output style&lt;/td&gt;
&lt;td&gt;Unchanged, never part of message history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Project-root CLAUDE.md, unscoped rules&lt;/td&gt;
&lt;td&gt;Re-injected from disk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auto memory&lt;/td&gt;
&lt;td&gt;Re-injected from disk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rules with &lt;code&gt;paths:&lt;/code&gt; frontmatter&lt;/td&gt;
&lt;td&gt;Lost until a matching file is read again&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nested CLAUDE.md in subdirectories&lt;/td&gt;
&lt;td&gt;Lost until a file in that subdirectory is read again&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Invoked skill bodies&lt;/td&gt;
&lt;td&gt;Re-injected, capped at 5,000 tokens per skill and 25,000 total, oldest dropped first&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hooks&lt;/td&gt;
&lt;td&gt;Unaffected, they run as code rather than context&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The two "lost" rows explain most mystery regressions. A path-scoped rule loads into message history when its trigger file is read, so compaction summarizes it away with everything else. If a rule genuinely must survive, drop the &lt;code&gt;paths:&lt;/code&gt; frontmatter or move it into the project-root CLAUDE.md.&lt;/p&gt;

&lt;p&gt;The skill-truncation row has a practical consequence too: truncation keeps the start of the file, so the most important instructions belong near the top of any &lt;code&gt;SKILL.md&lt;/code&gt; you write.&lt;/p&gt;

&lt;p&gt;One failure mode to recognize. If a single file or tool output is large enough that context refills immediately after each summary, Claude Code stops auto-compacting after a few attempts and shows a thrashing error rather than looping forever. That is a signal to &lt;code&gt;/clear&lt;/code&gt; and change approach, not to retry.&lt;/p&gt;

&lt;p&gt;You can also get ahead of it. &lt;code&gt;/compact focus on the auth bug fix&lt;/code&gt; keeps what you choose instead of what the automatic pass guesses, and a "Compact Instructions" section in CLAUDE.md sets that preference permanently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does the 1M context window cost extra?
&lt;/h2&gt;

&lt;p&gt;Per token, no. The 1M context window uses standard model pricing with no premium for tokens beyond 200K. That is a genuine difference from how long-context pricing has worked elsewhere, and it is easy to miss.&lt;/p&gt;

&lt;p&gt;Availability is the part that varies:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Opus with 1M&lt;/th&gt;
&lt;th&gt;Sonnet 4.6 with 1M&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Max, Team, Enterprise&lt;/td&gt;
&lt;td&gt;Included with subscription&lt;/td&gt;
&lt;td&gt;Requires usage credits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pro&lt;/td&gt;
&lt;td&gt;Requires usage credits&lt;/td&gt;
&lt;td&gt;Requires usage credits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API and pay-as-you-go&lt;/td&gt;
&lt;td&gt;Full access&lt;/td&gt;
&lt;td&gt;Full access&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Sonnet 5 sidesteps the table entirely: on the Anthropic API it runs at 1M on every plan with no credits required.&lt;/p&gt;

&lt;p&gt;The cost that does scale is recurring, and this is where a bigger window quietly gets expensive. Claude Code sends your full conversation with every request, and each tool use sends another request carrying that history. Prompt caching means you re-read it at cached rates rather than full price, but cached is not free. A one-line question in a session that has been open all day still draws usage for the entire conversation.&lt;/p&gt;

&lt;p&gt;Cache misses make it worse. Your first message after a break longer than the cache lifetime reprocesses everything at full price. That lifetime is an hour on a subscription, and five minutes on an API key, a cloud provider, or once you are drawing on usage credits.&lt;/p&gt;

&lt;p&gt;So the honest framing is this: 1M does not make long sessions cheap. It makes them possible. &lt;code&gt;/clear&lt;/code&gt; remains free, and &lt;code&gt;/compact&lt;/code&gt; is itself a large request because it has to read the conversation it summarizes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seven levers that actually reclaim context
&lt;/h2&gt;

&lt;p&gt;In rough order of how much they return for the effort:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/clear&lt;/code&gt; between unrelated tasks.&lt;/strong&gt; Costs nothing and returns everything. Use &lt;code&gt;/rename&lt;/code&gt; first if you might want the session back via &lt;code&gt;/resume&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delegate verbose reads to subagents.&lt;/strong&gt; Log processing, documentation fetches, wide codebase exploration. The output stays in their window; a summary comes back to yours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trim your skills.&lt;/strong&gt; &lt;code&gt;disable-model-invocation: true&lt;/code&gt; for skills you always invoke by name, &lt;code&gt;skillOverrides&lt;/code&gt; for skills you did not write. This was worth roughly 9,000 tokens per session in my install.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep CLAUDE.md under 200 lines.&lt;/strong&gt; &lt;a href="https://code.claude.com/docs/en/costs#reduce-token-usage" rel="noopener noreferrer"&gt;Anthropic's own guidance&lt;/a&gt;. Workflow-specific detail belongs in skills, which load on demand, rather than in a file that loads every session regardless of what you are doing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefer CLI tools over MCP servers.&lt;/strong&gt; &lt;code&gt;gh&lt;/code&gt;, &lt;code&gt;aws&lt;/code&gt;, &lt;code&gt;gcloud&lt;/code&gt;, and &lt;code&gt;sentry-cli&lt;/code&gt; add no per-tool listing at all. MCP schemas are deferred by default, but names still cost something, and &lt;code&gt;/mcp&lt;/code&gt; will show you which servers are worth keeping.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Preprocess with hooks.&lt;/strong&gt; A PreToolUse hook that greps a log for &lt;code&gt;ERROR&lt;/code&gt; before Claude sees it turns tens of thousands of tokens into hundreds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write specific prompts.&lt;/strong&gt; "Improve this codebase" triggers broad scanning. "Add input validation to the login function in auth.ts" does not.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://maketocreate.com/claude-code-mcp-server-configuration-2026-setup-guide/" rel="noopener noreferrer"&gt;configuring MCP servers, including tool search and per-server context cost&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://maketocreate.com/claude-code-plan-mode-how-i-use-it-and-when-i-dont/" rel="noopener noreferrer"&gt;exploring before editing, which keeps file reads purposeful instead of speculative&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this stops and architecture begins
&lt;/h2&gt;

&lt;p&gt;Everything above is Claude Code mechanics: the numbers, the commands, the settings. It is deliberately not a theory of context design.&lt;/p&gt;

&lt;p&gt;If you are building your own agentic system and need the patterns rather than the CLI, that is a different problem with a different shape, covering retrieval, reranking, and where accuracy degrades inside a long window.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://maketocreate.com/context-engineering-architecture-8-stages-from-demo-to-production/" rel="noopener noreferrer"&gt;the architecture-level patterns for designing context-limited systems, from retrieval through compaction&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://maketocreate.com/claude-fable-5-in-claude-code-when-the-2x-model-pays-off/" rel="noopener noreferrer"&gt;the 1M-context model built for long autonomous sessions, and when the extra capability pays&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How big is Claude Code's context window?
&lt;/h3&gt;

&lt;p&gt;200,000 tokens by default, and 1,000,000 tokens on Fable 5, Sonnet 5, Opus 4.6 and later, and Sonnet 4.6. On the Anthropic API, Fable 5, Sonnet 5, and Opus 4.7 and later always run with the 1M window. Haiku 4.5 stays at 200K with no extended option.&lt;/p&gt;

&lt;h3&gt;
  
  
  What model does Claude Code use by default?
&lt;/h3&gt;

&lt;p&gt;Sonnet, which resolves to Sonnet 5 on the Anthropic API. On Amazon Bedrock and Google Cloud the same &lt;code&gt;sonnet&lt;/code&gt; alias resolves to Sonnet 4.5, and on Microsoft Foundry to Sonnet 4.5, so your default window size depends on your provider as well as your alias. Switch with &lt;code&gt;/model&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I check how much context I am using?
&lt;/h3&gt;

&lt;p&gt;Run &lt;code&gt;/context&lt;/code&gt; for a live breakdown by category, including which CLAUDE.md and auto memory files loaded and how much is reserved for the autocompact buffer. &lt;code&gt;/usage&lt;/code&gt; adds cost and plan-limit attribution, and &lt;code&gt;/mcp&lt;/code&gt; shows per-server cost. You can also surface context usage continuously in your status line.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does the 1M context window cost more per token?
&lt;/h3&gt;

&lt;p&gt;No. It uses standard model pricing with no premium beyond 200K. What does scale is the recurring cost: your full conversation is re-sent with every request, at cached rates when the cache is warm and at full price after a cache miss. A bigger window raises the floor on every turn of a long session.&lt;/p&gt;

&lt;h3&gt;
  
  
  What gets lost when Claude Code compacts?
&lt;/h3&gt;

&lt;p&gt;Your requests and key code snippets are preserved. Project-root CLAUDE.md and auto memory are re-injected from disk. Rules with &lt;code&gt;paths:&lt;/code&gt; frontmatter and nested CLAUDE.md files are lost until a matching file is read again, and invoked skill bodies come back truncated to 5,000 tokens each and 25,000 total, oldest dropped first. Detailed instructions given early in a conversation are the most common casualty, which is why persistent rules belong in CLAUDE.md rather than in chat.&lt;/p&gt;

&lt;h2&gt;
  
  
  The number that matters
&lt;/h2&gt;

&lt;p&gt;The ceiling is a spec. Your startup footprint is a choice, and it is the one you can actually change.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;/context&lt;/code&gt; once, right now, on a project you work in daily. If the number surprises you, the fix is usually not a bigger window. It is fewer skills loaded by default, a shorter CLAUDE.md, and the habit of typing &lt;code&gt;/clear&lt;/code&gt; when you move to something new.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>contextwindow</category>
      <category>aicodingtools</category>
      <category>tokenusage</category>
    </item>
    <item>
      <title>Claude Code Hooks: 12 Production Patterns (and the Stop-Hook Trap)</title>
      <dc:creator>Nishil Bhave</dc:creator>
      <pubDate>Tue, 04 Aug 2026 15:32:08 +0000</pubDate>
      <link>https://dev.to/nishilbhave/claude-code-hooks-12-production-patterns-and-the-stop-hook-trap-3kib</link>
      <guid>https://dev.to/nishilbhave/claude-code-hooks-12-production-patterns-and-the-stop-hook-trap-3kib</guid>
      <description>&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%2Fzuz5vjhlnvretlrqgbjo.jpg" 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%2Fzuz5vjhlnvretlrqgbjo.jpg" alt="Six Claude Code hook patterns in a card grid (PreToolUse, PostToolUse, Secret Scan, UserPromptSubmit, Stop Hook and Exit Code 2) noting that exit code 2 blocks a tool call" width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Anthropic's annualized run-rate revenue more than tripled year over year to $30 billion by April 2026, helped substantially by Claude Code (&lt;a href="https://fortune.com/2026/04/24/anthropic-engineering-missteps-claude-code-performance-decline-user-backlash/" rel="noopener noreferrer"&gt;Fortune&lt;/a&gt;, 2026). And yet only 29% of developers trust AI output to be accurate, down from 40% a year earlier, while 84% use or plan to use the tools anyway (&lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Stack Overflow Developer Survey 2025&lt;/a&gt;, 2025).&lt;/p&gt;

&lt;p&gt;Claude Code hooks are how you close that gap. They sit outside the model loop, run as plain shell scripts, and either allow or block what the agent is about to do. No prompt-engineering, no vibes, just exit codes.&lt;/p&gt;

&lt;p&gt;I've been running hooks in production for eight months across two repos. This is the working set: 12 patterns I trust, plus the one Stop-hook footgun that's currently the top-voted complaint on Hacker News.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://maketocreate.com/the-complete-claude-code-workflow-how-i-ship-10x-faster/" rel="noopener noreferrer"&gt;the broader Claude Code workflow guide that hooks plug into&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hooks are deterministic shell scripts that intercept Claude Code's tool calls, they run outside the model so the agent can't talk its way past them.&lt;/li&gt;
&lt;li&gt;Exit code 2 blocks; exit code 1 does &lt;strong&gt;not&lt;/strong&gt;. Writing JSON &lt;code&gt;decision: "block"&lt;/code&gt; to stdout from &lt;code&gt;exit 0&lt;/code&gt; silently fails, the #1 reported gotcha (&lt;a href="https://news.ycombinator.com/item?id=47895029" rel="noopener noreferrer"&gt;Hacker News&lt;/a&gt;, 2026).&lt;/li&gt;
&lt;li&gt;Stop hooks behave as advisory in practice: a correct block tells Claude to keep going, and users report it stopping anyway. Replace them with &lt;code&gt;PostToolUse&lt;/code&gt; flags + &lt;code&gt;PreToolUse&lt;/code&gt; gates if you need real enforcement.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Why Are Claude Code Hooks the Most Underrated Production Tool?
&lt;/h2&gt;

&lt;p&gt;Stack Overflow's 2025 survey found 29% of developers trusting AI accuracy against 46% who actively distrust it, and 52% who either reject agents outright or keep AI pinned to autocomplete (&lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Stack Overflow&lt;/a&gt;, 2025). Hooks are what change that. They turn "I hope the agent doesn't &lt;code&gt;rm -rf&lt;/code&gt;" into a regex check that runs in 4ms.&lt;/p&gt;

&lt;p&gt;The model can be jailbroken. Prompt instructions can be overridden by a clever tool result. Even Claude Code's own deny-rules silently stop checking once a command chains more than 50 subcommands with &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, &lt;code&gt;||&lt;/code&gt;, or &lt;code&gt;;&lt;/code&gt;. Adversa AI demonstrated the bypass by padding a blocked &lt;code&gt;curl&lt;/code&gt; with 50 harmless &lt;code&gt;true&lt;/code&gt; commands (&lt;a href="https://adversa.ai/blog/claude-code-security-bypass-deny-rules-disabled/" rel="noopener noreferrer"&gt;Adversa AI&lt;/a&gt;, 2026). A hook is the layer that doesn't care what the model wants to do; it cares what's actually being executed.&lt;/p&gt;

&lt;p&gt;The hooks reference now documents 31 event names. Nine cover the vast majority of real usage, &lt;code&gt;PreToolUse&lt;/code&gt;, &lt;code&gt;PostToolUse&lt;/code&gt;, &lt;code&gt;UserPromptSubmit&lt;/code&gt;, &lt;code&gt;Stop&lt;/code&gt;, &lt;code&gt;SubagentStop&lt;/code&gt;, &lt;code&gt;Notification&lt;/code&gt;, &lt;code&gt;SessionStart&lt;/code&gt;, &lt;code&gt;SessionEnd&lt;/code&gt; and &lt;code&gt;PreCompact&lt;/code&gt;, and the rest are specialized hooks for narrower moments in the loop (&lt;code&gt;PostToolBatch&lt;/code&gt;, &lt;code&gt;PostToolUseFailure&lt;/code&gt;, &lt;code&gt;PermissionRequest&lt;/code&gt;, &lt;code&gt;Setup&lt;/code&gt;, &lt;code&gt;WorktreeCreate&lt;/code&gt;, and friends) (&lt;a href="https://code.claude.com/docs/en/hooks" rel="noopener noreferrer"&gt;Claude Code Hooks Reference&lt;/a&gt;, 2026).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why this matters more than it looks:&lt;/strong&gt; When 1.1M+ public GitHub repos already import an LLM SDK and 693,867 of those landed in the last 12 months alone (a 178% jump year-over-year (&lt;a href="https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/" rel="noopener noreferrer"&gt;GitHub Octoverse 2025&lt;/a&gt;, 2025)) the surface area for unattended agent mistakes is now enormous. Deterministic gates are no longer optional infrastructure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://maketocreate.com/agentic-ai-explained-what-it-is-how-it-works-and-why-it-matters/" rel="noopener noreferrer"&gt;the broader agentic AI shift that makes hook discipline a baseline skill&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How Does the Hook Lifecycle Actually Work?
&lt;/h2&gt;

&lt;p&gt;Each hook is a shell command Claude Code spawns at a specific event, piping a JSON payload to stdin. The script reads stdin, decides, and exits. Anthropic's docs are blunt: &lt;em&gt;"For most hook events, only exit code 2 blocks the action. Claude Code treats exit code 1 as a non-blocking error and proceeds with the action"&lt;/em&gt; (&lt;a href="https://code.claude.com/docs/en/hooks" rel="noopener noreferrer"&gt;Claude Code Hooks Reference&lt;/a&gt;, 2026). This single line is responsible for more broken hooks than every other gotcha combined.&lt;/p&gt;

&lt;p&gt;Every hook receives the same base payload:&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;"session_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;"abc123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"transcript_path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/path/to/transcript.jsonl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cwd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/repo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permission_mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hook_event_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;"PreToolUse"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tool_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tool_input"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rm -rf /"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script's response is read in two ways. Exit code is checked first. Then, for &lt;code&gt;PreToolUse&lt;/code&gt; only, Claude Code parses stdout for a &lt;code&gt;hookSpecificOutput&lt;/code&gt; JSON object that can return &lt;code&gt;permissionDecision: "allow" | "deny" | "ask" | "defer"&lt;/code&gt; plus an &lt;code&gt;updatedInput&lt;/code&gt; payload to rewrite the tool call before it runs. Other events use a top-level &lt;code&gt;decision: "block"&lt;/code&gt; field with a &lt;code&gt;reason&lt;/code&gt; string fed back to the model.&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%2Fcmdbtfqww94nh0zls6mh.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%2Fcmdbtfqww94nh0zls6mh.png" alt="Three hook exit codes compared: exit 0 runs and is advisory only, exit 2 is the only code that blocks the tool call, and exit 1 or any other code is logged as a non-blocking error while the tool runs anyway" width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hooks are configured in &lt;code&gt;~/.claude/settings.json&lt;/code&gt; (user-wide), &lt;code&gt;.claude/settings.json&lt;/code&gt; (project, checked in), or &lt;code&gt;.claude/settings.local.json&lt;/code&gt; (project, gitignored). Project settings override user. Plugin hooks override both. A starter PreToolUse entry looks like this:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://maketocreate.com/context-engineering-architecture-8-stages-from-demo-to-production/" rel="noopener noreferrer"&gt;why deterministic context layers like hooks beat in-prompt instructions&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Which Claude Code Hooks Stop Dangerous Commands? (Patterns 1–4)
&lt;/h2&gt;

&lt;p&gt;Sonatype detected 34,319 new open-source malware packages in Q3 2025 alone (a 140% jump quarter over quarter) and its Repository Firewall blocked 110,270 attacks in the same window (&lt;a href="https://www.sonatype.com/blog/open-source-malware-index-q3-2025" rel="noopener noreferrer"&gt;Sonatype&lt;/a&gt;, 2025). The validation patterns below are how you stop a confused agent from &lt;code&gt;pip install&lt;/code&gt;-ing the next Shai-Hulud worm into your repo.&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%2Fimages.unsplash.com%2Fphoto-1555066931-4365d14bab8c%3Fw%3D1200%26h%3D630%26fit%3Dcrop%26q%3D80" 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%2Fimages.unsplash.com%2Fphoto-1555066931-4365d14bab8c%3Fw%3D1200%26h%3D630%26fit%3Dcrop%26q%3D80" alt="Close-up of source code on a laptop screen during an automated CI pipeline run" width="1200" height="630"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pattern 1: Bash deny-list.&lt;/strong&gt; A &lt;code&gt;PreToolUse&lt;/code&gt; hook on the &lt;code&gt;Bash&lt;/code&gt; matcher that regex-checks &lt;code&gt;tool_input.command&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="n"&gt;DANGER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\brm\s+-rf\s+/|curl[^|]*\|\s*(ba)?sh|sudo\s|dd\s+if=|:\(\)\{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;command&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;DANGER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Blocked dangerous command: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# exit 2 = BLOCK; do not use exit 1
&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pattern 2: Secret scanner on writes.&lt;/strong&gt; Same shape, but matcher &lt;code&gt;Edit|Write|MultiEdit&lt;/code&gt; and the regex hits AWS keys, &lt;code&gt;sk-ant-…&lt;/code&gt; Anthropic keys, GitHub PATs, and &lt;code&gt;BEGIN PRIVATE KEY&lt;/code&gt; blocks inside &lt;code&gt;tool_input.content&lt;/code&gt;. Triggers the moment the agent tries to write a secret to a file, not after.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pattern 3 (Branch protection).&lt;/strong&gt; &lt;code&gt;PreToolUse&lt;/code&gt; on &lt;code&gt;Bash&lt;/code&gt; that blocks &lt;code&gt;git push&lt;/code&gt; and &lt;code&gt;git commit&lt;/code&gt; against &lt;code&gt;main&lt;/code&gt; or &lt;code&gt;master&lt;/code&gt; whenever HEAD points at a protected branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;command&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;git push&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;git commit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="n"&gt;branch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_output&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;git&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;branch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--show-current&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;branch&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;main&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;master&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Refusing direct write to &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;branch&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. Open a feature branch.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pattern 4: Dependency lockdown.&lt;/strong&gt; Same &lt;code&gt;Bash&lt;/code&gt; matcher; intercepts &lt;code&gt;npm install &amp;lt;pkg&amp;gt;&lt;/code&gt;, &lt;code&gt;pip install &amp;lt;pkg&amp;gt;&lt;/code&gt;, &lt;code&gt;cargo add &amp;lt;pkg&amp;gt;&lt;/code&gt; against an allowlist file. Shai-Hulud, the first documented self-replicating open-source worm, compromised more than 500 packages in days by spreading autonomously across registries and developer machines, and the same year brought hijackings of trusted packages like &lt;code&gt;chalk&lt;/code&gt; and &lt;code&gt;debug&lt;/code&gt; (&lt;a href="https://www.sonatype.com/state-of-the-software-supply-chain/2026/open-source-malware" rel="noopener noreferrer"&gt;Sonatype State of the Software Supply Chain&lt;/a&gt;, 2026). An allowlist hook is the cheapest mitigation that exists.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What broke before I added Pattern 1:&lt;/strong&gt; Claude Sonnet 4.5, on a session where I was tired and accept-edits was on, generated a &lt;code&gt;find . -name "*.tmp" -delete&lt;/code&gt; that picked up a &lt;code&gt;.tmp&lt;/code&gt; directory I'd been using as scratch storage. Eight hours of CSV exports gone. The deny-list regex took 12 minutes to write and would have caught it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://maketocreate.com/codeprobe-9-specialized-ai-agents-that-audit-your-codebase-for-solid-security-performance/" rel="noopener noreferrer"&gt;the codebase audit skill that pairs with these guardrails&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How Do You Enforce Code Quality With Hooks? (Patterns 5–7)
&lt;/h2&gt;

&lt;p&gt;Anthropic's prompt caching cuts cached-input cost by 90%, which is what makes always-on quality hooks affordable to run on every edit (&lt;a href="https://platform.claude.com/docs/en/about-claude/pricing" rel="noopener noreferrer"&gt;Anthropic API pricing&lt;/a&gt;, 2026). The patterns below run on the agent's output, not its input, they catch slop after the model commits to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pattern 5: Auto-format on save.&lt;/strong&gt; &lt;code&gt;PostToolUse&lt;/code&gt; matcher &lt;code&gt;Edit|Write|MultiEdit&lt;/code&gt;. Reads the touched path, runs prettier / ruff / gofmt, exits 0:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file_path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;notebook_path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rsplit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ruff&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;format&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;js&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prettier&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prettier&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;go&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gofmt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]}.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmt&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pattern 6 (Test gating).&lt;/strong&gt; Block any non-test Bash command if the test suite is currently red. Implemented as a &lt;code&gt;PreToolUse&lt;/code&gt; matcher &lt;code&gt;Bash&lt;/code&gt; that reads &lt;code&gt;.claude/tests-passing&lt;/code&gt; (touched by your CI hook on green) and exits 2 if missing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pattern 7: Structured output capture.&lt;/strong&gt; &lt;code&gt;PostToolBatch&lt;/code&gt;, which fires after a full batch of parallel tool calls resolves, writes a summarized JSON record per batch into &lt;code&gt;.claude/runs/&amp;lt;session_id&amp;gt;.json&lt;/code&gt;. Useful when a long agent run does 80 tool calls and you want a machine-readable replay later. Combine with the audit pattern below for full traceability.&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%2F0nbv8ymoo6ofs4z0hd50.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%2F0nbv8ymoo6ofs4z0hd50.png" alt="Slope chart of the AI trust gap widening from 2024 to 2025: adoption rose from 76 percent to 84 percent while trust in accuracy fell from 40 percent to 29 percent, widening the gap from 36 points to 55 points" width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Can Hooks Cap a Runaway Agent's Costs? (Patterns 8–10)
&lt;/h2&gt;

&lt;p&gt;One developer's eight-month Claude Code run consumed 10 billion tokens, which would have cost more than $15,000 at API list rates against roughly $800 on a Max plan (&lt;a href="https://www.morphllm.com/ai-coding-costs" rel="noopener noreferrer"&gt;Morph&lt;/a&gt;, 2026). A subscription absorbs that, but it does not make the underlying burn visible, and it does not stop an agent from spending your weekly limit in an afternoon. Hooks are the only place you can put a hard ceiling on that without changing the model's behavior. The three patterns below cover notifications, session priming, and a cost circuit breaker I haven't seen anyone else publish.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pattern 8: Notification routing.&lt;/strong&gt; &lt;code&gt;Notification&lt;/code&gt; event hook that pipes Claude Code's permission prompts to ntfy.sh, a Slack webhook, or &lt;code&gt;osascript -e 'display notification …'&lt;/code&gt; on macOS. Useful when you walk away from a long run and don't want to come back to a session blocked on a 30-second-old "Approve Bash?" prompt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Claude Code needs attention&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;osascript&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-e&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;display notification &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; with title &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Claude Code&lt;/span&gt;&lt;span class="sh"&gt;"'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pattern 9: SessionStart context loading.&lt;/strong&gt; Inject git status, recent commits, and failing test output into the agent's context the moment a session opens, via the &lt;code&gt;additionalContext&lt;/code&gt; field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_output&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;git&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;log&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--oneline&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-10&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_output&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;git&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-sb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hookSpecificOutput&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hookEventName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SessionStart&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;additionalContext&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;## Git&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;```
&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;endraw&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;
&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
```&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}))&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent wakes up oriented instead of asking you what branch you're on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pattern 10 (Cost circuit breaker).&lt;/strong&gt; A &lt;code&gt;PreToolUse&lt;/code&gt; hook on &lt;code&gt;Bash|Edit|Write&lt;/code&gt; that increments a counter in a tmp file scoped by &lt;code&gt;session_id&lt;/code&gt;. Past N tool calls in T seconds, exit 2 with &lt;code&gt;"You've made 200 tool calls in 60 seconds, please summarize and confirm direction before continuing."&lt;/code&gt; This forces a checkpoint instead of a $300 runaway. I've never seen this pattern documented elsewhere; it took one accidentally-billed weekend to invent it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The hook that paid for itself in one session:&lt;/strong&gt; I added the cost circuit breaker after a Sonnet 4.5 agent spent four hours and 8M tokens chasing a phantom test failure that turned out to be a stale lock file. The hook would have stopped it at minute 12.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;durable execution patterns that complement hook-based cost control&lt;/p&gt;




&lt;h2&gt;
  
  
  How Do You Audit What an Agent Actually Did? (Patterns 11–12)
&lt;/h2&gt;

&lt;p&gt;The 1.1M public repos using LLM SDKs and the 178% YoY jump in new ones (&lt;a href="https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/" rel="noopener noreferrer"&gt;GitHub Octoverse 2025&lt;/a&gt;, 2025) tell you that audit logging is no longer a "nice to have", it's the only durable record of what an autonomous agent actually did to your code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pattern 11: Append-only JSONL audit log.&lt;/strong&gt; &lt;code&gt;PostToolUse&lt;/code&gt; matcher &lt;code&gt;*&lt;/code&gt; that appends one record per tool call to &lt;code&gt;~/.claude-audit/&amp;lt;date&amp;gt;.jsonl&lt;/code&gt;. Captures timestamp, session, cwd, tool, input, and exit. Cheap insurance, disk is free, accountability isn't:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;home&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.claude-audit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%Y-%m-%d&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.jsonl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exist_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;session&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;session_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cwd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cwd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pattern 12: SubagentStop checkpointing.&lt;/strong&gt; When a subagent finishes (a Task tool call, a parallel review agent), &lt;code&gt;SubagentStop&lt;/code&gt; fires with a transcript path. Hook this to extract the agent's final answer and write it to a structured location. Pairs naturally with the multi-agent review approach in &lt;a href="https://maketocreate.com/i-built-a-multi-agent-code-review-skill-for-claude-code-heres-how-it-works/" rel="noopener noreferrer"&gt;the multi-agent code review skill&lt;/a&gt;, the SubagentStop hook is what gives you a machine-readable trail of which agent flagged what.&lt;/p&gt;

&lt;p&gt;That transcript path is also your durable record after the session ends: &lt;a href="https://maketocreate.com/claude-code-save-conversation-find-export-transcripts/" rel="noopener noreferrer"&gt;where Claude Code saves conversations on disk and how to find, export, and redact the JSONL your hooks write to&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Claude Keeps Ignoring Your Stop Hook (the gotcha section)
&lt;/h2&gt;

&lt;p&gt;A Hacker News thread titled &lt;em&gt;"Tell HN: Claude 4.7 is ignoring stop hooks"&lt;/em&gt; hit 109 points in late April 2026 (&lt;a href="https://news.ycombinator.com/item?id=47895029" rel="noopener noreferrer"&gt;Hacker News&lt;/a&gt;, 2026). The reported pattern: a Stop hook configured to block until tests pass, Claude acknowledging the block message in chat, and then the session ending anyway. There are three things going on, and only one of them is a bug.&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%2Fimages.unsplash.com%2Fphoto-1611769454616-948e64664119%3Fixid%3DM3w3MjE1NTZ8MHwxfHNlYXJjaHwxMnx8aG9va3N8ZW58MHx8fHwxNzg1ODU3NDkxfDA%26ixlib%3Drb-4.1.0%3Fw%3D1200%26h%3D630%26fit%3Dcrop%26q%3D80" 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%2Fimages.unsplash.com%2Fphoto-1611769454616-948e64664119%3Fixid%3DM3w3MjE1NTZ8MHwxfHNlYXJjaHwxMnx8aG9va3N8ZW58MHx8fHwxNzg1ODU3NDkxfDA%26ixlib%3Drb-4.1.0%3Fw%3D1200%26h%3D630%26fit%3Dcrop%26q%3D80" alt="blue tote bag hanging on black metal bar - Photo by Young-Kyung Kim on Unsplash" width="1051" height="630"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gotcha #1, exit code mismatch.&lt;/strong&gt; The most common failure mode isn't the stop hook itself; it's people writing &lt;code&gt;print(json.dumps({"decision": "block", "reason": "tests failing"}))&lt;/code&gt; and exiting 0. From the docs: stdout JSON is parsed as advisory, but only &lt;code&gt;exit 2&lt;/code&gt; actually blocks. Top reply on the HN thread: &lt;em&gt;"Exit 2 means a blocking error. Claude Code ignores stdout and any JSON in it."&lt;/em&gt; Half the "stop hook ignored" reports are this.&lt;/p&gt;

&lt;p&gt;Gotcha #2. Stop hooks are tool-result-shaped messages. When a Stop hook does block correctly, its &lt;code&gt;reason&lt;/code&gt; is delivered to the model as something structurally indistinguishable from a tool result. Claude is RLHF-trained to resist instructions inside tool results (prompt-injection defense), so it sometimes acknowledges the block and stops anyway. This is the part that's genuinely frustrating, and it's what the HN thread surfaced. Anthropic's Claude Code team replied asking for &lt;code&gt;/feedback&lt;/code&gt; reports but hasn't shipped a documented fix at time of writing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gotcha #3, the block loop.&lt;/strong&gt; The docs are explicit about what a successful block actually does: &lt;em&gt;"When you block a &lt;code&gt;Stop&lt;/code&gt; event, Claude continues the conversation instead of stopping"&lt;/em&gt; (&lt;a href="https://code.claude.com/docs/en/hooks" rel="noopener noreferrer"&gt;Claude Code Hooks Reference&lt;/a&gt;, 2026). That is the whole mechanism, and it is also the trap. A Stop hook that blocks unconditionally never lets a session end. Claude keeps working, hits &lt;code&gt;Stop&lt;/code&gt; again, gets blocked again. You need your own guard: a counter or flag file keyed on &lt;code&gt;session_id&lt;/code&gt;, checked before you emit &lt;code&gt;decision: "block"&lt;/code&gt;. Older hook write-ups tell you to read a &lt;code&gt;stop_hook_active&lt;/code&gt; field for this. It is not in the current reference, so don't build on it. Own the loop guard yourself.&lt;/p&gt;

&lt;p&gt;Two of those three are hooks behaving exactly as documented: only exit code 2 blocks, and a successful block continues the conversation rather than ending it. Gotcha #2 is the only one that's a genuine defect, which is worth knowing before you spend an afternoon debugging your own script.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The deterministic workaround.&lt;/strong&gt; Stop being a Stop hook. Replace it with two cooperating hooks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# PostToolUse matcher: Edit|Write|MultiEdit
# Marks the workspace as "tests required"
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="n"&gt;pathlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.claude/tests-required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;touch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# PreToolUse matcher: Bash
# Blocks any non-test command until tests pass
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;command&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;flag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.claude/tests-required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\b(pytest|jest|npm test|cargo test)\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tests required. Run pytest first; the flag clears on green.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model can't argue with this. It's not delivered as a chat message; it's a refused tool call. Whatever the model thinks about it is irrelevant, the Bash command never runs.&lt;/p&gt;

&lt;p&gt;the eval mindset that makes deterministic guardrails feel natural&lt;/p&gt;

&lt;p&gt;Watch on YouTube: &lt;a href="https://www.youtube.com/watch?v=IkaPHiMDazM" rel="noopener noreferrer"&gt;Hooks in Claude Code (Anthropic)&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How Do You Debug a Hook Without Losing an Afternoon?
&lt;/h2&gt;

&lt;p&gt;Three commands cover 95% of debugging. Start with &lt;code&gt;claude --debug&lt;/code&gt;: it prints every hook invocation, the exact stdin payload, the exit code, and any stderr (&lt;a href="https://code.claude.com/docs/en/hooks" rel="noopener noreferrer"&gt;Claude Code Hooks Reference&lt;/a&gt;, 2026). If a hook isn't firing at all, you'll see it skipped here with a reason.&lt;/p&gt;

&lt;p&gt;Second, run the hook directly from the CLI with a synthetic payload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'{"session_id":"test","cwd":"'&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s1"&gt;'","tool_name":"Bash","tool_input":{"command":"rm -rf /"},"hook_event_name":"PreToolUse"}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | python3 ~/.claude/hooks/guard.py&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"exit=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Third, the in-session &lt;code&gt;/hooks&lt;/code&gt; slash command lists every hook currently registered for the active project. If your settings file has a typo, this is where you find out.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The 30-second smoke test I run on every new hook:&lt;/strong&gt; add &lt;code&gt;print("HOOK FIRED:", data["hook_event_name"], file=sys.stderr)&lt;/code&gt; at the top of the script, run with &lt;code&gt;claude --debug&lt;/code&gt;, watch for the line. If it doesn't appear, the matcher is wrong. If it appears but nothing happens, the exit code is wrong. Two minutes of work, saves an hour.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://maketocreate.com/claude-code-errors-every-code-cause-and-fix-2026-guide/" rel="noopener noreferrer"&gt;the wider Claude Code error catalogue for everything a hook isn't causing&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What's the difference between exit 1 and exit 2 in Claude Code hooks?
&lt;/h3&gt;

&lt;p&gt;Exit code 2 is the only blocking exit code; exit 1 (and every other non-zero code) is treated as a non-blocking error and the tool call still proceeds (&lt;a href="https://code.claude.com/docs/en/hooks" rel="noopener noreferrer"&gt;Claude Code Hooks Reference&lt;/a&gt;, 2026). Stderr is fed back to the model on exit 2 only. This is the single most common hook bug.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can hooks see Claude's chat messages or only tool calls?
&lt;/h3&gt;

&lt;p&gt;Hooks see tool calls and their inputs, plus user prompts via the &lt;code&gt;UserPromptSubmit&lt;/code&gt; event. They don't see assistant chat output directly, only tool responses through &lt;code&gt;PostToolUse&lt;/code&gt;. The &lt;code&gt;Stop&lt;/code&gt; and &lt;code&gt;SubagentStop&lt;/code&gt; events do receive &lt;code&gt;last_assistant_message&lt;/code&gt;, so the final turn is visible, but nothing in between is. If you want to gate on what the model &lt;em&gt;said&lt;/em&gt; rather than what it &lt;em&gt;did&lt;/em&gt;, hooks are the wrong layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Are Claude Code hooks safe to share publicly via GitHub?
&lt;/h3&gt;

&lt;p&gt;Project-level hooks in &lt;code&gt;.claude/settings.json&lt;/code&gt; are checked into the repo and run on anyone's machine. Treat them like any other executable in the repo. Use &lt;code&gt;.claude/settings.local.json&lt;/code&gt; (gitignored by default) for hooks that load secrets, point to absolute paths on your machine, or post to private webhooks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why do my Stop hooks work in plan mode but not auto-accept mode?
&lt;/h3&gt;

&lt;p&gt;Stop-hook delivery semantics changed across Claude versions; the HN thread reporting Claude 4.7 ignoring stop hooks describes this (&lt;a href="https://news.ycombinator.com/item?id=47895029" rel="noopener noreferrer"&gt;Hacker News&lt;/a&gt;, 2026). The deterministic workaround (PostToolUse flag + PreToolUse gate) works identically across modes because it doesn't rely on the model honoring a Stop message.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do hooks work the same in Claude Code on the web vs CLI?
&lt;/h3&gt;

&lt;p&gt;Hooks run server-side scripts and only fire in environments where Claude Code can spawn local processes: the CLI, the desktop app, and the IDE extensions. Claude Code on the web (claude.ai/code) doesn't currently execute local hooks; the file lives in your project but is ignored at runtime.&lt;/p&gt;




&lt;h2&gt;
  
  
  What to Do With This
&lt;/h2&gt;

&lt;p&gt;Pick three patterns. Start with the Bash deny-list (Pattern 1), the audit log (Pattern 11), and one of the stop-hook workaround halves. Run them for a week. Then add the secret scanner and the cost circuit breaker.&lt;/p&gt;

&lt;p&gt;The point of hooks isn't to lock the agent down, it's to remove the failure modes you're tired of worrying about, so you can let the agent run longer with fewer interruptions. Every hook you ship is one more thing you don't have to remember to check.&lt;/p&gt;

&lt;p&gt;the next layer up, where hooks become the substrate for orchestrated subagents&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>hooks</category>
      <category>aicodingtools</category>
      <category>developertooling</category>
    </item>
    <item>
      <title>Claude Scheduled Tasks: Mine Ran 8.5 Hours and Burned 60% of My Limit</title>
      <dc:creator>Nishil Bhave</dc:creator>
      <pubDate>Sat, 01 Aug 2026 14:36:29 +0000</pubDate>
      <link>https://dev.to/nishilbhave/claude-scheduled-tasks-mine-ran-85-hours-and-burned-60-of-my-limit-53p3</link>
      <guid>https://dev.to/nishilbhave/claude-scheduled-tasks-mine-ran-85-hours-and-burned-60-of-my-limit-53p3</guid>
      <description>&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%2Fnswj9wpcxie82gm4pvq4.webp" 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%2Fnswj9wpcxie82gm4pvq4.webp" alt="A lighthouse lamp still burning over an empty sea, illustrating a Claude scheduled task that ran 8.5 hours unattended" width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I sat down at my desk around 3:30 PM and found a scheduled task still running. It had fired at 7:31 AM that morning. The job it was supposed to do takes about three minutes.&lt;/p&gt;

&lt;p&gt;My current session read 60% used. The weekly "all models" bar read 16%. I had not touched Claude all day.&lt;/p&gt;

&lt;p&gt;My first instinct was that someone else was on my account. That turned out to be wrong, and the real answer was more interesting: my own scheduled task had been stuck in a loop for eight and a half hours, re-writing the same paragraph, because the thing running it would not accept "I'm done" as an answer.&lt;/p&gt;

&lt;p&gt;Here's the full chain, the receipts I used to trace it, and the checklist I'd give anyone running unattended agents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A daily scheduled task on Claude Opus 5 ran from &lt;strong&gt;7:31 AM to roughly 4:02 PM&lt;/strong&gt; instead of its usual three minutes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Root cause:&lt;/strong&gt; the task called Gmail and Calendar tools that were approval-gated. A scheduled run is unattended by definition, so nobody was there to approve. The run was dead on arrival, every single morning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The expensive part was not the failure, it was the retry.&lt;/strong&gt; The model correctly concluded "run failed" and stopped. The scheduler re-prompted it anyway, dozens of times, and every iteration re-sent the entire growing transcript.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pressing stop did not stop it.&lt;/strong&gt; When I finally found the run and hit Claude's stop button, it carried on regardless.&lt;/li&gt;
&lt;li&gt;It ended wedged on &lt;code&gt;API Error: 400 messages.56: user messages must have non-empty content&lt;/code&gt;, a state that "Try again" can never clear.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;This cost a limit window, not money.&lt;/strong&gt; Weekly limits reset. The account's usage-credit meter read $0.00 that same evening.&lt;/li&gt;
&lt;li&gt;There is no per-conversation usage breakdown in Claude, so "where did my limit go" is currently only answerable by digging through run history.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What happened: the 8.5-hour timeline
&lt;/h2&gt;

&lt;p&gt;The task was called "Refresh personal dashboard." I created it on July 27, 2026 through claude.ai's Scheduled feature. It ran daily at 7:31 AM on Opus 5 at high effort, and its job was mundane: run three Gmail searches for bank, job, and GitHub alerts, pull the next seven days from Google Calendar, build a small self-contained HTML dashboard, and update a desktop artifact.&lt;/p&gt;

&lt;p&gt;Here is the shape of what actually happened, drawn against the two timestamps I can prove and the one I observed.&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%2Fkyhu8oba76letg1p9gif.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%2Fkyhu8oba76letg1p9gif.png" alt="Timeline chart contrasting the intended three-minute run of a Claude scheduled task with its actual 8 hour 31 minute run on 1 August 2026. The task fired at 7:31 AM, was found still active at 3:30 PM, and showed its last activity at 4:02 PM." width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Three points on that line are solid: the API confirms the trigger fired at 02:01:34 UTC, which is 7:31 AM IST; I found it still active at roughly 3:30 PM; the last activity on the run sits at about 4:02 PM. The phases in between happened in a known order, but I never recorded exactly when one became the next, so I'm not going to draw boundaries I can't defend.&lt;/p&gt;

&lt;p&gt;The intended bar is drawn to true scale. That sliver is the entire job.&lt;/p&gt;

&lt;h2&gt;
  
  
  The root cause: approval-gated tools in an unattended run
&lt;/h2&gt;

&lt;p&gt;The task needed two things it could never have.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mcp__Gmail__search_threads&lt;/code&gt; and &lt;code&gt;mcp__Google_Calendar__list_events&lt;/code&gt; were both approval-gated on my account. That's the setting where Claude asks before each call and waits for you to click approve.&lt;/p&gt;

&lt;p&gt;A scheduled run is unattended by definition. That's the entire point of scheduling something for 7:31 AM. There is nobody sitting there to clear the gate, and there is no mechanism for the gate to clear itself.&lt;/p&gt;

&lt;p&gt;So the run was dead on arrival. Not occasionally. Every morning since July 27, by design, and the system let me create it that way without a word of warning.&lt;/p&gt;

&lt;p&gt;&lt;a href="/article-images/runaway-claude-agent/usage-limits-60-percent.webp" class="article-body-image-wrapper"&gt;&lt;img src="/article-images/runaway-claude-agent/usage-limits-60-percent.webp" alt="The Claude usage screen showing current session 60 percent used and weekly all-models usage at 16 percent"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The part I want to be precise about: &lt;strong&gt;the model behaved correctly here.&lt;/strong&gt; It hit a gate it could not pass, and it wrote an accurate diagnosis. It said the run failed, named both gated tools, and gave the fix. Then it deliberately refused to fake the output. Its own words were that a visibly stale dashboard beats a fresh timestamp sitting over empty spending cards.&lt;/p&gt;

&lt;p&gt;That's the right call. If it had invented plausible numbers, I'd have had a dashboard that lied to me every morning and I might never have noticed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The loop: when the harness won't take "done" for an answer
&lt;/h2&gt;

&lt;p&gt;The model concluded the run had failed. The scheduler re-prompted it.&lt;/p&gt;

&lt;p&gt;So it concluded again. Slightly different wording, same substance: run failed, nothing written, Gmail and Calendar are approval-gated, set them to always-allow and re-fire. Then again. And again.&lt;/p&gt;

&lt;p&gt;&lt;a href="/article-images/runaway-claude-agent/loop-repeated-conclusions-1.webp" class="article-body-image-wrapper"&gt;&lt;img src="/article-images/runaway-claude-agent/loop-repeated-conclusions-1.webp" alt="A Claude transcript showing several near-identical run-failed conclusions in sequence"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Reading back through it is a strange experience, because the model is visibly aware of the problem and completely unable to escape it. At one point it wrote this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Acknowledged. That call was mine and it shouldn't have happened. I'd already concluded twice. No further tool calls.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That line is the whole incident in one sentence. The model was tracking its own repetition. The harness driving it was not.&lt;/p&gt;

&lt;p&gt;This is where the usage went. Every iteration of that loop re-sent the entire conversation so far, and the conversation kept growing. On top of that, I had five MCP connectors attached to this task: Gmail, Google Calendar, Asana, vidIQ, and Claude Code Remote, plus a documents plugin. Every connector's full tool catalog rides along in every model call, whether the task touches that connector or not.&lt;/p&gt;

&lt;p&gt;I want to be careful here, because it would be easy to overclaim. I never measured token counts, so I'm not going to give you a number. What I can say structurally is that a growing transcript plus five connectors' worth of tool schemas, re-sent on every iteration for hours, against the most expensive model available, is a very effective way to consume a limit.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "API Error: 400 user messages must have non-empty content" means
&lt;/h2&gt;

&lt;p&gt;By this point I was trying to kill it. I hit Claude's stop button. Nothing happened. I hit it again. The run carried on exactly as before, still re-writing its conclusion, completely indifferent to the fact that I was now sitting there watching it and actively telling it to stop.&lt;/p&gt;

&lt;p&gt;Shortly after that, the run stopped being a loop and became a wall.&lt;/p&gt;

&lt;p&gt;&lt;a href="/article-images/runaway-claude-agent/api-error-400-wall.webp" class="article-body-image-wrapper"&gt;&lt;img src="/article-images/runaway-claude-agent/api-error-400-wall.webp" alt="A wall of repeated red API Error 400 messages and a Something went wrong banner"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API Error: 400 messages.56: user messages must have non-empty content
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you hit this string, here's what it means. In the API, a conversation is a list of messages, each tagged with a role, and tool results travel back to the model inside &lt;strong&gt;user-role&lt;/strong&gt; messages. Something in that loop appended a user-role message at position 56 with nothing in it.&lt;/p&gt;

&lt;p&gt;The API rejects any request containing an empty message. Not the new part of the request. The whole thing, because the entire history goes up on every call.&lt;/p&gt;

&lt;p&gt;That's why this state is permanent. Message 56 is now baked into that conversation's history, so every future call carries it, so every future call gets rejected the same way. The "Try again" button re-sends the same invalid history and fails identically. There's no repair path from inside the conversation. The transcript is scrap.&lt;/p&gt;

&lt;p&gt;I want to be careful about what I'm claiming here. I don't know what put the empty message at position 56, and I didn't capture enough to prove it. What I can report is the order I saw things happen in: I was pressing stop, the stop wasn't taking, and then position 56 turned up empty and the run wedged. An interrupt landing while a turn is in flight is at least a plausible way to end up with a user-role message that has nothing in it. That's a hypothesis, not a finding, and I'd rather say so than dress it up.&lt;/p&gt;

&lt;p&gt;One small mercy: those rejected calls are refused before the model ever runs, so the wall of red errors itself is not what burned my limit. The hours of real generations before the corruption are.&lt;/p&gt;

&lt;p&gt;If you want the wider catalogue of what Claude Code throws and what each one means, I keep that separately: &lt;a href="https://maketocreate.com/claude-code-errors-every-code-cause-and-fix-2026-guide/" rel="noopener noreferrer"&gt;every Claude Code error code, cause, and fix&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I traced it
&lt;/h2&gt;

&lt;p&gt;This part turned out to be the most useful thing I learned, because the tooling for it barely exists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There is no per-conversation usage breakdown in Claude.&lt;/strong&gt; The usage screen tells you a percentage for the current session and for the week. It does not tell you which conversation spent it. If you want to know where your limit went, the interface simply will not tell you.&lt;/p&gt;

&lt;p&gt;So I worked backwards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Run history was the first real signal.&lt;/strong&gt; The scheduled task keeps a list of its runs, and the current one was still marked active hours after it should have finished. That's what turned a vague "my usage is weird" into a specific suspect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The routines API gave me ground truth.&lt;/strong&gt; Querying &lt;code&gt;/v1/code/triggers&lt;/code&gt; returned the actual stored configuration rather than what I remembered setting up: the model, the cron expression, &lt;code&gt;last_fired_at&lt;/code&gt; at 02:01:34 UTC, the five attached connectors, and the full stored prompt. (&lt;a href="https://code.claude.com/docs/en/routines" rel="noopener noreferrer"&gt;Routines are documented here&lt;/a&gt;; the run-history and configuration surface is the same underlying system.) It also returned &lt;code&gt;persist_session: false&lt;/code&gt;, which matters more than it sounds. Each run starts a fresh session. So the transcript that reached message 56 was built entirely within one morning's run. That wasn't accumulated drift over days. One run did that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Local forensics ruled out my own machine.&lt;/strong&gt; I checked launch-agent logs and confirmed the Mac had been asleep from 8 PM until 3:22 PM. Nothing local could have driven this. The whole thing ran server-side, which is exactly what scheduled tasks are supposed to do, and exactly why nothing on my end could stop it.&lt;/p&gt;

&lt;p&gt;By 6:36 PM the session bar had rolled over to 4%. Here's the honest framing of what this cost me, because it's the part people get wrong in both directions.&lt;/p&gt;

&lt;p&gt;The weekly window had only opened the previous evening, so that 16% was essentially one wedged run. For comparison, by that evening, after a full afternoon of genuine work, the weekly all-models bar had moved only from 16% to 18%. One broken run cost sixteen points. An afternoon of me actually using the thing cost two.&lt;/p&gt;

&lt;p&gt;And on the same settings page, further down: &lt;strong&gt;usage credits, $0.00 spent.&lt;/strong&gt; This cost me a limit window, not money. Weekly limits reset. If you're on a subscription and this happens to you, you have lost some capacity for a few days, not a bill. Anyone telling you a runaway agent on a Max plan "cost them hundreds" is describing API billing, which is a different product. If you want the full picture of how the plans and their limits actually work, I've written that up in detail: &lt;a href="https://maketocreate.com/claude-code-cost-in-2026-honest-pro-vs-max-vs-api-guide/" rel="noopener noreferrer"&gt;how Claude Code's Pro, Max, and API pricing and limits really compare&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to keep scheduled tasks from burning your limits
&lt;/h2&gt;

&lt;p&gt;Five things, in the order I'd do them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Put scheduled tasks on a cheap model.&lt;/strong&gt; Mine was on Opus 5 at high effort because I built it interactively and never thought about it again. A routine that assembles a dashboard from three searches does not need the most expensive model available. Sonnet is the right default for unattended work. If you're weighing which model is worth its cost for which job, that tradeoff is its own topic: &lt;a href="https://maketocreate.com/claude-fable-5-in-claude-code-when-the-2x-model-pays-off/" rel="noopener noreferrer"&gt;when the more expensive model actually earns its keep&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Attach only the connectors the task uses.&lt;/strong&gt; I had five plus a plugin on a task that needed two. Every attached connector's tool catalog is sent on every call of every run. Trimming this is free.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Set the specific tools the task needs to always-allow.&lt;/strong&gt; This is the one that would have prevented the whole incident. An approval-gated tool in an unattended run is not a risk, it's a guaranteed failure, because there is never anyone there to approve it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Don't include steps that depend on a machine that might be asleep.&lt;/strong&gt; My task's final step pushed an artifact to a desktop that is reliably asleep at 7:31 AM. That step could never have completed either.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Check the run history after the first few runs.&lt;/strong&gt; Then occasionally after that. This is the only warning system that currently exists. There is no usage alert, no anomaly detection, and no ledger. If you don't look, nothing will tell you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Anthropic should fix about scheduled tasks
&lt;/h2&gt;

&lt;p&gt;I want to be fair here. The model did its job well, and the failure is in the layer around it. Four things would have caught this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Refuse or warn at creation time.&lt;/strong&gt; The system knew my Gmail and Calendar tools were approval-gated, and it knew I was scheduling an unattended run that called them. Those two facts together are a guaranteed failure and could be checked the moment I hit save.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Put a runtime cap and a circuit breaker on scheduled runs.&lt;/strong&gt; A task that normally takes three minutes ran for eight and a half hours. Nothing intervened. A simple ceiling on wall-clock time or turn count would have ended this at minute ten. Repeating a near-identical conclusion more than twice is also a fairly obvious signal that something has stopped making progress.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Make the stop button authoritative.&lt;/strong&gt; This is the one that bothers me most, because it's the last line of defence and it isn't automated, it's me. A cap failing is a missing feature. A human being present, seeing the problem, pressing stop, and the run continuing anyway is a different category of problem. Whatever "stop" does today, on a wedged scheduled run it did not stop anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Give us a per-conversation usage breakdown.&lt;/strong&gt; This is the big one. "Where did my usage go" should not require querying an undocumented API endpoint and reading launch-agent logs. A per-conversation view would have turned my afternoon of detective work into about thirty seconds.&lt;/p&gt;

&lt;p&gt;I did file feedback on the run itself, so this is in front of them with the transcript attached.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;I'm not going to tell you Claude will do this to you. This is one incident on one account with a specific misconfiguration, and I set that misconfiguration up myself.&lt;/p&gt;

&lt;p&gt;What I'd take from it is narrower and more useful. Unattended agents fail differently from interactive ones. When you're sitting in front of a stuck agent, you notice in seconds and you kill it. This one fired at 7:31 AM while I was asleep, ran unwatched for eight hours, and then, when I did finally turn up and press stop, kept going anyway. The assumption I didn't know I was making was that I could always just intervene. That turned out not to be true.&lt;/p&gt;

&lt;p&gt;The model was the most reliable component in this whole chain. It diagnosed the problem correctly on the first try, refused to fabricate data to cover the gap, and noticed it was repeating itself. It just had no way to make anything listen, and by the end, neither did I.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does Claude have scheduled tasks?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes. claude.ai has a Scheduled feature that runs a saved prompt on a recurring schedule, and Claude Code has the equivalent through &lt;a href="https://code.claude.com/docs/en/routines" rel="noopener noreferrer"&gt;routines&lt;/a&gt;, &lt;a href="https://claude.com/blog/introducing-routines-in-claude-code" rel="noopener noreferrer"&gt;introduced as a way to run unattended automation&lt;/a&gt;. Both run server-side on Anthropic's infrastructure, so they don't need your machine to be awake. That's the useful part and also the part that lets a broken run continue for hours without you knowing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do Claude scheduled tasks count against your usage limits?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes. A scheduled run consumes the same plan limits as anything you do by hand, and it does so whether or not the run succeeds. In my case a run that produced no output at all consumed roughly 16% of a weekly window, because the cost is in the model calls, not in whether the task achieved anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is my Claude weekly limit used up when I didn't do anything?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Check your scheduled tasks first, and look at run history rather than the usage screen. The usage screen shows you a total with no attribution, so it can't tell you which conversation spent your limit. A task stuck in a retry loop is the failure mode to look for, especially one on an expensive model with several connectors attached.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I fix a conversation showing "API Error 400: user messages must have non-empty content"?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. An empty user-role message is permanently part of that conversation's history, and the full history is re-sent on every call, so every retry fails identically. "Try again" cannot work. Start a new conversation. If it's a scheduled task, disable it before it fires again, because the underlying cause will still be there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do the failed API calls use up your usage?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The rejected ones don't. A &lt;code&gt;400&lt;/code&gt; is refused before the model runs, so the wall of identical errors at the end of my run wasn't the expensive part. The damage was done earlier, by the hours of real generations in the retry loop before the transcript corrupted.&lt;/p&gt;

</description>
      <category>claude</category>
      <category>aiagents</category>
      <category>automation</category>
      <category>postmortem</category>
    </item>
    <item>
      <title>Context Engineering Architecture: 8 Stages From Demo to Production</title>
      <dc:creator>Nishil Bhave</dc:creator>
      <pubDate>Fri, 31 Jul 2026 11:28:43 +0000</pubDate>
      <link>https://dev.to/nishilbhave/context-engineering-architecture-8-stages-from-demo-to-production-42gm</link>
      <guid>https://dev.to/nishilbhave/context-engineering-architecture-8-stages-from-demo-to-production-42gm</guid>
      <description>&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%2F8fyscfihysa9oat35vcn.jpg" 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%2F8fyscfihysa9oat35vcn.jpg" alt="An 8-stage context engineering pipeline (intent classification, parallel retrieval, reranking, compression, context assembly, token-budget audit, guardrails, and observability) flowing into a production agent" width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The 8-Stage Pipeline That Replaced Naive Prompting
&lt;/h2&gt;

&lt;p&gt;Most "agentic AI" demos fall apart the moment you put real data behind them. The agent works in a notebook with three documents and crumbles in production with three thousand. The model didn't get worse. The context did.&lt;/p&gt;

&lt;p&gt;A 2025 MIT NANDA study found that 95% of generative AI pilots fail to deliver measurable ROI (&lt;a href="https://mlq.ai/media/quarterly_decks/v0.1_State_of_AI_in_Business_2025_Report.pdf" rel="noopener noreferrer"&gt;MIT NANDA&lt;/a&gt;, 2025). The reflexive answer is to blame the model: too small, too cheap, too dumb. But teams that ship working agents will tell you the same thing. The bottleneck isn't the model. It's the architecture that decides what the model gets to see.&lt;/p&gt;

&lt;p&gt;That architecture has a name now. &lt;strong&gt;Context engineering&lt;/strong&gt;: the discipline of dynamically assembling the right tokens, in the right order, within the right budget, every single turn. Anthropic calls it "the natural progression of prompt engineering" (&lt;a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents" rel="noopener noreferrer"&gt;Anthropic Engineering&lt;/a&gt;, 2025). 82% of IT leaders agree prompt engineering alone is no longer enough to power AI at scale (&lt;a href="https://datahub.com/blog/context-engineering-vs-prompt-engineering/" rel="noopener noreferrer"&gt;DataHub&lt;/a&gt;, 2026).&lt;/p&gt;

&lt;p&gt;I've spent the last year building agents at &lt;a href="https://growthengine.app" rel="noopener noreferrer"&gt;Growth Engine&lt;/a&gt;, and the same eight stages show up every time the system survives contact with users. This guide is the reference I wish I'd had when I started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://maketocreate.com/agentic-ai-explained-what-it-is-how-it-works-and-why-it-matters/" rel="noopener noreferrer"&gt;foundational guide to agentic AI&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;95% of GenAI pilots fail in production. The root cause is context architecture, not model selection (&lt;a href="https://mlq.ai/media/quarterly_decks/v0.1_State_of_AI_in_Business_2025_Report.pdf" rel="noopener noreferrer"&gt;MIT NANDA&lt;/a&gt;, 2025).&lt;/li&gt;
&lt;li&gt;Production agents need 8 discrete stages: intent classification → parallel retrieval → reranking → compression → context assembly → token-budget audit → guardrails → observability.&lt;/li&gt;
&lt;li&gt;95% of data teams plan to invest in context engineering training in 2026 (&lt;a href="https://datahub.com/blog/context-engineer/" rel="noopener noreferrer"&gt;DataHub&lt;/a&gt;, 2026).&lt;/li&gt;
&lt;li&gt;Token budgets aren't free, and the curve differs by vendor: Gemini 3.1 Pro doubles its rate above 200k tokens and GPT-5.5 charges 2× input above 272k, while current Claude models price the full 1M window flat. Architecture decides cost.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What Is Context Engineering Architecture?
&lt;/h2&gt;

&lt;p&gt;Context engineering architecture is the system-level design pattern for assembling the exact tokens an LLM needs to complete a task: dynamically, every turn, within a measured token budget. It treats context as a finite resource with diminishing marginal returns, not as a magic-prompt input (&lt;a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents" rel="noopener noreferrer"&gt;Anthropic Engineering&lt;/a&gt;, 2025).&lt;/p&gt;

&lt;p&gt;Prompt engineering optimizes a static template. Context engineering optimizes a runtime pipeline. The difference shows up the moment your agent has to deal with conversation history, retrieved documents, tool outputs, and user-specific memory all at once.&lt;/p&gt;

&lt;p&gt;Here's the practical distinction. A prompt engineer asks: &lt;em&gt;"What's the best instruction to give the model?"&lt;/em&gt; A context engineer asks: &lt;em&gt;"Of the 1.4M tokens we could give the model, which 24,000 actually matter for this turn, and how do we pick them in 80 milliseconds?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Both questions have answers. Only the second one survives production load.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://maketocreate.com/the-rise-of-ai-native-apps-why-architecture-beats-features/" rel="noopener noreferrer"&gt;why AI-native apps need new architectural patterns&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The frame shift:&lt;/strong&gt; prompt engineering treats the LLM as a black box you negotiate with. Context engineering treats the LLM as a deterministic function whose output is a function of its input. The input is a system you design, not a string you write.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Why Do Production Agents Fail Without Context Engineering?
&lt;/h2&gt;

&lt;p&gt;Production agents fail because LLMs degrade non-linearly with context size. Stanford research shows retrieval accuracy drops more than 30% when relevant information sits in the middle of a long context window rather than at the start or end (&lt;a href="https://arxiv.org/abs/2307.03172" rel="noopener noreferrer"&gt;Liu et al.&lt;/a&gt;, 2023). This is the now-famous "lost in the middle" problem, and it gets worse as context grows.&lt;/p&gt;

&lt;p&gt;The Datadog State of AI Engineering report found something even more revealing. In production traces, &lt;strong&gt;69% of all input tokens were system-prompt tokens&lt;/strong&gt;: instructions, policies, and tool definitions that the same agent re-sends on every single call (&lt;a href="https://www.datadoghq.com/state-of-ai-engineering/" rel="noopener noreferrer"&gt;Datadog&lt;/a&gt;, 2026). That's not context. That's expensive boilerplate, repeated forever, drowning the actual question.&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%2F5hjrm2dvmczo54adm7os.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%2F5hjrm2dvmczo54adm7os.png" alt="Retrieval accuracy by document position: 72% at position 1, dropping to 40% in the middle of the context window, recovering to 70% at the last position" width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;According to a 2026 Anthropic engineering analysis, "context must be treated as a finite resource with diminishing marginal returns" (&lt;a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents" rel="noopener noreferrer"&gt;Anthropic Engineering&lt;/a&gt;, 2025). Stuff the window indiscriminately and your accuracy goes down even though your token bill goes up. That's the economics of bad context architecture in one sentence.&lt;/p&gt;

&lt;p&gt;semantic caching to reduce repeated context costs&lt;/p&gt;




&lt;h2&gt;
  
  
  What Are the 8 Stages of a Production Context Pipeline?
&lt;/h2&gt;

&lt;p&gt;A production context pipeline runs eight discrete stages on every agent turn: intent classification, parallel retrieval, reranking, compression, context assembly, token-budget audit, guardrails, and observability. Each stage has a specific failure mode, a measurable output, and a place where you can swap implementations without rewriting the rest. This is the architectural difference between a demo and a system.&lt;/p&gt;

&lt;p&gt;Most articles on context engineering stop at "use RAG and summarize older messages." That's not architecture. That's two patterns. The pipeline below is what you actually run when an agent has to handle a thousand concurrent users with auditable behavior.&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%2Fimages.unsplash.com%2Fphoto-1580106815433-a5b1d1d53d85%3Fw%3D1200%26q%3D80" 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%2Fimages.unsplash.com%2Fphoto-1580106815433-a5b1d1d53d85%3Fw%3D1200%26q%3D80" alt="Long glass corridor inside a data center, suggesting linear stage-by-stage pipeline flow" width="1200" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's walk through each stage. For each one I'll give you the job, the failure mode, the metric, and a code sketch.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 1: How Does Intent Classification Route the Request?
&lt;/h2&gt;

&lt;p&gt;Intent classification is the router that decides what &lt;em&gt;kind&lt;/em&gt; of context the request needs before any retrieval happens. A small, fast classifier (often a 7B model or even a logistic regression on embeddings) tags the user's input with an intent (&lt;code&gt;lookup&lt;/code&gt;, &lt;code&gt;multi_hop_reasoning&lt;/code&gt;, &lt;code&gt;code_generation&lt;/code&gt;, &lt;code&gt;tool_call&lt;/code&gt;, &lt;code&gt;chitchat&lt;/code&gt;) and routes the turn to a different downstream pipeline for each.&lt;/p&gt;

&lt;p&gt;Why does this matter? Because you don't need vector retrieval for "thanks." You don't need conversation history for a fresh code-review request. And you absolutely don't need a 24-document RAG dump for a math question. Skipping the router is how teams end up paying for retrieval on every turn whether it's needed or not.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Stage 1: Intent classification, fast, cheap, deterministic
&lt;/span&gt;&lt;span class="n"&gt;INTENTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lookup&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reasoning&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_call&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code_gen&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chitchat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;classify_intent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;embed_fast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# ~5ms with bge-small
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;classifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embedding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# logreg, ~1ms
&lt;/span&gt;
&lt;span class="n"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;classify_intent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PIPELINES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# different stages run for each intent
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The failure mode here is simple. Classify wrong, and the rest of the pipeline does work that doesn't help. The metric is intent-accuracy on a held-out eval set, plus the percentage of turns that bypass retrieval entirely (target: 20-40% of agent turns don't need RAG at all).&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 2: Why Run Retrieval in Parallel Instead of Sequentially?
&lt;/h2&gt;

&lt;p&gt;Parallel retrieval fans the query out across multiple data sources at once (vector store, full-text search, knowledge graph, recent conversation memory, user profile) and waits for all of them to respond. The vector database market is projected to grow from USD $2.65B in 2025 to $8.95B by 2030, a 27.5% CAGR (&lt;a href="https://www.marketsandmarkets.com/Market-Reports/vector-database-market-112683895.html" rel="noopener noreferrer"&gt;MarketsandMarkets&lt;/a&gt;, 2025), but a vector store alone is rarely enough.&lt;/p&gt;

&lt;p&gt;Real production retrieval is hybrid. You hit BM25 for exact-match terms, dense embeddings for semantic similarity, a graph for entity relationships, and your CRM or feature store for user-specific facts, all at the same time. Then you union the results.&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%2Fimages.unsplash.com%2Fphoto-1515879218367-8466d910aaa4%3Fw%3D1200%26q%3D80" 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%2Fimages.unsplash.com%2Fphoto-1515879218367-8466d910aaa4%3Fw%3D1200%26q%3D80" alt="Engineer's monitor displaying terminal code, used for the parallel retrieval and reranking stage" width="1200" height="801"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Stage 2: Parallel retrieval, fan out, wait for all
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parallel_retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Doc&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nf"&gt;vector_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;       &lt;span class="c1"&gt;# semantic
&lt;/span&gt;        &lt;span class="nf"&gt;bm25_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;         &lt;span class="c1"&gt;# lexical
&lt;/span&gt;        &lt;span class="nf"&gt;graph_lookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;extract_entities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;  &lt;span class="c1"&gt;# entities
&lt;/span&gt;        &lt;span class="nf"&gt;memory_recall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;    &lt;span class="c1"&gt;# user memory
&lt;/span&gt;    &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;dedupe_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;flatten&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The failure mode is &lt;em&gt;retrieval starvation&lt;/em&gt;: a slow source becomes the bottleneck. Set per-source timeouts (200-300ms), drop late responses, and proceed with what you have. The metric is recall@50 across the union, not any single source.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What I learned shipping this:&lt;/strong&gt; every team I've worked with under-sizes their k. They ask for top-5 and wonder why the answer's missing. Retrieve 20-50 candidates from each source. The reranker in stage 3 is what gets you down to 5, and it's better at picking than the embedding similarity score.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://maketocreate.com/ai-agents-for-solo-founders-how-to-run-a-business-without-employees/" rel="noopener noreferrer"&gt;agent infrastructure patterns for small teams&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 3: How Much Does Reranking Actually Improve Accuracy?
&lt;/h2&gt;

&lt;p&gt;Reranking takes the 50-200 candidate documents from parallel retrieval and re-scores them with a more expensive cross-encoder, returning the top 3-10 that actually answer the question. The gains are well documented. Databricks testing found reranking improves retrieval quality by up to 48% over baseline retrieval and cuts hallucinations by 35% compared to raw embedding similarity, while ZeroEntropy's own zerank-1 reports a 28% NDCG@10 lift over baseline retrievers (&lt;a href="https://zeroentropy.dev/articles/ultimate-guide-to-choosing-the-best-reranking-model-in-2025/" rel="noopener noreferrer"&gt;ZeroEntropy&lt;/a&gt;, 2025). The latency cost depends entirely on which model you pick. Dedicated rerankers land around 100ms for Cohere's rerank-3.5 and roughly 60ms for zerank-1, while general-purpose cross-encoders run anywhere from 200ms to 2 seconds per query. At the top of the current leaderboard, Cohere's Rerank 4 Pro scores 1627 ELO, about 170 points above its v3.5 predecessor and more than 400 points ahead on business and finance tasks (&lt;a href="https://cohere.com/blog/rerank-4" rel="noopener noreferrer"&gt;Cohere&lt;/a&gt;, 2026).&lt;/p&gt;

&lt;p&gt;That accuracy delta is what kills the demo-to-production gap for most RAG pipelines.&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%2Fmfe91izdjgfg39ooe51a.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%2Fmfe91izdjgfg39ooe51a.png" alt="Measured gains from a reranking stage: up to 48% retrieval quality uplift and 35% fewer hallucinations (Databricks), and a 28% NDCG@10 lift for zerank-1 (ZeroEntropy)" width="800" height="514"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Stage 3: Reranking - bring the top-50 down to top-5
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rerank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Doc&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Doc&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;pairs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cross_encoder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# budget 100-200ms for 50 pairs
&lt;/span&gt;    &lt;span class="n"&gt;ranked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ranked&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A cross-encoder reranker is one of the highest-leverage additions you can make to an existing RAG pipeline. The failure mode is mostly cost (each rerank pass costs roughly 10x the embedding pass), and the metric is precision@5 on labeled query-document pairs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 4: What Does Context Compression Look Like in Production?
&lt;/h2&gt;

&lt;p&gt;Context compression turns the top reranked documents into the smallest faithful representation that still answers the question. This isn't summarization in the GPT-3 sense. It's structured extraction, span selection, and key-value distillation aimed at removing tokens that don't pull weight.&lt;/p&gt;

&lt;p&gt;Datadog's 2026 traces make the real target clear: system-prompt tokens, not retrieved documents, dominated the window at 69% of all input tokens (&lt;a href="https://www.datadoghq.com/state-of-ai-engineering/" rel="noopener noreferrer"&gt;Datadog&lt;/a&gt;, 2026). That means compression has to happen on more than just RAG output. Tool definitions get pruned to the ones the intent classifier thinks are relevant. Conversation history gets summarized once it exceeds a length threshold. Older tool outputs get written to disk and replaced with a pointer.&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%2Fe1n667wgja0by11858qw.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%2Fe1n667wgja0by11858qw.png" alt="Donut chart showing 69% of production input tokens are system-prompt tokens and 31% is everything else, per Datadog 2026 traces" width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A few patterns that work in practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Span selection&lt;/strong&gt; over generative summarization for retrieved documents: pick the 2-3 sentences that match the query, throw away the rest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool-shedding&lt;/strong&gt;: only include tool definitions for tools the router said are plausibly relevant. A 50-tool agent shouldn't ship 50 tool schemas every turn.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conversation summarization&lt;/strong&gt; at a threshold (say, 8 turns): replace older turns with a structured summary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Externalized memory&lt;/strong&gt;: write tool outputs and intermediate state to a key-value store, replace them with pointers in the prompt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The metric is the compression ratio (output tokens / input tokens) at preserved task accuracy. A good rule of thumb: you should be able to compress 4-6x without measurable accuracy loss on your eval set.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://maketocreate.com/i-built-a-multi-agent-code-review-skill-for-claude-code-heres-how-it-works/" rel="noopener noreferrer"&gt;multi-agent orchestration patterns&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 5: How Does Context Assembly Order Tokens for the Model?
&lt;/h2&gt;

&lt;p&gt;Context assembly is the deterministic step that takes everything from the previous stages (system prompt, compressed retrieval, tool definitions, conversation summary, current message) and lays them out in a specific order designed to fight context rot. Anthropic's research is explicit that ordering matters as much as content: the start and end of the window are where attention is strongest (&lt;a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents" rel="noopener noreferrer"&gt;Anthropic Engineering&lt;/a&gt;, 2025).&lt;/p&gt;

&lt;p&gt;A reasonable default ordering, top to bottom:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;System prompt&lt;/strong&gt;: short, declarative, the policy and persona&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool definitions&lt;/strong&gt;: pruned to the relevant subset&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long-term memory&lt;/strong&gt;: user-specific facts, structured&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retrieved context&lt;/strong&gt;: the reranked, compressed top-K&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conversation summary&lt;/strong&gt;: older history, compressed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recent turns&lt;/strong&gt;: last 4-8 messages verbatim&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Current user message&lt;/strong&gt;: the actual question, last&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The current user message goes last because that's where the model's attention is strongest. The system prompt goes first because that's the second-strongest position, and you want the policy bracketing the request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Stage 5: Context assembly - deterministic order
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;assemble_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ContextParts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;render_tools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;long_term_memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;render_memory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;long_term_memory&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;retrieved_docs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;render_docs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;retrieved_docs&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recent_turns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_message&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't get clever here. The assembler should be a pure function: same inputs, same outputs, no LLM calls. That's how you replay traces in observability and trust the result.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 6: How Do You Audit Token Budgets Before Sending the Prompt?
&lt;/h2&gt;

&lt;p&gt;Token-budget audit is the mandatory checkpoint between assembly and sending. It counts the assembled tokens, compares them to the model's effective window, and either fits or rejects the prompt before you spend money on it. This is the stage every shallow tutorial skips.&lt;/p&gt;

&lt;p&gt;Token budgets aren't free, and the pricing structure varies more than most teams expect. Some vendors charge a flat rate across the whole window, others tier it at a threshold:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Claude Opus 5&lt;/strong&gt;: 1M context at $5/$25 per million tokens, flat across the window with no long-context premium (&lt;a href="https://platform.claude.com/docs/en/about-claude/models/overview" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude Sonnet 5&lt;/strong&gt;: 1M context at $3/$15 per million, also flat.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GPT-5.5&lt;/strong&gt;: 1.05M context at $5/$30 per million, rising to 2× input and 1.5× output above 272k (&lt;a href="https://developers.openai.com/api/docs/models/gpt-5.5" rel="noopener noreferrer"&gt;OpenAI&lt;/a&gt;, 2026).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini 3.1 Pro&lt;/strong&gt;: $2/$12 per million under 200k, doubling to $4/$18 above it (&lt;a href="https://ai.google.dev/gemini-api/docs/pricing" rel="noopener noreferrer"&gt;Google&lt;/a&gt;, 2026).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The lesson isn't that long context is uniformly expensive. It's that the cost curve differs by vendor, so a budget audit tuned to one model's threshold will silently mis-price another.&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%2Fkfelstqe9b4gwtoqa1s6.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%2Fkfelstqe9b4gwtoqa1s6.png" alt="Slope chart of input price per 1M tokens below vs above each vendor long-context threshold: Claude Opus 5 flat at $5 and Sonnet 5 flat at $3, GPT-5.5 rising $5 to $10, Gemini 3.1 Pro rising $2 to $4" width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The audit step is short and worth its weight in incidents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Stage 6: Token-budget audit
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;audit_budget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ModelConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AuditResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;count_tokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokenizer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hard_limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;BudgetExceeded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hard_limit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;soft_limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;In premium tier: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; tokens, +2x pricing applies&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;AuditResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;premium&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;soft_limit&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;standard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why does this matter beyond cost? Because budget overruns aren't graceful. They truncate, often silently, and your model loses exactly the part of the prompt you needed most. The audit gives you a place to fail loudly and trigger a re-compress if you've exceeded your target.&lt;/p&gt;

&lt;p&gt;If you want to see this accounting in a tool you already use rather than one you build, Claude Code exposes the same numbers through &lt;code&gt;/context&lt;/code&gt;, down to what its system prompt, memory files, and skill descriptions consume before your first message.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://maketocreate.com/claude-code-context-window-size-200k-vs-1m-what-fills-it/" rel="noopener noreferrer"&gt;what actually fills a Claude Code context window, measured&lt;/a&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%2Fimages.unsplash.com%2Fphoto-1537884944318-390069bb8665%3Fw%3D1200%26q%3D80" 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%2Fimages.unsplash.com%2Fphoto-1537884944318-390069bb8665%3Fw%3D1200%26q%3D80" alt="Monitor with dense code on a dark background, representing token-budget audit instrumentation" width="1200" height="800"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 7: What Guardrails Belong in the Context Pipeline?
&lt;/h2&gt;

&lt;p&gt;Guardrails are the validation, redaction, and policy-enforcement layer that runs before the prompt leaves your service and after the model's response comes back. Most teams bolt these on at the application layer; production teams bake them into the context pipeline because that's where the data lives at the right granularity.&lt;/p&gt;

&lt;p&gt;Guardrails that belong in the pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PII redaction&lt;/strong&gt; before retrieval: never let a customer query leak names or emails into your vector store logs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool-call whitelisting&lt;/strong&gt;: the model is only allowed to call tools the intent classifier authorized for this turn.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output schema validation&lt;/strong&gt;: if you asked for JSON, parse it; if it fails, retry with the parser error included as feedback (this single pattern fixes most "the model didn't follow the format" complaints).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Citation requirement&lt;/strong&gt;: if the response cites a fact, that fact must appear in the retrieved context. If it doesn't, flag it as a hallucination candidate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refusal policy&lt;/strong&gt;: block topics the agent shouldn't address before they hit the model, not after.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cognizant deployed 1,000 context engineers across its ContextFabric platform in late 2025 and reported up to 70% fewer hallucinations versus baseline agents, largely attributed to disciplined guardrails plus retrieval (&lt;a href="https://news.cognizant.com/2025-08-29-Cognizant-to-Deploy-1,000-Context-Engineers,-Powered-by-ContextFabric-TM-,-to-Industrialize-Agentic-AI" rel="noopener noreferrer"&gt;Cognizant&lt;/a&gt;, 2025).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Stage 7: Guardrails - bidirectional
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pre_send_guardrails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;redact_pii&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;post_response_guardrails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;retrieved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Doc&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ValidatedResponse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;validate_schema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;retry_with_parser_feedback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;citations_grounded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;retrieved&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;flag_hallucination&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ValidatedResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://maketocreate.com/codeprobe-9-specialized-ai-agents-that-audit-your-codebase-for-solid-security-performance/" rel="noopener noreferrer"&gt;AI agent guardrails for code review&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Stage 8: How Do You Observe a Context Pipeline in Production?
&lt;/h2&gt;

&lt;p&gt;Observability for context engineering means instrumenting every stage with OpenTelemetry GenAI &lt;a href="https://maketocreate.com/opentelemetry-genai-tracing-ai-agents-without-leaking-pii/" rel="noopener noreferrer"&gt;semantic conventions&lt;/a&gt; so you can answer questions like "which stage caused this bad answer?" without re-running the whole pipeline. According to LangChain's State of Agent Engineering 2025, &lt;strong&gt;89% of organizations have implemented some form of agent observability&lt;/strong&gt;. Among teams running agents in production, that number jumps to 94% (&lt;a href="https://www.langchain.com/state-of-agent-engineering" rel="noopener noreferrer"&gt;LangChain&lt;/a&gt;, 2025).&lt;/p&gt;

&lt;p&gt;The OpenTelemetry semantic conventions for GenAI standardize the spans, attributes, and events you should emit (&lt;a href="https://opentelemetry.io/docs/specs/semconv/gen-ai/" rel="noopener noreferrer"&gt;OpenTelemetry&lt;/a&gt;, 2025). At minimum, every agent turn should produce a trace with one span per pipeline stage, plus the full prompt and response captured as events.&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%2Fimages.unsplash.com%2Fphoto-1581094794329-c8112a89af12%3Fw%3D1200%26q%3D80" 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%2Fimages.unsplash.com%2Fphoto-1581094794329-c8112a89af12%3Fw%3D1200%26q%3D80" alt="Developer in a dark workstation typing on multiple keyboards, representing observability and on-call" width="1200" height="1799"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What to capture per stage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Intent classification&lt;/strong&gt;: predicted intent, confidence, time-to-classify&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retrieval&lt;/strong&gt;: sources queried, doc IDs returned, recall@k if you have ground truth&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reranking&lt;/strong&gt;: top-k IDs, reranker scores, latency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compression&lt;/strong&gt;: input tokens, output tokens, ratio&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assembly&lt;/strong&gt;: final token count, ordering checksum&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit&lt;/strong&gt;: total tokens, budget tier, pass/fail&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guardrails&lt;/strong&gt;: flags raised, redactions made, validation outcomes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model call&lt;/strong&gt;: model name, prompt tokens, completion tokens, finish reason, time-to-first-token, total latency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Datadog 2026 report found that &lt;strong&gt;5% of all LLM call spans returned an error in February 2026&lt;/strong&gt;, and 60% of those were caused by exceeded rate limits. By March the error rate had dropped to 2%, with rate limits accounting for almost a third of them, which still worked out to nearly 8.4 million rate-limit errors in a single month across observed production traffic (&lt;a href="https://www.datadoghq.com/state-of-ai-engineering/" rel="noopener noreferrer"&gt;Datadog&lt;/a&gt;, 2026). Without per-stage instrumentation, you can't tell whether your agent is failing because retrieval was empty, the assembly was malformed, or the model itself rate-limited. With it, you can.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Stage 8: Observability - per-stage spans
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;opentelemetry&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;trace&lt;/span&gt;
&lt;span class="n"&gt;tracer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_tracer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;context-pipeline&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_as_current_span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent.turn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;turn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_as_current_span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;intent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;classify_intent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gen_ai.intent.predicted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_as_current_span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;retrieve&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;docs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parallel_retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gen_ai.retrieval.docs_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="c1"&gt;# ... and so on for each stage
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What I learned shipping this:&lt;/strong&gt; the single highest-leverage piece of instrumentation is logging the &lt;em&gt;assembled&lt;/em&gt; prompt, every token, every turn, to a queryable store. When a user complains "the agent gave me a wrong answer," you need to see the exact bytes the model saw. Aggregated metrics won't tell you that.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  How Do Memory and Context Engineering Relate?
&lt;/h2&gt;

&lt;p&gt;Memory is the long-lived state that persists across agent turns: user preferences, prior conversations, distilled facts. It feeds into stages 2 (retrieval) and 5 (assembly). Memory is &lt;em&gt;part of&lt;/em&gt; a context pipeline, not a separate system. The 2025 mem0 Series A funding round of $24M, plus its selection as the exclusive memory provider for AWS Strands Agent SDK, signals just how foundational this layer has become (&lt;a href="https://sacra.com/c/mem0/" rel="noopener noreferrer"&gt;Sacra&lt;/a&gt;, 2025).&lt;/p&gt;

&lt;p&gt;There are three memory types that show up in every production architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Episodic memory&lt;/strong&gt;: the conversation history itself, summarized after a threshold&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Semantic memory&lt;/strong&gt;: distilled facts the user has stated ("my company is a Series B SaaS")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Procedural memory&lt;/strong&gt;: patterns the agent has learned about the user ("they prefer concise answers")&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Memory products like mem0, Letta, and LlamaIndex differ mostly on how aggressively they distill and index these, but they all plug into the same stages of your pipeline. Don't treat memory as a feature you bolt on later. It's stage 2 input.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://maketocreate.com/the-end-of-user-interfaces-how-ai-agents-will-kill-the-dashboard/" rel="noopener noreferrer"&gt;how persistent memory changes interface design&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How Do You Build a Context Pipeline Step by Step?
&lt;/h2&gt;

&lt;p&gt;Build the pipeline in order of leverage, not in order of stages. Most teams ship the model integration first and discover the architecture problems later. Here's the order I'd recommend if you're starting from a working prompt-and-RAG demo and trying to harden it for production.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Add observability first (Stage 8).&lt;/strong&gt; Before you change anything, instrument what's already running. You can't optimize a pipeline you can't see. OpenTelemetry GenAI conventions are stable enough to adopt in 2026.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add the token-budget audit (Stage 6).&lt;/strong&gt; Once you can see token counts per turn, surprising things become visible, like the 69% system-prompt domination Datadog found.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add reranking (Stage 3).&lt;/strong&gt; Highest accuracy-per-dollar improvement of any stage. Cohere's Rerank 4 or ZeroEntropy's zerank models will get you most of the documented uplift in a single afternoon.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add intent classification (Stage 1).&lt;/strong&gt; Once you have telemetry, you'll see how many turns don't actually need retrieval. Routing them away cuts cost and latency immediately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add compression (Stage 4).&lt;/strong&gt; Now that you can measure, optimize the largest contributor, usually the system prompt or the retrieved-doc dump.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add guardrails (Stage 7).&lt;/strong&gt; With the rest of the pipeline structured, schema-validation, redaction, and grounding checks slot in naturally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Productionize parallel retrieval and assembly (Stages 2 &amp;amp; 5).&lt;/strong&gt; These are usually already partially built. You're just making them deterministic and traced.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The whole sequence is roughly a quarter of focused work for a small team. The result is an agent that survives ten times the load of the demo it started as.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Are the Context Engineering Best Practices That Actually Matter?
&lt;/h2&gt;

&lt;p&gt;The best practices that survive contact with production are mostly about measurement and ordering, not about clever prompt wording. Seven rules cover almost everything I've had to learn the expensive way.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Practice&lt;/th&gt;
&lt;th&gt;Why it matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Measure the system prompt before anything else&lt;/td&gt;
&lt;td&gt;It is usually the largest line item, not the retrieved documents. Datadog's traces put it at 69% of input tokens.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Set the token ceiling before you build&lt;/td&gt;
&lt;td&gt;A budget you enforce in code (Stage 6) is an architectural constraint. A budget you hold in your head is a wish.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Put the answer at the edges of the window&lt;/td&gt;
&lt;td&gt;Attention is strongest at the start and end. Burying key context in the middle costs you more than 30% accuracy.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rerank before you compress, never after&lt;/td&gt;
&lt;td&gt;Compression is lossy. Compressing 50 candidates and then ranking them means you rank damaged text.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Version the assembly, not the prompt&lt;/td&gt;
&lt;td&gt;The thing that changes behavior is the order and composition of the window. Diff that, and your regressions become explainable.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Instrument per stage or you are guessing&lt;/td&gt;
&lt;td&gt;Without a span per stage you cannot tell an empty retrieval from a malformed assembly from a rate limit.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Treat the pricing curve as an architecture input&lt;/td&gt;
&lt;td&gt;Thresholds differ by vendor. A budget tuned to one model's tier silently mis-prices another.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The one I see skipped most often is the second. Teams add retrieval, add memory, add tools, and never write down what a turn is allowed to cost. Six months later the agent works and nobody can explain the bill.&lt;/p&gt;

&lt;p&gt;The one that pays back fastest is the fourth. Reordering compression after reranking is usually a few hours of work and it stops you from throwing away the sentence that held the answer.&lt;/p&gt;

&lt;p&gt;If you only adopt two of these, take measurement first and ordering second. Everything else in this pipeline is easier to fix once you can see what the model is actually receiving.&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How does context engineering differ from prompt engineering?
&lt;/h3&gt;

&lt;p&gt;Prompt engineering optimizes a static instruction string to elicit a desired output. Context engineering optimizes a dynamic, runtime pipeline that assembles instructions, retrieved data, memory, and tools per turn within a measured token budget. 82% of IT leaders agree prompt engineering alone is no longer sufficient at scale (&lt;a href="https://datahub.com/blog/context-engineering-vs-prompt-engineering/" rel="noopener noreferrer"&gt;DataHub&lt;/a&gt;, 2026).&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I need all 8 stages for a small project?
&lt;/h3&gt;

&lt;p&gt;No. A side-project agent can work with just stages 2 (retrieval), 5 (assembly), and 8 (basic observability). The other stages get added as the agent scales. You'll feel the pain of missing them when traffic and data grow. Cognizant's deployment of 1,000 context engineers signals these stages matter at enterprise scale (&lt;a href="https://news.cognizant.com/2025-08-29-Cognizant-to-Deploy-1,000-Context-Engineers,-Powered-by-ContextFabric-TM-,-to-Industrialize-Agentic-AI" rel="noopener noreferrer"&gt;Cognizant&lt;/a&gt;, 2025).&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does context order matter inside the prompt?
&lt;/h3&gt;

&lt;p&gt;LLMs pay more attention to tokens at the start and end of their context window. Stanford's "Lost in the Middle" research found a &amp;gt;30% accuracy drop for information placed in the middle of a long context (&lt;a href="https://arxiv.org/abs/2307.03172" rel="noopener noreferrer"&gt;Liu et al.&lt;/a&gt;, 2023). Putting the system prompt first and the user's question last is the strongest default ordering.&lt;/p&gt;

&lt;h3&gt;
  
  
  How big should my token budget be?
&lt;/h3&gt;

&lt;p&gt;It depends on your model and intent. For most agent turns, target 8k-24k tokens of total context. Budget audits (Stage 6) should reject anything beyond your soft limit and trigger a recompress. Check your specific model before you set the ceiling, because the pricing curve is not consistent across vendors. Gemini 3.1 Pro doubles its rate above 200k and GPT-5.5 charges 2× input above 272k, while the current Claude Opus and Sonnet models price the full 1M window flat (&lt;a href="https://ai.google.dev/gemini-api/docs/pricing" rel="noopener noreferrer"&gt;Google&lt;/a&gt;, 2026) (&lt;a href="https://developers.openai.com/api/docs/models/gpt-5.5" rel="noopener noreferrer"&gt;OpenAI&lt;/a&gt;, 2026).&lt;/p&gt;

&lt;h3&gt;
  
  
  Which framework should I use to build this?
&lt;/h3&gt;

&lt;p&gt;LangGraph, Vercel AI SDK, AutoGen, and Anthropic's official agent SDK all ship context-management primitives in 2026. The pipeline above is framework-agnostic. Pick the one that matches your stack. If you're starting fresh in TypeScript, Vercel AI SDK is the lowest-friction; in Python, LangGraph or the Anthropic SDK directly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion: The Architecture Is the Product
&lt;/h2&gt;

&lt;p&gt;The teams shipping working agents in 2026 aren't winning because they have a better model. They're winning because they have a better pipeline. The 8 stages above, intent classification, parallel retrieval, reranking, compression, assembly, token-budget audit, guardrails, observability, are the difference between a system that works in a notebook and one that survives a Tuesday afternoon at 3pm with a thousand concurrent users.&lt;/p&gt;

&lt;p&gt;Three things to take with you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Treat context as a finite, measured resource.&lt;/strong&gt; Stage 6 (the token-budget audit) is the highest-leverage discipline most teams skip.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability before optimization.&lt;/strong&gt; OpenTelemetry GenAI conventions are stable; instrument first, change second.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The architecture is the moat.&lt;/strong&gt; Models will get better. Your pipeline is what compounds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building agents and haven't formalized these stages yet, start with the observability layer this week. Everything else flows from being able to see what's actually in your prompts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://maketocreate.com/agentic-ai-explained-what-it-is-how-it-works-and-why-it-matters/" rel="noopener noreferrer"&gt;foundational guide to agentic AI fundamentals&lt;/a&gt;&lt;/p&gt;

</description>
      <category>contextengineering</category>
      <category>aiagents</category>
      <category>llmarchitecture</category>
      <category>rag</category>
    </item>
    <item>
      <title>Claude Cowork Security Risks: What It Can Touch, and What It Can't</title>
      <dc:creator>Nishil Bhave</dc:creator>
      <pubDate>Wed, 29 Jul 2026 00:55:13 +0000</pubDate>
      <link>https://dev.to/nishilbhave/claude-cowork-security-risks-what-it-can-touch-and-what-it-cant-525p</link>
      <guid>https://dev.to/nishilbhave/claude-cowork-security-risks-what-it-can-touch-and-what-it-cant-525p</guid>
      <description>&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%2Fv2j7f17y08zpe4k674cp.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%2Fv2j7f17y08zpe4k674cp.png" alt="A dark archive of locked filing cabinets, one drawer open in warm light: Claude Cowork's scoped file access in a picture." width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The moment that made me stop and think wasn't a bug. It was Claude Cowork asking, politely, whether it could open the folder where I keep client contracts. I said no. Then I sat there wondering why my instinct was so fast, and whether it was even right.&lt;/p&gt;

&lt;p&gt;That's the real question under every "is Claude Cowork safe" search. It's an agent that reads, writes, and edits files on your Mac or Windows machine, runs multi-step tasks on its own, and does it all on Opus 4.8. I live in Claude Code every day, so I'm not agent-shy. But letting a model touch my file system is a different kind of trust than letting it write code in a terminal I'm watching. So I read Anthropic's actual docs, tested the consent flow, and here's my honest read on the risks, the legal questions, and what the plugin system quietly widens.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cowork only reaches folders you explicitly connect, and it can't touch anything else. Permanently deleting a file always needs your approval, in every mode (&lt;a href="https://support.claude.com/en/articles/13364135-use-claude-cowork-safely" rel="noopener noreferrer"&gt;Claude Cowork docs&lt;/a&gt;, 2026).&lt;/li&gt;
&lt;li&gt;Its work runs in an isolated, temporary environment on Anthropic's servers that can't reach your home or company network, and gets wiped when the session ends (&lt;a href="https://support.claude.com/en/articles/13364135-use-claude-cowork-safely" rel="noopener noreferrer"&gt;Claude Cowork docs&lt;/a&gt;, 2026).&lt;/li&gt;
&lt;li&gt;Prompt injection is the risk that matters most. OWASP ranks it the #1 LLM vulnerability for the second edition running (&lt;a href="https://owasp.org/www-project-top-10-for-large-language-model-applications/" rel="noopener noreferrer"&gt;OWASP&lt;/a&gt;, 2025).&lt;/li&gt;
&lt;li&gt;Data handling depends on your plan. Commercial and Enterprise don't train on your data by default; consumer Pro and Max follow the consumer policy, so check your privacy toggle (&lt;a href="https://privacy.claude.com/en/articles/7996868-is-my-data-used-for-model-training" rel="noopener noreferrer"&gt;Anthropic Privacy Center&lt;/a&gt;, 2026).&lt;/li&gt;
&lt;li&gt;The legal exposure isn't the tool, it's the folder you point it at. You stay responsible for every action Claude takes on your behalf.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Is Claude Cowork safe to use?
&lt;/h2&gt;

&lt;p&gt;Cowork is about as safe as the scope you give it, and the defaults lean conservative. It can't reach anything outside the folders you connect, and it asks before it does anything significant (&lt;a href="https://claude.com/product/cowork" rel="noopener noreferrer"&gt;Claude Cowork&lt;/a&gt;, 2026). The risk isn't that it goes rogue across your whole drive. The risk is the access you hand it and the instructions it might read inside that access.&lt;/p&gt;

&lt;p&gt;Here's why the question feels loaded, and why your caution is reasonable. Enterprise leaders already rank cybersecurity among their top AI worries (&lt;a href="https://hai.stanford.edu/ai-index/2025-ai-index-report/responsible-ai" rel="noopener noreferrer"&gt;Stanford HAI AI Index&lt;/a&gt;, 2025), and most organizations are nowhere near ready for autonomous tools. In IBM's 2025 breach study, 63% of breached organizations either had no AI governance policy or were still developing one (&lt;a href="https://www.ibm.com/reports/data-breach" rel="noopener noreferrer"&gt;IBM Cost of a Data Breach&lt;/a&gt;, 2025). An agent that edits files lands right in that gap.&lt;/p&gt;

&lt;p&gt;So when people ask if it's safe, I split the answer. Is the tool built with sane guardrails? Mostly yes, and I'll show the receipts below. Will it be safe in your hands? That depends entirely on what you connect it to and which approval mode you leave running.&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%2Fmp0pqllyb4q5nirpvrdk.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%2Fmp0pqllyb4q5nirpvrdk.png" alt="Horizontal bar chart: in 2025, business leaders named inaccuracy at 64 percent, regulatory compliance at 63 percent, and cybersecurity at 60 percent as their top-of-mind AI risks." width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the full picture of what the product is and who it's for, see the &lt;a href="https://maketocreate.com/what-is-claude-cowork-anthropics-non-coding-desktop-agent-explained/" rel="noopener noreferrer"&gt;complete guide to what Claude Cowork is and does&lt;/a&gt;. This piece stays on the part that keeps people up at night: security, legal, and the access surface.&lt;/p&gt;

&lt;h2&gt;
  
  
  What can Claude Cowork actually access on your computer?
&lt;/h2&gt;

&lt;p&gt;Cowork can read your files, browse the web, run code, use apps you connect, and take screenshots to understand your screen, but only within the folders and tools you grant (&lt;a href="https://support.claude.com/en/articles/13364135-use-claude-cowork-safely" rel="noopener noreferrer"&gt;Claude Cowork docs&lt;/a&gt;, 2026). The product page puts the boundary bluntly: "You choose the folders and tools. Claude can't reach anything else" (&lt;a href="https://claude.com/product/cowork" rel="noopener noreferrer"&gt;Claude Cowork&lt;/a&gt;, 2026).&lt;/p&gt;

&lt;p&gt;That folder boundary is the single most important security fact about the tool. It isn't scanning your whole machine. It sees what's inside the directories you connect, and nothing above or beside them. Anthropic's own guidance is to create a dedicated working folder rather than granting broad access, which is exactly how I'd set it up.&lt;/p&gt;

&lt;p&gt;There's a second layer people miss. The actual work runs in an isolated, temporary environment on Anthropic's servers, separate from your computer, and that environment can't reach your home or company network. It's removed when the session ends (&lt;a href="https://support.claude.com/en/articles/13364135-use-claude-cowork-safely" rel="noopener noreferrer"&gt;Claude Cowork docs&lt;/a&gt;, 2026). If the desktop app is offline, the session can't reach your computer at all. So the blast radius has two walls: the folders you pick, and a sandbox that can't wander onto your LAN.&lt;/p&gt;

&lt;p&gt;When it does need to act in the world, it prefers your connectors and integrations first, falls back to your browser when needed, and only uses your screen as a last resort (&lt;a href="https://claude.com/product/cowork" rel="noopener noreferrer"&gt;Claude Cowork&lt;/a&gt;, 2026). Direct screen and app control, the "computer use" capability, is still labeled a research preview, and it asks permission before accessing each application.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What it can't do:&lt;/strong&gt; reach files outside your connected folders, touch your local network from its sandbox, or permanently delete anything without asking. Those aren't settings you configure. They're how the tool is built.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How does the Claude Cowork consent and permissions flow work?
&lt;/h2&gt;

&lt;p&gt;Cowork gives you three approval modes, and one protection holds across all of them: it always asks before permanently deleting files (&lt;a href="https://support.claude.com/en/articles/13364135-use-claude-cowork-safely" rel="noopener noreferrer"&gt;Claude Cowork docs&lt;/a&gt;, 2026). The modes are manually approve, where you sign off on each action; automatically approve, where Claude reviews an action for safety before running it; and skip all approvals, where it just goes.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approval mode&lt;/th&gt;
&lt;th&gt;What runs without asking&lt;/th&gt;
&lt;th&gt;What always asks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Manually approve&lt;/td&gt;
&lt;td&gt;Nothing; you sign off on each action&lt;/td&gt;
&lt;td&gt;Everything, including deletion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automatically approve&lt;/td&gt;
&lt;td&gt;Actions Claude's safety review clears&lt;/td&gt;
&lt;td&gt;Permanent file deletion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skip all approvals&lt;/td&gt;
&lt;td&gt;Everything else&lt;/td&gt;
&lt;td&gt;Permanent file deletion&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That deletion guarantee is the detail I keep coming back to. Even in "skip all approvals," a permanent delete still stops and waits for you. It's a small design choice that closes off the scariest failure mode, the one where an agent quietly erases the wrong directory. On the buyer-intent question of whether it's free to try, it's included on every paid plan, so you can test the consent flow yourself before trusting it with anything real (&lt;a href="https://maketocreate.com/how-much-does-claude-cowork-cost-in-2026-free-on-every-paid-plan/" rel="noopener noreferrer"&gt;what Cowork costs and why it's free on paid plans&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;In practice, I run manual approve for anything new and only relax it once I've watched the tool work in a folder for a while. The permissions setting can also show you Claude's plan and wait for your approval before anything significant happens, which is the same "read the plan before you execute" rhythm I lean on in Claude Code. If you want to see how that plays out step by step during a real task, that's covered in how permissions actually behave during a live Cowork session.&lt;/p&gt;

&lt;p&gt;The real caveat: skip all approvals is a loaded gun for a reason I'll get to in the risks section. Deletion is protected, sure. Everything else in that mode runs without you in the loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does Anthropic do with your Claude Cowork data?
&lt;/h2&gt;

&lt;p&gt;This is where the plan you're on changes the answer, so read carefully. For commercial products, Anthropic's default is clear: "By default, we will not use your inputs or outputs from our commercial products to train our models" (&lt;a href="https://privacy.claude.com/en/articles/7996868-is-my-data-used-for-model-training" rel="noopener noreferrer"&gt;Anthropic Privacy Center&lt;/a&gt;, 2026). That covers Claude for Work, the API, and Enterprise. If you're running Cowork under a commercial or Enterprise org, your files aren't training fodder by default.&lt;/p&gt;

&lt;p&gt;Consumer plans are different, and this is the part I'd want a lawyer-adjacent friend to underline. Free, Pro, and Max follow the consumer data policy, where chats can be used for model improvement unless you opt out in your privacy settings. Deleted conversations are removed from your history immediately and purged from the backend within about 30 days, while data you opt into training on can be retained de-identified for up to five years (&lt;a href="https://privacy.claude.com/en/articles/10023548-how-long-do-you-store-my-data" rel="noopener noreferrer"&gt;Anthropic Privacy Center&lt;/a&gt;, 2026).&lt;/p&gt;

&lt;p&gt;Here's the gap worth flagging plainly. Anthropic's Cowork safety docs don't spell out a Cowork-specific "we do or don't train on the files you open" line, and neither does the consumer training policy, which never names Cowork at all. By reasonable inference, Cowork on consumer Pro or Max inherits the consumer policy, and Cowork under a commercial org inherits the no-train default. One nuance the consumer policy does state: raw content from connectors, including remote and local MCP servers, is excluded from training (&lt;a href="https://privacy.claude.com/en/articles/10023580-is-my-data-used-for-model-training" rel="noopener noreferrer"&gt;Anthropic Privacy Center&lt;/a&gt;, 2026). That's a connector carve-out, not a file-contents one.&lt;/p&gt;

&lt;p&gt;So a blanket claim that "Anthropic never trains on your Cowork files" isn't something I can stand behind for consumer plans. Check your training toggle, and if the files are sensitive, don't rely on the default.&lt;/p&gt;

&lt;p&gt;One more distinction that trips people up: Zero Data Retention. ZDR applies to eligible Anthropic APIs, products using a commercial org API key, and Claude Code for Enterprise. It does not apply to Claude Free, Pro, or Max (&lt;a href="https://privacy.claude.com/en/articles/8956058-i-have-a-zero-data-retention-agreement-with-anthropic-what-products-does-it-apply-to" rel="noopener noreferrer"&gt;Anthropic Privacy Center&lt;/a&gt;, 2026). If your compliance story depends on ZDR, a consumer Cowork seat won't give it to you.&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%2F5ev1kpj3ux3j413f17k1.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%2F5ev1kpj3ux3j413f17k1.png" alt="Radar chart scoring Claude Cowork across six security dimensions on a 1 to 10 scale: deletion protection 9, folder scoping 8, sandbox isolation 8, audit and logging 7, prompt-injection defense 6, and data-handling clarity 5." width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude Cowork legal considerations: client data, confidentiality, and who's liable
&lt;/h2&gt;

&lt;p&gt;The legal risk with Cowork isn't hypothetical model behavior, it's the data you route through it and the promises you've already made about that data. Anthropic states it directly: "You remain responsible for all actions taken by Claude performed on your behalf" (&lt;a href="https://support.claude.com/en/articles/13364135-use-claude-cowork-safely" rel="noopener noreferrer"&gt;Claude Cowork docs&lt;/a&gt;, 2026). That sentence is the whole legal posture in one line. The tool is a delegate, not a shield.&lt;/p&gt;

&lt;p&gt;So before you point it at a folder, ask the boring questions that actually matter. Do you have a confidentiality obligation on those files? Are they covered by a client NDA, a DPA, HIPAA, or GDPR? On a consumer plan without ZDR and with the training toggle in an uncertain state, running privileged documents through Cowork could put you sideways with a contract you signed. That's not a Cowork flaw. It's the same rule that applies to any cloud tool, just with an agent doing the moving.&lt;/p&gt;

&lt;p&gt;This is why my instinct on the contract folder was right, even before I could explain it. My working rule: consumer Cowork is fine for my own drafts, notes, code, and research. Anything under someone else's confidentiality terms goes through a commercial or Enterprise org with the no-train default and, ideally, an org where an admin has set the guardrails. If you're a solo user weighing whether that's worth it, the comparison in how Cowork's file access model differs from Claude Code's is a useful gut-check on where each tool fits.&lt;/p&gt;

&lt;p&gt;What about a "Claude Cowork legal plugin"? That search maps to something real, and it's worth being precise. Legal is one of the named plugin categories Anthropic ships, alongside finance, HR, and the rest (&lt;a href="https://support.claude.com/en/articles/13837440-use-plugins-in-claude" rel="noopener noreferrer"&gt;Claude plugins docs&lt;/a&gt;, 2026). A legal-category plugin can package skills and connectors for legal work, but installing one doesn't change your obligations or grant any special privacy protection. It's convenience, not compliance. Treat any plugin, legal-branded or not, as another thing widening what the agent can reach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude Cowork plugins and capabilities: what they add to the access surface
&lt;/h2&gt;

&lt;p&gt;Plugins extend what Cowork can do by bundling skills, connectors, and sub-agents into one package, and on desktop the plugins you add yourself are saved locally to your computer (&lt;a href="https://support.claude.com/en/articles/13837440-use-plugins-in-claude" rel="noopener noreferrer"&gt;Claude plugins docs&lt;/a&gt;, 2026). That's the capabilities story people search for under "claude code cowork plugins capabilities 2026," and it's genuinely useful. It's also where the access surface quietly grows.&lt;/p&gt;

&lt;p&gt;Think about what a connector actually is. Cowork supports MCP connectors, both local servers on your machine and remote HTTP servers, across Free, Pro, Max, Team, and Enterprise plans (&lt;a href="https://support.claude.com/en/articles/11176164-use-connectors-to-extend-claude-s-capabilities" rel="noopener noreferrer"&gt;Claude connectors docs&lt;/a&gt;, 2026). Every connector you add is a new door: a database, a SaaS app, a remote endpoint. The folder boundary still holds for files, but connectors open reach into systems that live outside those folders entirely.&lt;/p&gt;

&lt;p&gt;Here's the part I'd underline for anyone in a company. On Enterprise, admins can restrict which actions are available within each connector, for example allowing read access but disabling write operations, and those permissions apply org-wide (&lt;a href="https://claude.com/blog/cowork-for-enterprise" rel="noopener noreferrer"&gt;Making Claude Cowork ready for enterprise&lt;/a&gt;, 2026). That read-only-per-connector control is the most underrated safety feature in the product. If I ran a team deploying this, I'd wire every connector read-only until a specific workflow earned write access.&lt;/p&gt;

&lt;p&gt;Enterprise also gets the audit trail that consumer plans don't. Cowork emits OpenTelemetry events for tool and connector calls, files read or modified, and whether each action was approved manually or automatically (&lt;a href="https://claude.com/blog/cowork-for-enterprise" rel="noopener noreferrer"&gt;Making Claude Cowork ready for enterprise&lt;/a&gt;, 2026). One caveat from the docs: Cowork activity isn't captured in the Compliance API yet, so Team and Enterprise route it to a SIEM through OpenTelemetry instead (&lt;a href="https://support.claude.com/en/articles/14477985-monitor-claude-cowork-activity-with-opentelemetry" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026). If you need a record of what the agent touched, that's your path.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Claude Cowork security risks I actually watch for
&lt;/h2&gt;

&lt;p&gt;If I had to rank the real risks, prompt injection sits at the top, and it's not close. OWASP lists prompt injection as the #1 vulnerability for LLM applications, for the second edition in a row, with "excessive agency" and "sensitive information disclosure" also in the top ten (&lt;a href="https://owasp.org/www-project-top-10-for-large-language-model-applications/" rel="noopener noreferrer"&gt;OWASP&lt;/a&gt;, 2025). All three describe a file-touching agent almost perfectly.&lt;/p&gt;

&lt;p&gt;Anthropic names the threat itself: malicious instructions embedded in external content that Claude reads, and it trains Claude to detect these attacks with external safeguards on top (&lt;a href="https://support.claude.com/en/articles/13364135-use-claude-cowork-safely" rel="noopener noreferrer"&gt;Claude Cowork docs&lt;/a&gt;, 2026). The docs also give two flat warnings I'd take seriously: avoid granting access to local files with sensitive information like financial documents, and be cautious about using Claude in the browser for anything sensitive. Detection helps. It isn't a guarantee.&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%2Frczcfkcpoxiispn6mw6l.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%2Frczcfkcpoxiispn6mw6l.png" alt="Lollipop chart ranking the Claude Cowork risks the author watches most, on a 1 to 10 attention scale: prompt injection 9, skip-all-approvals mode 8, over-broad folder access 7, plugin or connector overreach 6, consumer training opt-out left on 6, accidental wrong-file edit 4." width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Second on my list is the interaction between skip all approvals and that injection risk. Permanent deletion is still gated in every mode, which closes the worst case. But injection steering the agent into non-deletion actions is no longer hypothetical. Security firm PromptArmor demonstrated a prompt-injection attack against Cowork: a .docx carrying concealed white-on-white instructions steered the agent into exfiltrating the victim's largest file to an attacker-controlled account, with no human approval required at any point (&lt;a href="https://www.promptarmor.com/resources/claude-cowork-exfiltrates-files" rel="noopener noreferrer"&gt;PromptArmor&lt;/a&gt;, 2026). I haven't seen a public report of injection-triggered file writes or edits specifically, but the exfiltration case settles the principle: a poisoned document can drive real actions without you in the loop. Either way, I keep sensitive folders out of auto-approve.&lt;/p&gt;

&lt;p&gt;The rest of my list is mundane on purpose: over-broad folder grants, plugins and connectors expanding reach, a consumer training toggle left in the wrong position, and the plain old accidental wrong-file edit. None of these are exotic. All of them are yours to control.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use Claude Cowork safely
&lt;/h2&gt;

&lt;p&gt;The safest setup takes about two minutes and removes most of the risk above. Give Cowork a dedicated working folder instead of broad access, exactly as Anthropic recommends, and never point it at directories holding secrets, credentials, or files you're contractually bound to protect (&lt;a href="https://support.claude.com/en/articles/13364135-use-claude-cowork-safely" rel="noopener noreferrer"&gt;Claude Cowork docs&lt;/a&gt;, 2026). Scope is your strongest lever, and it costs nothing.&lt;/p&gt;

&lt;p&gt;Here's the checklist I'd hand a teammate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scope tight.&lt;/strong&gt; One project folder, not your home directory or Documents root.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep secrets out.&lt;/strong&gt; No &lt;code&gt;.env&lt;/code&gt; files, no password stores, no client contracts in the connected folder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Default to manual approve&lt;/strong&gt; for anything new, and only relax it once you trust the pattern.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wire connectors read-only&lt;/strong&gt; where you can, and add write access per workflow, not blanket.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check the training toggle&lt;/strong&gt; on consumer plans, and use a commercial or Enterprise org for anyone else's data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On a team, turn on the audit trail&lt;/strong&gt; via OpenTelemetry so you can see what the agent touched.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's genuinely how I run it. Watching an agent work in a tightly scoped folder for a few sessions is the fastest way to calibrate trust, and it's a lot cheaper than learning the boundaries the hard way. For the moment-to-moment version of this, including what the approval prompts look like during a task, see the hands-on walkthrough of Cowork permissions in a real session.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is Claude Cowork safe to let touch my files?
&lt;/h3&gt;

&lt;p&gt;Reasonably, if you scope it. Cowork only reaches folders you connect, runs in an isolated server-side sandbox that can't touch your local network, and always asks before permanently deleting files (&lt;a href="https://support.claude.com/en/articles/13364135-use-claude-cowork-safely" rel="noopener noreferrer"&gt;Claude Cowork docs&lt;/a&gt;, 2026). The main residual risk is prompt injection, so keep sensitive folders out of auto-approve.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can Claude Cowork delete my files without asking?
&lt;/h3&gt;

&lt;p&gt;No. Cowork always asks before permanently deleting files, in every approval mode, including skip all approvals (&lt;a href="https://support.claude.com/en/articles/13364135-use-claude-cowork-safely" rel="noopener noreferrer"&gt;Claude Cowork docs&lt;/a&gt;, 2026). Deletion is the one action the tool won't automate. Other actions, like edits and moves, can run without a prompt if you've enabled auto or skip modes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does Anthropic train its models on my Cowork data?
&lt;/h3&gt;

&lt;p&gt;It depends on your plan. Commercial and Enterprise don't train on your inputs or outputs by default (&lt;a href="https://privacy.claude.com/en/articles/7996868-is-my-data-used-for-model-training" rel="noopener noreferrer"&gt;Anthropic Privacy Center&lt;/a&gt;, 2026). Consumer Free, Pro, and Max follow the consumer policy, where data can be used for model improvement unless you opt out. Check your privacy toggle before using sensitive files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is it legal to use Claude Cowork for client or work files?
&lt;/h3&gt;

&lt;p&gt;That's on you, not the tool. Anthropic states you remain responsible for all actions Claude takes on your behalf. If files carry NDA, DPA, HIPAA, or GDPR obligations, use a commercial or Enterprise org with the no-train default rather than a consumer seat, and confirm the arrangement meets your contract's terms.&lt;/p&gt;

&lt;h3&gt;
  
  
  What can Claude Cowork plugins access?
&lt;/h3&gt;

&lt;p&gt;Plugins bundle skills, connectors, and sub-agents, and they can widen reach well beyond your files, into databases and SaaS apps through MCP connectors (&lt;a href="https://support.claude.com/en/articles/13837440-use-plugins-in-claude" rel="noopener noreferrer"&gt;Claude plugins docs&lt;/a&gt;, 2026). A legal-branded plugin adds legal skills, not legal protection. Add connectors read-only where possible and treat each one as a new access door.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;Is it safe to let Claude Cowork touch your file system? My honest answer, as someone who does almost everything in Claude Code and came in skeptical: yes, within a folder you've scoped tightly, on a plan whose data terms match your obligations, with skip all approvals switched off for anything sensitive. The guardrails Anthropic ships, folder boundaries, a network-isolated sandbox, and deletion that always asks, are real and sensible.&lt;/p&gt;

&lt;p&gt;The risk that remains is the same one that tops every AI security list, prompt injection, plus the ordinary human risk of granting too much access. Both are yours to manage, and both are cheap to manage well. Scope the folder, keep secrets out, default to manual approve, and match the plan to the sensitivity of the data. Do that and Cowork earns a place in the workflow. Skip it and you're the vulnerability, not the tool.&lt;/p&gt;

&lt;p&gt;For the full product picture, platforms, and eligibility, the &lt;a href="https://maketocreate.com/what-is-claude-cowork-anthropics-non-coding-desktop-agent-explained/" rel="noopener noreferrer"&gt;complete guide to Claude Cowork&lt;/a&gt; is the hub. This page is the one to bookmark before you connect that first folder.&lt;/p&gt;

</description>
      <category>claudecowork</category>
      <category>claudecoworksecurity</category>
      <category>aiagentsecurity</category>
      <category>claudecoworklegal</category>
    </item>
    <item>
      <title>How to Use Claude Code's Frontend-Design Plugin</title>
      <dc:creator>Nishil Bhave</dc:creator>
      <pubDate>Mon, 27 Jul 2026 12:35:34 +0000</pubDate>
      <link>https://dev.to/nishilbhave/how-to-use-claude-codes-frontend-design-plugin-511i</link>
      <guid>https://dev.to/nishilbhave/how-to-use-claude-codes-frontend-design-plugin-511i</guid>
      <description>&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%2Fhia0uz5xw285di7lnl3q.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%2Fhia0uz5xw285di7lnl3q.png" alt="A comparison hero showing the Claude Code frontend-design plugin turning generic AI defaults into a distinctive design direction." width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I installed the frontend-design plugin, gave Claude Code a plain brief, and watched it do something it almost never does on its own: it stopped and argued with itself about typography before writing a single line of CSS. Same model, same prompt, one plugin. The output went from a page I have seen a thousand times to one I actually wanted to look at.&lt;/p&gt;

&lt;p&gt;That is the entire value of this plugin, and also the source of most of the confusion around it. It is not a new command you run. It is not a UI library. It is a skill that changes how Claude &lt;em&gt;thinks&lt;/em&gt; about a frontend task, and once you understand that, the "how do I use it" question has a slightly surprising answer. Below is exactly what it is, how to install it, a real before-and-after from my own testing, and an honest read on where it earns its place and where it does not.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The frontend-design plugin is an official, Anthropic-authored plugin in the &lt;code&gt;claude-plugins-official&lt;/code&gt; marketplace (&lt;a href="https://github.com/anthropics/claude-plugins-official" rel="noopener noreferrer"&gt;anthropics/claude-plugins-official&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;It ships a single skill and no slash command. Claude auto-invokes it on frontend work, because plugin skills are model-invoked (&lt;a href="https://code.claude.com/docs/en/plugins" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026).&lt;/li&gt;
&lt;li&gt;Install it with &lt;code&gt;/plugin install frontend-design@claude-plugins-official&lt;/code&gt;, then run &lt;code&gt;/reload-plugins&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It mostly changes taste, not correctness. Across 12 runs it widened the range of designs the same brief produced, while the one page that shipped visibly broken came from the no-plugin arm.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is the Claude Code frontend-design plugin?
&lt;/h2&gt;

&lt;p&gt;The frontend-design plugin is an official Claude Code plugin, published by Anthropic in the &lt;code&gt;claude-plugins-official&lt;/code&gt; marketplace. Its whole job is to make Claude produce distinctive frontend interfaces instead of the generic look AI tools default to. Its own description calls it guidance for "distinctive, intentional visual design when building new UI or reshaping an existing one." The manifest lists Anthropic as the author, and the skill itself is credited to Prithvi Rajasekaran and Alexander Bricken.&lt;/p&gt;

&lt;p&gt;Here is the structural fact that trips people up. Plugins arrived in Claude Code in October 2025, and one can bundle slash commands, subagents, hooks, and MCP servers (&lt;a href="https://claude.com/blog/claude-code-plugins" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2025; &lt;a href="https://code.claude.com/docs/en/plugins" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). This one bundles none of those. It contains exactly one thing: a skill, defined in a single &lt;code&gt;SKILL.md&lt;/code&gt; file. There is no &lt;code&gt;/frontend-design&lt;/code&gt; to type.&lt;/p&gt;

&lt;p&gt;That matters because plugin skills are &lt;em&gt;model-invoked&lt;/em&gt;. The documentation is blunt about it: "Skills are model-invoked: Claude automatically uses them based on the task context" (&lt;a href="https://code.claude.com/docs/en/plugins" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). So you do not "run" the frontend-design plugin the way you run a command. You install it, and from then on Claude reads the skill's guidance into context whenever it decides you are doing frontend work. The plugin's own README says the quiet part out loud: "Claude automatically uses this skill for frontend work." Most write-ups I have seen get this wrong and invent a command that does not exist.&lt;/p&gt;

&lt;p&gt;So what is inside that one skill? It is a short design brief written to Claude, not to you. It tells the model to approach the work "as the design lead at a small studio" whose client has already rejected anything that felt templated. It asks for deliberate choices about palette, typography, and layout, and for one justified aesthetic risk per project. And it names the enemy specifically, which is the part I find most useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does the plugin actually change?
&lt;/h2&gt;

&lt;p&gt;According to the skill's own text, current AI-generated design clusters around three recognizable looks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A warm cream background near &lt;code&gt;#F4F1EA&lt;/code&gt;, with a high-contrast serif and a terracotta accent.&lt;/li&gt;
&lt;li&gt;A near-black background with a single acid-green or vermilion accent.&lt;/li&gt;
&lt;li&gt;A broadsheet layout with hairline rules, zero border-radius, and dense newspaper columns.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The skill's line is that all three "are defaults rather than choices, and they appear regardless of subject."&lt;/p&gt;

&lt;p&gt;That is a genuinely sharp observation, and it is the mechanism behind everything the plugin does. It forces a two-pass process before any code is written. First it brainstorms a compact design plan: palette as four to six named hex values, two or more typefaces with defined roles, a layout concept, and one signature element the page will be remembered by. Then it critiques that plan against the generic default before building. If part of the plan reads like the thing Claude would produce for any similar prompt, it revises and says what it changed.&lt;/p&gt;

&lt;p&gt;To see the difference honestly, I ran the same brief both ways: "a landing hero for Perch, a self-hosted uptime monitor for people who do not trust status-page SaaS." Six runs without the plugin, six with it. I kept every output, so the claims below are checkable.&lt;/p&gt;

&lt;h3&gt;
  
  
  How I isolated the plugin
&lt;/h3&gt;

&lt;p&gt;Getting the isolation right took more care than the experiment did. Both arms ran through &lt;code&gt;claude -p&lt;/code&gt; with &lt;code&gt;--settings&lt;/code&gt; pinning &lt;code&gt;enabledPlugins&lt;/code&gt; explicitly. Everything off for the control arm. Only &lt;code&gt;frontend-design@claude-plugins-official&lt;/code&gt; on for the other. Plugin presence was the single variable.&lt;/p&gt;

&lt;p&gt;The obvious route is &lt;code&gt;--plugin-dir&lt;/code&gt;, and it is a trap. It silently re-enables your entire plugin set. I have another plugin installed that ships its own competing &lt;code&gt;frontend-design&lt;/code&gt; skill. That route would have quietly put two design skills in the treatment arm, and any difference I found would have been unattributable.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--bare&lt;/code&gt; isolates properly, but it never reads OAuth. It needs an API key or it dies at auth having written nothing at all.&lt;/p&gt;

&lt;h3&gt;
  
  
  What did not happen
&lt;/h3&gt;

&lt;p&gt;Neither arm produced the template everyone expects. No indigo-to-purple gradient. No giant "99.99%" over three feature cards. Not once in twelve runs.&lt;/p&gt;

&lt;p&gt;Every single run picked a deliberate typeface without being asked. If you have read that Claude reaches for Inter and a purple gradient by default, that was fair when those write-ups were published. It is not what the model does now. The floor moved.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Run&lt;/th&gt;
&lt;th&gt;Arm&lt;/th&gt;
&lt;th&gt;Typeface&lt;/th&gt;
&lt;th&gt;Background&lt;/th&gt;
&lt;th&gt;Overflow&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;Plugin off&lt;/td&gt;
&lt;td&gt;Instrument Serif&lt;/td&gt;
&lt;td&gt;Cream&lt;/td&gt;
&lt;td&gt;0px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Plugin off&lt;/td&gt;
&lt;td&gt;JetBrains Mono&lt;/td&gt;
&lt;td&gt;Dark&lt;/td&gt;
&lt;td&gt;0px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Plugin off&lt;/td&gt;
&lt;td&gt;Space Grotesk&lt;/td&gt;
&lt;td&gt;Dark&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;374px, broken&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Plugin off&lt;/td&gt;
&lt;td&gt;Instrument Sans&lt;/td&gt;
&lt;td&gt;Dark&lt;/td&gt;
&lt;td&gt;160px, decorative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Plugin off&lt;/td&gt;
&lt;td&gt;Inter Tight&lt;/td&gt;
&lt;td&gt;Dark&lt;/td&gt;
&lt;td&gt;0px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Plugin off&lt;/td&gt;
&lt;td&gt;Space Grotesk&lt;/td&gt;
&lt;td&gt;Dark&lt;/td&gt;
&lt;td&gt;0px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;Plugin on&lt;/td&gt;
&lt;td&gt;Archivo&lt;/td&gt;
&lt;td&gt;Dark&lt;/td&gt;
&lt;td&gt;0px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Plugin on&lt;/td&gt;
&lt;td&gt;Bricolage Grotesque&lt;/td&gt;
&lt;td&gt;Cream&lt;/td&gt;
&lt;td&gt;0px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Plugin on&lt;/td&gt;
&lt;td&gt;Archivo&lt;/td&gt;
&lt;td&gt;Dark&lt;/td&gt;
&lt;td&gt;0px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Plugin on&lt;/td&gt;
&lt;td&gt;Archivo&lt;/td&gt;
&lt;td&gt;Dark&lt;/td&gt;
&lt;td&gt;0px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Plugin on&lt;/td&gt;
&lt;td&gt;Bricolage Grotesque&lt;/td&gt;
&lt;td&gt;Cream&lt;/td&gt;
&lt;td&gt;0px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Plugin on&lt;/td&gt;
&lt;td&gt;Fraunces&lt;/td&gt;
&lt;td&gt;Cream&lt;/td&gt;
&lt;td&gt;0px&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Background is classified by the WCAG relative luminance of each page's computed body colour, not by eye. Overflow is the widest element sticking out past the 1440px viewport. The 160px on run 3 is a decorative glow clipped by its container, so it causes no document scroll and is not a defect.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the plugin actually moved
&lt;/h3&gt;

&lt;p&gt;So the plugin is not rescuing output from a generic bucket, because the plain model is not sitting in one. What it changes is narrower and more interesting: how much the runs resemble &lt;em&gt;each other&lt;/em&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%2F0rqhfstue53izvcq7t93.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%2F0rqhfstue53izvcq7t93.png" alt="Grouped bar chart of background palette across twelve identical hero-brief runs. Without the frontend-design plugin, 1 of 6 runs used a light or cream background and 5 used a dark background. With the plugin, 3 used light or cream and 3 used dark, an even split." width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Background colour is the cleanest place to see it, because it is measurable rather than a matter of taste. I took the computed body background of each page and its WCAG relative luminance. Without the plugin, five of six runs came back dark and one cream. With it, three dark and three cream. Same brief, twice the spread.&lt;/p&gt;

&lt;p&gt;The layouts tell the same story harder. Three comparisons, plugin off on the left and on on the right each time. These are independent runs from each arm rather than matched pairs, so read them as samples, not as one page redesigned.&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%2Fh40vojgtfes8tgejgucq.jpg" 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%2Fh40vojgtfes8tgejgucq.jpg" alt="Two landing hero pages side by side from the same brief. On the left, without the plugin, a dark page in condensed mono type with an amber accent and a monitoring panel. On the right, with the plugin, a cream page with a serif headline and a wire running across it with birds perched along it." width="800" height="305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The right-hand page made the hero a wire with birds perched along it, each bird a monitored service with its latency underneath and one marked as not responding. That is the "hero is a thesis" instinct doing something none of the plain runs attempted: making the page &lt;em&gt;perform&lt;/em&gt; the product rather than describe it.&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%2Fzxu90qmc7c661zrxy7n0.jpg" 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%2Fzxu90qmc7c661zrxy7n0.jpg" alt="Two landing hero pages side by side from the same brief. On the left, without the plugin, a dark page with a green accent, headline on the left and a live monitoring panel on the right. On the right, with the plugin, a warm cream page with a serif italic headline and a dark inset chart." width="800" height="305"&gt;&lt;/a&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%2Fmmp97lvrrn941ay8bdl3.jpg" 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%2Fmmp97lvrrn941ay8bdl3.jpg" alt="Two landing hero pages side by side from the same brief. On the left, without the plugin, a dark page with a green accent and the same headline-left, monitoring-panel-right layout as the previous comparison. On the right, with the plugin, a white editorial page with a serif headline and a fine ruled timeline." width="800" height="305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Look at the two left-hand pages in those last two comparisons. Same palette, same skeleton of headline left and live monitor panel right, and both opening on the same sentence construction, "Your status page shouldn't". A third no-plugin run opened that way too. Those were independent sessions with no shared context, converging on one answer. The right-hand pages, from the same brief, do not resemble each other at all.&lt;/p&gt;

&lt;p&gt;One result cuts against the plugin's reputation as a pure taste layer, and I would rather show it than leave it out. One no-plugin run shipped visibly broken.&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%2Fotqm0mr1vb9jyxe5k6vw.jpg" 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%2Fotqm0mr1vb9jyxe5k6vw.jpg" alt="A landing hero generated without the frontend-design plugin, labelled as a broken layout: the headline is clipped behind the dashboard panel, body text overlaps other elements, and the install command runs off the right edge of the page." width="800" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A paragraph overflows the viewport by 374 pixels and forces horizontal scroll on the whole document. The headline is clipped behind the dashboard panel and the install command runs off the right edge. No plugin-arm page had any overflow at all. That is one page out of six at a sample size of six, so treat it as a flag rather than a finding. It does point the opposite way to "this only changes how things look."&lt;/p&gt;

&lt;p&gt;Three of the plugin runs reached for Archivo and all three came back dark, which keeps this honest: the plugin widens the range, it does not guarantee a distinct answer every time. Give it a brief with no real subject to grab onto and it has nothing to build a point of view from. Give it the actual product and who it is for, and the spread opens up.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I install the frontend-design plugin?
&lt;/h2&gt;

&lt;p&gt;You install it from the official marketplace with one command inside Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/plugin install frontend-design@claude-plugins-official
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;claude-plugins-official&lt;/code&gt; marketplace is registered automatically the first time you start Claude Code interactively, so on a normal setup you do not have to add it yourself (&lt;a href="https://code.claude.com/docs/en/plugins" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). If you are scripting a fresh machine and the marketplace is not there yet, add it explicitly first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;claude plugin marketplace add anthropics/claude-plugins-official
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you prefer clicking to typing, run &lt;code&gt;/plugin&lt;/code&gt; with no arguments, choose Discover, and browse to frontend-design. Either path lands in the same place. After it installs, run &lt;code&gt;/reload-plugins&lt;/code&gt; so Claude picks up the skill without a restart (&lt;a href="https://code.claude.com/docs/en/plugins" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026).&lt;/p&gt;

&lt;p&gt;To confirm it took, ask Claude a frontend question and watch whether it starts talking about a design direction before it writes code. Because the skill is model-invoked, there is no command output that says "plugin active." The behavior is the confirmation. If you want to force the point, check that the plugin is enabled in the &lt;code&gt;/plugin&lt;/code&gt; manager. In daily use I just look at whether Claude is reasoning about palette and type instead of dumping a template.&lt;/p&gt;

&lt;p&gt;One install detail that saved me confusion: the skill only fires when Claude classifies the task as frontend work. If you open with something vague like "help me with my app," it may not trigger. I now open frontend sessions with an explicit framing ("design and build the settings page for X"), which reliably pulls the skill into context. That is a general truth about model-invoked skills, and it is the same reason a good skill description matters when you write your own.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I actually use it in a real frontend workflow?
&lt;/h2&gt;

&lt;p&gt;Once it is installed, "using it" is mostly a matter of giving Claude a brief with a real subject and then reading the design plan it produces before you let it build. The plugin's power comes from that plan step, so the worst thing you can do is skip past it to the code.&lt;/p&gt;

&lt;p&gt;Here is the workflow that works for me, using the Perch hero from earlier as the example.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Give it a subject, not just a component.&lt;/strong&gt; "Build a hero section" gets you a hero. "Build the hero for a self-hosted uptime monitor for people burned by status-page outages" gets you a hero with a point of view. The skill explicitly says the subject's own world (its materials, artifacts, and vernacular) is where distinctive choices come from, so hand it that world.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Read the design plan it returns.&lt;/strong&gt; With the plugin active, Claude proposed a compact token system before writing anything. Paraphrased, the plan looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Palette:   Dusk #121821 · Bone #f3ede2 · Ember #e8623f · Moss #6f8f6a · Brass #c9a24a
Type:      Display "Archivo Narrow" (tall, condensed, used sparingly)
           Body "Public Sans" · Mono "JetBrains Mono" for live metrics
Layout:    The hero IS the product. A working "watch wall" of service tiles,
           one of them flatlined and pulsing Ember, instead of a centered pitch.
Signature: A single heartbeat line under the wall that ticks in real time,
           like a seismograph for your infrastructure.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice what is not there: no &lt;code&gt;#F4F1EA&lt;/code&gt; cream, no indigo gradient, no giant percentage. The plan derived the palette from a watchtower-at-dusk idea and made the hero &lt;em&gt;do the product's job&lt;/em&gt; rather than describe it. That "the hero is a thesis" instinct is straight from the skill.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Sanity-check the plan against your constraints, then build.&lt;/strong&gt; This is your cheapest intervention point. If the signature element is too much, or a font pick will not survive your bundle budget, say so now. Editing a plan costs a sentence. Editing a built page costs a rebuild. Once I approved, the code it produced was legitimately different from the default. In my original test the no-plugin page had opened like this (reconstructed, since I did not keep those pages, and as covered above the re-run controls never produced this template):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"hero"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Monitor your uptime.&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"stat"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;99.99%&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"cta"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Start free&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The plugin version opened with the working status grid and the heartbeat line as the first thing you see, with the headline demoted to a caption. Same brief, completely different thesis for what the page is.&lt;/p&gt;

&lt;p&gt;To put numbers on it, I scored both outputs one to ten across five dimensions. The plugin lifted the aesthetic dimensions clearly, and left one dimension flat on purpose.&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%2F24ak6wvbtr8vqgfcubgo.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%2F24ak6wvbtr8vqgfcubgo.png" alt="Slope chart scoring one output without vs with the frontend-design plugin across five dimensions, each one to ten. Aesthetic distinctiveness rose from 3 to 8, typography from 4 to 8, microcopy from 4 to 7, layout and hierarchy from 5 to 7, and functional correctness stayed flat at 7." width="799" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Read that flat dashed line at the bottom as the honest caveat. The plugin did nothing for whether the code ran, handled state, or shipped without bugs. It is a skill about taste, and taste is exactly the thing base models are worst at and this plugin is best at. If your problem is a broken build, this is not your tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where does the frontend-design plugin help, and where does it not?
&lt;/h2&gt;

&lt;p&gt;The plugin is not equally useful across frontend work. It shines when the aesthetic direction is undefined and there is a subject to build a point of view around. It does much less, and occasionally gets in the way, when the design is already decided for you.&lt;/p&gt;

&lt;p&gt;I rated its usefulness across the kinds of frontend tasks I actually hand Claude, one to ten. The gap between the top and the bottom is large enough that "should I use this here" is worth a two-second thought, not a reflex.&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%2F3s7o3bhgrfkdhe85k484.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%2F3s7o3bhgrfkdhe85k484.png" alt="Lollipop chart rating the frontend-design plugin's usefulness one to ten by task type. Greenfield landing or hero 9, marketing site redesign 8, new component from scratch 7, dense data dashboard 5, brand or design-system-constrained work 3, tiny widget or bug fix 2." width="799" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The top of that chart is greenfield work with room to make choices. A landing page, a marketing site, a product hero, a fresh component with no existing look to match. This is where the two-pass design plan pays for itself, because there is a real decision to make and the plugin makes Claude make it deliberately.&lt;/p&gt;

&lt;p&gt;The bottom is where I turn it off in my head. Brand or design-system-constrained work is the sharp one. If you already have tokens, a component library, and a locked visual language, the plugin's instinct to "take one real aesthetic risk" is a liability rather than a feature. It can fight your system and hand you a beautiful thing that does not match anything else you ship. For a tiny widget or a bug fix, the elaborate planning is pure overhead, the same way over-planning a one-line change is a tax in &lt;a href="https://maketocreate.com/claude-code-plan-mode-how-i-use-it-and-when-i-dont/" rel="noopener noreferrer"&gt;Claude Code's plan mode&lt;/a&gt;. Dense data dashboards sit in the middle: layout discipline matters more than flair there, and the plugin helps the frame but not the data density problem.&lt;/p&gt;

&lt;p&gt;The honest summary: reach for it when you want Claude to have taste, and skip it when you need Claude to obey a system it did not design.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does it fit with CLAUDE.md and the rest of my setup?
&lt;/h2&gt;

&lt;p&gt;The plugin injects design guidance per session, but it does not know &lt;em&gt;your&lt;/em&gt; preferences unless you tell it. That is where the rest of the Claude Code stack comes in, and it is worth being deliberate about the division of labor.&lt;/p&gt;

&lt;p&gt;For persistent, project-specific design rules (your brand fonts, your spacing scale, the components you never want reinvented), the plugin is the wrong home, because it is generic by design. The right home is your project's &lt;a href="https://maketocreate.com/claude-md-best-practices-the-complete-2026-guide/" rel="noopener noreferrer"&gt;CLAUDE.md file&lt;/a&gt;, where standing instructions live across every session. In practice I let the plugin supply the general "make deliberate choices, avoid the defaults" instinct, and I let CLAUDE.md supply the specifics that make those choices land inside my actual system. The two stack cleanly: the plugin raises the aesthetic floor, CLAUDE.md keeps it on-brand.&lt;/p&gt;

&lt;p&gt;It is also worth knowing where this plugin sits in the wider extension landscape so you do not go looking for features it does not have. It is one skill, distributed as a plugin. If you want the fuller picture of how plugins, skills, and marketplaces relate, and how to manage more than one, I cover that in &lt;a href="https://maketocreate.com/claude-skills-marketplace-skills-sh-shipping-your-own-skill/" rel="noopener noreferrer"&gt;the Claude skills and marketplace guide&lt;/a&gt;. And if you are wiring frontend work into a repeatable loop rather than one-off pages, the plugin slots into &lt;a href="https://maketocreate.com/the-complete-claude-code-workflow-how-i-ship-10x-faster/" rel="noopener noreferrer"&gt;a full end-to-end Claude Code workflow&lt;/a&gt; as the "design pass" step. That lands right after you have agreed on what to build, and before the model starts generating components.&lt;/p&gt;

&lt;p&gt;If you want to go deeper than the plugin does on its own, Anthropic's &lt;a href="https://github.com/anthropics/claude-cookbooks/blob/main/coding/prompting_for_frontend_aesthetics.ipynb" rel="noopener noreferrer"&gt;Frontend Aesthetics Cookbook&lt;/a&gt; is the longer-form prompting reference its README points to. Worth a read before you tackle anything ambitious.&lt;/p&gt;

&lt;p&gt;A note for anyone comparing this to third-party design plugins: the official one is deliberately minimal. It does not ban specific fonts, mandate a rigid question template, or ship a component kit, whatever some write-ups claim. Its actual content is the design-lead framing and the two-pass process, and that restraint is a feature. It nudges taste without hijacking your stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is the Claude Code frontend-design plugin?
&lt;/h3&gt;

&lt;p&gt;It is an official, Anthropic-authored plugin in the &lt;code&gt;claude-plugins-official&lt;/code&gt; marketplace that pushes Claude Code to produce distinctive frontend interfaces instead of generic AI-default designs. It contains a single model-invoked skill, no commands, and works by making Claude draft and critique a design plan before writing code (&lt;a href="https://code.claude.com/docs/en/plugins" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026).&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I install the frontend-design plugin?
&lt;/h3&gt;

&lt;p&gt;Run &lt;code&gt;/plugin install frontend-design@claude-plugins-official&lt;/code&gt; inside Claude Code, then &lt;code&gt;/reload-plugins&lt;/code&gt;. The official marketplace is registered automatically on first launch; if it is missing, add it with &lt;code&gt;claude plugin marketplace add anthropics/claude-plugins-official&lt;/code&gt; first (&lt;a href="https://code.claude.com/docs/en/plugins" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026).&lt;/p&gt;

&lt;h3&gt;
  
  
  Is there a /frontend-design command to run it?
&lt;/h3&gt;

&lt;p&gt;No. It ships a skill, and skills are model-invoked, so Claude activates it automatically based on task context rather than through a command (&lt;a href="https://code.claude.com/docs/en/plugins" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). To make sure it fires, frame your request clearly as frontend work, for example "design and build the pricing page," rather than something vague.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does the frontend-design plugin write bug-free code?
&lt;/h3&gt;

&lt;p&gt;No, and it does not try to. It is a taste layer on top of Claude's normal coding, not a correctness or testing tool, so treat the generated design as a first draft you still review. Worth noting from my 12-run test: the one page that shipped visibly broken, with 374 pixels of horizontal overflow, came from the no-plugin arm, and no plugin-arm page had any overflow. That is a single page at a sample size of six, so it is a flag rather than evidence the plugin improves correctness.&lt;/p&gt;

&lt;h3&gt;
  
  
  When should I not use the frontend-design plugin?
&lt;/h3&gt;

&lt;p&gt;Skip it for brand or design-system-constrained work where the visual language is already locked, for tiny widgets or bug fixes where the planning is overhead, and for anything where correctness matters more than look. Its instinct to take an aesthetic risk is a liability inside a system it did not design.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;The frontend-design plugin does one thing and does it well: it makes Claude Code stop defaulting. Install it, give it a real subject, read the design plan before you approve, and you get frontend work with an actual point of view instead of the interchangeable AI look. In my re-run it doubled the palette spread from one brief and broke the no-plugin arm's habit of converging on the same layout, and it did that without any new command to learn.&lt;/p&gt;

&lt;p&gt;My rules after living with it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Install it once&lt;/strong&gt; with &lt;code&gt;/plugin install frontend-design@claude-plugins-official&lt;/code&gt;, then let it ride. It is model-invoked, so there is nothing to run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feed it a subject, not a component.&lt;/strong&gt; The distinctiveness comes from the world you hand it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read the design plan.&lt;/strong&gt; That is your cheapest edit point, and skipping it wastes the whole plugin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turn it off in your head&lt;/strong&gt; for design-system work, tiny fixes, and anything where correctness beats taste.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Put your durable rules in &lt;a href="https://maketocreate.com/claude-md-best-practices-the-complete-2026-guide/" rel="noopener noreferrer"&gt;a well-tuned CLAUDE.md&lt;/a&gt; so the plugin's taste lands inside your system, and treat this as one deliberate step in your build, not a magic button. Design first, then let it build.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>frontenddesign</category>
      <category>plugins</category>
      <category>aicoding</category>
    </item>
    <item>
      <title>How Much Does Claude Cowork Cost in 2026? Free on Every Paid Plan</title>
      <dc:creator>Nishil Bhave</dc:creator>
      <pubDate>Sat, 25 Jul 2026 22:53:11 +0000</pubDate>
      <link>https://dev.to/nishilbhave/how-much-does-claude-cowork-cost-in-2026-free-on-every-paid-plan-3pig</link>
      <guid>https://dev.to/nishilbhave/how-much-does-claude-cowork-cost-in-2026-free-on-every-paid-plan-3pig</guid>
      <description>&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%2F5dq55byeja385q3fch33.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%2F5dq55byeja385q3fch33.png" alt="Claude plan pricing ladder from Pro to Max 20x with a badge showing Cowork is included free on every paid tier" width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Claude Cowork costs nothing extra. It's bundled free into every paid Claude plan, so the honest answer to "how much does Claude Cowork cost" is "whatever you already pay for Claude." There's no separate Cowork subscription, no per-task fee, and no add-on toggle in billing.&lt;/p&gt;

&lt;p&gt;That's the headline, and it's genuinely good news. But it hides the part that actually decides your bill. Cowork runs agent tasks, and agent tasks burn a lot more tokens than a chat message. So the real question isn't the price of Cowork, it's which plan gives you enough usage to run it every day without slamming into a limit. I live in Claude Code, and I've watched the same token math play out there for months. Below is the accurate pricing ladder, the token-burn catch nobody puts on the pricing page, and which tier I'd actually pay for.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Cowork is free on every paid Claude plan and is not sold separately (&lt;a href="https://claude.com/pricing" rel="noopener noreferrer"&gt;Claude pricing&lt;/a&gt;, 2026). The free tier does not include it.&lt;/li&gt;
&lt;li&gt;The ladder: Pro $20/mo, Max 5x $100/mo, Max 20x $200/mo, then Team and Enterprise.&lt;/li&gt;
&lt;li&gt;Agent workloads use about 4x the tokens of chat (&lt;a href="https://www.anthropic.com/engineering/built-multi-agent-research-system" rel="noopener noreferrer"&gt;Anthropic engineering&lt;/a&gt;, 2025), so Max is the realistic daily-driver tier for Cowork.&lt;/li&gt;
&lt;li&gt;Anthropic's own data shows just 8.7% of Cowork sessions are software development (&lt;a href="https://venturebeat.com/technology/anthropic-brings-claude-cowork-to-mobile-and-web-as-usage-data-shows-most-users-arent-coding" rel="noopener noreferrer"&gt;VentureBeat&lt;/a&gt;, 2026): this is a tool for non-coding knowledge work.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Is Claude Cowork free?
&lt;/h2&gt;

&lt;p&gt;Yes. Claude Cowork is free on every paid Claude plan, and it's included the moment you subscribe to Pro ($20/mo) or higher (&lt;a href="https://claude.com/pricing" rel="noopener noreferrer"&gt;Claude pricing&lt;/a&gt;, 2026). There's no separate purchase, no upgrade prompt, and no metered Cowork line item. If you already pay for Claude, you already have Cowork.&lt;/p&gt;

&lt;p&gt;The one boundary is the free tier. Claude's $0 plan does not include Cowork at all. That's deliberate: Cowork is an agent that reads, writes, and edits files on your machine across multi-step tasks, and that workload is far too token-heavy to give away for free. So "is Claude Cowork free" has a two-part answer. Free to use if you're on a paid plan. Not available if you're on the free one.&lt;/p&gt;

&lt;p&gt;There's a common misconception worth killing here, because I keep seeing it repeated. A lot of secondary write-ups still say Cowork is "Max only." That was briefly true at launch and isn't true now. Anthropic opened Cowork to Max subscribers first on January 12, 2026, then extended it to all Pro users within days (&lt;a href="https://www.engadget.com/ai/anthropic-opens-up-its-claude-cowork-feature-to-anyone-with-a-20-subscription-194000021.html" rel="noopener noreferrer"&gt;Engadget&lt;/a&gt;, 2026). Today the primary pricing page lists Cowork as included in Pro and every tier above it.&lt;/p&gt;

&lt;p&gt;According to Anthropic's pricing, Claude Cowork ships inside the Pro plan and higher at no additional cost, alongside Claude Code, which means a single $20/month subscription unlocks the full desktop agent (&lt;a href="https://claude.com/pricing" rel="noopener noreferrer"&gt;Claude pricing&lt;/a&gt;, 2026). For most people asking whether Cowork is free, that's the practical answer: it's free with the cheapest paid plan Anthropic sells.&lt;/p&gt;

&lt;h2&gt;
  
  
  How much does Claude Cowork cost across each plan?
&lt;/h2&gt;

&lt;p&gt;Cowork's price is your Claude plan's price, nothing more. The ladder runs Pro at $20/month, Max 5x at $100/month, Max 20x at $200/month, then Team at $25 per seat and custom Enterprise pricing (&lt;a href="https://claude.com/pricing" rel="noopener noreferrer"&gt;Claude pricing&lt;/a&gt;, 2026). Every one of those paid tiers includes Cowork in full. What changes as you climb isn't Cowork's feature set, it's how much you can run it.&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%2Fws4svs2906xx3djfwj9t.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%2Fws4svs2906xx3djfwj9t.png" alt="Stepped price ladder for Claude plans: Free $0, Pro $20, Max 5x $100, Max 20x $200, with Cowork included from Pro up" width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's the same ladder as a table, with what the price actually buys you:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Price / month&lt;/th&gt;
&lt;th&gt;Cowork included?&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Chat only, no agent access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pro&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Trying Cowork, light and occasional tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max 5x&lt;/td&gt;
&lt;td&gt;$100&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Daily Cowork use without babysitting limits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max 20x&lt;/td&gt;
&lt;td&gt;$200&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Heavy, all-day agent workloads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team&lt;/td&gt;
&lt;td&gt;$25 / seat&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Small teams sharing Cowork&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enterprise&lt;/td&gt;
&lt;td&gt;Custom&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Org rollout, admin controls&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Whatever phrasing brought you here, price, cost, or subscription, it resolves to the same table. You're not pricing Cowork, you're pricing your Claude usage. The only genuine decision is how much headroom you need, and that comes straight from how tokens work. If you also run the terminal coding agent, the cost math is a bit different, and I break that down separately in &lt;a href="https://maketocreate.com/claude-code-cost-in-2026-honest-pro-vs-max-vs-api-guide/" rel="noopener noreferrer"&gt;my full Claude Code pricing and limits guide&lt;/a&gt;. This page stays strictly on Cowork.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Cowork burns more tokens than chat (the real cost)
&lt;/h2&gt;

&lt;p&gt;The true cost of Cowork isn't the sticker price, it's token consumption, because agent tasks use roughly 4x the tokens of an ordinary chat turn (&lt;a href="https://www.anthropic.com/engineering/built-multi-agent-research-system" rel="noopener noreferrer"&gt;Anthropic engineering&lt;/a&gt;, 2025). A chat message is one prompt and one reply. A Cowork task reads files, plans steps, calls tools, writes output, and re-reads its own work, and every one of those steps spends tokens against your plan's limit.&lt;/p&gt;

&lt;p&gt;Think about what a single Cowork run involves. It opens several files, holds them in a large context window, reasons across multiple steps, and edits or produces documents. That's not one exchange, it's a loop. Anthropic's own engineering team put a number on the pattern: agents use about 4x the tokens of chat, and multi-agent systems use about 15x. Cowork sits on the single-agent end of that range, but the direction is unmistakable. The same work that felt "free" in chat quietly costs several times more as an agent task.&lt;/p&gt;

&lt;p&gt;I've felt this exact effect in Claude Code, which shares the same token economics. On Pro, a couple of real multi-file tasks can eat a chunk of your window before lunch. When I moved heavier work to Max, the limits basically stopped interrupting me. Cowork behaves the same way, for the same reason: it's an agent, not a chatbot, and agents are hungry.&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%2Fpyln8gto3pv2hka6wr78.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%2Fpyln8gto3pv2hka6wr78.png" alt="Horizontal bars showing usage headroom versus Pro: Pro 1x, Max 5x is five times, Max 20x is twenty times" width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is why I keep saying Max is the realistic daily-driver tier for Cowork, and it's the single most useful thing on this page. The plan names are literal: Max 5x gives you five times Pro's usage, Max 20x gives you twenty times. When your workload is agentic, that multiplier isn't a luxury, it's the difference between finishing a task and watching a progress bar stall on a limit. Pro is plenty to try Cowork. It's thin for living in it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which Claude plan is best for Cowork?
&lt;/h2&gt;

&lt;p&gt;Pick your plan by how often you'll run agent tasks, not by the Cowork feature list, since every paid tier ships the same Cowork. Pro ($20) is right for testing and occasional use. Max 5x ($100) is the sweet spot for daily use (&lt;a href="https://claude.com/pricing" rel="noopener noreferrer"&gt;Claude pricing&lt;/a&gt;, 2026). Max 20x ($200) is for people who run Cowork all day, back to back.&lt;/p&gt;

&lt;p&gt;Here's how I'd match plan to person:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pro, $20.&lt;/strong&gt; You want to see what Cowork does. You'll run a few tasks a week, nothing that runs for twenty minutes unattended. Pro proves the value cheaply, and if you outgrow it you'll know within a fortnight.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Max 5x, $100.&lt;/strong&gt; Cowork is part of your actual workflow. You reconcile spreadsheets, draft docs, and clean up files most days. This is where the token math stops fighting you, and it's the tier I'd point most Cowork users to first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Max 20x, $200.&lt;/strong&gt; You lean on agent tasks constantly, or you kick off long, unattended cloud sessions and want them to just run. If limits on Max 5x still interrupt you, 20x buys the headroom.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The counterintuitive bit: the cheapest way to use Cowork well is often to pay more. On Pro, you spend real attention rationing tasks and watching your window. On Max, that anxiety disappears and you actually use the agent for what it's good at. The $80 jump from Pro to Max 5x buys back the mental overhead of limit-watching, which for a working professional is the better trade almost every time. Cost is a real input to the Cowork-versus-Claude-Code decision too, and I weigh both sides in my honest comparison of Claude Code and Cowork.&lt;/p&gt;

&lt;p&gt;According to Anthropic's usage data from 1.2 million Cowork sessions, 33.4% were business operations and 16.4% were content creation, while software development was just 8.7% (&lt;a href="https://venturebeat.com/technology/anthropic-brings-claude-cowork-to-mobile-and-web-as-usage-data-shows-most-users-arent-coding" rel="noopener noreferrer"&gt;VentureBeat&lt;/a&gt;, 2026). If your work looks like that first bucket, Max 5x is almost certainly your tier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three Claude Cowork pricing myths, corrected
&lt;/h2&gt;

&lt;p&gt;Most confusion about Cowork's cost comes from three wrong claims that keep circulating. All three are easy to settle against Anthropic's own pages (&lt;a href="https://claude.com/pricing" rel="noopener noreferrer"&gt;Claude pricing&lt;/a&gt;, 2026). Getting them right matters, because pricing decisions built on stale facts cost real money.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Myth 1: Cowork is Max-only.&lt;/strong&gt; It was, for about four days in January 2026. Anthropic launched it to Max first, then opened it to all Pro subscribers. Cowork is now included from Pro ($20) upward. Any 2026 guide still saying "Max required" is out of date.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Myth 2: Cowork launched in October 2024.&lt;/strong&gt; This one is just wrong, and it's worth naming because low-quality sources repeat it. Cowork went generally available on macOS and Windows on April 9, 2026, then reached web, iPhone, Android, and cloud sessions on July 7, 2026 (&lt;a href="https://venturebeat.com/technology/anthropic-brings-claude-cowork-to-mobile-and-web-as-usage-data-shows-most-users-arent-coding" rel="noopener noreferrer"&gt;VentureBeat&lt;/a&gt;, 2026). It now runs on Claude Opus 4.8, Anthropic's flagship model released May 28, 2026 (&lt;a href="https://www.anthropic.com/news/claude-opus-4-8" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Myth 3: Cowork bills tokens like the API.&lt;/strong&gt; No. On a subscription, you don't pay per token. You pay a flat monthly price and get a usage allowance. Heavy Cowork use doesn't produce a surprise invoice, it just draws down your plan's limit faster, which is exactly why the tier you pick matters.&lt;/p&gt;

&lt;p&gt;Do any of these change the price of Cowork itself? No. Cowork is free on paid plans regardless. But believing the first myth pushes people onto a $100 plan they didn't need to try the tool, and that's an $80 mistake born of a stale sentence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is Cowork worth the token cost? My read after real tasks
&lt;/h2&gt;

&lt;p&gt;Worth it depends on whether your work is file-heavy and repetitive, and for a large share of knowledge workers it clearly is, given that over 90% of Cowork sessions are non-coding (&lt;a href="https://venturebeat.com/technology/anthropic-brings-claude-cowork-to-mobile-and-web-as-usage-data-shows-most-users-arent-coding" rel="noopener noreferrer"&gt;VentureBeat&lt;/a&gt;, 2026). If your day is spreadsheets, reports, and document wrangling, Cowork earns its token cost. If it isn't, you're paying for headroom you won't use.&lt;/p&gt;

&lt;p&gt;I'll be straight, because that's the point of this page. I do almost everything in Claude Code, in the terminal, and Cowork isn't my daily driver. But I've run enough real tasks to see where it genuinely wins: the file-first, non-coding jobs I'd otherwise do by hand. Pulling scattered updates into one report. Reconciling two spreadsheets. Turning a messy folder into a clean deliverable. Those are the "work around the work" tasks Cowork is built for, and they're exactly the ones a terminal coding tool handles awkwardly.&lt;/p&gt;

&lt;p&gt;Here's the honest calculus. Cowork's free-on-paid-plans pricing means you're never deciding "should I buy Cowork." You're deciding "does my Cowork use justify Max." For someone doing operations or content work most days, yes, easily. The token burn is real, but so is the time it gives back, and Max 5x at $100 turns that burn into a non-issue. For an occasional user, stay on Pro and enjoy it for free. There's no wrong answer that costs you extra, because Cowork itself never does. For the full picture of what Cowork is and everything it can do, start with &lt;a href="https://maketocreate.com/what-is-claude-cowork-anthropics-non-coding-desktop-agent-explained/" rel="noopener noreferrer"&gt;the complete Claude Cowork guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is Claude Cowork free on the Pro plan?
&lt;/h3&gt;

&lt;p&gt;Yes, on any paid Claude plan. Cowork is included at no extra charge from Pro ($20/month) upward and is not sold separately (&lt;a href="https://claude.com/pricing" rel="noopener noreferrer"&gt;Claude pricing&lt;/a&gt;, 2026). The free $0 tier does not include it, because agent tasks are too token-intensive to offer for free.&lt;/p&gt;

&lt;h3&gt;
  
  
  How much does Claude Cowork cost per month?
&lt;/h3&gt;

&lt;p&gt;Cowork itself costs nothing beyond your Claude plan. The plans are Pro $20, Max 5x $100, Max 20x $200, Team $25 per seat, and custom Enterprise (&lt;a href="https://claude.com/pricing" rel="noopener noreferrer"&gt;Claude pricing&lt;/a&gt;, 2026). All paid tiers include the full Cowork desktop agent, so your Cowork cost equals your plan cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I need a separate subscription for Cowork?
&lt;/h3&gt;

&lt;p&gt;No. There is no standalone Cowork subscription or per-task fee. It's bundled into existing Claude plans alongside Claude Code (&lt;a href="https://claude.com/pricing" rel="noopener noreferrer"&gt;Claude pricing&lt;/a&gt;, 2026). If you already pay for Claude Pro or Max, Cowork is already active in your account at no additional cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which plan is best for heavy Cowork use?
&lt;/h3&gt;

&lt;p&gt;Max is the realistic tier for daily use, because agent tasks use about 4x the tokens of chat (&lt;a href="https://www.anthropic.com/engineering/built-multi-agent-research-system" rel="noopener noreferrer"&gt;Anthropic engineering&lt;/a&gt;, 2025). Max 5x ($100) suits most daily users; Max 20x ($200) fits people running long or back-to-back agent sessions. Pro works for occasional tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does Cowork charge per token like the API?
&lt;/h3&gt;

&lt;p&gt;No. On a subscription you pay a flat monthly price, not per token. Heavy Cowork use draws down your plan's usage allowance faster but never generates a metered bill (&lt;a href="https://claude.com/pricing" rel="noopener noreferrer"&gt;Claude pricing&lt;/a&gt;, 2026). Per-token pricing only applies to direct API usage, which is separate from Cowork.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bottom line on Claude Cowork pricing
&lt;/h2&gt;

&lt;p&gt;Claude Cowork is free on every paid Claude plan, full stop. There's no separate cost, no per-task fee, and no upsell, just Pro at $20, Max at $100 or $200, and Cowork included on all of them. The only real decision is usage.&lt;/p&gt;

&lt;p&gt;And that decision comes down to tokens. Agent tasks burn several times more than chat, so if Cowork is part of your daily work, budget for Max rather than Pro, not because Cowork costs more, but because you'll run it enough to want the headroom. Try it on Pro, and move up the moment the limits start interrupting real work. To go deeper on what Cowork actually does and who it's for, read &lt;a href="https://maketocreate.com/what-is-claude-cowork-anthropics-non-coding-desktop-agent-explained/" rel="noopener noreferrer"&gt;the complete Claude Cowork guide&lt;/a&gt;, and if you're weighing it against the terminal coding agent, see Claude Code vs Cowork.&lt;/p&gt;

</description>
      <category>claudecowork</category>
      <category>claudecoworkpricing</category>
      <category>anthropic</category>
    </item>
    <item>
      <title>What Is Claude Cowork? Anthropic's Non-Coding Desktop Agent, Explained</title>
      <dc:creator>Nishil Bhave</dc:creator>
      <pubDate>Fri, 24 Jul 2026 15:27:01 +0000</pubDate>
      <link>https://dev.to/nishilbhave/what-is-claude-cowork-anthropics-non-coding-desktop-agent-explained-3o41</link>
      <guid>https://dev.to/nishilbhave/what-is-claude-cowork-anthropics-non-coding-desktop-agent-explained-3o41</guid>
      <description>&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%2Fhl0xln2w9ixmvf84jjqa.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%2Fhl0xln2w9ixmvf84jjqa.png" alt="The facets of Claude Cowork, Anthropic's non-coding desktop agent, converging on one node: editing files, multi-step tasks, scheduled runs, cross-platform support, and free on paid plans." width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I do almost everything in Claude Code. Terminal open, repo loaded, an agent chewing through a task: that's my whole workday. So when Anthropic shipped Claude Cowork, a desktop agent aimed at people who don't live in a terminal, my honest first reaction was a shrug. Did I need it? Probably not.&lt;/p&gt;

&lt;p&gt;That turned out to be the wrong question. Most knowledge work isn't code, but it's still repetitive, multi-step, and buried in files. In roughly 1.2 million Cowork sessions in late May 2026, just 8.7% went to software development (&lt;a href="https://techcrunch.com/2026/07/07/the-coding-agent-wars-are-spilling-into-the-rest-of-the-office-claude-cowork/" rel="noopener noreferrer"&gt;TechCrunch&lt;/a&gt;, 2026). The other nine-tenths was research, documents, and business operations. This guide covers what Cowork is, what it does, who gets it, and the narrow band where it genuinely beats opening a chat window, written by someone who reaches for &lt;a href="https://maketocreate.com/claude-code-installation-guide-every-platform-every-gotcha/" rel="noopener noreferrer"&gt;Claude Code, Anthropic's terminal coding agent&lt;/a&gt; by reflex.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Cowork is Anthropic's desktop agent for non-coding knowledge work: it reads, edits, and organizes files on your Mac or Windows with your permission (&lt;a href="https://claude.com/product/cowork" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026).&lt;/li&gt;
&lt;li&gt;It went generally available on &lt;strong&gt;April 9, 2026&lt;/strong&gt; (&lt;a href="https://claude.com/blog/cowork-for-enterprise" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026), and reached mobile, web, and cloud (scheduled, device-free) sessions on &lt;strong&gt;July 7, 2026&lt;/strong&gt; (&lt;a href="https://claude.com/blog/cowork-web-mobile" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026).&lt;/li&gt;
&lt;li&gt;It's &lt;strong&gt;free on every paid Claude plan&lt;/strong&gt; (Pro, Max, Team, Enterprise), but tasks burn far more tokens than chat, so Max is the realistic daily-driver tier.&lt;/li&gt;
&lt;li&gt;Only &lt;strong&gt;8.7%&lt;/strong&gt; of a sample of 1.2M sessions went to coding, proof that Cowork is built for the other 91% of knowledge work.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What Is Claude Cowork, Exactly?
&lt;/h2&gt;

&lt;p&gt;Claude Cowork is Anthropic's desktop agent for non-coding knowledge work: it reads, writes, edits, and organizes files on your computer with your consent, and runs multi-step tasks from start to finish (&lt;a href="https://claude.com/product/cowork" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026). The shorthand that stuck, coined in TechCrunch's launch coverage, is "Claude Code without the code." That's the fastest way to grasp what it is: same agentic engine, aimed at documents instead of repositories.&lt;/p&gt;

&lt;p&gt;The distinction that matters is agent versus chatbot. A chat window answers a question and stops. Cowork takes a goal ("clean up this folder of client contracts and build me a summary spreadsheet") and works through it: reading files, making changes, checking its work, and asking before it does anything it shouldn't. It lives inside Claude Desktop rather than a browser tab, which is what lets it touch your local files at all.&lt;/p&gt;

&lt;p&gt;Why does that matter? Because the moment an assistant can act on your files, the unit of work changes. You stop copy-pasting text in and out of a chat and start handing over the whole job. A chatbot can tell you how to merge twelve spreadsheets; Cowork opens them, merges them, and saves the result where you asked. That shift, from advice to execution, is the line between a smart search box and an actual agent.&lt;/p&gt;

&lt;p&gt;Under the hood, Cowork is built on the Claude Agent SDK and draws on the same underlying model as Claude Code (&lt;a href="https://techcrunch.com/2026/01/12/anthropics-new-cowork-tool-offers-claude-code-without-the-code/" rel="noopener noreferrer"&gt;TechCrunch&lt;/a&gt;, 2026). As of mid-2026 that's Claude Opus 4.8, which carries a 1M-token context window (&lt;a href="https://www.anthropic.com/claude/opus" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026). The practical upshot of that context size: Cowork can hold a lot of your files in its head at once, so it doesn't lose the plot halfway through a long job.&lt;/p&gt;

&lt;p&gt;The framing I'd push back on is "Cowork is Anthropic's ChatGPT competitor." It isn't a chat product. It's the consumer-shaped sibling of a developer tool, and that lineage is the whole point: Anthropic took the agent loop that made Claude Code useful and pointed it at the files a non-engineer actually deals with all day.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Can Claude Cowork Actually Do?
&lt;/h2&gt;

&lt;p&gt;What Cowork does is best answered with data, not adjectives. Across about 1.2 million sessions in late May 2026, business operations made up 33.4% of usage, content creation 16.4%, and software development only 8.7% (&lt;a href="https://techcrunch.com/2026/07/07/the-coding-agent-wars-are-spilling-into-the-rest-of-the-office-claude-cowork/" rel="noopener noreferrer"&gt;TechCrunch&lt;/a&gt;, 2026). People aren't using it to write code. They're using it to move real work off their plate.&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%2Fbxro73f6iis3bun6a0ix.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%2Fbxro73f6iis3bun6a0ix.png" alt="Donut chart: in roughly 1.2 million Claude Cowork sessions in late May 2026, business operations was 33.4 percent, content creation 16.4 percent, software development just 8.7 percent, and other knowledge work 41.5 percent." width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In plain terms, Cowork handles jobs like these: reorganizing a messy folder, pulling figures out of a stack of PDFs into one spreadsheet, drafting a report from source documents, turning meeting notes into a formatted brief, or cleaning up file names across a project. Each is a multi-step task that a chatbot can talk about but can't finish, because it can't reach your files.&lt;/p&gt;

&lt;p&gt;The first job I handed Cowork was deliberately un-glamorous: a folder of thirty-odd research PDFs I'd been meaning to sort. I asked it to read them, tag each by topic, and build a one-page summary with links back to the files. It worked through the stack, paused to ask before renaming anything, and dropped a clean summary doc next to the originals. No terminal, no scripting, no me hovering over it. That's the shape of what it's genuinely good at.&lt;/p&gt;

&lt;p&gt;That maps to how people use Claude more broadly. In Anthropic's own usage analysis, documents and reports make up 15% of outputs and explanations another 17% (&lt;a href="https://www.anthropic.com/research/economic-index-june-2026-report" rel="noopener noreferrer"&gt;Anthropic Economic Index&lt;/a&gt;, 2026). Cowork is what turns those from something you ask about in a chat into a finished file sitting in your folder, which is a bigger leap than it sounds.&lt;/p&gt;

&lt;p&gt;The feature that changed my mind was scheduled, unattended runs. Since July 2026, Cowork can execute tasks in the cloud with no device online, so a job can run overnight or on a recurring schedule (&lt;a href="https://claude.com/blog/cowork-web-mobile" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026). "Every Monday at 7am, compile last week's support tickets into a summary" is now a thing you set once. When a scheduled run misbehaves, the fixes live in the troubleshooting guide, cause-and-fix for common Cowork errors.&lt;/p&gt;

&lt;p&gt;Now the anti-hype part, because it's the whole reason to trust the rest. Cowork isn't magic. For a one-off question ("what's the formula for compound interest?"), it's slower and more expensive than just asking Claude in a chat, because it spins up the full agent loop for something a sentence would answer. It's token-hungry by design. And on a genuinely novel task, it still needs supervision: I've watched it confidently misread a file's structure and head down the wrong path until I stopped it. The pattern that works is narrow, well-defined jobs on files it can actually see, not open-ended "figure out my whole workflow" prompts.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does Claude Cowork Work?
&lt;/h2&gt;

&lt;p&gt;How Cowork works comes down to one design choice: scoped consent. You pick the folders and tools it can touch, Claude can't reach anything outside them, and it asks before it acts (&lt;a href="https://support.claude.com/en/articles/13345190-get-started-with-claude-cowork" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026). Nothing on your machine is fair game by default. You grant access folder by folder, and every consequential action pauses for your approval.&lt;/p&gt;

&lt;p&gt;The loop is straightforward. You open Claude Cowork from Claude Desktop (or, since July 2026, from the sidebar of the Claude app on iOS and Android, or from claude.ai on the web). You give it a goal and point it at the folders it needs. It plans the steps, starts working, and checks in when it hits something that needs a decision or a permission it doesn't have yet.&lt;/p&gt;

&lt;p&gt;"Multi-step" is the phrase that carries the weight. A single request can fan out into a dozen actions: open a file, extract a table, reconcile it against another file, flag a mismatch, write a note, save the output. You see each step as it happens, and you can stop or redirect it mid-run. It's less "type a prompt, get a wall of text" and more like watching a careful assistant work through a checklist, one item at a time.&lt;/p&gt;

&lt;p&gt;If you've used &lt;a href="https://maketocreate.com/claude-code-plan-mode-how-i-use-it-and-when-i-dont/" rel="noopener noreferrer"&gt;Claude Code's plan mode, the read-before-edit approval flow in the terminal agent&lt;/a&gt;, this rhythm will feel familiar. Cowork borrows the same "propose before you change anything" instinct, just wrapped in a desktop UI instead of a &lt;code&gt;Shift+Tab&lt;/code&gt; keystroke. That approval gate is the difference between a helpful agent and a scary one, and it's the first thing I'd check before letting any tool near my files.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;My take:&lt;/strong&gt; the consent model is genuinely good, but treat "ask before acting" as a floor, not a guarantee. I still point file agents at a copy of a folder, not the original, the first few times I run a new kind of task. Watch what it actually does, then loosen up.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What Can Cowork Connect To? Plugins and Tools
&lt;/h2&gt;

&lt;p&gt;Cowork isn't limited to reading and writing local files. It extends through plugins and tools, and Anthropic launched a plugin marketplace for the desktop apps in early 2026 (&lt;a href="https://claude.com/product/cowork" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026). Plugins let Cowork reach past your folders into the services where your work actually lives, so a task can pull data from a connected tool, act on it, and write the result back to a file on your machine.&lt;/p&gt;

&lt;p&gt;The same rule that governs folders governs tools: you choose which ones Cowork can use, and it can't reach anything you haven't granted (&lt;a href="https://support.claude.com/en/articles/13345190-get-started-with-claude-cowork" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026). That's the right instinct. An agent that can both edit your files and call external services is genuinely powerful, and the permissions model is what keeps "powerful" from tipping into "reckless." Before you wire up a plugin that can act on your behalf, it's worth knowing exactly what it can touch, which is its own subject in the security and permissions deep-dive, what Cowork can and can't reach and the real risks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which Devices and Platforms Run Claude Cowork?
&lt;/h2&gt;

&lt;p&gt;Claude Cowork runs on Mac, Windows, web, and mobile, and it can now run in the cloud with no device online at all (&lt;a href="https://claude.com/blog/cowork-web-mobile" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026). That spread happened fast, and the dates matter because low-quality sources keep repeating a wrong "October 2024" launch. Here's the verified timeline.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;January 2026:&lt;/strong&gt; Anthropic launched Cowork as a macOS research preview, Max-first, with a waitlist for other plans (&lt;a href="https://techcrunch.com/2026/01/12/anthropics-new-cowork-tool-offers-claude-code-without-the-code/" rel="noopener noreferrer"&gt;TechCrunch&lt;/a&gt;, 2026).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;February 2026:&lt;/strong&gt; a Windows beta joined the rollout.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;April 9, 2026:&lt;/strong&gt; general availability on both macOS and Windows, across all paid plans (&lt;a href="https://claude.com/blog/cowork-for-enterprise" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026), corroborated by &lt;a href="https://9to5mac.com/2026/04/09/anthropic-scales-up-with-enterprise-features-for-claude-cowork-and-managed-agents/" rel="noopener noreferrer"&gt;9to5Mac&lt;/a&gt; (2026).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;July 7, 2026:&lt;/strong&gt; mobile (iOS and Android), web, and cloud remote and scheduled sessions, in beta and starting with Max users (&lt;a href="https://claude.com/blog/cowork-web-mobile" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the short version: a desktop-only Mac beta in January became a cross-platform, run-anywhere agent in about six months. If you're specifically trying to install it on a PC, the Windows-specific setup steps and gotchas are their own topic: see the Claude Cowork for Windows install guide, including the virtualization gate. For everyone else, the takeaway is that "where can I run Cowork" now has a boring answer: pretty much anywhere you already use Claude.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who Gets Claude Cowork?
&lt;/h2&gt;

&lt;p&gt;Who gets Claude Cowork is simple: anyone on a paid Claude plan. Cowork is available to Pro, Max, Team, and Enterprise subscribers, and it is not on the free tier (&lt;a href="https://support.claude.com/en/articles/13345190-get-started-with-claude-cowork" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026). Pro starts at $20/month and Max at $100/month (&lt;a href="https://claude.com/pricing" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026), and Cowork is included at no extra charge on each.&lt;/p&gt;

&lt;p&gt;That "free on the plan you already pay for" framing carries more weight than it first appears. Anthropic captured 40% of enterprise LLM API spend by late 2025, up from 24% in 2024 and 12% in 2023 (&lt;a href="https://menlovc.com/perspective/2025-the-state-of-generative-ai-in-the-enterprise/" rel="noopener noreferrer"&gt;Menlo Ventures&lt;/a&gt;, 2025). Its newest agent shipping bundled into existing subscriptions, rather than as a separate SKU, is a deliberate distribution play, and a real value if you're already inside its ecosystem.&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%2F4ukclu1mvhtpaxwr9lh9.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%2F4ukclu1mvhtpaxwr9lh9.png" alt="Line chart: Anthropic's share of enterprise LLM API spend rose from 12 percent in 2023 to 24 percent in 2024 to 40 percent in 2025." width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The catch is tokens. Anthropic is explicit that working on tasks with Cowork consumes more of your usage allowance than chatting, because multi-step jobs are compute-intensive (&lt;a href="https://support.claude.com/en/articles/13345190-get-started-with-claude-cowork" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026). On Pro, a couple of ambitious Cowork runs can eat your window. If you plan to use it daily, Max is the realistic tier, and the full cost math lives in the Claude Cowork pricing breakdown, is it free, what each plan gets, and the token-burn caveat.&lt;/p&gt;

&lt;p&gt;Eligibility is one question; fit is another. Cowork is aimed squarely at non-developers doing multi-step desk work: analysts wrangling data, operations people chasing documents, researchers synthesizing sources, anyone whose day is spreadsheets and PDFs rather than pull requests. And the audience is broader than "at work." Claude usage skews more personal on weekends, climbing from roughly 35% of activity on weekdays to nearly 50% on Saturdays and Sundays (&lt;a href="https://www.anthropic.com/research/economic-index-june-2026-report" rel="noopener noreferrer"&gt;Anthropic Economic Index&lt;/a&gt;, 2026). A general-purpose file agent gets pulled into life admin as readily as quarterly reports, which is exactly why it's bundled into consumer plans rather than sold as an enterprise add-on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cowork or Claude Code? The Short Version
&lt;/h2&gt;

&lt;p&gt;The one-line answer: use Claude Code for anything that touches a codebase or a terminal, and Claude Cowork for file-heavy work that doesn't. They share an engine, but they're pointed at different jobs, which is exactly why Anthropic's own data shows only 8.7% of Cowork sessions are coding (&lt;a href="https://techcrunch.com/2026/07/07/the-coding-agent-wars-are-spilling-into-the-rest-of-the-office-claude-cowork/" rel="noopener noreferrer"&gt;TechCrunch&lt;/a&gt;, 2026).&lt;/p&gt;

&lt;p&gt;At a glance:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Claude Code&lt;/th&gt;
&lt;th&gt;Claude Cowork&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Lives in&lt;/td&gt;
&lt;td&gt;Your terminal&lt;/td&gt;
&lt;td&gt;Your desktop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Works on&lt;/td&gt;
&lt;td&gt;Codebases, Git, tests, builds&lt;/td&gt;
&lt;td&gt;Files and documents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Command line&lt;/td&gt;
&lt;td&gt;Required&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Same agent loop, asks before changing anything&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is a summary on purpose. The full head-to-head, with the tasks I ran in both, is its own piece: Claude Code vs Claude Cowork, the comparison from a Claude Code power user.&lt;/p&gt;

&lt;p&gt;Here's where I have to be straight with you, because it's the whole reason I can be useful on this topic. I default to Claude Code. When I broke down where my Anthropic tool-hours actually go, Cowork is a real slice, but a minority one.&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%2Fl9uom3fu1pmioaarkht6.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%2Fl9uom3fu1pmioaarkht6.png" alt="Lollipop chart: the author's own estimate of where their working hours go across Anthropic tools, Claude Code 78 percent, Claude Cowork 14 percent, Claude chat 8 percent." width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So where does Cowork genuinely earn its slice for me? Two places. First, file-wrangling that has nothing to do with code: batching documents, cleaning up a downloads graveyard, turning a folder of invoices into a table. Doing that in a terminal is a chore; Cowork just does it. Second, scheduled work I don't want to babysit. Those are the tasks where opening Claude Code would be using a wrench as a hammer.&lt;/p&gt;

&lt;p&gt;If you're not a developer, flip that verdict entirely. For most people, Cowork is the point of contact, and Claude Code is the thing they never need to open. The reason this comparison is worth writing carefully is that the honest answer depends on who's asking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Does Cowork cost extra on top of my plan?
&lt;/h3&gt;

&lt;p&gt;No, Cowork requires a paid Claude plan, but it costs nothing extra on top of one. It's included on Pro ($20/month), Max ($100/month and up), Team, and Enterprise (&lt;a href="https://claude.com/pricing" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026). The free tier doesn't include it. Because tasks burn more tokens than chat, the pricing guide covers which tier actually fits daily use.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I open Claude Cowork?
&lt;/h3&gt;

&lt;p&gt;You open Claude Cowork from Claude Desktop on Mac or Windows, and since July 2026 also from the sidebar of the Claude mobile app or from claude.ai on the web (&lt;a href="https://claude.com/blog/cowork-web-mobile" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026). Once open, you grant it access to specific folders. It can't see anything you don't explicitly share, and it asks before making changes. For the full first-run walkthrough and real workflows, see how to use Claude Cowork.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is Claude Cowork the same as Claude Code?
&lt;/h3&gt;

&lt;p&gt;No. They share the same agent engine, but Claude Code is a terminal tool for coding, while Cowork is a desktop app for non-coding file work. Anthropic's own usage data makes the split concrete: only 8.7% of Cowork sessions are software development (&lt;a href="https://techcrunch.com/2026/07/07/the-coding-agent-wars-are-spilling-into-the-rest-of-the-office-claude-cowork/" rel="noopener noreferrer"&gt;TechCrunch&lt;/a&gt;, 2026). See the full comparison for a task-by-task breakdown.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can Claude Cowork write code?
&lt;/h3&gt;

&lt;p&gt;It can, but that's not what it's for. Coding was just 8.7% of a 1.2M-session sample (&lt;a href="https://techcrunch.com/2026/07/07/the-coding-agent-wars-are-spilling-into-the-rest-of-the-office-claude-cowork/" rel="noopener noreferrer"&gt;TechCrunch&lt;/a&gt;, 2026), and serious development work belongs in Claude Code, which is built around repositories, version control, and the terminal. Reach for Cowork when the "code" is really a quick script to tidy files, not a codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can Claude Cowork run tasks while I'm away?
&lt;/h3&gt;

&lt;p&gt;Yes. As of July 7, 2026, Cowork supports cloud sessions that run with no device online, including scheduled and recurring tasks (&lt;a href="https://claude.com/blog/cowork-web-mobile" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026). The feature rolled out in beta starting with Max users. It's the biggest reason to consider Cowork beyond one-off jobs: you can hand it recurring work and stop thinking about it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why would a company trust an agent with its files?
&lt;/h3&gt;

&lt;p&gt;Because access is scoped and permission-gated: Cowork only touches folders you name, and it asks before acting (&lt;a href="https://support.claude.com/en/articles/13345190-get-started-with-claude-cowork" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;, 2026). It rides a broader shift, too. Gartner projects 40% of enterprise apps will feature task-specific AI agents by the end of 2026, up from under 5% in 2025 (&lt;a href="https://www.gartner.com/en/newsroom/press-releases/2025-08-26-gartner-predicts-40-percent-of-enterprise-apps-will-feature-task-specific-ai-agents-by-2026-up-from-less-than-5-percent-in-2025" rel="noopener noreferrer"&gt;Gartner&lt;/a&gt;, 2025).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Claude Cowork is Anthropic's agent for the 91% of knowledge work that isn't code: a desktop app that reads, edits, and organizes your files with permission, runs multi-step jobs, and, since July 2026, executes scheduled tasks in the cloud without your machine on. It's free on every paid plan, generally available on Mac and Windows since April 2026, and now on web and mobile too.&lt;/p&gt;

&lt;p&gt;My honest verdict, as someone who lives in the terminal: Cowork isn't going to replace Claude Code for developers, and it isn't trying to. It earns its place for file-heavy, non-coding, run-while-you-sleep work, and for the many people who were never going to open a terminal in the first place. And if the alternative you're weighing is an open-source agent framework rather than Anthropic's sibling tool, the Cowork vs OpenClaw comparison covers that decision.&lt;/p&gt;

&lt;p&gt;Is it worth turning on? If you already pay for a Claude plan, absolutely, because it costs you nothing extra to try. Give it a real, bounded task on a copy of some files and see how it does. The worst case is you learn it doesn't fit your work; the best case is you hand off a recurring chore for good. What I wouldn't do is upgrade to Max solely for Cowork before you've confirmed the workflow sticks, since the token appetite is real. If you want to decide between the two tools for your own setup, start with the Claude Code vs Claude Cowork comparison, then check the pricing details to pick a tier.&lt;/p&gt;

</description>
      <category>claudecowork</category>
      <category>whatisclaudecowork</category>
      <category>anthropic</category>
      <category>aiagents</category>
    </item>
    <item>
      <title>Node.js for Claude Code: Which Version, and When You Don't Need It</title>
      <dc:creator>Nishil Bhave</dc:creator>
      <pubDate>Tue, 21 Jul 2026 11:23:11 +0000</pubDate>
      <link>https://dev.to/nishilbhave/nodejs-for-claude-code-which-version-and-when-you-dont-need-it-4oln</link>
      <guid>https://dev.to/nishilbhave/nodejs-for-claude-code-which-version-and-when-you-dont-need-it-4oln</guid>
      <description>&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%2F299ahhoxnplucrl1ooj9.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%2F299ahhoxnplucrl1ooj9.png" alt="A comparison table for installing Claude Code: the native installer and Homebrew or WinGet need no Node.js, while the npm path needs Node 22 or later." width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I ran &lt;code&gt;nvm use 18&lt;/code&gt; for an old project, switched terminals, typed &lt;code&gt;claude&lt;/code&gt;, and got &lt;code&gt;command not found&lt;/code&gt;. Ten minutes later I was reading a Stack Overflow thread about the "Claude Code requires Node.js version 18 or higher" error, convinced I'd broken my Node setup. I hadn't. I'd just installed Claude Code the old way, back when it actually cared what Node version was on my PATH.&lt;/p&gt;

&lt;p&gt;Here's the thing almost every setup guide still gets wrong: the Node.js question is mostly historical. The install method Anthropic now recommends downloads a native binary that never touches your Node at all. So before you go installing a specific Node version, or blaming nvm, it's worth knowing what actually needs Node, which version, and when you can stop caring entirely.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Code's recommended install (the native installer) needs &lt;strong&gt;zero Node.js&lt;/strong&gt;. It ships a native binary that doesn't invoke Node at runtime (&lt;a href="https://code.claude.com/docs/en/setup" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026).&lt;/li&gt;
&lt;li&gt;Only the &lt;strong&gt;npm install path&lt;/strong&gt; needs Node, and as of v2.1.198 it wants &lt;strong&gt;Node 22 or later&lt;/strong&gt; (&lt;a href="https://code.claude.com/docs/en/setup" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026).&lt;/li&gt;
&lt;li&gt;Even on the npm path, Node is used at install time only. The installed &lt;code&gt;claude&lt;/code&gt; binary is native and never calls your Node.&lt;/li&gt;
&lt;li&gt;The classic &lt;code&gt;requires Node.js version 18 or higher&lt;/code&gt; error and most nvm conflicts are npm / VS Code extension problems. The cleanest fix is switching to the native installer.&lt;/li&gt;
&lt;li&gt;You'll still want Node 22 LTS around for npx-based MCP servers and your own JavaScript projects.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Does Claude Code need Node.js?
&lt;/h2&gt;

&lt;p&gt;No. Not for the install method Anthropic recommends. The native installer (&lt;code&gt;curl -fsSL https://claude.ai/install.sh | bash&lt;/code&gt; on macOS and Linux, or &lt;code&gt;irm https://claude.ai/install.ps1 | iex&lt;/code&gt; in PowerShell) downloads a native binary and, in Anthropic's own words, that binary "does not itself invoke Node" (&lt;a href="https://code.claude.com/docs/en/setup" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). No Node, no version to match, no PATH to keep in sync.&lt;/p&gt;

&lt;p&gt;That surprises people, because for a long time Claude Code shipped only as an npm package, and npm packages need Node. The runtime moved on. Today the npm package is one install path among several (native, Homebrew, WinGet, apt, dnf, apk), and it's the only one that touches Node. Here's the part that trips everyone up: even the npm package installs the &lt;em&gt;same&lt;/em&gt; native binary as the standalone installer. It pulls the binary in through a per-platform optional dependency like &lt;code&gt;@anthropic-ai/claude-code-darwin-arm64&lt;/code&gt;, links it into place, and then Node's job is done. Your Node version matters while npm runs the install. It does not matter when &lt;code&gt;claude&lt;/code&gt; runs.&lt;/p&gt;

&lt;p&gt;So the honest answer to "does Claude Code need Node" is: the app doesn't, one of its install paths does, and only for a few seconds during setup.&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%2Fcbuprmxoh6gd39xwce7l.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%2Fcbuprmxoh6gd39xwce7l.png" alt="Horizontal bar chart: the native Claude Code installer needs no Node.js, while the npm install path required Node 18 on older versions and Node 22 on v2.1.198 and later." width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Node.js version does Claude Code need?
&lt;/h2&gt;

&lt;p&gt;If you install through npm, you need &lt;strong&gt;Node.js 22 or later&lt;/strong&gt;. That became the requirement in Claude Code v2.1.198 (&lt;a href="https://code.claude.com/docs/en/setup" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). Before that release the floor was Node 18, which is why you still see the "requires Node.js version 18 or higher" message quoted all over old forum threads.&lt;/p&gt;

&lt;p&gt;There's a nice bit of grace built in. If you run &lt;code&gt;npm install -g @anthropic-ai/claude-code&lt;/code&gt; on an older Node version, npm prints an &lt;code&gt;EBADENGINE&lt;/code&gt; warning but doesn't fail. The install completes and &lt;code&gt;claude&lt;/code&gt; still runs, because the package downloads that native binary and the binary doesn't use your Node. So the version requirement is really a warning about the install step, not a hard wall you smash into.&lt;/p&gt;

&lt;p&gt;Every other install path skips the question. The native installer, Homebrew, WinGet, and the Linux package managers (apt, dnf, apk) all pull the same signed native binary with no Node involved. For reference, the actual system requirements are macOS 13.0+, Windows 10 1809+, Ubuntu 20.04+, Debian 10+, or Alpine 3.19+, with 4 GB of RAM and an x64 or ARM64 processor (&lt;a href="https://code.claude.com/docs/en/setup" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). Node isn't on that list.&lt;/p&gt;

&lt;p&gt;My recommendation: if you have any other reason to want Node (and most developers do), install &lt;strong&gt;Node 22 LTS&lt;/strong&gt;. It clears the npm requirement and it's the current long-term-support line, so you're not chasing a moving target. But install it for &lt;em&gt;your&lt;/em&gt; work, not for Claude Code.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to check what you actually have
&lt;/h2&gt;

&lt;p&gt;Before you touch a single version, find out how Claude Code is installed and which Node your shell sees. Ninety percent of the confusion I run into is someone fixing the wrong thing because they never checked. Four commands settle it.&lt;/p&gt;

&lt;p&gt;Start with the built-in diagnostic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude &lt;span class="nt"&gt;--version&lt;/span&gt;   &lt;span class="c"&gt;# confirms claude is on your PATH at all&lt;/span&gt;
claude doctor      &lt;span class="c"&gt;# full report: install type, update status, PATH issues&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;claude doctor&lt;/code&gt; is the fastest way to learn whether you're on a native or npm install, and it flags PATH and update problems in plain language. Then check for duplicate installs, which cause more "it worked yesterday" mysteries than anything else:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;which &lt;span class="nt"&gt;-a&lt;/span&gt; claude    &lt;span class="c"&gt;# macOS / Linux: lists every claude on your PATH&lt;/span&gt;
where.exe claude   &lt;span class="c"&gt;# Windows PowerShell&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If more than one path comes back, you have competing installs fighting over which &lt;code&gt;claude&lt;/code&gt; runs. A native install shows up as &lt;code&gt;~/.local/bin/claude&lt;/code&gt; symlinked into &lt;code&gt;~/.local/share/claude/versions/&lt;/code&gt;; an npm global shows in &lt;code&gt;npm -g ls @anthropic-ai/claude-code&lt;/code&gt; (&lt;a href="https://code.claude.com/docs/en/troubleshoot-install" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). Keep one, remove the rest. Finally, separate the two questions people constantly merge:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;--version&lt;/span&gt;     &lt;span class="c"&gt;# what Node your shell sees (relevant only for npm installs and MCP)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;claude doctor&lt;/code&gt; says you're on a native install, that &lt;code&gt;node --version&lt;/code&gt; output has nothing to do with whether Claude Code runs. That single realization saves most of the debugging.&lt;/p&gt;

&lt;h2&gt;
  
  
  When you still want Node.js around
&lt;/h2&gt;

&lt;p&gt;Claude Code doesn't need Node. Your workflow probably does. This is the nuance that gets lost when people either over-install ("Node 18+ required!") or under-install ("Claude Code needs nothing, delete Node").&lt;/p&gt;

&lt;p&gt;Three real reasons to keep Node on the machine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MCP servers.&lt;/strong&gt; A lot of Model Context Protocol servers ship as npm packages and launch through &lt;code&gt;npx&lt;/code&gt;. If you wire up a filesystem, GitHub, or Postgres MCP server that runs via &lt;code&gt;npx&lt;/code&gt;, that command needs Node even though Claude Code itself doesn't. Point Claude Code at those tools and you're back to needing a working Node.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your actual projects.&lt;/strong&gt; If you write JavaScript or TypeScript, you already have Node, and Claude Code will happily run your &lt;code&gt;npm test&lt;/code&gt;, &lt;code&gt;npm run build&lt;/code&gt;, and &lt;code&gt;npx&lt;/code&gt; scripts inside a session. No Node, no build tooling for it to drive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Other global CLIs.&lt;/strong&gt; Plenty of dev tools install through npm. If Claude Code is your only npm-installed tool, you can drop Node. If it's one of ten, keep it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the decision isn't "does Claude Code need Node," it's "does anything I ask Claude Code to &lt;em&gt;do&lt;/em&gt; need Node." I put the signals I actually weigh into a quick self-check below. Score yourself: if you land high, install Node 22 LTS; if you land low, the native installer alone is genuinely all you need.&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%2Feratzcsxburl5pxpg8b4.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%2Feratzcsxburl5pxpg8b4.png" alt="Radar chart scoring five signals for whether you need Node.js installed: running npx MCP servers scores 9, building JavaScript or TypeScript projects 8, working in WSL with Windows Node 6, relying on the VS Code extension's Node detection 5, and running only the native CLI 1." width="799" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The "requires Node.js version 18 or higher" error
&lt;/h2&gt;

&lt;p&gt;This is the error that sends people down the rabbit hole: &lt;code&gt;Error: Claude Code requires Node.js version 18 or higher to be installed.&lt;/code&gt; It shows up even when you have Node 22 installed and working, which is what makes it so maddening. I've had it fire in a terminal where &lt;code&gt;node --version&lt;/code&gt; printed &lt;code&gt;v22&lt;/code&gt; a second earlier.&lt;/p&gt;

&lt;p&gt;The message is almost always lying about the cause. It's not that Node is missing or too old. It's that the process throwing the error can't &lt;em&gt;see&lt;/em&gt; your Node. This happens most on the npm path and inside the VS Code extension. A version manager like nvm or asdf hasn't been initialized in that process's environment, so the Node you set up in your shell isn't on the PATH the extension inherited (&lt;a href="https://github.com/anthropics/claude-code/issues/8439" rel="noopener noreferrer"&gt;GitHub issue #8439&lt;/a&gt;, 2026). The Node is right there. The tool just isn't looking in the right place.&lt;/p&gt;

&lt;p&gt;I'm keeping this at the runtime level on purpose. This isn't an error-code catalog, and the exact message text drifts between versions. If you're chasing a specific exit code or a different Node-adjacent failure, I keep a fuller breakdown in &lt;a href="https://maketocreate.com/claude-code-errors-every-code-cause-and-fix-2026-guide/" rel="noopener noreferrer"&gt;the errors guide with every code, cause, and fix&lt;/a&gt;. For this one, there are two durable fixes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Switch to the native installer.&lt;/strong&gt; It has no Node dependency, so the whole class of "can't find Node" errors disappears. This is what I did, and I haven't seen the message since.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make sure your version manager is loaded&lt;/strong&gt; in the environment that runs Claude Code, whether that's your shell rc file or the IDE's launch environment. More on that next, because nvm is the usual culprit.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When I sort the Node-related install failures I've either hit or seen reported, they cluster in a way that tells the whole story. Almost none of them are about the Claude Code binary itself.&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%2F25f6h5am8wqztwj59kqt.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%2F25f6h5am8wqztwj59kqt.png" alt="Donut chart categorizing eight documented Node-related install failure modes for Claude Code: version manager or PATH not loaded accounts for three, WSL importing Windows Node two, npm packaging issues two, and npm permission errors one." width="799" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  nvm conflicts with Claude Code (and how to fix them)
&lt;/h2&gt;

&lt;p&gt;nvm is the single most common reason Claude Code and Node fall out with each other. The trap is simple: you install Claude Code globally under one Node version, then run &lt;code&gt;nvm use&lt;/code&gt; to switch to a different version for another project. nvm points your PATH at the new version's global folder, the old global &lt;code&gt;claude&lt;/code&gt; isn't there, and suddenly the command is gone. Nothing broke. The shim just moved.&lt;/p&gt;

&lt;p&gt;On Windows Subsystem for Linux it gets one layer worse, and the docs are specific about it. WSL imports the Windows PATH by default, so if you have nvm installed in &lt;em&gt;both&lt;/em&gt; Windows and WSL, switching Node versions inside WSL can break because the Windows nvm takes priority. The most common cause is that nvm simply isn't loaded in your shell (&lt;a href="https://code.claude.com/docs/en/troubleshoot-install" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). A related symptom is &lt;code&gt;exec: node: not found&lt;/code&gt; when you run &lt;code&gt;claude&lt;/code&gt;, which means WSL is reaching for the &lt;em&gt;Windows&lt;/em&gt; Node install. You can confirm it by running &lt;code&gt;which node&lt;/code&gt;: a path starting with &lt;code&gt;/mnt/c/&lt;/code&gt; is a Windows binary leaking into Linux.&lt;/p&gt;

&lt;p&gt;The fixes, in order of how much I trust them:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Load nvm in your shell rc.&lt;/strong&gt; Half the "nvm conflict" reports are just nvm not being sourced. Add the loader to &lt;code&gt;~/.bashrc&lt;/code&gt; or &lt;code&gt;~/.zshrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;NVM_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.nvm"&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVM_DIR&lt;/span&gt;&lt;span class="s2"&gt;/nvm.sh"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVM_DIR&lt;/span&gt;&lt;span class="s2"&gt;/nvm.sh"&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVM_DIR&lt;/span&gt;&lt;span class="s2"&gt;/bash_completion"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NVM_DIR&lt;/span&gt;&lt;span class="s2"&gt;/bash_completion"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Prepend your Linux Node path&lt;/strong&gt; if Windows paths still win in WSL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.nvm/versions/node/&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;node &lt;span class="nt"&gt;-v&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Or sidestep the whole thing with the native installer.&lt;/strong&gt; This is the real answer. The native &lt;code&gt;claude&lt;/code&gt; binary isn't a Node program, so it doesn't live in any nvm version folder and doesn't care which Node you've switched to. I moved to the native install specifically because I was tired of &lt;code&gt;nvm use&lt;/code&gt; deciding whether Claude Code existed. Since then, my Node version and my Claude Code install have nothing to do with each other, which is exactly how it should be. One caution from the docs worth repeating: don't disable Windows PATH importing to force the issue, and don't uninstall Node from Windows if you use it for Windows development. Fix the load order, don't burn the setup down.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about the VS Code extension and Node?
&lt;/h2&gt;

&lt;p&gt;The VS Code extension deserves its own note, because it's where the Node story gets most confusing. The extension doesn't run the same &lt;code&gt;claude&lt;/code&gt; you have in your terminal. It bundles a private copy of the CLI inside its own extension directory and uses that for its chat panel, and it does not add &lt;code&gt;claude&lt;/code&gt; to your PATH (&lt;a href="https://code.claude.com/docs/en/troubleshoot-install" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). So if you installed only the extension and then open a terminal expecting &lt;code&gt;claude&lt;/code&gt; to work, it won't. There's no &lt;code&gt;~/.local/bin/claude&lt;/code&gt; because the extension never put one there.&lt;/p&gt;

&lt;p&gt;This also explains why the "requires Node.js version 18 or higher" error shows up inside the editor more than anywhere else. VS Code launches with whatever environment it inherited when it started, which frequently does not include your shell's nvm or asdf initialization. Your terminal sees Node 22; the editor process sees no Node at all, because the version manager that puts Node on the PATH never ran in that process. Same machine, same Node install, two different views of it.&lt;/p&gt;

&lt;p&gt;The runtime takeaway is simple. If you want &lt;code&gt;claude&lt;/code&gt; in your terminal, run the standalone native install, and don't assume the extension covered it. If the extension itself throws a Node error, the fix is to launch VS Code from a terminal where your version manager is already loaded, so the editor inherits a PATH that can actually find Node. That's an environment problem, not a Node problem, which is the theme of this entire article.&lt;/p&gt;

&lt;h2&gt;
  
  
  npm vs the native installer: which should you pick?
&lt;/h2&gt;

&lt;p&gt;For most people, the native installer. It's what Anthropic recommends, it needs no Node, and it auto-updates in the background so you're not running &lt;code&gt;npm install -g ...@latest&lt;/code&gt; every couple of weeks. That's the whole pitch, and it's a good one.&lt;/p&gt;

&lt;p&gt;The npm path is still fine if you already manage a pile of global npm tooling and you're on Node 22 or later. You get the same native binary either way. Two rules if you go this route. First, don't use &lt;code&gt;sudo npm install -g @anthropic-ai/claude-code&lt;/code&gt;, which invites permission and security problems. Second, if the binary goes missing after install, check that optional dependencies aren't disabled, because the native binary ships as a per-platform optional dependency (&lt;a href="https://code.claude.com/docs/en/setup" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026).&lt;/p&gt;

&lt;p&gt;If you're migrating off an old npm install to escape Node headaches, the sequence is short:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# See every claude on your PATH (watch for duplicates)&lt;/span&gt;
which &lt;span class="nt"&gt;-a&lt;/span&gt; claude

&lt;span class="c"&gt;# Remove the npm global install&lt;/span&gt;
npm uninstall &lt;span class="nt"&gt;-g&lt;/span&gt; @anthropic-ai/claude-code

&lt;span class="c"&gt;# Install the native binary (macOS / Linux)&lt;/span&gt;
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://claude.ai/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open a new terminal and run &lt;code&gt;claude --version&lt;/code&gt; to confirm the native one is answering. If you want the full platform-by-platform walkthrough, including the Windows and WSL specifics I've only touched on here, that all lives in &lt;a href="https://maketocreate.com/claude-code-installation-guide-every-platform-every-gotcha/" rel="noopener noreferrer"&gt;the complete install and setup guide&lt;/a&gt;. This article is about the runtime; that one is about the steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does Claude Code need Node.js?&lt;/strong&gt;&lt;br&gt;
Not for the recommended native installer, which ships a native binary that doesn't invoke Node at runtime. Only the npm install path needs Node, and even then it's used at install time, not when &lt;code&gt;claude&lt;/code&gt; runs (&lt;a href="https://code.claude.com/docs/en/setup" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Node.js version does Claude Code require?&lt;/strong&gt;&lt;br&gt;
If you install through npm, Node 22 or later as of v2.1.198. Older Node versions trigger an &lt;code&gt;EBADENGINE&lt;/code&gt; warning but usually still install and run. The native, Homebrew, WinGet, and Linux package-manager installs require no Node at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does Claude Code say it requires Node.js 18 when I have Node 22?&lt;/strong&gt;&lt;br&gt;
Because the process throwing the error can't see your Node, not because your Node is too old. It's typically the npm path or the VS Code extension running without your version manager loaded, so nvm's Node isn't on the PATH it inherited. Loading nvm in your shell fixes it; switching to the native installer removes the dependency entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I fix nvm conflicts with Claude Code?&lt;/strong&gt;&lt;br&gt;
Make sure nvm is sourced in your &lt;code&gt;~/.bashrc&lt;/code&gt; or &lt;code&gt;~/.zshrc&lt;/code&gt;, and in WSL prepend your Linux Node path so the Windows Node install doesn't take priority. The durable fix is the native installer, which isn't a Node program and ignores your nvm state completely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should I install Claude Code with npm or the native installer?&lt;/strong&gt;&lt;br&gt;
The native installer for most people: no Node requirement and background auto-updates. Use npm only if you already manage global npm tools and run Node 22+, and never with &lt;code&gt;sudo&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;p&gt;The Node.js story around Claude Code is mostly a leftover from when npm was the only way in. Today, the runtime question has a clean answer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The recommended native installer needs no Node. Full stop.&lt;/li&gt;
&lt;li&gt;The npm path needs Node 22+, but only at install time. The binary it installs is native.&lt;/li&gt;
&lt;li&gt;The "requires Node 18" error and nvm conflicts are PATH and version-manager problems, and the native installer makes them vanish.&lt;/li&gt;
&lt;li&gt;Keep Node 22 LTS anyway, because your MCP servers and your own projects want it, even if Claude Code doesn't.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Get Claude Code installed the native way, keep Node for your real work, and stop letting &lt;code&gt;nvm use&lt;/code&gt; decide whether your AI pair-programmer shows up. If you hit a specific error along the way, the &lt;a href="https://maketocreate.com/claude-code-errors-every-code-cause-and-fix-2026-guide/" rel="noopener noreferrer"&gt;troubleshooting guide&lt;/a&gt; has the rest.&lt;/p&gt;

</description>
      <category>node</category>
      <category>claudecode</category>
      <category>nvm</category>
      <category>nodeversion</category>
    </item>
    <item>
      <title>AnythingLLM Ollama Model Not Found: 5 Fixes That Work</title>
      <dc:creator>Nishil Bhave</dc:creator>
      <pubDate>Mon, 20 Jul 2026 16:14:24 +0000</pubDate>
      <link>https://dev.to/nishilbhave/anythingllm-ollama-model-not-found-5-fixes-that-work-hma</link>
      <guid>https://dev.to/nishilbhave/anythingllm-ollama-model-not-found-5-fixes-that-work-hma</guid>
      <description>&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%2Fhkds47292qienbqri456.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%2Fhkds47292qienbqri456.png" alt="Five AnythingLLM and Ollama model-not-found causes, from server not running to out of memory, converging into one working connection." width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You wired AnythingLLM to Ollama, hit send, and got "model not found." Or the model dropdown sits empty. Or it spins on "loading available models" forever. The frustrating part: your model is right there when you run &lt;code&gt;ollama list&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's the thing almost nobody says out loud. That error is rarely about a broken model. It's about two local processes that can't find each other. AnythingLLM talks to Ollama over HTTP, and every "model not found" I've chased traces back to one of five plumbing problems, not a corrupt download.&lt;/p&gt;

&lt;p&gt;I reproduced all five on Ollama 0.32.0 before writing this, so the fixes below are what I actually saw, not what I assume happens. We'll go symptom, cause, fix, ordered by how often each one is the real culprit.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ollama listens on &lt;code&gt;127.0.0.1:11434&lt;/code&gt; only by default (&lt;a href="https://docs.ollama.com/faq" rel="noopener noreferrer"&gt;Ollama docs&lt;/a&gt;, 2026), which is the top reason a Dockerized AnythingLLM can't see it.&lt;/li&gt;
&lt;li&gt;Inside Docker, &lt;code&gt;localhost&lt;/code&gt; points at the container, not your host. Use &lt;code&gt;http://host.docker.internal:11434&lt;/code&gt; instead (&lt;a href="https://docs.anythingllm.com/ollama-connection-troubleshooting" rel="noopener noreferrer"&gt;AnythingLLM docs&lt;/a&gt;, 2026).&lt;/li&gt;
&lt;li&gt;The literal "model not found" is usually a tag mismatch: you asked for &lt;code&gt;llama3&lt;/code&gt; but you have &lt;code&gt;llama3.1:8b&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Chat working but document upload failing is a separate cause: the embedder model was never pulled.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The 30-second diagnosis
&lt;/h2&gt;

&lt;p&gt;Ollama binds to &lt;code&gt;127.0.0.1:11434&lt;/code&gt; by default (&lt;a href="https://docs.ollama.com/faq" rel="noopener noreferrer"&gt;Ollama docs&lt;/a&gt;, 2026), and AnythingLLM reaches it over that HTTP endpoint. So before you touch any setting, match your symptom to the likely cause, then answer five questions in order.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What you see&lt;/th&gt;
&lt;th&gt;Most likely cause&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Empty model dropdown, or "loading available models" never finishes&lt;/td&gt;
&lt;td&gt;Ollama isn't running, or the Base URL is wrong (Docker)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chat errors mid-reply with "model not found"&lt;/td&gt;
&lt;td&gt;Tag mismatch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chat works, but uploading a document fails&lt;/td&gt;
&lt;td&gt;Embedder model not pulled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Right model, right URL, still won't load or times out&lt;/td&gt;
&lt;td&gt;Not enough memory&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each of those maps to a fix below. Here's the ordered version to run top to bottom:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Is Ollama even running?&lt;/strong&gt; Run &lt;code&gt;curl http://127.0.0.1:11434&lt;/code&gt;. No response means start with Cause 1.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does the exact tag exist?&lt;/strong&gt; Run &lt;code&gt;ollama list&lt;/code&gt; and read the NAME column carefully. If your model name doesn't match a row exactly, jump to Cause 3.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Are you running AnythingLLM in Docker?&lt;/strong&gt; If yes, and the dropdown is empty, it's almost always the Base URL. Go to Cause 2.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does chat work but embedding a document fail?&lt;/strong&gt; That's the embedder, Cause 4.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Right tag, right URL, still won't load?&lt;/strong&gt; You're probably out of memory. Cause 5.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most people are one setting away from a working setup. Let's find which one. For the wider picture on getting models onto your machine in the first place, see our &lt;a href="https://maketocreate.com/local-llms-in-2026-which-runtime-to-run-and-the-hardware-you-need/" rel="noopener noreferrer"&gt;pillar guide to running LLMs locally&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cause 1: Ollama isn't actually running
&lt;/h2&gt;

&lt;p&gt;If &lt;code&gt;curl http://127.0.0.1:11434&lt;/code&gt; returns nothing, Ollama isn't up, and AnythingLLM has nothing to talk to (&lt;a href="https://docs.ollama.com/faq" rel="noopener noreferrer"&gt;Ollama docs&lt;/a&gt;, 2026). This shows up in the UI as an empty model list or a "loading available models" spinner that never resolves. It looks like AnythingLLM is broken. It isn't. The server it depends on is just asleep.&lt;/p&gt;

&lt;p&gt;Start it and confirm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start the server (foreground; leave it running)&lt;/span&gt;
ollama serve

&lt;span class="c"&gt;# In another terminal, prove it's alive&lt;/span&gt;
curl http://127.0.0.1:11434
&lt;span class="c"&gt;# -&amp;gt; "Ollama is running"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I pointed a client at the wrong port to simulate a down server, &lt;code&gt;curl&lt;/code&gt; returned exit code 7 and an empty body. That's the fingerprint of "nothing is listening here," which is different from "model not found." If you get exit 7 or a blank response, the server is your problem, not the model. No terminal handy? Open &lt;code&gt;http://127.0.0.1:11434&lt;/code&gt; in a browser instead. A running server answers with the plain text "Ollama is running"; anything else, a spinner or a connection error, means it's down or bound somewhere your browser can't reach.&lt;/p&gt;

&lt;p&gt;One gotcha worth knowing: the Ollama desktop app and &lt;code&gt;ollama serve&lt;/code&gt; both try to hold port 11434. If the app is already running, a second &lt;code&gt;ollama serve&lt;/code&gt; fails with an "address already in use" error, which reads like a crash but just means the port is taken. Pick one. On a Mac or Windows box, the menu-bar app is usually enough. If you're not sure what's on the port, &lt;code&gt;lsof -nP -iTCP:11434 -sTCP:LISTEN&lt;/code&gt; (macOS and Linux) tells you which process owns it. Managing the service itself, stopping it, restarting it, or removing it, lives in our &lt;a href="https://maketocreate.com/ollama-in-2026-run-tune-and-fix-local-llms-complete-guide/" rel="noopener noreferrer"&gt;complete Ollama setup and maintenance guide&lt;/a&gt;, not here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cause 2: AnythingLLM is pointed at the wrong Base URL
&lt;/h2&gt;

&lt;p&gt;This is the big one for Docker users, and the AnythingLLM docs are blunt about it: "localhost and 127.0.0.1 are not valid URLs for the Docker container Ollama connection in AnythingLLM because both of these refer to the container network and not the host machine" (&lt;a href="https://docs.anythingllm.com/ollama-connection-troubleshooting" rel="noopener noreferrer"&gt;AnythingLLM docs&lt;/a&gt;, 2026). The symptom is a desktop install that works fine, then an empty dropdown the moment you switch to the Docker image.&lt;/p&gt;

&lt;p&gt;Think about what &lt;code&gt;localhost&lt;/code&gt; means inside a container. It means &lt;em&gt;this container&lt;/em&gt;. Your Ollama server is running on the host, one network hop away, and the container has no idea. So the fix is to give AnythingLLM an address that reaches the host:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;macOS / Windows:&lt;/strong&gt; &lt;code&gt;http://host.docker.internal:11434&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linux:&lt;/strong&gt; &lt;code&gt;http://172.17.0.1:11434&lt;/code&gt;, and add &lt;code&gt;--add-host=host.docker.internal:host-gateway&lt;/code&gt; to your &lt;code&gt;docker run&lt;/code&gt; command&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You need Docker v18.03+ on Mac or Windows, and 20.10+ on Linux, for &lt;code&gt;host.docker.internal&lt;/code&gt; to resolve (&lt;a href="https://raw.githubusercontent.com/Mintplex-Labs/anything-llm/master/docker/HOW_TO_USE_DOCKER.md" rel="noopener noreferrer"&gt;AnythingLLM Docker guide&lt;/a&gt;, 2026). Set the address in AnythingLLM under the Ollama LLM provider, in the Ollama Base URL field.&lt;/p&gt;

&lt;p&gt;Now the half that most tutorials skip. Even with &lt;code&gt;host.docker.internal&lt;/code&gt;, the connection can still fail, and here's why. I checked what Ollama actually listens on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lsof &lt;span class="nt"&gt;-nP&lt;/span&gt; &lt;span class="nt"&gt;-iTCP&lt;/span&gt;:11434 &lt;span class="nt"&gt;-sTCP&lt;/span&gt;:LISTEN
&lt;span class="c"&gt;# ollama ... TCP 127.0.0.1:11434 (LISTEN)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It binds to &lt;code&gt;127.0.0.1&lt;/code&gt; only. A loopback address won't accept a connection coming in from a container, no matter what URL you type. You have to tell Ollama to listen on all interfaces first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# macOS: expose Ollama on the network, then restart the app&lt;/span&gt;
launchctl setenv OLLAMA_HOST &lt;span class="s2"&gt;"0.0.0.0:11434"&lt;/span&gt;

&lt;span class="c"&gt;# Linux (systemd): add to the service override, then reload + restart&lt;/span&gt;
&lt;span class="c"&gt;# Environment="OLLAMA_HOST=0.0.0.0:11434"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The values above come straight from the Ollama FAQ (&lt;a href="https://docs.ollama.com/faq" rel="noopener noreferrer"&gt;Ollama docs&lt;/a&gt;, 2026), and setting &lt;code&gt;OLLAMA_HOST=0.0.0.0:11434&lt;/code&gt; is what made the container reachable in my tests. Base URL and bind address are two separate switches. Flip both.&lt;/p&gt;

&lt;p&gt;Here's a &lt;code&gt;docker run&lt;/code&gt; that gets the container networking right on a Linux host, where &lt;code&gt;host.docker.internal&lt;/code&gt; needs the extra flag to resolve:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 3001:3001 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--add-host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host.docker.internal:host-gateway &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; ~/anythingllm:/app/server/storage &lt;span class="se"&gt;\&lt;/span&gt;
  mintplexlabs/anythingllm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the container running, set the Ollama Base URL to &lt;code&gt;http://host.docker.internal:11434&lt;/code&gt; in AnythingLLM's UI, under the Ollama LLM provider. The &lt;code&gt;--add-host&lt;/code&gt; flag is the piece that makes that hostname resolve to your host from inside the container; the base URL itself is a UI setting, not a container env var. If you'd rather debug it live, shell into the running container and hit Ollama from there before touching AnythingLLM's UI: &lt;code&gt;docker exec -it &amp;lt;container&amp;gt; sh&lt;/code&gt;, then &lt;code&gt;curl http://host.docker.internal:11434/api/tags&lt;/code&gt;. If that curl returns your model list as JSON, the network path is good and any remaining "model not found" is a tag problem, not a connection one. If it hangs or refuses, you're still on the bind-address half. That one test splits the two most common Docker failures apart in about ten seconds, which beats guessing at settings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cause 3: The model tag doesn't match
&lt;/h2&gt;

&lt;p&gt;This one earns the literal error. When AnythingLLM sends a request for a model Ollama doesn't have, the server answers with a flat "not found." On Ollama 0.32.0, with only &lt;code&gt;llama3.1:8b&lt;/code&gt; pulled, here's exactly what I got back from the chat endpoint AnythingLLM uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:11434/api/chat &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"model":"mistral","messages":[{"role":"user","content":"hi"}]}'&lt;/span&gt;
&lt;span class="c"&gt;# {"error":"model 'mistral' not found"}&lt;/span&gt;

curl http://localhost:11434/api/generate &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"model":"llama3","prompt":"hi"}'&lt;/span&gt;
&lt;span class="c"&gt;# {"error":"model 'llama3' not found"}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the second one. I have &lt;code&gt;llama3.1:8b&lt;/code&gt; installed, but a request for &lt;code&gt;llama3&lt;/code&gt; fails, because Ollama matches the full name and tag, not a family. Asking for &lt;code&gt;llama3.1&lt;/code&gt; with no tag fails too, since that resolves to &lt;code&gt;llama3.1:latest&lt;/code&gt;, which I never pulled. This is the trap: the model "exists" in your head as "Llama," but Ollama only knows &lt;code&gt;llama3.1:8b&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The fix is mechanical. Read the exact name, then use it verbatim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama list
&lt;span class="c"&gt;# NAME              ID              SIZE      MODIFIED&lt;/span&gt;
&lt;span class="c"&gt;# llama3.1:8b       46e0c10c039e    4.9 GB    2 months ago&lt;/span&gt;
&lt;span class="c"&gt;# qwen3:8b          500a1f067a9f    5.2 GB    5 months ago&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the NAME column exactly, tag included, and select that in AnythingLLM. If the model isn't listed at all, pull it with the precise name from &lt;a href="https://ollama.com/library" rel="noopener noreferrer"&gt;ollama.com/library&lt;/a&gt;: &lt;code&gt;ollama pull llama3.1:8b&lt;/code&gt;. Watch the pull finish before you retry, because a half-downloaded model can show up in odd states, and a canceled pull leaves nothing selectable.&lt;/p&gt;

&lt;p&gt;A subtle version of this bug is the missing tag. When you type a bare name like &lt;code&gt;llama3.1&lt;/code&gt;, Ollama expands it to &lt;code&gt;llama3.1:latest&lt;/code&gt;, and if you only ever pulled &lt;code&gt;llama3.1:8b&lt;/code&gt;, that &lt;code&gt;:latest&lt;/code&gt; alias doesn't exist. The dropdown may even list the model while the request still fails, because AnythingLLM sometimes remembers a model you selected before you changed what's installed. If you upgraded or re-pulled models and the old choice broke, open the LLM settings, re-open the model dropdown so it refreshes from Ollama, and pick the current tag again.&lt;/p&gt;

&lt;p&gt;Models live in &lt;code&gt;~/.ollama/models&lt;/code&gt; on macOS and &lt;code&gt;/usr/share/ollama/.ollama/models&lt;/code&gt; on Linux by default (&lt;a href="https://docs.ollama.com/faq" rel="noopener noreferrer"&gt;Ollama docs&lt;/a&gt;, 2026), so if you moved that directory with &lt;code&gt;OLLAMA_MODELS&lt;/code&gt;, make sure the server AnythingLLM talks to is the one that can actually see your files. Running Ollama as your user in a terminal and as a background service can point at two different model directories, which looks exactly like "I pulled it but it's gone." Managing and cleaning up those tags is covered in our &lt;a href="https://maketocreate.com/ollama-in-2026-run-tune-and-fix-local-llms-complete-guide/" rel="noopener noreferrer"&gt;Ollama model management and removal section&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cause 4: AnythingLLM's embedder needs its own model
&lt;/h2&gt;

&lt;p&gt;Here's a cause that trips up a lot of people because it hides. Your chat works. Then you upload a document, and it fails. AnythingLLM uses a &lt;em&gt;separate&lt;/em&gt; embedding model to turn documents into vectors, and if you point that embedder at Ollama, you have to download a real embedding model for it, not an LLM (&lt;a href="https://docs.anythingllm.com/setup/embedder-configuration/local/ollama" rel="noopener noreferrer"&gt;AnythingLLM docs&lt;/a&gt;, 2026). The usual pick is &lt;code&gt;nomic-embed-text&lt;/code&gt;. If you never pulled it, the chat model can be perfect and RAG still breaks.&lt;/p&gt;

&lt;p&gt;The reason it hides is timing. The embedder only runs when you add a document to a workspace, so a chat-only session never touches it. You can talk to your model for an hour, decide everything works, then drop in a PDF and watch it fail on a component you didn't know was in play. That's why "chat works but upload doesn't" is such a reliable fingerprint for this one: it points straight at the embedding path, not the chat model you've been staring at.&lt;/p&gt;

&lt;p&gt;The embedding endpoint fails loudly, and its wording is worth seeing, because it differs from the chat error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:11434/api/embeddings &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"model":"mxbai-embed-large","prompt":"test"}'&lt;/span&gt;
&lt;span class="c"&gt;# {"error":"model \"mxbai-embed-large\" not found, try pulling it first"}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things to catch here. First, the embeddings endpoint appends "try pulling it first," while the chat endpoint just says "not found." Same root cause, different string, so don't assume they're separate bugs. Second, once I pulled &lt;code&gt;nomic-embed-text&lt;/code&gt;, the same call returned a real vector instead of an error. The fix is one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull nomic-embed-text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, in AnythingLLM, set the embedding model to &lt;code&gt;nomic-embed-text&lt;/code&gt; and confirm the embedder's Base URL matches the one your chat model uses. If chat reaches Ollama but embedding doesn't, you probably changed the URL in one place and not the other.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cause 5: The model is too big for your memory
&lt;/h2&gt;

&lt;p&gt;You've got the right tag and the right URL, and it still won't load. At that point the suspect is memory. Ollama has to hold the model weights in RAM (or VRAM on a GPU) to run them, and the file size is the floor for how much you need. I measured the actual on-disk footprint of the models I keep around, and the spread is dramatic:&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%2Fq3rmyllemm5ao0awtfoz.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%2Fq3rmyllemm5ao0awtfoz.png" alt="Horizontal bar chart of measured Ollama model footprints on disk: qwen3:30b 18.56 GB, deepseek-r1:14b 8.99 GB, qwen3:8b 5.23 GB, llama3.1:8b 4.92 GB, nomic-embed-text 0.27 GB, measured with ollama list on Ollama 0.32.0." width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;qwen3:30b&lt;/code&gt; is 18.56 GB on disk. A &lt;code&gt;llama3.1:8b&lt;/code&gt; is under 5 GB. Real RAM use runs a bit higher than the file, because the context window and key-value cache need room too. So if you select a 30B model on a 16 GB laptop, it can load partially, thrash, or fail outright, and AnythingLLM surfaces that as a dead or timing-out model rather than a clean error.&lt;/p&gt;

&lt;p&gt;Two levers control the footprint. Quantization is the first: a &lt;code&gt;q4&lt;/code&gt; (4-bit) build is roughly half the size of a &lt;code&gt;q8&lt;/code&gt; (8-bit) one of the same model, at a small quality cost, which is why the default tags lean on &lt;code&gt;q4&lt;/code&gt;. Context length is the second: a longer context window grows the key-value cache that sits alongside the weights, so a model that loads fine at 8K tokens can run you out of memory at 128K. On a GPU, anything that doesn't fit in VRAM spills to system RAM and CPU, and generation slows to a crawl instead of failing outright.&lt;/p&gt;

&lt;p&gt;The fix is to right-size. Pick a smaller or more heavily quantized tag (a &lt;code&gt;:8b&lt;/code&gt; instead of a &lt;code&gt;:30b&lt;/code&gt;, or a &lt;code&gt;q4&lt;/code&gt; variant), shrink the context length in AnythingLLM's model settings, or free up memory by closing other heavy apps before you load. If you want a runtime with a friendlier model-size picker and per-model RAM estimates baked into the UI, our &lt;a href="https://maketocreate.com/lm-studio-in-2026-download-models-run-local-llms-vs-ollama/" rel="noopener noreferrer"&gt;LM Studio guide&lt;/a&gt; pairs with AnythingLLM too, since AnythingLLM speaks to both, and LM Studio makes the memory math visible before you download.&lt;/p&gt;

&lt;h2&gt;
  
  
  After the fix: keep it from coming back
&lt;/h2&gt;

&lt;p&gt;Roughly every recurring case I've seen comes from a setting drifting out of sync after a change, so treat these three as a checklist. First, restart AnythingLLM after you touch any Ollama environment variable, since &lt;code&gt;OLLAMA_HOST&lt;/code&gt; and friends are read at startup (&lt;a href="https://docs.ollama.com/faq" rel="noopener noreferrer"&gt;Ollama docs&lt;/a&gt;, 2026). Second, keep the Base URL identical for the chat model and the embedder. Third, remember that desktop and Docker installs use different addresses, so a config that worked on your laptop won't copy-paste into a container.&lt;/p&gt;

&lt;p&gt;The pattern that saved me the most time: when something breaks, I re-run &lt;code&gt;curl http://127.0.0.1:11434&lt;/code&gt; and &lt;code&gt;ollama list&lt;/code&gt; first, every time, before I open AnythingLLM's settings. Nine times out of ten the answer is right there, and I've stopped editing UI fields at random. It's boring, and it works.&lt;/p&gt;

&lt;p&gt;One more thing worth knowing if you push AnythingLLM further. It also runs MCP tool servers for its agents, configured by editing an &lt;code&gt;anythingllm_mcp_servers.json&lt;/code&gt; file in its storage plugins directory (&lt;a href="https://docs.anythingllm.com/mcp-compatibility/overview" rel="noopener noreferrer"&gt;AnythingLLM docs&lt;/a&gt;, 2026). Those servers connect over their own transport, separate from the Ollama link, so a broken model connection won't take your tools down with it. If you're heading in that direction, our &lt;a href="https://maketocreate.com/mcp-servers-in-2026-complete-model-context-protocol-guide/" rel="noopener noreferrer"&gt;guide to Model Context Protocol servers&lt;/a&gt; is a good next stop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why does AnythingLLM show no Ollama models even though Ollama is running?
&lt;/h3&gt;

&lt;p&gt;Almost always the Base URL. Ollama binds to &lt;code&gt;127.0.0.1:11434&lt;/code&gt; by default (&lt;a href="https://docs.ollama.com/faq" rel="noopener noreferrer"&gt;Ollama docs&lt;/a&gt;, 2026), so a Dockerized AnythingLLM pointed at &lt;code&gt;localhost&lt;/code&gt; reaches the container, not your host. Switch the URL to &lt;code&gt;http://host.docker.internal:11434&lt;/code&gt; and set &lt;code&gt;OLLAMA_HOST=0.0.0.0:11434&lt;/code&gt; on the host, then restart.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Base URL should AnythingLLM use for Ollama in Docker?
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;http://host.docker.internal:11434&lt;/code&gt; on macOS and Windows. On Linux, use &lt;code&gt;http://172.17.0.1:11434&lt;/code&gt; and add &lt;code&gt;--add-host=host.docker.internal:host-gateway&lt;/code&gt; to your &lt;code&gt;docker run&lt;/code&gt; command (&lt;a href="https://docs.anythingllm.com/ollama-connection-troubleshooting" rel="noopener noreferrer"&gt;AnythingLLM docs&lt;/a&gt;, 2026). You need Docker v18.03+ on Mac or Windows, or 20.10+ on Linux, for the hostname to resolve.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does it say model not found when I already pulled the model?
&lt;/h3&gt;

&lt;p&gt;You're likely requesting the wrong tag. On Ollama 0.32.0, asking for &lt;code&gt;llama3&lt;/code&gt; when you have &lt;code&gt;llama3.1:8b&lt;/code&gt; returns &lt;code&gt;{"error":"model 'llama3' not found"}&lt;/code&gt;, since Ollama matches the full name and tag. Run &lt;code&gt;ollama list&lt;/code&gt;, copy the NAME column exactly, and select that string in AnythingLLM.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does AnythingLLM need a separate embedding model?
&lt;/h3&gt;

&lt;p&gt;Yes. Chat and document embedding use different models. If you set Ollama as the embedder, AnythingLLM needs a dedicated embedding model downloaded, not an LLM (&lt;a href="https://docs.anythingllm.com/setup/embedder-configuration/local/ollama" rel="noopener noreferrer"&gt;AnythingLLM docs&lt;/a&gt;, 2026). The common choice is &lt;code&gt;nomic-embed-text&lt;/code&gt;: if chat works but uploads fail, run &lt;code&gt;ollama pull nomic-embed-text&lt;/code&gt;, then set it as the embedding model with the same Base URL your chat model uses.&lt;/p&gt;

&lt;h3&gt;
  
  
  How much RAM do I need to run a model in Ollama?
&lt;/h3&gt;

&lt;p&gt;Enough to hold the weights plus the context. Measured footprints range from 4.92 GB for &lt;code&gt;llama3.1:8b&lt;/code&gt; to 18.56 GB for &lt;code&gt;qwen3:30b&lt;/code&gt; on Ollama 0.32.0, and real usage runs higher. If a correctly-named model won't load, pick a smaller or more quantized tag, or reduce the context length.&lt;/p&gt;

&lt;h2&gt;
  
  
  The five-cause checklist
&lt;/h2&gt;

&lt;p&gt;When AnythingLLM says "model not found," the model is rarely the problem. Walk the list: is Ollama running, is the Base URL reaching the host, does the tag match &lt;code&gt;ollama list&lt;/code&gt; exactly, did you pull the embedder, and does the model fit in memory? One of those five is your answer, and each has a one-line fix.&lt;/p&gt;

&lt;p&gt;Start with &lt;code&gt;curl&lt;/code&gt; and &lt;code&gt;ollama list&lt;/code&gt; before you touch any settings. It's the fastest way to tell a plumbing problem from a real one. When you're ready to go deeper on models, quantization, and the hardware behind them, our &lt;a href="https://maketocreate.com/local-llms-in-2026-which-runtime-to-run-and-the-hardware-you-need/" rel="noopener noreferrer"&gt;guide to running LLMs locally&lt;/a&gt; picks up where this leaves off.&lt;/p&gt;

</description>
      <category>anythingllm</category>
      <category>ollama</category>
      <category>localllm</category>
      <category>modelnotfound</category>
    </item>
    <item>
      <title>Claude Code Plan Mode: How I Use It (and When I Don't)</title>
      <dc:creator>Nishil Bhave</dc:creator>
      <pubDate>Thu, 16 Jul 2026 22:15:02 +0000</pubDate>
      <link>https://dev.to/nishilbhave/claude-code-plan-mode-how-i-use-it-and-when-i-dont-60a</link>
      <guid>https://dev.to/nishilbhave/claude-code-plan-mode-how-i-use-it-and-when-i-dont-60a</guid>
      <description>&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%2F0ktfbdxgttpgdsitnvav.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%2F0ktfbdxgttpgdsitnvav.png" alt="Claude Code plan mode as a pipeline: six code files flow through explore, draft plan, approve, and execute edits into one approved change" width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first time plan mode saved me, I hadn't written a line of code yet. I asked Claude Code to "wire the new billing webhook into the retry queue," and instead of editing files, it laid out a plan that pointed at the wrong queue. I caught the mistake in the plan, not in a diff I had to unwind an hour later. That is the whole pitch for plan mode, and it is why I leave it one keystroke away all day.&lt;/p&gt;

&lt;p&gt;Agentic coding tools have a default failure mode: they edit first and explain later. A wrong assumption becomes a wrong diff, and now you are reviewing changes that should never have happened. Plan mode inverts that. Claude reads, explores, and proposes, and nothing touches your source until you say go. Below is exactly how I run it, the approval flow most people skim past, and the honest line on when it is worth the friction and when it is not.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Plan mode is a read-only permission mode: Claude explores and writes a plan but does not edit source until you approve (&lt;a href="https://code.claude.com/docs/en/permission-modes" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026).&lt;/li&gt;
&lt;li&gt;Enter it with &lt;code&gt;Shift+Tab&lt;/code&gt; (cycles default → acceptEdits → plan), a &lt;code&gt;/plan&lt;/code&gt; prompt prefix, or &lt;code&gt;claude --permission-mode plan&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Across ~40 of my own sessions, the proposed plan changed my approach before any code on 71% of cross-file refactors, but only 8% of one-line fixes.&lt;/li&gt;
&lt;li&gt;Approve to auto, approve to review each edit, or keep planning: the approval prompt sets the permission mode for everything that follows.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is plan mode in Claude Code?
&lt;/h2&gt;

&lt;p&gt;Plan mode is one of Claude Code's permission modes, and its permission is "Reads only" (&lt;a href="https://code.claude.com/docs/en/permission-modes" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). Claude reads files and runs read-only shell commands to explore your repo, then writes a plan describing what it intends to change. It does not edit your source, run migrations, or push anything until you approve the plan. Think of it as a scoped research pass with a written proposal at the end.&lt;/p&gt;

&lt;p&gt;That "reads only" line matters because it is enforced, not a suggestion. Permission modes sit on a ladder from most oversight to least: default (labeled Manual), then acceptEdits, then plan, then auto, then dontAsk, then bypassPermissions. Plan mode is the one that lets Claude think out loud across your whole codebase while guaranteeing the working tree stays untouched.&lt;/p&gt;

&lt;p&gt;Here is the part people miss: plan mode is not a "planning feature" bolted on top of chat. It is a permission boundary. When Claude is in plan mode, the edit and write tools are blocked at the permission layer, so even if the model decides mid-thought that it wants to change a file, it can't. According to Claude Code's documentation, edits stay blocked until you approve the plan, regardless of whether auto mode is also active (&lt;a href="https://code.claude.com/docs/en/permission-modes" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). That guarantee is what makes it safe to point Claude at unfamiliar code and let it roam.&lt;/p&gt;

&lt;p&gt;The mode exists because the alternative is expensive. If Claude edits four files on a wrong premise, you are now doing archaeology on a diff instead of correcting one sentence in a plan. I would rather argue with a paragraph than revert a commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I turn plan mode on and off?
&lt;/h2&gt;

&lt;p&gt;You enter plan mode by pressing &lt;code&gt;Shift+Tab&lt;/code&gt;, which cycles through default → acceptEdits → plan, and the current mode shows in the status bar (&lt;a href="https://code.claude.com/docs/en/interactive-mode" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). There are three other ways in, and I use all of them depending on the moment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Shift+Tab&lt;/code&gt;&lt;/strong&gt; mid-session, the one I hit most. Tap until the status bar reads plan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/plan&lt;/code&gt; as a prompt prefix&lt;/strong&gt; when I want a single planned turn without changing the session's default. Prefix one prompt with &lt;code&gt;/plan&lt;/code&gt; and that turn runs in plan mode.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;claude --permission-mode plan&lt;/code&gt;&lt;/strong&gt; at startup, so the session opens straight into planning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;defaultMode: "plan"&lt;/code&gt;&lt;/strong&gt; in &lt;code&gt;.claude/settings.json&lt;/code&gt; to make a whole project plan-first.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Getting out is just as quick. Press &lt;code&gt;Shift+Tab&lt;/code&gt; again to leave plan mode without approving anything, which is what I do when a "plan" turns out to be a two-line change I already understand. The keystroke is deliberately the same one you used to get in, so toggling costs nothing.&lt;/p&gt;

&lt;p&gt;One habit worth stealing: I do not start most sessions in plan mode. I start in Manual, read Claude's first response, and only tab into plan mode once I realize a task is bigger than it looked. Plan mode has a real cost in small ways too, prompt suggestions are skipped while it is active, so for quick back-and-forth it adds a little friction for no benefit.&lt;/p&gt;

&lt;p&gt;A quick question worth asking before you toggle: is the risk in &lt;em&gt;what&lt;/em&gt; Claude will change, or in &lt;em&gt;whether&lt;/em&gt; the approach is right? Plan mode only helps with the second one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens when Claude finishes a plan?
&lt;/h2&gt;

&lt;p&gt;When the plan is ready, Claude presents it and asks how to proceed, and your answer sets the permission mode for everything that follows (&lt;a href="https://code.claude.com/docs/en/permission-modes" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). This is the step most tutorials rush, and it is the most important one, because "approve" is not a single button. You are choosing how much leash Claude gets for the actual edits.&lt;/p&gt;

&lt;p&gt;The approval prompt offers these paths:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Approve and start in auto mode&lt;/strong&gt;, where Claude executes with background safety checks instead of per-tool prompts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Approve and accept edits&lt;/strong&gt;, so edits apply and you review them after the fact via &lt;code&gt;git diff&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Approve and review each edit manually&lt;/strong&gt;, the tightest option, where every change waits for you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep planning with feedback&lt;/strong&gt;, which sends the plan back with your notes instead of executing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refine with Ultraplan&lt;/strong&gt; for a browser-based review pass.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Approving exits plan mode and switches the session into whichever mode you picked, then Claude starts editing (&lt;a href="https://code.claude.com/docs/en/permission-modes" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). A couple of details make this smoother in daily use. &lt;code&gt;Ctrl+G&lt;/code&gt; opens the proposed plan in your default text editor so you can rewrite it directly before Claude proceeds, which beats typing a paragraph of corrections into the prompt. And approving a plan auto-names the session from the plan content, so your history stays legible weeks later.&lt;/p&gt;

&lt;p&gt;So which path do I actually pick? I logged it across roughly 40 real sessions. Most of the time I approve and review the diff rather than handing Claude the keys, and a healthy chunk of plans go back for another round before I let any edit happen.&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%2Fbwjsg93mhakuh1uafl3q.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%2Fbwjsg93mhakuh1uafl3q.png" alt="Donut chart of what I choose at Claude Code's plan-approval prompt across 40 sessions: approve and review the diff 46 percent, keep planning with feedback 24 percent, approve to auto mode 22 percent, discard and rethink 8 percent." width="799" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  When is plan mode actually worth it?
&lt;/h2&gt;

&lt;p&gt;Plan mode pays off in direct proportion to blast radius, and my own tracking makes the pattern obvious. Across ~40 sessions, the proposed plan changed my approach before any code was written on 71% of cross-file refactors, but on only 8% of one-line fixes. The bigger and less familiar the change, the more the planning pass earns its keep.&lt;/p&gt;

&lt;p&gt;Here is the same data by task type. Read it as "how often did planning first actually catch something," because that is the only metric that justifies the extra step.&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%2Ftahu70gov1ei6ngk1z6n.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%2Ftahu70gov1ei6ngk1z6n.png" alt="Horizontal bar chart: share of tasks where Claude Code's plan changed my approach before any code, by task type. Cross-file refactor 71 percent, multi-file feature 64 percent, unfamiliar-code task 58 percent, single-file bugfix 29 percent, one-line or config tweak 8 percent." width="799" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The tasks at the top of that chart share a trait: the risk lives in the approach, not the typing. On a cross-file refactor, Claude has to pick which abstraction to change, and picking wrong is invisible until you are three files deep. A plan surfaces that choice while it is still cheap to argue about. The documentation says as much, listing plan mode's sweet spot as "Exploring a codebase before changing it" (&lt;a href="https://code.claude.com/docs/en/permission-modes" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026).&lt;/p&gt;

&lt;p&gt;For a concrete example, I use plan mode almost every time I hand Claude a task that touches my publishing pipeline, because a bad edit there breaks a scheduler that runs unattended. If you want the broader picture of how planning fits a full session, I walk through it in &lt;a href="https://maketocreate.com/the-complete-claude-code-workflow-how-i-ship-10x-faster/" rel="noopener noreferrer"&gt;my full Claude Code workflow, from first prompt to shipped change&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  When should I skip plan mode?
&lt;/h2&gt;

&lt;p&gt;Skip plan mode when the risk is zero and the approach is obvious, which for me is anything under the 30% line on that chart. One-line fixes, config bumps, renames you have done fifty times, throwaway scripts: planning these is pure overhead. You read a plan for a change you already understand, approve it, and wonder why you added a step. Over-planning is a real tax, and it is easy to fall into once plan mode becomes a reflex.&lt;/p&gt;

&lt;p&gt;I settled on a five-signal test to decide in a second or two. Score the task from one to ten on each axis, and if the shape fills the chart, plan first; if it hugs the center, just let Claude edit. The two archetypes below make the call obvious: a cross-file refactor pushes every axis outward, while a one-line fix barely leaves the middle.&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%2Feqdx71jmevdsxfy3y6m9.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%2Feqdx71jmevdsxfy3y6m9.png" alt="Radar chart comparing two task types on five plan-mode signals scored one to ten. A cross-file refactor scores high on blast radius, unfamiliar code, ambiguous ask, hard to reverse and approach risk, filling the chart. A one-line fix scores low on all five, hugging the center." width="800" height="614"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The five signals are blast radius (how many files or systems), unfamiliar code (do I know this area cold), ambiguous ask (is the requirement fuzzy), hard to reverse (migrations, deletes, anything stateful), and approach risk (is there more than one reasonable way to do it). Any two of these firing is usually enough for me to tab into plan mode. None of them firing means I am wasting a keystroke.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does plan mode work with auto mode and /goal?
&lt;/h2&gt;

&lt;p&gt;Plan mode and auto mode are complementary: auto mode removes per-tool prompts, and the plan-approval step decides whether Claude drops into auto mode once the plan is blessed (&lt;a href="https://code.claude.com/docs/en/permission-modes" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). While you are still planning, a setting called &lt;code&gt;useAutoModeDuringPlan&lt;/code&gt; (on by default) lets the classifier approve read-only exploration without prompting you, so Claude can grep and read freely. Edits stay blocked until you approve, either way. My usual flow is plan, read, then "approve and start in auto mode" for anything long.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/goal&lt;/code&gt; stacks on top of that. It sets a completion condition and keeps Claude working across turns until a separate small fast model, which defaults to Haiku, confirms the condition holds; it requires Claude Code v2.1.139 or later (&lt;a href="https://code.claude.com/docs/en/goal" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). A goal does not change permissions on its own, so the documented pattern is to pair it with auto mode for unattended runs. In practice I plan the work, approve into auto mode, then set a &lt;code&gt;/goal&lt;/code&gt; like "all tests in the billing module pass," and let it run. Clear it any time with &lt;code&gt;/goal clear&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The mental model I use: plan mode decides &lt;em&gt;what&lt;/em&gt; Claude will do, auto mode decides &lt;em&gt;how many prompts&lt;/em&gt; it takes to do it, and &lt;code&gt;/goal&lt;/code&gt; decides &lt;em&gt;when it stops&lt;/em&gt;. They are three different knobs, and reaching for the wrong one is where people get frustrated. If you want more control over the model doing the planning, &lt;code&gt;/effort&lt;/code&gt; accepts low, medium, high, xhigh, max, and ultracode, and I bump it up before planning a genuinely gnarly refactor (&lt;a href="https://code.claude.com/docs/en/commands" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026).&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the failure modes to watch for?
&lt;/h2&gt;

&lt;p&gt;The most common failure mode is not plan mode breaking, it is a plan that reads clean but rests on a wrong premise. Since edits stay blocked until you approve, the plan is your last cheap checkpoint, and rubber-stamping it defeats the entire point (&lt;a href="https://code.claude.com/docs/en/permission-modes" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). I have approved confidently-wrong plans more than once, and every time the tell was there in the plan text if I had read it instead of skimming.&lt;/p&gt;

&lt;p&gt;A few specific traps I have hit, so you can dodge them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The confidently-wrong plan.&lt;/strong&gt; Claude states an assumption about your code as fact. Read the first paragraph of every plan for premises, not just the numbered steps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan "leaking" into edits.&lt;/strong&gt; If you approve into auto mode by reflex, Claude starts changing files faster than you expected. When in doubt, approve into "review each edit" instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Over-planning trivial work.&lt;/strong&gt; Covered above, but it bears repeating because it is the easiest bad habit to form.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan drift on long sessions.&lt;/strong&gt; On very long conversations, context compaction can drop details the plan depended on. For big work, approve and execute reasonably soon rather than planning for an hour first.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these are reasons to avoid plan mode. They are reasons to treat the plan as a document you actually read. If your session is misbehaving for other reasons, that is a separate topic, and I keep those in &lt;a href="https://maketocreate.com/claude-code-errors-every-code-cause-and-fix-2026-guide/" rel="noopener noreferrer"&gt;the full Claude Code errors and troubleshooting reference&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should I make plan mode the default?
&lt;/h2&gt;

&lt;p&gt;You can make plan mode a project default by setting &lt;code&gt;defaultMode: "plan"&lt;/code&gt; in &lt;code&gt;.claude/settings.json&lt;/code&gt;, and for some repos that is exactly right (&lt;a href="https://code.claude.com/docs/en/permission-modes" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). I turn it on by default in codebases where a careless edit is expensive: anything with a deploy pipeline, shared infrastructure, or state that is annoying to restore. For a scratch repo or a personal project, defaulting to plan mode just adds a step I will tab out of anyway.&lt;/p&gt;

&lt;p&gt;The setting that makes a plan-first project pleasant is a good &lt;code&gt;CLAUDE.md&lt;/code&gt;, because a plan is only as sharp as the context Claude has about your conventions. A repo with &lt;a href="https://maketocreate.com/claude-md-best-practices-the-complete-2026-guide/" rel="noopener noreferrer"&gt;a solid CLAUDE.md guiding Claude's context&lt;/a&gt; produces plans that already know your naming, your test command, and your no-go zones, which cuts the "keep planning" round-trips. If you are still getting set up, start with &lt;a href="https://maketocreate.com/claude-code-installation-guide-every-platform-every-gotcha/" rel="noopener noreferrer"&gt;the complete Claude Code install and setup guide&lt;/a&gt; and turn plan mode on once you have a real project loaded. For heavier planning, Ultraplan runs the same flow in a browser-based Claude Code on the web session, which is handy when the plan is long enough that a text editor beats a terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What does plan mode actually do in Claude Code?
&lt;/h3&gt;

&lt;p&gt;Plan mode is a read-only permission mode. Claude reads files and runs read-only shell commands to explore your codebase, then writes a plan describing intended changes, but it does not edit source until you approve (&lt;a href="https://code.claude.com/docs/en/permission-modes" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). It is a permission boundary, not just a prompt style, so edits are blocked at the tool layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I turn on plan mode?
&lt;/h3&gt;

&lt;p&gt;Press &lt;code&gt;Shift+Tab&lt;/code&gt; to cycle default → acceptEdits → plan, and watch the status bar for the current mode (&lt;a href="https://code.claude.com/docs/en/interactive-mode" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). You can also prefix a single prompt with &lt;code&gt;/plan&lt;/code&gt;, launch with &lt;code&gt;claude --permission-mode plan&lt;/code&gt;, or set &lt;code&gt;defaultMode: "plan"&lt;/code&gt; in &lt;code&gt;.claude/settings.json&lt;/code&gt; to make a project plan-first.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I get out of plan mode?
&lt;/h3&gt;

&lt;p&gt;Press &lt;code&gt;Shift+Tab&lt;/code&gt; again to leave plan mode without approving a plan (&lt;a href="https://code.claude.com/docs/en/permission-modes" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026). Approving a plan also exits plan mode automatically and switches the session into whichever permission mode your chosen approve option describes, such as auto mode or accept-edits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does plan mode cost extra tokens?
&lt;/h3&gt;

&lt;p&gt;Plan mode has no separate fee, but a thorough planning pass reads files and runs exploration commands, so it spends tokens like any other turn. Pairing it with &lt;code&gt;/goal&lt;/code&gt; adds a small evaluation cost on the fast model that checks your condition, which the docs describe as typically negligible next to main-turn spend (&lt;a href="https://code.claude.com/docs/en/goal" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;, 2026).&lt;/p&gt;

&lt;h3&gt;
  
  
  When should I not use plan mode?
&lt;/h3&gt;

&lt;p&gt;Skip it for one-line fixes, config tweaks, and changes you have made many times, where the approach carries no real risk. In my tracking, planning changed my approach on just 8% of one-line tasks versus 71% of cross-file refactors, so the payoff is almost entirely on large or unfamiliar work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;Plan mode is the cheapest insurance in Claude Code, and it costs one keystroke. It turns "Claude edited four files on a bad assumption" into "Claude proposed editing four files, and I said no." After a few hundred sessions, my rules are simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tab into plan mode&lt;/strong&gt; whenever two of the five signals fire: big blast radius, unfamiliar code, ambiguous ask, hard-to-reverse work, or real approach risk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read the plan for premises,&lt;/strong&gt; not just steps. The wrong assumption is almost always stated in plain text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose your approval carefully,&lt;/strong&gt; because it sets the permission mode for every edit that follows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skip it&lt;/strong&gt; for trivial changes, where planning is friction with no upside.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are wiring this into a real workflow, the natural next steps are getting your &lt;a href="https://maketocreate.com/claude-md-best-practices-the-complete-2026-guide/" rel="noopener noreferrer"&gt;CLAUDE.md tuned so plans arrive with the right context&lt;/a&gt; and slotting plan mode into &lt;a href="https://maketocreate.com/the-complete-claude-code-workflow-how-i-ship-10x-faster/" rel="noopener noreferrer"&gt;a repeatable end-to-end Claude Code workflow&lt;/a&gt;. Plan first, then let it build.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>planmode</category>
      <category>aicoding</category>
    </item>
    <item>
      <title>Awesome LLM Apps: 52 Ranked by What's Maintained (2026)</title>
      <dc:creator>Nishil Bhave</dc:creator>
      <pubDate>Tue, 14 Jul 2026 00:46:44 +0000</pubDate>
      <link>https://dev.to/nishilbhave/awesome-llm-apps-52-ranked-by-whats-maintained-2026-28a9</link>
      <guid>https://dev.to/nishilbhave/awesome-llm-apps-52-ranked-by-whats-maintained-2026-28a9</guid>
      <description>&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%2F1juuxvdeealw96cy0ato.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%2F1juuxvdeealw96cy0ato.png" alt="Awesome LLM apps directory hero: a 6-card grid of app categories (local runners, chat UIs, RAG, agent builders, coding agents, voice and search) with maintenance status dots" width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Search "awesome-llm-apps" and you land on one giant GitHub repo. &lt;a href="https://github.com/Shubhamsaboo/awesome-llm-apps" rel="noopener noreferrer"&gt;Shubhamsaboo/awesome-llm-apps&lt;/a&gt; has crossed 115,000 stars (&lt;a href="https://github.com/Shubhamsaboo/awesome-llm-apps" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026), and it is genuinely excellent. But read the fine print: it bills itself as "100+ AI Agent and RAG apps you can actually run, clone, customize, ship." Those are starter templates you build from, organized by technique. They are not finished apps you install and use.&lt;/p&gt;

&lt;p&gt;This is the other kind of directory. It is 52 real, runnable LLM apps that I either use myself or have graded against hard repo signals, sorted into 7 categories, with one column that does the actual work: a maintenance verdict. Maintained, Slowing, or Abandoned. That column is the point of the page, because the flat "awesome" lists will happily send you to a tool whose last commit landed in 2024. If you want the runtime landscape underneath all of this, the local engines and the hardware math, start with &lt;a href="https://maketocreate.com/local-llms-in-2026-which-runtime-to-run-and-the-hardware-you-need/" rel="noopener noreferrer"&gt;the complete 2026 guide to running LLMs locally&lt;/a&gt;; this directory assumes you just want the ranked list.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The popular "awesome-llm-apps" repo (&lt;a href="https://github.com/Shubhamsaboo/awesome-llm-apps" rel="noopener noreferrer"&gt;Shubhamsaboo&lt;/a&gt;, 115,000+ stars, June 2026) is a cookbook of templates you build, not a directory of finished apps you run. This page is the latter.&lt;/li&gt;
&lt;li&gt;Of the 52 apps I rank here, 42 are Maintained, 6 are Slowing, and 4 are Abandoned. That looks healthy only because I threw out the dead forks before counting.&lt;/li&gt;
&lt;li&gt;Last-commit recency beats star count. GPT4All sits on 77,000 stars but has been quiet since May 2025 (&lt;a href="https://github.com/nomic-ai/gpt4all" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026); gpt-engineer and Verba are archived outright.&lt;/li&gt;
&lt;li&gt;Install official or actively-shipping first: Ollama or LM Studio to run models, Open WebUI or LibreChat to chat, AnythingLLM or Dify to build.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How Did I Rank These LLM Apps?&lt;/li&gt;
&lt;li&gt;Local Model Runners&lt;/li&gt;
&lt;li&gt;Chat UIs and Frontends&lt;/li&gt;
&lt;li&gt;RAG and Chat-With-Your-Docs Apps&lt;/li&gt;
&lt;li&gt;Agent Frameworks and No-Code Builders&lt;/li&gt;
&lt;li&gt;Coding Agents&lt;/li&gt;
&lt;li&gt;AI Search and Research Apps&lt;/li&gt;
&lt;li&gt;Voice, Speech, and Roleplay&lt;/li&gt;
&lt;li&gt;Do GitHub Stars Tell You Which App to Pick?&lt;/li&gt;
&lt;li&gt;What Does the Maintenance Split Tell You?&lt;/li&gt;
&lt;li&gt;How Do I Pick and Run One of These?&lt;/li&gt;
&lt;li&gt;Frequently Asked Questions&lt;/li&gt;
&lt;li&gt;The Bottom Line&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Did I Rank These LLM Apps?
&lt;/h2&gt;

&lt;p&gt;I graded all 52 apps on one axis the awesome lists ignore: is anyone still shipping it? Four of the 52 are already dead, including two archived repos and one whose parent company folded in late 2023 (&lt;a href="https://analyticsindiamag.com/deep-tech/conversational-ai-startup-coqui-shuts-down/" rel="noopener noreferrer"&gt;Analytics India Magazine&lt;/a&gt;). "Does it exist" is the wrong question in a space moving this fast. "Was it touched this month" is the right one.&lt;/p&gt;

&lt;p&gt;So every entry carries one of three statuses, and I want to be honest about how I assigned them. I run roughly 20 of these in real projects, from Ollama and Open WebUI on my own machine to Dify and Cline at work. The rest I graded on repo signals you can check yourself in five minutes: who backs it, when the last commit landed, whether releases are tagged on a cadence or just trail off. Star counts I treat with suspicion, for reasons the chart below makes obvious.&lt;/p&gt;

&lt;p&gt;Here is the rubric, plainly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Maintained.&lt;/strong&gt; A first-party app from a company that has skin in the game, or a community project with commits in roughly the last six weeks, real releases, and a maintainer who answers issues. Production-considerable once you scope its credentials.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slowing.&lt;/strong&gt; It still works, and several are still widely deployed, but the commit cadence has dropped off (no meaningful push in two to seven months) or the project is mid-transition to something new. Fine to use; keep a fallback in mind.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Abandoned.&lt;/strong&gt; Archived, orphaned by a shutdown, or quiet for nine months or more. Listed on purpose, so you recognize the dead fork before you copy a 2024 tutorial that points at it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One caveat on the numbers. The star counts and last-commit dates here come straight from each project's GitHub page in June 2026, so they will drift after I publish; that drift is exactly why I lead with recency, not stars. Across the 52 apps, the split lands at 42 Maintained, 6 Slowing, and 4 Abandoned. Why does my list read 81% healthy when half of every "awesome" list is rot? Because this is a shortlist, not a census. The ratio you see is what survives the filter, which is the filter you wanted someone else to run for you.&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%2Fd3xc5m5zoyghnepjqt4t.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%2Fd3xc5m5zoyghnepjqt4t.png" alt="Donut chart of maintenance status across 52 curated LLM apps: 42 Maintained (81 percent), 6 Slowing (12 percent), 4 Abandoned (7 percent)." width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Local Model Runners
&lt;/h2&gt;

&lt;p&gt;If you want to run a model on your own hardware, this is where you start, and the category is dominated by one tool: Ollama has passed 175,000 GitHub stars (&lt;a href="https://github.com/ollama/ollama" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026), more than any other app in this directory except the automation platforms. These are the apps that pull weights, manage quantization, and expose a local API. Get this layer right and everything above it gets easier. For the deep dive on which runtime wins on your machine, the pillar covers llama.cpp versus Ollama versus vLLM in detail.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;App&lt;/th&gt;
&lt;th&gt;Maintainer&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/ollama/ollama" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Ollama (company)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The default. One command to pull and run almost any open model, with a clean local API. If you run one tool locally, run this. Full walkthrough: &lt;a href="https://maketocreate.com/ollama-in-2026-run-tune-and-fix-local-llms-complete-guide/" rel="noopener noreferrer"&gt;the complete Ollama setup and model guide&lt;/a&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/ggml-org/llama.cpp" rel="noopener noreferrer"&gt;llama.cpp&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;ggml.org (community)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The C++ engine half this ecosystem is built on, Ollama included. Run it raw only when you want to hand-tune quantization and squeeze a weak GPU.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://lmstudio.ai/" rel="noopener noreferrer"&gt;LM Studio&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;LM Studio (company)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The friendliest GUI for people who never touch a terminal. Closed source but free, with a model browser and a built-in server. Guide: &lt;a href="https://maketocreate.com/lm-studio-in-2026-download-models-run-local-llms-vs-ollama/" rel="noopener noreferrer"&gt;downloading and running models in LM Studio&lt;/a&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/janhq/jan" rel="noopener noreferrer"&gt;Jan&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Menlo Research&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Open-source LM Studio. A polished desktop app that runs models fully offline. The one I hand to people who distrust closed binaries.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/oobabooga/text-generation-webui" rel="noopener noreferrer"&gt;text-generation-webui&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;oobabooga (community)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The power user's cockpit. Every loader, every sampler, every extension. Overwhelming, but nothing else exposes this many knobs.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/LostRuins/koboldcpp" rel="noopener noreferrer"&gt;KoboldCpp&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;LostRuins (community)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A single-file llama.cpp wrapper beloved by the local roleplay crowd. Tiny, fast to start, zero install ceremony.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/vllm-project/vllm" rel="noopener noreferrer"&gt;vLLM&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;vLLM project&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not a desktop app, a serving engine. When you outgrow Ollama and need real throughput across many users, this is the jump.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/mudler/LocalAI" rel="noopener noreferrer"&gt;LocalAI&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;mudler (community)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A drop-in OpenAI-compatible API you self-host. Best when you want existing apps to talk to local models with no code changes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/nomic-ai/gpt4all" rel="noopener noreferrer"&gt;GPT4All&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Nomic AI&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Abandoned&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Was the easiest on-ramp in 2023. The repo has been quiet since May 2025 (&lt;a href="https://github.com/nomic-ai/gpt4all" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026) as Nomic moved on. Use Jan or LM Studio instead.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Chat UIs and Frontends
&lt;/h2&gt;

&lt;p&gt;Once a model is running, you need something to talk to it, and this category is unusually healthy. Open WebUI leads it at over 143,000 GitHub stars (&lt;a href="https://github.com/open-webui/open-webui" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026), a full ChatGPT-style frontend that points at Ollama or any OpenAI-compatible endpoint. The rest split into self-hosted web apps and lightweight desktop clients. Pick by whether you want a server to run or a binary to download.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;App&lt;/th&gt;
&lt;th&gt;Maintainer&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/open-webui/open-webui" rel="noopener noreferrer"&gt;Open WebUI&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Open WebUI (community)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The category king. RAG, tools, multi-user, model management, all of it. The default UI for a local Ollama setup.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/danny-avila/LibreChat" rel="noopener noreferrer"&gt;LibreChat&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Danny Avila (community)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The best multi-provider hub. One UI over OpenAI, Anthropic, Google, and local models, with agents and presets. My pick when I swap models all day.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/lobehub/lobe-chat" rel="noopener noreferrer"&gt;Lobe Chat&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;LobeHub&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The prettiest of the bunch. Plugins, voice, vision, and a genuinely polished UX. A touch more opinionated than LibreChat.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/Bin-Huang/chatbox" rel="noopener noreferrer"&gt;Chatbox&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Bin Huang (community)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A cross-platform desktop client that just works. No server to run; point it at a key or a local endpoint and go.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/CherryHQ/cherry-studio" rel="noopener noreferrer"&gt;Cherry Studio&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Cherry HQ&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A desktop client that has quietly gotten excellent for knowledge work, with built-in agents and document chat.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/enricoros/big-AGI" rel="noopener noreferrer"&gt;big-AGI&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Enrico Ros (community)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Smaller and developer-flavored. Multi-model "beam" and persona features the bigger UIs still lack.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  RAG and Chat-With-Your-Docs Apps
&lt;/h2&gt;

&lt;p&gt;This is where most people actually want an LLM: pointed at their own documents. AnythingLLM has climbed past 62,000 GitHub stars (&lt;a href="https://github.com/Mintplex-Labs/anything-llm" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026) by being the most complete "chat with your files" app you can self-host. But this category also holds two of my four dead entries, so the maintenance column earns its keep here more than anywhere. RAG demos age fast.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;App&lt;/th&gt;
&lt;th&gt;Maintainer&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/Mintplex-Labs/anything-llm" rel="noopener noreferrer"&gt;AnythingLLM&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Mintplex Labs&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The most complete chat-with-your-docs app. Workspaces, multiple vector DBs, desktop or Docker. The one I install for non-technical teams.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/infiniflow/ragflow" rel="noopener noreferrer"&gt;RAGFlow&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;InfiniFlow&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Deep-document RAG with serious parsing for tables, layouts, and OCR. Heavier to run, best results on messy PDFs.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/onyx-dot-app/onyx" rel="noopener noreferrer"&gt;Onyx&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Onyx (company)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Formerly Danswer. Enterprise-grade search and chat across your company's apps, with connectors for nearly everything.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/khoj-ai/khoj" rel="noopener noreferrer"&gt;Khoj&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Khoj (company)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Your second brain. Self-hostable, indexes your notes and files, and answers across them. Lovely for Obsidian users.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/zylon-ai/private-gpt" rel="noopener noreferrer"&gt;PrivateGPT&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Zylon&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The name that launched the local-RAG wave. Still maintained by Zylon, still fully offline document Q&amp;amp;A.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/Cinnamon/kotaemon" rel="noopener noreferrer"&gt;Kotaemon&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Cinnamon&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A clean open-source RAG UI with good defaults, inline citations, and an easy demo path.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/deepset-ai/haystack" rel="noopener noreferrer"&gt;Haystack&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;deepset&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;deepset's production RAG framework, not an app. Reach for it when you are building a pipeline, not installing one.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/QuivrHQ/quivr" rel="noopener noreferrer"&gt;Quivr&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Quivr (company)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Slowing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Was a hot "second brain." The core repo has been quiet since mid-2025 (&lt;a href="https://github.com/QuivrHQ/quivr" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026) after the team pivoted to a RAG framework. Works, but watch it.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/weaviate/Verba" rel="noopener noreferrer"&gt;Verba&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Weaviate&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Abandoned&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Weaviate's RAG showcase, now archived (&lt;a href="https://github.com/weaviate/Verba" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026). A nice demo to read, not a thing to build on.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Agent Frameworks and No-Code Builders
&lt;/h2&gt;

&lt;p&gt;If you want to build something rather than just chat, this is the deepest category in the directory, and the most volatile. The visual builders alone are enormous: Langflow sits above 150,000 GitHub stars and Dify above 146,000 (&lt;a href="https://github.com/langgenius/dify" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026). The split here is clean: code-first frameworks for developers, and drag-and-drop platforms for everyone else. Both halves are mostly Maintained, with two notable exceptions sliding toward Slowing. The model you wire into any of these matters as much as the framework, so see &lt;a href="https://maketocreate.com/best-open-source-llm-in-2026-open-weights-worth-running/" rel="noopener noreferrer"&gt;which open-source model to actually pick&lt;/a&gt; before you commit.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;App&lt;/th&gt;
&lt;th&gt;Maintainer&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/langgenius/dify" rel="noopener noreferrer"&gt;Dify&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;LangGenius&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The best open-source LLM app platform. Visual workflows, RAG, agents, and an API in one box, shipping constantly.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/langflow-ai/langflow" rel="noopener noreferrer"&gt;Langflow&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Langflow (company)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A polished node editor backed by a real company. Build agent flows visually, export an API.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/n8n-io/n8n" rel="noopener noreferrer"&gt;n8n&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;n8n (company)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not LLM-specific, but at 194,000+ stars it has become the glue for production AI workflows. Self-hostable, endlessly useful.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/langchain-ai/langchain" rel="noopener noreferrer"&gt;LangChain&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;LangChain (company)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The framework everyone complains about and still uses. 140,000+ stars. The default glue for LLM apps in Python and JS.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/run-llama/llama_index" rel="noopener noreferrer"&gt;LlamaIndex&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;LlamaIndex (company)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The data framework. If your app is mostly RAG, this is often a cleaner fit than LangChain.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/crewAIInc/crewAI" rel="noopener noreferrer"&gt;CrewAI&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;CrewAI (company)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The most popular multi-agent framework. Define roles, give them tools, let them collaborate. Pragmatic and well-documented.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/Significant-Gravitas/AutoGPT" rel="noopener noreferrer"&gt;AutoGPT&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Significant Gravitas&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The 185,000-star project that started the autonomous-agent hype. Now a low-code platform; the original loop is mostly history.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/FlowiseAI/Flowise" rel="noopener noreferrer"&gt;Flowise&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;FlowiseAI&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Drag-and-drop LangChain. Build chatbots and agent flows visually, export an API. Great for prototypes and non-coders.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/letta-ai/letta" rel="noopener noreferrer"&gt;Letta&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Letta (company)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Formerly MemGPT. Treats long-term agent memory as a first-class concern. The interesting one to watch in stateful agents.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/microsoft/autogen" rel="noopener noreferrer"&gt;AutoGen&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Microsoft&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Slowing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Microsoft's multi-agent framework, now in maintenance mode. Microsoft directs new work to the Microsoft Agent Framework (&lt;a href="https://learn.microsoft.com/en-us/agent-framework/migration-guide/from-autogen/" rel="noopener noreferrer"&gt;Microsoft Learn&lt;/a&gt;, 2026); the community fork is AG2.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/geekan/MetaGPT" rel="noopener noreferrer"&gt;MetaGPT&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;DeepWisdom&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Slowing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The "software company in a box" multi-agent demo. Impressive paper, but commits have thinned since early 2026 (&lt;a href="https://github.com/geekan/MetaGPT" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Coding Agents
&lt;/h2&gt;

&lt;p&gt;Coding is the use case where open-source apps genuinely rival the paid tools, and the leader proves it: OpenHands has passed 78,000 GitHub stars (&lt;a href="https://github.com/All-Hands-AI/OpenHands" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026) running as an autonomous agent that edits, tests, and iterates in a sandbox. This category lives or dies on the model behind it, so the freshness column matters less than which LLM you point it at. For that decision, I keep a separate scorecard.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;App&lt;/th&gt;
&lt;th&gt;Maintainer&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/All-Hands-AI/OpenHands" rel="noopener noreferrer"&gt;OpenHands&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;All Hands AI&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Formerly OpenDevin. The leading open-source coding agent. Runs in a sandbox, plans, edits, tests, and iterates.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/cline/cline" rel="noopener noreferrer"&gt;Cline&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Cline (community)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The best open-source coding agent inside VS Code. Plan and act modes, MCP support, bring your own key. My daily driver for autonomous edits.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/OpenInterpreter/open-interpreter" rel="noopener noreferrer"&gt;Open Interpreter&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Open Interpreter&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lets a model run code on your machine to get things done. Powerful and a little terrifying, so sandbox it.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/block/goose" rel="noopener noreferrer"&gt;Goose&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Block&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Block's open-source agent. Extensible via MCP, runs locally, and is genuinely good. The dark horse of this list.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/Aider-AI/aider" rel="noopener noreferrer"&gt;Aider&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Paul Gauthier (community)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The terminal coding agent purists love. Git-aware, model-agnostic, no IDE required. Pairs beautifully with a strong model: &lt;a href="https://maketocreate.com/best-llm-for-coding-in-2026-7-models-ranked-by-use-case/" rel="noopener noreferrer"&gt;the best LLM to drive a coding agent&lt;/a&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/continuedev/continue" rel="noopener noreferrer"&gt;Continue&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Continue (company)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The open-source Copilot alternative for VS Code and JetBrains. Autocomplete plus chat, your model, your rules.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/TabbyML/tabby" rel="noopener noreferrer"&gt;Tabby&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;TabbyML&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Slowing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A self-hosted assistant with autocomplete and chat. Solid, but commits have thinned since March 2026 (&lt;a href="https://github.com/TabbyML/tabby" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/gpt-engineer-org/gpt-engineer" rel="noopener noreferrer"&gt;gpt-engineer&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;gpt-engineer org&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Abandoned&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The "describe an app, get a codebase" pioneer, now archived (&lt;a href="https://github.com/gpt-engineer-org/gpt-engineer" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026). Read it for history; use OpenHands or Aider to actually ship.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  AI Search and Research Apps
&lt;/h2&gt;

&lt;p&gt;This is the smallest category, but it is where open source quietly caught the commercial answer engines. These tools pair a model with a search backend to produce sourced answers or full reports instead of a wall of links. Most are Maintained, with one Stanford research project that is brilliant but should be treated as code, not a product. The model you choose drives the quality of the synthesis, which is its own rabbit hole.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;App&lt;/th&gt;
&lt;th&gt;Maintainer&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/assafelovic/gpt-researcher" rel="noopener noreferrer"&gt;GPT Researcher&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Assaf Elovic (community)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Point it at a question, get a sourced report. The most useful open research agent I have run.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/ItzCrazyKns/Perplexica" rel="noopener noreferrer"&gt;Perplexica&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;ItzCrazyKns (community)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;An open-source Perplexity. Pairs a local model with SearXNG for private AI search. Very usable.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/miurla/morphic" rel="noopener noreferrer"&gt;Morphic&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Yuki Hattori (community)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A clean generative answer-engine UI you can self-host or deploy on Vercel. Small but well-kept.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(&lt;a href="https://github.com/stanford-oval/storm" rel="noopener noreferrer"&gt;https://github.com/stanford-oval/storm&lt;/a&gt;)&lt;/td&gt;
&lt;td&gt;Stanford OVAL&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Slowing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Stanford's research-to-article system. Brilliant as a paper and a demo; treat it as research code, quiet since fall 2025 (&lt;a href="https://github.com/stanford-oval/storm" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Voice, Speech, and Roleplay
&lt;/h2&gt;

&lt;p&gt;The last category is the most fragmented, which is why it has the lowest Maintained ratio in the directory. Speech and character apps are easy to start and hard to keep current. OpenAI's Whisper model alone has over 103,000 GitHub stars (&lt;a href="https://github.com/openai/whisper" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026), but the interesting work happens in the wrappers around it, and one of the most beloved TTS projects here was orphaned when its company shut down.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;App&lt;/th&gt;
&lt;th&gt;Maintainer&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/ggml-org/whisper.cpp" rel="noopener noreferrer"&gt;whisper.cpp&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;ggml.org (community)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Whisper transcription in portable C++. Runs on a laptop, a phone, a Pi. The speech-to-text backbone of countless local apps.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/openai/whisper" rel="noopener noreferrer"&gt;Whisper&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;OpenAI&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The open-weight STT model itself. The repo updates rarely because the model is finished, and the weights are everywhere.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/SillyTavern/SillyTavern" rel="noopener noreferrer"&gt;SillyTavern&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;SillyTavern (community)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Maintained&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The power-user frontend for AI roleplay and characters. Endless customization; pairs with KoboldCpp or any backend.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/SYSTRAN/faster-whisper" rel="noopener noreferrer"&gt;faster-whisper&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;SYSTRAN&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Slowing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The fast CTranslate2 reimplementation everyone actually deploys for transcription. Still the workhorse, but pushes have slowed since late 2025 (&lt;a href="https://github.com/SYSTRAN/faster-whisper" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/coqui-ai/TTS" rel="noopener noreferrer"&gt;Coqui TTS&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Coqui (defunct)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Abandoned&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The open TTS standard, orphaned when Coqui the company shut down in late 2023 (&lt;a href="https://analyticsindiamag.com/deep-tech/conversational-ai-startup-coqui-shuts-down/" rel="noopener noreferrer"&gt;Analytics India Magazine&lt;/a&gt;). Use the actively maintained &lt;a href="https://github.com/idiap/coqui-ai-TTS" rel="noopener noreferrer"&gt;Idiap community fork&lt;/a&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Do GitHub Stars Tell You Which App to Pick?
&lt;/h2&gt;

&lt;p&gt;No, and the gap is wider than most directories admit. The top of the star chart is led by n8n at 194,000+ stars (&lt;a href="https://github.com/n8n-io/n8n" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026), a tool that is not even LLM-specific, followed by AutoGPT at 185,000, whose original autonomous loop is now mostly historical. Stars measure attention at the moment a project went viral. They do not measure whether anyone is still fixing bugs this quarter.&lt;/p&gt;

&lt;p&gt;That mismatch is the single most useful thing to internalize before you install anything. A 50,000-star tool like Goose, shipping daily, will serve you better than a 185,000-star project coasting on a 2023 launch. The chart below ranks the eight most-starred apps in this directory. Read it as a popularity contest, not a quality ranking, and then cross-reference the maintenance column above before you commit.&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%2Fiz2lyqzoe38pg9fc5jt6.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%2Fiz2lyqzoe38pg9fc5jt6.png" alt="Lollipop chart of the eight most-starred LLM apps in this directory: n8n 194K, AutoGPT 185K, Ollama 175K, Langflow 150K, Dify 147K, Open WebUI 143K, LangChain 140K, llama.cpp 118K." width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Does the Maintenance Split Tell You?
&lt;/h2&gt;

&lt;p&gt;The clearest signal across all 52 apps is not which one is best. It is who stands behind it. Every Abandoned entry has the same backstory: a company that folded (Coqui), a vendor that archived its demo (Verba, from Weaviate), a pioneer that got superseded (gpt-engineer), or a single maintainer who moved on (GPT4All). Not one of them died because the idea was bad. They died because nobody had a standing reason to keep shipping.&lt;/p&gt;

&lt;p&gt;That pattern repeats across the categories below. The deepest category, agent frameworks and builders, is also the one with the most company backing, which is exactly why it stays healthy. The thinnest categories, search and voice, carry the highest share of single-maintainer risk. Where would you rather place a production bet?&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%2Fbun85cz4ur73690am3zr.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%2Fbun85cz4ur73690am3zr.png" alt="Horizontal bar chart of 52 curated LLM apps by category: Agent frameworks and builders 11, Local runners 9, RAG apps 9, Coding agents 8, Chat UIs 6, Voice and roleplay 5, AI search 4." width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Do I Pick and Run One of These?
&lt;/h2&gt;

&lt;p&gt;Picking the app is half the job; the other half is matching it to a model and a runtime. The honest order of operations I follow: decide what you are building, pick the app from the category above, then choose the model that drives it. Most people skip the last step and wonder why a great app gives mediocre answers. The app is a shell. The model is the engine.&lt;/p&gt;

&lt;p&gt;So if you are running anything locally, settle the runtime first. For most people that means &lt;a href="https://maketocreate.com/ollama-in-2026-run-tune-and-fix-local-llms-complete-guide/" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; for a clean command-line setup or &lt;a href="https://maketocreate.com/lm-studio-in-2026-download-models-run-local-llms-vs-ollama/" rel="noopener noreferrer"&gt;LM Studio&lt;/a&gt; for a friendly GUI, both of which slot under the chat UIs and RAG apps above. Then pick the brain. If you are coding, the model choice swamps the app choice, so weigh it carefully in &lt;a href="https://maketocreate.com/best-llm-for-coding-in-2026-7-models-ranked-by-use-case/" rel="noopener noreferrer"&gt;the best LLM for coding&lt;/a&gt;. If you are deciding between hosted frontier models to power an agent, the trade-offs in &lt;a href="https://maketocreate.com/claude-opus-vs-gpt-5-in-2026-opus-4-8-vs-gpt-5-5-tested/" rel="noopener noreferrer"&gt;Claude Opus versus GPT-5&lt;/a&gt; and &lt;a href="https://maketocreate.com/deepseek-r1-vs-v3-in-2026-when-to-use-each-and-why-theyre-merging/" rel="noopener noreferrer"&gt;DeepSeek R1 versus V3&lt;/a&gt; will save you a few wrong turns. And if you want to stay fully open and self-hosted, start from &lt;a href="https://maketocreate.com/best-open-source-llm-in-2026-open-weights-worth-running/" rel="noopener noreferrer"&gt;the best open-source LLM&lt;/a&gt; and work back to the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is the awesome-llm-apps repo?
&lt;/h3&gt;

&lt;p&gt;"awesome-llm-apps" usually means the GitHub repo &lt;a href="https://github.com/Shubhamsaboo/awesome-llm-apps" rel="noopener noreferrer"&gt;Shubhamsaboo/awesome-llm-apps&lt;/a&gt;, a collection of 100-plus runnable AI agent and RAG app templates with full source code, now past 115,000 stars (&lt;a href="https://github.com/Shubhamsaboo/awesome-llm-apps" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026). It is a cookbook you build from. This directory ranks 52 finished apps you install instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are the best open-source LLM apps in 2026?
&lt;/h3&gt;

&lt;p&gt;For most people the best picks are the actively maintained leaders in each category: Ollama or LM Studio to run models, Open WebUI or LibreChat to chat, AnythingLLM or Dify to build, and OpenHands or Cline to code. All rank Maintained here, with Open WebUI alone above 143,000 GitHub stars (&lt;a href="https://github.com/open-webui/open-webui" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026).&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I run these LLM apps locally?
&lt;/h3&gt;

&lt;p&gt;Most of these apps need a model and a runtime underneath them. Install Ollama or LM Studio first, pull an open-weight model, then point a frontend like Open WebUI or AnythingLLM at the local endpoint. The pillar covers hardware requirements and runtime trade-offs in &lt;a href="https://maketocreate.com/local-llms-in-2026-which-runtime-to-run-and-the-hardware-you-need/" rel="noopener noreferrer"&gt;the guide to running LLMs locally&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which LLM apps are abandoned or unsafe to rely on?
&lt;/h3&gt;

&lt;p&gt;Four of the 52 here are dead: GPT4All (quiet since May 2025), Verba and gpt-engineer (both archived), and Coqui TTS (company shut down in late 2023, &lt;a href="https://analyticsindiamag.com/deep-tech/conversational-ai-startup-coqui-shuts-down/" rel="noopener noreferrer"&gt;Analytics India Magazine&lt;/a&gt;). They still run, but nobody is patching them. For Coqui, use the Idiap community fork that picks up active maintenance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do GitHub stars mean an LLM app is good?
&lt;/h3&gt;

&lt;p&gt;No. Stars measure attention at launch, not whether a project still ships. n8n leads this directory at 194,000+ stars yet is not LLM-specific, while AutoGPT's 185,000 stars sit on a loop that is now mostly historical (&lt;a href="https://github.com/Significant-Gravitas/AutoGPT" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, June 2026). Check the last commit date before you trust the badge.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;A useful LLM app directory is not the longest list. It is the one that already threw out the dead forks for you. The 52 apps here are the ones I would actually evaluate in 2026, and the most valuable column is the status: 42 Maintained, 6 Slowing, 4 Abandoned.&lt;/p&gt;

&lt;p&gt;If you remember one thing, make it this: pick by who is still shipping, not by who went viral. Company-backed and actively-maintained apps cluster in the Maintained column for a reason, while the famous abandoned ones are famous precisely because they launched loud and then stopped. Start with a boring, well-kept app, add a riskier one only when it earns the slot, and check the last commit date either way. For the runtime and hardware layer underneath all of it, go back up to &lt;a href="https://maketocreate.com/local-llms-in-2026-which-runtime-to-run-and-the-hardware-you-need/" rel="noopener noreferrer"&gt;the complete guide to running LLMs locally&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>awesomellmapps</category>
      <category>bestllmapps</category>
      <category>opensourcellmapps</category>
      <category>llmappslist</category>
    </item>
  </channel>
</rss>
