<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="https://futurewithml.netlify.app/feed_style.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <tabi:metadata xmlns:tabi="https://github.com/welpo/tabi">
        <tabi:base_url>https:&#x2F;&#x2F;futurewithml.netlify.app</tabi:base_url>
        <tabi:separator>
            |
        </tabi:separator>
        <tabi:about_feeds>This is a web feed, also known as an Atom feed. Subscribe by copying the URL from the address bar into your newsreader. Visit About Feeds to learn more and get started. It&#x27;s free.</tabi:about_feeds>
        <tabi:visit_the_site>Visit website</tabi:visit_the_site>
        <tabi:recent_posts>Recent posts</tabi:recent_posts>
        <tabi:last_updated_on>Updated on $DATE</tabi:last_updated_on>
        <tabi:default_theme></tabi:default_theme>
        <tabi:post_listing_date>date</tabi:post_listing_date>
        <tabi:current_section>Hybrid Architecture</tabi:current_section>
    </tabi:metadata><link rel="extra-stylesheet" href="https://futurewithml.netlify.app/skins/cyber.css?h=eb029a27afbc61465b52" /><title>Future With ML - Hybrid Architecture</title>
        <subtitle>Machine Learning Design Patterns, MLOps, and AI Engineering insights by Christian Picon Calderon</subtitle>
    <link href="https://futurewithml.netlify.app/tags/hybrid-architecture/atom.xml" rel="self" type="application/atom+xml"/>
    <link href="https://futurewithml.netlify.app/tags/hybrid-architecture/" rel="alternate" type="text/html"/>
    <generator uri="https://www.getzola.org/">Zola</generator><updated>2026-01-06T11:00:00+00:00</updated><id>https://futurewithml.netlify.app/tags/hybrid-architecture/atom.xml</id><entry xml:lang="en">
        <title>The Hybrid Architecture Pattern: Lessons from agent-team-creator</title>
        <published>2026-01-06T11:00:00+00:00</published>
        <updated>2026-01-06T11:00:00+00:00</updated>
        <author>
            <name>Christian Picon Calderon</name>
        </author>
        <link rel="alternate" href="https://futurewithml.netlify.app/posts/claude-code-plugin-journey-part1/" type="text/html"/>
        <id>https://futurewithml.netlify.app/posts/claude-code-plugin-journey-part1/</id>
        
            <content type="html">&lt;h1 id=&quot;the-hybrid-architecture-pattern-lessons-from-agent-team-creator&quot;&gt;The Hybrid Architecture Pattern: Lessons from agent-team-creator&lt;&#x2F;h1&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This is Part 1 of a three-part series. Start with &lt;a href=&quot;&#x2F;posts&#x2F;claude-code-plugin-journey-part0&#x2F;&quot;&gt;Part 0: Agent Team Creator&lt;&#x2F;a&gt; to see what the plugin does, or continue here for the development journey.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I thought building a Claude Code plugin would take a weekend. Three days into wrestling with MCP tool access bugs, three-location file synchronization, and documentation that promised features that didn’t work, I realized I was building something more valuable than a plugin—I was mapping uncharted territory.&lt;&#x2F;p&gt;
&lt;p&gt;This is the story of building &lt;strong&gt;agent-team-creator&lt;&#x2F;strong&gt;, a Claude Code plugin that analyzes codebases and generates project-specific AI agents. Along the way, I discovered a pattern that turned platform limitations into architectural clarity: the &lt;strong&gt;Hybrid Architecture Pattern&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;act-i-the-setup&quot;&gt;Act I: The Setup&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;the-vision&quot;&gt;The Vision&lt;&#x2F;h3&gt;
&lt;p&gt;The idea was simple: analyze any codebase and automatically generate a team of specialized Claude Code agents tailored to that project. A React frontend? Generate a component-designer agent. A Python ML pipeline? Spawn a model-trainer agent. The plugin would understand your code and create AI collaborators that speak your project’s language.&lt;&#x2F;p&gt;
&lt;p&gt;I had read the documentation. Claude Code plugins support five component types—commands, agents, skills, hooks, and MCP integrations. Agents can spawn subagents using the Task tool. MCP servers provide external service access. It seemed straightforward.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s what I expected versus what I found:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Expectation&lt;&#x2F;th&gt;&lt;th&gt;Reality&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Plugin agents can access MCP tools&lt;&#x2F;td&gt;&lt;td&gt;Plugin agents &lt;strong&gt;cannot&lt;&#x2F;strong&gt; access MCP (documented bug)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Agents can spawn nested subagents&lt;&#x2F;td&gt;&lt;td&gt;Single-level nesting only&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Documentation describes actual behavior&lt;&#x2F;td&gt;&lt;td&gt;Docs claim MCP works, but it doesn’t&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Changes propagate automatically&lt;&#x2F;td&gt;&lt;td&gt;3-location manual sync required&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Model inheritance works&lt;&#x2F;td&gt;&lt;td&gt;Defaults to Sonnet 4 regardless of settings&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The gap between expectation and reality would become my curriculum.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;understanding-the-terrain&quot;&gt;Understanding the Terrain&lt;&#x2F;h3&gt;
&lt;p&gt;Before diving into the pain points, let me share the landscape. Claude Code plugins have five component types, each with distinct triggering mechanisms:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Component&lt;&#x2F;th&gt;&lt;th&gt;Trigger&lt;&#x2F;th&gt;&lt;th&gt;Purpose&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Skills&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Auto-invoked&lt;&#x2F;td&gt;&lt;td&gt;Context providers based on description matching&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Commands&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;User-initiated (&lt;code&gt;&#x2F;command&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;td&gt;Slash command shortcuts&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Agents&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Spawned via Task tool&lt;&#x2F;td&gt;&lt;td&gt;Separate Claude instances for specialized work&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Hooks&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Event-driven&lt;&#x2F;td&gt;&lt;td&gt;Automation handlers (PreToolUse, PostToolUse, etc.)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;MCPs&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Tool calls&lt;&#x2F;td&gt;&lt;td&gt;External service integrations&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The directory structure follows a predictable pattern:&lt;&#x2F;p&gt;





&lt;div class=&quot;tree-container&quot; id=&quot;tree-202&quot;&gt;
    &lt;canvas class=&quot;tree-canvas&quot; aria-label=&quot;Directory structure visualization&quot;&gt;&lt;&#x2F;canvas&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    const containerId = &#x27;tree-202&#x27;;

    &#x2F;&#x2F; Decode HTML entities (Tera encodes &#x2F; as &amp;#x2F;)
    function decodeHTML(str) {
        const textarea = document.createElement(&#x27;textarea&#x27;);
        textarea.innerHTML = str;
        return textarea.value;
    }

    const rootName = decodeHTML(&#x27;plugin-root&#x27;);
    const nodeData = decodeHTML(&#x27;.claude-plugin&amp;#x2F;:marketplace.json;plugin.json,commands&amp;#x2F;:*.md,agents&amp;#x2F;:*.md,skills&amp;#x2F;:SKILL.md,hooks&amp;#x2F;:*.md,.mcp.json:config&#x27;);

    function parseNodes(data) {
        const folders = [];
        data.split(&#x27;,&#x27;).forEach(folder =&gt; {
            const [name, childrenStr] = folder.split(&#x27;:&#x27;);
            const children = childrenStr ? childrenStr.split(&#x27;;&#x27;).map(c =&gt; c.trim()) : [];
            folders.push({ name: name.trim(), children, type: &#x27;folder&#x27; });
        });
        return folders;
    }

    function initTree() {
        const container = document.getElementById(containerId);
        if (!container) return;

        const canvas = container.querySelector(&#x27;.tree-canvas&#x27;);
        const ctx = canvas.getContext(&#x27;2d&#x27;);

        let particles = [];
        let time = 0;

        const colors = {
            root: &#x27;#ff0080&#x27;,
            folder: &#x27;#00d4ff&#x27;,
            file: &#x27;#8b5cf6&#x27;,
            config: &#x27;#ff8800&#x27;,
            accent: &#x27;#00ff88&#x27;,
            connection: &#x27;rgba(0, 212, 255, 0.3)&#x27;,
            text: &#x27;#e0e0e4&#x27;
        };

        const folders = parseNodes(nodeData);

        function resize() {
            const rect = container.getBoundingClientRect();
            canvas.width = rect.width;
            canvas.height = 320;
        }
        resize();
        window.addEventListener(&#x27;resize&#x27;, resize);

        function getNodePositions() {
            const nodes = [];
            const centerX = canvas.width &#x2F; 2;
            const rootY = 50;
            const folderY = 140;
            const fileY = 230;

            &#x2F;&#x2F; Root node
            nodes.push({
                type: &#x27;root&#x27;,
                label: rootName,
                x: centerX,
                y: rootY,
                radius: 28,
                color: colors.root
            });

            &#x2F;&#x2F; Folder nodes
            const folderSpacing = Math.min(120, (canvas.width - 100) &#x2F; folders.length);
            const startX = centerX - ((folders.length - 1) * folderSpacing) &#x2F; 2;

            folders.forEach((folder, i) =&gt; {
                const x = startX + i * folderSpacing;
                const isConfig = folder.name.includes(&#x27;.&#x27;) || folder.name.includes(&#x27;json&#x27;);

                nodes.push({
                    type: &#x27;folder&#x27;,
                    label: folder.name,
                    x: x,
                    y: folderY,
                    radius: 22,
                    color: isConfig ? colors.config : colors.folder,
                    parentIndex: 0,
                    children: folder.children
                });
            });

            &#x2F;&#x2F; File nodes (spread under their parent folders)
            let fileIndex = 0;
            folders.forEach((folder, folderIdx) =&gt; {
                const parentNode = nodes[folderIdx + 1];
                const childCount = folder.children.length;

                folder.children.forEach((child, childIdx) =&gt; {
                    const offset = (childIdx - (childCount - 1) &#x2F; 2) * 50;
                    nodes.push({
                        type: &#x27;file&#x27;,
                        label: child,
                        x: parentNode.x + offset,
                        y: fileY + (childIdx % 2) * 35,
                        radius: 18,
                        color: colors.file,
                        parentIndex: folderIdx + 1
                    });
                    fileIndex++;
                });
            });

            return nodes;
        }

        function draw() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            const nodes = getNodePositions();

            &#x2F;&#x2F; Draw connections
            ctx.strokeStyle = colors.connection;
            ctx.lineWidth = 2;

            nodes.forEach((node, i) =&gt; {
                if (node.parentIndex !== undefined) {
                    const parent = nodes[node.parentIndex];
                    ctx.beginPath();
                    ctx.moveTo(parent.x, parent.y + parent.radius);
                    ctx.lineTo(node.x, node.y - node.radius);
                    ctx.stroke();
                }
            });

            &#x2F;&#x2F; Draw nodes
            nodes.forEach((node, i) =&gt; {
                &#x2F;&#x2F; Glow effect
                ctx.shadowColor = node.color;
                ctx.shadowBlur = 15;

                &#x2F;&#x2F; Node circle
                ctx.fillStyle = node.color;
                ctx.beginPath();
                ctx.arc(node.x, node.y, node.radius, 0, Math.PI * 2);
                ctx.fill();

                ctx.shadowBlur = 0;

                &#x2F;&#x2F; Border
                ctx.strokeStyle = colors.accent;
                ctx.lineWidth = 2;
                ctx.stroke();

                &#x2F;&#x2F; Icon based on type
                ctx.fillStyle = &#x27;#0a0a0f&#x27;;
                ctx.font = node.type === &#x27;root&#x27; ? &#x27;16px sans-serif&#x27; : &#x27;12px sans-serif&#x27;;
                ctx.textAlign = &#x27;center&#x27;;
                ctx.textBaseline = &#x27;middle&#x27;;

                if (node.type === &#x27;root&#x27;) {
                    ctx.fillText(&#x27;📁&#x27;, node.x, node.y);
                } else if (node.type === &#x27;folder&#x27;) {
                    ctx.fillText(&#x27;📂&#x27;, node.x, node.y);
                } else {
                    ctx.fillText(&#x27;📄&#x27;, node.x, node.y);
                }

                &#x2F;&#x2F; Label
                ctx.fillStyle = colors.text;
                ctx.font = node.type === &#x27;root&#x27; ? &#x27;bold 12px JetBrains Mono&#x27; : &#x27;10px JetBrains Mono&#x27;;
                ctx.fillText(node.label, node.x, node.y + node.radius + 14);
            });

            &#x2F;&#x2F; Animated particles
            if (time % 60 === 0 &amp;&amp; particles.length &lt; 8) {
                const randomFolder = Math.floor(Math.random() * folders.length) + 1;
                const parentNode = nodes[randomFolder];
                if (parentNode) {
                    particles.push({
                        x: nodes[0].x,
                        y: nodes[0].y,
                        targetX: parentNode.x,
                        targetY: parentNode.y,
                        progress: 0,
                        speed: 0.02
                    });
                }
            }

            particles = particles.filter(p =&gt; p.progress &lt; 1);
            particles.forEach(p =&gt; {
                p.progress += p.speed;
                const ease = p.progress * p.progress * (3 - 2 * p.progress);
                const x = p.x + (p.targetX - p.x) * ease;
                const y = p.y + (p.targetY - p.y) * ease;

                ctx.fillStyle = colors.accent;
                ctx.shadowColor = colors.accent;
                ctx.shadowBlur = 10;
                ctx.beginPath();
                ctx.arc(x, y, 4, 0, Math.PI * 2);
                ctx.fill();
                ctx.shadowBlur = 0;
            });

            time++;
            requestAnimationFrame(draw);
        }

        if (!window.matchMedia(&#x27;(prefers-reduced-motion: reduce)&#x27;).matches) {
            draw();
        } else {
            &#x2F;&#x2F; Static version
            const nodes = getNodePositions();
            nodes.forEach(node =&gt; {
                ctx.fillStyle = node.color;
                ctx.beginPath();
                ctx.arc(node.x, node.y, node.radius, 0, Math.PI * 2);
                ctx.fill();

                ctx.fillStyle = colors.text;
                ctx.font = &#x27;10px JetBrains Mono&#x27;;
                ctx.textAlign = &#x27;center&#x27;;
                ctx.fillText(node.label, node.x, node.y + node.radius + 14);
            });
        }
    }

    if (document.readyState === &#x27;loading&#x27;) {
        document.addEventListener(&#x27;DOMContentLoaded&#x27;, initTree);
    } else {
        initTree();
    }
})();
&lt;&#x2F;script&gt;

&lt;style&gt;
.tree-container {
    background: var(--bg-0);
    border: 1px solid var(--divider-color);
    border-radius: 12px;
    padding: 1rem;
    margin: 1.5rem 0;
    position: relative;
}

.tree-canvas {
    width: 100%;
    height: 320px;
    display: block;
}

@media (max-width: 768px) {
    .tree-container {
        overflow-x: auto;
    }

    .tree-canvas {
        min-width: 500px;
    }
}
&lt;&#x2F;style&gt;
&lt;p&gt;Armed with this knowledge, I built my first prototype. It worked—sort of. The commands executed. The agents spawned. And then everything started breaking in ways the documentation didn’t prepare me for.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;act-ii-the-descent&quot;&gt;Act II: The Descent&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;pain-point-1-the-mcp-tool-access-bug&quot;&gt;Pain Point #1: The MCP Tool Access Bug&lt;&#x2F;h3&gt;
&lt;p&gt;My agent-team-creator plugin needed to integrate with Jira. The Atlassian MCP plugin was installed and working beautifully in the main Claude Code session. Following the documentation, I configured my plugin agent to access these MCP tools.&lt;&#x2F;p&gt;
&lt;p&gt;The error was immediate and confusing:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Error: No such tool available: mcp__plugin_atlassian__getJiraIssue
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I spent hours debugging. Was my configuration wrong? Did I misname the tool? Then I found them—four GitHub issues documenting the same problem:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Issue&lt;&#x2F;th&gt;&lt;th&gt;Description&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;#13605&lt;&#x2F;td&gt;&lt;td&gt;Custom plugin subagents cannot access MCP tools&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;#15810&lt;&#x2F;td&gt;&lt;td&gt;Subagents don’t inherit MCP tools from plugin-defined agents&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;#14496&lt;&#x2F;td&gt;&lt;td&gt;Inconsistent MCP access with complex prompts&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;#7296&lt;&#x2F;td&gt;&lt;td&gt;Scope inheritance failure for Task-launched agents&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The documentation said:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“When the tools field is omitted, subagents inherit all MCP tools available to the main thread.”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Reality disagreed. Plugin-defined agents live in a different scope—they can see the MCP tools listed in the main session, but they cannot invoke them.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;strong&gt;★ Teaching Moment: The MCP Scope Reality&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;MCP tools work reliably in two contexts:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The main Claude Code session&lt;&#x2F;li&gt;
&lt;li&gt;Commands (which run in the main session’s scope)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;MCP tools &lt;strong&gt;do not work&lt;&#x2F;strong&gt; in:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Plugin-defined agents spawned via Task tool&lt;&#x2F;li&gt;
&lt;li&gt;Subagents of any kind&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If your plugin needs external service access, your &lt;strong&gt;commands&lt;&#x2F;strong&gt; must handle it, not your agents.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;pain-point-2-three-location-sync-hell&quot;&gt;Pain Point #2: Three-Location Sync Hell&lt;&#x2F;h3&gt;
&lt;p&gt;After modifying my agent definitions, I reloaded Claude Code. My changes weren’t there. I edited again. Still nothing.&lt;&#x2F;p&gt;
&lt;p&gt;It turns out Claude Code plugins exist in three separate locations that must be manually synchronized:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Location&lt;&#x2F;th&gt;&lt;th&gt;Path&lt;&#x2F;th&gt;&lt;th&gt;Purpose&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Marketplace Source&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;~&#x2F;.claude&#x2F;local-marketplace&#x2F;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Where you edit&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Installed Plugin&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;~&#x2F;.claude&#x2F;plugins&#x2F;plugin-name&#x2F;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Where Claude reads&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Cache&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;~&#x2F;.claude&#x2F;plugins&#x2F;cache&#x2F;marketplace&#x2F;plugin&#x2F;version&#x2F;&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Versioned backup&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;There’s no hot reload. There’s no auto-sync. You edit in one place, but Claude reads from another.&lt;&#x2F;p&gt;
&lt;p&gt;The solution? A sync script:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;!&#x2F;bin&#x2F;bash&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;PLUGIN_NAME&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;agent-team-creator&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;MARKETPLACE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;HOME&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;.claude&#x2F;local-marketplace&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;INSTALLED&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;HOME&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;.claude&#x2F;plugins&#x2F;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;PLUGIN_NAME&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;CACHE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;HOME&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;.claude&#x2F;plugins&#x2F;cache&#x2F;local-marketplace&#x2F;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;PLUGIN_NAME&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;1.0.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;rsync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;av&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;MARKETPLACE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;commands&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;INSTALLED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;commands&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;rsync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;av&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;MARKETPLACE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;commands&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;CACHE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;commands&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;rsync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;av&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;MARKETPLACE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;agents&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;INSTALLED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;agents&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;rsync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;av&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;MARKETPLACE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;agents&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;CACHE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;agents&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-echo z-shell&quot;&gt;echo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Plugin synced to all locations&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After every change: sync, quit Claude Code, restart. This became muscle memory.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;strong&gt;★ Teaching Moment: Debugging Your Plugin&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;When things go wrong, these commands are your friends:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; Check if plugin is loaded&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;ls&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-meta z-group z-expansion z-tilde&quot;&gt;&lt;span class=&quot;z-variable z-language z-tilde z-shell&quot;&gt;~&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;.claude&#x2F;plugins&#x2F;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; Verify cache sync&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;diff&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;r&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-expansion z-tilde&quot;&gt;&lt;span class=&quot;z-variable z-language z-tilde z-shell&quot;&gt;~&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;.claude&#x2F;plugins&#x2F;agent-team-creator&#x2F; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;        &lt;span class=&quot;z-meta z-group z-expansion z-tilde&quot;&gt;&lt;span class=&quot;z-variable z-language z-tilde z-shell&quot;&gt;~&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;.claude&#x2F;plugins&#x2F;cache&#x2F;local-marketplace&#x2F;agent-team-creator&#x2F;1.0.0&#x2F;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; Validate marketplace.json syntax&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;cat&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-meta z-group z-expansion z-tilde&quot;&gt;&lt;span class=&quot;z-variable z-language z-tilde z-shell&quot;&gt;~&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;.claude&#x2F;local-marketplace&#x2F;.claude-plugin&#x2F;marketplace.json&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-pipe z-shell&quot;&gt;|&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;jq&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; .&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; View plugin structure&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;tree&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-meta z-group z-expansion z-tilde&quot;&gt;&lt;span class=&quot;z-variable z-language z-tilde z-shell&quot;&gt;~&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;.claude&#x2F;plugins&#x2F;agent-team-creator&#x2F;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;pain-point-3-schema-validation-gotchas&quot;&gt;Pain Point #3: Schema Validation Gotchas&lt;&#x2F;h3&gt;
&lt;p&gt;My first marketplace.json was rejected with cryptic errors:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;owner: Expected object, received string
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;source: Invalid input
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The schema is strict and underdocumented. Here’s what works:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; class=&quot;language-json z-code&quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-begin z-json&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;$schema&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;https:&#x2F;&#x2F;anthropic.com&#x2F;claude-code&#x2F;marketplace.schema.json&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;name&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;local-marketplace&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;description&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Local plugins for Claude Code&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;owner&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-begin z-json&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;name&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Your Name&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;email&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;your@email.com&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;  &lt;span class=&quot;z-punctuation z-section z-mapping z-end z-json&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;plugins&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-sequence z-begin z-json&quot;&gt;[&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;    &lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-begin z-json&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;      &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;name&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;plugin-name&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;      &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;description&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Plugin description&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;      &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;version&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;1.0.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;      &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;author&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-begin z-json&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;        &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;name&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Author Name&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;        &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;email&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;author@email.com&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;      &lt;span class=&quot;z-punctuation z-section z-mapping z-end z-json&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;      &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;source&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;.&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;      &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;category&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;development&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-mapping z-end z-json&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-sequence z-json&quot;&gt;  &lt;span class=&quot;z-punctuation z-section z-sequence z-end z-json&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-end z-json&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Key gotchas:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;owner&lt;&#x2F;code&gt; must be an object with &lt;code&gt;name&lt;&#x2F;code&gt; and &lt;code&gt;email&lt;&#x2F;code&gt;, not a string&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;source&lt;&#x2F;code&gt; must be &lt;code&gt;&quot;.&#x2F;&quot;&lt;&#x2F;code&gt; with the trailing slash&lt;&#x2F;li&gt;
&lt;li&gt;Missing any required field causes silent failures&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;act-iii-the-discovery&quot;&gt;Act III: The Discovery&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;the-documentation-vs-reality-gap&quot;&gt;The Documentation vs. Reality Gap&lt;&#x2F;h3&gt;
&lt;p&gt;The breaking point came when I built an entire multi-agent architecture based on documented behavior—only to have it fail completely.&lt;&#x2F;p&gt;
&lt;p&gt;The docs promised:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“MCP Tools: Subagents can access MCP tools from configured MCP servers.”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I tested extensively. Plugin-defined subagents &lt;strong&gt;cannot&lt;&#x2F;strong&gt; access MCP tools. This isn’t a configuration issue—it’s a known bug tracked across multiple GitHub issues.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The lesson&lt;&#x2F;strong&gt;: Documentation represents &lt;em&gt;intended&lt;&#x2F;em&gt; behavior, not &lt;em&gt;guaranteed&lt;&#x2F;em&gt; behavior. Always validate assumptions empirically before building dependent architectures.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-nesting-wall&quot;&gt;The Nesting Wall&lt;&#x2F;h3&gt;
&lt;p&gt;My original design had agents spawning specialized sub-agents in a recursive tree structure. Elegant in theory. Impossible in practice.&lt;&#x2F;p&gt;
&lt;p&gt;When I tried:&lt;&#x2F;p&gt;





&lt;div class=&quot;blocked-flow-container&quot; id=&quot;blocked-&quot;&gt;
    &lt;canvas class=&quot;blocked-flow-canvas&quot; aria-label=&quot;Flow diagram with blocked step&quot;&gt;&lt;&#x2F;canvas&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    const containerId = &#x27;blocked-&#x27;;
    const nodeNames = [&#x27;User&#x27;, &#x27;Command&#x27;, &#x27;Agent&#x27;, &#x27;SubAgent&#x27;];
    const blockedName = &#x27;SubSubAgent&#x27;;

    function initBlockedFlow() {
        const container = document.getElementById(containerId);
        if (!container) return;

        const canvas = container.querySelector(&#x27;.blocked-flow-canvas&#x27;);
        const ctx = canvas.getContext(&#x27;2d&#x27;);

        let particles = [];
        let time = 0;
        let pulsePhase = 0;

        const colors = {
            nodes: [&#x27;#ff0080&#x27;, &#x27;#00d4ff&#x27;, &#x27;#00ff88&#x27;, &#x27;#8b5cf6&#x27;],
            blocked: &#x27;#ff4444&#x27;,
            blockedBg: &#x27;#442222&#x27;,
            particle: &#x27;#00ff88&#x27;,
            connection: &#x27;rgba(0, 212, 255, 0.4)&#x27;,
            blockedConnection: &#x27;rgba(255, 68, 68, 0.5)&#x27;,
            text: &#x27;#e0e0e4&#x27;
        };

        function resize() {
            const rect = container.getBoundingClientRect();
            canvas.width = rect.width;
            canvas.height = 180;
        }
        resize();
        window.addEventListener(&#x27;resize&#x27;, resize);

        function getNodePositions() {
            const allNodes = [...nodeNames, blockedName];
            const margin = 60;
            const spacing = (canvas.width - margin * 2) &#x2F; (allNodes.length - 1);
            const y = canvas.height &#x2F; 2;

            return allNodes.map((name, i) =&gt; ({
                label: name,
                x: margin + i * spacing,
                y: y,
                radius: 26,
                isBlocked: i === allNodes.length - 1,
                color: i &lt; nodeNames.length ? colors.nodes[i % colors.nodes.length] : colors.blockedBg
            }));
        }

        function draw() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            const nodes = getNodePositions();

            pulsePhase += 0.05;

            &#x2F;&#x2F; Draw connections
            for (let i = 0; i &lt; nodes.length - 1; i++) {
                const from = nodes[i];
                const to = nodes[i + 1];
                const isBlockedConnection = to.isBlocked;

                ctx.beginPath();
                ctx.moveTo(from.x + from.radius, from.y);
                ctx.lineTo(to.x - to.radius, to.y);

                if (isBlockedConnection) {
                    ctx.strokeStyle = colors.blockedConnection;
                    ctx.setLineDash([8, 4]);
                } else {
                    ctx.strokeStyle = colors.connection;
                    ctx.setLineDash([]);
                }
                ctx.lineWidth = 3;
                ctx.stroke();
                ctx.setLineDash([]);

                &#x2F;&#x2F; Arrow
                if (!isBlockedConnection) {
                    const midX = (from.x + to.x) &#x2F; 2;
                    ctx.fillStyle = colors.connection;
                    ctx.beginPath();
                    ctx.moveTo(midX - 5, from.y - 6);
                    ctx.lineTo(midX + 8, from.y);
                    ctx.lineTo(midX - 5, from.y + 6);
                    ctx.closePath();
                    ctx.fill();
                }
            }

            &#x2F;&#x2F; Draw &quot;BLOCKED&quot; label on the blocked connection
            const lastNormal = nodes[nodes.length - 2];
            const blocked = nodes[nodes.length - 1];
            const midX = (lastNormal.x + blocked.x) &#x2F; 2;

            ctx.save();
            ctx.fillStyle = colors.blocked;
            ctx.font = &#x27;bold 11px JetBrains Mono&#x27;;
            ctx.textAlign = &#x27;center&#x27;;

            &#x2F;&#x2F; Pulsing X
            const pulse = Math.sin(pulsePhase) * 0.3 + 1;
            ctx.font = `bold ${14 * pulse}px JetBrains Mono`;
            ctx.fillText(&#x27;❌&#x27;, midX, nodes[0].y - 20);

            ctx.font = &#x27;bold 10px JetBrains Mono&#x27;;
            ctx.fillText(&#x27;BLOCKED&#x27;, midX, nodes[0].y + 32);
            ctx.restore();

            &#x2F;&#x2F; Draw nodes
            nodes.forEach((node, i) =&gt; {
                if (node.isBlocked) {
                    &#x2F;&#x2F; Blocked node - pulsing red border
                    ctx.shadowColor = colors.blocked;
                    ctx.shadowBlur = 10 + Math.sin(pulsePhase) * 5;

                    ctx.fillStyle = node.color;
                    ctx.beginPath();
                    ctx.arc(node.x, node.y, node.radius, 0, Math.PI * 2);
                    ctx.fill();

                    ctx.strokeStyle = colors.blocked;
                    ctx.lineWidth = 3;
                    ctx.setLineDash([4, 4]);
                    ctx.stroke();
                    ctx.setLineDash([]);

                    ctx.shadowBlur = 0;

                    &#x2F;&#x2F; Strikethrough effect
                    ctx.strokeStyle = colors.blocked;
                    ctx.lineWidth = 2;
                    ctx.beginPath();
                    ctx.moveTo(node.x - node.radius + 5, node.y - node.radius + 5);
                    ctx.lineTo(node.x + node.radius - 5, node.y + node.radius - 5);
                    ctx.stroke();
                } else {
                    &#x2F;&#x2F; Normal node
                    ctx.shadowColor = node.color;
                    ctx.shadowBlur = 15;

                    ctx.fillStyle = node.color;
                    ctx.beginPath();
                    ctx.arc(node.x, node.y, node.radius, 0, Math.PI * 2);
                    ctx.fill();

                    ctx.shadowBlur = 0;

                    ctx.strokeStyle = &#x27;#00ff88&#x27;;
                    ctx.lineWidth = 2;
                    ctx.stroke();
                }

                &#x2F;&#x2F; Label
                ctx.fillStyle = node.isBlocked ? &#x27;#666&#x27; : &#x27;#0a0a0f&#x27;;
                ctx.font = &#x27;bold 10px JetBrains Mono&#x27;;
                ctx.textAlign = &#x27;center&#x27;;
                ctx.textBaseline = &#x27;middle&#x27;;

                &#x2F;&#x2F; Wrap text if needed
                const words = node.label.split(&#x2F;(?=[A-Z])&#x2F;);
                if (words.length &gt; 1 &amp;&amp; node.label.length &gt; 8) {
                    ctx.fillText(words[0], node.x, node.y - 6);
                    ctx.fillText(words.slice(1).join(&#x27;&#x27;), node.x, node.y + 6);
                } else {
                    ctx.fillText(node.label, node.x, node.y);
                }
            });

            &#x2F;&#x2F; Particles (only on valid connections)
            particles.forEach(p =&gt; {
                p.progress += p.speed;
                if (p.progress &gt;= 1) {
                    p.segmentIndex++;
                    p.progress = 0;
                    if (p.segmentIndex &gt;= nodes.length - 2) {
                        p.segmentIndex = 0;
                    }
                }

                const from = nodes[p.segmentIndex];
                const to = nodes[p.segmentIndex + 1];

                if (from &amp;&amp; to &amp;&amp; !to.isBlocked) {
                    const ease = p.progress * p.progress * (3 - 2 * p.progress);
                    const x = from.x + (to.x - from.x) * ease;
                    const y = from.y + (to.y - from.y) * ease;

                    ctx.fillStyle = colors.particle;
                    ctx.shadowColor = colors.particle;
                    ctx.shadowBlur = 10;
                    ctx.beginPath();
                    ctx.arc(x, y, 4, 0, Math.PI * 2);
                    ctx.fill();
                    ctx.shadowBlur = 0;
                }
            });

            time++;
            requestAnimationFrame(draw);
        }

        &#x2F;&#x2F; Initialize particles
        for (let i = 0; i &lt; 2; i++) {
            particles.push({
                segmentIndex: i,
                progress: 0,
                speed: 0.015
            });
        }

        if (!window.matchMedia(&#x27;(prefers-reduced-motion: reduce)&#x27;).matches) {
            draw();
        } else {
            &#x2F;&#x2F; Static version
            const nodes = getNodePositions();
            nodes.forEach(node =&gt; {
                ctx.fillStyle = node.color;
                ctx.beginPath();
                ctx.arc(node.x, node.y, node.radius, 0, Math.PI * 2);
                ctx.fill();

                ctx.fillStyle = node.isBlocked ? &#x27;#666&#x27; : &#x27;#0a0a0f&#x27;;
                ctx.font = &#x27;bold 10px JetBrains Mono&#x27;;
                ctx.textAlign = &#x27;center&#x27;;
                ctx.fillText(node.label, node.x, node.y);
            });
        }
    }

    if (document.readyState === &#x27;loading&#x27;) {
        document.addEventListener(&#x27;DOMContentLoaded&#x27;, initBlockedFlow);
    } else {
        initBlockedFlow();
    }
})();
&lt;&#x2F;script&gt;

&lt;style&gt;
.blocked-flow-container {
    background: var(--bg-0);
    border: 1px solid var(--divider-color);
    border-radius: 12px;
    padding: 1rem;
    margin: 1.5rem 0;
    position: relative;
}

.blocked-flow-canvas {
    width: 100%;
    height: 180px;
    display: block;
}

@media (max-width: 768px) {
    .blocked-flow-container {
        overflow-x: auto;
    }

    .blocked-flow-canvas {
        min-width: 500px;
    }
}
&lt;&#x2F;style&gt;
&lt;p&gt;Claude Code responded:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Error: Subagents cannot spawn subagents
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a hard platform limit. Single-level nesting only. The constraint exists for good reasons—preventing infinite recursion, maintaining bounded resource consumption, ensuring predictable execution. But it invalidated my entire architecture.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;model-inheritance-that-doesn-t-inherit&quot;&gt;Model Inheritance That Doesn’t Inherit&lt;&#x2F;h3&gt;
&lt;p&gt;I configured my agents to use &lt;code&gt;model: inherit&lt;&#x2F;code&gt;, expecting them to use whatever model the parent session used. Every single subagent defaulted to Sonnet 4, regardless of:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Parent model&lt;&#x2F;li&gt;
&lt;li&gt;Global settings&lt;&#x2F;li&gt;
&lt;li&gt;Local settings&lt;&#x2F;li&gt;
&lt;li&gt;Explicit agent configuration&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Another discovery: Claude Code infers agent behavior from naming. An agent named “code-reviewer” triggers built-in review behaviors that may override your custom instructions. Naming isn’t just labeling—it’s functional.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;act-iv-the-solution&quot;&gt;Act IV: The Solution&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;the-hybrid-architecture-pattern&quot;&gt;The Hybrid Architecture Pattern&lt;&#x2F;h3&gt;
&lt;p&gt;Constraints breed creativity. Facing MCP access bugs, nesting limits, and model inheritance failures, I developed what I now call the &lt;strong&gt;Hybrid Architecture Pattern&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The core insight: &lt;strong&gt;Commands and Agents have different capabilities. Use each for what it does well.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Command Layer (I&#x2F;O)&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;MCP tool access (works reliably)&lt;&#x2F;li&gt;
&lt;li&gt;File system operations&lt;&#x2F;li&gt;
&lt;li&gt;User interaction (AskUserQuestion)&lt;&#x2F;li&gt;
&lt;li&gt;Response caching&lt;&#x2F;li&gt;
&lt;li&gt;External service communication&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Agent Layer (Intelligence)&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Pure reasoning and analysis&lt;&#x2F;li&gt;
&lt;li&gt;Content formatting&lt;&#x2F;li&gt;
&lt;li&gt;Decision making&lt;&#x2F;li&gt;
&lt;li&gt;Pattern recognition&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;No direct I&#x2F;O dependencies&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Commands become the I&#x2F;O adapters. Agents become the reasoning engines. Neither tries to do the other’s job.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-6-phase-pipeline&quot;&gt;The 6-Phase Pipeline&lt;&#x2F;h3&gt;
&lt;p&gt;Here’s how this plays out in my &lt;code&gt;&#x2F;generate-jira-task&lt;&#x2F;code&gt; command:&lt;&#x2F;p&gt;



&lt;div class=&quot;pipeline-container&quot; id=&quot;pipeline&quot;&gt;
    &lt;canvas class=&quot;pipeline-canvas&quot; aria-label=&quot;Pipeline flow visualization&quot;&gt;&lt;&#x2F;canvas&gt;
    &lt;div class=&quot;pipeline-legend&quot;&gt;
        &lt;span class=&quot;legend-item&quot;&gt;&lt;span class=&quot;legend-dot command&quot;&gt;&lt;&#x2F;span&gt; Command (I&#x2F;O)&lt;&#x2F;span&gt;
        &lt;span class=&quot;legend-item&quot;&gt;&lt;span class=&quot;legend-dot agent&quot;&gt;&lt;&#x2F;span&gt; Agent (Intelligence)&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    const containerId = &#x27;pipeline&#x27;;
    const phasesData = [
    {&quot;phase&quot;: 0, &quot;owner&quot;: &quot;Command&quot;, &quot;label&quot;: &quot;MCP Check&quot;, &quot;io&quot;: &quot;external&quot;},
    {&quot;phase&quot;: 1, &quot;owner&quot;: &quot;Command&quot;, &quot;label&quot;: &quot;Project Resolve&quot;, &quot;io&quot;: &quot;external&quot;},
    {&quot;phase&quot;: 2, &quot;owner&quot;: &quot;Command&quot;, &quot;label&quot;: &quot;Load Report&quot;, &quot;io&quot;: &quot;local&quot;},
    {&quot;phase&quot;: 3, &quot;owner&quot;: &quot;Command&quot;, &quot;label&quot;: &quot;Dup Check&quot;, &quot;io&quot;: &quot;external&quot;},
    {&quot;phase&quot;: 4, &quot;owner&quot;: &quot;Agent&quot;, &quot;label&quot;: &quot;Reasoning&quot;, &quot;io&quot;: &quot;none&quot;},
    {&quot;phase&quot;: 5, &quot;owner&quot;: &quot;Agent&quot;, &quot;label&quot;: &quot;Formatting&quot;, &quot;io&quot;: &quot;none&quot;},
    {&quot;phase&quot;: 6, &quot;owner&quot;: &quot;Command&quot;, &quot;label&quot;: &quot;Output&quot;, &quot;io&quot;: &quot;external&quot;}
];

    function initPipeline() {
        const container = document.getElementById(containerId);
        if (!container) return;

        const canvas = container.querySelector(&#x27;.pipeline-canvas&#x27;);
        const ctx = canvas.getContext(&#x27;2d&#x27;);

        &#x2F;&#x2F; Responsive sizing
        function resize() {
            const rect = container.getBoundingClientRect();
            canvas.width = rect.width;
            canvas.height = 180;
        }
        resize();
        window.addEventListener(&#x27;resize&#x27;, resize);

        &#x2F;&#x2F; Colors
        const colors = {
            command: &#x27;#00d4ff&#x27;,
            agent: &#x27;#00ff88&#x27;,
            external: &#x27;#8b5cf6&#x27;,
            local: &#x27;#ff8800&#x27;,
            none: &#x27;#444466&#x27;,
            particle: &#x27;#00ff88&#x27;,
            bg: &#x27;rgba(10, 10, 15, 0.8)&#x27;
        };

        &#x2F;&#x2F; Animation state
        let particles = [];
        let time = 0;

        &#x2F;&#x2F; Get phase positions
        function getPhasePositions() {
            const phases = phasesData;
            const margin = 60;
            const spacing = (canvas.width - margin * 2) &#x2F; (phases.length - 1);
            return phases.map((p, i) =&gt; ({
                ...p,
                x: margin + i * spacing,
                y: canvas.height &#x2F; 2,
                radius: 24
            }));
        }

        &#x2F;&#x2F; Create particle
        function createParticle(positions) {
            return {
                phaseIndex: 0,
                progress: 0,
                speed: 0.01 + Math.random() * 0.01,
                x: positions[0].x,
                y: positions[0].y
            };
        }

        &#x2F;&#x2F; Draw
        function draw() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            const positions = getPhasePositions();

            &#x2F;&#x2F; Draw connections
            ctx.lineWidth = 2;
            ctx.strokeStyle = &#x27;rgba(0, 212, 255, 0.3)&#x27;;
            ctx.beginPath();
            positions.forEach((pos, i) =&gt; {
                if (i === 0) ctx.moveTo(pos.x, pos.y);
                else ctx.lineTo(pos.x, pos.y);
            });
            ctx.stroke();

            &#x2F;&#x2F; Draw arrows
            for (let i = 0; i &lt; positions.length - 1; i++) {
                const from = positions[i];
                const to = positions[i + 1];
                const midX = (from.x + to.x) &#x2F; 2;
                const midY = (from.y + to.y) &#x2F; 2;

                ctx.fillStyle = &#x27;rgba(0, 212, 255, 0.5)&#x27;;
                ctx.beginPath();
                ctx.moveTo(midX - 6, midY - 4);
                ctx.lineTo(midX + 6, midY);
                ctx.lineTo(midX - 6, midY + 4);
                ctx.closePath();
                ctx.fill();
            }

            &#x2F;&#x2F; Draw phase nodes
            positions.forEach((pos, i) =&gt; {
                const isCommand = pos.owner === &#x27;Command&#x27;;
                const color = isCommand ? colors.command : colors.agent;

                &#x2F;&#x2F; Glow
                const gradient = ctx.createRadialGradient(pos.x, pos.y, 0, pos.x, pos.y, pos.radius * 2);
                gradient.addColorStop(0, color.replace(&#x27;)&#x27;, &#x27;, 0.3)&#x27;).replace(&#x27;rgb&#x27;, &#x27;rgba&#x27;));
                gradient.addColorStop(1, &#x27;transparent&#x27;);
                ctx.fillStyle = gradient;
                ctx.beginPath();
                ctx.arc(pos.x, pos.y, pos.radius * 2, 0, Math.PI * 2);
                ctx.fill();

                &#x2F;&#x2F; Node
                ctx.fillStyle = color;
                ctx.beginPath();
                ctx.arc(pos.x, pos.y, pos.radius, 0, Math.PI * 2);
                ctx.fill();

                &#x2F;&#x2F; Phase number
                ctx.fillStyle = &#x27;#0a0a0f&#x27;;
                ctx.font = &#x27;bold 14px JetBrains Mono, monospace&#x27;;
                ctx.textAlign = &#x27;center&#x27;;
                ctx.textBaseline = &#x27;middle&#x27;;
                ctx.fillText(pos.phase, pos.x, pos.y);

                &#x2F;&#x2F; Label
                ctx.fillStyle = &#x27;#e0e0e4&#x27;;
                ctx.font = &#x27;11px JetBrains Mono, monospace&#x27;;
                ctx.fillText(pos.label, pos.x, pos.y + pos.radius + 16);

                &#x2F;&#x2F; I&#x2F;O indicator
                if (pos.io !== &#x27;none&#x27;) {
                    ctx.fillStyle = pos.io === &#x27;external&#x27; ? colors.external : colors.local;
                    ctx.font = &#x27;9px JetBrains Mono, monospace&#x27;;
                    ctx.fillText(pos.io.toUpperCase(), pos.x, pos.y - pos.radius - 10);
                }
            });

            &#x2F;&#x2F; Update and draw particles
            particles.forEach(p =&gt; {
                if (p.phaseIndex &gt;= positions.length - 1) {
                    p.phaseIndex = 0;
                    p.progress = 0;
                }

                const from = positions[p.phaseIndex];
                const to = positions[p.phaseIndex + 1];

                p.progress += p.speed;
                if (p.progress &gt;= 1) {
                    p.phaseIndex++;
                    p.progress = 0;
                }

                if (to) {
                    p.x = from.x + (to.x - from.x) * p.progress;
                    p.y = from.y + (to.y - from.y) * p.progress;
                }

                &#x2F;&#x2F; Draw particle
                ctx.fillStyle = colors.particle;
                ctx.beginPath();
                ctx.arc(p.x, p.y, 4, 0, Math.PI * 2);
                ctx.fill();

                &#x2F;&#x2F; Particle glow
                const pGrad = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, 12);
                pGrad.addColorStop(0, &#x27;rgba(0, 255, 136, 0.4)&#x27;);
                pGrad.addColorStop(1, &#x27;transparent&#x27;);
                ctx.fillStyle = pGrad;
                ctx.beginPath();
                ctx.arc(p.x, p.y, 12, 0, Math.PI * 2);
                ctx.fill();
            });

            time++;
            requestAnimationFrame(draw);
        }

        &#x2F;&#x2F; Initialize particles
        const positions = getPhasePositions();
        for (let i = 0; i &lt; 3; i++) {
            const p = createParticle(positions);
            p.phaseIndex = i * 2;
            particles.push(p);
        }

        &#x2F;&#x2F; Respect reduced motion
        if (!window.matchMedia(&#x27;(prefers-reduced-motion: reduce)&#x27;).matches) {
            draw();
        } else {
            &#x2F;&#x2F; Static version
            const positions = getPhasePositions();
            ctx.clearRect(0, 0, canvas.width, canvas.height);

            ctx.lineWidth = 2;
            ctx.strokeStyle = &#x27;rgba(0, 212, 255, 0.5)&#x27;;
            ctx.beginPath();
            positions.forEach((pos, i) =&gt; {
                if (i === 0) ctx.moveTo(pos.x, pos.y);
                else ctx.lineTo(pos.x, pos.y);
            });
            ctx.stroke();

            positions.forEach((pos) =&gt; {
                const color = pos.owner === &#x27;Command&#x27; ? colors.command : colors.agent;
                ctx.fillStyle = color;
                ctx.beginPath();
                ctx.arc(pos.x, pos.y, pos.radius, 0, Math.PI * 2);
                ctx.fill();

                ctx.fillStyle = &#x27;#0a0a0f&#x27;;
                ctx.font = &#x27;bold 14px JetBrains Mono, monospace&#x27;;
                ctx.textAlign = &#x27;center&#x27;;
                ctx.textBaseline = &#x27;middle&#x27;;
                ctx.fillText(pos.phase, pos.x, pos.y);

                ctx.fillStyle = &#x27;#e0e0e4&#x27;;
                ctx.font = &#x27;11px JetBrains Mono, monospace&#x27;;
                ctx.fillText(pos.label, pos.x, pos.y + pos.radius + 16);
            });
        }
    }

    if (document.readyState === &#x27;loading&#x27;) {
        document.addEventListener(&#x27;DOMContentLoaded&#x27;, initPipeline);
    } else {
        initPipeline();
    }
})();
&lt;&#x2F;script&gt;

&lt;style&gt;
.pipeline-container {
    background: var(--bg-0);
    border: 1px solid var(--divider-color);
    border-radius: 12px;
    padding: 1.5rem 1rem 1rem;
    margin: 1.5rem 0;
    position: relative;
}

.pipeline-canvas {
    width: 100%;
    height: 180px;
    display: block;
}

.pipeline-legend {
    display: flex;
    justify-content: center;
    gap: 2rem;
    margin-top: 0.5rem;
    font-family: &#x27;JetBrains Mono&#x27;, monospace;
    font-size: 0.8rem;
    color: var(--meta-color);
}

.legend-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.legend-dot {
    width: 12px;
    height: 12px;
    border-radius: 50%;
}

.legend-dot.command {
    background: #00d4ff;
}

.legend-dot.agent {
    background: #00ff88;
}

@media (max-width: 768px) {
    .pipeline-container {
        overflow-x: auto;
    }

    .pipeline-canvas {
        min-width: 600px;
    }
}
&lt;&#x2F;style&gt;
&lt;p&gt;Commands handle all external communication (cyan nodes). Agents handle all thinking (green nodes). The boundary is clean—notice how I&#x2F;O operations (marked EXTERNAL&#x2F;LOCAL) cluster at the Command layer.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;graceful-degradation&quot;&gt;Graceful Degradation&lt;&#x2F;h3&gt;
&lt;p&gt;What if MCP isn’t available? The pattern handles this elegantly:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;FALLBACK_MODE activates when:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  - Atlassian MCP plugin unavailable
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Actions:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  - Skip Phase 1 (project resolution)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  - Skip Phase 3 (duplicate check)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  - Phase 6: Output markdown to .claude&#x2F;reports&#x2F;jira-drafts&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The intelligence layer (Phases 4-5) works identically whether connected to Jira or not. The I&#x2F;O layer gracefully degrades to local file output.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;strong&gt;★ Teaching Moment: Command and Agent Frontmatter&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Command Template&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-other z-document z-begin z-yaml&quot;&gt;---&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;generate-jira-task&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;description&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Generate Jira task from debugging report&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;allowed-tools&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Read&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Write&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Glob&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Grep&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Task&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;AskUserQuestion&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;argument-hint&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;[report-file]&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-other z-document z-begin z-yaml&quot;&gt;---&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Agent Template&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-other z-document z-begin z-yaml&quot;&gt;---&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;implementation-planner&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;description&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-block-scalar z-literal z-yaml&quot;&gt;|&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;  Use this agent to analyze debugging reports and create implementation plans.
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;model&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;inherit&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;color&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;cyan&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;tools&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Read&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Grep&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Glob&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-other z-document z-begin z-yaml&quot;&gt;---&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note: Agents should &lt;strong&gt;not&lt;&#x2F;strong&gt; include MCP tools in their tools list—they won’t work anyway.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;act-v-the-return&quot;&gt;Act V: The Return&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;what-works-now&quot;&gt;What Works Now&lt;&#x2F;h3&gt;
&lt;p&gt;The agent-team-creator plugin now functions reliably with three commands:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&#x2F;generate-agent-team&lt;&#x2F;code&gt; - Analyzes codebases and generates specialized agents&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;generate-debugger&lt;&#x2F;code&gt; - Creates project-specific debugging agents&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;generate-jira-task&lt;&#x2F;code&gt; - Converts debugging reports to Jira tasks&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Each follows the Hybrid Architecture Pattern. Commands handle I&#x2F;O. Agents handle reasoning. The system degrades gracefully when services are unavailable.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;lessons-learned&quot;&gt;Lessons Learned&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Lesson&lt;&#x2F;th&gt;&lt;th&gt;Implication&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Trust but verify documentation&lt;&#x2F;td&gt;&lt;td&gt;Build minimal proofs-of-concept before committing to architectures&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Constraints reveal clarity&lt;&#x2F;td&gt;&lt;td&gt;The hybrid pattern is cleaner than my original unconstrained design&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Sync is your responsibility&lt;&#x2F;td&gt;&lt;td&gt;Automate it. Make it muscle memory.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Naming is functional&lt;&#x2F;td&gt;&lt;td&gt;Agent names influence platform behavior&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Explicit over implicit&lt;&#x2F;td&gt;&lt;td&gt;Never assume tool inheritance; declare everything&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;quick-start-checklist-for-new-plugin-developers&quot;&gt;Quick-Start Checklist for New Plugin Developers&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Setup&lt;&#x2F;strong&gt;: Create marketplace structure with proper JSON schema&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Develop&lt;&#x2F;strong&gt;: Edit files in marketplace source only&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Sync&lt;&#x2F;strong&gt;: Run rsync script after every change&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Restart&lt;&#x2F;strong&gt;: Quit and restart Claude Code (no hot reload)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Test&lt;&#x2F;strong&gt;: Verify command availability with &lt;code&gt;&#x2F;help&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Debug&lt;&#x2F;strong&gt;: Use &lt;code&gt;diff -r&lt;&#x2F;code&gt; and &lt;code&gt;jq&lt;&#x2F;code&gt; for validation&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The key lesson: &lt;strong&gt;Commands for I&#x2F;O, Agents for reasoning&lt;&#x2F;strong&gt;. This pattern works around every bug I encountered.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Building agent-team-creator taught me more about AI agent architecture than any documentation could. The bugs weren’t obstacles—they were teachers. The constraints weren’t limitations—they were design principles in disguise.&lt;&#x2F;p&gt;
&lt;p&gt;The Hybrid Architecture Pattern emerged from necessity, but I now believe it’s superior to unconstrained designs. Clear boundaries between I&#x2F;O and intelligence layers make systems easier to test, debug, and extend. Graceful degradation becomes natural when you’ve already separated concerns.&lt;&#x2F;p&gt;
&lt;p&gt;In Part 2 of this series, I’ll step back from the practical details and examine what these discoveries reveal about agent framework design more broadly. Why do inheritance models break down in multi-agent systems? What makes the hub-and-spoke topology emerge naturally? And what does naming-as-behavior tell us about AI systems in general?&lt;&#x2F;p&gt;
&lt;p&gt;For now, if you’re building Claude Code plugins: embrace the constraints. They’ll teach you things the documentation can’t.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;get-the-plugin&quot;&gt;Get the Plugin&lt;&#x2F;h2&gt;
&lt;p&gt;The plugin is open source: &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Cpicon&#x2F;claude-code-plugins&quot;&gt;Cpicon&#x2F;claude-code-plugins&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Use the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Cpicon&#x2F;claude-code-plugins&#x2F;issues&quot;&gt;GitHub Issues&lt;&#x2F;a&gt; tab to request features, report bugs, or discuss improvements.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;strong&gt;Series Navigation:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Part 0&lt;&#x2F;strong&gt;: &lt;a href=&quot;&#x2F;posts&#x2F;claude-code-plugin-journey-part0&#x2F;&quot;&gt;Agent Team Creator&lt;&#x2F;a&gt; — What the plugin does and how to use it&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Part 1&lt;&#x2F;strong&gt; (You are here): Building the plugin, lessons learned&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Part 2&lt;&#x2F;strong&gt;: &lt;a href=&quot;&#x2F;posts&#x2F;claude-code-plugin-journey-part2&#x2F;&quot;&gt;The Inheritance Paradox&lt;&#x2F;a&gt; — Research insights, patterns&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;This post is based on empirical observations from building the agent-team-creator plugin. All pain points and solutions were documented through real development sessions.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        <summary type="html">The Hybrid Architecture Pattern: Lessons from agent-team-creator

This is Part 1 of a three-part series. Start with Part 0: Agent Team Creator to see what the plugin does, or continue here for the development journey.

I thought building a Claude Code plugin would take a weekend. Three days into wrestling with MCP tool access bugs, three-location file synchronization, and documentation that promised features that didn’t work, I realized I was building something more valuable than a plugin—I was mapping uncharted territory.
This is the story of building agent-team-creator, a Claude Code plugin that analyzes codebases and generates project-specific AI agents. Along the way, I discovered a pattern that turned platform limitations into architectural clarity: the Hybrid Architecture Pattern.
…</summary>
        </entry>
</feed>
