<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Ketan Damle on Medium]]></title>
        <description><![CDATA[Stories by Ketan Damle on Medium]]></description>
        <link>https://medium.com/@koriigami?source=rss-c2491c06adc7------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*9mNi0Cab1GB7gaM0d0OkNw.jpeg</url>
            <title>Stories by Ketan Damle on Medium</title>
            <link>https://medium.com/@koriigami?source=rss-c2491c06adc7------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 01:55:56 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@koriigami/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[My Skills Became an Open Standard the Same Week I Archived Them]]></title>
            <link>https://medium.com/@koriigami/my-skills-became-an-open-standard-the-same-week-i-archived-them-6a4a2bb965b1?source=rss-c2491c06adc7------2</link>
            <guid isPermaLink="false">https://medium.com/p/6a4a2bb965b1</guid>
            <category><![CDATA[developer-tools]]></category>
            <category><![CDATA[open-source]]></category>
            <category><![CDATA[productivity]]></category>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[claude-code]]></category>
            <dc:creator><![CDATA[Ketan Damle]]></dc:creator>
            <pubDate>Sat, 31 Oct 2026 04:31:02 GMT</pubDate>
            <atom:updated>2026-10-31T04:31:02.795Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*A81L3KboBhpmWUTtWyl1kQ.png" /></figure><h4><strong>Agent Skills moved to the Linux Foundation. Here’s which of my SKILL.md files survived, and why most of them didn’t.</strong></h4><p>On 22 October, Anthropic handed Agent Skills to the Agentic AI Foundation, the Linux Foundation project that already looks after MCP and AGENTS.md. SKILL.md stopped being one company’s file format and became an open standard.</p><p>Eight days later, I moved three of my own skills into a folder called skills-archive.</p><p>That timing looks like bad luck. It isn’t. The standard and my archive folder are answering the same question: what is a skill actually for, now that the models are this good?</p><h3>What actually changed on 22 October</h3><p>Less than the headlines suggest, and that’s the point.</p><p>According to <a href="https://winbuzzer.com/2026/10/27/anthropics-ai-workflow-standard-joins-the-linux-foundation-xcxwbn/">coverage of the announcement</a>, the donation covers the Agent Skills name, logo, GitHub organisation and the agentskills.io domain. Anthropic says more than 70 agent platforms already read the format, including ChatGPT, Cursor, GitHub Copilot and VS Code. Your existing SKILL.md files keep working. Nobody has to join anything to use them.</p><p>The format itself is small. A skill is a folder with a SKILL.md file in it, plus optional scripts and reference files. The <a href="https://agentskills.io/specification">specification</a> requires two frontmatter fields, name and description. An agent loads only those two at startup and reads the rest of the file when a task matches.</p><p>So the news isn’t “skills got better”. It’s “skills now belong to everyone, so whatever you put in them should be worth carrying between tools”. That made me look hard at mine.</p><h3>Why I wrote skills in the first place</h3><p>I didn’t write skills because they were elegant. I wrote them because I was tired.</p><p>Earlier models had much less context and much less memory. Every time I wanted to turn a draft into an X thread, or an article into an Instagram carousel, I had to explain the whole workflow again: the format, the voice, the file paths, the rules I’d learned the hard way. Putting it all in CLAUDE.md wasn’t enough to make it stick.</p><p>So I wrote it down as skills. Lots of it.</p><p>By June I had three content skills doing most of the work:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nU4kGRt3PC7UmWNl7FwC0g.png" /></figure><p>That’s about 11,500 words of instructions. The writing skill even chained into the others: its step 5.7 offered to run the Instagram skill when the Reddit posts were done. I had built a workflow engine out of markdown files, because the model couldn’t hold the workflow in its head.</p><h3>What changed: the model can hold the workflow now</h3><p>I now run Opus 5.5 on high effort as the orchestrator. It plans, makes the design calls, and keeps track of what happens next. It holds a whole content workflow in context without me spelling it out step by step.</p><p>When I restructured my content folder this week, the 11,500 words of skills turned into two short documents: a strategy file (who I write for, what channels I use, how often) and a CLAUDE.md that explains where things live. The model reads those, asks me what it needs, and does the rest.</p><p>The skills had been doing two different jobs, and I hadn’t noticed:</p><ol><li><strong>Remembering the workflow.</strong> Which step comes next, what the output should look like, what to check.</li><li><strong>Doing a repeatable job.</strong> Producing the same kind of output, the same way, every time.</li></ol><p>A strong orchestrator makes the first job unnecessary. It doesn’t make the second one go away.</p><h3>The skills that stay</h3><p>Most of the skills I still use do implementation work: building and updating parts of a project, or updating the artifacts I track my work in. I run most of them on Sonnet 5.5, not Opus.</p><p>That’s the split that makes sense to me now:</p><ul><li><strong>Opus 5.5, no skill:</strong> planning, judgment, design decisions, deciding what to do next. These change every time, so writing them down as fixed steps makes them worse.</li><li><strong>Sonnet 5.5, with a skill:</strong> jobs where I already know exactly what “done” looks like. The skill is a recipe, and a cheaper, faster model follows a good recipe just fine.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TMk8z0NNpjkAl0ljRzO5Sg.png" /><figcaption><strong>Opus 5.5 on high effort plans and decides with no skill, then hands off to Sonnet 5.5, which runs skills like /radar, implementation tasks and artifact updates</strong></figcaption></figure><p>The one new skill I wrote this week fits that pattern. It’s called /radar: it scans recent news for my content pillars, writes a dated note in a fixed format, and suggests what&#39;s worth posting about. Same inputs, same output shape, twice a week. That&#39;s a skill.</p><p>Deciding which of those news items is worth an article, and what I actually think about it? That’s not a skill. That’s me and the orchestrator.</p><h3>Checking my files against the standard</h3><p>If skills are now portable, the ones I keep should follow the spec. So I checked my three archived skills against it.</p><p>Only one of the three was clean. koriigami-write-article uses just name and description, which is exactly what the spec asks for.</p><p>The other two had habits I’d picked up along the way:</p><ul><li>koriigami-post-x lists allowed-tools as a YAML list. The spec describes it as a space-separated string, and marks the field as experimental.</li><li>koriigami-post-instagram-kagadmodyaa adds its own top-level type and version fields. The spec has a metadata block for extra information like that. It&#39;s also 805 lines long, where the spec recommends keeping SKILL.md under 500 and moving detail into separate reference files.</li></ul><p>None of this broke anything in Claude, which is part of the problem. A tool that tolerates your quirks doesn’t tell you they’re quirks.</p><p>I should be honest about the bigger gap. I’ve only ever run my skills in Claude. I haven’t loaded one in Codex, Cursor or anything else, so I can’t tell you what transfers cleanly and what doesn’t. That’s the next thing I’m testing, with /radarfirst, because it&#39;s small and I use it every week.</p><h3>What I’m changing</h3><ol><li><strong>Workflow and judgment go in plain documents, not skills.</strong> A strategy file and CLAUDE.md, read by a model that’s good enough to use them.</li><li><strong>Skills are for repeatable jobs.</strong> If I can’t describe what “done” looks like in advance, it isn’t a skill yet.</li><li><strong>Repeatable jobs run on Sonnet 5.5.</strong> Opus plans; Sonnet executes the recipe.</li><li><strong>Every skill I keep follows the spec.</strong> name and description up front, anything extra under metadata.</li><li><strong>No portability claims until I’ve tested one.</strong> If a skill only works in one tool, it’s a prompt with a filename.</li></ol><p>The standard didn’t make my old skills obsolete. Better models did. What the standard did was make me ask which of my skills I’d bother taking with me to another tool. For most of them, the honest answer was none. For the few that are left, it’s all of them.</p><p><em>Originally published at </em><a href="https://koriigami.com/blog/claude-code-skills-standard?utm_source=medium&amp;utm_medium=referral&amp;utm_campaign=organic"><em>koriigami.com</em></a><em> on October 31, 2026.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6a4a2bb965b1" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Boris’s Claude Code Workflow: What I’d Do Differently]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@koriigami/boriss-claude-code-workflow-what-i-d-do-differently-599c4bc5c4cd?source=rss-c2491c06adc7------2"><img src="https://cdn-images-1.medium.com/max/1800/1*XvWYikJahI2w5THJ54C2xQ.png" width="1800"></a></p><p class="medium-feed-snippet">The creator of Claude Code shared his full workflow. Here&#x2019;s what&#x2019;s worth copying, what only works at Anthropic scale, and the one habit I&#x2026;</p><p class="medium-feed-link"><a href="https://medium.com/@koriigami/boriss-claude-code-workflow-what-i-d-do-differently-599c4bc5c4cd?source=rss-c2491c06adc7------2">Continue reading on Medium »</a></p></div>]]></description>
            <link>https://medium.com/@koriigami/boriss-claude-code-workflow-what-i-d-do-differently-599c4bc5c4cd?source=rss-c2491c06adc7------2</link>
            <guid isPermaLink="false">https://medium.com/p/599c4bc5c4cd</guid>
            <category><![CDATA[boris-cherny]]></category>
            <category><![CDATA[claude]]></category>
            <category><![CDATA[claude-code]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[productivity]]></category>
            <dc:creator><![CDATA[Ketan Damle]]></dc:creator>
            <pubDate>Thu, 21 May 2026 04:31:04 GMT</pubDate>
            <atom:updated>2026-05-21T04:31:04.130Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Build a Personal Knowledge Base With Claude Code]]></title>
            <link>https://medium.com/@koriigami/build-a-personal-knowledge-base-with-claude-code-25d215b61822?source=rss-c2491c06adc7------2</link>
            <guid isPermaLink="false">https://medium.com/p/25d215b61822</guid>
            <category><![CDATA[productivity]]></category>
            <category><![CDATA[obsidian]]></category>
            <category><![CDATA[knowledge-management]]></category>
            <category><![CDATA[claude-code]]></category>
            <category><![CDATA[llm]]></category>
            <dc:creator><![CDATA[Ketan Damle]]></dc:creator>
            <pubDate>Tue, 19 May 2026 06:12:58 GMT</pubDate>
            <atom:updated>2026-05-19T06:15:44.764Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XOt_pMRf_HQmc15IKQcD2Q.png" /></figure><h4>Andrej Karpathy shared a deceptively simple pattern in April 2026. Instead of RAG, have Claude maintain a structured markdown wiki that compounds as you add to it.</h4><p>In April 2026, Andrej Karpathy (OpenAI co-founder, former Tesla AI Director) <a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f">published a GitHub Gist</a> called “LLM Wiki.” It got <a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f">5,000+ stars</a> within days. Not because it was technically impressive. Because it was surprisingly simple.</p><p>The premise: instead of building a RAG pipeline with embeddings and vector search, you have Claude Code maintain a structured collection of markdown files. You dump in raw sources. Claude organizes them. You ask questions. Claude searches its own index and answers with citations linking back to specific wiki pages.</p><p>Karpathy’s own reaction was the most honest part: “I thought I had to reach for fancy RAG, but the LLM has been pretty good about auto-maintaining index files.”</p><p>That’s it. That’s the idea. Here’s how to build it.</p><h3>Why RAG doesn’t work well for personal notes</h3><p>If you’ve ever set up a RAG pipeline for your own documents, you’ve probably hit this: the retrieval works fine for direct questions but falls apart on synthesis. Ask “what did that paper say about X?” and you get an answer. Ask “how does X relate to the patterns I’ve been noticing across the last three projects?” and you get something generic that ignores half of what’s in your collection.</p><p>The reason is structural. <a href="https://www.mindstudio.ai/blog/llm-wiki-vs-rag-markdown-knowledge-base-comparison">RAG has no accumulation</a>. Every query starts from scratch: retrieve, rank, inject into context, generate. If the answer requires synthesizing five documents, the system has to find all five, hope the retrieval worked, and stitch them together on the fly. There’s no memory of connections you’ve already made, no building on earlier synthesis.</p><p>There’s another problem with RAG that’s underappreciated: <a href="https://www.stackai.com/blog/rag-limitations">retrieval failures are silent</a>. The system doesn’t tell you it didn’t find the relevant chunk. It just generates a response without it, and you can’t tell whether the answer is complete or missing something important.</p><p>For personal knowledge (your notes, your research, your patterns across projects), neither of these tradeoffs is acceptable. You want answers that reflect your actual context, not a best-effort retrieval pass.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MNSoFF2tMxd9ZZXcLsibUA.png" /></figure><h3>The LLM wiki pattern: what it actually does differently</h3><p>The core idea is simple once you see it. Instead of searching your notes at query time, you have Claude pre-process them into a structured wiki. Connections get made when you ingest a source, not when you ask a question. The wiki accumulates knowledge the way a notebook does, except Claude writes the notebook.</p><p><a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f">Three layers</a>, each with a clear role:</p><p><strong>Raw sources</strong> are immutable. PDFs, articles, transcripts, images, meeting notes: everything you feed the system. Claude reads from here but never writes to it. This is your record of what actually exists.</p><p><strong>The wiki</strong> is Claude’s layer. A directory of markdown files: concept pages, entity pages, comparison pages, synthesis pages. Claude creates and updates these as you ingest new sources. Each page links to others using [[wikilinks]]. Over time, the connections accumulate. Claude is responsible for maintaining them.</p><p><strong>The schema</strong> is a CLAUDE.md file that tells Claude how the wiki works: what the folder structure is, what conventions to follow, what to do when it ingests a new source, how to handle contradictions between pages. If you&#39;ve read <a href="https://medium.com/articles/claude-md-guide">my earlier piece on CLAUDE.md</a>, this is the same pattern: encode the rules once, let Claude follow them consistently.</p><p>The reason this works at personal scale is context. <a href="https://www.mindstudio.ai/blog/llm-wiki-vs-rag-markdown-knowledge-base-comparison">For knowledge bases under roughly 100,000 tokens</a> (call it 500–1,000 average-length notes), Claude can hold the index in context and reason over it directly. No embeddings, no vector database, no infrastructure to maintain.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cv-oHdEPLNmOnndMZww4pg.png" /></figure><h3>Three operations you’ll use every day</h3><h4>Ingest</h4><p>You found something worth keeping. An article, a paper, a set of notes from a meeting. You save it to your raw/ folder and tell Claude to ingest it.</p><p>Claude reads the source, creates or updates wiki pages (a summary page for the source itself, concept pages for any new ideas it introduces, entity pages for people or projects mentioned), and updates the index file so future queries can find it. Then it marks the source as processed.</p><p>The result: the source is in your collection, its key ideas are on wiki pages that link to each other, and the index knows it exists.</p><h4>Query</h4><p>You ask a question. Claude searches the wiki (starting with the index, pulling relevant pages) and answers with citations that link directly to specific wiki pages, not back to raw sources. Because the wiki pages already contain synthesis, the answers can reference connections across multiple sources without repeating that work.</p><p>This is the payoff. A question that would require RAG to stitch together five documents just requires Claude to read the wiki pages it already built when those documents came in.</p><h4>Lint</h4><p>The wiki gets messy over time. Dead links, orphan pages, contradictions between what you thought two years ago and what you know now, stale pages that reflect outdated understanding. You run lint and Claude checks for all of it, fixing what it can automatically and flagging what needs your attention.</p><p>This is what makes the system compound. Not just accumulating pages, but maintaining the quality of the connections between them.</p><h3>How to set this up with Claude Code and Obsidian</h3><p>This takes about 30 minutes to get running for the first time.</p><h4>Step 1: Create your vault structure.</h4><p>Create a folder for your wiki (~/wiki or wherever makes sense). Inside it:</p><pre>wiki/<br>├── raw/              ← immutable sources go here<br>│   ├── articles/<br>│   ├── papers/<br>│   └── notes/<br>├── wiki/             ← Claude&#39;s markdown pages<br>├── index.md          ← Claude maintains this automatically<br>└── CLAUDE.md         ← your schema</pre><p>If you want an Obsidian view, open Obsidian and point it at this folder as a new vault. Everything stays in plain markdown, with no lock-in.</p><h4>Step 2: Write your CLAUDE.md schema.</h4><p>This is the most important file. It tells Claude exactly how your wiki works. Start from <a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f">Karpathy’s original gist</a> and adapt it, or use one of the community implementations as a starting point. <a href="https://github.com/nvk/llm-wiki">nvk/llm-wiki</a> and <a href="https://github.com/Ar9av/obsidian-wiki">Ar9av/obsidian-wiki</a> are both solid bases.</p><p>Your schema should define: what the folder structure means, how to name wiki pages, what sections every page should have, how to handle contradictions, and the exact commands for ingest/query/lint.</p><p>A minimal version for the ingest operation looks like:</p><pre>## Ingest command<br>When I say &quot;ingest [filename]&quot;:<br>1. Read raw/[filename]<br>2. Create wiki/[slug].md with: summary, key concepts, related pages<br>3. Update or create concept pages for any new ideas<br>4. Add entry to index.md<br>5. Mark source as processed in raw/ (add a .processed suffix or move to raw/done/)</pre><h4>Step 3: Ingest your first sources.</h4><p>Open Claude Code with your wiki folder as the working directory. It will read your CLAUDE.md automatically. Then:</p><pre>ingest articles/that-paper-i-saved.pdf</pre><p>Claude processes it, creates wiki pages, updates the index. Do this with a handful of sources to see the structure before you decide if you want to adjust anything.</p><h4>Step 4: Ask your first question.</h4><pre>What have I captured about [topic]? Summarize the key patterns and link to the relevant wiki pages.</pre><p>The first few times you do this, the wiki will be sparse and the answers limited. That’s fine. The system compounds: the more you ingest, the more useful the queries become.</p><h4>Step 5: Schedule a weekly lint.</h4><p>Add a reminder to run lint once a week. Ten minutes of cleanup keeps the wiki useful as it grows. Without it, dead links accumulate and pages diverge from each other.</p><h3>A few things to get right from the start</h3><p><strong>Keep raw sources immutable.</strong> The moment you let Claude edit source files, you lose track of what was original and what was generated. Raw files are your ground truth. Only the wiki layer gets modified.</p><p><strong>Write the schema before you ingest anything.</strong> If you start ingesting without a schema, Claude will make up conventions on the fly and they’ll be inconsistent. Twenty pages in, you’ll be retrofitting structure to a mess. Write the CLAUDE.md first, even if it’s minimal.</p><p><strong>Don’t index everything.</strong> RAG pipelines tempt you to throw everything in. The LLM wiki works best when you’re intentional. If a source isn’t worth reading again, it’s not worth ingesting. The index quality matters more than the index size.</p><p><strong>Know the scale limit.</strong> The approach works reliably below roughly <a href="https://www.mindstudio.ai/blog/llm-wiki-vs-rag-markdown-knowledge-base-comparison">50,000–100,000 tokens</a> of wiki content. For most personal knowledge bases, that’s a long way off. When you approach it, you’ll know; queries will start getting slower and less coherent. At that point, a hybrid approach with a retrieval layer makes sense.</p><h3>Start small, then let it compound</h3><p>The first instinct is to migrate your entire Notion or Roam database on day one. Don’t. Don’t. Start with five sources in one domain, a subject you’re actively thinking about. Ingest them, query them, see how the wiki pages look.</p><p>The value of this system comes from time, not volume. A wiki with 50 deeply connected pages is more useful than a wiki with 500 loosely indexed ones. Ingest consistently. Lint regularly. Let Claude maintain the connections. That’s the whole pattern.</p><p>Karpathy called it “surprisingly viable.” After a few weeks with it running in the background, I’d say that’s underselling it.</p><p><em>Originally published at </em><a href="https://koriigami.com/blog/llm-wiki-knowledge-base?utm_source=medium&amp;utm_medium=referral&amp;utm_campaign=organic"><em>koriigami.com</em></a><em> on May 23, 2026.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=25d215b61822" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Claude Code Routines: scheduling autonomous agents without keeping your laptop open]]></title>
            <link>https://medium.com/@koriigami/claude-code-routines-scheduling-autonomous-agents-without-keeping-your-laptop-open-04f79f032fba?source=rss-c2491c06adc7------2</link>
            <guid isPermaLink="false">https://medium.com/p/04f79f032fba</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[claude-routine]]></category>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[automation]]></category>
            <category><![CDATA[claude-code]]></category>
            <dc:creator><![CDATA[Ketan Damle]]></dc:creator>
            <pubDate>Fri, 08 May 2026 05:01:00 GMT</pubDate>
            <atom:updated>2026-05-19T06:23:51.740Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*39ZfqLTjJ-LH8geT9t3-Ew.png" /></figure><h4>Configure a prompt, attach a repo, pick a trigger. Claude runs it on Anthropic’s infrastructure: no laptop, no cron job, no babysitting.</h4><p>There’s a category of work that’s genuinely repetitive: the Monday morning dependency scan, the PR summary that should auto-generate every time a branch is merged, the weekly competitive brief that takes 20 minutes to pull together but could be done by Claude in the background.</p><p>You know Claude could do these. But Claude only works when you’re in a session, which means you either start the session yourself, every time, or the task doesn’t happen.</p><p><a href="https://claude.com/blog/introducing-routines-in-claude-code">Claude Code Routines</a>, launched April 14, 2026, closes that gap. A routine is a saved configuration: a prompt, one or more GitHub repositories, and a set of connectors. Set it once. It runs on Anthropic’s cloud infrastructure (on a schedule, triggered by a GitHub event, or fired via API) with no approval prompts, no open laptop required.</p><p>This isn’t another Zapier. Zapier routes data between apps. Routines write code, read files, run analysis, and commit results. The output is Claude Code’s output: actual work product, not just a triggered notification.</p><h3>What a routine actually is</h3><p>A routine is not a background process on your machine. It runs in an <a href="https://code.claude.com/docs/en/routines">Anthropic-managed cloud container</a>, the same environment as Claude Code on the web. Your repo is cloned fresh at the start of each run. Claude executes its task. Any outputs (files edited, branches created, commits pushed) go directly to GitHub under your identity.</p><p>Three things define a routine:</p><p><strong>A prompt.</strong> This has to be self-contained. There are no approval prompts during a run; Claude cannot ask clarifying questions or request confirmation. What you write in the prompt is the entire brief. Vague prompts produce vague routines.</p><p><strong>One or more GitHub repos.</strong> Every routine needs at least one repository. The repo is cloned from the default branch at the start of each run. By default, Claude can only push to branches prefixed with claude/. To push to main or any existing branch, enable that per-repo in the settings.</p><p><strong>Connectors.</strong> Any MCP connectors you’ve added to your Claude Code account are available to routines. Slack, Linear, Notion, GitHub, whatever you’ve connected. All included by default; remove what the routine doesn’t need.</p><p>Run limits: <a href="https://code.claude.com/docs/en/routines">Pro gets 5 runs/day, Max gets 15, Team and Enterprise get 25</a>. One-off scheduled runs don’t count against these caps.</p><h3>Setting one up</h3><p>Go to <a href="https://claude.ai/code/routines">claude.ai/code/routines</a> and click “New routine.” Seven steps, most of them quick:</p><ol><li><strong>Name it:</strong> something descriptive that will make sense in a list of routines</li><li><strong>Write the prompt:</strong> specific, imperative, self-contained (more on this below)</li><li><strong>Select repos:</strong> the repositories this routine will clone and potentially modify</li><li><strong>Choose an environment:</strong> controls network access and available packages; the default works for most cases</li><li><strong>Pick a trigger:</strong> schedule, GitHub event, API, or any combination</li><li><strong>Review connectors:</strong> remove any the routine doesn’t actually need</li><li><strong>Create, then “Run now”</strong> to verify the first run before relying on it</li></ol><p>From the CLI, /schedule accepts natural language: /schedule daily dependency scan at 9am creates a routine directly. You can manage them with /schedule list, /schedule update, and /schedule run.</p><p><strong>One setup gotcha:</strong> GitHub event triggers require the <strong>Claude GitHub App</strong> installed on the target repository. This is a separate step from the standard GitHub auth (/web-setup). If the GitHub App isn&#39;t installed, event triggers silently won&#39;t fire. Install it from the repository settings or from the routine configuration UI before relying on event-based triggers.</p><h4>Writing a prompt that works autonomously</h4><p>The biggest failure mode for routines is a prompt written as if Claude can ask follow-up questions. It can’t.</p><p>Bad: Review open PRs and summarize them.</p><p>Good: Review all open pull requests in the repository that have been open for more than 3 days and have no reviewer assigned. For each PR: read the diff, write a 2-3 sentence plain-English summary of what it changes, identify any obvious risks or missing tests, and post a comment on the PR with your findings. Sign off comments with &quot;- Routine Review&quot;.</p><p>The second version leaves no ambiguity. Claude knows exactly what to look at, what to produce, and where to put it.</p><h3>Three trigger types</h3><p><strong>Schedule.</strong> Recurring runs at whatever cadence you set: hourly, daily, weekdays only, weekly. Minimum interval is one hour. Useful for anything time-based: morning briefings, weekly reports, end-of-week commit summaries.</p><p><strong>GitHub event.</strong> Fires when something happens in the repo: PR opened, PR closed, PR labeled, release published. You configure filters by author, title, base branch, labels, and draft status to control exactly which events trigger a run. Useful for automating responses to repo activity without building a custom GitHub Action.</p><p><strong>API.</strong> Each routine gets a unique POST endpoint and bearer token. Hit it from anywhere: a webhook, another script, a mobile shortcut. Pass optional context in the text field (the contents of an alert, the body of an incoming message). Useful when you want to trigger Claude from an external system.</p><p>A single routine can use all three simultaneously.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZXWww-HStrpDbBJKlMschA.png" /><figcaption>How a routine runs: three trigger types (Schedule, GitHub Event, API) feed into the routine’s three inputs (Prompt, Repos, Connectors), which produce commits, issues, and messages</figcaption></figure><h3>Who this is for (beyond developers)</h3><p>Most coverage of Routines focuses on engineering workflows. That’s the obvious use: automated code review, dependency scanning, PR summaries. But the feature isn’t limited to people who write code for a living. Any role with repetitive research, synthesis, or reporting tasks and a GitHub-hosted repo to work from can benefit.</p><p>Here are four perspectives:</p><h4>Developer</h4><p><strong>Dependency audit (weekly, Monday 8am):</strong> Scans for outdated or vulnerable packages, generates an upgrade plan with breaking change notes, and posts it as a GitHub issue. You see it in your inbox Monday morning.</p><p><strong>PR summary on merge (GitHub event: PR closed):</strong> Filters for PRs where is merged = true. Writes a human-readable changelog entry from the diff and commits it to CHANGELOG.md on a claude/changelog branch. Review and squash-merge weekly.</p><p><strong>Test coverage gap report (weekly):</strong> Runs coverage analysis, identifies untested functions, and opens a GitHub issue ranking them by call frequency. Makes the “what should we test next” decision obvious rather than manual.</p><h4>Product designer</h4><p><strong>Competitor UI monitor (weekly):</strong> Tracks a list of competitors in a competitors.md file. Searches for product update announcements, screenshots, and changelog entries. Generates a structured summary: what changed, what it means for your current design decisions.</p><p><strong>Design handoff checklist (GitHub event: PR opened with label “design-handoff”):</strong> When a PR tagged design-handoffopens, the routine reads the linked spec file, generates an implementation checklist for the dev team, and posts it as a PR comment. Reduces back-and-forth between design and engineering.</p><p><strong>User research synthesis (GitHub event: new file in </strong><strong>/research/transcripts/):</strong> When a new transcript is pushed, the routine extracts themes, groups them by journey stage, and appends findings to /research/synthesis.md. The synthesis document stays current without a dedicated synthesis session.</p><h4>Product manager</h4><p><strong>Sprint planning prep (Monday, before standup):</strong> Reads the current sprint backlog from a connected Linear or GitHub Projects board, maps items against estimated capacity, and generates a ranked list of what should make the sprint. Takes 30 seconds to review instead of 30 minutes to build.</p><p><strong>Release notes on merge (GitHub event: PR merged to </strong><strong>main with label &quot;release&quot;):</strong> Reads the diff, writes a user-facing release note in plain English, and appends it to RELEASES.md. By the time you&#39;re ready to communicate the release, the draft is already there.</p><p><strong>Stakeholder update (Friday, 4pm):</strong> Pulls open issues, merged PRs, and sprint progress for the week. Generates a non-technical summary paragraph suitable for the weekly team email. You edit the tone; you don’t write the first draft.</p><h4>CEO / Founder</h4><p><strong>Executive digest (daily, 7am):</strong> Reads a priorities.md file you maintain in the repo, pulls recent GitHub activity across connected repos, and generates a one-page morning brief: what shipped, what&#39;s blocked, what needs a decision today.</p><p><strong>OKR health check (biweekly):</strong> Cross-references a okrs.md file against recent commits and issues. Generates a status summary per objective: on track, at risk, or stalled. Evidence comes from actual repo activity, not self-reported status.</p><p><strong>Board memo first draft (monthly, 1st of the month):</strong> Reads kpis.md, okrs.md, and recent activity. Generates a structured board update draft: what was planned, what shipped, what&#39;s next, what decisions are needed. You edit and finalize; you don&#39;t start from a blank page.</p><h3>When not to use Routines</h3><p><strong>When the task needs your judgment mid-run.</strong> Routines are fully autonomous. If the task has a branch point (“if X, do Y; if Z, ask me first”), that ask-first path doesn’t exist. Either the prompt handles the branching explicitly, or the task isn’t right for a routine.</p><p><strong>When you need local file system access.</strong> Routines run in Anthropic’s cloud. They clone your GitHub repos and can read/write files within them, but they can’t touch files on your machine or inside your private network.</p><p><strong>When the task takes less than 5 minutes and you’re already at your desk.</strong> For quick one-off tasks, just open a Claude Code session. The overhead of configuring and maintaining a routine only pays off when the task recurs reliably.</p><p><strong>When you’re under the run limit on the wrong plan.</strong> Five runs per day on Pro sounds like a lot until you add a daily briefing (1), a weekly report (not daily but averages), two event triggers that fire on active repos, and a Monday planning routine. Prioritize before you configure.</p><h3>The shift it represents</h3><p>Every role has tasks that should happen on a cadence but don’t, because the friction of starting them is higher than the value of doing them once. They end up on a mental list of “things I should do regularly” that never quite makes it to “things I actually do regularly.”</p><p>Routines are the infrastructure for closing that gap. Recurring work moves off your plate entirely, done in the background, waiting in your inbox when you need it.</p><p><a href="https://x.com/NickSpisak_/status/2044167561978491236">Nick Spisak’s summary</a> is the cleanest mental model for when each Claude Code mode applies: use a routine when you want to set it and forget it, use a desktop schedule when you need local access, use /loop when you need it right now. Three modes, three different jobs.</p><p>Configure one routine this week. Something you actually do on a recurring basis, not something theoretical. See how the output compares to what you’d produce manually, and adjust the prompt from there.</p><h3>Sources</h3><p>[1] Introducing routines in Claude Code: <a href="https://claude.com/blog/introducing-routines-in-claude-code">Anthropic Blog</a>. Launch announcement, April 14, 2026. Official framing and feature overview.</p><p>[2] Automate work with routines: <a href="https://code.claude.com/docs/en/routines">Claude Code Docs</a>. Full setup documentation: trigger types, run limits, GitHub App requirement, environment configuration, branch permissions.</p><p>[3] Claude Code Routines discussion: <a href="https://news.ycombinator.com/item?id=47768133">Hacker News</a>. 720 points, 413 comments. Community reaction including vendor lock-in concerns and practitioner perspectives.</p><p>[4] Nick Spisak routine/schedule/loop breakdown: <a href="https://x.com/NickSpisak_/status/2044167561978491236">X</a>. Three-mode mental model: routine (set and forget), desktop schedule (local access), /loop (right now).</p><p><em>Originally published at </em><a href="https://koriigami.com/blog/claude-code-routines?utm_source=medium&amp;utm_medium=referral&amp;utm_campaign=organic"><em>koriigami.com</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=04f79f032fba" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Claude Opus 4.7: what’s actually better and when to upgrade]]></title>
            <link>https://medium.com/@koriigami/claude-opus-4-7-whats-actually-better-and-when-to-upgrade-eae0e2cb3c60?source=rss-c2491c06adc7------2</link>
            <guid isPermaLink="false">https://medium.com/p/eae0e2cb3c60</guid>
            <category><![CDATA[claude]]></category>
            <category><![CDATA[claude-code]]></category>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[anthropic-claude]]></category>
            <dc:creator><![CDATA[Ketan Damle]]></dc:creator>
            <pubDate>Thu, 07 May 2026 08:36:57 GMT</pubDate>
            <atom:updated>2026-05-07T08:36:57.035Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*txDCl8ecICSQmwzQxOlpSQ.png" /></figure><h4>The benchmarks are real. So is the 35% tokenizer surprise. Here’s what changed and how to decide if now is the right time.</h4><p>Every model release comes with the same question: is this worth switching?</p><p>With Opus 4.7, the answer is more complicated than usual. The headline is accurate: <a href="https://platform.claude.com/docs/en/about-claude/pricing">same 5/25 pricing</a>, real benchmark gains across <a href="https://llm-stats.com/blog/research/claude-opus-4-7-vs-opus-4-6">12 of 14 reported tests</a>. But three things make this upgrade decision less obvious than it looks: a new tokenizer that can raise your real costs by up to 35%, a set of breaking API changes that require code updates, and at least one workflow type where 4.7 performs worse than 4.6.</p><p>This is a practical breakdown, not a benchmark post. The goal is a clear decision framework for whether to switch now, switch carefully, or hold.</p><h3>What’s genuinely better</h3><p>The gains in Opus 4.7 are real and concentrated in specific areas.</p><p><strong>Coding benchmarks jumped significantly.</strong> <a href="https://www.anthropic.com/news/claude-opus-4-7">SWE-bench Pro</a> climbed from 53.4% to 64.3%, and SWE-bench Verified went from 80.8% to 87.6%. <a href="https://www.mindstudio.ai/blog/claude-opus-4-7-vs-4-6-comparison">CursorBench</a>, which tests real-world coding inside an IDE environment, went from 58% to 70%. These are not marginal improvements.</p><p><strong>Agentic efficiency improved by 2x.</strong> Opus 4.7 averaged <a href="https://www.mindstudio.ai/blog/claude-opus-4-7-vs-4-6-comparison">7.1 LLM calls to complete the same tasks that Opus 4.6 needed 16.3 calls for</a>. p50 latency dropped from 242 seconds to 183 seconds. The model is also <a href="https://evolink.ai/blog/claude-opus-4-7-review-2026">60% less likely to drop subtasks in long agentic sequences</a> compared to its predecessor. For multi-step agentic workflows, this is the most consequential improvement in the release.</p><p><strong>The model proactively verifies its own work.</strong> In agentic contexts, <a href="https://claudefa.st/blog/models/claude-opus-4-7">Opus 4.7 writes tests, runs them, and fixes failures before surfacing results</a>. This “verify before reporting” behavior reduces back-and-forth on complex tasks without you having to prompt for it explicitly.</p><p><strong>Vision capability changed dramatically.</strong> <a href="https://www.the-ai-corner.com/p/claude-opus-4-7-guide-benchmarks-2026">Vision accuracy went from 54.5% to 98.5%</a>, and maximum image resolution tripled from 1568px to 2576px (1.15MP to 3.75MP). The model can now read small text in screenshots, parse dense UI mockups, and extract information from high-resolution photos that previous versions couldn’t process cleanly. If your workflows involve image analysis or document processing, this is a substantial capability change.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*M9Y1622tlRddYfrkBj6rKA.png" /><figcaption>Opus 4.6 vs Opus 4.7: benchmark comparison across coding, agentic efficiency, vision, effort levels, and cost</figcaption></figure><h3>The new effort system</h3><p>Opus 4.7 ships with a redesigned effort parameter.</p><p>The scale now has five levels: low, medium, high, <strong>xhigh</strong> (new), and max. <a href="https://platform.claude.com/docs/en/build-with-claude/effort">Anthropic recommends starting with xhigh for coding and agentic use cases</a>, and the internal benchmark numbers support that: xhigh scores approximately 71% on the Agentic Coding benchmark while consuming around 100k tokens. Max effort only reaches 74.5%, but consumes over 200k tokens. For most production workloads, xhigh is the better cost-performance tradeoff.</p><p>The practical change from Opus 4.6 here is not just the new level; it’s that you now have explicit control over where the model sits on the intelligence-vs-cost curve.</p><p>There’s also a new <strong>task budgets</strong> feature in beta. Pass the task-budgets-2026-03-13 beta header and add task_budget: {type: &quot;tokens&quot;, total: N} to output_config, with a minimum of 20k tokens. The model sees a running countdown and prioritizes work accordingly, which is useful for long-running agentic loops where you want graceful completion rather than abrupt cutoff when token limits are hit.</p><h3>What got worse</h3><p>Three things to understand before flipping the switch.</p><p><strong>Multi-source web research regressed.</strong> This is the clearest regression in 4.7. When the agent browses, reads several pages, and synthesizes findings into a report, <a href="https://www.mindstudio.ai/blog/claude-opus-4-7-review">4.7 runs redundant queries, source attribution accuracy drops, contradiction detection weakens, and citation specificity falls</a>. Opus 4.6 outperforms 4.7 on this specific workflow. If multi-source web research synthesis is your primary use case, this upgrade is not ready for you yet.</p><p><strong>Instruction following got more literal.</strong> Opus 4.7 follows instructions precisely rather than inferring what you meant. Where Opus 4.6 would sometimes generalize an instruction from one context to a related one, 4.7 doesn’t. Prompts that relied on 4.6’s loose interpretation will produce narrower, more literal outputs. This is not uniformly bad, but it will break workflows where you relied on the model making reasonable inferences. You’ll need to rewrite those prompts to be explicit.</p><p><strong>The new tokenizer adds up to 35% more tokens.</strong> Opus 4.7 ships with a new tokenizer that can produce <a href="https://www.finout.io/blog/claude-opus-4.7-pricing-the-real-cost-story-behind-the-unchanged-price-tag">1x to 1.35x as many tokens</a> for the same input text, depending on content type. The rate card didn’t change. Your invoice might. If you’re running high-volume pipelines, measure your actual token counts on 4.7 before assuming your costs stayed flat.</p><h3>The four breaking API changes</h3><p>These require code changes, not just prompt updates.</p><p><strong>budget_tokens is gone.</strong> The old way to control extended thinking depth (thinking: {type: &quot;enabled&quot;, budget_tokens: N}) is removed entirely. The new approach is <a href="https://platform.claude.com/docs/en/about-claude/models/migration-guide">adaptive thinking</a>: pass thinking: {type: &quot;adaptive&quot;} and the model decides how much to reason based on the task. You lose the ability to set an explicit thinking token cap.</p><p><strong>thinking.display default changed.</strong> It used to default to &quot;summarized&quot;, meaning you&#39;d get a thinking summary in the response. In 4.7 it defaults to &quot;omitted&quot;, meaning block.thinking comes back as an empty string unless you explicitly setthinking.display: &quot;summarized&quot; or &quot;full&quot;. Any code that reads thinking blocks without checking for empty strings will silently produce blank output.</p><p><strong>Temperature, top_p, and top_k now return 400.</strong> These parameters no longer work at non-default values on Opus 4.7. If your code sets any of them, the API returns a 400 error. Remove them from your request or update your error handling.</p><p><strong>Prefilling assistant messages is blocked.</strong> Passing a partial assistant message to steer the output format returns a 400 error. Use system prompt instructions or output_config.format instead.</p><h3>Decision framework</h3><p>Here’s where to land based on what you’re actually building.</p><h4>Switch now if:</h4><ul><li>Your primary use case is coding, code review, or software engineering tasks</li><li>You run multi-step agentic workflows and care about completion rate on long tasks</li><li>Your workflows involve image analysis or high-resolution document processing</li><li>You’re building new pipelines without legacy 4.6 prompts to migrate</li></ul><h4>Switch after testing if:</h4><ul><li>You have production prompts tuned to Opus 4.6’s behavior: test your prompts against 4.7’s more literal interpretation before deploying</li><li>You’re cost-sensitive and running high-volume workloads: measure actual token counts on 4.7 first, since the tokenizer change can add 35% to the bill</li><li>You use any of the four broken API features: adaptive thinking migration is the most complex; plan the refactor before switching</li></ul><h4>Hold or keep 4.6 if:</h4><ul><li>Your core workflow is multi-source web research synthesis: this is the one area where 4.6 outperforms 4.7 as of this writing</li></ul><p>For most people, the upgrade is worth it. The 2x agentic efficiency alone justifies it for anyone running agent loops. But “most people” is not “everyone,” and the tokenizer cost increase plus the four breaking changes mean this is a planned migration, not a one-line model ID swap.</p><p>The practical migration path: use model ID claude-opus-4-7-20260416, raise max_tokens to give headroom for the tokenizer change, and start with effort: &quot;xhigh&quot; for agentic tasks. If using xhigh or max effort, start max_tokens at 64k minimum.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rVk30EqEyJWSPp3g6fI8uw.png" /><figcaption><em>When to upgrade to Opus 4.7: switch now, switch after testing, or hold on 4.6</em></figcaption></figure><h3>Where Agent Teams fit</h3><p><a href="https://techcrunch.com/2026/02/05/anthropic-releases-opus-4-6-with-new-agent-teams/">Agent Teams were introduced with Opus 4.6 in February 2026</a> and Opus 4.7 inherits them. If you’ve been using the orchestrator-worker pattern, 4.7 is a clear upgrade as the orchestrator model.</p><p>The 2x reduction in LLM calls matters most here: the orchestrator on Opus 4.7 completes planning and synthesis passes faster with fewer total invocations. The proactive output verification also reduces review cycles between orchestrator and worker.</p><p>For a detailed look at how to structure these workflows, the previous article in this series covers <a href="https://medium.com/12-multi-agent-orchestration-opus-4-7.md">multi-agent orchestration with Opus 4.7 Agent Teams</a> in full.</p><h3>The real upgrade story</h3><p>“Same price, better model” is the headline. The more accurate description is: significantly better for coding and agentic work, with a meaningful regression on web research synthesis, and up to 35% more expensive in practice due to the tokenizer change.</p><p>That’s not a reason to skip the upgrade. It’s a reason to test on your actual use cases first, update your API code for the four breaking changes, and recheck your cost estimates before you go to production.</p><p>The model is better where it counts for most builders. Just don’t assume the upgrade is frictionless.</p><h3>Sources</h3><p>[1] Claude Opus 4.7 release announcement: <a href="https://www.anthropic.com/news/claude-opus-4-7">Anthropic</a>. April 16, 2026. SWE-bench Verified 87.6%, vision accuracy, Agent Teams inheritance, Project Glasswing.</p><p>[2] What’s new in Claude Opus 4.7: <a href="https://platform.claude.com/docs/en/about-claude/models/whats-new-claude-4-7">Anthropic Platform Docs</a>. xhigh effort level, task budgets beta, image resolution specs, breaking changes.</p><p>[3] Claude Opus 4.7 vs 4.6 comparison: <a href="https://www.mindstudio.ai/blog/claude-opus-4-7-vs-4-6-comparison">MindStudio</a>. SWE-bench Pro/Verified/CursorBench numbers, 7.1 vs 16.3 LLM calls, p50 latency.</p><p>[4] Claude Opus 4.7 review (regressions): <a href="https://www.mindstudio.ai/blog/claude-opus-4-7-review">MindStudio</a>. Web research regression detail: redundant queries, source attribution, contradiction detection.</p><p>[5] Claude Opus 4.7 pricing and tokenizer impact: <a href="https://www.finout.io/blog/claude-opus-4.7-pricing-the-real-cost-story-behind-the-unchanged-price-tag">Finout</a>. 1x–1.35x token inflation from new tokenizer.</p><p>[6] Claude Opus 4.7 benchmark analysis: <a href="https://www.the-ai-corner.com/p/claude-opus-4-7-guide-benchmarks-2026">The AI Corner</a>. Vision accuracy 54.5% to 98.5%, CursorBench breakdown.</p><p>[7] Claude Opus 4.7 migration guide: <a href="https://platform.claude.com/docs/en/about-claude/models/migration-guide">Anthropic Platform Docs</a>. Four breaking API changes with migration paths.</p><p>[8] Effort parameter documentation: <a href="https://platform.claude.com/docs/en/build-with-claude/effort">Anthropic Platform Docs</a>. Five effort levels, xhigh recommendation for coding and agentic tasks.</p><p>[9] Effort level cost-performance analysis: <a href="https://claudefa.st/blog/models/claude-opus-4-7">Claudefa.st</a>. xhigh at ~100k tokens = ~71%; max at ~200k tokens = ~74.5%.</p><p>[10] Claude Opus 4.6 Agent Teams launch: <a href="https://techcrunch.com/2026/02/05/anthropic-releases-opus-4-6-with-new-agent-teams/">TechCrunch</a>. February 2026. Agent Teams introduced with 4.6, not 4.7.</p><p><em>Originally published at </em><a href="https://koriigami.com/blog/claude-opus-4-7?utm_source=medium&amp;utm_medium=referral&amp;utm_campaign=organic"><em>koriigami.com</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=eae0e2cb3c60" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building Custom Slash Commands and Skills for Claude Code]]></title>
            <link>https://medium.com/@koriigami/building-custom-slash-commands-and-skills-for-claude-code-a9d990e2930e?source=rss-c2491c06adc7------2</link>
            <guid isPermaLink="false">https://medium.com/p/a9d990e2930e</guid>
            <category><![CDATA[skills]]></category>
            <category><![CDATA[automation]]></category>
            <category><![CDATA[claude]]></category>
            <category><![CDATA[productivity]]></category>
            <category><![CDATA[claude-code]]></category>
            <dc:creator><![CDATA[Ketan Damle]]></dc:creator>
            <pubDate>Fri, 01 May 2026 16:53:38 GMT</pubDate>
            <atom:updated>2026-05-01T16:53:38.334Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_3pDkOaYT5-hVIqnsLYOpA.png" /></figure><h4>Stop typing the same instructions. Build a skill once, use it forever.</h4><p>You’ve opened a new Claude Code session for the third time this week. You type the same block of instructions you always type: “Review this PR diff. Check for missing error handling, performance issues, and anything that breaks our naming conventions. Format your response as a structured list by category.”</p><p>Claude does a great job. Just like it did on Monday. And last Thursday.</p><p>The problem isn’t that Claude can’t do this. The problem is that <em>you</em> have to remember to ask it the right way, every single time.</p><p>Skills are the fix.</p><h3>What Skills Actually Are</h3><p>A Claude Code skill is a saved, reusable prompt — packaged as a file that becomes a slash command.</p><p>When you type /review-pr, Claude doesn&#39;t just know what to do. It loads a set of instructions you wrote once, and follows them exactly, every time. You get consistent behavior without re-explaining yourself.</p><p>The mental model: <strong>a skill is a CLAUDE.md file for a specific task.</strong> Your CLAUDE.md sets project-wide context. A skill sets task-specific context, on demand.</p><p>As of January 2026, Claude Code merged its slash commands system directly into skills [2]. These used to be two separate mechanisms — now they’re the same thing. If you write a skill, you automatically get a /slash-command from it. One system, zero duplication.</p><p>If you’ve been using Claude Code for a while, you may have had project-specific slash commands in .claude/commands/. Those still work — they&#39;re now treated as project-scoped skills. No migration needed.</p><h3>Your First Skill: /daily-standup in 10 Minutes</h3><p>Here’s one worth building immediately: a skill that reads your git history from the past 24 hours and formats a standup update.</p><h4>Step 1: Create the skill file</h4><pre>mkdir -p ~/.claude/skills/daily-standup<br>touch ~/.claude/skills/daily-standup/SKILL.md</pre><h4>Step 2: Write the SKILL.md</h4><pre>---<br>name: daily-standup<br>description: &quot;Summarize yesterday&#39;s git commits and generate a standup update&quot;<br>version: 1<br>---<br>​<br># Daily Standup Skill<br>​<br>Run the following command and analyze the output:<br>​<br>```bash<br>git log --since=&quot;24 hours ago&quot; --oneline --author=&quot;$(git config user.name)&quot;</pre><p>Then generate a standup update in this format:</p><h4>What I did yesterday:</h4><ul><li>[bullet per meaningful commit or theme, grouped logically]</li></ul><h4>What I’m working on today:</h4><ul><li>[leave this blank — the user will fill it in]</li></ul><h4>Blockers:</h4><ul><li>None (unless the user mentions one)</li></ul><p>Keep it concise. No filler. Each bullet should be something a teammate actually cares about.</p><h4>Step 3: Use it</h4><pre>/daily-standup</pre><p>That’s it. Claude reads your git log, analyzes the commits, and produces a standup-ready summary. You fill in “today” and you’re done in 30 seconds.</p><h3>Global vs. Project Skills: Where to Store Them</h3><p>Claude Code has two places for skills [1]:</p><h4>Global: `~/.claude/skills/`</h4><p>Stored in your home directory. Available in every project, every session. Use this for workflows that belong to *you* — not to a specific codebase.</p><pre>~/.claude/skills/<br>├── daily-standup/SKILL.md<br>├── review-pr/SKILL.md<br>├── explain-error/SKILL.md<br>└── commit/SKILL.md</pre><h4>Project: `.claude/skills/` or `.claude/commands/`</h4><p>Stored inside a repository. Only available when working in that project. Use this for conventions that are specific to a codebase — like a skill that enforces your team’s exact PR review checklist. Both paths work; `.claude/skills/` is the newer recommended location, `.claude/commands/` is supported for backward compatibility.</p><pre>.claude/skills/<br>├── review-api-changes/SKILL.md<br>└── check-design-tokens/SKILL.md</pre><h4>Precedence rule:</h4><p>If you have a global skill and a project skill with the same `name`, the project skill wins. This lets you override global defaults per-repo [5].</p><p>A practical split: put personal productivity skills (standup, commit messages, error explanations) globally. Put repo-specific review checklists, deploy procedures, and naming convention checks in the project.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jVPuA0JXgzlLOJNr4AKHpQ.png" /></figure><h3>The SKILL.md Format</h3><p>Every skill is a single `SKILL.md` file with a YAML frontmatter block followed by the instruction body [4]:</p><pre>name: review-pr<br>description: &quot;Review a pull request diff for error handling, performance, and naming conventions&quot;<br>version: 1<br>---</pre><h4>PR Review Skill</h4><p>Fetch the current PR diff using:</p><pre>gh pr diff</pre><p>Review the changes and produce a structured report with these sections:</p><p><strong>Error Handling: M</strong>issing try/catch, unhandled promise rejections, no null checks on external data</p><p><strong>Performance: </strong>N+1 queries, unnecessary re-renders, large bundle imports</p><p><strong>Naming Conventions: C</strong>amelCase for variables, PascalCase for components, kebab-case for files</p><p><strong>Summary: </strong>one paragraph with the overall assessment and whether this is ready to merge</p><p>Be specific. Cite line numbers where relevant.</p><h4>The key fields in frontmatter:</h4><ol><li><strong>`name`</strong> becomes your `/slash-command`. Keep it short and a single hyphenated string.</li><li><strong>`description`</strong> used for auto-discovery (more on this below). Write it as a sentence describing what the skill does, not how.</li><li><strong>`version`</strong> is optional. Increment when you make significant changes. Useful for skills you share or install from the marketplace; fine to omit for personal skills.</li></ol><p>The instruction body is everything after the frontmatter. Write it in imperative voice: “Fetch the diff”, “Review the changes”, “Generate a report.” Be explicit about what format you want Claude to produce.</p><h3>Auto-Discovery: Skills That Suggest Themselves</h3><p>Here’s a feature that earns its keep after you’ve built a few skills.</p><p>Claude Code reads the `<strong>description</strong>` field of every installed skill at session start. When your message matches a skill’s description semantically, Claude will proactively suggest using it — even if you didn’t type the slash command [1].</p><p>So if you have a `<strong>/review-pr</strong>` skill installed with description `”Review a pull request diff…”` and you say “can you check this PR for issues?”, Claude might respond: “It looks like your `<strong>/review-pr</strong>` skill is designed for this, want me to use that?”</p><p>This is why the description field matters more than it looks. Write it as a clear, intent-describing sentence. “Review a pull request diff for error handling and naming issues” will match more reliably than “PR review helper”.</p><p><em>Auto-discovery is most useful once you have 5+ skills installed. At that point, you stop needing to remember slash commands , Claude surfaces the right tool based on what you’re asking.</em></p><h3>The EXTEND.md Pattern: Personalizable Skills</h3><p>If you install a skill from the marketplace (or share one with your team), you probably don’t want to edit the base SKILL.md directly, that would break updates.</p><p>Instead, many skills support an `EXTEND.md` preferences file. You place it alongside the skill:</p><pre>~/.claude/skills/review-pr/<br>├── SKILL.md        ← the base skill (don&#39;t edit this)<br>└── EXTEND.md       ← your personal overrides</pre><p>The EXTEND.md typically uses YAML frontmatter for structured preferences:</p><pre>---<br>version: 1<br>preferred_output: markdown-table<br>severity_levels: [critical, warning, suggestion]<br>ignore_patterns:<br>  - &quot;*.test.ts&quot;<br>  - &quot;*.stories.tsx&quot;<br>---</pre><p>When Claude runs the skill, it reads EXTEND.md first and merges your preferences into the execution. You get a shared base behavior with personal customization layered on top; no forks, no merge conflicts [3].</p><h3>Five Skills Worth Building</h3><p>If you’re a product designer or AI-first developer, these five cover most of the repetitive work:</p><p><strong>/commit</strong>: Reads your staged diff, generates a conventional commit message in the right format, asks for confirmation before running git commit. Saves the 2–3 minutes of writing a good message under pressure.</p><p><strong>/review-pr</strong>: Fetches the PR diff via gh pr diff, checks against your team&#39;s standards, outputs a structured review. Useful as a self-review before requesting a real reviewer.</p><p><strong>/explain-error</strong>: Paste an error message, stack trace, or unexpected output. Claude identifies the root cause, explains what went wrong, and suggests a fix. Works well for unfamiliar errors in codebases you didn&#39;t write.</p><p><strong>/write-component</strong>: For design-to-code work: describe a UI component, reference a Figma node if available, specify your stack (React + Tailwind, etc.). Claude generates the component following your existing conventions, using CLAUDE.md as context.</p><p><strong>/check-accessibility</strong>: Run against a component or page file. Checks for missing aria labels, keyboard navigation issues, color contrast violations, and focus management problems. A good pre-publish checklist.</p><h3>Sharing Skills and the Marketplace</h3><p>Skills are just files. Sharing them is as simple as committing them to a public repo.</p><p>The <strong>baoyu-skills marketplace</strong> (github.com/JimLiu/baoyu-skills) is the largest community collection [3]. It includes content skills, AI generation skills, and development workflow tools, most of which install via Claude Code’s plugin system with a single command.</p><p>If you build a skill that works well, consider publishing it. The format is simple enough that a SKILL.md + README is a complete, installable skill package.</p><p>For team use: store project skills in .claude/skills/ in your repo. Any developer who clones the repo gets the skills automatically. No separate install step, no docs to maintain — the skill is the docs.</p><h3>Getting Started Checklist</h3><p>Work through these in order. Each one builds on the last.</p><ul><li>Identify your top 3 most-repeated Claude Code prompts (the ones you type from memory)</li><li>Create ~/.claude/skills/ if it doesn&#39;t exist</li><li>Pick the simplest repeated prompt and convert it to a SKILL.md</li><li>Test the skill with /your-skill-name in a real session</li><li>Refine the instruction body based on the output — be more specific about format</li><li>Build skill #2 and #3</li><li>Add EXTEND.md support to any skill you might share or reuse across projects</li><li>Browse the baoyu-skills marketplace for skills you don’t need to build yourself</li></ul><p>Start with one. The skill-building habit develops once you’ve felt the difference between typing a skill name and re-explaining a workflow from scratch.</p><h3>You’ve Completed the Claude Code Power User Series</h3><p>If you’ve followed this series from Part 1:</p><ul><li>You’ve set up a <strong>CLAUDE.md</strong> that gives Claude context about your project before you type a word.</li><li>You’ve configured <strong>hooks</strong> that make your best practices automatic, formatting, notifications, safety checks.</li><li>You’ve run <strong>parallel agents</strong> on a codebase without file conflicts using git worktrees.</li><li>And now you have <strong>skills</strong> that save your best prompts and turn them into repeatable workflows.</li></ul><p>These four things compound. A CLAUDE.md + hooks + parallel agents + custom skills is a development environment that gets noticeably more productive the more you use it — because the overhead of working with Claude goes down while the quality of its output goes up.</p><p>The rest is iteration. Build skills for the tasks that still feel slow. Update your CLAUDE.md when you learn something new about your codebase. Add hooks for the checks that matter most. The system improves as you use it.</p><h3>Sources</h3><p>[1] Claude Code documentation : Skills and slash commands: <a href="https://code.claude.com/docs/en/skills">https://code.claude.com/docs/en/skills</a></p><p>[2] Anthropic changelog, January 2026 : Slash commands merged into Skills system</p><p>[3] baoyu-skills marketplace : github.com/JimLiu/baoyu-skills</p><p>[4] Claude Code documentation : SKILL.md format and frontmatter reference: <a href="https://code.claude.com/docs/en/skills#skillmd-format">https://code.claude.com/docs/en/skills#skillmd-format</a></p><p>[5] Claude Code documentation: Global vs project skill precedence: <a href="https://code.claude.com/docs/en/skills#skill-locations">https://code.claude.com/docs/en/skills#skill-locations</a></p><p><em>This is </em><strong><em>Part 4 </em></strong><em>of the </em><strong><em>Claude Code Power User</em></strong><em> series. End of Series</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a9d990e2930e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Running Parallel Claude Code Agents on a Single Codebase]]></title>
            <link>https://medium.com/@koriigami/running-parallel-claude-code-agents-on-a-single-codebase-927d70e7349d?source=rss-c2491c06adc7------2</link>
            <guid isPermaLink="false">https://medium.com/p/927d70e7349d</guid>
            <category><![CDATA[claude-code]]></category>
            <category><![CDATA[productivity]]></category>
            <category><![CDATA[git-worktree]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[ai-agent]]></category>
            <dc:creator><![CDATA[Ketan Damle]]></dc:creator>
            <pubDate>Wed, 29 Apr 2026 14:31:01 GMT</pubDate>
            <atom:updated>2026-05-01T16:50:26.945Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WeA-qUg56qLnZFGBitsVLg.png" /></figure><h4>Stop waiting for one agent to finish before starting the next.</h4><p>You ask Claude Code to fix a bug. It works. While it’s doing that, you have three other tasks sitting in a queue - a feature to add, a test suite to expand, a refactor to finish. You wait. Claude commits the bug fix. You paste the next task. You wait again.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*K6r6C3wjBbf-XGm8J-h-0Q.png" /></figure><p>This is the single-agent bottleneck. It’s the most common way people use Claude Code, and the most wasteful. Those tasks aren’t dependent on each other. There’s no reason they need to run one after another.</p><p>Claude Code now has a native answer to this: git worktrees plus parallel agent sessions. You can run two, three, four Claude Code agents simultaneously on the same repo; each one working on a separate branch, completely isolated, without stepping on each other’s work.</p><blockquote>This is Part 3 of the Claude Code Power User series. We covered CLAUDE.md configuration in <a href="https://medium.com/@koriigami/claude-md-the-file-that-changes-how-claude-codes-your-project-751e74439c08">Part 1</a> and hooks in <a href="https://medium.com/@koriigami/claude-code-hooks-automate-what-claude-should-always-do-d1cd4b031a30">Part 2</a>. Here we get into multi-agent architecture: the setup that Boris Cherny, Claude Code’s creator, has described as central to his own development process. [1]</blockquote><h3>The Core Concept: One Repo, Many Working Trees</h3><p>Before worktrees, running parallel Claude Code agents on the same repo meant either cloning the repo multiple times (messy, disk-heavy, diverges from your remotes) or accepting that agents would clobber each other’s file changes mid-task.</p><p>Git worktrees solve this cleanly. A worktree is an isolated checkout of your repository at a specific branch. The repo’s Git history and object store are shared (you don’t duplicate the whole repo), but each worktree has its own working directory and branch pointer. Changes in one worktree don’t appear in another until you merge. [2]</p><p>Claude Code’s --worktree flag automates the full setup. Under the hood it runs git worktree add, creates a new branch, sets up an isolated session directory under .claude/worktrees/, and launches a Claude Code session scoped to that context. When the session closes, teardown is handled for you.</p><p>The mental model is this: each agent lives in its own lane. Same highway (the repo), different lanes (worktrees). They never collide unless you explicitly merge them.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qlwyBfmfoBSx7q_mhnijsg.png" /></figure><h3>Setting Up Your First Worktree</h3><p>Starting a parallel agent session takes one command:</p><pre>claude --worktree feature-auth</pre><p>That’s it. Claude Code will:</p><ol><li>Create a new branch worktree-feature-auth</li><li>Set up an isolated working directory at .claude/worktrees/feature-auth/</li><li>Inherit your project’s CLAUDE.md configuration</li><li>Launch a Claude Code session scoped to that worktree</li></ol><p>In a second terminal window (or a tmux pane), you can start a second agent immediately:</p><pre>claude --worktree fix-payment-bug</pre><p>Now you have two Claude Code agents running simultaneously. One is building the auth feature on worktree-feature-auth. The other is diagnosing and fixing the payment bug on worktree-fix-payment-bug. Neither knows the other exists. Neither touches the other&#39;s files.</p><h4>What Gets Inherited, What Doesn’t</h4><p>Each worktree session inherits:</p><ul><li>CLAUDE.md from the project root (unless you place an overriding CLAUDE.md in the worktree directory)</li><li>Hooks configuration (each agent runs its own hook context. The same hooks apply, but they fire independently per session)</li><li>.claude/settings.json defaults</li></ul><p>Each worktree session does NOT share:</p><ul><li>Conversation history with other sessions</li><li>File changes (by design this is the whole point)</li><li>In-progress tool calls or task state</li></ul><h3>Real-World Parallel Workflows</h3><p>Theory is easy. Here’s how parallel worktrees look in practice.</p><h4>1. Bug Fix + Feature Development</h4><p>The classic case. You have a production bug that needs fixing; nothing too complex, but it needs focus. You also have a feature sprint you’re supposed to be making progress on.</p><pre># Terminal 1 — fix the bug<br>claude --worktree fix-invoice-rounding<br># Prompt: &quot;The invoice total rounds incorrectly for non-USD currencies. Investigate<br># src/billing/invoice.ts, fix the rounding logic, and add a regression test.&quot;<br>​<br># Terminal 2 — keep building<br>claude --worktree feat-invoice-templates<br># Prompt: &quot;Add a template selection step to the invoice creation flow.<br># Reference the existing flow in src/billing/create-invoice.tsx.&quot;</pre><p>Both run. Both commit to their own branches. You review the bug fix first (it’s smaller), merge it, then review the feature PR with fresh context.</p><h4>2. Implementation + Test Coverage</h4><p>You want Claude to write a new module AND ensure it’s fully tested, but you don’t want to wait for implementation to finish before testing starts. If the implementation is well-specced, an agent can start writing tests against the spec while another builds the module.</p><pre># Terminal 1 — build the module<br>claude --worktree feat-rate-limiter<br># Prompt: &quot;Implement a token-bucket rate limiter in src/lib/rate-limiter.ts<br># per the spec in docs/specs/rate-limiter.md&quot;<br>​<br># Terminal 2 — write tests against the spec<br>claude --worktree test-rate-limiter<br># Prompt: &quot;Write a comprehensive test suite for the rate limiter spec in<br># docs/specs/rate-limiter.md. Target file: src/lib/rate-limiter.test.ts.<br># The implementation is being written in parallel — test to the spec, not the code.&quot;</pre><p>When both finish, you merge the implementation branch, then apply the test branch on top. Some tests may need minor adjustments where the spec was ambiguous , but you’ve saved the sequential wait.</p><h4>3. Refactor + New Feature (Parallel, Non-Overlapping Files)</h4><p>When you know two tasks touch separate parts of the codebase, there’s no reason to run them sequentially. A refactor of your API layer doesn’t block a UI component update.</p><pre># Terminal 1 — refactor<br>claude --worktree refactor-api-layer<br># Prompt: &quot;Refactor src/api/ to use the new response wrapper pattern<br># from src/lib/api-response.ts. No new features — only structural changes.&quot;<br>​<br># Terminal 2 — new component<br>claude --worktree feat-settings-panel<br># Prompt: &quot;Build the new settings panel component per the mockup in<br># design/settings-panel.png. Output to src/components/SettingsPanel.tsx.&quot;</pre><h4>4. Research + Writing (Non-Code Work)</h4><p>Parallel worktrees aren’t just for engineers. If you’re using Claude Code for content work, like writing this article series you can run a research agent and a drafting agent simultaneously.</p><pre># Terminal 1 — research agent<br>claude --worktree research-topic-x<br># Prompt: &quot;Research [topic]. Summarize key findings into research/RESEARCH-topic-x.md&quot;<br>​<br># Terminal 2 — drafting agent<br>claude --worktree draft-article-y<br># Prompt: &quot;Draft the article outline and opening section for article-y.md,<br># using existing research in research/RESEARCH-article-y.md&quot;</pre><h4>5. Code Quality: Three-Agent Parallel Review</h4><p>The parallel agent pattern I use day-to-day isn’t worktrees. It’s parallel subagent dispatch. My /simplify command runs three Claude agents simultaneously against the same codebase: one scans for reuse opportunities, one reviews code quality, one audits efficiency. All three run in parallel and report back their findings before any changes are applied.</p><p>No worktrees needed, because all three agents are read-only. No file conflicts are possible when you’re only reading. This is the lighter end of the parallel-agent spectrum: read-parallel analysis rather than write-isolated development.</p><p>The pattern generalises. Any task where multiple agents examine the same code without modifying it (security audits, dependency scans, performance profiling) can run this way. You get the speed of parallelism without the branch management overhead of worktrees.</p><pre># /simplify dispatches three agents in a single command — you don&#39;t manage them individually<br>/simplify<br>​<br># Under the hood, three agents run simultaneously:<br># Agent 1: scan for reuse opportunities and duplicate code<br># Agent 2: review code quality (naming, structure, complexity)<br># Agent 3: audit efficiency (unnecessary computations, redundant state)</pre><p>Parallel agents exist on a spectrum. Use worktrees when agents need to make changes that can’t step on each other. Use subagent dispatch when agents are reading the same codebase from different angles.</p><h3>Agent Teams: The Next Level</h3><p>Worktrees give you parallel isolation. Agent Teams give you coordination.</p><p>Introduced in Claude Opus 4.6 (February 2026), Agent Teams let you define a structured team of Claude instances that operate collaboratively. One instance acts as orchestrator: it breaks down tasks, assigns subtasks to workers, and reviews their results before anything is committed. [3]</p><p>The distinction matters:</p><ul><li><strong>Subagents</strong> (the original model) are quick, focused workers that complete a task and report back. They’re fire-and-forget. No awareness of other agents.</li><li><strong>Agent Teams</strong> are teammates. They share findings, coordinate on approach, and the orchestrator maintains a global view of what’s been done and what remains.</li></ul><h4>Enabling Agent Teams</h4><p>Agent Teams is currently experimental. Enable it with an environment variable:</p><pre>export CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1</pre><p>Or persist it in .claude/settings.json so it applies to every session in the project:</p><pre>{<br>  &quot;env&quot;: {<br>    &quot;CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS&quot;: &quot;1&quot;<br>  }<br>}</pre><p>Once enabled, there’s no CLI flag or config file to write. You activate a team through a natural language prompt; Claude handles the orchestration:</p><pre>Create an agent team to add a CSV export feature to the reports page.<br>Break it into implementation, tests, and review. Run implementation<br>and tests in parallel, then review both before committing.</pre><p>The orchestrator agent takes over: it reads the codebase, plans the work, assigns tasks to worker agents running in parallel worktrees, and reviews the combined output before producing a final diff. Task state is stored locally at ~/.claude/tasks/{team-name}/.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MNmY4wpcUjWC846ntIiURg.png" /></figure><p>The orchestrator runs on Opus (currently 4.7), which costs roughly 5× what Sonnet costs per token. A typical team session — orchestrator plus two Sonnet workers at around 1K tokens each — runs $0.03–0.15. That’s negligible. It compounds in longer sessions with multiple review cycles. For tasks you can complete in a single 10–15 minute Sonnet session, Agent Teams adds overhead without proportionate benefit. Reserve it for complex multi-file work where the orchestrator’s coordination and review step actually changes the outcome.</p><h3>When NOT to Parallelize</h3><p>Parallel agents are powerful. They’re also genuinely wrong for some situations.</p><p><strong>When tasks share files.</strong> If two agents are likely to edit the same file, a shared utility, a config, a type definition; you’ll face a merge conflict that can be harder to resolve than just doing the work sequentially. Worktrees isolate branches, not merge conflicts. You still have to reconcile divergent changes when you merge.</p><p><strong>When context dependency is high.</strong> If Task B depends on understanding what Task A produced, running them in parallel means Task B operates on assumptions. This works fine with a spec (the test-against-spec pattern above), but if the spec is the output of Task A, you need to wait.</p><p><strong>When you’re debugging something subtle.</strong> Debugging requires close attention. Running a parallel agent session in the background while you’re debugging pulls your focus. The benefit of parallelism is that you’re doing something useful while Claude works — not that you’re watching two Claude sessions simultaneously.</p><p><strong>When merge overhead exceeds the time saved.</strong> For small tasks (under 10–15 minutes of Claude work), the overhead of creating worktrees, managing two terminal sessions, and reviewing two separate branches may cost more time than just doing them sequentially. Reserve parallel workflows for tasks substantial enough to justify the coordination cost.</p><h3>Getting Started Checklist</h3><p>Use this as a quick reference the first time you set up a parallel workflow:</p><pre>[ ] Identify two tasks that are independent (no shared files, no output dependency)<br>[ ] Open two terminal windows or tmux panes<br>[ ] Run: claude --worktree &lt;name-1&gt; in the first window<br>[ ] Run: claude --worktree &lt;name-2&gt; in the second window<br>[ ] Give each agent its task prompt<br>[ ] Let both run — check in periodically but don&#39;t hover<br>[ ] Review the smaller/faster task first<br>[ ] Merge the first branch, then review and merge the second<br>[ ] Clean up worktrees: git worktree remove .claude/worktrees/&lt;name&gt;</pre><p>For teams experimenting with Agent Teams:</p><pre>[ ] Add CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 to .claude/settings.json env block<br>[ ] Start with a small, well-scoped task to test team coordination<br>[ ] Describe the task and team structure in natural language — Claude handles orchestration<br>[ ] Audit the final diff carefully — multi-agent output needs more review scrutiny, not less</pre><h3>The Mindset Shift</h3><p>The biggest barrier to parallel agents isn’t technical — it’s the instinct to work serially.</p><p>Most developers have an internal queue: finish one thing, start the next. That works well when you’re the one writing the code. It’s unnecessarily limiting when Claude Code is doing the work and your job is to direct and review.</p><p>Think about how you’d delegate to a team. You don’t assign one task, wait for it to finish, then assign the next. You map out the work, identify what can run in parallel, assign it, and follow up at natural review points.</p><p>That’s the frame for parallel Claude Code agents. You’re not a developer who uses Claude as a tool. You’re a technical lead directing a team of agents — and the quality of your direction, not the speed of your typing, is what limits throughput.</p><h3>Sources</h3><p>[1] Boris Cherny on parallel multi-agent development workflows — cited from public statements describing his personal Claude Code usage. Cherny is the creator of Claude Code at Anthropic.</p><p>[2] Git worktree documentation — git worktree add allows multiple working trees attached to the same repository. Each worktree has its own checkout, branch pointer, and working directory. Official reference: <a href="https://git-scm.com/docs/git-worktree">https://git-scm.com/docs/git-worktree</a></p><p>[3] Claude Opus 4.6 Agent Teams — introduced February 6, 2026. Enables orchestrator + worker agent coordination with shared context and autonomous task assignment. Reference: Anthropic release notes for Claude Opus 4.6.</p><p><em>This is </em><strong><em>Part 3 </em></strong><em>of the </em><strong><em>Claude Code Power User</em></strong><em> series.</em></p><p><em>Originally published at </em><a href="https://www.koriigami.com/blog/parallel-claude-code-agents?utm_source=medium&amp;utm_medium=referral&amp;utm_campaign=organic"><em>https://koriigami.com</em></a><em> on April 24, 2026.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=927d70e7349d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Claude Code Hooks: Automate What Claude Should Always Do]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@koriigami/claude-code-hooks-automate-what-claude-should-always-do-d1cd4b031a30?source=rss-c2491c06adc7------2"><img src="https://cdn-images-1.medium.com/max/1200/1*bIBbD6jO0QACvKb1RYWGWQ.png" width="1200"></a></p><p class="medium-feed-snippet">You ask Claude Code to write a feature, add tests, format the files, and commit when done.</p><p class="medium-feed-link"><a href="https://medium.com/@koriigami/claude-code-hooks-automate-what-claude-should-always-do-d1cd4b031a30?source=rss-c2491c06adc7------2">Continue reading on Medium »</a></p></div>]]></description>
            <link>https://medium.com/@koriigami/claude-code-hooks-automate-what-claude-should-always-do-d1cd4b031a30?source=rss-c2491c06adc7------2</link>
            <guid isPermaLink="false">https://medium.com/p/d1cd4b031a30</guid>
            <category><![CDATA[automation]]></category>
            <category><![CDATA[productivity]]></category>
            <category><![CDATA[claude-code]]></category>
            <category><![CDATA[claude]]></category>
            <category><![CDATA[ai]]></category>
            <dc:creator><![CDATA[Ketan Damle]]></dc:creator>
            <pubDate>Fri, 24 Apr 2026 05:01:01 GMT</pubDate>
            <atom:updated>2026-05-01T16:22:08.041Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[How I Audited My Claude Code Setup Across 15 Projects (And Found Hardcoded Credentials)]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@koriigami/how-i-audited-my-claude-code-setup-across-15-projects-and-found-hardcoded-credentials-4f7c5d6cf119?source=rss-c2491c06adc7------2"><img src="https://cdn-images-1.medium.com/max/1200/1*-JLhSBm-yEtsyoB1WAPMjg.png" width="1200"></a></p><p class="medium-feed-snippet">What reading every .claude/settings.json file I own taught me about the permission model, and why your config file is more powerful than&#x2026;</p><p class="medium-feed-link"><a href="https://medium.com/@koriigami/how-i-audited-my-claude-code-setup-across-15-projects-and-found-hardcoded-credentials-4f7c5d6cf119?source=rss-c2491c06adc7------2">Continue reading on Medium »</a></p></div>]]></description>
            <link>https://medium.com/@koriigami/how-i-audited-my-claude-code-setup-across-15-projects-and-found-hardcoded-credentials-4f7c5d6cf119?source=rss-c2491c06adc7------2</link>
            <guid isPermaLink="false">https://medium.com/p/4f7c5d6cf119</guid>
            <category><![CDATA[claude-code]]></category>
            <category><![CDATA[claude]]></category>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[automation]]></category>
            <category><![CDATA[productivity]]></category>
            <dc:creator><![CDATA[Ketan Damle]]></dc:creator>
            <pubDate>Fri, 24 Apr 2026 00:00:44 GMT</pubDate>
            <atom:updated>2026-05-19T06:22:50.334Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Google Analytics in Next.js 15+ with @next/third-parties]]></title>
            <link>https://medium.com/@koriigami/google-analytics-in-next-js-15-with-next-third-parties-164be149e7b7?source=rss-c2491c06adc7------2</link>
            <guid isPermaLink="false">https://medium.com/p/164be149e7b7</guid>
            <category><![CDATA[nextjs]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[analytics]]></category>
            <category><![CDATA[firebase]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Ketan Damle]]></dc:creator>
            <pubDate>Wed, 22 Apr 2026 00:00:32 GMT</pubDate>
            <atom:updated>2026-04-27T04:01:01.320Z</atom:updated>
            <content:encoded><![CDATA[<h4>Adding Google Analytics to a Next.js site used to mean manually injecting script tags, dealing with hydration issues, and hoping you didn’t break SSR. Next.js 15 introduced @next/third-parties, an official package that handles the messy parts for you.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*9iDPm4TzgNuBEcPc.png" /></figure><p>This guide covers the setup, custom event tracking, and common gotchas.</p><h3>Why @next/third-parties</h3><p>Before this package, the typical approach was:</p><pre>// The old way - manual Script component<br>import Script from &#39;next/script&#39;;<br> <br>export default function Layout({ children }) {<br>  return (<br>    &lt;html&gt;<br>      &lt;head&gt;<br>        &lt;Script<br>          src={`https://www.googletagmanager.com/gtag/js?id=G-XXXXX`}<br>          strategy=&quot;afterInteractive&quot;<br>        /&gt;<br>        &lt;Script id=&quot;gtag-init&quot; strategy=&quot;afterInteractive&quot;&gt;<br>          {`<br>            window.dataLayer = window.dataLayer || [];<br>            function gtag(){dataLayer.push(arguments);}<br>            gtag(&#39;js&#39;, new Date());<br>            gtag(&#39;config&#39;, &#39;G-XXXXX&#39;);<br>          `}<br>        &lt;/Script&gt;<br>      &lt;/head&gt;<br>      &lt;body&gt;{children}&lt;/body&gt;<br>    &lt;/html&gt;<br>  );<br>}</pre><p>This works, but you’re managing script loading yourself. The @next/third-parties package wraps this in a component that:</p><ul><li>Handles script loading timing correctly</li><li>Avoids hydration mismatches</li><li>Provides a typed sendGAEvent function for custom events</li><li>Follows Next.js best practices for third-party scripts</li></ul><h3>Installation</h3><pre>npm install @next/third-parties</pre><p>That’s it. No additional dependencies.</p><h3>Basic setup</h3><p>Add the GoogleAnalytics component to your root layout:</p><pre>// app/layout.tsx<br>import { GoogleAnalytics } from &#39;@next/third-parties/google&#39;;<br> <br>export default function RootLayout({<br>  children,<br>}: {<br>  children: React.ReactNode;<br>}) {<br>  return (<br>    &lt;html lang=&quot;en&quot;&gt;<br>      &lt;body&gt;<br>        {children}<br>        &lt;GoogleAnalytics gaId=&quot;G-XXXXXXXXXX&quot; /&gt;<br>      &lt;/body&gt;<br>    &lt;/html&gt;<br>  );<br>}</pre><p>Replace G-XXXXXXXXXX with your measurement ID from Google Analytics.</p><h3>Finding your measurement ID</h3><ol><li>Go to <a href="https://analytics.google.com/">Google Analytics</a></li><li>Admin (gear icon) → Data Streams</li><li>Click your web stream</li><li>Copy the Measurement ID (starts with G-)</li></ol><h3>Environment variable setup</h3><p>Hardcoding the GA ID works, but using an environment variable is cleaner:</p><pre># .env.local<br>NEXT_PUBLIC_GOOGLE_ANALYTICS_ID=G-XXXXXXXXXX</pre><pre>// app/layout.tsx<br>import { GoogleAnalytics } from &#39;@next/third-parties/google&#39;;<br> <br>export default function RootLayout({<br>  children,<br>}: {<br>  children: React.ReactNode;<br>}) {<br>  const gaId = process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS_ID;<br> <br>  return (<br>    &lt;html lang=&quot;en&quot;&gt;<br>      &lt;body&gt;<br>        {children}<br>        {gaId &amp;&amp; &lt;GoogleAnalytics gaId={gaId} /&gt;}<br>      &lt;/body&gt;<br>    &lt;/html&gt;<br>  );<br>}</pre><p>The NEXT_PUBLIC_ prefix is required because the GA ID needs to be available client-side.</p><h3>Production-only tracking</h3><p>You probably don’t want analytics running during development. Add an environment check:</p><pre>// app/layout.tsx<br>import { GoogleAnalytics } from &#39;@next/third-parties/google&#39;;<br> <br>export default function RootLayout({<br>  children,<br>}: {<br>  children: React.ReactNode;<br>}) {<br>  const gaId = process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS_ID;<br>  const isProduction = process.env.NODE_ENV === &#39;production&#39;;<br> <br>  return (<br>    &lt;html lang=&quot;en&quot;&gt;<br>      &lt;body&gt;<br>        {children}<br>        {gaId &amp;&amp; isProduction &amp;&amp; &lt;GoogleAnalytics gaId={gaId} /&gt;}<br>      &lt;/body&gt;<br>    &lt;/html&gt;<br>  );<br>}</pre><p>Now analytics only loads in production builds.</p><h3>Pageview tracking</h3><p>Good news: you don’t need to do anything special. Google Analytics automatically tracks pageviews when the browser history state changes. This means client-side navigations between Next.js routes send pageview data without configuration.</p><p>For this to work, make sure “Enhanced Measurement” is enabled in your GA property:</p><ol><li>Admin → Data Streams → Select your stream</li><li>Enhanced measurement → Toggle on</li><li>Ensure “Page changes based on browser history events” is checked</li></ol><h3>Custom event tracking</h3><p>Pageviews are automatic, but you’ll want to track specific user actions: button clicks, form submissions, purchases.</p><h4>The sendGAEvent function</h4><p>Import sendGAEvent from @next/third-parties/google:</p><pre>&#39;use client&#39;;<br> <br>import { sendGAEvent } from &#39;@next/third-parties/google&#39;;<br> <br>export function BookingButton() {<br>  const handleClick = () =&gt; {<br>    sendGAEvent(&#39;event&#39;, &#39;booking_started&#39;, {<br>      service_type: &#39;consultation&#39;,<br>    });<br> <br>    // Continue with booking logic...<br>  };<br> <br>  return (<br>    &lt;button onClick={handleClick}&gt;<br>      Book Now<br>    &lt;/button&gt;<br>  );<br>}</pre><p>The function signature is:</p><pre>sendGAEvent(command: string, eventName: string, eventParams?: object)</pre><ul><li>command is usually &#39;event&#39;</li><li>eventName is your custom event name</li><li>eventParams is an optional object with additional data</li></ul><h4>Common event patterns</h4><p><strong>Button clicks:</strong></p><pre>sendGAEvent(&#39;event&#39;, &#39;cta_clicked&#39;, {<br>  button_text: &#39;Get Started&#39;,<br>  page_location: window.location.pathname,<br>});</pre><p><strong>Form submissions:</strong></p><pre>const handleSubmit = async (formData: FormData) =&gt; {<br>  const result = await submitForm(formData);<br> <br>  if (result.success) {<br>    sendGAEvent(&#39;event&#39;, &#39;form_submitted&#39;, {<br>      form_name: &#39;contact&#39;,<br>    });<br>  }<br>};</pre><p><strong>External link clicks:</strong></p><pre>&lt;a<br>  href=&quot;https://external-site.com&quot;<br>  target=&quot;_blank&quot;<br>  onClick={() =&gt; sendGAEvent(&#39;event&#39;, &#39;external_link_clicked&#39;, {<br>    destination: &#39;https://external-site.com&#39;,<br>  })}<br>&gt;<br>  Visit Partner Site<br>&lt;/a&gt;</pre><p><strong>Service selection:</strong></p><pre>const handleServiceSelect = (serviceName: string) =&gt; {<br>  sendGAEvent(&#39;event&#39;, &#39;service_selected&#39;, {<br>    service_name: serviceName,<br>  });<br> <br>  // Navigate to booking page...<br>};</pre><h3>Creating a tracking utility</h3><p>For larger apps, wrap sendGAEvent in a utility file:</p><pre>// lib/analytics.ts<br>&#39;use client&#39;;<br> <br>import { sendGAEvent } from &#39;@next/third-parties/google&#39;;<br> <br>export const analytics = {<br>  trackEvent: (eventName: string, params?: Record&lt;string, string | number&gt;) =&gt; {<br>    sendGAEvent(&#39;event&#39;, eventName, params);<br>  },<br> <br>  trackPageView: (pagePath: string) =&gt; {<br>    sendGAEvent(&#39;event&#39;, &#39;page_view&#39;, {<br>      page_path: pagePath,<br>    });<br>  },<br> <br>  trackButtonClick: (buttonName: string, location?: string) =&gt; {<br>    sendGAEvent(&#39;event&#39;, &#39;button_clicked&#39;, {<br>      button_name: buttonName,<br>      page_location: location || window.location.pathname,<br>    });<br>  },<br> <br>  trackFormSubmission: (formName: string, success: boolean) =&gt; {<br>    sendGAEvent(&#39;event&#39;, &#39;form_submission&#39;, {<br>      form_name: formName,<br>      success: success ? &#39;true&#39; : &#39;false&#39;,<br>    });<br>  },<br> <br>  trackBookingStarted: (serviceType: string) =&gt; {<br>    sendGAEvent(&#39;event&#39;, &#39;booking_started&#39;, {<br>      service_type: serviceType,<br>    });<br>  },<br> <br>  trackBookingCompleted: (serviceType: string, bookingId: string) =&gt; {<br>    sendGAEvent(&#39;event&#39;, &#39;booking_completed&#39;, {<br>      service_type: serviceType,<br>      booking_id: bookingId,<br>    });<br>  },<br>};</pre><p>Usage:</p><pre>&#39;use client&#39;;<br> <br>import { analytics } from &#39;@/lib/analytics&#39;;<br> <br>export function ContactForm() {<br>  const handleSubmit = async (e: React.FormEvent) =&gt; {<br>    e.preventDefault();<br> <br>    const result = await submitContactForm(formData);<br>    analytics.trackFormSubmission(&#39;contact&#39;, result.success);<br>  };<br> <br>  return &lt;form onSubmit={handleSubmit}&gt;...&lt;/form&gt;;<br>}</pre><h3>Event naming conventions</h3><p>Google Analytics has some rules for event names:</p><ul><li>Must be 40 characters or fewer</li><li>Must start with a letter</li><li>Can only contain letters, numbers, and underscores</li><li>Case-sensitive (button_clicked and Button_Clicked are different events)</li></ul><p>Use snake_case for consistency:</p><pre>// Good<br>sendGAEvent(&#39;event&#39;, &#39;booking_completed&#39;, { ... });<br>sendGAEvent(&#39;event&#39;, &#39;contact_form_submitted&#39;, { ... });<br> <br>// Avoid<br>sendGAEvent(&#39;event&#39;, &#39;Booking Completed&#39;, { ... });<br>sendGAEvent(&#39;event&#39;, &#39;contact-form-submitted&#39;, { ... });</pre><h3>Debugging analytics</h3><h4>Check if the script loads</h4><p>Open browser DevTools → Network tab → Filter by “google”. You should see requests to googletagmanager.com.</p><h4>Use GA Debug mode</h4><p>Install the <a href="https://chrome.google.com/webstore/detail/google-analytics-debugger/jnkmfdileelhofjcijamephohjechhna">Google Analytics Debugger</a> Chrome extension. It logs all GA events to the console.</p><h4>Real-time reports</h4><p>In Google Analytics:</p><ol><li>Reports → Realtime</li><li>Open your site in another tab</li><li>Watch events appear as they happen</li></ol><blockquote>Events show up in realtime within seconds. Standard reports can take 24–48 hours to populate.</blockquote><h4>Verify the tag is detected</h4><ol><li>Admin → Data Streams → Select your stream</li><li>Click “Test your connection”</li><li>Enter your URL</li><li>Should show “Your Google tag was correctly detected”</li></ol><h3>Common issues</h3><h4>Events not showing up</h4><p><strong>Check the environment:</strong> Events only fire in production if you added the isProduction check. For testing, temporarily remove that condition.</p><p><strong>Wrong measurement ID:</strong> Double-check the ID. Typos are common.</p><p><strong>Ad blockers:</strong> Many ad blockers prevent GA scripts from loading. Test in incognito mode with extensions disabled.</p><h4>Duplicate pageviews</h4><p>If you’re seeing duplicate pageviews, you might have both the old Script method and the new GoogleAnalytics component. Use one or the other, not both.</p><h4>Events not attached to the right page</h4><p>When tracking events, the page URL is automatically captured. If you need to override it:</p><pre>sendGAEvent(&#39;event&#39;, &#39;custom_event&#39;, {<br>  page_location: &#39;/custom/path&#39;,<br>  page_title: &#39;Custom Page Title&#39;,<br>});</pre><h4>sendGAEvent is undefined</h4><p>Make sure:</p><ol><li>The GoogleAnalytics component is in your layout</li><li>You’re calling sendGAEvent in a client component (&#39;use client&#39;)</li><li>The component has mounted (events won’t fire during SSR)</li></ol><h3>TypeScript types</h3><p>The sendGAEvent function accepts any object for eventParams. For type safety, define your event types:</p><pre>// lib/analytics.ts<br> <br>type EventParams = {<br>  button_clicked: {<br>    button_name: string;<br>    page_location: string;<br>  };<br>  form_submitted: {<br>    form_name: string;<br>    success: boolean;<br>  };<br>  booking_completed: {<br>    service_type: string;<br>    booking_id: string;<br>  };<br>};<br> <br>export function trackEvent&lt;T extends keyof EventParams&gt;(<br>  eventName: T,<br>  params: EventParams[T]<br>) {<br>  sendGAEvent(&#39;event&#39;, eventName, params);<br>}</pre><p>Now you get autocomplete and type checking:</p><pre>// Type-safe<br>trackEvent(&#39;button_clicked&#39;, { button_name: &#39;cta&#39;, page_location: &#39;/home&#39; });<br> <br>// Type error - missing page_location<br>trackEvent(&#39;button_clicked&#39;, { button_name: &#39;cta&#39; });</pre><h3>Privacy considerations</h3><h4>Cookie consent</h4><p>Depending on your audience, you may need cookie consent before loading GA. Common pattern:</p><pre>&#39;use client&#39;;<br> <br>import { GoogleAnalytics } from &#39;@next/third-parties/google&#39;;<br>import { useState, useEffect } from &#39;react&#39;;<br> <br>export function AnalyticsWrapper() {<br>  const [consentGiven, setConsentGiven] = useState(false);<br> <br>  useEffect(() =&gt; {<br>    const consent = localStorage.getItem(&#39;analytics_consent&#39;);<br>    if (consent === &#39;true&#39;) {<br>      setConsentGiven(true);<br>    }<br>  }, []);<br> <br>  if (!consentGiven) return null;<br> <br>  return &lt;GoogleAnalytics gaId={process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS_ID!} /&gt;;<br>}</pre><p>Then conditionally render in layout:</p><pre>&lt;body&gt;<br>  {children}<br>  &lt;AnalyticsWrapper /&gt;<br>  &lt;CookieBanner onAccept={() =&gt; { /* trigger re-render */ }} /&gt;<br>&lt;/body&gt;</pre><h4>IP anonymization</h4><p>GA4 anonymizes IP addresses by default. You don’t need to configure anything extra.</p><h3>File structure</h3><pre>app/<br>  layout.tsx          # GoogleAnalytics component<br>lib/<br>  analytics.ts        # Optional: tracking utility functions<br>.env.local              # NEXT_PUBLIC_GOOGLE_ANALYTICS_ID</pre><h3>Key takeaways</h3><blockquote>Use @next/third-parties instead of manual script injection. Pageviews are tracked automatically with Enhanced Measurement. Use sendGAEvent for custom events in client components. Add a NODE_ENV === &#39;production&#39; check to avoid dev tracking.</blockquote><p>The @next/third-parties package removes the friction from GA setup. Add the component, configure your measurement ID, and you&#39;re tracking. Custom events are one function call. No manual script management, no hydration issues.</p><h3>Going further: Looker Studio for client reporting</h3><p>Setting up GA4 on your site is one thing. When a client asks “how is my website performing?” — they don’t want to navigate Google Analytics. They want a clean dashboard with a date picker and the five numbers they actually care about.</p><p><a href="https://lookerstudio.google.com/">Looker Studio</a> connects directly to GA4 and lets you build that dashboard without any code.</p><h4>Connecting GA4 to Looker Studio</h4><ol><li>Go to <a href="https://lookerstudio.google.com/">lookerstudio.google.com</a> and create a new report</li><li>Click <strong>Add data</strong> → search for <strong>Google Analytics</strong></li><li>Select your GA4 property → click <strong>Add</strong></li></ol><p>That’s the connection. All GA4 data is now available as dimensions and metrics in Looker Studio.</p><h4>What to include in the dashboard</h4><p>I built this for a client who is a mental well-being life coach — she publishes articles frequently and drives traffic from LinkedIn and Facebook. She needed answers to specific questions, not a full analytics education.</p><p><strong>Overview</strong></p><ul><li>Date range control — lets her toggle between last 7, 30, or a custom range herself</li><li>Scorecards: total sessions, total users, average engagement time</li></ul><p><strong>Audience</strong></p><ul><li>Device category breakdown (desktop / mobile / tablet)</li><li>Top countries by sessions</li><li>Top browsers and operating systems</li></ul><p><strong>Traffic sources</strong></p><ul><li>Session source / medium table — shows whether traffic is coming from LinkedIn, Facebook, direct, organic search, or email</li><li>With UTM parameters on her links, this table shows exactly which post or campaign drove each visit</li></ul><p><strong>Content performance</strong></p><ul><li>Top viewed pages</li><li>Top 5 articles by sessions — essential if your client publishes content regularly and wants to know what resonates</li></ul><h4>UTM tracking for content creators</h4><p>UTM parameters are the difference between “traffic came from Facebook” and “traffic came from that specific post you published last Tuesday.”</p><p>Add them to every link your client shares:</p><pre>https://example.com/blog/article-slug?utm_source=facebook&amp;utm_medium=social&amp;utm_campaign=march-content</pre><p>The Session Source / Medium chart in Looker Studio will label them exactly as you’ve set. Your client sees at a glance which content channel is actually driving visitors — not just which platform.</p><h3>When Looker Studio is worth setting up</h3><p>Not every client needs a custom dashboard — GA4’s built-in reports are sufficient for most. Looker Studio earns its setup time when:</p><ul><li>Your client doesn’t want to learn the GA4 interface</li><li>Multiple stakeholders need to view the same data</li><li>The client publishes content regularly and wants to track performance systematically</li><li>You want to combine GA4 with other data sources (Google Search Console, Sheets)</li></ul><p><em>Originally published at </em><a href="https://www.koriigami.com/blog/google-analytics-nextjs"><em>https://www.koriigami.com</em></a><em> on April 22, 2026.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=164be149e7b7" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>