<?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: Igor Kramar</title>
    <description>The latest articles on DEV Community by Igor Kramar (@ikramar).</description>
    <link>https://dev.to/ikramar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2211561%2F11d1ba7b-e52e-4488-bc50-cbb19848e004.jpg</url>
      <title>DEV Community: Igor Kramar</title>
      <link>https://dev.to/ikramar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ikramar"/>
    <language>en</language>
    <item>
      <title>I wrapped Claude Code in a zsh function. Here's every decision I almost got wrong.</title>
      <dc:creator>Igor Kramar</dc:creator>
      <pubDate>Mon, 25 May 2026 14:05:46 +0000</pubDate>
      <link>https://dev.to/ikramar/i-wrapped-claude-code-in-a-zsh-function-heres-every-decision-i-almost-got-wrong-2ofc</link>
      <guid>https://dev.to/ikramar/i-wrapped-claude-code-in-a-zsh-function-heres-every-decision-i-almost-got-wrong-2ofc</guid>
      <description>&lt;p&gt;Claude Code's &lt;code&gt;--help&lt;/code&gt; lists 50+ flags. After two weeks of using it daily, I built a zsh wrapper called &lt;code&gt;cco&lt;/code&gt; that bakes in the flags I actually want. The wrapper itself is 60 lines. The interesting part is the decisions behind those 60 lines — most of them I had to backtrack on at least once.&lt;/p&gt;

&lt;p&gt;This is the decision log. If you're using Claude Code seriously, some of these will save you the same backtracks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision 1: Function, not alias, not shell script
&lt;/h2&gt;

&lt;p&gt;The dumb instinct is &lt;code&gt;alias cc="claude --permission-mode acceptEdits --append-system-prompt ..."&lt;/code&gt;. It works until you want subcommands. &lt;code&gt;cco plan&lt;/code&gt;, &lt;code&gt;cco safe&lt;/code&gt;, &lt;code&gt;cco review&lt;/code&gt; — aliases can't branch on arguments.&lt;/p&gt;

&lt;p&gt;Standalone shell script in &lt;code&gt;~/.local/bin/cc&lt;/code&gt; was the next thought. It works for most cases, but spawns a subshell. That's fine for stateless commands. It's not fine when the command wraps an interactive process that wants the parent terminal's tty for tmux attachment and prompt rendering. Worked in testing, behaved weird in edge cases.&lt;/p&gt;

&lt;p&gt;A zsh function runs in the current shell. Inherits the tty cleanly. Can dispatch on subcommands. Can be tab-completed via &lt;code&gt;compdef&lt;/code&gt;. That's what I went with.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost&lt;/strong&gt;: lives in your &lt;code&gt;.zshrc&lt;/code&gt; (or a sourced module file). Not portable to bash users without rewriting. I'm fine with that — I'm not shipping this to other people.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision 2: &lt;code&gt;cc&lt;/code&gt; vs &lt;code&gt;cco&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I picked &lt;code&gt;cc&lt;/code&gt; first. Two letters, mnemonic for "Claude Code". I almost committed it.&lt;/p&gt;

&lt;p&gt;Then I checked my aliases file. &lt;code&gt;cl&lt;/code&gt; was already taken by &lt;code&gt;cargo clippy --all-targets&lt;/code&gt;. Fine, I wasn't using &lt;code&gt;cl&lt;/code&gt; anyway. But that made me look at &lt;code&gt;cc&lt;/code&gt; more carefully.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cc&lt;/code&gt; on macOS is a symlink to the C compiler at &lt;code&gt;/usr/bin/cc&lt;/code&gt;. I have &lt;code&gt;/opt/homebrew/opt/llvm/bin&lt;/code&gt; ahead in &lt;code&gt;$PATH&lt;/code&gt;, so &lt;code&gt;which cc&lt;/code&gt; resolves to system clang. A zsh function would shadow it — functions take precedence over &lt;code&gt;$PATH&lt;/code&gt; lookups in interactive shells.&lt;/p&gt;

&lt;p&gt;The argument for shadowing it anyway: I never type &lt;code&gt;cc&lt;/code&gt; directly to invoke a compiler. Cargo, CMake, Make — they all call it programmatically.&lt;/p&gt;

&lt;p&gt;The counter-argument: programmatic calls happen via &lt;code&gt;execvp&lt;/code&gt;, which doesn't see shell functions. &lt;strong&gt;But&lt;/strong&gt; — Rust's &lt;code&gt;cc&lt;/code&gt; crate (used by &lt;code&gt;openssl-sys&lt;/code&gt;, &lt;code&gt;ring&lt;/code&gt;, &lt;code&gt;zstd-sys&lt;/code&gt;, and a thousand other dependencies) sometimes invokes &lt;code&gt;cc&lt;/code&gt; through shell wrappers in build scripts. The probability of hitting this is low. The debugging cost when it does happen — staring at a &lt;code&gt;ring&lt;/code&gt; build failure that makes no sense — is high.&lt;/p&gt;

&lt;p&gt;Renamed to &lt;code&gt;cco&lt;/code&gt;. Three keystrokes instead of two. Worth it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson&lt;/strong&gt;: before claiming a short command name, grep your aliases file and run &lt;code&gt;type &amp;lt;name&amp;gt;&lt;/code&gt;. Two minutes of due diligence beats an hour of "why won't this crate build."&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision 3: System prompt lives in a separate file
&lt;/h2&gt;

&lt;p&gt;Claude Code accepts &lt;code&gt;--append-system-prompt "string"&lt;/code&gt;. Tempting to inline it in the function. Don't.&lt;/p&gt;

&lt;p&gt;System prompts grow. Mine started as three lines (anti-sycophancy, confidence marking, counterargument-first) and is now closer to thirty. Editing thirty lines inside a shell function is painful — escaping, line continuation, no syntax highlighting for the content.&lt;/p&gt;

&lt;p&gt;I put mine in &lt;code&gt;~/.config/claude/system-prompt.md&lt;/code&gt;. The function reads it at invocation:&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;local &lt;/span&gt;&lt;span class="nv"&gt;sys_prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/.config/claude/system-prompt.md"&lt;/span&gt;
&lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$sys_prompt&lt;/span&gt;&lt;span class="s2"&gt;"&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="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"✗ System prompt not found: &lt;/span&gt;&lt;span class="nv"&gt;$sys_prompt&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;return &lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;prompt_content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&amp;lt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$sys_prompt&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="c"&gt;# ... later ...&lt;/span&gt;
claude &lt;span class="nt"&gt;--append-system-prompt&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$prompt_content&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Edit in your real editor.&lt;/strong&gt; Markdown syntax highlighting. Spell check. Git diff when you tweak it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separate from code.&lt;/strong&gt; Different lifecycle. I commit my zsh modules to a public dotfiles repo. My system prompt I might not — it contains opinions I haven't published yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reload without sourcing.&lt;/strong&gt; Edit the file, next &lt;code&gt;cco&lt;/code&gt; invocation picks up the change. No &lt;code&gt;source ~/.zshrc&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The trade-off: one more file dependency. If the file is missing, the function bails out with an error. Acceptable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision 4: Subcommands instead of flags
&lt;/h2&gt;

&lt;p&gt;The function dispatches on the first argument:&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="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$sub&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in
  &lt;/span&gt;plan&lt;span class="p"&gt;)&lt;/span&gt;   ...  &lt;span class="c"&gt;# read-only analysis&lt;/span&gt;
  safe&lt;span class="o"&gt;)&lt;/span&gt;   ...  &lt;span class="c"&gt;# dontAsk + tight whitelist&lt;/span&gt;
  review&lt;span class="o"&gt;)&lt;/span&gt; ...  &lt;span class="c"&gt;# ultrareview&lt;/span&gt;
  resume&lt;span class="o"&gt;)&lt;/span&gt; ...  &lt;span class="c"&gt;# session picker&lt;/span&gt;
  here&lt;span class="o"&gt;)&lt;/span&gt;   ...  &lt;span class="c"&gt;# current branch, no worktree&lt;/span&gt;
  run|&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  ...  &lt;span class="c"&gt;# default: worktree + tmux + acceptEdits&lt;/span&gt;
&lt;span class="k"&gt;esac&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I considered &lt;code&gt;cco --plan&lt;/code&gt;, &lt;code&gt;cco --safe&lt;/code&gt;, etc. Two reasons against:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Flag parsing collides with Claude's flags.&lt;/strong&gt; &lt;code&gt;cco --plan&lt;/code&gt; could mean "wrapper's plan mode" or "pass &lt;code&gt;--plan&lt;/code&gt; to claude" (which doesn't exist, but the parsing logic gets ambiguous fast).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subcommands compose better with tab completion.&lt;/strong&gt; &lt;code&gt;cco &amp;lt;Tab&amp;gt;&lt;/code&gt; shows the menu. &lt;code&gt;cco --&amp;lt;Tab&amp;gt;&lt;/code&gt; would dump every claude flag.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The default case is &lt;code&gt;run|*&lt;/code&gt; — bare &lt;code&gt;cco&lt;/code&gt; or &lt;code&gt;cco "some prompt"&lt;/code&gt; both work. The &lt;code&gt;run&lt;/code&gt; keyword exists mostly so tab completion has something to show in the menu for the default.&lt;/p&gt;

&lt;p&gt;There's one edge case I left in: &lt;code&gt;cco "plan my vacation"&lt;/code&gt; would match the &lt;code&gt;plan)&lt;/code&gt; branch because the first word is &lt;code&gt;plan&lt;/code&gt;. If anyone ever hits this — &lt;code&gt;cco run "plan my vacation"&lt;/code&gt; is the workaround. I judged the collision rare enough to not care.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision 5: &lt;code&gt;--tmux&lt;/code&gt; in default mode
&lt;/h2&gt;

&lt;p&gt;This one I want to be honest about: I almost left tmux out, because I assumed nobody would want yet another tmux session per Claude invocation.&lt;/p&gt;

&lt;p&gt;I asked myself point-blank: do you live in tmux? Yes. Default stays tmux-on.&lt;/p&gt;

&lt;p&gt;If you don't live in tmux, the value proposition collapses. &lt;code&gt;--tmux&lt;/code&gt; only matters if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You want to detach the session and reattach later from another shell.&lt;/li&gt;
&lt;li&gt;You want multiple Claude tasks running in parallel, switchable from one terminal.&lt;/li&gt;
&lt;li&gt;You SSH into your dev machine sometimes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If none of those apply, &lt;code&gt;--tmux&lt;/code&gt; just leaks tmux sessions. After a week of work you'll have 40 zombie sessions in &lt;code&gt;tmux ls&lt;/code&gt;. Skip it.&lt;/p&gt;

&lt;p&gt;I added a cleanup alias just in case:&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;alias &lt;/span&gt;cco-cleanup&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'tmux ls 2&amp;gt;/dev/null | grep "^cco-" | cut -d: -f1 | xargs -I{} tmux kill-session -t {}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Decision 6: Worktree by default, "here" mode as escape hatch
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;--worktree&lt;/code&gt; creates a separate git worktree per invocation. Claude works on a parallel branch in a parallel directory. Your main checkout is untouched.&lt;/p&gt;

&lt;p&gt;The upside is real, especially on probation at a new job: Claude can refactor aggressively, and if it goes sideways, I just &lt;code&gt;git worktree remove&lt;/code&gt; and nothing happened. No &lt;code&gt;git stash&lt;/code&gt;, no "wait what state was I in", no panic.&lt;/p&gt;

&lt;p&gt;The downside: sometimes you don't want isolation. You're mid-task, files open in VSCode, mental model loaded. You want Claude to fix one bug &lt;em&gt;here&lt;/em&gt;, not in a parallel reality.&lt;/p&gt;

&lt;p&gt;So I added a &lt;code&gt;here&lt;/code&gt; subcommand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;here&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;shift
  local &lt;/span&gt;&lt;span class="nv"&gt;branch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git symbolic-ref &lt;span class="nt"&gt;--short&lt;/span&gt; HEAD 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'detached'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"📍 here mode — current branch (&lt;/span&gt;&lt;span class="nv"&gt;$branch&lt;/span&gt;&lt;span class="s2"&gt;), no worktree"&lt;/span&gt;
  claude &lt;span class="nt"&gt;--permission-mode&lt;/span&gt; acceptEdits &lt;span class="se"&gt;\&lt;/span&gt;
         &lt;span class="nt"&gt;--append-system-prompt&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$prompt_content&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
         &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same system prompt, same &lt;code&gt;acceptEdits&lt;/code&gt;, same logging. But no worktree, no tmux. Drop in, do the thing, drop out.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;cco&lt;/code&gt; for "go change the auth-store architecture." Use &lt;code&gt;cco here&lt;/code&gt; for "fix the null check on line 42."&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision 7: &lt;code&gt;caffeinate -is&lt;/code&gt; wrapping the default mode
&lt;/h2&gt;

&lt;p&gt;macOS clamshell sleep ruins long-running agent tasks. Close the lid, fetch tea, come back — the task has been paused since you walked away.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;caffeinate -is&lt;/code&gt; keeps the system awake (&lt;code&gt;-s&lt;/code&gt;) and prevents idle sleep (&lt;code&gt;-i&lt;/code&gt;) for the duration of the wrapped process. When Claude exits, &lt;code&gt;caffeinate&lt;/code&gt; releases its assertion. No leaked state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;caffeinate &lt;span class="nt"&gt;-is&lt;/span&gt; claude &lt;span class="nt"&gt;--worktree&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$wt_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--tmux&lt;/span&gt; ... &lt;span class="s2"&gt;"&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;&lt;strong&gt;Honest limitation&lt;/strong&gt;: &lt;code&gt;caffeinate -s&lt;/code&gt; only works while on AC power. Apple's SMC enforces clamshell sleep on battery regardless of what userland says. There's no way around it without third-party kexts I would never install.&lt;/p&gt;

&lt;p&gt;So: lid closed + AC + (external display OR keyboard) → works via standard clamshell mode. Lid closed + battery → sleeps no matter what. I tell people up front, because the alternative is them thinking the wrapper is broken.&lt;/p&gt;

&lt;p&gt;I only added &lt;code&gt;caffeinate&lt;/code&gt; to the default mode, not to &lt;code&gt;plan&lt;/code&gt;, &lt;code&gt;here&lt;/code&gt;, &lt;code&gt;safe&lt;/code&gt;, or &lt;code&gt;review&lt;/code&gt;. Reasoning: the other modes are short-lived. Default mode (worktree + long refactor) is where caffeination earns its keep.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision 8: Tee everything, except interactive pickers
&lt;/h2&gt;

&lt;p&gt;Each invocation logs to &lt;code&gt;~/claude-logs/&amp;lt;timestamp&amp;gt;_&amp;lt;projectname&amp;gt;.log&lt;/code&gt; via &lt;code&gt;tee&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;claude ... &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$log_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives me a searchable history without relying on Claude's internal session storage. When something goes wrong three days later — "wait, what did Claude say about the auth refactor on Tuesday" — I &lt;code&gt;rg&lt;/code&gt; the logs.&lt;/p&gt;

&lt;p&gt;Exception: &lt;code&gt;cco resume&lt;/code&gt; uses Claude's interactive session picker. Piping that through &lt;code&gt;tee&lt;/code&gt; breaks the picker's TUI rendering. No log for &lt;code&gt;resume&lt;/code&gt;. I considered fixing it with &lt;code&gt;script(1)&lt;/code&gt; but that's a yak shave for a feature I'd use rarely.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd do differently
&lt;/h2&gt;

&lt;p&gt;If I were starting over:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pick the name first, by elimination, not by aspiration.&lt;/strong&gt; I lost 15 minutes flip-flopping between &lt;code&gt;cc&lt;/code&gt;, &lt;code&gt;cl&lt;/code&gt;, and &lt;code&gt;cco&lt;/code&gt;. Running &lt;code&gt;type &amp;lt;candidate&amp;gt;&lt;/code&gt; against four options up front would have settled it immediately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write the system prompt before the wrapper.&lt;/strong&gt; The wrapper is plumbing. The system prompt is the actual leverage — that's where you tell Claude how to think. I built the wrapper first because it was the fun part. Wrong order.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't add features speculatively.&lt;/strong&gt; I almost added a &lt;code&gt;--wide&lt;/code&gt; flag for &lt;code&gt;--add-dir&lt;/code&gt; to pull in shared types and notes directories. I cut it before writing it. Six months in, I still don't need it. Good cut.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The wrapper
&lt;/h2&gt;

&lt;p&gt;Full code: &lt;a href="https://gist.github.com/IgorKramar/9b4c698909047934ee8e5dd775e94ebc" rel="noopener noreferrer"&gt;gist.github.com/IgorKramar/9b4c698909047934ee8e5dd775e94ebc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you build something similar, you'll make different decisions. Some of mine were context-specific (probation at a new job → worktree isolation matters more), some are tooling-specific (tmux user → &lt;code&gt;--tmux&lt;/code&gt; default). The point isn't to copy the code. The point is: when your wrapper hits 60 lines, every line should be a deliberate choice, not a default someone else's tutorial gave you.&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>zsh</category>
      <category>cli</category>
    </item>
    <item>
      <title>Mechanistic Interpretability is a 2026 Breakthrough Technology. Here's What That Means for the "LLMs Are Just Matrix Multiplication" Debate</title>
      <dc:creator>Igor Kramar</dc:creator>
      <pubDate>Sun, 10 May 2026 04:37:08 +0000</pubDate>
      <link>https://dev.to/ikramar/mechanistic-interpretability-is-a-2026-breakthrough-technology-heres-what-that-means-for-the-16jp</link>
      <guid>https://dev.to/ikramar/mechanistic-interpretability-is-a-2026-breakthrough-technology-heres-what-that-means-for-the-16jp</guid>
      <description>&lt;p&gt;Today a friend of mine — let's leave him nameless — said the line I've been hearing since 2022: &lt;em&gt;"It's still just matrices multiplying, guessing the most probable next word."&lt;/em&gt; For a long while I had no good rebuttal beyond intuition.&lt;/p&gt;

&lt;p&gt;I've been using LLMs as a daily tool since the original ChatGPT shipped in November 2022. I've gone through the lot — GPT-3.5, GPT-4, every Claude, Gemini, DeepSeek, Qwen, Mistral, the local Gemma stack on LM Studio. I write Claude plugins, build automation pipelines, run agents in production. I'm a frontend developer by trade, but AI tooling has become roughly half of what I do these days.&lt;/p&gt;

&lt;p&gt;So when someone tells me LLMs are just statistics, four years of practitioner intuition tell me something doesn't add up. But intuition is a rather poor argument. I went looking for what the research actually says in 2026. This piece is what I found.&lt;/p&gt;

&lt;p&gt;The short version: the "just matrix multiplication" framing was reasonable in 2021. In 2026, it isn't. There's a parallel story about cognitive offloading and what happens to the &lt;em&gt;user's&lt;/em&gt; mind when leaning on these tools — and there the sceptics are largely right. Both stories matter, and they're often muddled together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where "Stochastic Parrots" Came From
&lt;/h2&gt;

&lt;p&gt;The phrase comes from Bender, Gebru, McMillan-Major and Shmitchell's 2021 paper, &lt;em&gt;On the Dangers of Stochastic Parrots: Can Language Models Be Too Big?&lt;/em&gt; It's worth reading in full — foundational work, and the critique it raises about bias, environmental cost, and hype hasn't aged a day.&lt;/p&gt;

&lt;p&gt;The technical claim was narrower than how it's usually quoted. The authors argued that language models, as understood at the time, were stitching together linguistic forms from training data without any underlying model of meaning or the world the language refers to. Given what was visible from outside in 2021 — GPT-3 had only just shipped, interpretability tooling was primitive — this was a fair description.&lt;/p&gt;

&lt;p&gt;The phrase then became a kind of shibboleth. People who wanted to deflate AI hype would invoke "stochastic parrots" as shorthand. People who wanted to push back called the framing reductive. Both camps mostly stopped reading the paper itself and started using the phrase as a flag.&lt;/p&gt;

&lt;p&gt;What's changed since 2021 isn't whether the original critique was correct. What's changed is that we now have direct empirical access to what's happening &lt;em&gt;inside&lt;/em&gt; these models. And what's inside doesn't square with the "no world model, just surface statistics" picture.&lt;/p&gt;

&lt;h2&gt;
  
  
  The First Crack: Othello-GPT (2022)
&lt;/h2&gt;

&lt;p&gt;Kenneth Li and colleagues at Harvard published &lt;em&gt;Emergent World Representations: Exploring a Sequence Model Trained on a Synthetic Task&lt;/em&gt; (&lt;a href="https://arxiv.org/abs/2210.13382" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2210.13382&lt;/a&gt;). They trained a small GPT-style transformer on a single task: given a sequence of Othello moves, predict the next legal move. The model was given no rules, no board, no description of the game whatsoever. Just sequences.&lt;/p&gt;

&lt;p&gt;After training, the model played legal moves with high accuracy. The researchers then probed its internal activations and found a representation of the current board state — not in the input, not in the output, but constructed inside the model's residual stream. They confirmed this causally: by editing the internal representation of a single square, they could change the model's predicted next move in exactly the way you'd expect if it were "looking at" a modified board.&lt;/p&gt;

&lt;p&gt;Neel Nanda extended the work in 2023 (&lt;a href="https://arxiv.org/abs/2309.00941" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2309.00941&lt;/a&gt;), showing the board representation was actually linear — recoverable with simple probes and editable with vector arithmetic. Adam Karvonen reproduced the result on real chess games in 2024 (&lt;a href="https://arxiv.org/abs/2403.15498" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2403.15498&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;This isn't surface statistics. A pure n-gram model trained on Othello move sequences would develop conditional probabilities over move tokens, full stop. That a transformer trained on the same data builds a &lt;em&gt;board&lt;/em&gt; internally, and uses it causally, is a hard empirical fact about what next-token prediction can produce as a side effect of optimisation pressure.&lt;/p&gt;

&lt;p&gt;A small model on a toy domain, granted. But it's a proof of concept: "predict the next token" is a sufficient training signal for representations of the underlying generative process to emerge as a by-product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scaling Up: Anthropic's Interpretability Work (2024–2026)
&lt;/h2&gt;

&lt;p&gt;Anthropic ran the same playbook on a production model. &lt;em&gt;Scaling Monosemanticity: Extracting Interpretable Features from Claude 3 Sonnet&lt;/em&gt; (&lt;a href="https://transformer-circuits.pub/2024/scaling-monosemanticity/" rel="noopener noreferrer"&gt;https://transformer-circuits.pub/2024/scaling-monosemanticity/&lt;/a&gt;) used sparse autoencoders to extract millions of interpretable features from a real production model. The features were abstract, multilingual, multimodal — concepts like "Golden Gate Bridge," "code with security vulnerabilities," "sycophantic praise," each represented as an identifiable direction in the model's activation space.&lt;/p&gt;

&lt;p&gt;The follow-up papers in 2025 went further. &lt;em&gt;Circuit Tracing: Revealing Computational Graphs in Language Models&lt;/em&gt; and &lt;em&gt;On the Biology of a Large Language Model&lt;/em&gt; (&lt;a href="https://transformer-circuits.pub/2025/attribution-graphs/biology.html" rel="noopener noreferrer"&gt;https://transformer-circuits.pub/2025/attribution-graphs/biology.html&lt;/a&gt;) didn't just identify features — the team traced how features connect into circuits performing computation across layers. The findings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When the model writes a poem with a rhyme scheme, it picks the rhyming target word &lt;em&gt;before&lt;/em&gt; generating the line, then plans backward to that target. That's planning, not left-to-right generation.&lt;/li&gt;
&lt;li&gt;Asked "what's the capital of the state Dallas is in," the model first activates a Texas representation as an intermediate step, then retrieves Austin from there. Multi-hop reasoning through internal state, not direct lookup.&lt;/li&gt;
&lt;li&gt;In medical scenarios, the model forms an internal candidate diagnosis that influences its follow-up questions, even when the diagnosis is never stated aloud.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In January 2026, MIT Technology Review named mechanistic interpretability one of its 10 Breakthrough Technologies of the year (&lt;a href="https://www.technologyreview.com/2026/01/12/1130003/mechanistic-interpretability-ai-research-models-2026-breakthrough-technologies/" rel="noopener noreferrer"&gt;https://www.technologyreview.com/2026/01/12/1130003/mechanistic-interpretability-ai-research-models-2026-breakthrough-technologies/&lt;/a&gt;). That isn't an Anthropic press release — it's the field reaching the point where working tools for looking inside have actually arrived.&lt;/p&gt;

&lt;p&gt;And critically, those tools are open. Anthropic released the &lt;code&gt;circuit-tracer&lt;/code&gt; library, which works on open-weight models like Gemma-2-2b and Llama-3.2-1b. The Neuronpedia community platform (&lt;a href="https://www.neuronpedia.org" rel="noopener noreferrer"&gt;https://www.neuronpedia.org&lt;/a&gt;) hosts features and circuits for open models you can browse by hand. You needn't take anyone's word for it — run it yourself and have a look. Subhadip Mitra's January 2026 write-up (&lt;a href="https://subhadipmitra.com/blog/2026/circuit-tracing-production/" rel="noopener noreferrer"&gt;https://subhadipmitra.com/blog/2026/circuit-tracing-production/&lt;/a&gt;) frames this as interpretability shifting from "interesting research direction" to "practical engineering discipline."&lt;/p&gt;

&lt;p&gt;If you want to see this for yourself, the interactive notebooks at &lt;a href="https://transformer-circuits.pub" rel="noopener noreferrer"&gt;https://transformer-circuits.pub&lt;/a&gt; and Neuronpedia are the obvious starting points. Pick a feature, see what activates it, try to break the explanation. The most efficient cure for "it's just matrices" I know.&lt;/p&gt;

&lt;h2&gt;
  
  
  So Is the "Just Prediction" Argument Dead?
&lt;/h2&gt;

&lt;p&gt;Not quite. Intellectual honesty matters here, and I'd be writing a worse piece if I pretended the sceptic camp had nothing left.&lt;/p&gt;

&lt;p&gt;Schaeffer, Miranda, and Koyejo's &lt;em&gt;Are Emergent Abilities of Large Language Models a Mirage?&lt;/em&gt; (&lt;a href="https://arxiv.org/abs/2304.15004" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2304.15004&lt;/a&gt;) showed that some claimed "emergent" capabilities are partly artefacts of metric choice — swap a hard accuracy threshold for a smooth metric and the discontinuous jump disappears. The original Wei et al. emergence paper still holds for some capabilities, but the picture is more nuanced than "abilities suddenly appear at scale."&lt;/p&gt;

&lt;p&gt;Chain-of-thought rationales aren't always faithful to the actual computation that produced an answer. Models hallucinate. They have no online learning, no persistent memory between sessions outside of explicit memory systems. Much of Bender et al.'s critique about bias and hype landed hard and remains there.&lt;/p&gt;

&lt;p&gt;What's gone is the strong version: "LLMs only learn surface statistics, no internal model of the generating process exists." That claim is empirically falsified — by Othello-GPT, by Anthropic's circuits work, by Karvonen's chess results, by the linear spatial representations Tehenan et al. (&lt;a href="https://arxiv.org/abs/2506.02996" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2506.02996&lt;/a&gt;) found in LLM activations.&lt;/p&gt;

&lt;p&gt;The interesting questions have moved on. They're now about &lt;em&gt;which&lt;/em&gt; aspects of the world models are accurate, &lt;em&gt;when&lt;/em&gt; models reason faithfully versus rationalise, &lt;em&gt;how&lt;/em&gt; to use interpretability tools to debug failures. "Are they really thinking?" was the 2021 question. It isn't the 2026 question.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Other Side: Cognitive Offloading is Real
&lt;/h2&gt;

&lt;p&gt;Here the sceptics are mostly right, and we AI enthusiasts — myself included — have to be honest about it.&lt;/p&gt;

&lt;p&gt;Lee et al. at Microsoft Research and Carnegie Mellon (CHI 2025, &lt;a href="https://www.microsoft.com/en-us/research/publication/the-impact-of-generative-ai-on-critical-thinking-self-reported-reductions-in-cognitive-effort-and-confidence-effects-from-a-survey-of-knowledge-workers/" rel="noopener noreferrer"&gt;https://www.microsoft.com/en-us/research/publication/the-impact-of-generative-ai-on-critical-thinking-self-reported-reductions-in-cognitive-effort-and-confidence-effects-from-a-survey-of-knowledge-workers/&lt;/a&gt;) surveyed 319 knowledge workers using GenAI weekly, with 936 first-hand task examples. Higher confidence in the AI was associated with less critical thinking. Higher confidence in &lt;em&gt;one's own&lt;/em&gt; expertise was associated with more. The mechanism is cognitive offloading: when you trust the tool, you stop checking, and over time you stop developing the skill that would let you check in the first place.&lt;/p&gt;

&lt;p&gt;Gerlich (2025, &lt;em&gt;Societies&lt;/em&gt;, &lt;a href="https://www.mdpi.com/2075-4698/15/1/6" rel="noopener noreferrer"&gt;https://www.mdpi.com/2075-4698/15/1/6&lt;/a&gt;) found the same pattern in a separate 666-participant study. Lodge and Loble at the University of Technology Sydney published a March 2026 review of cognitive offloading in education (&lt;a href="https://www.uts.edu.au/news/2026/03/experts-warn-unstructured-ai-use-in-schools-risks-cognitive-atrophy" rel="noopener noreferrer"&gt;https://www.uts.edu.au/news/2026/03/experts-warn-unstructured-ai-use-in-schools-risks-cognitive-atrophy&lt;/a&gt;), warning that unstructured AI use in schools risks cognitive atrophy.&lt;/p&gt;

&lt;p&gt;But — and the story gets rather more interesting here — there's a strong counter-observation from a recent BCG study.&lt;/p&gt;

&lt;p&gt;Randazzo, Lifshitz, Kellogg, Dell'Acqua, Mollick, Candelon and Lakhani — &lt;em&gt;Cyborgs, Centaurs and Self-Automators: The Three Modes of Human-GenAI Knowledge Work&lt;/em&gt; (HBS Working Paper 26-036, December 2025, &lt;a href="https://ssrn.com/abstract=4921696" rel="noopener noreferrer"&gt;https://ssrn.com/abstract=4921696&lt;/a&gt;). 244 BCG consultants tracked through a seven-stage strategic problem-solving workflow. Three empirically distinct modes of AI use emerged:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cyborgs (~60%)&lt;/strong&gt; weave their work deeply with the AI across the entire workflow. Iterative dialogue, AI personas, using it to shape both the problem and the solution. They develop new AI-related capabilities — what the authors call &lt;em&gt;newskilling&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Centaurs (14%)&lt;/strong&gt; maintain a clear division of labour: humans decide what to do and how, AI is used selectively for specific support tasks. This group produced the &lt;em&gt;highest accuracy&lt;/em&gt; in business recommendations, outperforming both other modes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-Automators&lt;/strong&gt; (the remainder) copy data into AI, tweak slightly, paste it back. No skill gains at all. This is the offloading-into-atrophy pattern in its pure form.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the data immediately tells you that "using AI" is too coarse a category. Cyborgs and centaurs both grow, just along different trajectories. Self-automators lose out.&lt;/p&gt;

&lt;p&gt;There's a classic counter-effect in cognitive load theory that complements this: Sweller's worked example effect (1985, replicated dozens of times). For novices in a domain, studying a worked-out solution is often &lt;em&gt;more&lt;/em&gt; effective than struggling through problem-solving from scratch — because reduced cognitive load frees working memory for schema acquisition. When I watch Claude work through an architectural problem in a domain I'm new to, then attempt a similar problem myself, I'm running the worked-example pattern. That's the opposite of offloading.&lt;/p&gt;

&lt;p&gt;The difference between the two patterns comes down to one thing: whether you alternate observation with active retrieval. Watching Claude solve and nodding along is offloading. Watching, predicting the next step, attempting a variant yourself, comparing — that's learning.&lt;/p&gt;

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

&lt;p&gt;Yesterday I was setting up internet at my dacha. Weak LTE, antenna pointing the wrong way, no obvious solution. I sent Claude the coordinates of my plot and the base station, plus a photo of the antenna location with a compass and a timestamp visible in the EXIF.&lt;/p&gt;

&lt;p&gt;Claude calculated the bearing from the two coordinates using the haversine formula and got 226°. Then it noticed something: the EXIF timestamp said 17:03, and at that hour in early May in Omsk, the sun should be at roughly 225–230° azimuth. The compass in the photo confirmed the direction matched. All three checks lined up.&lt;/p&gt;

&lt;p&gt;There's no magic in this. It's three small inferential steps glued together: a geographic calculation, a known fact about solar position, a visual cross-check. I could have done each step myself, in three different tools, in twenty minutes, with a calculator and a sun-position website. Claude did it in one prompt as a coherent answer.&lt;/p&gt;

&lt;p&gt;That's the concrete shape of what these tools are good at right now. Not "thinking" in any mystical sense. Integration of small inferential steps across domains, fast enough that the overhead of doing it yourself stops being worth paying. And it's exactly where the offloading risk lives — because the next time I have a similar problem, I shan't reach for the calculator. I'll reach for Claude.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means for Practitioners
&lt;/h2&gt;

&lt;p&gt;If you write code with LLM assistance every day, the "just matrices" framing isn't useful for thinking about what you're working with. It isn't wrong at the hardware level — it's simply not at the right level of description for the questions that actually matter to you. Your CPU is "just transistors switching," and that fact doesn't help you reason about your application either.&lt;/p&gt;

&lt;p&gt;The framings that actually predict behaviour in 2026:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LLMs build internal representations of the structures generating their training data. Those representations can be accurate, partial, or distorted, and you can sometimes inspect them with interpretability tools.&lt;/li&gt;
&lt;li&gt;Their reasoning is partial, sometimes parallel, often faithful but not always. Treat chain-of-thought as evidence, not proof.&lt;/li&gt;
&lt;li&gt;Cognitive offloading is real and measurable. The tools grow you when you contest their outputs and shrink you when you trust them.&lt;/li&gt;
&lt;li&gt;The question "use AI or don't" is the wrong one. The right question is which of the BCG modes you operate in, and whether you're choosing it consciously.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to dig deeper, three concrete starting points: read &lt;em&gt;On the Biology of a Large Language Model&lt;/em&gt; end to end (it's HTML with interactive diagrams). Spend an hour on Neuronpedia trying to break the feature explanations. Read the Lee et al. Microsoft paper, then watch yourself for a week and notice when you skip the verification step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;The 2021 debate about whether LLMs were "really thinking" was good for its time. The 2026 debate is about which patterns of human-AI interaction grow human capability and which atrophy it. The first debate had no decent empirical handles. The second one does, and they point in fairly clear directions.&lt;/p&gt;

&lt;p&gt;When someone tells you "it's still just matrices," send them this article — or better, send them to Neuronpedia and ask them to explain what they're looking at. The conversation usually shifts from there.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>interpretability</category>
      <category>discuss</category>
    </item>
    <item>
      <title>I built a Claude Code plugin that argues with me about architecture. Then it caught me lying to it.</title>
      <dc:creator>Igor Kramar</dc:creator>
      <pubDate>Fri, 08 May 2026 20:29:24 +0000</pubDate>
      <link>https://dev.to/ikramar/i-built-a-claude-code-plugin-that-argues-with-me-about-architecture-then-it-caught-me-lying-to-it-3ne8</link>
      <guid>https://dev.to/ikramar/i-built-a-claude-code-plugin-that-argues-with-me-about-architecture-then-it-caught-me-lying-to-it-3ne8</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR.&lt;/strong&gt; I built a Claude Code plugin (MIT, &lt;a href="https://github.com/IgorKramar/archforge-marketplace" rel="noopener noreferrer"&gt;github.com/IgorKramar/archforge-marketplace&lt;/a&gt;) that turns Claude into a senior architect. After running one deep cycle on a real architectural decision, you get back: a multi-page ADR with explicit architectural rules, two or three honest alternatives with trade-offs, and a five-role adversarial roast. On one of my own ADRs the roast found a confused-deputy attack vector at the LLM-tool boundary that I'd missed — flagged independently by both the security role and the compliance role. The plugin then failed to follow its own language rules in a specific, instructive way. This article is what I learned, including how the failure led to the most useful feature I added.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I've been using Claude as a daily collaborator for about a year. For most things — code, writing, debugging — it's excellent. But I noticed a specific failure mode in architectural conversations. I'd say "I'm thinking of using Postgres for this." Claude would say "Great choice, here's why Postgres works." I'd say "Actually, let me reconsider, maybe SQLite." Claude would say "Excellent, SQLite is perfect for this case, here's why." Both answers couldn't be right. They couldn't even both be useful.&lt;/p&gt;

&lt;p&gt;Architecture is one of the few engineering activities where &lt;strong&gt;disagreement is the work&lt;/strong&gt;. You need someone who refuses to let you skip ahead. Someone who insists on alternatives. Someone who points at the downside you don't want to hear. Default LLM tuning is the opposite of that.&lt;/p&gt;

&lt;p&gt;So I built a plugin. It's MIT-licensed, the repo is at the end. This article is what I learned building it and putting it through a real architectural cycle on a real project — including the part where the plugin caught itself failing, and how that led to the most interesting feature in the whole thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a cycle, not a template
&lt;/h2&gt;

&lt;p&gt;Most AI-architecture tooling I'd seen was templates. "Here's an ADR template. Fill it in." But ADRs are the artifact, not the work. A good ADR is the residue of a process that included three things you can't fake by filling in a template:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Discovery&lt;/strong&gt; — making constraints, forces, and prior art explicit before you allow yourself to think about solutions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real alternatives&lt;/strong&gt; — not "the option I want" plus a strawman, but two or three genuine options each with honest trade-offs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Push-back&lt;/strong&gt; — someone willing to argue, especially when your first instinct is to skip ahead.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So I structured the plugin around a six-phase cycle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. DISCOVER  → constraints, forces, prior art, requirements
2. RESEARCH  → current information from the web (versions, prices, regulation)
3. DESIGN    → 2–3 alternatives, each with trade-offs
4. DECIDE    → pick one, state why, state when it breaks
5. DOCUMENT  → ADR + update ARCHITECTURE.md + diagrams
6. REVIEW    → architectural review when code lands
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each phase is a slash command (&lt;code&gt;/archforge:discover&lt;/code&gt;, &lt;code&gt;:research&lt;/code&gt;, etc.). There's &lt;code&gt;/archforge:cycle "&amp;lt;problem&amp;gt;"&lt;/code&gt; that walks the whole thing with user gates between phases. The phases enforce &lt;strong&gt;discipline&lt;/strong&gt;. You can't propose solutions in &lt;code&gt;discover&lt;/code&gt;. You can't introduce new alternatives in &lt;code&gt;decide&lt;/code&gt;. You can't write an ADR until you've actually decided. The structure forces the conversation to slow down where it matters.&lt;/p&gt;

&lt;p&gt;The router skill — the one that activates whenever the user mentions architecture or design — has a section that turned out to matter more than anything else:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;### Hold position. Argue. Don't soft-cave.&lt;/span&gt;

If the user proposes something you consider weak, say so directly and argue.
Do not collapse at the first pushback. Soft pushback that folds is a form of
disrespect — the user came for honest critique, not validation.
Maintain the position until presented with a real counter-argument.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That paragraph carried more weight in practice than I expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Want to try it before reading the story?
&lt;/h2&gt;

&lt;p&gt;Skip ahead if you want to know what it does first. But if you'd rather see for yourself:&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;# In Claude Code:&lt;/span&gt;
/plugin marketplace add https://github.com/IgorKramar/archforge-marketplace
/plugin &lt;span class="nb"&gt;install &lt;/span&gt;archforge@archforge-marketplace

&lt;span class="c"&gt;# In any project (preferably one with an open architectural question):&lt;/span&gt;
/archforge:init
/archforge:cycle &lt;span class="s2"&gt;"should I extract this module into its own service?"&lt;/span&gt; &lt;span class="nt"&gt;--scale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;light
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;light&lt;/code&gt;-scale cycle takes about 10 minutes, walks you through Discover → Design → Decide → Document with pauses for your input, and produces a short ADR with two alternatives and explicit reasoning. If you find the result useful, run a &lt;code&gt;--scale=deep&lt;/code&gt; cycle on a real decision next.&lt;/p&gt;

&lt;p&gt;The rest of this article is the story of what the cycle produced when I ran it on a hard problem in my own project, and what failed when I did.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the plugin actually contains
&lt;/h2&gt;

&lt;p&gt;Three layers of components, but the structure isn't the interesting part — what each layer does is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skills&lt;/strong&gt; — knowledge and disposition. Ten of them. A router skill that sets the architect persona. Specialists for ADR writing, system design, frontend architecture, backend architecture, AI agents architecture, code review, web research, an integration skill for &lt;a href="https://github.com/EveryInc/compound-engineering-plugin" rel="noopener noreferrer"&gt;Compound Engineering&lt;/a&gt;, an architectural-diagrams skill (C4, sequence, state, ER, deployment — all Mermaid). Skills are markdown files Claude pulls in when their description matches the current task.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Slash commands&lt;/strong&gt; — 17 of them in v0.4. The cycle phases. Plus shortcuts (&lt;code&gt;/archforge:adr&lt;/code&gt;), plus tooling (&lt;code&gt;/archforge:map&lt;/code&gt; for a decision dependency graph, &lt;code&gt;/archforge:observe&lt;/code&gt; for finding architectural decisions made implicitly in code, &lt;code&gt;/archforge:upgrade&lt;/code&gt; for migrating projects between plugin versions, &lt;code&gt;/archforge:diagram&lt;/code&gt; for any of the five diagram types).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sub-agents&lt;/strong&gt; — nine. Three for long-running tasks (&lt;code&gt;architect&lt;/code&gt;, &lt;code&gt;reviewer&lt;/code&gt;, &lt;code&gt;researcher&lt;/code&gt;). Five for adversarial review — but I'll get to those, because they're where the story turns. And one for catching the plugin failing itself. That last one is the entire point of this article.&lt;/p&gt;

&lt;p&gt;Plus soft-warning hooks that nudge you when you've changed many files without an ADR, when a new top-level directory appears, when many modules have been touched without architectural observation. Reminders, not gates.&lt;/p&gt;

&lt;h2&gt;
  
  
  The case study: an AI agent for a regulated market
&lt;/h2&gt;

&lt;p&gt;I'm building a SaaS product — call it "the project" for this article — an AI-driven landing page builder targeting small businesses in a regulated jurisdiction where strict data residency requirements rule out US-hosted LLM providers. Florists, barbers, coffee shops. The differentiation is that an AI agent walks the user from "I want a website" to "the website is published and I can see analytics" without the user having to know design, code, or AI prompting.&lt;/p&gt;

&lt;p&gt;The first architectural decision was the AI agent layer. This is hard because everything else depends on it: the backend's role, the data model, the load profile, the legal posture. And there are hard constraints — local data-protection law regulates personal data processing, and Anthropic's API isn't reachable from the target jurisdiction's infrastructure, which makes Claude itself problematic for the project technically and legally.&lt;/p&gt;

&lt;p&gt;I ran &lt;code&gt;/archforge:cycle "AI agent architecture for the editor"&lt;/code&gt;. Below is what happened, condensed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Discover, round 1 — and the constraint I'd missed
&lt;/h3&gt;

&lt;p&gt;The discovery phase produced a structured document: restated problem, functional requirements, quality attributes, constraints (team: solo developer, budget: startup, compliance: local data-protection law), prior art (Lovable, v0, Cursor, regional AI website builders), forces, and six open questions with polar options.&lt;/p&gt;

&lt;p&gt;I answered them. Then I noticed I'd written "Anthropic API only, server-side" as a constraint, and the plugin had built the rest on top of that. But Anthropic isn't reachable from infrastructure in the target jurisdiction, and sending end-user personal data to US servers violates the local data-protection law.&lt;/p&gt;

&lt;p&gt;I pointed this out. The plugin produced a &lt;strong&gt;second round of discover&lt;/strong&gt; — clearly labeled "Section 7: Second round of discover (after user input)". It:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Acknowledged the gap honestly: "this should have come up in round one; I accepted the user's premise without verifying it."&lt;/li&gt;
&lt;li&gt;Expanded alternatives to four LLM-provider categories: regional commercial APIs (regulator-certified), self-hosted open-source, Anthropic via tunnel (and explicitly flagged it as not solving the data-residency requirement — data still physically leaves the jurisdiction), and a hybrid.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pushed back on two of my answers&lt;/strong&gt; to the original questions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On Q3 (depth of business context) I'd answered "profile + dynamic memory (RAG)." The plugin pushed back: "Profile is cheap — 5–10 fields in the DB. Dynamic memory is a separate module with embedding provider, vector store, retrieval, ranking, periodic re-indexing. Is dynamic memory needed from day one of MVP, or is this clearly a V2 milestone? If V2 — fix it: profile now, dynamic memory in a later ADR."&lt;/p&gt;

&lt;p&gt;I said V2.&lt;/p&gt;

&lt;p&gt;On Q5 (evaluation), I'd asked for a full observability stack with weekly session labeling. The plugin pushed back: "Full stack with weekly labeling of 30-50 sessions is 3-5 hours per week of your time plus extra infrastructure. For a single developer, that either eats 5-10% of your time or becomes ceremony. Realistic path: log all LLM calls and tool calls structurally from day one (this is non-negotiable), defer the labeling and observability layer until you have ≥100 real sessions to label."&lt;/p&gt;

&lt;p&gt;I agreed. Both push-backs ended up in the final ADR as explicit V2 commitments.&lt;/p&gt;

&lt;p&gt;This was a senior engineer telling me that what I was asking for was disproportionate to my situation, and being right about it. The "Hold position. Argue. Don't soft-cave" instruction was earning its place.&lt;/p&gt;

&lt;h3&gt;
  
  
  Research, design, decide
&lt;/h3&gt;

&lt;p&gt;Research surfaced 50+ dated sources on regional LLM providers, their certification posture, pricing, and capability ceilings. Design produced three alternatives with honest trade-offs — Alt 1 minimalist, Alt 2 gateway with redundancy, Alt 3 full agent platform — and a 15-row comparison matrix. The plugin recommended Alt 2, &lt;strong&gt;not&lt;/strong&gt; Alt 3 (which scored higher on coverage). The reasoning: 5-6 weeks to MVP for a single developer is too long; many of Alt 3's features are premature.&lt;/p&gt;

&lt;p&gt;I picked Alt 2. The plugin produced ADR-0001 with seven explicit architectural rules — &lt;code&gt;PromptProvider&lt;/code&gt; trait, tool registry as enum + struct, dedicated &lt;code&gt;Orchestrator&lt;/code&gt; module, &lt;code&gt;current_state&lt;/code&gt; column from day 1, structured logging with zero-cost null fields for evaluation, vector storage installed but &lt;code&gt;embedding()&lt;/code&gt; returning &lt;code&gt;unimplemented!()&lt;/code&gt; until a future ADR.&lt;/p&gt;

&lt;p&gt;Real ADR. The kind I'd write if I'd spent an afternoon on it.&lt;/p&gt;

&lt;p&gt;Here's the C4 Component-level (L3) diagram the plugin produced for the AI module inside the backend, showing the path from client through gateway to LLM providers — the seven architectural rules made structural:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph TB
    Client["SPA (editor)&amp;lt;br/&amp;gt;via REST/SSE"]

    subgraph Backend["Backend — ai/ module"]
        direction TB
        Orchestrator["&amp;lt;b&amp;gt;Orchestrator&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;run_turn(session, message)&amp;lt;br/&amp;gt;dispatch_to_role() — V2"]
        ToolRegistry["&amp;lt;b&amp;gt;Tool Registry&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;enum + struct&amp;lt;br/&amp;gt;required_mode (V2)&amp;lt;br/&amp;gt;execute_tool()"]
        PromptProvider["&amp;lt;b&amp;gt;PromptProvider&amp;lt;/b&amp;gt; trait&amp;lt;br/&amp;gt;YamlPromptProvider — V0&amp;lt;br/&amp;gt;DbPromptProvider — V2"]
        Gateway["&amp;lt;b&amp;gt;LLM Gateway&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;chat_completion()&amp;lt;br/&amp;gt;embedding()&amp;lt;br/&amp;gt;routing-policy"]
        Sanitizer["&amp;lt;b&amp;gt;Sanitizer&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;strips PII&amp;lt;br/&amp;gt;before sending to&amp;lt;br/&amp;gt;secondary provider"]
        StateMachine["&amp;lt;b&amp;gt;SessionState&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;current_state&amp;lt;br/&amp;gt;('active' in V0)"]
        Logger["&amp;lt;b&amp;gt;StructuredLogger&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;provider, latency,&amp;lt;br/&amp;gt;tokens, cost,&amp;lt;br/&amp;gt;eval_label (V2)"]
    end

    subgraph DB["Database"]
        AISession[("ai_session&amp;lt;br/&amp;gt;+ current_state")]
        AIMessage[("ai_message&amp;lt;br/&amp;gt;+ provider, latency,&amp;lt;br/&amp;gt;tokens, cost, eval_*")]
        AIToolCall[("ai_tool_call")]
        BusinessProfile[("business_profile&amp;lt;br/&amp;gt;+ embedding vector NULL&amp;lt;br/&amp;gt;(V2)")]
        Prompts[("prompt_template — V2")]
    end

    subgraph Providers["LLM providers"]
        ProviderA["&amp;lt;b&amp;gt;Provider A&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;regulator-certified&amp;lt;br/&amp;gt;primary, PII-safe"]
        ProviderAClassif["&amp;lt;b&amp;gt;Provider A (Lite)&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;classification"]
        ProviderB["&amp;lt;b&amp;gt;Provider B&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;secondary,&amp;lt;br/&amp;gt;sanitized payloads only"]
        ProviderEmbed["&amp;lt;b&amp;gt;Provider C&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;embeddings"]
    end

    subgraph Future["V2 (same gateway)"]
        SelfHosted["&amp;lt;b&amp;gt;Self-hosted LLM&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;large open model&amp;lt;br/&amp;gt;via local inference server"]
        SelfHostedEmbed["&amp;lt;b&amp;gt;Self-hosted embeddings&amp;lt;/b&amp;gt;"]
    end

    Client --&amp;gt;|API call| Orchestrator
    Orchestrator --&amp;gt;|reads&amp;lt;br/&amp;gt;system prompt| PromptProvider
    Orchestrator --&amp;gt;|selects tools| ToolRegistry
    Orchestrator --&amp;gt;|chat_completion| Gateway
    Orchestrator --&amp;gt;|state&amp;lt;br/&amp;gt;transitions| StateMachine
    Orchestrator --&amp;gt;|every turn| Logger

    Gateway --&amp;gt;|PII-sensitive| ProviderA
    Gateway --&amp;gt;|classification / intent| ProviderAClassif
    Gateway --&amp;gt;|sanitized creative&amp;lt;br/&amp;gt;+ failover| Sanitizer
    Sanitizer --&amp;gt;|cleaned text| ProviderB
    Gateway --&amp;gt;|embedding| ProviderEmbed

    Gateway -.-&amp;gt;|V2: added&amp;lt;br/&amp;gt;via config| SelfHosted
    Gateway -.-&amp;gt;|V2: via config| SelfHostedEmbed

    StateMachine --&amp;gt; AISession
    Logger --&amp;gt; AIMessage
    Logger --&amp;gt; AIToolCall
    Orchestrator --&amp;gt;|reads context| BusinessProfile
    PromptProvider -.-&amp;gt;|V2| Prompts

    ToolRegistry --&amp;gt;|read_state&amp;lt;br/&amp;gt;update_*&amp;lt;br/&amp;gt;query_*| Orchestrator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Solid arrows are V0 connections (the initial implementation per ADR-0001). Dashed arrows are V2 — components the gateway and schema are ready to accept without rewriting calling code. The whole "V2" subgraph isn't built yet; the architecture is shaped to absorb it incrementally through later ADRs. The seven rules from the ADR are visible structurally: the &lt;code&gt;PromptProvider&lt;/code&gt; trait abstraction, the typed tool registry with reserved fields, the dedicated &lt;code&gt;Orchestrator&lt;/code&gt; module, the &lt;code&gt;current_state&lt;/code&gt; column from day 1, the gateway's split between &lt;code&gt;chat_completion()&lt;/code&gt; and &lt;code&gt;embedding()&lt;/code&gt;, the sanitizer pipeline as a guarded path before the secondary provider. None of this was generated as boilerplate — it followed from the discovery and design phases that came before.&lt;/p&gt;

&lt;h3&gt;
  
  
  Review found three blockers in its own ADR
&lt;/h3&gt;

&lt;p&gt;This was the first thing that genuinely surprised me. The review phase ran the &lt;code&gt;code-review-architectural&lt;/code&gt; skill on the same ADR the plugin had just produced. It found three blocking issues:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B-1.&lt;/strong&gt; The routing policy "PII data → primary provider, non-PII → secondary" is in the ADR. But who decides at runtime which is which? Three possible interpretations: static tool-to-provider mapping, attribute on the prompt, runtime classifier on message content. This is an architectural seam that will diverge in implementation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B-2.&lt;/strong&gt; The sanitizer for the secondary channel is described as nontrivial. But the ADR doesn't say what happens when the sanitizer &lt;strong&gt;fails&lt;/strong&gt;. Falls through? Blocks? Falls back to the primary provider? Gap between "the architecture protects the user" and "the developer protects the user."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B-3.&lt;/strong&gt; Failover between providers in the &lt;strong&gt;middle of an unfinished tool-use loop&lt;/strong&gt; is not addressed. Tool-use loops have multiple round-trips. If the primary provider fails on the third of five round-trips, what happens? The secondary provider's history format is incompatible. The most common failure point in hybrid gateways, not addressed.&lt;/p&gt;

&lt;p&gt;I applied all three. The review document was updated with &lt;code&gt;Status: Applied 2026-05-07&lt;/code&gt; and a closeout block listing each fix. &lt;strong&gt;The cycle compounded&lt;/strong&gt; — the next ADR builds on a corrected base.&lt;/p&gt;

&lt;p&gt;I wrote a draft of this article at this point. It was decent. But the story wasn't done.&lt;/p&gt;

&lt;h2&gt;
  
  
  v0.4: adversarial roast with five roles
&lt;/h2&gt;

&lt;p&gt;In v0.4 I added something I'd been thinking about for a while: &lt;strong&gt;multi-perspective adversarial review&lt;/strong&gt;. Not one reviewer — five, each with strict non-overlapping scope.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;devil-advocate&lt;/code&gt; — pressure-test for failure modes, hidden assumptions, edge cases, concurrency bugs.&lt;br&gt;
&lt;code&gt;pragmatist&lt;/code&gt; — operational reality, on-call burden, real cost over time, skills/bus factor, deployment risk.&lt;br&gt;
&lt;code&gt;junior-engineer&lt;/code&gt; — clarity for a fresh reader six months from now. Undefined terms, unfollowable steps, broken cross-references.&lt;br&gt;
&lt;code&gt;compliance-officer&lt;/code&gt; — regulatory exposure, PII flows, jurisdiction, audit, third-party risk.&lt;br&gt;
&lt;code&gt;futurist&lt;/code&gt; — 1-3 year horizon, structural drift, technology lifecycle, hiring, regulatory drift.&lt;/p&gt;

&lt;p&gt;Each role has an explicit "what I cover / what I do NOT cover" table referencing the other roles. The point: when independent perspectives converge on the same finding, the finding is real. When one role is silent on something, it's because another role owns it.&lt;/p&gt;

&lt;p&gt;Command: &lt;code&gt;/archforge:roast &amp;lt;ADR-NNNN&amp;gt;&lt;/code&gt;. Output: a directory of six documents — one summary plus one per role.&lt;/p&gt;

&lt;p&gt;Auto-roast at &lt;code&gt;--scale=deep&lt;/code&gt; between Decide and Document, so important decisions never become accepted ADRs without passing the multi-role gauntlet.&lt;/p&gt;

&lt;h3&gt;
  
  
  The roast on ADR-0002
&lt;/h3&gt;

&lt;p&gt;ADR-0002 was a modular monolith on a Cargo workspace — the second decision in the project, after the AI gateway was settled. I ran roast on it.&lt;/p&gt;

&lt;p&gt;The output was strong. &lt;strong&gt;14 high-severity findings, 16 medium, 16 low, plus 8 structural risks from the futurist.&lt;/strong&gt; Cross-cutting concerns — issues that multiple roles independently surfaced — were the most valuable part. Six of them. The most consequential:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CC-1: a class of confused-deputy attack at the boundary between LLM tools and the database access layer.&lt;/strong&gt; When AI tools execute under elevated database privileges (a common pattern when tool calls need to read across tenant boundaries efficiently) without authorization checks in the tool itself, prompt injection can cause horizontal data leakage between tenants. The &lt;code&gt;devil-advocate&lt;/code&gt; flagged it from a security lens (an attacker with prompt-injection access can use the trusted tool to do things the attacker shouldn't be able to). The &lt;code&gt;compliance-officer&lt;/code&gt; independently flagged the same code path from a regulatory lens (horizontal leakage of personal information across tenant boundaries violates the local data-protection law). Two roles, two angles, same architectural attack vector.&lt;/p&gt;

&lt;p&gt;This is exactly the "compound" mode I built the plugin for. &lt;strong&gt;Two independent reviewers from different lenses converged on a single architectural attack vector.&lt;/strong&gt; That's a real finding, not noise.&lt;/p&gt;

&lt;p&gt;The recommended fix was straightforward — add a rule to the ADR requiring tools to accept an authorization context and perform ownership checks, or alternatively use a constrained database role that enforces row-level security at the connection level. Plus open two new ADRs (operational baseline and compliance contour) before any paying users.&lt;/p&gt;

&lt;p&gt;This was the single best architectural moment I'd had with an AI tool. &lt;strong&gt;The plugin found a class of security bug in my own ADR through structured adversarial review, and proposed a concrete fix.&lt;/strong&gt; I was ready to publish the article.&lt;/p&gt;

&lt;h2&gt;
  
  
  And then the report was garbled
&lt;/h2&gt;

&lt;p&gt;The roast output came back in &lt;strong&gt;mixed Russian and English&lt;/strong&gt;. Section headers were in English (&lt;code&gt;## Headline findings&lt;/code&gt;, &lt;code&gt;## Cross-cutting concerns&lt;/code&gt;) but the prose was in Russian, and the prose was full of transliterated English — "обзервабилити" instead of "наблюдаемость", "operational baseline" instead of "операционный минимум", "compile-time гарантии" instead of "гарантии на этапе компиляции".&lt;/p&gt;

&lt;p&gt;I'd written an explicit terminology rule into the architect skill in v0.3 specifically to prevent this. Russian artifacts must use proper Russian engineering terminology, not transliterated English calques. The rule was there. It clearly hadn't been applied.&lt;/p&gt;

&lt;p&gt;I told Claude: "your output is full of anglicisms, please apply the terminology rule."&lt;/p&gt;

&lt;p&gt;What happened next is, in some ways, more interesting than the original bug.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overcorrection: the failure mode nobody talks about
&lt;/h2&gt;

&lt;p&gt;Claude's response started: "Виноват — это уже второй раз с тем же правилом, явно нарушил." (Guilty — second time with the same rule, clearly violated.)&lt;/p&gt;

&lt;p&gt;And then it rewrote the summary. With problems.&lt;/p&gt;

&lt;p&gt;It translated &lt;code&gt;Devil-advocate&lt;/code&gt; to "Обвинитель" (Prosecutor). And &lt;code&gt;Pragmatist&lt;/code&gt; to "Прагматик". And &lt;code&gt;Junior-engineer&lt;/code&gt; to "Новый разработчик". And &lt;code&gt;Compliance-officer&lt;/code&gt; to "Специалист по соответствию". And — and this is the worst — &lt;code&gt;Futurist&lt;/code&gt; to "Стратег" (Strategist).&lt;/p&gt;

&lt;p&gt;It translated the section headers. &lt;code&gt;## Headline findings&lt;/code&gt; became &lt;code&gt;## Главное&lt;/code&gt;. &lt;code&gt;## Cross-cutting concerns&lt;/code&gt; became &lt;code&gt;## Сквозные проблемы&lt;/code&gt;. &lt;code&gt;## Severity counts&lt;/code&gt; became &lt;code&gt;## Распределение по тяжести&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It translated the finding IDs. &lt;code&gt;CC-1&lt;/code&gt; became &lt;code&gt;СП-1&lt;/code&gt;. &lt;code&gt;CC-2&lt;/code&gt; became &lt;code&gt;СП-2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I read this and immediately knew there was something wrong, beyond just being a different translation choice. &lt;strong&gt;These weren't translations. They were structural breaks.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Devil-advocate&lt;/code&gt; is the name of an agent file. &lt;code&gt;agents/devil-advocate.md&lt;/code&gt;. There's a &lt;code&gt;name:&lt;/code&gt; field in the frontmatter that says &lt;code&gt;devil-advocate&lt;/code&gt;. That string is invoked by the orchestrating command. Translating it to "Обвинитель" means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Future references to that agent in other artifacts won't resolve.&lt;/li&gt;
&lt;li&gt;The roast directory's per-role files (&lt;code&gt;01-devil-advocate.md&lt;/code&gt;, &lt;code&gt;02-pragmatist.md&lt;/code&gt;...) suddenly don't match the roles named in the summary.&lt;/li&gt;
&lt;li&gt;Comparing this roast to a future one is impossible — two roasts on the same ADR will name the roles differently.&lt;/li&gt;
&lt;li&gt;The role concept itself was changed: "Стратег" (strategist) is not a translation of &lt;code&gt;Futurist&lt;/code&gt; (long-horizon role); it's a different role. The role was substituted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;## Headline findings&lt;/code&gt; is a section header prescribed by the &lt;code&gt;roast&lt;/code&gt; command file. The command writes that header literally. Other tooling (and a future user reading the directory) expects that header. Translating it to &lt;code&gt;## Главное&lt;/code&gt; means the document diverged from what the plugin's own templates promised.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CC-1&lt;/code&gt; is a finding ID that gets cross-referenced. The summary says "CC-1 — see devil-advocate F1.1 + compliance C1.1". If you rename CC-1 to СП-1 in the summary but the agent docs still call it CC-1 (because they were written first, in English), the cross-references break. References pointing at IDs that don't exist anymore.&lt;/p&gt;

&lt;p&gt;This is the plugin's own templates, names, and identifiers being &lt;strong&gt;silently translated under translation pressure&lt;/strong&gt;. After being told "apply the terminology rule", the assistant pattern-matched too aggressively and translated things that aren't terminology. They're identifiers.&lt;/p&gt;

&lt;p&gt;And here's the failure mode in a clean form: &lt;strong&gt;AI tools fail in two directions, and most reviews of AI tools only test one direction.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Undercorrection&lt;/strong&gt; — the LLM ignores a rule. ("обзервабилити" instead of "наблюдаемость".)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overcorrection&lt;/strong&gt; — the LLM applies a rule too widely after being corrected. (Translating identifiers along with prose.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The blog posts about LLM problems usually focus on the first. Hallucination, ignored constraints, dropped instructions. Overcorrection — over-eager application of corrections to inappropriate scope — is also a serious failure mode, and it's exactly the failure mode that &lt;strong&gt;trying harder&lt;/strong&gt; produces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Root cause: rules in one place, applied in many
&lt;/h2&gt;

&lt;p&gt;Why did this happen? The terminology rule lived in &lt;code&gt;skills/architect/SKILL.md&lt;/code&gt; — the router skill. The router skill is loaded into Claude's context when the architectural intent is detected. But the roast command spawns five sub-agents (&lt;code&gt;devil-advocate&lt;/code&gt;, &lt;code&gt;pragmatist&lt;/code&gt;, etc.). &lt;strong&gt;Each sub-agent is a separate context.&lt;/strong&gt; They read their own SKILL.md files. They don't automatically inherit rules from the router.&lt;/p&gt;

&lt;p&gt;So the structural bug was: the rule was authored once, but its enforcement depended on it being read in each of the contexts where output gets generated. In the roast, that was six contexts (five role agents plus the summarizing main thread). Five of them never saw the rule.&lt;/p&gt;

&lt;p&gt;After my correction, the main thread did know the rule. But it applied it to everything that vaguely resembled a Russian-with-anglicisms problem — including identifiers that should never have been translated.&lt;/p&gt;

&lt;p&gt;The fix could not be "remember to apply the rule everywhere". That's the same fix that already existed and didn't work. The fix had to be &lt;strong&gt;structural&lt;/strong&gt;: the rule needs to be embedded in every place where output is generated, with explicit guards against both directions of failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix, and what we built around it
&lt;/h2&gt;

&lt;p&gt;In v0.4-rc2, I did three things:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Embedded the language rule in every sub-agent.&lt;/strong&gt; All five roast agents and all three core agents (&lt;code&gt;architect&lt;/code&gt;, &lt;code&gt;reviewer&lt;/code&gt;, &lt;code&gt;researcher&lt;/code&gt;) now have an explicit &lt;code&gt;## Language and terminology&lt;/code&gt; section in their &lt;code&gt;agents/*.md&lt;/code&gt; files referencing the architect skill's taxonomy. Each agent's section names the specific identifiers that role uses (its own name, its own finding-ID scheme, the section headers it produces) that must never be translated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Rewrote the language rule in the router skill with explicit categories.&lt;/strong&gt; A 10-category taxonomy distinguishing what gets translated from what doesn't:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A. Plugin component identifiers — never translate.&lt;/li&gt;
&lt;li&gt;B. Software, library, protocol names — never.&lt;/li&gt;
&lt;li&gt;C. Standard abbreviations — never.&lt;/li&gt;
&lt;li&gt;D. Laws, regulations, standards — never.&lt;/li&gt;
&lt;li&gt;E. Artifact identifiers (finding IDs, rule numbers, ADR IDs) — never.&lt;/li&gt;
&lt;li&gt;F. Plugin template section names — never (verbatim English even when body is in another language).&lt;/li&gt;
&lt;li&gt;G. Project-internal proper nouns — never when capitalized.&lt;/li&gt;
&lt;li&gt;H. Term-of-art with no clean Russian equivalent — keep with first-occurrence gloss.&lt;/li&gt;
&lt;li&gt;I. Calques — translate per the calque table.&lt;/li&gt;
&lt;li&gt;J. Prose verbs and connectors — translate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Plus a section literally titled "Overcorrection is also a failure" with the exact examples of what had just gone wrong: &lt;code&gt;Devil-advocate&lt;/code&gt; should not become "Обвинитель", &lt;code&gt;## Headline findings&lt;/code&gt; should not become &lt;code&gt;## Главное&lt;/code&gt;, &lt;code&gt;CC-3&lt;/code&gt; should not become &lt;code&gt;СП-3&lt;/code&gt;. &lt;strong&gt;The negative examples are now part of the spec.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Added a new agent: &lt;code&gt;meta-reviewer&lt;/code&gt;.&lt;/strong&gt; This is the most important part.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the meta-reviewer does
&lt;/h2&gt;

&lt;p&gt;The five roast roles attack the substance of an ADR. The meta-reviewer doesn't. It checks &lt;strong&gt;the form&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It reads artifacts produced by the plugin and checks them against the plugin's own templates and rules. Five categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Template conformance&lt;/strong&gt; — does this ADR have all the required sections? Does this roast directory have a summary plus one file per role? Does this review have a Status section?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identifier preservation&lt;/strong&gt; — are agent names, command names, template section headers, finding IDs, software names, regulation names, all in their original form?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language-pass evidence&lt;/strong&gt; — for Russian artifacts, did the calque pass actually run? Is there a one-line note at the end stating what was changed?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-reference integrity&lt;/strong&gt; — does "ADR-NNNN" point at an ADR that exists? Does "see B-1" resolve to a finding that's in the document?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lifecycle integrity&lt;/strong&gt; — has anyone substantively edited an Accepted ADR (which should be superseded, not edited)?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Critically, the meta-reviewer &lt;strong&gt;does not evaluate architectural quality&lt;/strong&gt;. That's roast's job. The meta-reviewer is the role that asks: "does this artifact match what the plugin's own files said it should look like?"&lt;/p&gt;

&lt;p&gt;It uses &lt;strong&gt;the plugin's own source files as the specification&lt;/strong&gt;. It reads &lt;code&gt;commands/roast.md&lt;/code&gt; to know what sections a roast summary must have. It reads &lt;code&gt;skills/architect/SKILL.md&lt;/code&gt; to know which strings count as identifiers. The plugin is grading itself against its own promises.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;--scale=deep&lt;/code&gt; cycles, the meta-reviewer runs automatically: after the auto-roast (on the roast directory) and after Document (on the freshly-written ADR). High-severity divergences pause the cycle.&lt;/p&gt;

&lt;p&gt;So: the plugin found an architectural bug in its own ADR (review of ADR-0001). Then it found a security bug in another of its ADRs (roast of ADR-0002). Then it failed to follow its own language rule. Then it overcorrected and translated identifiers it shouldn't have. &lt;strong&gt;Now it has a role specifically designed to catch the kind of bug the previous version had.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is what compounding looks like, in the actual Compound Engineering sense: each cycle leaves the next cycle better-equipped, because the system itself is the artifact being improved.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd build differently if I started over
&lt;/h2&gt;

&lt;p&gt;One thing, mainly. I'd put the language rule in every relevant context &lt;strong&gt;from the start&lt;/strong&gt;, not in the router skill alone. The "DRY" instinct says rules should live in one place. For LLM tooling that turns out to be wrong: rules need to be in &lt;strong&gt;every context where they're enforced&lt;/strong&gt;, even at the cost of duplication. Sub-agent contexts don't automatically share state with the parent. Architecting LLM-tool systems is partly the discipline of accepting that LLMs do not naturally inherit context the way functions inherit lexical scope. The meta-reviewer pattern — a role specifically dedicated to checking that artifacts conform to the system's own rules — should probably exist in any AI plugin that produces structured artifacts, not just this one.&lt;/p&gt;

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

&lt;p&gt;The plugin's roadmap covers three minor versions. &lt;strong&gt;v0.5 "Sharper feedback"&lt;/strong&gt; sharpens existing feedback — a &lt;code&gt;/archforge:diff &amp;lt;ADR&amp;gt;&lt;/code&gt; command that checks whether an accepted ADR still lives in the actual code, an anti-patterns skill (concrete named ones — distributed monolith, database-as-integration-layer, sync chains, cache as source of truth), an architectural-metrics skill, an &lt;code&gt;/archforge:export&lt;/code&gt; command for shipping artifacts to articles or portfolios. &lt;strong&gt;v0.6 "Memory and history"&lt;/strong&gt; adds a historian agent reading the project archive, retrospectives, decision-map evolution, optional pre-commit hooks. &lt;strong&gt;v0.7 "Teams and budgets"&lt;/strong&gt; covers cost as a first-class architectural variable and multi-architect coordination.&lt;/p&gt;

&lt;p&gt;Full plan, including the explicit &lt;strong&gt;anti-roadmap&lt;/strong&gt; (no code generation from ADRs, no project-management integrations, no doc-site generators, no voting workflows on ADRs, no per-language plugin variants) is in &lt;a href="https://github.com/IgorKramar/archforge-marketplace/blob/main/ROADMAP.md" rel="noopener noreferrer"&gt;ROADMAP.md&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The compound pattern, more directly
&lt;/h2&gt;

&lt;p&gt;Most AI-tooling discourse focuses on &lt;strong&gt;automation&lt;/strong&gt; — getting AI to do more work for you. That's real and matters. But for some kinds of work, automation is the wrong frame.&lt;/p&gt;

&lt;p&gt;Architecture is one of those. The work isn't to produce an artifact faster. The work is to &lt;strong&gt;make a defensible decision under uncertainty&lt;/strong&gt;. The artifact is downstream of the decision. Defensible decisions require structured disagreement, real alternatives, honest trade-off analysis, and someone willing to push back when you skip ahead.&lt;/p&gt;

&lt;p&gt;If you cast AI as "thing that produces artifacts", you'll get bad architecture faster. If you cast AI as "thing that argues with me about my reasoning until I either change my mind or strengthen my case, while also checking that the artifacts of our conversation match the rules we agreed on", you'll get better architecture, slower, on purpose.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;archforge&lt;/code&gt; is one attempt at the second framing. Pairs naturally with &lt;a href="https://github.com/EveryInc/compound-engineering-plugin" rel="noopener noreferrer"&gt;Compound Engineering&lt;/a&gt; — CE handles feature-level workflow (Brainstorm → Plan → Work → Review → Compound), &lt;code&gt;archforge&lt;/code&gt; handles architectural decisions (Discover → Research → Design → Decide → Document → Review). Architectural decisions feed into CE plans by ADR number; CE compound learnings can produce new ADRs. The integration is materialized by running &lt;code&gt;/archforge:remember-compound-integration&lt;/code&gt; once per project.&lt;/p&gt;

&lt;p&gt;If you try the plugin, the most useful thing you can give back is a &lt;strong&gt;specific failure&lt;/strong&gt;. Not "it's great" — that's nice but not actionable. "I ran roast on this ADR and the futurist role completely missed X" — that's actionable, that's how v0.5 gets shaped.&lt;/p&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/IgorKramar/archforge-marketplace" rel="noopener noreferrer"&gt;github.com/IgorKramar/archforge-marketplace&lt;/a&gt;. Issues, PRs, and especially &lt;strong&gt;specific bug reports of the plugin failing on your project&lt;/strong&gt; are welcome. The plugin gets better when it fails in instructive ways. That's the whole point.&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>architecture</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Superpowers vs Compound Engineering: is the 'vs' even real?</title>
      <dc:creator>Igor Kramar</dc:creator>
      <pubDate>Mon, 04 May 2026 13:02:08 +0000</pubDate>
      <link>https://dev.to/ikramar/superpowers-vs-compound-engineering-is-the-vs-even-real-58gc</link>
      <guid>https://dev.to/ikramar/superpowers-vs-compound-engineering-is-the-vs-even-real-58gc</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; — Superpowers and Compound Engineering aren't competitors. They're optimised for different worlds. Superpowers is gold for &lt;strong&gt;mature codebases with established methodology&lt;/strong&gt; (TDD shops, large legacy systems, teams enforcing standards). Compound Engineering is gold for &lt;strong&gt;early-stage products where one person owns a feature end-to-end&lt;/strong&gt;. Pick by &lt;em&gt;what your codebase looks like&lt;/em&gt;, not by which README sounds shinier.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you've spent any time in the Claude Code plugin ecosystem in the last few months, you've almost certainly heard about both:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/obra/superpowers" rel="noopener noreferrer"&gt;&lt;strong&gt;Superpowers&lt;/strong&gt;&lt;/a&gt; by Jesse Vincent — a "complete software development methodology" plugin, ~42k stars, in Anthropic's official marketplace.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/EveryInc/compound-engineering-plugin" rel="noopener noreferrer"&gt;&lt;strong&gt;Compound Engineering&lt;/strong&gt;&lt;/a&gt; by Every — a 36-skill, 50-agent framework around the idea that "each unit of engineering work should make the next one easier", ~16k stars.
Both ship as Claude Code plugins. Both wrap roughly the same surface — brainstorm, plan, work, review. Both have evangelists writing "I 100x'd my output" posts. So the natural question gets asked a lot: &lt;strong&gt;which one wins?&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I installed both, ran them on the same projects for a few weeks (work — a Nuxt/Vue 3 platform product; personal — a small landing-page tool and my wife's florist site), and the answer turned out to be more interesting than I expected.&lt;/p&gt;

&lt;p&gt;The "vs" is the wrong question. Let me show you why.&lt;/p&gt;

&lt;h2&gt;
  
  
  What both plugins are actually solving
&lt;/h2&gt;

&lt;p&gt;Bare Claude Code is excellent at small tasks and dangerous at large ones. Without scaffolding it tends to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Skip planning and start typing code on turn two.&lt;/li&gt;
&lt;li&gt;Forget the lessons from yesterday's bug-hunt by tomorrow morning.&lt;/li&gt;
&lt;li&gt;Drift further from your project's conventions the longer the session runs.&lt;/li&gt;
&lt;li&gt;Treat each new request as if the codebase were a stranger.
Both plugins exist to fix this — but they fix it from different ends. To see the difference, you have to look past the README marketing and ask what each one &lt;em&gt;forces&lt;/em&gt; you to do.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The 90% overlap
&lt;/h2&gt;

&lt;p&gt;Honestly: most of the surface is the same. Here's the side-by-side:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Superpowers&lt;/th&gt;
&lt;th&gt;Compound Engineering&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Refine a vague idea&lt;/td&gt;
&lt;td&gt;&lt;code&gt;brainstorming&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/ce-brainstorm&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Turn it into a plan&lt;/td&gt;
&lt;td&gt;&lt;code&gt;writing-plans&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/ce-plan&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Isolated execution&lt;/td&gt;
&lt;td&gt;&lt;code&gt;using-git-worktrees&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ce-worktree&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code review before merge&lt;/td&gt;
&lt;td&gt;&lt;code&gt;requesting-code-review&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/ce-code-review&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Systematic debugging&lt;/td&gt;
&lt;td&gt;&lt;code&gt;systematic-debugging&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/ce-debug&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you only look at this table, the conclusion is "they're the same plugin with different prefixes". That conclusion is wrong, and the difference is hidden in two places: &lt;strong&gt;what each plugin enforces&lt;/strong&gt;, and &lt;strong&gt;what each one adds beyond the shared surface&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real difference
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Superpowers is a discipline-enforcement engine
&lt;/h3&gt;

&lt;p&gt;Read the Superpowers source and you find it again and again: this plugin is opinionated, and the opinions have teeth. The clearest example is TDD:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If Claude tries to write code before tests, this skill literally makes it delete the code and start over. No exceptions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's not a tip. That's a guard rail. Other examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The brainstorming skill &lt;strong&gt;activates automatically&lt;/strong&gt; when you describe a feature — you can't accidentally skip it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;systematic-debugging&lt;/code&gt; runs a 4-phase root-cause process and triggers a mandatory architectural review after three failed fix attempts.&lt;/li&gt;
&lt;li&gt;YAGNI and "evidence over claims" are baked in as non-negotiables.
Superpowers is, in Jesse Vincent's own framing, a &lt;em&gt;methodology&lt;/em&gt;. It's there to make Claude behave the way a senior engineer at a disciplined shop would behave, whether you remember to ask or not.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The cost of this is real: Superpowers will fight you when you don't want to do TDD, when you want to vibe-code a quick spike, when you'd rather see something running before you write the test. That's not a bug. That's the entire point.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compound Engineering is a knowledge-accumulation framework
&lt;/h3&gt;

&lt;p&gt;Compound Engineering's central claim is in its name: each cycle should make the next cycle cheaper. The unique skills, the ones Superpowers has no real equivalent for, all serve that claim:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/ce-compound&lt;/code&gt;&lt;/strong&gt; — after a feature ships, you write down what was learned. Bug patterns, gotchas, surprising decisions. These get indexed and pulled into the context of future plans.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/ce-compound-refresh&lt;/code&gt;&lt;/strong&gt; — periodically reviews stored learnings and decides whether to keep, update, replace or archive them. Without this, your knowledge base drifts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/ce-strategy&lt;/code&gt;&lt;/strong&gt; — maintains a &lt;code&gt;STRATEGY.md&lt;/code&gt; at the repo root: target problem, persona, key metrics, tracks. &lt;code&gt;/ce-ideate&lt;/code&gt;, &lt;code&gt;/ce-brainstorm&lt;/code&gt; and &lt;code&gt;/ce-plan&lt;/code&gt; all read it as grounding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/ce-product-pulse&lt;/code&gt;&lt;/strong&gt; — time-windowed reports of what users actually experienced, saved to &lt;code&gt;docs/pulse-reports/&lt;/code&gt; so a timeline of outcomes builds up over time.
Notice what's happening here: CE is reaching &lt;em&gt;above&lt;/em&gt; the engineering loop (strategy) and &lt;em&gt;below&lt;/em&gt; it (user outcomes), and tying both back into the planning context. It's trying to be a product loop, not just an engineering one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The cost is also real: 36 skills and 50+ agents is a lot of surface. Without discipline you end up running ceremonial workflows on tasks that didn't need them. And &lt;code&gt;/ce-compound&lt;/code&gt; only works if you actually use it after every cycle — skip it for two sprints and CE collapses into "Claude Code with extra slash commands".&lt;/p&gt;

&lt;h2&gt;
  
  
  Where each one breaks
&lt;/h2&gt;

&lt;p&gt;This is the part most comparison posts skip, so let me be specific.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Superpowers breaks when your domain isn't TDD-shaped.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I tried Superpowers on a Nuxt/Vue 3 SSR feature where most of the work was prop-drilling, layout tweaks and Pinia state plumbing. The TDD-first enforcement turned a 90-minute change into a 3-hour session of writing tests for code that's mostly visual. For SSR-specific bugs (hydration mismatches, server-only state) the discipline pays for itself. For "make this card layout responsive", it's pure friction.&lt;/p&gt;

&lt;p&gt;Superpowers also struggles with rapid iteration. Brainstorm-plan-test-implement is brilliant for a feature you'll ship to a million users. It's overkill for a 30-minute spike where the goal is to know whether an approach is even viable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compound Engineering breaks when you skip the compound step.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the trap. CE has so many slash commands that it feels productive even when you're just running &lt;code&gt;/ce-plan&lt;/code&gt; and &lt;code&gt;/ce-work&lt;/code&gt; on autopilot. But CE without &lt;code&gt;/ce-compound&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; compound engineering — it's just a more verbose Claude Code session. The plugin's value compounds only if you compound. I've watched myself skip it under deadline pressure on three consecutive cycles before I noticed the framework had quietly become decorative.&lt;/p&gt;

&lt;p&gt;CE also breaks at team scale. The named-persona reviewers (&lt;code&gt;ce-dhh-rails-reviewer&lt;/code&gt;, &lt;code&gt;ce-kieran-typescript-reviewer&lt;/code&gt;) encode somebody else's taste. On a personal project that's fine — useful, even. On a team project, "the reviewer Claude is roleplaying as DHH" is not a conversation I want to have with a senior colleague at standup.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shape that actually predicts which one fits
&lt;/h2&gt;

&lt;p&gt;Here's the rule of thumb I landed on after two months of switching back and forth:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Your situation&lt;/th&gt;
&lt;th&gt;Better fit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Mature codebase, established conventions, real test suite&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Superpowers&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Greenfield product, you own it end-to-end, conventions still forming&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Compound Engineering&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team enforcing TDD or similar discipline&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Superpowers&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Solo dev or small team, knowledge dies if not written down&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Compound Engineering&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Legacy system where consistency matters more than novelty&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Superpowers&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Early-stage product where strategy shifts week to week&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Compound Engineering&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You want the plugin to constrain you&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Superpowers&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You want the plugin to remember for you&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Compound Engineering&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Or stated more bluntly: &lt;strong&gt;Superpowers is for codebases with a methodology to enforce. Compound Engineering is for products where the knowledge to compound is still being created.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A startup with a 6-month-old codebase and a single engineer per feature has very little to enforce — there are no conventions yet, the test suite is patchy, the architecture is in flux. What it desperately needs is a memory: why did we pick Pinia over Vuex, what broke last sprint, who is the persona we're optimising for. CE's &lt;code&gt;/ce-strategy&lt;/code&gt;, &lt;code&gt;/ce-product-pulse&lt;/code&gt; and &lt;code&gt;/ce-compound&lt;/code&gt; are exactly that memory.&lt;/p&gt;

&lt;p&gt;A 10-year-old enterprise codebase with 30 engineers has the opposite shape. The knowledge already exists — in the test suite, in code review norms, in the architectural decision records. What it needs is &lt;em&gt;enforcement&lt;/em&gt;, because the failure mode is drift away from established standards under deadline pressure. Superpowers' "delete the code, write the test first, no exceptions" is precisely calibrated to that failure mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually run, and where
&lt;/h2&gt;

&lt;p&gt;For my work codebase (Nuxt/Vue 3, established team, real conventions), I lean on Superpowers — but selectively. &lt;code&gt;brainstorming&lt;/code&gt; and &lt;code&gt;writing-plans&lt;/code&gt; for any non-trivial feature; &lt;code&gt;systematic-debugging&lt;/code&gt; for tricky SSR bugs; I let TDD enforcement run on backend Pinia store logic and turn it down on pure UI work.&lt;/p&gt;

&lt;p&gt;For personal projects (the landing-page tool, the florist site), I run Compound Engineering. &lt;code&gt;/ce-strategy&lt;/code&gt; once at the start gives every subsequent &lt;code&gt;/ce-plan&lt;/code&gt; real context about what the product is for. &lt;code&gt;/ce-compound&lt;/code&gt; after each meaningful feature actually compounds — I've already had &lt;code&gt;/ce-plan&lt;/code&gt; surface a learning from a previous cycle that saved me an evening.&lt;/p&gt;

&lt;p&gt;I don't run both in the same repo. They both touch &lt;code&gt;CLAUDE.md&lt;/code&gt;, they both want to be the source of truth for how the agent behaves, and the conflict isn't worth it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest version of "vs"
&lt;/h2&gt;

&lt;p&gt;If someone asks "which plugin should I install?" — that's the wrong question. The right one is: &lt;strong&gt;what shape is the work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Mature codebase, established discipline, the failure mode is drift → Superpowers.&lt;/p&gt;

&lt;p&gt;Early product, single owner per feature, the failure mode is forgotten learnings → Compound Engineering.&lt;/p&gt;

&lt;p&gt;The "vs" framing is what marketing produces when two tools are competing for the same star count. Engineering produces a different question: what fits this codebase, this team, this stage?&lt;/p&gt;

&lt;p&gt;Try both. Run each on the project where its philosophy actually matches. You'll know within a week which one earned its place.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you've run them both and your shape is different from mine, I'd genuinely like to hear it in the comments — especially the cases where I'm probably wrong.&lt;/em&gt;&lt;/p&gt;

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