<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Thryx</title>
    <description>The latest articles on DEV Community by Thryx (@thryx).</description>
    <link>https://dev.to/thryx</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3911321%2Fba62a579-36d3-4022-a33c-0e30ad8df208.png</url>
      <title>DEV Community: Thryx</title>
      <link>https://dev.to/thryx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thryx"/>
    <language>en</language>
    <item>
      <title>How to Use Subagents in Claude Code</title>
      <dc:creator>Thryx</dc:creator>
      <pubDate>Thu, 16 Jul 2026 19:00:03 +0000</pubDate>
      <link>https://dev.to/thryx/how-to-use-subagents-in-claude-code-30a7</link>
      <guid>https://dev.to/thryx/how-to-use-subagents-in-claude-code-30a7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is a cross-post — the original (and any updates) live at &lt;a href="https://broke2builtai.com/guides/how-to-use-subagents-in-claude-code/" rel="noopener noreferrer"&gt;broke2builtai.com&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Long Claude Code sessions die the same way every time: the context window fills up with search results, file dumps, and dead-end exploration, and the model gets dumber right when you need it sharp. Subagents are the built-in fix — separate workers that do the messy digging in their &lt;em&gt;own&lt;/em&gt; context and hand back only the conclusion. Here's how to actually use them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a subagent actually is
&lt;/h2&gt;

&lt;p&gt;A subagent is a separate agent instance that Claude Code spins up with its own context window. It gets a task, works it — reading files, grepping, reasoning — and returns a single result message to the main conversation. All the intermediate noise stays in the subagent's context and dies with it.&lt;/p&gt;

&lt;p&gt;That buys you three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A clean main context.&lt;/strong&gt; The subagent burns its own tokens exploring; your main conversation only receives the conclusion. Fifty file reads on its side show up as one summary on yours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallel work.&lt;/strong&gt; Multiple subagents can run at once. Three independent questions, three workers, answered simultaneously instead of serially.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Specialization.&lt;/strong&gt; A custom subagent carries its own system prompt and its own tool restrictions, so it behaves like a focused specialist instead of a generalist with your whole session on its mind.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Triggering one: automatic vs explicit
&lt;/h2&gt;

&lt;p&gt;You don't have to configure anything to start. Claude decides to delegate on its own when a task looks like broad search or research — "find everywhere we handle auth" is the kind of thing it will hand to a subagent without being asked.&lt;/p&gt;

&lt;p&gt;When you want control, ask explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use a subagent to find every place we construct SQL queries by hand

spawn an agent to research how the payment webhook flow works, then summarize it
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plain language is the interface. Say "subagent" or "spawn an agent" and describe the task; Claude handles the rest.&lt;/p&gt;

&lt;p&gt;One thing to know about the plumbing: subagent results come back to the &lt;em&gt;main agent&lt;/em&gt;, not directly to you. The main agent reads the result and summarizes it in its reply. You're always talking to the coordinator, never the worker.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a custom subagent
&lt;/h2&gt;

&lt;p&gt;The real power move is defining your own. A custom subagent is one Markdown file with YAML frontmatter, and it lives in one of two places:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;.claude/agents/&lt;/code&gt;&lt;/strong&gt; in your repo — project-level. Commit it and your whole team gets the same specialist.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;~/.claude/agents/&lt;/code&gt;&lt;/strong&gt; — personal, available in every project you open.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a read-only code reviewer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;code-reviewer&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;this&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;agent&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;when&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;has&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;just&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;been&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;written&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;or&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;modified&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;needs&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;review.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Checks&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;bugs,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;security&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;issues,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;convention&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;violations&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;before&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;anything&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ships."&lt;/span&gt;
&lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Read, Grep, Glob&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

You are a senior code reviewer. Review the changes you're pointed at
for correctness bugs first, then security issues, then convention
violations. Be specific: file and line, what's wrong, why it matters.
Do not suggest rewrites of code that works. Report findings ranked
by severity, worst first.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four frontmatter fields matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;name&lt;/code&gt;&lt;/strong&gt; — kebab-case identifier.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;description&lt;/code&gt;&lt;/strong&gt; — when Claude should use it. This is the routing signal; more on it below, because it's where most subagents fail.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;tools&lt;/code&gt;&lt;/strong&gt; — optional allowlist. Everything not listed is off the table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;model&lt;/code&gt;&lt;/strong&gt; — optional; pin the model this subagent runs on.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything below the frontmatter is the subagent's system prompt. If you've read &lt;a href="https://dev.to/guides/how-to-write-a-system-prompt-for-an-ai-agent/"&gt;how to write a system prompt for an AI agent&lt;/a&gt;, all of it applies here — concrete rules, explicit output shape, no vibes.&lt;/p&gt;

&lt;p&gt;Don't want to hand-write the file? Run &lt;code&gt;/agents&lt;/code&gt; inside Claude Code — it opens an interactive manager for creating and editing subagents.&lt;/p&gt;

&lt;h2&gt;
  
  
  The description is the routing signal — write it like a trigger
&lt;/h2&gt;

&lt;p&gt;Claude reads the &lt;code&gt;description&lt;/code&gt; field to decide when to delegate. That makes it the single most important line in the file. Write it as a trigger condition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Weak — Claude has no idea when to reach for this&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;A helpful agent for code quality.&lt;/span&gt;

&lt;span class="c1"&gt;# Strong — reads like a rule Claude can match against&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Use this agent when code has just been written or modified and needs review.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;"Use this agent when…" followed by concrete situations is the pattern that works. If your subagent never fires automatically, fix the description before you touch anything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Restrict tools — it's a safety feature, not a nicety
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;tools&lt;/code&gt; allowlist is what makes specialists trustworthy. A reviewer with only &lt;code&gt;Read, Grep, Glob&lt;/code&gt; &lt;em&gt;cannot&lt;/em&gt; accidentally edit a file, no matter how confused it gets. That's a guarantee, not a hope.&lt;/p&gt;

&lt;p&gt;Good candidates for the specialist treatment, each with tools scoped to the job:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code reviewer&lt;/strong&gt; — read-only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test runner/fixer&lt;/strong&gt; — needs to run commands and edit test files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs writer&lt;/strong&gt; — read plus write, no shell.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security auditor&lt;/strong&gt; — read-only, again.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read-only explorer&lt;/strong&gt; — for "map this codebase" jobs where you want zero chance of side effects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One structural limit to design around: a subagent cannot spawn further subagents. Delegation goes one level deep, so the main agent is always the coordinator fanning work out — build your workflows with that shape in mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest trade-off
&lt;/h2&gt;

&lt;p&gt;Subagents are not free. Each one spins up its own instance, which means added latency before you see anything, and its exploration burns tokens even though they never land in your context. For a single quick file lookup, direct search is flat-out better — don't spawn a worker to answer a one-line grep.&lt;/p&gt;

&lt;p&gt;The rule of thumb: delegate when the search is &lt;strong&gt;broad&lt;/strong&gt; or the task is &lt;strong&gt;self-contained&lt;/strong&gt;. Keep it direct when the answer is one known location away.&lt;/p&gt;

&lt;p&gt;The token side is worth planning around too, since subagents burn tokens even though those tokens never land in your context. If cost is a concern, one option is pointing Claude Code at a cheaper backend — the GLM Coding Plan is one, and I walk through that setup in &lt;a href="https://dev.to/guides/how-to-set-up-claude-code-with-glm-api/"&gt;how to set up Claude Code with the GLM API&lt;/a&gt;. When the exploring is cheap, "spawn three workers" feels like a shrug instead of a bill.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Broke to Built is one broke human + AI agents building real software with no budget, writing down every step. This site's tools run on free GLM — &lt;a href="https://z.ai/subscribe?ic=BWTG6TRYYQ" rel="noopener noreferrer"&gt;z.ai's Coding Plan&lt;/a&gt; is the referral that funds our compute (disclosed affiliate).&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>automation</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Validate a SaaS Idea With No Money</title>
      <dc:creator>Thryx</dc:creator>
      <pubDate>Wed, 15 Jul 2026 19:00:02 +0000</pubDate>
      <link>https://dev.to/thryx/how-to-validate-a-saas-idea-with-no-money-5d6b</link>
      <guid>https://dev.to/thryx/how-to-validate-a-saas-idea-with-no-money-5d6b</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is a cross-post — the original (and any updates) live at &lt;a href="https://broke2builtai.com/guides/how-to-validate-a-saas-idea-with-no-money/" rel="noopener noreferrer"&gt;broke2builtai.com&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The usual way a SaaS idea dies is after months of building — when one week of checking would have killed it for free. That order is backwards, and fixing it costs nothing. Validation isn't a budget problem — every tool you need has a free tier. It's a courage problem: you have to show the idea to strangers before it's real, and accept what they do (not what they say) as the verdict.&lt;/p&gt;

&lt;p&gt;Here's the whole playbook at $0, in the order I'd run it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What validation actually means
&lt;/h2&gt;

&lt;p&gt;Validation is evidence that strangers want the thing enough to give you something: an email, a slot on their calendar, or money. Not your friends. Not people being polite. Strangers, giving something up.&lt;/p&gt;

&lt;p&gt;Y Combinator's motto is "make something people want" — and the only way to know people want it is to watch what they &lt;em&gt;do&lt;/em&gt; when you put the promise in front of them. Everything below is a way of generating that behavior cheaply.&lt;/p&gt;

&lt;p&gt;Two rules before anything else:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Compliments are not data.&lt;/strong&gt; "That's a cool idea" costs the speaker nothing and predicts nothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You are not the customer.&lt;/strong&gt; Even if you have the problem yourself, you're testing whether &lt;em&gt;other people&lt;/em&gt; have it badly enough to act.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The ladder of evidence
&lt;/h2&gt;

&lt;p&gt;Every validation signal sits on a rung. Weakest to strongest:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;People say it's interesting.&lt;/strong&gt; Nearly worthless. Everyone says this about everything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;People give an email for a waitlist.&lt;/strong&gt; A small real cost. Worth something.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;People book and show up to a 15-minute call.&lt;/strong&gt; Time is expensive. This is serious interest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;People pre-order or sign a letter of intent.&lt;/strong&gt; Money or a signature. This is the top.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The whole game is climbing this ladder before you write code. Distrust the bottom rung completely, treat the second rung as a hint, and don't commit months of your life to anything that hasn't touched rung three or four.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Find the complaint before you pitch the cure ($0)
&lt;/h2&gt;

&lt;p&gt;Before you talk to anyone, go read what people already say when nobody's pitching them. Search Reddit and niche forums for the problem — not your product, the &lt;em&gt;problem&lt;/em&gt;. Look for phrases like "how do you deal with," "is there a tool for," "I'm so sick of."&lt;/p&gt;

&lt;p&gt;You're reading, not posting. Do not spam communities with your idea — that burns the channel you'll need later. What you want from this step:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The exact words people use to describe the pain (this becomes your landing page headline).&lt;/li&gt;
&lt;li&gt;What they currently do about it — spreadsheets, duct-taped tools, paying a VA, nothing.&lt;/li&gt;
&lt;li&gt;Whether the complaint shows up repeatedly or you had to dig for one thread from three years ago.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you can't find anyone complaining, that's your first data point, and it's not a good one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Run 5-10 problem interviews
&lt;/h2&gt;

&lt;p&gt;Find 5-10 people who plausibly have the problem and get them talking. The one rule that makes or breaks this: &lt;strong&gt;ask about their current behavior and past attempts, never about your idea.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;"Would you use a tool that does X?" gets you a polite yes and zero information. People say yes to be nice. Instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Walk me through the last time this happened."&lt;/li&gt;
&lt;li&gt;"What did you do about it?"&lt;/li&gt;
&lt;li&gt;"What have you tried before? What did you pay for it?"&lt;/li&gt;
&lt;li&gt;"What happened after that?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Past behavior is evidence. If they've never tried to solve the problem — never searched for a tool, never hacked a spreadsheet, never paid anyone — the pain probably isn't real enough to sustain a product, no matter how enthusiastically they nod.&lt;/p&gt;

&lt;p&gt;Reaching out cold is the uncomfortable part, and it's also free. A short, honest message — "I'm researching how people handle X, can I ask you three questions?" — outperforms anything clever. If writing that outreach note is what's stopping you, the same structure I use in &lt;a href="https://dev.to/guides/chatgpt-prompt-to-write-a-professional-email/"&gt;the professional email prompt guide&lt;/a&gt; works for this: context, one clear ask, easy out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Put up a landing page and a waitlist ($0)
&lt;/h2&gt;

&lt;p&gt;Now turn the language from steps 1 and 2 into a one-page test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One sentence stating the promise.&lt;/strong&gt; Use the words your interviewees used, not your clever positioning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One CTA.&lt;/strong&gt; Join the waitlist. That's it — no nav, no feature grid, no pricing page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total transparency.&lt;/strong&gt; Say it's upcoming. No fake "Buy now" button that takes card details for a product that doesn't exist. You're measuring pull, not tricking people.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The free stack: &lt;a href="https://carrd.co" rel="noopener noreferrer"&gt;Carrd&lt;/a&gt; has a free tier that handles a one-page site fine, or throw plain HTML on any free subdomain you already have access to. For the form, Google Forms is free forever, and Tally's free tier embeds cleanly if you want it to look less like a survey. Wire the CTA to the form, and you have a functioning validation machine for exactly $0.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Drive small, genuine traffic and measure
&lt;/h2&gt;

&lt;p&gt;A landing page with no visitors measures nothing. But you don't need an ad budget — you need a handful of real humans from communities you &lt;em&gt;actually belong to&lt;/em&gt;. Share it where you already participate, framed honestly: "I'm exploring this, does it resonate?" A few dozen genuine visitors tell you more than a thousand bought clicks, because you know exactly who they are and why they came.&lt;/p&gt;

&lt;p&gt;Watch one number: signup rate — emails collected per real visitor. Don't obsess over the absolute count; obsess over whether people who have the problem convert when they see the promise stated in their own words.&lt;/p&gt;

&lt;p&gt;Then climb. Email the waitlist and ask for a 15-minute call (rung three). On the calls, if the pain is real, ask the money question: "If I build this, would you pre-pay for the first month?" or, for anything B2B-shaped, "would you sign a letter of intent?" (rung four). Every rung people climb willingly is evidence. Every rung they refuse is also evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set your kill criteria before you start
&lt;/h2&gt;

&lt;p&gt;This is the step everyone skips, and it's the one that protects the only capital you actually have: your time.&lt;/p&gt;

&lt;p&gt;Before you run any of the above, write down what result means "drop it." For example: &lt;em&gt;if after a week of genuine effort I can't find 10 people who care enough to give an email or take a call, this idea is dead.&lt;/em&gt; Whatever your line is, set it while you're still objective — because after two weeks of effort, sunk cost will happily move the goalposts for you.&lt;/p&gt;

&lt;p&gt;A killed idea after one week is a win. The same idea killed after six months of building is the disaster this whole process exists to prevent.&lt;/p&gt;

&lt;h2&gt;
  
  
  The broke-builder edge: let AI do the grunt work
&lt;/h2&gt;

&lt;p&gt;Here's what's changed about this playbook: the mechanical parts now take minutes instead of days. An AI agent will draft your landing page copy, your survey questions, your outreach messages, and five headline variants to test — faster than you can make coffee. If you're setting up agents to do that kind of drafting reliably, the structure matters more than the model; that's exactly what &lt;a href="https://dev.to/guides/how-to-write-a-system-prompt-for-an-ai-agent/"&gt;how to write a system prompt for an AI agent&lt;/a&gt; covers. And the quality of what comes back tracks the quality of what you feed in — Meta-Prompt Architect is the tool I built for turning a rough "draft my landing copy" into a reusable, high-signal instruction, so the agent's first pass is usable instead of generic.&lt;/p&gt;

&lt;p&gt;I run my own drafting and build agents through Claude Code pointed at the GLM Coding Plan, which keeps the token bill near zero — the setup is in &lt;a href="https://dev.to/guides/how-to-set-up-claude-code-with-glm-api/"&gt;how to set up Claude Code with the GLM API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But be clear-eyed about what AI does and doesn't buy you here. It compresses the &lt;em&gt;cheap&lt;/em&gt; parts. The scarce input in validation was never the code or the copy — it's honest contact with strangers. No agent can sit through a problem interview for you, and no model can make a stranger hand over an email they don't want to give. That part is still yours, and it's the part that counts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this fits
&lt;/h2&gt;

&lt;p&gt;The whole sequence — complaints → interviews → landing page → traffic → calls → money — runs on Google Forms, Carrd or a free subdomain, Tally, Reddit search, and your own nerve. Zero dollars, one to two weeks, and at the end you either have strangers' emails and booked calls, or you have a clean kill and your next idea.&lt;/p&gt;

&lt;p&gt;Since the building itself is nearly free now too (cheap tokens, see the &lt;a href="https://dev.to/guides/how-to-set-up-claude-code-with-glm-api/"&gt;GLM setup guide&lt;/a&gt;), the temptation is to skip validation entirely because "I can just build it in a weekend." Resist that. Cheap building makes validation &lt;em&gt;more&lt;/em&gt; valuable, not less: when everyone can ship, the only edge left is knowing what's worth shipping. Climb the ladder first.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Broke to Built is one broke human + AI agents building real software with no budget, writing down every step. This site's tools run on free GLM — &lt;a href="https://z.ai/subscribe?ic=BWTG6TRYYQ" rel="noopener noreferrer"&gt;z.ai's Coding Plan&lt;/a&gt; is the referral that funds our compute (disclosed affiliate).&lt;/em&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Use Claude Code Plugins (Install from a Marketplace or Build Your Own)</title>
      <dc:creator>Thryx</dc:creator>
      <pubDate>Tue, 14 Jul 2026 19:00:09 +0000</pubDate>
      <link>https://dev.to/thryx/how-to-use-claude-code-plugins-install-from-a-marketplace-or-build-your-own-574</link>
      <guid>https://dev.to/thryx/how-to-use-claude-code-plugins-install-from-a-marketplace-or-build-your-own-574</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is a cross-post — the original (and any updates) live at &lt;a href="https://broke2builtai.com/guides/how-to-use-claude-code-plugins/" rel="noopener noreferrer"&gt;broke2builtai.com&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My Claude Code setup took months to accrete: a review command here, a formatting hook there, an MCP server for the database, a subagent for QA. Then I started a second project and discovered the setup didn't come with me — it was smeared across four config surfaces in the first repo, and "install my tooling" meant a twenty-minute archaeology dig through my own dotfiles. Plugins are Claude Code's answer to exactly that problem: one directory that bundles all of it, installable with one command.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a plugin actually is
&lt;/h2&gt;

&lt;p&gt;A plugin is a folder with a manifest. Inside it, the same primitives you can already wire up by hand, packaged to travel together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Skills and commands&lt;/strong&gt; — the prompt templates behind &lt;code&gt;/name&lt;/code&gt; invocations, the same format as a &lt;a href="https://dev.to/guides/how-to-create-a-custom-slash-command-in-claude-code/"&gt;custom slash command&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agents&lt;/strong&gt; — subagent definitions that show up in &lt;code&gt;/agents&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hooks&lt;/strong&gt; — lifecycle event handlers, same schema as &lt;a href="https://dev.to/guides/how-to-use-claude-code-hooks/"&gt;Claude Code hooks&lt;/a&gt; in your settings, just living in &lt;code&gt;hooks/hooks.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP servers&lt;/strong&gt; — a bundled &lt;code&gt;.mcp.json&lt;/code&gt;, so installing the plugin connects the tools without anyone running &lt;a href="https://dev.to/guides/how-to-add-an-mcp-server-to-claude-code/"&gt;&lt;code&gt;claude mcp add&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Plugins can also carry LSP servers for code intelligence, background monitors, and executables — but the four above are the ones you'll actually package first.&lt;/p&gt;

&lt;p&gt;The one behavioral difference from hand-wired pieces: &lt;strong&gt;namespacing.&lt;/strong&gt; A skill named &lt;code&gt;hello&lt;/code&gt; in a plugin named &lt;code&gt;my-plugin&lt;/code&gt; is invoked as &lt;code&gt;/my-plugin:hello&lt;/code&gt;, not &lt;code&gt;/hello&lt;/code&gt;. That's deliberate — two plugins can both ship a &lt;code&gt;deploy&lt;/code&gt; skill without colliding. Your own standalone &lt;code&gt;.claude/&lt;/code&gt; files keep their short names.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install one from a marketplace in two minutes
&lt;/h2&gt;

&lt;p&gt;A marketplace is a catalog — a repo or URL that lists plugins and where to fetch them. Using one is a two-step deal: add the catalog, then install individual plugins from it. Think app store: adding the store installs nothing.&lt;/p&gt;

&lt;p&gt;Anthropic's official marketplace (&lt;code&gt;claude-plugins-official&lt;/code&gt;) is registered automatically. Run &lt;code&gt;/plugin&lt;/code&gt; inside a session and you get a tabbed manager — &lt;strong&gt;Discover&lt;/strong&gt;, &lt;strong&gt;Installed&lt;/strong&gt;, &lt;strong&gt;Marketplaces&lt;/strong&gt;, &lt;strong&gt;Errors&lt;/strong&gt;, cycled with Tab. Browse Discover, hit Enter on a plugin, and the details pane shows what it contains, its context cost in tokens, and a "Will install" inventory before you commit.&lt;/p&gt;

&lt;p&gt;Or skip the browsing and install directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/plugin &lt;span class="nb"&gt;install &lt;/span&gt;github@claude-plugins-official
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For third-party catalogs, add the marketplace first. The community marketplace — where reviewed third-party submissions land, each pinned to a specific commit — is the obvious second stop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/plugin marketplace add anthropics/claude-plugins-community
/plugin &lt;span class="nb"&gt;install &lt;/span&gt;some-plugin@claude-community
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;/plugin marketplace add&lt;/code&gt; accepts a GitHub &lt;code&gt;owner/repo&lt;/code&gt; shorthand, a full git URL (include the &lt;code&gt;https://&lt;/code&gt; and the &lt;code&gt;.git&lt;/code&gt;), a local directory, or a direct URL to a hosted &lt;code&gt;marketplace.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Installing prompts you for a &lt;strong&gt;scope&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;user&lt;/strong&gt; — you, across all projects (the default)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;project&lt;/strong&gt; — written to &lt;code&gt;.claude/settings.json&lt;/code&gt;, so everyone who clones the repo gets it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;local&lt;/strong&gt; — this repo only, gitignored&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then activate without restarting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/reload-plugins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the full loop. The plugin's skills now show up under their namespace — install &lt;code&gt;commit-commands&lt;/code&gt; from Anthropic's demo marketplace and you get &lt;code&gt;/commit-commands:commit&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Managing what you've installed
&lt;/h2&gt;

&lt;p&gt;The day-to-day commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/plugin list                                &lt;span class="c"&gt;# what's installed, grouped by scope&lt;/span&gt;
/plugin disable plugin-name@marketplace-name  &lt;span class="c"&gt;# turn off without uninstalling&lt;/span&gt;
/plugin &lt;span class="nb"&gt;enable &lt;/span&gt;plugin-name@marketplace-name
/plugin uninstall plugin-name@marketplace-name
/plugin update plugin-name@marketplace-name   &lt;span class="c"&gt;# pull a plugin update&lt;/span&gt;
/plugin marketplace update marketplace-name   &lt;span class="c"&gt;# refresh a catalog&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything also exists as a shell command (&lt;code&gt;claude plugin install formatter@my-marketplace --scope project&lt;/code&gt;) for scripts and CI. Two things worth knowing before you accumulate a pile: removing a marketplace uninstalls every plugin you got from it, and every enabled plugin adds tokens to &lt;em&gt;every&lt;/em&gt; session — &lt;code&gt;claude plugin details &amp;lt;name&amp;gt;&lt;/code&gt; shows the projected cost, split into always-on and on-invoke. Audit occasionally; the Installed tab literally flags plugins you haven't touched in weeks.&lt;/p&gt;

&lt;h2&gt;
  
  
  When a plugin beats hand-wiring each piece
&lt;/h2&gt;

&lt;p&gt;Honest answer: not always. The decision is about distribution, not capability — a plugin can't do anything the standalone pieces can't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hand-wire when&lt;/strong&gt; it's one project, it's just you, and you're still iterating. Files in &lt;code&gt;.claude/&lt;/code&gt; are faster to edit, need no manifest, and keep short names. Every plugin in my own setup started life as a loose skill or hook I was still fiddling with.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Package a plugin when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Someone else needs your setup.&lt;/strong&gt; The alternative is a README that says "create these four files, paste this JSON, run these three commands." A plugin turns that into one install — and the MCP servers, hooks, and agents arrive pre-wired to each other.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You need it in more than one repo.&lt;/strong&gt; User-scope install once beats copying &lt;code&gt;.claude/&lt;/code&gt; folders around and watching them drift.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You want versioned updates.&lt;/strong&gt; Bump the &lt;code&gt;version&lt;/code&gt; field, users get the update; your copied-folder users get nothing, forever.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The pieces only make sense together.&lt;/strong&gt; A deploy skill that calls a deploy MCP server guarded by a deploy hook is one product, not three configs. Shipping them separately invites the broken half-install.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tell is the second consumer. The moment a setup has one — a teammate, your own second machine, a future you — packaging pays for itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build your own: the anatomy
&lt;/h2&gt;

&lt;p&gt;A minimal plugin is two files. The manifest lives at &lt;code&gt;.claude-plugin/plugin.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-first-plugin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A greeting plugin to learn the basics"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;name&lt;/code&gt; is the only required field — it becomes the namespace prefix. &lt;code&gt;version&lt;/code&gt; is optional but load-bearing: set it and users only get updates when you bump it; omit it and the git commit SHA is the version, so every push ships. Set it for stable releases, omit it while iterating.&lt;/p&gt;

&lt;p&gt;Components sit at the plugin &lt;strong&gt;root&lt;/strong&gt;, not inside &lt;code&gt;.claude-plugin/&lt;/code&gt; — the number-one structural mistake, per Anthropic's own docs. Only &lt;code&gt;plugin.json&lt;/code&gt; goes in there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-plugin/
├── .claude-plugin/
│   └── plugin.json       # only the manifest lives here
├── skills/
│   └── hello/
│       └── SKILL.md      # becomes /my-plugin:hello
├── commands/             # flat .md files, same format as custom slash commands
├── agents/               # subagent definitions
├── hooks/
│   └── hooks.json        # same schema as hooks in settings.json
└── .mcp.json             # bundled MCP servers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;skills/&lt;/code&gt; is the recommended layout for new plugins (each skill a folder with a &lt;code&gt;SKILL.md&lt;/code&gt;); &lt;code&gt;commands/&lt;/code&gt; holds flat Markdown files in the older style. If you already have working pieces in a project's &lt;code&gt;.claude/&lt;/code&gt; directory, migration is mostly &lt;code&gt;cp -r&lt;/code&gt; — copy &lt;code&gt;commands/&lt;/code&gt;, &lt;code&gt;agents/&lt;/code&gt;, &lt;code&gt;skills/&lt;/code&gt; across, and move your &lt;code&gt;hooks&lt;/code&gt; object out of &lt;code&gt;settings.json&lt;/code&gt; into &lt;code&gt;hooks/hooks.json&lt;/code&gt;, same shape.&lt;/p&gt;

&lt;p&gt;One rule saves you a debugging afternoon: &lt;strong&gt;use &lt;code&gt;${CLAUDE_PLUGIN_ROOT}&lt;/code&gt; for every internal path&lt;/strong&gt; in hook commands and MCP configs. Installed plugins are copied into a cache at &lt;code&gt;~/.claude/plugins/cache&lt;/code&gt;, not run from where the user cloned them — so relative paths that reach outside the plugin directory (&lt;code&gt;../shared-utils&lt;/code&gt;) simply don't exist after install. The variable always resolves to wherever the plugin actually landed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test locally, then validate
&lt;/h2&gt;

&lt;p&gt;Point Claude Code at the directory — no marketplace, no install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude &lt;span class="nt"&gt;--plugin-dir&lt;/span&gt; ./my-plugin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Invoke your skill (&lt;code&gt;/my-plugin:hello&lt;/code&gt;), check &lt;code&gt;/agents&lt;/code&gt; for your agents, trigger your hooks. As you edit, &lt;code&gt;/reload-plugins&lt;/code&gt; picks up changes mid-session. Before shipping, lint the whole structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude plugin validate ./my-plugin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It checks &lt;code&gt;plugin.json&lt;/code&gt;, skill and agent frontmatter, and &lt;code&gt;hooks/hooks.json&lt;/code&gt; for schema errors — the same check Anthropic's review pipeline runs on community submissions. There's also &lt;code&gt;claude plugin init my-tool&lt;/code&gt;, which scaffolds a manifest and starter skill under &lt;code&gt;~/.claude/skills/&lt;/code&gt; that loads automatically next session — the fastest path from nothing to a working plugin skeleton.&lt;/p&gt;

&lt;h2&gt;
  
  
  Distribute it: a marketplace is one JSON file
&lt;/h2&gt;

&lt;p&gt;To share, you publish a catalog. A marketplace is a repo with a &lt;code&gt;.claude-plugin/marketplace.json&lt;/code&gt; listing your plugins:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-plugins"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Your Name"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plugins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"quality-review-plugin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./plugins/quality-review-plugin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Adds a quality-review skill for quick code reviews"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;source&lt;/code&gt; can be a relative path inside the same repo (the simple case: one repo, &lt;code&gt;plugins/&lt;/code&gt; folder, catalog at the root) or an object pointing at another GitHub repo, so one catalog can index plugins living anywhere. Test the whole flow locally before pushing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/plugin marketplace add ./my-marketplace
/plugin &lt;span class="nb"&gt;install &lt;/span&gt;quality-review-plugin@my-plugins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then push to GitHub and your users run &lt;code&gt;/plugin marketplace add your-name/your-repo&lt;/code&gt;. For a team, go one step further: add the marketplace to the project's &lt;code&gt;.claude/settings.json&lt;/code&gt; under &lt;code&gt;extraKnownMarketplaces&lt;/code&gt;, and Claude Code prompts every collaborator who trusts the repo to install the team plugins. That plus a committed &lt;a href="https://dev.to/guides/how-to-write-a-claude-md-file/"&gt;CLAUDE.md file&lt;/a&gt; is the whole "onboard a new dev's AI tooling" problem, solved in two files.&lt;/p&gt;

&lt;h2&gt;
  
  
  The security paragraph you shouldn't skip
&lt;/h2&gt;

&lt;p&gt;A plugin is code execution with your user privileges — hooks run shell commands, MCP servers are processes, and installing from a marketplace means trusting whoever controls that repo, including their future pushes. Anthropic verifies none of it for third-party sources. The same rules as any dependency: read the component inventory before installing, prefer pinned catalogs like the community marketplace, and be pickier about marketplaces than about plugins — the catalog decides what an update contains.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this fits
&lt;/h2&gt;

&lt;p&gt;Plugins are the distribution layer for everything else in this cluster: the &lt;a href="https://dev.to/guides/how-to-create-a-custom-slash-command-in-claude-code/"&gt;slash commands&lt;/a&gt; you templatize, the &lt;a href="https://dev.to/guides/how-to-use-claude-code-hooks/"&gt;hooks&lt;/a&gt; that enforce your rules, the &lt;a href="https://dev.to/guides/how-to-add-an-mcp-server-to-claude-code/"&gt;MCP servers&lt;/a&gt; that feed Claude real data, the &lt;a href="https://dev.to/guides/how-to-use-subagents-in-claude-code/"&gt;subagents&lt;/a&gt; that parallelize the work. Once your setup is a plugin, it follows you to every project — which means the economics of running it everywhere start to matter. I keep the heavy drafting lanes on the &lt;a href="https://z.ai/subscribe?ic=BWTG6TRYYQ" rel="noopener noreferrer"&gt;z.ai GLM Coding Plan&lt;/a&gt; — that's a referral link, it helps fund our compute, and the plan costs the same with or without it; setup walkthrough in &lt;a href="https://dev.to/guides/how-to-set-up-claude-code-with-glm-api/"&gt;how to set up Claude Code with the GLM API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And the honest limit of packaging: a plugin makes instructions &lt;em&gt;installable&lt;/em&gt;, not &lt;em&gt;good&lt;/em&gt;. A bad prompt shipped to five repos is a bad prompt five times. The skill and agent bodies inside your plugin are system prompts, and writing those tight is its own craft — &lt;a href="https://promptbase.com/skill/metaprompt-system-architect?via=drbasilicious" rel="noopener noreferrer"&gt;Meta-Prompt + System Prompt Architect&lt;/a&gt; ($8.99, one-time) is the skill I use to turn rough intent into the kind of precise, reusable, failure-aware instructions that are actually worth namespacing and shipping. Package the wiring with a plugin; make what's inside worth installing.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Broke to Built is one broke human + AI agents building real software with no budget, writing down every step. This site's tools run on free GLM — &lt;a href="https://z.ai/subscribe?ic=BWTG6TRYYQ" rel="noopener noreferrer"&gt;z.ai's Coding Plan&lt;/a&gt; is the referral that funds our compute (disclosed affiliate).&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Use Claude Code in VS Code</title>
      <dc:creator>Thryx</dc:creator>
      <pubDate>Mon, 13 Jul 2026 19:00:55 +0000</pubDate>
      <link>https://dev.to/thryx/how-to-use-claude-code-in-vs-code-50oi</link>
      <guid>https://dev.to/thryx/how-to-use-claude-code-in-vs-code-50oi</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is a cross-post — the original (and any updates) live at &lt;a href="https://broke2builtai.com/guides/how-to-use-claude-code-in-vs-code/" rel="noopener noreferrer"&gt;broke2builtai.com&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Most people's first Claude Code session is a terminal squinting contest: a multi-file diff scrolls past as text, you approve it half-read, and then you alt-tab into your editor to find out what actually changed. VS Code integration fixes exactly that. Here's how to wire it up, what you actually get, and when the plain terminal is still the right call.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mental model first: it's the same agent
&lt;/h2&gt;

&lt;p&gt;Get this straight before touching setup, because it saves you a bunch of confusion: Claude Code in VS Code is &lt;em&gt;not&lt;/em&gt; a different product. The extension is a window into the same agent you run in a terminal. Your &lt;a href="https://dev.to/guides/how-to-write-a-claude-md-file/"&gt;CLAUDE.md&lt;/a&gt; loads exactly the same. Your hooks fire. Your MCP servers connect. Your skills and slash commands all work. Nothing you've configured gets redone or duplicated — the IDE just gives that same agent better ways to show you things and better context about what you're looking at.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite: a working CLI
&lt;/h2&gt;

&lt;p&gt;You need the Claude Code CLI installed and authenticated before any of this matters. If you haven't done that yet — or you have, and the token meter is scaring you — the budget path is running it against the GLM models: full walkthrough in &lt;a href="https://dev.to/guides/how-to-set-up-claude-code-with-glm-api/"&gt;how to set up Claude Code with the GLM API&lt;/a&gt;. The plan I use for that is the z.ai GLM Coding Plan — disclosure up front: &lt;a href="https://z.ai/subscribe?ic=BWTG6TRYYQ" rel="noopener noreferrer"&gt;https://z.ai/subscribe?ic=BWTG6TRYYQ&lt;/a&gt; is a referral link, it helps fund our compute, and it's the same plan you'd get without it.&lt;/p&gt;

&lt;p&gt;Once &lt;code&gt;claude&lt;/code&gt; runs in any terminal, you're ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup: run claude in the integrated terminal
&lt;/h2&gt;

&lt;p&gt;Here's the whole install process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open your project in VS Code.&lt;/li&gt;
&lt;li&gt;Open the integrated terminal.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;claude&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. Claude Code auto-detects that it's running inside VS Code, and the official extension typically auto-installs on its own the first time you do this. No marketplace hunting, no config file. (The extension does live on the VS Code marketplace if you'd rather install it directly — same result.)&lt;/p&gt;

&lt;p&gt;The one detail that matters: the auto-detect and auto-install happen in the &lt;em&gt;integrated&lt;/em&gt; terminal. If your session didn't connect on its own, /ide (next section) is the fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  If it didn't connect: /ide
&lt;/h2&gt;

&lt;p&gt;Sometimes a terminal-launched session doesn't hook into the IDE automatically. There's a slash command for exactly that. Inside your Claude Code session, run:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;That connects the running session to VS Code. It's the first thing to try any time the integration features listed below aren't showing up.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you actually get
&lt;/h2&gt;

&lt;p&gt;Four concrete upgrades over a plain terminal, roughly in order of how much they'll change your day:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Native diff review.&lt;/strong&gt; When Claude proposes changes, they open in VS Code's diff viewer instead of rendering as terminal text. This is the headline feature. A three-file refactor as side-by-side diffs you can scan properly is a different experience from the same refactor as a wall of &lt;code&gt;+&lt;/code&gt;/&lt;code&gt;-&lt;/code&gt; lines — you catch the wrong-but-plausible edit &lt;em&gt;before&lt;/em&gt; accepting it, not after.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your selection is context.&lt;/strong&gt; Whatever you've selected, and whichever file is active, gets shared with Claude automatically. Highlight a gnarly function and ask "why does this leak?" — no pasting, no describing where the code lives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shared diagnostics.&lt;/strong&gt; The lint and type errors VS Code already knows about are shared with Claude. So "fix the type errors in this file" works off the same red squiggles you're staring at, instead of Claude re-deriving the problems from scratch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A quick-launch shortcut.&lt;/strong&gt; &lt;code&gt;Ctrl+Esc&lt;/code&gt; on Windows/Linux, &lt;code&gt;Cmd+Esc&lt;/code&gt; on Mac — opens Claude Code focused on your current file. It turns "I'll ask Claude about this" from a context switch into a keystroke.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feeding it context
&lt;/h2&gt;

&lt;p&gt;Two habits worth building once you're in the editor. You can &lt;code&gt;@&lt;/code&gt;-mention files in your prompt to pull them in as context references, and you can drag files straight into the prompt for the same effect. Between those, the auto-shared selection, and the shared diagnostics, most of the "let me explain where everything is" preamble from terminal-only sessions just disappears.&lt;/p&gt;

&lt;p&gt;This is also where your standing setup compounds. The IDE hands Claude &lt;em&gt;situational&lt;/em&gt; context — what you're looking at right now. Your &lt;a href="https://dev.to/guides/how-to-write-a-claude-md-file/"&gt;CLAUDE.md&lt;/a&gt; hands it &lt;em&gt;standing&lt;/em&gt; context — the commands, conventions, and do-NOTs that apply every session. And anything you've wired via &lt;a href="https://dev.to/guides/how-to-add-an-mcp-server-to-claude-code/"&gt;MCP servers&lt;/a&gt; is available here too, because — same agent. The three layers stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest trade-off: when plain terminal wins
&lt;/h2&gt;

&lt;p&gt;The extension is not a mandatory upgrade, and some good workflows skip it deliberately. If you live in tmux, you already have your own pane and session management and the IDE window is just in the way. If you're working over SSH on a remote box, the plain CLI is the natural fit. Plenty of people run Claude Code as a pure terminal tool forever and lose nothing that matters to them.&lt;/p&gt;

&lt;p&gt;Where the extension earns its keep is visual review: the moment Claude starts proposing multi-file changes you actually want to &lt;em&gt;read&lt;/em&gt; before accepting, the native diff viewer stops being a nicety and starts being the reason you catch mistakes. If your sessions are mostly one-file edits and quick questions, the terminal alone is fine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cursor and Windsurf
&lt;/h2&gt;

&lt;p&gt;Both are VS Code forks, and the same extension mechanism works in them — run the CLI in the integrated terminal, connect the same way. If your editor of choice is one of those, everything above carries over.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this fits
&lt;/h2&gt;

&lt;p&gt;Editor integration is the visibility layer. The other half of getting real work out of the agent in your editor is what you feed it — and that's economics plus instructions.&lt;/p&gt;

&lt;p&gt;Economics: IDE workflows make it &lt;em&gt;easy&lt;/em&gt; to hand Claude more context and bigger tasks, which burns more tokens. I keep the meter sane by running against the GLM Coding Plan — again, &lt;a href="https://z.ai/subscribe?ic=BWTG6TRYYQ" rel="noopener noreferrer"&gt;https://z.ai/subscribe?ic=BWTG6TRYYQ&lt;/a&gt; is our disclosed referral link, and the setup is in &lt;a href="https://dev.to/guides/how-to-set-up-claude-code-with-glm-api/"&gt;the GLM API guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Instructions: a better window into the agent doesn't fix vague prompts. For the repeated stuff, can your workflows into a &lt;a href="https://dev.to/guides/how-to-create-a-custom-slash-command-in-claude-code/"&gt;custom slash command&lt;/a&gt; so one keystroke plus one command runs the whole routine. And for writing instructions that actually steer — reusable, high-signal, testable — &lt;a href="https://payhip.com/b/POjTR" rel="noopener noreferrer"&gt;Meta-Prompt Architect&lt;/a&gt; is the pack I use so every token, cheap or not, does real work.&lt;/p&gt;

&lt;p&gt;Wire it up, hit &lt;code&gt;Ctrl+Esc&lt;/code&gt;, and stop approving diffs you haven't read.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Broke to Built is one broke human + AI agents building real software with no budget, writing down every step. This site's tools run on free GLM — &lt;a href="https://z.ai/subscribe?ic=BWTG6TRYYQ" rel="noopener noreferrer"&gt;z.ai's Coding Plan&lt;/a&gt; is the referral that funds our compute (disclosed affiliate).&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Use Claude Code Hooks (Turn Rules Into Guarantees)</title>
      <dc:creator>Thryx</dc:creator>
      <pubDate>Sun, 12 Jul 2026 19:00:55 +0000</pubDate>
      <link>https://dev.to/thryx/how-to-use-claude-code-hooks-turn-rules-into-guarantees-57oe</link>
      <guid>https://dev.to/thryx/how-to-use-claude-code-hooks-turn-rules-into-guarantees-57oe</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is a cross-post — the original (and any updates) live at &lt;a href="https://broke2builtai.com/guides/how-to-use-claude-code-hooks/" rel="noopener noreferrer"&gt;broke2builtai.com&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You put "always run prettier after editing" in your CLAUDE.md. Claude does it... most of the time. Then one long session it edits nine files, formats six, and you find the mess in the diff. That gap — between a rule the model &lt;em&gt;usually&lt;/em&gt; follows and a rule that &lt;em&gt;always&lt;/em&gt; runs — is exactly what hooks close.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Claude Code hooks actually are
&lt;/h2&gt;

&lt;p&gt;Hooks are shell commands you define that Claude Code runs automatically at lifecycle events — before a tool call, after one succeeds, when you submit a prompt, when a session starts, when Claude finishes responding.&lt;/p&gt;

&lt;p&gt;The key word is &lt;em&gt;deterministic&lt;/em&gt;. Instructions in a &lt;a href="https://dev.to/guides/how-to-write-a-claude-md-file/"&gt;CLAUDE.md file&lt;/a&gt; are suggestions the model reads and usually honors — but it can overlook one mid-task. A hook isn't read by the model at all. The harness executes it, every time the event fires, no judgment involved. Rules become guarantees.&lt;/p&gt;

&lt;p&gt;That's the whole mental model: CLAUDE.md for judgment calls, hooks for laws.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where hooks live
&lt;/h2&gt;

&lt;p&gt;Hook config goes in your settings JSON, and there are three layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;~/.claude/settings.json&lt;/code&gt;&lt;/strong&gt; — user-level, follows you across every project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;.claude/settings.json&lt;/code&gt;&lt;/strong&gt; — project-level, committed to the repo so your whole team gets the same guardrails.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;.claude/settings.local.json&lt;/code&gt;&lt;/strong&gt; — project-level but personal; gitignored.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't want to hand-edit JSON? Run &lt;code&gt;/hooks&lt;/code&gt; inside a Claude Code session and it walks you through setting them up interactively. I'd still learn the raw shape, though, because that's what you'll be debugging later.&lt;/p&gt;

&lt;h2&gt;
  
  
  The config shape
&lt;/h2&gt;

&lt;p&gt;Here's a working starting template — a hook that auto-formats any file Claude edits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"PostToolUse"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"matcher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Edit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx prettier --write &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;$(jq -r '.tool_input.file_path')&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three parts to understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The event&lt;/strong&gt; (&lt;code&gt;PostToolUse&lt;/code&gt;) — when this fires. The main ones: &lt;code&gt;PreToolUse&lt;/code&gt; (before a tool call — this one can block it), &lt;code&gt;PostToolUse&lt;/code&gt; (after a tool call succeeds), &lt;code&gt;UserPromptSubmit&lt;/code&gt; (when you submit a prompt), &lt;code&gt;SessionStart&lt;/code&gt;, &lt;code&gt;Stop&lt;/code&gt; (when Claude finishes responding), &lt;code&gt;Notification&lt;/code&gt;, &lt;code&gt;PreCompact&lt;/code&gt;, and &lt;code&gt;SubagentStop&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The matcher&lt;/strong&gt; (&lt;code&gt;"Edit"&lt;/code&gt;) — which tool triggers it, for the tool events. Tool names like &lt;code&gt;Edit&lt;/code&gt; or &lt;code&gt;Bash&lt;/code&gt;, patterns like &lt;code&gt;"Edit|Write"&lt;/code&gt; to catch both, or an empty matcher to fire on every tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The hooks list&lt;/strong&gt; — &lt;code&gt;{ "type": "command", "command": "..." }&lt;/code&gt; entries, the actual shell commands to run.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How a hook sees what's happening
&lt;/h2&gt;

&lt;p&gt;Every hook receives the event's data as JSON on stdin. For tool events that includes the tool name and its input — the file path being edited, the bash command about to run. &lt;code&gt;jq&lt;/code&gt; is the standard way to pull fields out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.tool_input.file_path'&lt;/span&gt;   &lt;span class="c"&gt;# the file an Edit is touching&lt;/span&gt;
jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.tool_input.command'&lt;/span&gt;     &lt;span class="c"&gt;# the command a Bash call is running&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's what the template above is doing — reading the edited file's path off stdin and handing it to prettier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exit codes: the control channel
&lt;/h2&gt;

&lt;p&gt;Your hook talks back to Claude Code through its exit code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exit 0&lt;/strong&gt; — continue normally. For &lt;code&gt;UserPromptSubmit&lt;/code&gt; and &lt;code&gt;SessionStart&lt;/code&gt; hooks, whatever the hook prints to stdout gets added into Claude's context — which means a hook can &lt;em&gt;inject&lt;/em&gt; information at the top of a session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exit 2&lt;/strong&gt; — &lt;strong&gt;block the action.&lt;/strong&gt; The tool call doesn't happen, and whatever you printed to stderr is fed back to Claude so it knows why and can adjust course instead of retrying blindly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Exit 2 is the power move. It's the difference between "please don't touch that folder" and a bouncer at the door.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four recipes worth stealing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Auto-format after every edit.&lt;/strong&gt; The template above. Swap &lt;code&gt;prettier&lt;/code&gt; for &lt;code&gt;black&lt;/code&gt;, &lt;code&gt;gofmt&lt;/code&gt;, whatever your stack formats with. You'll never review an unformatted diff again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Block edits to protected paths.&lt;/strong&gt; A &lt;code&gt;PreToolUse&lt;/code&gt; hook with matcher &lt;code&gt;"Edit|Write"&lt;/code&gt; that reads the file path from stdin and exits 2 if it matches something sacred:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.tool_input.file_path'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-qE&lt;/span&gt; &lt;span class="s1"&gt;'\.env|migrations/'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Blocked: &lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="s2"&gt; is protected. Edit the source template instead."&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
  &lt;span class="nb"&gt;exit &lt;/span&gt;2
&lt;span class="k"&gt;fi
&lt;/span&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save that as a script, point the hook's &lt;code&gt;command&lt;/code&gt; at it. The stderr message matters — Claude reads it and reroutes instead of slamming into the wall repeatedly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Audit-log every Bash command.&lt;/strong&gt; A hook matching &lt;code&gt;Bash&lt;/code&gt; that appends &lt;code&gt;jq -r '.tool_input.command'&lt;/code&gt; to a log file. When you're running Claude with broad permissions, that trail is how you sleep at night.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Desktop notification when Claude needs you.&lt;/strong&gt; A &lt;code&gt;Notification&lt;/code&gt; event hook that fires your OS's notifier. You stop babysitting the terminal and go do something else until it pings you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two warnings before you go hook-happy
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Hooks run with your user's full permissions.&lt;/strong&gt; The harness executes your command as you — a buggy hook can do real damage, same as any shell script with your keys. Keep commands simple, and test every hook standalone in a terminal before wiring it into settings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hooks add latency on every matching event.&lt;/strong&gt; An empty matcher on &lt;code&gt;PreToolUse&lt;/code&gt; means your script runs before &lt;em&gt;every single tool call&lt;/em&gt;. Keep hooks fast and scoped to the tools they actually care about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters more on cheap models
&lt;/h2&gt;

&lt;p&gt;Here's the un-obvious payoff. Deterministic enforcement matters &lt;em&gt;most&lt;/em&gt; when the model is weakest. I run a lot of sessions against GLM models to keep costs near zero — setup is in &lt;a href="https://dev.to/guides/how-to-set-up-claude-code-with-glm-api/"&gt;how to set up Claude Code with the GLM API&lt;/a&gt; — and a lighter model drifts from soft instructions more than a frontier one does. Hooks don't care. The formatter runs, the protected path stays blocked, the audit log fills up, regardless of what the model remembered. The plan I use for that is the z.ai GLM Coding Plan — full disclosure, &lt;a href="https://z.ai/subscribe?ic=BWTG6TRYYQ" rel="noopener noreferrer"&gt;https://z.ai/subscribe?ic=BWTG6TRYYQ&lt;/a&gt; is a referral link that helps fund our compute; same plan either way, just through our link.&lt;/p&gt;

&lt;p&gt;Hooks plus a cheap backend is the combo: the guardrails are free and mechanical, so the tokens only pay for actual thinking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this fits
&lt;/h2&gt;

&lt;p&gt;Hooks are the enforcement layer of a Claude Code setup, and they slot alongside the other layers. Your &lt;a href="https://dev.to/guides/how-to-write-a-claude-md-file/"&gt;CLAUDE.md&lt;/a&gt; holds the judgment-call rules and project facts; &lt;a href="https://dev.to/guides/how-to-create-a-custom-slash-command-in-claude-code/"&gt;custom slash commands&lt;/a&gt; turn your repeated workflows into one-word triggers; hooks make the non-negotiables actually non-negotiable. Wire the three together and the tool stops needing supervision.&lt;/p&gt;

&lt;p&gt;The remaining variable is instruction quality — hooks enforce the hard rules, but everything else still rides on how well you prompt. &lt;a href="https://payhip.com/b/POjTR" rel="noopener noreferrer"&gt;Meta-Prompt Architect&lt;/a&gt; is the pack I use to turn rough intent into reusable, high-signal instructions, so the tokens I'm paying for (referral-funded or not) do real work instead of thrashing.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Broke to Built is one broke human + AI agents building real software with no budget, writing down every step. This site's tools run on free GLM — &lt;a href="https://z.ai/subscribe?ic=BWTG6TRYYQ" rel="noopener noreferrer"&gt;z.ai's Coding Plan&lt;/a&gt; is the referral that funds our compute (disclosed affiliate).&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Schedule Claude Code to Run Daily in the Cloud (Routines)</title>
      <dc:creator>Thryx</dc:creator>
      <pubDate>Sat, 11 Jul 2026 19:00:46 +0000</pubDate>
      <link>https://dev.to/thryx/how-to-schedule-claude-code-to-run-daily-in-the-cloud-routines-1cgg</link>
      <guid>https://dev.to/thryx/how-to-schedule-claude-code-to-run-daily-in-the-cloud-routines-1cgg</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is a cross-post — the original (and any updates) live at &lt;a href="https://broke2builtai.com/guides/how-to-schedule-claude-code-to-run-daily-in-the-cloud/" rel="noopener noreferrer"&gt;broke2builtai.com&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Everything I run, I eventually want to run &lt;em&gt;without me&lt;/em&gt;. A daily content job, a nightly dependency check, a weekly report — the moment a task is worth doing on a schedule, the machine executing it shouldn't be a Windows tower that somebody has to leave on. Claude Code's answer is &lt;strong&gt;routines&lt;/strong&gt;: scheduled cloud agents that fire on a cron, do real work in an isolated cloud session, and leave before you wake up. I set my first ones up today; here's the honest walkthrough.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a routine actually is
&lt;/h2&gt;

&lt;p&gt;A routine is a stored job: a prompt, a GitHub repo, a model, and a schedule. When the cron fires, Anthropic's cloud spins up a fresh sandboxed session — its own clone of your repo, its own tools (shell, file read/write, search), optionally your claude.ai MCP connectors — and hands your prompt to the agent as if you'd typed it. The agent works until the job is done, and the whole session is saved so you can read exactly what it did at &lt;a href="https://claude.ai/code/routines" rel="noopener noreferrer"&gt;claude.ai/code/routines&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Two properties define the shape of everything you build with them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Isolation.&lt;/strong&gt; The session starts with &lt;em&gt;zero context&lt;/em&gt;. It hasn't read your chat history, doesn't know your conventions, and can't see your machine. The prompt has to carry everything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A repo is the world.&lt;/strong&gt; The git checkout is the filesystem the agent lives in — and also its best output channel, because the agent can commit and push. A routine that writes its results into the repo builds a ledger; the next run reads it and continues.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating one with /schedule
&lt;/h2&gt;

&lt;p&gt;Inside Claude Code, type &lt;code&gt;/schedule&lt;/code&gt; and describe the job in plain language. It will walk you through the pieces:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The task.&lt;/strong&gt; What the agent should do each run, and what "done" looks like.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The repo.&lt;/strong&gt; Which GitHub repository gets cloned into the session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The schedule.&lt;/strong&gt; A 5-field cron expression, &lt;strong&gt;always in UTC&lt;/strong&gt;, minimum interval one hour. Say a local time and it converts — but double-check the conversion; a "9am daily" job that quietly runs at 9am UTC is a classic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The model.&lt;/strong&gt; Defaults to Sonnet, which is right for most scheduled work — save the heavier models for jobs where judgment is the product.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For a one-shot instead of a recurring job ("run this once tomorrow at 6am"), the same flow takes a single future timestamp; the routine fires once and disables itself. That one-shot mode is quietly the best feasibility tool in the product — before committing to a daily job, I fire a single probe run whose only task is &lt;em&gt;"try the pipeline and report what breaks."&lt;/em&gt; Today's probe told me in one run whether a cloud sandbox could render video with native canvas and ffmpeg. Twenty minutes of cloud time answered what could have been a day of guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The prompt is a system prompt — write it like one
&lt;/h2&gt;

&lt;p&gt;Because the session starts cold, routine prompts are a different genre from chat messages. Mine follow a fixed skeleton:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identity and mission&lt;/strong&gt; — one paragraph, including what the deliverable is.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Numbered steps&lt;/strong&gt; — where things live in the repo, which scripts to run, in what order.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failure policy&lt;/strong&gt; — diagnose briefly, try one workaround, then record the blocker instead of thrashing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The deliverable's exact shape&lt;/strong&gt; — if I want JSON, I show the JSON.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the same discipline as writing a &lt;a href="https://dev.to/guides/how-to-write-a-claude-md-file/"&gt;CLAUDE.md file&lt;/a&gt; or a &lt;a href="https://dev.to/guides/how-to-use-subagents-in-claude-code/"&gt;custom subagent&lt;/a&gt;: instruction quality is the product. An unattended agent amplifies whatever you wrote — precision compounds, vagueness compounds faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  The secrets problem (and the pattern that solves it)
&lt;/h2&gt;

&lt;p&gt;Here's the constraint that shapes real automations: &lt;strong&gt;the cloud session cannot access your local environment variables or files.&lt;/strong&gt; Whatever credential your job needs — an upload token, an API key — has to reach the routine some other way, and committing it to the repo is not that way. Ever.&lt;/p&gt;

&lt;p&gt;The pattern I use: a &lt;strong&gt;keyed relay&lt;/strong&gt;. The real credential lives server-side as a secret in a tiny hosted service (a Cloudflare Worker's free tier does this for $0), and the service exposes one narrow endpoint gated by a random key. The routine's prompt carries only that key. My video pipeline works exactly like this: the Worker holds the YouTube OAuth token as a Worker secret; the routine renders the video in the sandbox and POSTs the file to the relay; the relay does the upload. If the routine's key ever leaked, the blast radius is "someone could post a video to my channel" — not "someone owns my Google account." Scope the key to the action, keep the credential where nobody's prompt can see it.&lt;/p&gt;

&lt;p&gt;OAuth'd MCP connectors attached to the routine solve the same problem for supported services (mail, drives, and similar) without any hosting at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  What runs well on a schedule
&lt;/h2&gt;

&lt;p&gt;The jobs that have earned a cron in my setup, all on the theme of &lt;a href="https://dev.to/log/"&gt;building while you sleep&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Content generation&lt;/strong&gt; — a nightly drafter that stocks a queue for a human-or-stronger-model gate to review in the morning. Nothing auto-publishes ungated; the routine removes the blank-page step, not the judgment step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feasibility probes&lt;/strong&gt; — one-shot runs that answer "can this environment do X" with facts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repo hygiene&lt;/strong&gt; — dependency bumps, dead-link checks, stale-issue triage, committed as a report or a PR.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ledger updates&lt;/strong&gt; — pull yesterday's numbers from an API, append to a data file, push.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cost note, disclosed as always: routine runs consume your plan's usage like any session, so the economics of &lt;em&gt;daily&lt;/em&gt; automation depend on what your tokens cost. I keep the heavy drafting lanes on the &lt;a href="https://z.ai/subscribe?ic=BWTG6TRYYQ" rel="noopener noreferrer"&gt;z.ai GLM Coding Plan&lt;/a&gt; — that's a referral link, it helps fund our compute, and the plan costs the same with or without it; the setup is in &lt;a href="https://dev.to/guides/how-to-set-up-claude-code-with-glm-api/"&gt;how to set up Claude Code with the GLM API&lt;/a&gt;. Cheap tokens for the bulk lanes, scheduled cloud runs for the judgment lanes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this fits
&lt;/h2&gt;

&lt;p&gt;Routines are the last piece of a stack where each layer removes one manual step. &lt;a href="https://dev.to/guides/how-to-write-a-claude-md-file/"&gt;CLAUDE.md&lt;/a&gt; encodes your standing rules, &lt;a href="https://dev.to/guides/how-to-use-claude-code-hooks/"&gt;hooks&lt;/a&gt; enforce them mechanically, &lt;a href="https://dev.to/guides/how-to-use-subagents-in-claude-code/"&gt;subagents&lt;/a&gt; parallelize the work — and a routine removes the final human act of &lt;em&gt;showing up to start it&lt;/em&gt;. What's left is the part that was always the real job: writing instructions good enough to run unattended. That's the exact muscle &lt;a href="https://payhip.com/b/POjTR" rel="noopener noreferrer"&gt;Meta-Prompt Architect&lt;/a&gt; trains — turning rough intent into the tight, reusable, failure-aware instructions that a 6am cloud session with zero context and nobody watching can actually execute. On the GLM plan (referral above, disclosed) or any backend: the prompt is the program now. Write it like one.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Broke to Built is one broke human + AI agents building real software with no budget, writing down every step. This site's tools run on free GLM — &lt;a href="https://z.ai/subscribe?ic=BWTG6TRYYQ" rel="noopener noreferrer"&gt;z.ai's Coding Plan&lt;/a&gt; is the referral that funds our compute (disclosed affiliate).&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Post to LinkedIn from a Script: the 15-Minute OAuth Walkthrough (2026)</title>
      <dc:creator>Thryx</dc:creator>
      <pubDate>Fri, 10 Jul 2026 19:00:49 +0000</pubDate>
      <link>https://dev.to/thryx/how-to-post-to-linkedin-from-a-script-the-15-minute-oauth-walkthrough-2026-58fp</link>
      <guid>https://dev.to/thryx/how-to-post-to-linkedin-from-a-script-the-15-minute-oauth-walkthrough-2026-58fp</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is a cross-post — the original (and any updates) live at &lt;a href="https://broke2builtai.com/guides/how-to-post-to-linkedin-from-a-script-oauth/" rel="noopener noreferrer"&gt;broke2builtai.com&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every scheduled-posting tool for LinkedIn wants a subscription for what is, underneath, four HTTP requests. I assumed the DIY route was gated behind a partner-program application and weeks of waiting — that's the reputation. Then I actually did it today, and the whole thing — app creation to a verified working token — took about fifteen minutes, because the two products a personal posting script needs are instant self-serve checkboxes. Here's the exact walkthrough, including the one place LinkedIn tried to trip me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create the app (you need a company page)
&lt;/h2&gt;

&lt;p&gt;Go to &lt;a href="https://www.linkedin.com/developers/apps" rel="noopener noreferrer"&gt;linkedin.com/developers/apps&lt;/a&gt; and create an app. The one real prerequisite: LinkedIn requires a &lt;strong&gt;company page&lt;/strong&gt; to verify the app against. If the page is yours, this is a non-event — you approve the verification request as the page admin and it's verified instantly.&lt;/p&gt;

&lt;p&gt;Don't let the company-page requirement confuse you about what you're building: the app is verified against the page, but with the scopes below you'll be posting &lt;strong&gt;as yourself&lt;/strong&gt;, to your own member feed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Request the two instant products
&lt;/h2&gt;

&lt;p&gt;On the app's &lt;strong&gt;Products&lt;/strong&gt; tab, request:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Share on LinkedIn&lt;/strong&gt; — this is what grants the &lt;code&gt;w_member_social&lt;/code&gt; scope, the permission to create posts as a member.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sign In with LinkedIn using OpenID Connect&lt;/strong&gt; — this grants &lt;code&gt;openid profile email&lt;/code&gt;, which you need to fetch your own member id.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both are &lt;strong&gt;instant self-serve grants&lt;/strong&gt;: tick the checkbox, accept the LinkedIn API Terms, done. No review queue, no application essay.&lt;/p&gt;

&lt;p&gt;One boundary I hit while poking around: the &lt;strong&gt;Community Management API&lt;/strong&gt; — the product that lets you post as an organization/page rather than as yourself — &lt;strong&gt;cannot share an app with other products&lt;/strong&gt;. It demands its own dedicated app. So if page-posting is in your future, plan on a second app; don't try to bolt it onto this one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Add a redirect URL (it can literally 404)
&lt;/h2&gt;

&lt;p&gt;On the &lt;strong&gt;Auth&lt;/strong&gt; tab, add an authorized redirect URL. Here's the part that saves you from standing up a server: &lt;strong&gt;any https URL on a domain you control works — even one that returns a 404.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why: LinkedIn's OAuth flow ends by redirecting your browser to that URL with &lt;code&gt;?code=...&lt;/code&gt; appended. For a one-time personal-token setup, you don't need the page to &lt;em&gt;do&lt;/em&gt; anything — you just need to read the &lt;code&gt;code&lt;/code&gt; parameter out of the address bar after the redirect lands. A dead path on a domain you own is a perfectly valid OAuth redirect target for this purpose.&lt;/p&gt;

&lt;p&gt;While you're on the Auth tab, note your &lt;strong&gt;Client ID&lt;/strong&gt; and &lt;strong&gt;Client Secret&lt;/strong&gt; — and keep the secret out of your repo. Same rule as &lt;a href="https://dev.to/guides/how-to-schedule-claude-code-to-run-daily-in-the-cloud/"&gt;giving credentials to a scheduled cloud agent&lt;/a&gt;: secrets live in environment variables or server-side stores, never in git.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: The consent URL
&lt;/h2&gt;

&lt;p&gt;Build this URL (one line) and open it in a browser where you're logged in to LinkedIn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;https://www.linkedin.com/oauth/v2/authorization
  ?response_type=code
  &amp;amp;client_id=YOUR_CLIENT_ID
  &amp;amp;redirect_uri=YOUR_REDIRECT_URL
  &amp;amp;scope=openid%20profile%20email%20w_member_social
  &amp;amp;state=SOME_RANDOM_STRING
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Approve the consent screen, and LinkedIn bounces you to your redirect URL with &lt;code&gt;?code=...&lt;/code&gt; in the query string. Copy that code — it's single-use and short-lived, so move straight to the exchange.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The gotcha that got me:&lt;/strong&gt; LinkedIn may interrupt the consent flow with a &lt;strong&gt;security checkpoint asking you to verify your email&lt;/strong&gt; if the login looks unusual to it. It's not a bug in your setup — complete the verification and the flow resumes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Exchange the code for a token
&lt;/h2&gt;

&lt;p&gt;Form-encoded POST:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://www.linkedin.com/oauth/v2/accessToken &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/x-www-form-urlencoded"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nv"&gt;grant_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;authorization_code &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;THE_CODE_FROM_THE_REDIRECT &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nv"&gt;redirect_uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;YOUR_REDIRECT_URL &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nv"&gt;client_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;YOUR_CLIENT_ID &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nv"&gt;client_secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;YOUR_CLIENT_SECRET
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response gives you &lt;code&gt;access_token&lt;/code&gt;, &lt;code&gt;expires_in: 5184000&lt;/code&gt;, an &lt;code&gt;id_token&lt;/code&gt;, and the granted &lt;code&gt;scope&lt;/code&gt;. That &lt;code&gt;expires_in&lt;/code&gt; is the quiet headline: &lt;strong&gt;5,184,000 seconds is two months.&lt;/strong&gt; For a personal script, that means re-doing this dance six times a year, not building refresh-token plumbing on day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Verify the token and get your member id
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://api.linkedin.com/v2/userinfo &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &amp;lt;your-access-token&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns your name plus a &lt;code&gt;sub&lt;/code&gt; field — your member id. Your author URN for posting is &lt;code&gt;urn:li:person:&amp;lt;sub&amp;gt;&lt;/code&gt;. If this call returns your own name, the OAuth leg is done and verified.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: The post call (per LinkedIn's docs)
&lt;/h2&gt;

&lt;p&gt;Honesty checkpoint: everything above this line I ran today and watched succeed, through the &lt;code&gt;userinfo&lt;/code&gt; verification. The post call itself I'm giving you &lt;strong&gt;as documented by LinkedIn&lt;/strong&gt; — I validated the token and URN, not an actual published post yet.&lt;/p&gt;

&lt;p&gt;Per the docs, posting is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.linkedin.com/rest/posts &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &amp;lt;your-access-token&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Restli-Protocol-Version: 2.0.0"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"LinkedIn-Version: YYYYMM"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "author": "urn:li:person:YOUR_SUB",
    "commentary": "Posted from a script.",
    "visibility": "PUBLIC",
    "distribution": { "feedDistribution": "MAIN_FEED" },
    "lifecycleState": "PUBLISHED"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two headers people miss: &lt;code&gt;X-Restli-Protocol-Version: 2.0.0&lt;/code&gt; is required, and &lt;code&gt;LinkedIn-Version&lt;/code&gt; must be a valid &lt;code&gt;YYYYMM&lt;/code&gt; API version string — check LinkedIn's versioning docs for the current active version and substitute it for the placeholder above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this goes next
&lt;/h2&gt;

&lt;p&gt;A two-month token plus a four-request flow is exactly the shape of thing you hand to an agent. Mine drafts in a cheap lane — I run bulk generation on the &lt;a href="https://z.ai/subscribe?ic=BWTG6TRYYQ" rel="noopener noreferrer"&gt;z.ai GLM Coding Plan&lt;/a&gt; (that's a referral link, it helps fund our compute, and the plan costs the same with or without it; setup in &lt;a href="https://dev.to/guides/how-to-set-up-claude-code-with-glm-api/"&gt;how to set up Claude Code with the GLM API&lt;/a&gt;) — and the posting step is just this walkthrough's step 7 wearing a cron. If you want the whole loop hands-off, the same pattern as &lt;a href="https://dev.to/guides/how-to-schedule-claude-code-to-run-daily-in-the-cloud/"&gt;scheduling Claude Code to run daily in the cloud&lt;/a&gt; applies: keep the LinkedIn token server-side, let the scheduled job call a narrow relay. And if the script needs richer context than "write a post" — your voice, your topics, your rules — that's a job for a proper instruction stack, the kind you build once with something like an &lt;a href="https://dev.to/guides/how-to-add-an-mcp-server-to-claude-code/"&gt;MCP server feeding your agent real data&lt;/a&gt; and a prompt written like it has to survive unattended. &lt;a href="https://payhip.com/b/POjTR" rel="noopener noreferrer"&gt;Meta-Prompt Architect&lt;/a&gt; is my tool for exactly that last part: turning "post good stuff to LinkedIn" into instructions precise enough that the 2-month token is the only thing you ever have to touch.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Broke to Built is one broke human + AI agents building real software with no budget, writing down every step. This site's tools run on free GLM — &lt;a href="https://z.ai/subscribe?ic=BWTG6TRYYQ" rel="noopener noreferrer"&gt;z.ai's Coding Plan&lt;/a&gt; is the referral that funds our compute (disclosed affiliate).&lt;/em&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Create a Skill in Claude Code</title>
      <dc:creator>Thryx</dc:creator>
      <pubDate>Thu, 09 Jul 2026 21:19:15 +0000</pubDate>
      <link>https://dev.to/thryx/how-to-create-a-skill-in-claude-code-pih</link>
      <guid>https://dev.to/thryx/how-to-create-a-skill-in-claude-code-pih</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is a cross-post — the original (and any updates) live at &lt;a href="https://broke2builtai.com/guides/how-to-create-a-skill-in-claude-code/" rel="noopener noreferrer"&gt;broke2builtai.com&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first time I watched Claude Code reach for a skill I hadn't told it to use — read a folder, run the script inside it, and hand back the finished thing — the difference from a slash command finally landed. A slash command waits for you to type it. A skill waits for the &lt;em&gt;situation&lt;/em&gt;. Claude decides. That one shift is the whole feature, and building one takes about five minutes once you know where the file goes.&lt;/p&gt;

&lt;p&gt;Here's the entire thing end to end, including the one gotcha that decides whether your skill ever actually fires.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Skill actually is
&lt;/h2&gt;

&lt;p&gt;A Skill is a folder with a &lt;code&gt;SKILL.md&lt;/code&gt; file inside it. The Markdown holds instructions; the YAML frontmatter at the top holds a &lt;code&gt;name&lt;/code&gt; and a &lt;code&gt;description&lt;/code&gt;. That description is doing the most important job in the whole file: Claude reads it to decide, on its own, whether the current task warrants invoking the skill. Nothing else you write matters if the description doesn't get you picked.&lt;/p&gt;

&lt;p&gt;That's the mental model to hold onto: a &lt;a href="https://dev.to/guides/how-to-create-a-custom-slash-command-in-claude-code/"&gt;custom slash command&lt;/a&gt; is a prompt &lt;em&gt;you&lt;/em&gt; trigger by typing &lt;code&gt;/name&lt;/code&gt;; a skill is a procedure &lt;em&gt;Claude&lt;/em&gt; triggers when the context matches. Same reusable-instructions idea, opposite trigger.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the file goes
&lt;/h2&gt;

&lt;p&gt;Two locations register, exactly like commands and &lt;a href="https://dev.to/guides/how-to-use-subagents-in-claude-code/"&gt;subagents&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Project skill&lt;/strong&gt; — &lt;code&gt;.claude/skills/&amp;lt;skill-name&amp;gt;/SKILL.md&lt;/code&gt; inside the repo. Committed, so your whole team gets it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Personal skill&lt;/strong&gt; — &lt;code&gt;~/.claude/skills/&amp;lt;skill-name&amp;gt;/SKILL.md&lt;/code&gt; in your home directory. Follows you across every project on your machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each skill is its own folder, and the folder name should match the &lt;code&gt;name&lt;/code&gt; in the frontmatter. A loose &lt;code&gt;SKILL.md&lt;/code&gt; sitting somewhere else won't be picked up.&lt;/p&gt;

&lt;h2&gt;
  
  
  The minimum viable skill
&lt;/h2&gt;

&lt;p&gt;Create the folder and the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.claude/skills/pytest-runner/SKILL.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then write the two-part file — frontmatter, then body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pytest-runner&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Run,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;generate,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;or&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;debug&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;pytest&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tests&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;this&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;project.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Use&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;when&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;asks&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;run&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;suite,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;add&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tests&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;function,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;or&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;figure&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;out&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;why&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;failing."&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

When invoked:
&lt;span class="p"&gt;
1.&lt;/span&gt; Run the suite with &lt;span class="sb"&gt;`python -m pytest -q`&lt;/span&gt; and read the output.
&lt;span class="p"&gt;2.&lt;/span&gt; If tests fail, show the failing test names and the assertion, then propose the smallest fix.
&lt;span class="p"&gt;3.&lt;/span&gt; When asked to add tests, match the existing style in &lt;span class="sb"&gt;`tests/`&lt;/span&gt; — same fixtures, same naming.
&lt;span class="p"&gt;4.&lt;/span&gt; Never mark work done until the suite is green; paste the passing summary line.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a working skill. No install step, no registration file — Claude Code discovers it from the folder. Next time you ask something that matches the description, Claude reaches for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one gotcha: the description IS the trigger
&lt;/h2&gt;

&lt;p&gt;If your skill never fires, the description is almost always why. Claude selects a skill by matching the task against the description text, so a vague &lt;code&gt;description: helps with tests&lt;/code&gt; competes badly against everything else in context and usually loses.&lt;/p&gt;

&lt;p&gt;Write the description like a trigger list, not a summary. Name the concrete situations, the verbs, and the file types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Weak:&lt;/strong&gt; &lt;code&gt;description: Testing helper.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strong:&lt;/strong&gt; &lt;code&gt;description: Run, generate, or debug pytest tests. Use when the user asks to run the suite, add tests for a function/module, or diagnose a failing test.&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The body can be as long and detailed as you want — that content only loads once the skill is invoked. The description is the part that's always competing for selection, so that's where the precision has to live. This is the same discipline behind &lt;a href="https://dev.to/guides/how-to-write-a-system-prompt-for-an-ai-agent/"&gt;writing a good system prompt for an agent&lt;/a&gt;: be explicit about &lt;em&gt;when&lt;/em&gt;, not just &lt;em&gt;what&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bundling scripts, references, and templates
&lt;/h2&gt;

&lt;p&gt;The reason a skill beats a slash command for real workflows is that the folder can hold more than instructions. Anything you drop in the skill directory is available to Claude when the skill runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.claude/skills/release-notes/
├── SKILL.md
├── template.md          # the format to fill in
└── changelog-parse.py   # a helper the skill runs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reference them from &lt;code&gt;SKILL.md&lt;/code&gt; by relative path — "fill in &lt;code&gt;template.md&lt;/code&gt;", "run &lt;code&gt;changelog-parse.py&lt;/code&gt; on the git log" — and Claude reads or executes them as part of following the skill. That's how a skill packages an entire procedure (a format + a script + the rules for using them), not just a paragraph of prompt. If the script needs a tool that prompts for permission, the same &lt;a href="https://dev.to/guides/how-to-use-claude-code-hooks/"&gt;permission and hooks rules&lt;/a&gt; apply as anywhere else in Claude Code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skill vs. slash command vs. CLAUDE.md — which to reach for
&lt;/h2&gt;

&lt;p&gt;Three ways to give Claude Code reusable instructions, and they're not interchangeable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CLAUDE.md&lt;/strong&gt; — always-on. Loaded every session. Use it for standing facts about the project (&lt;a href="https://dev.to/guides/how-to-write-a-claude-md-file/"&gt;here's how to write one&lt;/a&gt;). The cost is context: everything in it is paid for on every turn.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slash command&lt;/strong&gt; — you-triggered, on demand. Use it when &lt;em&gt;you&lt;/em&gt; decide the moment (&lt;code&gt;/review&lt;/code&gt;, &lt;code&gt;/deploy&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skill&lt;/strong&gt; — model-triggered, on demand. Use it when you want Claude to notice the situation and reach for the procedure itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The practical rule: standing context goes in CLAUDE.md; a procedure you invoke yourself is a slash command; a procedure Claude should invoke when it sees the trigger is a skill. Getting that split right is what keeps your everyday context lean while still having deep procedures on tap.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest workflow
&lt;/h2&gt;

&lt;p&gt;Build the skill small, then watch whether it fires. Ask something that &lt;em&gt;should&lt;/em&gt; trigger it and see if Claude reaches for it — if it doesn't, tighten the description and try again. That loop takes a couple of minutes and is the only real test that matters, because a skill that never gets invoked is just a Markdown file nobody reads.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This site runs its own automation on Claude Code and free-tier AI. If you're wiring up cheap models to do real work, we run everything on GLM's free tier through the &lt;a href="https://z.ai/subscribe?ic=BWTG6TRYYQ" rel="noopener noreferrer"&gt;z.ai Coding Plan&lt;/a&gt; (referral link — it funds our compute); a tight SKILL.md is exactly the kind of harness that keeps a cheaper model on rails.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Broke to Built is one broke human + AI agents building real software with no budget, writing down every step. This site's tools run on free GLM — &lt;a href="https://z.ai/subscribe?ic=BWTG6TRYYQ" rel="noopener noreferrer"&gt;z.ai's Coding Plan&lt;/a&gt; is the referral that funds our compute (disclosed affiliate).&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
