[{"data":1,"prerenderedAt":3321},["ShallowReactive",2],{"docs:\u002Fextensions":3},{"id":4,"title":5,"accent":6,"body":7,"description":3285,"estReadTime":3286,"extension":3287,"eyebrow":3288,"icon":3289,"intro":3290,"lastUpdated":3290,"meta":3291,"navigation":336,"next":3292,"path":3295,"prev":3296,"review":3290,"seo":3299,"stem":6,"tocItems":3310,"__hash__":3320},"docs\u002Fextensions.md","Extensions","extensions",{"type":8,"value":9,"toc":3268},"minimark",[10,18,21,249,602,984,1805,2038,2449,2809,3111,3264],[11,12,13,14,17],"p",{},"The base Claude Code loop — read, edit, run, respond — is already useful. But every shop that's running Claude at scale has layered ",[15,16,6],"em",{}," on top: little configuration files that give Claude new capabilities, new guardrails, and new collaborators. This chapter walks each of the nine layers, from the simplest (a slash command in a markdown file) to the most elaborate (a multi-agent team with its own AGENTS.md). By the end you should be able to read any Claude Code repo on GitHub and recognize what each file is doing.",[11,19,20],{},"Every section ships with a working example. Copy it, change a name, and commit — that's the whole onboarding.",[22,23,26,34,177,192,197,200,246],"docs-section",{"id":24,"title":25},"decision","Decision Framework",[11,27,28,29,33],{},"There's a tempting anti-pattern early on: \"I'll solve this with a hook!\" for anything that involves Claude doing something wrong. Sometimes a hook is right. Often a ",[30,31,32],"code",{},"CLAUDE.md"," line is right. Sometimes it's a subagent. Before reaching for any layer, ask the question below and match it to the row.",[35,36,37,53],"table",{},[38,39,40],"thead",{},[41,42,43,47,50],"tr",{},[44,45,46],"th",{},"If you want…",[44,48,49],{},"Reach for",[44,51,52],{},"Why",[54,55,56,69,86,99,112,125,138,151,164],"tbody",{},[41,57,58,62,66],{},[59,60,61],"td",{},"Claude to follow a rule every session",[59,63,64],{},[30,65,32],{},[59,67,68],{},"Cheap, always-on, no config",[41,70,71,77,83],{},[59,72,73,74],{},"Expertise Claude loads ",[15,75,76],{},"only when relevant",[59,78,79],{},[80,81,82],"strong",{},"Skill",[59,84,85],{},"Triggered by context, costs nothing otherwise",[41,87,88,91,96],{},[59,89,90],{},"A repeatable prompt you re-type a lot",[59,92,93],{},[80,94,95],{},"Slash command",[59,97,98],{},"One file, one-liner to invoke",[41,100,101,104,109],{},[59,102,103],{},"A deterministic action on every file write",[59,105,106],{},[80,107,108],{},"Hook",[59,110,111],{},"Not Claude's choice — the harness guarantees it",[41,113,114,117,122],{},[59,115,116],{},"A big investigation that would blow context",[59,118,119],{},[80,120,121],{},"Subagent",[59,123,124],{},"Fresh window, returns a summary",[41,126,127,130,135],{},[59,128,129],{},"Multiple specialists collaborating",[59,131,132],{},[80,133,134],{},"Agent Team",[59,136,137],{},"Coordinated, parallel, shared state",[41,139,140,143,148],{},[59,141,142],{},"Claude to read\u002Fwrite an external service",[59,144,145],{},[80,146,147],{},"MCP server",[59,149,150],{},"Structured tools, not scraped terminal output",[41,152,153,156,161],{},[59,154,155],{},"A bundle of the above, distributable",[59,157,158],{},[80,159,160],{},"Plugin",[59,162,163],{},"One install command for your team",[41,165,166,169,174],{},[59,167,168],{},"Real-time language diagnostics",[59,170,171],{},[80,172,173],{},"LSP integration",[59,175,176],{},"Claude sees errors as you edit",[178,179,182],"docs-callout",{"title":180,"variant":181},"The smallest thing that works","tip",[11,183,184,185,187,188,191],{},"When in doubt, pick the row higher in the table. A well-written ",[30,186,32],{}," rule prevents more mistakes than a clever hook. Hooks that duplicate rules already in CLAUDE.md are noise. Save hooks for things Claude can't refuse to do — not things you'd ",[15,189,190],{},"like"," it to do.",[193,194,196],"h3",{"id":195},"mental-model-where-does-each-layer-live","Mental model: where does each layer live?",[11,198,199],{},"Think of Claude Code as a stack, from closest to the model outward:",[201,202,203,210,216,222,228,234,240],"ul",{},[204,205,206,209],"li",{},[80,207,208],{},"Model"," — Opus \u002F Sonnet \u002F Haiku. You don't extend this; you pick it.",[204,211,212,215],{},[80,213,214],{},"System prompt + CLAUDE.md"," — always present. Personality, project rules.",[204,217,218,221],{},[80,219,220],{},"Skills"," — on-demand knowledge, injected when Claude judges them relevant.",[204,223,224,227],{},[80,225,226],{},"Commands"," — user-invoked prompt templates.",[204,229,230,233],{},[80,231,232],{},"Tools"," — Read, Edit, Bash, plus MCP-supplied ones.",[204,235,236,239],{},[80,237,238],{},"Hooks"," — the harness intercepting tool calls.",[204,241,242,245],{},[80,243,244],{},"Subagents \u002F Teams"," — additional Claude instances spawned by the main one.",[11,247,248],{},"Extensions aren't competing with each other — they compose. A mature project uses five or six of them, each doing the job it's best at.",[22,250,252,262,265,282,536,540,550,565,589,593],{"id":251,"title":220},"skills",[11,253,254,255,257,258,261],{},"A ",[80,256,82],{}," is a folder with a ",[30,259,260],{},"SKILL.md"," inside. When Claude's current context matches the skill's description, the harness automatically injects the file's contents — giving Claude just-in-time expertise without paying the token cost when it's not needed. This is the single most underused extension in the whole platform.",[11,263,264],{},"Skills live in three places, scanned in order:",[201,266,267,273,279],{},[204,268,269,272],{},[30,270,271],{},"~\u002F.claude\u002Fskills\u002F"," — your personal skills across every project.",[204,274,275,278],{},[30,276,277],{},".claude\u002Fskills\u002F"," — project skills the whole team gets.",[204,280,281],{},"Bundled with plugins you install — covered later.",[283,284,290],"pre",{"className":285,"code":286,"filename":287,"language":288,"meta":289,"style":289},"language-markdown shiki shiki-themes github-light","---\nname: postgres-migrations\ndescription: Use this skill whenever the user wants to create, modify, roll back, or review a Postgres migration in this project. Triggers include any mention of 'migration', a new file under `db\u002Fmigrations\u002F`, or ALTER\u002FCREATE TABLE changes. Do NOT trigger on unrelated SQL queries inside application code.\n---\n\n# Writing safe Postgres migrations\n\n## House conventions\n\n- Every migration is a pair: `NNN_name.up.sql` and `NNN_name.down.sql`.\n- `NNN` is a zero-padded 4-digit number, one higher than the highest on disk.\n- All DDL is wrapped in `BEGIN; ... COMMIT;` — no exceptions.\n- `CREATE INDEX` must use `CONCURRENTLY` in production, which means it cannot be inside the transaction. Emit a second migration for the index.\n\n## Before you write\n\n1. Run `ls db\u002Fmigrations | tail -n 5` and pick the next number.\n2. Read the most recent 2 migrations for naming style.\n3. Confirm the target table's current shape with `psql -c '\\d tablename'`.\n\n## Rollback rule\n\nEvery `up.sql` must have a reversible `down.sql`. If the change isn't reversible (data loss, irreversible type change), refuse and ask for a plan from the user.\n\n## Example\n\nup: add a nullable column, backfill in a follow-up, then NOT NULL in a third migration.\n",".claude\u002Fskills\u002Fpostgres-migrations\u002FSKILL.md","markdown","",[30,291,292,301,315,326,331,338,345,350,356,361,384,395,409,426,431,437,442,457,466,480,485,491,496,514,519,525,530],{"__ignoreMap":289},[293,294,297],"span",{"class":295,"line":296},"line",1,[293,298,300],{"class":299},"sgsFI","---\n",[293,302,304,308,311],{"class":295,"line":303},2,[293,305,307],{"class":306},"shJU0","name",[293,309,310],{"class":299},": ",[293,312,314],{"class":313},"sYBdl","postgres-migrations\n",[293,316,318,321,323],{"class":295,"line":317},3,[293,319,320],{"class":306},"description",[293,322,310],{"class":299},[293,324,325],{"class":313},"Use this skill whenever the user wants to create, modify, roll back, or review a Postgres migration in this project. Triggers include any mention of 'migration', a new file under `db\u002Fmigrations\u002F`, or ALTER\u002FCREATE TABLE changes. Do NOT trigger on unrelated SQL queries inside application code.\n",[293,327,329],{"class":295,"line":328},4,[293,330,300],{"class":299},[293,332,334],{"class":295,"line":333},5,[293,335,337],{"emptyLinePlaceholder":336},true,"\n",[293,339,341],{"class":295,"line":340},6,[293,342,344],{"class":343},"surfw","# Writing safe Postgres migrations\n",[293,346,348],{"class":295,"line":347},7,[293,349,337],{"emptyLinePlaceholder":336},[293,351,353],{"class":295,"line":352},8,[293,354,355],{"class":343},"## House conventions\n",[293,357,359],{"class":295,"line":358},9,[293,360,337],{"emptyLinePlaceholder":336},[293,362,364,368,371,375,378,381],{"class":295,"line":363},10,[293,365,367],{"class":366},"sqxcx","-",[293,369,370],{"class":299}," Every migration is a pair: ",[293,372,374],{"class":373},"sYu0t","`NNN_name.up.sql`",[293,376,377],{"class":299}," and ",[293,379,380],{"class":373},"`NNN_name.down.sql`",[293,382,383],{"class":299},".\n",[293,385,387,389,392],{"class":295,"line":386},11,[293,388,367],{"class":366},[293,390,391],{"class":373}," `NNN`",[293,393,394],{"class":299}," is a zero-padded 4-digit number, one higher than the highest on disk.\n",[293,396,398,400,403,406],{"class":295,"line":397},12,[293,399,367],{"class":366},[293,401,402],{"class":299}," All DDL is wrapped in ",[293,404,405],{"class":373},"`BEGIN; ... COMMIT;`",[293,407,408],{"class":299}," — no exceptions.\n",[293,410,412,414,417,420,423],{"class":295,"line":411},13,[293,413,367],{"class":366},[293,415,416],{"class":373}," `CREATE INDEX`",[293,418,419],{"class":299}," must use ",[293,421,422],{"class":373},"`CONCURRENTLY`",[293,424,425],{"class":299}," in production, which means it cannot be inside the transaction. Emit a second migration for the index.\n",[293,427,429],{"class":295,"line":428},14,[293,430,337],{"emptyLinePlaceholder":336},[293,432,434],{"class":295,"line":433},15,[293,435,436],{"class":343},"## Before you write\n",[293,438,440],{"class":295,"line":439},16,[293,441,337],{"emptyLinePlaceholder":336},[293,443,445,448,451,454],{"class":295,"line":444},17,[293,446,447],{"class":366},"1.",[293,449,450],{"class":299}," Run ",[293,452,453],{"class":373},"`ls db\u002Fmigrations | tail -n 5`",[293,455,456],{"class":299}," and pick the next number.\n",[293,458,460,463],{"class":295,"line":459},18,[293,461,462],{"class":366},"2.",[293,464,465],{"class":299}," Read the most recent 2 migrations for naming style.\n",[293,467,469,472,475,478],{"class":295,"line":468},19,[293,470,471],{"class":366},"3.",[293,473,474],{"class":299}," Confirm the target table's current shape with ",[293,476,477],{"class":373},"`psql -c '\\d tablename'`",[293,479,383],{"class":299},[293,481,483],{"class":295,"line":482},20,[293,484,337],{"emptyLinePlaceholder":336},[293,486,488],{"class":295,"line":487},21,[293,489,490],{"class":343},"## Rollback rule\n",[293,492,494],{"class":295,"line":493},22,[293,495,337],{"emptyLinePlaceholder":336},[293,497,499,502,505,508,511],{"class":295,"line":498},23,[293,500,501],{"class":299},"Every ",[293,503,504],{"class":373},"`up.sql`",[293,506,507],{"class":299}," must have a reversible ",[293,509,510],{"class":373},"`down.sql`",[293,512,513],{"class":299},". If the change isn't reversible (data loss, irreversible type change), refuse and ask for a plan from the user.\n",[293,515,517],{"class":295,"line":516},24,[293,518,337],{"emptyLinePlaceholder":336},[293,520,522],{"class":295,"line":521},25,[293,523,524],{"class":343},"## Example\n",[293,526,528],{"class":295,"line":527},26,[293,529,337],{"emptyLinePlaceholder":336},[293,531,533],{"class":295,"line":532},27,[293,534,535],{"class":299},"up: add a nullable column, backfill in a follow-up, then NOT NULL in a third migration.\n",[193,537,539],{"id":538},"the-two-rules-of-a-great-skill-description","The two rules of a great skill description",[11,541,542,543,545,546,549],{},"The ",[30,544,320],{}," field in the YAML frontmatter is the ",[15,547,548],{},"only"," thing the model sees when deciding whether to load the skill. Treat it like a trigger specification, not a sales pitch.",[551,552,553,559],"ol",{},[204,554,555,558],{},[80,556,557],{},"Start with \"Use this skill when…\""," and name concrete nouns the user would type.",[204,560,561,564],{},[80,562,563],{},"Include a \"do NOT trigger\" clause"," to suppress false positives on neighboring topics.",[178,566,569,579],{"title":567,"variant":568},"Anatomy of a skill folder","info",[11,570,571,572,574,575,578],{},"A skill can be just a single ",[30,573,260],{},", but it can also ship scripts, reference docs, and templates. Put them alongside the markdown and reference them with paths like ",[30,576,577],{},"scripts\u002Fbackfill.sh"," — Claude resolves those relative to the skill's folder.",[11,580,581,582,584,585,588],{},"Keep ",[30,583,260],{}," under 500 lines. If the knowledge is longer, split it into a short SKILL.md that ",[15,586,587],{},"points"," to sibling files Claude loads on demand.",[193,590,592],{"id":591},"skills-vs-claudemd-when-to-use-which","Skills vs CLAUDE.md — when to use which",[11,594,595,597,598,601],{},[30,596,32],{}," is for rules that apply to every turn. Skills are for rules that apply to ",[15,599,600],{},"some"," turns. A convention like \"use pnpm, not npm\" belongs in CLAUDE.md. A 200-line walkthrough of your OAuth flow belongs in a skill — it's useless token spend on the 80% of sessions that don't touch auth.",[22,603,605,619,622,832,836,859,863,874,963],{"id":604,"title":226},"commands",[11,606,254,607,610,611,614,615,618],{},[80,608,609],{},"slash command"," is a saved prompt. You put a markdown file in ",[30,612,613],{},".claude\u002Fcommands\u002F",", and typing ",[30,616,617],{},"\u002Fname"," expands it into Claude's input. Variables, tool restrictions, even model selection — all configurable.",[11,620,621],{},"Commands are the cheapest extension on the stack: one file, no code, no install. If you catch yourself typing the same paragraph twice, make a command.",[283,623,626],{"className":285,"code":624,"filename":625,"language":288,"meta":289,"style":289},"---\ndescription: Review the current branch against main as if you were a staff engineer\nargument-hint: [focus-area]\nallowed-tools: Read, Grep, Glob, Bash(git diff*), Bash(git log*)\nmodel: opus\n---\n\nYou are a staff-level engineer doing a code review. The user wants your honest opinion, not a rubber stamp.\n\nInspect the diff vs main:\n\n    !`git diff --stat origin\u002Fmain...HEAD`\n    !`git log --oneline origin\u002Fmain..HEAD`\n\nFor the full diff, run `git diff origin\u002Fmain...HEAD` as needed.\n\n$ARGUMENTS\n\nProduce a review with:\n\n1. **Summary** — one paragraph on what this PR does and whether it's ready.\n2. **Blocking** — issues that must be fixed before merge. Cite file:line.\n3. **Non-blocking** — style, naming, or follow-up suggestions. Cite file:line.\n4. **Missing tests** — cases not covered that matter.\n5. **Verdict** — `LGTM`, `LGTM with suggestions`, or `Needs changes`.\n\nBe specific. 'Consider refactoring' is not a comment.\n",".claude\u002Fcommands\u002Freview-pr.md",[30,627,628,632,641,655,665,675,679,683,688,692,697,701,709,716,720,731,735,740,744,749,753,764,774,784,795,823,827],{"__ignoreMap":289},[293,629,630],{"class":295,"line":296},[293,631,300],{"class":299},[293,633,634,636,638],{"class":295,"line":303},[293,635,320],{"class":306},[293,637,310],{"class":299},[293,639,640],{"class":313},"Review the current branch against main as if you were a staff engineer\n",[293,642,643,646,649,652],{"class":295,"line":317},[293,644,645],{"class":306},"argument-hint",[293,647,648],{"class":299},": [",[293,650,651],{"class":313},"focus-area",[293,653,654],{"class":299},"]\n",[293,656,657,660,662],{"class":295,"line":328},[293,658,659],{"class":306},"allowed-tools",[293,661,310],{"class":299},[293,663,664],{"class":313},"Read, Grep, Glob, Bash(git diff*), Bash(git log*)\n",[293,666,667,670,672],{"class":295,"line":333},[293,668,669],{"class":306},"model",[293,671,310],{"class":299},[293,673,674],{"class":313},"opus\n",[293,676,677],{"class":295,"line":340},[293,678,300],{"class":299},[293,680,681],{"class":295,"line":347},[293,682,337],{"emptyLinePlaceholder":336},[293,684,685],{"class":295,"line":352},[293,686,687],{"class":299},"You are a staff-level engineer doing a code review. The user wants your honest opinion, not a rubber stamp.\n",[293,689,690],{"class":295,"line":358},[293,691,337],{"emptyLinePlaceholder":336},[293,693,694],{"class":295,"line":363},[293,695,696],{"class":299},"Inspect the diff vs main:\n",[293,698,699],{"class":295,"line":386},[293,700,337],{"emptyLinePlaceholder":336},[293,702,703,706],{"class":295,"line":397},[293,704,705],{"class":299},"    !",[293,707,708],{"class":373},"`git diff --stat origin\u002Fmain...HEAD`\n",[293,710,711,713],{"class":295,"line":411},[293,712,705],{"class":299},[293,714,715],{"class":373},"`git log --oneline origin\u002Fmain..HEAD`\n",[293,717,718],{"class":295,"line":428},[293,719,337],{"emptyLinePlaceholder":336},[293,721,722,725,728],{"class":295,"line":433},[293,723,724],{"class":299},"For the full diff, run ",[293,726,727],{"class":373},"`git diff origin\u002Fmain...HEAD`",[293,729,730],{"class":299}," as needed.\n",[293,732,733],{"class":295,"line":439},[293,734,337],{"emptyLinePlaceholder":336},[293,736,737],{"class":295,"line":444},[293,738,739],{"class":299},"$ARGUMENTS\n",[293,741,742],{"class":295,"line":459},[293,743,337],{"emptyLinePlaceholder":336},[293,745,746],{"class":295,"line":468},[293,747,748],{"class":299},"Produce a review with:\n",[293,750,751],{"class":295,"line":482},[293,752,337],{"emptyLinePlaceholder":336},[293,754,755,757,761],{"class":295,"line":487},[293,756,447],{"class":366},[293,758,760],{"class":759},"sbYKK"," **Summary**",[293,762,763],{"class":299}," — one paragraph on what this PR does and whether it's ready.\n",[293,765,766,768,771],{"class":295,"line":493},[293,767,462],{"class":366},[293,769,770],{"class":759}," **Blocking**",[293,772,773],{"class":299}," — issues that must be fixed before merge. Cite file:line.\n",[293,775,776,778,781],{"class":295,"line":498},[293,777,471],{"class":366},[293,779,780],{"class":759}," **Non-blocking**",[293,782,783],{"class":299}," — style, naming, or follow-up suggestions. Cite file:line.\n",[293,785,786,789,792],{"class":295,"line":516},[293,787,788],{"class":366},"4.",[293,790,791],{"class":759}," **Missing tests**",[293,793,794],{"class":299}," — cases not covered that matter.\n",[293,796,797,800,803,806,809,812,815,818,821],{"class":295,"line":521},[293,798,799],{"class":366},"5.",[293,801,802],{"class":759}," **Verdict**",[293,804,805],{"class":299}," — ",[293,807,808],{"class":373},"`LGTM`",[293,810,811],{"class":299},", ",[293,813,814],{"class":373},"`LGTM with suggestions`",[293,816,817],{"class":299},", or ",[293,819,820],{"class":373},"`Needs changes`",[293,822,383],{"class":299},[293,824,825],{"class":295,"line":527},[293,826,337],{"emptyLinePlaceholder":336},[293,828,829],{"class":295,"line":532},[293,830,831],{"class":299},"Be specific. 'Consider refactoring' is not a comment.\n",[193,833,835],{"id":834},"how-commands-differ-from-skills","How commands differ from skills",[201,837,838,844,850],{},[204,839,840,843],{},[80,841,842],{},"You invoke commands."," Claude decides when to load skills.",[204,845,846,849],{},[80,847,848],{},"Commands expand once."," Skills stay in context for the turn.",[204,851,852,855,856,858],{},[80,853,854],{},"Commands can restrict tools."," ",[30,857,659],{}," in frontmatter scopes what Claude can do inside that invocation.",[193,860,862],{"id":861},"dynamic-commands-with-shell-substitution","Dynamic commands with shell substitution",[11,864,865,866,869,870,873],{},"Prefixing a line with ",[30,867,868],{},"!"," runs a shell command and inlines its stdout into the prompt. It's how a review command can show Claude the diff without you pasting it. Prefix with ",[30,871,872],{},"@"," to inline a file path.",[283,875,878],{"className":285,"code":876,"filename":877,"language":288,"meta":289,"style":289},"---\ndescription: Debug the last failing test\nallowed-tools: Read, Edit, Bash(npm test*)\n---\n\nThe last test run failed. Here's the output:\n\n!`npm test 2>&1 | tail -n 60`\n\nRelevant test file:\n\n@$ARGUMENTS\n\nPhase 1: Read the failing file and the module under test. Do NOT edit yet.\nPhase 2: Explain what's breaking. One paragraph.\nPhase 3: Propose a fix. Wait for approval before editing.\n",".claude\u002Fcommands\u002Fdebug-last.md",[30,879,880,884,893,902,906,910,915,919,926,930,935,939,944,948,953,958],{"__ignoreMap":289},[293,881,882],{"class":295,"line":296},[293,883,300],{"class":299},[293,885,886,888,890],{"class":295,"line":303},[293,887,320],{"class":306},[293,889,310],{"class":299},[293,891,892],{"class":313},"Debug the last failing test\n",[293,894,895,897,899],{"class":295,"line":317},[293,896,659],{"class":306},[293,898,310],{"class":299},[293,900,901],{"class":313},"Read, Edit, Bash(npm test*)\n",[293,903,904],{"class":295,"line":328},[293,905,300],{"class":299},[293,907,908],{"class":295,"line":333},[293,909,337],{"emptyLinePlaceholder":336},[293,911,912],{"class":295,"line":340},[293,913,914],{"class":299},"The last test run failed. Here's the output:\n",[293,916,917],{"class":295,"line":347},[293,918,337],{"emptyLinePlaceholder":336},[293,920,921,923],{"class":295,"line":352},[293,922,868],{"class":299},[293,924,925],{"class":373},"`npm test 2>&1 | tail -n 60`\n",[293,927,928],{"class":295,"line":358},[293,929,337],{"emptyLinePlaceholder":336},[293,931,932],{"class":295,"line":363},[293,933,934],{"class":299},"Relevant test file:\n",[293,936,937],{"class":295,"line":386},[293,938,337],{"emptyLinePlaceholder":336},[293,940,941],{"class":295,"line":397},[293,942,943],{"class":299},"@$ARGUMENTS\n",[293,945,946],{"class":295,"line":411},[293,947,337],{"emptyLinePlaceholder":336},[293,949,950],{"class":295,"line":428},[293,951,952],{"class":299},"Phase 1: Read the failing file and the module under test. Do NOT edit yet.\n",[293,954,955],{"class":295,"line":433},[293,956,957],{"class":299},"Phase 2: Explain what's breaking. One paragraph.\n",[293,959,960],{"class":295,"line":439},[293,961,962],{"class":299},"Phase 3: Propose a fix. Wait for approval before editing.\n",[178,964,966],{"title":965,"variant":181},"Personal vs team commands",[11,967,968,969,972,973,975,976,979,980,983],{},"Personal commands go in ",[30,970,971],{},"~\u002F.claude\u002Fcommands\u002F",". Team commands go in ",[30,974,613],{}," and are committed. Namespacing: a file at ",[30,977,978],{},".claude\u002Fcommands\u002Fdb\u002Fmigrate.md"," is invoked as ",[30,981,982],{},"\u002Fdb:migrate",".",[22,985,987,990,997,1001,1087,1331,1583,1784,1798,1802],{"id":986,"title":238},"hooks",[11,988,989],{},"Hooks are the harness intercepting tool calls. They fire on fixed events: before a tool runs, after a tool runs, when Claude is about to respond, when a session starts, when it ends. Each hook is a shell command that reads JSON on stdin and exits with a status code.",[11,991,992,993,996],{},"Hooks are for ",[15,994,995],{},"deterministic"," policy. \"Format every file you save\" is a hook — formatting shouldn't depend on whether Claude remembered. \"Block pushes to main\" is a hook — the cost of getting that wrong is too high to trust to a rule.",[193,998,1000],{"id":999},"the-event-surface","The event surface",[35,1002,1003,1016],{},[38,1004,1005],{},[41,1006,1007,1010,1013],{},[44,1008,1009],{},"Event",[44,1011,1012],{},"Fires when…",[44,1014,1015],{},"Typical use",[54,1017,1018,1031,1044,1057,1070],{},[41,1019,1020,1025,1028],{},[59,1021,1022],{},[30,1023,1024],{},"PreToolUse",[59,1026,1027],{},"Before a tool runs — can block it",[59,1029,1030],{},"Deny dangerous bash, require approval",[41,1032,1033,1038,1041],{},[59,1034,1035],{},[30,1036,1037],{},"PostToolUse",[59,1039,1040],{},"After a tool returns",[59,1042,1043],{},"Format on save, lint, commit nudges",[41,1045,1046,1051,1054],{},[59,1047,1048],{},[30,1049,1050],{},"UserPromptSubmit",[59,1052,1053],{},"Before Claude sees your message",[59,1055,1056],{},"Inject current git branch, redact secrets",[41,1058,1059,1064,1067],{},[59,1060,1061],{},[30,1062,1063],{},"Stop",[59,1065,1066],{},"Claude finishes a turn",[59,1068,1069],{},"Run tests, send notification, checkpoint",[41,1071,1072,1081,1084],{},[59,1073,1074,1077,1078],{},[30,1075,1076],{},"SessionStart"," \u002F ",[30,1079,1080],{},"SessionEnd",[59,1082,1083],{},"Session lifecycle",[59,1085,1086],{},"Bootstrap env, log session summary",[283,1088,1093],{"className":1089,"code":1090,"filename":1091,"language":1092,"meta":289,"style":289},"language-json shiki shiki-themes github-light","{\n  \"hooks\": {\n    \"PostToolUse\": [\n      {\n        \"matcher\": \"Edit|Write\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"bash .claude\u002Fhooks\u002Fformat-on-save.sh\"\n          }\n        ]\n      }\n    ],\n    \"PreToolUse\": [\n      {\n        \"matcher\": \"Bash\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"bash .claude\u002Fhooks\u002Fdeny-destructive.sh\"\n          }\n        ]\n      }\n    ],\n    \"Stop\": [\n      {\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"bash .claude\u002Fhooks\u002Frun-tests.sh\"\n          }\n        ]\n      }\n    ]\n  }\n}\n",".claude\u002Fsettings.json","json",[30,1094,1095,1100,1108,1116,1121,1134,1141,1146,1158,1168,1173,1178,1183,1188,1195,1199,1210,1216,1220,1230,1239,1243,1247,1251,1255,1262,1266,1272,1277,1288,1298,1303,1308,1313,1319,1325],{"__ignoreMap":289},[293,1096,1097],{"class":295,"line":296},[293,1098,1099],{"class":299},"{\n",[293,1101,1102,1105],{"class":295,"line":303},[293,1103,1104],{"class":373},"  \"hooks\"",[293,1106,1107],{"class":299},": {\n",[293,1109,1110,1113],{"class":295,"line":317},[293,1111,1112],{"class":373},"    \"PostToolUse\"",[293,1114,1115],{"class":299},": [\n",[293,1117,1118],{"class":295,"line":328},[293,1119,1120],{"class":299},"      {\n",[293,1122,1123,1126,1128,1131],{"class":295,"line":333},[293,1124,1125],{"class":373},"        \"matcher\"",[293,1127,310],{"class":299},[293,1129,1130],{"class":313},"\"Edit|Write\"",[293,1132,1133],{"class":299},",\n",[293,1135,1136,1139],{"class":295,"line":340},[293,1137,1138],{"class":373},"        \"hooks\"",[293,1140,1115],{"class":299},[293,1142,1143],{"class":295,"line":347},[293,1144,1145],{"class":299},"          {\n",[293,1147,1148,1151,1153,1156],{"class":295,"line":352},[293,1149,1150],{"class":373},"            \"type\"",[293,1152,310],{"class":299},[293,1154,1155],{"class":313},"\"command\"",[293,1157,1133],{"class":299},[293,1159,1160,1163,1165],{"class":295,"line":358},[293,1161,1162],{"class":373},"            \"command\"",[293,1164,310],{"class":299},[293,1166,1167],{"class":313},"\"bash .claude\u002Fhooks\u002Fformat-on-save.sh\"\n",[293,1169,1170],{"class":295,"line":363},[293,1171,1172],{"class":299},"          }\n",[293,1174,1175],{"class":295,"line":386},[293,1176,1177],{"class":299},"        ]\n",[293,1179,1180],{"class":295,"line":397},[293,1181,1182],{"class":299},"      }\n",[293,1184,1185],{"class":295,"line":411},[293,1186,1187],{"class":299},"    ],\n",[293,1189,1190,1193],{"class":295,"line":428},[293,1191,1192],{"class":373},"    \"PreToolUse\"",[293,1194,1115],{"class":299},[293,1196,1197],{"class":295,"line":433},[293,1198,1120],{"class":299},[293,1200,1201,1203,1205,1208],{"class":295,"line":439},[293,1202,1125],{"class":373},[293,1204,310],{"class":299},[293,1206,1207],{"class":313},"\"Bash\"",[293,1209,1133],{"class":299},[293,1211,1212,1214],{"class":295,"line":444},[293,1213,1138],{"class":373},[293,1215,1115],{"class":299},[293,1217,1218],{"class":295,"line":459},[293,1219,1145],{"class":299},[293,1221,1222,1224,1226,1228],{"class":295,"line":468},[293,1223,1150],{"class":373},[293,1225,310],{"class":299},[293,1227,1155],{"class":313},[293,1229,1133],{"class":299},[293,1231,1232,1234,1236],{"class":295,"line":482},[293,1233,1162],{"class":373},[293,1235,310],{"class":299},[293,1237,1238],{"class":313},"\"bash .claude\u002Fhooks\u002Fdeny-destructive.sh\"\n",[293,1240,1241],{"class":295,"line":487},[293,1242,1172],{"class":299},[293,1244,1245],{"class":295,"line":493},[293,1246,1177],{"class":299},[293,1248,1249],{"class":295,"line":498},[293,1250,1182],{"class":299},[293,1252,1253],{"class":295,"line":516},[293,1254,1187],{"class":299},[293,1256,1257,1260],{"class":295,"line":521},[293,1258,1259],{"class":373},"    \"Stop\"",[293,1261,1115],{"class":299},[293,1263,1264],{"class":295,"line":527},[293,1265,1120],{"class":299},[293,1267,1268,1270],{"class":295,"line":532},[293,1269,1138],{"class":373},[293,1271,1115],{"class":299},[293,1273,1275],{"class":295,"line":1274},28,[293,1276,1145],{"class":299},[293,1278,1280,1282,1284,1286],{"class":295,"line":1279},29,[293,1281,1150],{"class":373},[293,1283,310],{"class":299},[293,1285,1155],{"class":313},[293,1287,1133],{"class":299},[293,1289,1291,1293,1295],{"class":295,"line":1290},30,[293,1292,1162],{"class":373},[293,1294,310],{"class":299},[293,1296,1297],{"class":313},"\"bash .claude\u002Fhooks\u002Frun-tests.sh\"\n",[293,1299,1301],{"class":295,"line":1300},31,[293,1302,1172],{"class":299},[293,1304,1306],{"class":295,"line":1305},32,[293,1307,1177],{"class":299},[293,1309,1311],{"class":295,"line":1310},33,[293,1312,1182],{"class":299},[293,1314,1316],{"class":295,"line":1315},34,[293,1317,1318],{"class":299},"    ]\n",[293,1320,1322],{"class":295,"line":1321},35,[293,1323,1324],{"class":299},"  }\n",[293,1326,1328],{"class":295,"line":1327},36,[293,1329,1330],{"class":299},"}\n",[283,1332,1337],{"className":1333,"code":1334,"filename":1335,"language":1336,"meta":289,"style":289},"language-bash shiki shiki-themes github-light","#!\u002Fusr\u002Fbin\u002Fenv bash\n# PostToolUse hook: format files Claude just wrote.\n# Reads JSON on stdin, extracts file paths, runs prettier.\n\nset -euo pipefail\n\n# Input looks like: { \"tool\": \"Edit\", \"tool_input\": { \"file_path\": \"...\" } }\nPATHS=$(jq -r \".tool_input.file_path \u002F\u002F empty\" \u003C\u003C\u003C \"$(cat)\")\n\n[ -z \"$PATHS\" ] && exit 0\n\nfor f in $PATHS; do\n  case \"$f\" in\n    *.ts|*.tsx|*.js|*.jsx|*.vue|*.json|*.md)\n      npx --yes prettier --write \"$f\" >\u002Fdev\u002Fnull 2>&1 || true\n      ;;\n  esac\ndone\n\nexit 0\n",".claude\u002Fhooks\u002Fformat-on-save.sh","bash",[30,1338,1339,1345,1350,1355,1359,1370,1374,1379,1416,1420,1446,1450,1467,1482,1523,1558,1563,1568,1573,1577],{"__ignoreMap":289},[293,1340,1341],{"class":295,"line":296},[293,1342,1344],{"class":1343},"sAwPA","#!\u002Fusr\u002Fbin\u002Fenv bash\n",[293,1346,1347],{"class":295,"line":303},[293,1348,1349],{"class":1343},"# PostToolUse hook: format files Claude just wrote.\n",[293,1351,1352],{"class":295,"line":317},[293,1353,1354],{"class":1343},"# Reads JSON on stdin, extracts file paths, runs prettier.\n",[293,1356,1357],{"class":295,"line":328},[293,1358,337],{"emptyLinePlaceholder":336},[293,1360,1361,1364,1367],{"class":295,"line":333},[293,1362,1363],{"class":373},"set",[293,1365,1366],{"class":373}," -euo",[293,1368,1369],{"class":313}," pipefail\n",[293,1371,1372],{"class":295,"line":340},[293,1373,337],{"emptyLinePlaceholder":336},[293,1375,1376],{"class":295,"line":347},[293,1377,1378],{"class":1343},"# Input looks like: { \"tool\": \"Edit\", \"tool_input\": { \"file_path\": \"...\" } }\n",[293,1380,1381,1384,1388,1391,1395,1398,1401,1404,1407,1410,1413],{"class":295,"line":352},[293,1382,1383],{"class":299},"PATHS",[293,1385,1387],{"class":1386},"sD7c4","=",[293,1389,1390],{"class":299},"$(",[293,1392,1394],{"class":1393},"s7eDp","jq",[293,1396,1397],{"class":373}," -r",[293,1399,1400],{"class":313}," \".tool_input.file_path \u002F\u002F empty\"",[293,1402,1403],{"class":1386}," \u003C\u003C\u003C",[293,1405,1406],{"class":313}," \"$(",[293,1408,1409],{"class":1393},"cat",[293,1411,1412],{"class":313},")\"",[293,1414,1415],{"class":299},")\n",[293,1417,1418],{"class":295,"line":358},[293,1419,337],{"emptyLinePlaceholder":336},[293,1421,1422,1425,1428,1431,1434,1437,1440,1443],{"class":295,"line":363},[293,1423,1424],{"class":299},"[ ",[293,1426,1427],{"class":1386},"-z",[293,1429,1430],{"class":313}," \"",[293,1432,1433],{"class":299},"$PATHS",[293,1435,1436],{"class":313},"\"",[293,1438,1439],{"class":299}," ] && ",[293,1441,1442],{"class":373},"exit",[293,1444,1445],{"class":373}," 0\n",[293,1447,1448],{"class":295,"line":386},[293,1449,337],{"emptyLinePlaceholder":336},[293,1451,1452,1455,1458,1461,1464],{"class":295,"line":397},[293,1453,1454],{"class":1386},"for",[293,1456,1457],{"class":299}," f ",[293,1459,1460],{"class":1386},"in",[293,1462,1463],{"class":299}," $PATHS; ",[293,1465,1466],{"class":1386},"do\n",[293,1468,1469,1472,1474,1477,1479],{"class":295,"line":411},[293,1470,1471],{"class":1386},"  case",[293,1473,1430],{"class":313},[293,1475,1476],{"class":299},"$f",[293,1478,1436],{"class":313},[293,1480,1481],{"class":1386}," in\n",[293,1483,1484,1487,1490,1493,1496,1498,1501,1503,1506,1508,1511,1513,1516,1518,1521],{"class":295,"line":428},[293,1485,1486],{"class":1386},"    *",[293,1488,1489],{"class":313},".ts",[293,1491,1492],{"class":1386},"|*",[293,1494,1495],{"class":313},".tsx",[293,1497,1492],{"class":1386},[293,1499,1500],{"class":313},".js",[293,1502,1492],{"class":1386},[293,1504,1505],{"class":313},".jsx",[293,1507,1492],{"class":1386},[293,1509,1510],{"class":313},".vue",[293,1512,1492],{"class":1386},[293,1514,1515],{"class":313},".json",[293,1517,1492],{"class":1386},[293,1519,1520],{"class":313},".md",[293,1522,1415],{"class":1386},[293,1524,1525,1528,1531,1534,1537,1539,1541,1543,1546,1549,1552,1555],{"class":295,"line":433},[293,1526,1527],{"class":1393},"      npx",[293,1529,1530],{"class":373}," --yes",[293,1532,1533],{"class":313}," prettier",[293,1535,1536],{"class":373}," --write",[293,1538,1430],{"class":313},[293,1540,1476],{"class":299},[293,1542,1436],{"class":313},[293,1544,1545],{"class":1386}," >",[293,1547,1548],{"class":313},"\u002Fdev\u002Fnull",[293,1550,1551],{"class":1386}," 2>&1",[293,1553,1554],{"class":1386}," ||",[293,1556,1557],{"class":373}," true\n",[293,1559,1560],{"class":295,"line":439},[293,1561,1562],{"class":299},"      ;;\n",[293,1564,1565],{"class":295,"line":444},[293,1566,1567],{"class":1386},"  esac\n",[293,1569,1570],{"class":295,"line":459},[293,1571,1572],{"class":1386},"done\n",[293,1574,1575],{"class":295,"line":468},[293,1576,337],{"emptyLinePlaceholder":336},[293,1578,1579,1581],{"class":295,"line":482},[293,1580,1442],{"class":373},[293,1582,1445],{"class":373},[283,1584,1587],{"className":1333,"code":1585,"filename":1586,"language":1336,"meta":289,"style":289},"#!\u002Fusr\u002Fbin\u002Fenv bash\n# PreToolUse hook: block obviously destructive shell commands.\n# Exit 2 = block + return message to Claude.\n\nset -euo pipefail\n\nCMD=$(jq -r \".tool_input.command \u002F\u002F empty\" \u003C\u003C\u003C \"$(cat)\")\n\ndeny() {\n  echo \"Blocked by policy: $1\" >&2\n  exit 2\n}\n\ncase \"$CMD\" in\n  *\"rm -rf \u002F\"*|*\"rm -rf ~\"*) deny \"recursive delete of system paths\" ;;\n  *\"git push --force\"*)       deny \"force-push requires a human\" ;;\n  *\"git reset --hard origin\"*) deny \"hard reset to remote — confirm with a human\" ;;\nesac\n\nexit 0\n",".claude\u002Fhooks\u002Fdeny-destructive.sh",[30,1588,1589,1593,1598,1603,1607,1615,1619,1645,1649,1657,1673,1681,1685,1689,1703,1732,1751,1769,1774,1778],{"__ignoreMap":289},[293,1590,1591],{"class":295,"line":296},[293,1592,1344],{"class":1343},[293,1594,1595],{"class":295,"line":303},[293,1596,1597],{"class":1343},"# PreToolUse hook: block obviously destructive shell commands.\n",[293,1599,1600],{"class":295,"line":317},[293,1601,1602],{"class":1343},"# Exit 2 = block + return message to Claude.\n",[293,1604,1605],{"class":295,"line":328},[293,1606,337],{"emptyLinePlaceholder":336},[293,1608,1609,1611,1613],{"class":295,"line":333},[293,1610,1363],{"class":373},[293,1612,1366],{"class":373},[293,1614,1369],{"class":313},[293,1616,1617],{"class":295,"line":340},[293,1618,337],{"emptyLinePlaceholder":336},[293,1620,1621,1624,1626,1628,1630,1632,1635,1637,1639,1641,1643],{"class":295,"line":347},[293,1622,1623],{"class":299},"CMD",[293,1625,1387],{"class":1386},[293,1627,1390],{"class":299},[293,1629,1394],{"class":1393},[293,1631,1397],{"class":373},[293,1633,1634],{"class":313}," \".tool_input.command \u002F\u002F empty\"",[293,1636,1403],{"class":1386},[293,1638,1406],{"class":313},[293,1640,1409],{"class":1393},[293,1642,1412],{"class":313},[293,1644,1415],{"class":299},[293,1646,1647],{"class":295,"line":352},[293,1648,337],{"emptyLinePlaceholder":336},[293,1650,1651,1654],{"class":295,"line":358},[293,1652,1653],{"class":1393},"deny",[293,1655,1656],{"class":299},"() {\n",[293,1658,1659,1662,1665,1668,1670],{"class":295,"line":363},[293,1660,1661],{"class":373},"  echo",[293,1663,1664],{"class":313}," \"Blocked by policy: ",[293,1666,1667],{"class":373},"$1",[293,1669,1436],{"class":313},[293,1671,1672],{"class":1386}," >&2\n",[293,1674,1675,1678],{"class":295,"line":386},[293,1676,1677],{"class":373},"  exit",[293,1679,1680],{"class":373}," 2\n",[293,1682,1683],{"class":295,"line":397},[293,1684,1330],{"class":299},[293,1686,1687],{"class":295,"line":411},[293,1688,337],{"emptyLinePlaceholder":336},[293,1690,1691,1694,1696,1699,1701],{"class":295,"line":428},[293,1692,1693],{"class":1386},"case",[293,1695,1430],{"class":313},[293,1697,1698],{"class":299},"$CMD",[293,1700,1436],{"class":313},[293,1702,1481],{"class":1386},[293,1704,1705,1708,1711,1714,1717,1720,1723,1726,1729],{"class":295,"line":433},[293,1706,1707],{"class":1386},"  *",[293,1709,1710],{"class":313},"\"rm -rf \u002F\"",[293,1712,1713],{"class":1386},"*|*",[293,1715,1716],{"class":313},"\"rm -rf ~\"",[293,1718,1719],{"class":1386},"*",[293,1721,1722],{"class":1386},")",[293,1724,1725],{"class":1393}," deny",[293,1727,1728],{"class":313}," \"recursive delete of system paths\"",[293,1730,1731],{"class":299}," ;;\n",[293,1733,1734,1736,1739,1741,1743,1746,1749],{"class":295,"line":439},[293,1735,1707],{"class":1386},[293,1737,1738],{"class":313},"\"git push --force\"",[293,1740,1719],{"class":1386},[293,1742,1722],{"class":1386},[293,1744,1745],{"class":1393},"       deny",[293,1747,1748],{"class":313}," \"force-push requires a human\"",[293,1750,1731],{"class":299},[293,1752,1753,1755,1758,1760,1762,1764,1767],{"class":295,"line":444},[293,1754,1707],{"class":1386},[293,1756,1757],{"class":313},"\"git reset --hard origin\"",[293,1759,1719],{"class":1386},[293,1761,1722],{"class":1386},[293,1763,1725],{"class":1393},[293,1765,1766],{"class":313}," \"hard reset to remote — confirm with a human\"",[293,1768,1731],{"class":299},[293,1770,1771],{"class":295,"line":459},[293,1772,1773],{"class":1386},"esac\n",[293,1775,1776],{"class":295,"line":468},[293,1777,337],{"emptyLinePlaceholder":336},[293,1779,1780,1782],{"class":295,"line":482},[293,1781,1442],{"class":373},[293,1783,1445],{"class":373},[178,1785,1788],{"title":1786,"variant":1787},"Exit codes matter","warning",[11,1789,1790,1793,1794,1797],{},[80,1791,1792],{},"0"," — continue silently. ",[80,1795,1796],{},"2"," — block the tool call and return stderr to Claude (it will read the message and adjust). Anything else — error, the harness surfaces it to you.",[193,1799,1801],{"id":1800},"hooks-vs-claudemd-rules","Hooks vs CLAUDE.md rules",[11,1803,1804],{},"A CLAUDE.md rule is a suggestion Claude can forget. A hook is policy the machine enforces. Rule of thumb: if the cost of non-compliance is \"minor annoyance,\" use CLAUDE.md. If the cost is \"production outage,\" use a hook. Use both when it matters — CLAUDE.md explains why, the hook guarantees it.",[22,1806,1809,1819,1822,2001,2005,2008,2017,2023,2027],{"id":1807,"title":1808},"subagents","Subagents",[11,1810,254,1811,1814,1815,1818],{},[80,1812,1813],{},"subagent"," is a Claude instance spawned by your main Claude, with a fresh context window and a specific job. The main Claude hands off the task via the ",[30,1816,1817],{},"Task"," tool, the subagent does its work, and only the final summary comes back. Your main context stays clean.",[11,1820,1821],{},"The pattern unlocks two things: parallelism (spawn three subagents at once, wait for all three) and context isolation (a subagent can read 500 files without polluting the main conversation).",[283,1823,1826],{"className":285,"code":1824,"filename":1825,"language":288,"meta":289,"style":289},"---\nname: codebase-explorer\ndescription: Use this agent when you need to quickly understand how something works across many files. Specify thoroughness: 'quick' for 2-3 files, 'medium' for a feature, 'thorough' for cross-cutting concerns. Returns a structured answer — does not edit.\ntools: Read, Grep, Glob, Bash(git log*), Bash(git blame*)\nmodel: haiku\n---\n\nYou are a code explorer. Your job is to answer a focused question about an unfamiliar codebase with surgical precision.\n\n## Your rules\n\n- You do NOT edit files. Ever. Your tool set reflects that.\n- Start broad (Glob), narrow (Grep), then confirm (Read).\n- If you read more than 30 files without answers, stop and report what you found.\n- Always cite file:line when you make a claim.\n\n## Output format\n\nReturn one of these, nothing else:\n\n**Answer:** \u003Cthe direct answer>\n**Evidence:**\n- `src\u002Ffoo.ts:42` — \u003Cwhat it shows>\n- `src\u002Fbar.ts:108` — \u003Cwhat it shows>\n**Confidence:** high | medium | low\n**Follow-ups:** \u003Conly if the main Claude should investigate further>\n",".claude\u002Fagents\u002Fcodebase-explorer.md",[30,1827,1828,1832,1841,1858,1868,1877,1881,1885,1890,1894,1899,1903,1910,1917,1924,1931,1935,1940,1944,1949,1953,1961,1966,1976,1985,1993],{"__ignoreMap":289},[293,1829,1830],{"class":295,"line":296},[293,1831,300],{"class":299},[293,1833,1834,1836,1838],{"class":295,"line":303},[293,1835,307],{"class":306},[293,1837,310],{"class":299},[293,1839,1840],{"class":313},"codebase-explorer\n",[293,1842,1843,1845,1847,1850,1852,1855],{"class":295,"line":317},[293,1844,320],{"class":306},[293,1846,310],{"class":299},[293,1848,1849],{"class":306},"Use this agent when you need to quickly understand how something works across many files. Specify thoroughness",[293,1851,310],{"class":299},[293,1853,1854],{"class":313},"'quick'",[293,1856,1857],{"class":313}," for 2-3 files, 'medium' for a feature, 'thorough' for cross-cutting concerns. Returns a structured answer — does not edit.\n",[293,1859,1860,1863,1865],{"class":295,"line":328},[293,1861,1862],{"class":306},"tools",[293,1864,310],{"class":299},[293,1866,1867],{"class":313},"Read, Grep, Glob, Bash(git log*), Bash(git blame*)\n",[293,1869,1870,1872,1874],{"class":295,"line":333},[293,1871,669],{"class":306},[293,1873,310],{"class":299},[293,1875,1876],{"class":313},"haiku\n",[293,1878,1879],{"class":295,"line":340},[293,1880,300],{"class":299},[293,1882,1883],{"class":295,"line":347},[293,1884,337],{"emptyLinePlaceholder":336},[293,1886,1887],{"class":295,"line":352},[293,1888,1889],{"class":299},"You are a code explorer. Your job is to answer a focused question about an unfamiliar codebase with surgical precision.\n",[293,1891,1892],{"class":295,"line":358},[293,1893,337],{"emptyLinePlaceholder":336},[293,1895,1896],{"class":295,"line":363},[293,1897,1898],{"class":343},"## Your rules\n",[293,1900,1901],{"class":295,"line":386},[293,1902,337],{"emptyLinePlaceholder":336},[293,1904,1905,1907],{"class":295,"line":397},[293,1906,367],{"class":366},[293,1908,1909],{"class":299}," You do NOT edit files. Ever. Your tool set reflects that.\n",[293,1911,1912,1914],{"class":295,"line":411},[293,1913,367],{"class":366},[293,1915,1916],{"class":299}," Start broad (Glob), narrow (Grep), then confirm (Read).\n",[293,1918,1919,1921],{"class":295,"line":428},[293,1920,367],{"class":366},[293,1922,1923],{"class":299}," If you read more than 30 files without answers, stop and report what you found.\n",[293,1925,1926,1928],{"class":295,"line":433},[293,1927,367],{"class":366},[293,1929,1930],{"class":299}," Always cite file:line when you make a claim.\n",[293,1932,1933],{"class":295,"line":439},[293,1934,337],{"emptyLinePlaceholder":336},[293,1936,1937],{"class":295,"line":444},[293,1938,1939],{"class":343},"## Output format\n",[293,1941,1942],{"class":295,"line":459},[293,1943,337],{"emptyLinePlaceholder":336},[293,1945,1946],{"class":295,"line":468},[293,1947,1948],{"class":299},"Return one of these, nothing else:\n",[293,1950,1951],{"class":295,"line":482},[293,1952,337],{"emptyLinePlaceholder":336},[293,1954,1955,1958],{"class":295,"line":487},[293,1956,1957],{"class":759},"**Answer:**",[293,1959,1960],{"class":299}," \u003Cthe direct answer>\n",[293,1962,1963],{"class":295,"line":493},[293,1964,1965],{"class":759},"**Evidence:**\n",[293,1967,1968,1970,1973],{"class":295,"line":498},[293,1969,367],{"class":366},[293,1971,1972],{"class":373}," `src\u002Ffoo.ts:42`",[293,1974,1975],{"class":299}," — \u003Cwhat it shows>\n",[293,1977,1978,1980,1983],{"class":295,"line":516},[293,1979,367],{"class":366},[293,1981,1982],{"class":373}," `src\u002Fbar.ts:108`",[293,1984,1975],{"class":299},[293,1986,1987,1990],{"class":295,"line":521},[293,1988,1989],{"class":759},"**Confidence:**",[293,1991,1992],{"class":299}," high | medium | low\n",[293,1994,1995,1998],{"class":295,"line":527},[293,1996,1997],{"class":759},"**Follow-ups:**",[293,1999,2000],{"class":299}," \u003Conly if the main Claude should investigate further>\n",[193,2002,2004],{"id":2003},"how-the-main-claude-invokes-a-subagent","How the main Claude invokes a subagent",[11,2006,2007],{},"From the main session, you describe the task and Claude chooses the agent by name. The delegation looks like this in your transcript:",[283,2009,2015],{"className":2010,"code":2012,"filename":2013,"language":2014,"meta":289},[2011],"language-text","Use the codebase-explorer agent with \"medium\" thoroughness to find every place we cache user profiles. I want the caching key format, the TTL, and which service writes vs reads. Do not change any code.\n","prompt","text",[30,2016,2012],{"__ignoreMap":289},[178,2018,2020],{"title":2019,"variant":568},"Subagents and token economics",[11,2021,2022],{},"Subagents pay their own context cost. A fresh 50K-token exploration in a subagent costs the same as doing it inline — except only a 2K summary lands in your main conversation. For one-off questions, inline is cheaper. For questions you'll re-ask over the session, delegation is.",[193,2024,2026],{"id":2025},"when-not-to-use-a-subagent","When NOT to use a subagent",[201,2028,2029,2032,2035],{},[204,2030,2031],{},"Short, fast questions — spinning up a fresh context adds latency.",[204,2033,2034],{},"Tasks that require back-and-forth with the user — subagents can't pause for clarification.",[204,2036,2037],{},"Anything that needs the main session's existing context — subagents start blank, they don't inherit your scratchpad.",[22,2039,2042,2056,2236,2420,2424,2435,2438],{"id":2040,"title":2041},"agent-teams","Agent Teams",[11,2043,2044,2045,2048,2049,2052,2053,2055],{},"An ",[80,2046,2047],{},"agent team"," is the next step up: multiple subagents working in parallel, coordinated by an orchestrator, with shared state on disk. You get this when you structure your repo around ",[30,2050,2051],{},"AGENTS.md"," — a sibling to ",[30,2054,32],{}," that names the roles and the rules of engagement.",[283,2057,2059],{"className":285,"code":2058,"filename":2051,"language":288,"meta":289,"style":289},"# Agent Team\n\nThis repo runs a four-agent team for feature work. The orchestrator (the main Claude session) delegates to three specialists.\n\n## Roles\n\n- **planner** — turns a feature request into a written plan. Read-only. Model: opus.\n- **implementer** — executes one plan step end-to-end. Model: sonnet.\n- **reviewer** — reads the diff and files a PR review. Read-only. Model: opus.\n- **tester** — writes or extends tests for the change. Model: sonnet.\n\n## Shared state\n\n- Plans live at `.claude\u002Fstate\u002Fplans\u002F\u003Cfeature>.md`.\n- Reviews live at `.claude\u002Fstate\u002Freviews\u002F\u003Cfeature>.md`.\n- Every agent reads and writes here; the orchestrator is the traffic cop.\n\n## Rules of engagement\n\n- Only the implementer edits source files.\n- The reviewer NEVER edits. If it finds issues, it writes a review doc and hands back to the orchestrator.\n- The planner never implements. If it catches itself writing code, stop and write plan steps instead.\n- The tester can edit only files matching `**\u002F*.test.*`.\n\n## Ordering\n\nplanner → implementer → tester → reviewer → (orchestrator decides ship vs repair).\n",[30,2060,2061,2066,2070,2075,2079,2084,2088,2098,2108,2118,2128,2132,2137,2141,2153,2165,2172,2176,2181,2185,2192,2199,2206,2218,2222,2227,2231],{"__ignoreMap":289},[293,2062,2063],{"class":295,"line":296},[293,2064,2065],{"class":343},"# Agent Team\n",[293,2067,2068],{"class":295,"line":303},[293,2069,337],{"emptyLinePlaceholder":336},[293,2071,2072],{"class":295,"line":317},[293,2073,2074],{"class":299},"This repo runs a four-agent team for feature work. The orchestrator (the main Claude session) delegates to three specialists.\n",[293,2076,2077],{"class":295,"line":328},[293,2078,337],{"emptyLinePlaceholder":336},[293,2080,2081],{"class":295,"line":333},[293,2082,2083],{"class":343},"## Roles\n",[293,2085,2086],{"class":295,"line":340},[293,2087,337],{"emptyLinePlaceholder":336},[293,2089,2090,2092,2095],{"class":295,"line":347},[293,2091,367],{"class":366},[293,2093,2094],{"class":759}," **planner**",[293,2096,2097],{"class":299}," — turns a feature request into a written plan. Read-only. Model: opus.\n",[293,2099,2100,2102,2105],{"class":295,"line":352},[293,2101,367],{"class":366},[293,2103,2104],{"class":759}," **implementer**",[293,2106,2107],{"class":299}," — executes one plan step end-to-end. Model: sonnet.\n",[293,2109,2110,2112,2115],{"class":295,"line":358},[293,2111,367],{"class":366},[293,2113,2114],{"class":759}," **reviewer**",[293,2116,2117],{"class":299}," — reads the diff and files a PR review. Read-only. Model: opus.\n",[293,2119,2120,2122,2125],{"class":295,"line":363},[293,2121,367],{"class":366},[293,2123,2124],{"class":759}," **tester**",[293,2126,2127],{"class":299}," — writes or extends tests for the change. Model: sonnet.\n",[293,2129,2130],{"class":295,"line":386},[293,2131,337],{"emptyLinePlaceholder":336},[293,2133,2134],{"class":295,"line":397},[293,2135,2136],{"class":343},"## Shared state\n",[293,2138,2139],{"class":295,"line":411},[293,2140,337],{"emptyLinePlaceholder":336},[293,2142,2143,2145,2148,2151],{"class":295,"line":428},[293,2144,367],{"class":366},[293,2146,2147],{"class":299}," Plans live at ",[293,2149,2150],{"class":373},"`.claude\u002Fstate\u002Fplans\u002F\u003Cfeature>.md`",[293,2152,383],{"class":299},[293,2154,2155,2157,2160,2163],{"class":295,"line":433},[293,2156,367],{"class":366},[293,2158,2159],{"class":299}," Reviews live at ",[293,2161,2162],{"class":373},"`.claude\u002Fstate\u002Freviews\u002F\u003Cfeature>.md`",[293,2164,383],{"class":299},[293,2166,2167,2169],{"class":295,"line":439},[293,2168,367],{"class":366},[293,2170,2171],{"class":299}," Every agent reads and writes here; the orchestrator is the traffic cop.\n",[293,2173,2174],{"class":295,"line":444},[293,2175,337],{"emptyLinePlaceholder":336},[293,2177,2178],{"class":295,"line":459},[293,2179,2180],{"class":343},"## Rules of engagement\n",[293,2182,2183],{"class":295,"line":468},[293,2184,337],{"emptyLinePlaceholder":336},[293,2186,2187,2189],{"class":295,"line":482},[293,2188,367],{"class":366},[293,2190,2191],{"class":299}," Only the implementer edits source files.\n",[293,2193,2194,2196],{"class":295,"line":487},[293,2195,367],{"class":366},[293,2197,2198],{"class":299}," The reviewer NEVER edits. If it finds issues, it writes a review doc and hands back to the orchestrator.\n",[293,2200,2201,2203],{"class":295,"line":493},[293,2202,367],{"class":366},[293,2204,2205],{"class":299}," The planner never implements. If it catches itself writing code, stop and write plan steps instead.\n",[293,2207,2208,2210,2213,2216],{"class":295,"line":498},[293,2209,367],{"class":366},[293,2211,2212],{"class":299}," The tester can edit only files matching ",[293,2214,2215],{"class":373},"`**\u002F*.test.*`",[293,2217,383],{"class":299},[293,2219,2220],{"class":295,"line":516},[293,2221,337],{"emptyLinePlaceholder":336},[293,2223,2224],{"class":295,"line":521},[293,2225,2226],{"class":343},"## Ordering\n",[293,2228,2229],{"class":295,"line":527},[293,2230,337],{"emptyLinePlaceholder":336},[293,2232,2233],{"class":295,"line":532},[293,2234,2235],{"class":299},"planner → implementer → tester → reviewer → (orchestrator decides ship vs repair).\n",[283,2237,2240],{"className":285,"code":2238,"filename":2239,"language":288,"meta":289,"style":289},"---\nname: reviewer\ndescription: Use this agent to review a diff for correctness, style, and missing tests. It reads but never edits. It writes its verdict to .claude\u002Fstate\u002Freviews\u002F.\ntools: Read, Grep, Glob, Bash(git diff*), Write\nmodel: opus\n---\n\nYou are the reviewer on a three-agent feature team. You receive a branch name and write a structured review.\n\n## Workflow\n\n1. Run `git diff main...HEAD` and read every changed file in full.\n2. For each change, answer: does this do what the plan said? Is it correct? Is it tested?\n3. Write your review to `.claude\u002Fstate\u002Freviews\u002F\u003Cbranch>.md` using the format below.\n4. Return a one-line summary to the orchestrator.\n\n## Review format\n\n    # Review: \u003Cbranch>\n\n    ## Verdict\n    LGTM | LGTM with suggestions | Needs changes\n\n    ## Blocking\n    - file:line — \u003Cissue>\n\n    ## Non-blocking\n    - file:line — \u003Csuggestion>\n\n    ## Missing tests\n    - \u003Ccase>\n",".claude\u002Fagents\u002Freviewer.md",[30,2241,2242,2246,2255,2264,2273,2281,2285,2289,2294,2298,2303,2307,2319,2326,2339,2346,2350,2355,2359,2364,2368,2373,2378,2382,2387,2392,2396,2401,2406,2410,2415],{"__ignoreMap":289},[293,2243,2244],{"class":295,"line":296},[293,2245,300],{"class":299},[293,2247,2248,2250,2252],{"class":295,"line":303},[293,2249,307],{"class":306},[293,2251,310],{"class":299},[293,2253,2254],{"class":313},"reviewer\n",[293,2256,2257,2259,2261],{"class":295,"line":317},[293,2258,320],{"class":306},[293,2260,310],{"class":299},[293,2262,2263],{"class":313},"Use this agent to review a diff for correctness, style, and missing tests. It reads but never edits. It writes its verdict to .claude\u002Fstate\u002Freviews\u002F.\n",[293,2265,2266,2268,2270],{"class":295,"line":328},[293,2267,1862],{"class":306},[293,2269,310],{"class":299},[293,2271,2272],{"class":313},"Read, Grep, Glob, Bash(git diff*), Write\n",[293,2274,2275,2277,2279],{"class":295,"line":333},[293,2276,669],{"class":306},[293,2278,310],{"class":299},[293,2280,674],{"class":313},[293,2282,2283],{"class":295,"line":340},[293,2284,300],{"class":299},[293,2286,2287],{"class":295,"line":347},[293,2288,337],{"emptyLinePlaceholder":336},[293,2290,2291],{"class":295,"line":352},[293,2292,2293],{"class":299},"You are the reviewer on a three-agent feature team. You receive a branch name and write a structured review.\n",[293,2295,2296],{"class":295,"line":358},[293,2297,337],{"emptyLinePlaceholder":336},[293,2299,2300],{"class":295,"line":363},[293,2301,2302],{"class":343},"## Workflow\n",[293,2304,2305],{"class":295,"line":386},[293,2306,337],{"emptyLinePlaceholder":336},[293,2308,2309,2311,2313,2316],{"class":295,"line":397},[293,2310,447],{"class":366},[293,2312,450],{"class":299},[293,2314,2315],{"class":373},"`git diff main...HEAD`",[293,2317,2318],{"class":299}," and read every changed file in full.\n",[293,2320,2321,2323],{"class":295,"line":411},[293,2322,462],{"class":366},[293,2324,2325],{"class":299}," For each change, answer: does this do what the plan said? Is it correct? Is it tested?\n",[293,2327,2328,2330,2333,2336],{"class":295,"line":428},[293,2329,471],{"class":366},[293,2331,2332],{"class":299}," Write your review to ",[293,2334,2335],{"class":373},"`.claude\u002Fstate\u002Freviews\u002F\u003Cbranch>.md`",[293,2337,2338],{"class":299}," using the format below.\n",[293,2340,2341,2343],{"class":295,"line":433},[293,2342,788],{"class":366},[293,2344,2345],{"class":299}," Return a one-line summary to the orchestrator.\n",[293,2347,2348],{"class":295,"line":439},[293,2349,337],{"emptyLinePlaceholder":336},[293,2351,2352],{"class":295,"line":444},[293,2353,2354],{"class":343},"## Review format\n",[293,2356,2357],{"class":295,"line":459},[293,2358,337],{"emptyLinePlaceholder":336},[293,2360,2361],{"class":295,"line":468},[293,2362,2363],{"class":299},"    # Review: \u003Cbranch>\n",[293,2365,2366],{"class":295,"line":482},[293,2367,337],{"emptyLinePlaceholder":336},[293,2369,2370],{"class":295,"line":487},[293,2371,2372],{"class":299},"    ## Verdict\n",[293,2374,2375],{"class":295,"line":493},[293,2376,2377],{"class":299},"    LGTM | LGTM with suggestions | Needs changes\n",[293,2379,2380],{"class":295,"line":498},[293,2381,337],{"emptyLinePlaceholder":336},[293,2383,2384],{"class":295,"line":516},[293,2385,2386],{"class":299},"    ## Blocking\n",[293,2388,2389],{"class":295,"line":521},[293,2390,2391],{"class":299},"    - file:line — \u003Cissue>\n",[293,2393,2394],{"class":295,"line":527},[293,2395,337],{"emptyLinePlaceholder":336},[293,2397,2398],{"class":295,"line":532},[293,2399,2400],{"class":299},"    ## Non-blocking\n",[293,2402,2403],{"class":295,"line":1274},[293,2404,2405],{"class":299},"    - file:line — \u003Csuggestion>\n",[293,2407,2408],{"class":295,"line":1279},[293,2409,337],{"emptyLinePlaceholder":336},[293,2411,2412],{"class":295,"line":1290},[293,2413,2414],{"class":299},"    ## Missing tests\n",[293,2416,2417],{"class":295,"line":1300},[293,2418,2419],{"class":299},"    - \u003Ccase>\n",[193,2421,2423],{"id":2422},"conductor-vs-orchestrator","Conductor vs orchestrator",[11,2425,2426,2427,2430,2431,2434],{},"Two patterns dominate team setups. ",[80,2428,2429],{},"Conductor"," — a human drives, kicking off agents one at a time and reading results before moving on. Higher-trust, lower-risk, suitable for small teams and novel work. ",[80,2432,2433],{},"Orchestrator"," — the main Claude drives, calling subagents autonomously according to the AGENTS.md. Higher-throughput, best for well-shaped tasks the team has done many times.",[11,2436,2437],{},"Start with conductor. Graduate to orchestrator once your AGENTS.md is battle-tested.",[178,2439,2441],{"title":2440,"variant":181},"Worktrees pair beautifully with teams",[11,2442,2443,2444,983],{},"Give each concurrent agent its own git worktree. Isolated branches, no write contention on the working directory, and the reviewer can run side-by-side with the implementer. See ",[2445,2446,2448],"a",{"href":2447},"\u002Forchestration#worktrees","Orchestration → Git Worktrees",[22,2450,2453,2469,2480,2668,2672,2679,2703,2797],{"id":2451,"title":2452},"mcp","MCP",[11,2454,2455,2457,2458,2461,2462,2465,2466,983],{},[80,2456,2452],{}," — the Model Context Protocol — is the standard for plugging external services into Claude as first-class tools. Where hooks intercept tool calls and subagents spawn new Claudes, MCP adds ",[15,2459,2460],{},"new tools"," — a Linear \"create issue\" tool, a Postgres \"run query\" tool, a Sentry \"fetch error\" tool — that Claude calls the same way it calls ",[30,2463,2464],{},"Read"," or ",[30,2467,2468],{},"Bash",[11,2470,2471,2472,2475,2476,2479],{},"An MCP server is any process that speaks the protocol. It can run locally (stdio transport) or remotely (HTTP\u002FSSE). Anthropic and third parties publish hundreds; Claude Code discovers them from ",[30,2473,2474],{},".mcp.json"," in your project or ",[30,2477,2478],{},"~\u002F.claude\u002Fmcp.json"," personally.",[283,2481,2483],{"className":1089,"code":2482,"filename":2474,"language":1092,"meta":289,"style":289},"{\n  \"mcpServers\": {\n    \"postgres\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"-y\",\n        \"@modelcontextprotocol\u002Fserver-postgres\",\n        \"postgresql:\u002F\u002Flocalhost:5432\u002Fdev\"\n      ]\n    },\n    \"linear\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@modelcontextprotocol\u002Fserver-linear\"],\n      \"env\": {\n        \"LINEAR_API_KEY\": \"${env:LINEAR_API_KEY}\"\n      }\n    },\n    \"filesystem-docs\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"-y\",\n        \"@modelcontextprotocol\u002Fserver-filesystem\",\n        \"\u002FUsers\u002Fyou\u002Fcompany-docs\"\n      ]\n    }\n  }\n}\n",[30,2484,2485,2489,2496,2503,2515,2522,2529,2536,2541,2546,2551,2558,2568,2585,2592,2602,2606,2610,2617,2627,2633,2639,2646,2651,2655,2660,2664],{"__ignoreMap":289},[293,2486,2487],{"class":295,"line":296},[293,2488,1099],{"class":299},[293,2490,2491,2494],{"class":295,"line":303},[293,2492,2493],{"class":373},"  \"mcpServers\"",[293,2495,1107],{"class":299},[293,2497,2498,2501],{"class":295,"line":317},[293,2499,2500],{"class":373},"    \"postgres\"",[293,2502,1107],{"class":299},[293,2504,2505,2508,2510,2513],{"class":295,"line":328},[293,2506,2507],{"class":373},"      \"command\"",[293,2509,310],{"class":299},[293,2511,2512],{"class":313},"\"npx\"",[293,2514,1133],{"class":299},[293,2516,2517,2520],{"class":295,"line":333},[293,2518,2519],{"class":373},"      \"args\"",[293,2521,1115],{"class":299},[293,2523,2524,2527],{"class":295,"line":340},[293,2525,2526],{"class":313},"        \"-y\"",[293,2528,1133],{"class":299},[293,2530,2531,2534],{"class":295,"line":347},[293,2532,2533],{"class":313},"        \"@modelcontextprotocol\u002Fserver-postgres\"",[293,2535,1133],{"class":299},[293,2537,2538],{"class":295,"line":352},[293,2539,2540],{"class":313},"        \"postgresql:\u002F\u002Flocalhost:5432\u002Fdev\"\n",[293,2542,2543],{"class":295,"line":358},[293,2544,2545],{"class":299},"      ]\n",[293,2547,2548],{"class":295,"line":363},[293,2549,2550],{"class":299},"    },\n",[293,2552,2553,2556],{"class":295,"line":386},[293,2554,2555],{"class":373},"    \"linear\"",[293,2557,1107],{"class":299},[293,2559,2560,2562,2564,2566],{"class":295,"line":397},[293,2561,2507],{"class":373},[293,2563,310],{"class":299},[293,2565,2512],{"class":313},[293,2567,1133],{"class":299},[293,2569,2570,2572,2574,2577,2579,2582],{"class":295,"line":411},[293,2571,2519],{"class":373},[293,2573,648],{"class":299},[293,2575,2576],{"class":313},"\"-y\"",[293,2578,811],{"class":299},[293,2580,2581],{"class":313},"\"@modelcontextprotocol\u002Fserver-linear\"",[293,2583,2584],{"class":299},"],\n",[293,2586,2587,2590],{"class":295,"line":428},[293,2588,2589],{"class":373},"      \"env\"",[293,2591,1107],{"class":299},[293,2593,2594,2597,2599],{"class":295,"line":433},[293,2595,2596],{"class":373},"        \"LINEAR_API_KEY\"",[293,2598,310],{"class":299},[293,2600,2601],{"class":313},"\"${env:LINEAR_API_KEY}\"\n",[293,2603,2604],{"class":295,"line":439},[293,2605,1182],{"class":299},[293,2607,2608],{"class":295,"line":444},[293,2609,2550],{"class":299},[293,2611,2612,2615],{"class":295,"line":459},[293,2613,2614],{"class":373},"    \"filesystem-docs\"",[293,2616,1107],{"class":299},[293,2618,2619,2621,2623,2625],{"class":295,"line":468},[293,2620,2507],{"class":373},[293,2622,310],{"class":299},[293,2624,2512],{"class":313},[293,2626,1133],{"class":299},[293,2628,2629,2631],{"class":295,"line":482},[293,2630,2519],{"class":373},[293,2632,1115],{"class":299},[293,2634,2635,2637],{"class":295,"line":487},[293,2636,2526],{"class":313},[293,2638,1133],{"class":299},[293,2640,2641,2644],{"class":295,"line":493},[293,2642,2643],{"class":313},"        \"@modelcontextprotocol\u002Fserver-filesystem\"",[293,2645,1133],{"class":299},[293,2647,2648],{"class":295,"line":498},[293,2649,2650],{"class":313},"        \"\u002FUsers\u002Fyou\u002Fcompany-docs\"\n",[293,2652,2653],{"class":295,"line":516},[293,2654,2545],{"class":299},[293,2656,2657],{"class":295,"line":521},[293,2658,2659],{"class":299},"    }\n",[293,2661,2662],{"class":295,"line":527},[293,2663,1324],{"class":299},[293,2665,2666],{"class":295,"line":532},[293,2667,1330],{"class":299},[193,2669,2671],{"id":2670},"choosing-mcp-over-a-shell-command","Choosing MCP over a shell command",[11,2673,2674,2675,2678],{},"You could let Claude call ",[30,2676,2677],{},"psql"," via Bash and scrape the output. It'll work — for a while. MCP beats it on three axes:",[201,2680,2681,2687,2693],{},[204,2682,2683,2686],{},[80,2684,2685],{},"Structured returns"," — rows come back as JSON, not terminal formatting Claude re-parses every time.",[204,2688,2689,2692],{},[80,2690,2691],{},"Discoverability"," — MCP advertises the tools it provides; Claude knows what's available without trial and error.",[204,2694,2695,2698,2699,2702],{},[80,2696,2697],{},"Permissions"," — you can allowlist MCP tools individually in ",[30,2700,2701],{},"settings.json",", finer-grained than \"allow all bash.\"",[283,2704,2707],{"className":1089,"code":2705,"filename":2706,"language":1092,"meta":289,"style":289},"{\n  \"permissions\": {\n    \"allow\": [\n      \"mcp__postgres__query\",\n      \"mcp__linear__list_issues\",\n      \"mcp__linear__get_issue\"\n    ],\n    \"ask\": [\n      \"mcp__linear__create_issue\",\n      \"mcp__linear__update_issue\"\n    ],\n    \"deny\": [\n      \"mcp__linear__delete_issue\"\n    ]\n  }\n}\n",".claude\u002Fsettings.json (MCP permissions)",[30,2708,2709,2713,2720,2727,2734,2741,2746,2750,2757,2764,2769,2773,2780,2785,2789,2793],{"__ignoreMap":289},[293,2710,2711],{"class":295,"line":296},[293,2712,1099],{"class":299},[293,2714,2715,2718],{"class":295,"line":303},[293,2716,2717],{"class":373},"  \"permissions\"",[293,2719,1107],{"class":299},[293,2721,2722,2725],{"class":295,"line":317},[293,2723,2724],{"class":373},"    \"allow\"",[293,2726,1115],{"class":299},[293,2728,2729,2732],{"class":295,"line":328},[293,2730,2731],{"class":313},"      \"mcp__postgres__query\"",[293,2733,1133],{"class":299},[293,2735,2736,2739],{"class":295,"line":333},[293,2737,2738],{"class":313},"      \"mcp__linear__list_issues\"",[293,2740,1133],{"class":299},[293,2742,2743],{"class":295,"line":340},[293,2744,2745],{"class":313},"      \"mcp__linear__get_issue\"\n",[293,2747,2748],{"class":295,"line":347},[293,2749,1187],{"class":299},[293,2751,2752,2755],{"class":295,"line":352},[293,2753,2754],{"class":373},"    \"ask\"",[293,2756,1115],{"class":299},[293,2758,2759,2762],{"class":295,"line":358},[293,2760,2761],{"class":313},"      \"mcp__linear__create_issue\"",[293,2763,1133],{"class":299},[293,2765,2766],{"class":295,"line":363},[293,2767,2768],{"class":313},"      \"mcp__linear__update_issue\"\n",[293,2770,2771],{"class":295,"line":386},[293,2772,1187],{"class":299},[293,2774,2775,2778],{"class":295,"line":397},[293,2776,2777],{"class":373},"    \"deny\"",[293,2779,1115],{"class":299},[293,2781,2782],{"class":295,"line":411},[293,2783,2784],{"class":313},"      \"mcp__linear__delete_issue\"\n",[293,2786,2787],{"class":295,"line":428},[293,2788,1318],{"class":299},[293,2790,2791],{"class":295,"line":433},[293,2792,1324],{"class":299},[293,2794,2795],{"class":295,"line":439},[293,2796,1330],{"class":299},[178,2798,2800],{"title":2799,"variant":568},"Writing your own MCP server",[11,2801,2802,2803,983],{},"The SDK is a few hundred lines to get running. If your team has an internal tool Claude keeps needing — a feature flag system, an audit log, an internal search engine — wrapping it in MCP is a day's work and pays back every session. See ",[2445,2804,2808],{"href":2805,"rel":2806},"https:\u002F\u002Fmodelcontextprotocol.io",[2807],"nofollow","modelcontextprotocol.io",[22,2810,2813,2823,3020,3024,3088,3097,3101],{"id":2811,"title":2812},"plugins","Plugins",[11,2814,254,2815,2818,2819,2822],{},[80,2816,2817],{},"plugin"," is a bundle: one or more skills, commands, hooks, subagents, and MCP servers, shipped as a single unit with a ",[30,2820,2821],{},"plugin.json"," manifest. Plugins solve the \"how do I share my setup with the team\" problem without asking everyone to paste eight files into the right folders.",[283,2824,2826],{"className":1089,"code":2825,"filename":2821,"language":1092,"meta":289,"style":289},"{\n  \"name\": \"company-workflows\",\n  \"version\": \"1.2.0\",\n  \"description\": \"Internal engineering workflows: PR reviews, migrations, feature flag checks.\",\n  \"author\": \"Platform Team \u003Cplatform@example.com>\",\n  \"homepage\": \"https:\u002F\u002Fgithub.com\u002Fexample\u002Fcompany-workflows\",\n  \"commands\": [\n    \"commands\u002Freview-pr.md\",\n    \"commands\u002Fmigrate.md\",\n    \"commands\u002Fflag-status.md\"\n  ],\n  \"skills\": [\n    \"skills\u002Fpostgres-migrations\u002F\",\n    \"skills\u002Ffeature-flags\u002F\"\n  ],\n  \"agents\": [\n    \"agents\u002Freviewer.md\"\n  ],\n  \"hooks\": \"hooks.json\",\n  \"mcpServers\": {\n    \"flags\": {\n      \"command\": \"node\",\n      \"args\": [\".\u002Fmcp\u002Fflag-server.js\"]\n    }\n  }\n}\n",[30,2827,2828,2832,2844,2856,2868,2880,2892,2899,2906,2913,2918,2923,2930,2937,2942,2946,2953,2958,2962,2973,2979,2986,2997,3008,3012,3016],{"__ignoreMap":289},[293,2829,2830],{"class":295,"line":296},[293,2831,1099],{"class":299},[293,2833,2834,2837,2839,2842],{"class":295,"line":303},[293,2835,2836],{"class":373},"  \"name\"",[293,2838,310],{"class":299},[293,2840,2841],{"class":313},"\"company-workflows\"",[293,2843,1133],{"class":299},[293,2845,2846,2849,2851,2854],{"class":295,"line":317},[293,2847,2848],{"class":373},"  \"version\"",[293,2850,310],{"class":299},[293,2852,2853],{"class":313},"\"1.2.0\"",[293,2855,1133],{"class":299},[293,2857,2858,2861,2863,2866],{"class":295,"line":328},[293,2859,2860],{"class":373},"  \"description\"",[293,2862,310],{"class":299},[293,2864,2865],{"class":313},"\"Internal engineering workflows: PR reviews, migrations, feature flag checks.\"",[293,2867,1133],{"class":299},[293,2869,2870,2873,2875,2878],{"class":295,"line":333},[293,2871,2872],{"class":373},"  \"author\"",[293,2874,310],{"class":299},[293,2876,2877],{"class":313},"\"Platform Team \u003Cplatform@example.com>\"",[293,2879,1133],{"class":299},[293,2881,2882,2885,2887,2890],{"class":295,"line":340},[293,2883,2884],{"class":373},"  \"homepage\"",[293,2886,310],{"class":299},[293,2888,2889],{"class":313},"\"https:\u002F\u002Fgithub.com\u002Fexample\u002Fcompany-workflows\"",[293,2891,1133],{"class":299},[293,2893,2894,2897],{"class":295,"line":347},[293,2895,2896],{"class":373},"  \"commands\"",[293,2898,1115],{"class":299},[293,2900,2901,2904],{"class":295,"line":352},[293,2902,2903],{"class":313},"    \"commands\u002Freview-pr.md\"",[293,2905,1133],{"class":299},[293,2907,2908,2911],{"class":295,"line":358},[293,2909,2910],{"class":313},"    \"commands\u002Fmigrate.md\"",[293,2912,1133],{"class":299},[293,2914,2915],{"class":295,"line":363},[293,2916,2917],{"class":313},"    \"commands\u002Fflag-status.md\"\n",[293,2919,2920],{"class":295,"line":386},[293,2921,2922],{"class":299},"  ],\n",[293,2924,2925,2928],{"class":295,"line":397},[293,2926,2927],{"class":373},"  \"skills\"",[293,2929,1115],{"class":299},[293,2931,2932,2935],{"class":295,"line":411},[293,2933,2934],{"class":313},"    \"skills\u002Fpostgres-migrations\u002F\"",[293,2936,1133],{"class":299},[293,2938,2939],{"class":295,"line":428},[293,2940,2941],{"class":313},"    \"skills\u002Ffeature-flags\u002F\"\n",[293,2943,2944],{"class":295,"line":433},[293,2945,2922],{"class":299},[293,2947,2948,2951],{"class":295,"line":439},[293,2949,2950],{"class":373},"  \"agents\"",[293,2952,1115],{"class":299},[293,2954,2955],{"class":295,"line":444},[293,2956,2957],{"class":313},"    \"agents\u002Freviewer.md\"\n",[293,2959,2960],{"class":295,"line":459},[293,2961,2922],{"class":299},[293,2963,2964,2966,2968,2971],{"class":295,"line":468},[293,2965,1104],{"class":373},[293,2967,310],{"class":299},[293,2969,2970],{"class":313},"\"hooks.json\"",[293,2972,1133],{"class":299},[293,2974,2975,2977],{"class":295,"line":482},[293,2976,2493],{"class":373},[293,2978,1107],{"class":299},[293,2980,2981,2984],{"class":295,"line":487},[293,2982,2983],{"class":373},"    \"flags\"",[293,2985,1107],{"class":299},[293,2987,2988,2990,2992,2995],{"class":295,"line":493},[293,2989,2507],{"class":373},[293,2991,310],{"class":299},[293,2993,2994],{"class":313},"\"node\"",[293,2996,1133],{"class":299},[293,2998,2999,3001,3003,3006],{"class":295,"line":498},[293,3000,2519],{"class":373},[293,3002,648],{"class":299},[293,3004,3005],{"class":313},"\".\u002Fmcp\u002Fflag-server.js\"",[293,3007,654],{"class":299},[293,3009,3010],{"class":295,"line":516},[293,3011,2659],{"class":299},[293,3013,3014],{"class":295,"line":521},[293,3015,1324],{"class":299},[293,3017,3018],{"class":295,"line":527},[293,3019,1330],{"class":299},[193,3021,3023],{"id":3022},"installing-a-plugin","Installing a plugin",[283,3025,3027],{"className":1333,"code":3026,"language":1336,"meta":289,"style":289},"# From the marketplace\nclaude plugin install company-workflows\n\n# From a git repo\nclaude plugin install https:\u002F\u002Fgithub.com\u002Fexample\u002Fcompany-workflows\n\n# Local development\nclaude plugin install .\u002Fpath\u002Fto\u002Fplugin\n",[30,3028,3029,3034,3048,3052,3057,3068,3072,3077],{"__ignoreMap":289},[293,3030,3031],{"class":295,"line":296},[293,3032,3033],{"class":1343},"# From the marketplace\n",[293,3035,3036,3039,3042,3045],{"class":295,"line":303},[293,3037,3038],{"class":1393},"claude",[293,3040,3041],{"class":313}," plugin",[293,3043,3044],{"class":313}," install",[293,3046,3047],{"class":313}," company-workflows\n",[293,3049,3050],{"class":295,"line":317},[293,3051,337],{"emptyLinePlaceholder":336},[293,3053,3054],{"class":295,"line":328},[293,3055,3056],{"class":1343},"# From a git repo\n",[293,3058,3059,3061,3063,3065],{"class":295,"line":333},[293,3060,3038],{"class":1393},[293,3062,3041],{"class":313},[293,3064,3044],{"class":313},[293,3066,3067],{"class":313}," https:\u002F\u002Fgithub.com\u002Fexample\u002Fcompany-workflows\n",[293,3069,3070],{"class":295,"line":340},[293,3071,337],{"emptyLinePlaceholder":336},[293,3073,3074],{"class":295,"line":347},[293,3075,3076],{"class":1343},"# Local development\n",[293,3078,3079,3081,3083,3085],{"class":295,"line":352},[293,3080,3038],{"class":1393},[293,3082,3041],{"class":313},[293,3084,3044],{"class":313},[293,3086,3087],{"class":313}," .\u002Fpath\u002Fto\u002Fplugin\n",[178,3089,3091],{"title":3090,"variant":181},"Plugin vs copy-paste",[11,3092,3093,3094,3096],{},"Copy-paste is fine for one-off projects. The moment two engineers have the same skill in their ",[30,3095,271],{},", you've got a plugin waiting to happen — one source of truth, version-pinned, one command to upgrade everyone. Future-you will thank past-you.",[193,3098,3100],{"id":3099},"marketplaces","Marketplaces",[11,3102,3103,3104,3106,3107,3110],{},"Plugins can be grouped into ",[15,3105,3099],{},": a directory with a ",[30,3108,3109],{},"marketplace.json"," listing multiple plugins. This is how Anthropic's official plugin catalog is structured, and how companies publish internal catalogs. Your team's marketplace can live on a private GitHub repo; Claude Code honors SSH auth.",[22,3112,3115,3124,3131,3135,3155,3242,3254,3258],{"id":3113,"title":3114},"lsp","LSP",[11,3116,3117,3119,3120,3123],{},[80,3118,3114],{}," — Language Server Protocol — is the same thing your editor uses to show red squiggles. When Claude Code is plugged into an LSP (directly in the VS Code extension, or via an MCP bridge in the terminal), it sees ",[15,3121,3122],{},"live diagnostics"," as it edits. Type errors, missing imports, unresolved symbols — all before a single test runs.",[11,3125,3126,3127,3130],{},"For typed languages this is a step-change. The typical \"edit, ",[30,3128,3129],{},"npm run tsc",", see error, edit again\" loop collapses to one turn.",[193,3132,3134],{"id":3133},"how-the-plumbing-looks","How the plumbing looks",[201,3136,3137,3143,3149],{},[204,3138,3139,3142],{},[80,3140,3141],{},"VS Code extension"," — LSP comes free, the extension brokers it to Claude.",[204,3144,3145,3148],{},[80,3146,3147],{},"Terminal CLI"," — run an LSP-over-MCP bridge (several exist on npm and PyPI). The bridge spawns your project's language server and exposes diagnostics as MCP tools.",[204,3150,3151,3154],{},[80,3152,3153],{},"JetBrains plugin"," — LSP built in.",[283,3156,3159],{"className":1089,"code":3157,"filename":3158,"language":1092,"meta":289,"style":289},"{\n  \"mcpServers\": {\n    \"tsserver\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"-y\",\n        \"@modelcontextprotocol\u002Fserver-lsp\",\n        \"--\",\n        \"typescript-language-server\",\n        \"--stdio\"\n      ]\n    }\n  }\n}\n",".mcp.json (typescript-language-server bridge)",[30,3160,3161,3165,3171,3178,3188,3194,3200,3207,3214,3221,3226,3230,3234,3238],{"__ignoreMap":289},[293,3162,3163],{"class":295,"line":296},[293,3164,1099],{"class":299},[293,3166,3167,3169],{"class":295,"line":303},[293,3168,2493],{"class":373},[293,3170,1107],{"class":299},[293,3172,3173,3176],{"class":295,"line":317},[293,3174,3175],{"class":373},"    \"tsserver\"",[293,3177,1107],{"class":299},[293,3179,3180,3182,3184,3186],{"class":295,"line":328},[293,3181,2507],{"class":373},[293,3183,310],{"class":299},[293,3185,2512],{"class":313},[293,3187,1133],{"class":299},[293,3189,3190,3192],{"class":295,"line":333},[293,3191,2519],{"class":373},[293,3193,1115],{"class":299},[293,3195,3196,3198],{"class":295,"line":340},[293,3197,2526],{"class":313},[293,3199,1133],{"class":299},[293,3201,3202,3205],{"class":295,"line":347},[293,3203,3204],{"class":313},"        \"@modelcontextprotocol\u002Fserver-lsp\"",[293,3206,1133],{"class":299},[293,3208,3209,3212],{"class":295,"line":352},[293,3210,3211],{"class":313},"        \"--\"",[293,3213,1133],{"class":299},[293,3215,3216,3219],{"class":295,"line":358},[293,3217,3218],{"class":313},"        \"typescript-language-server\"",[293,3220,1133],{"class":299},[293,3222,3223],{"class":295,"line":363},[293,3224,3225],{"class":313},"        \"--stdio\"\n",[293,3227,3228],{"class":295,"line":386},[293,3229,2545],{"class":299},[293,3231,3232],{"class":295,"line":397},[293,3233,2659],{"class":299},[293,3235,3236],{"class":295,"line":411},[293,3237,1324],{"class":299},[293,3239,3240],{"class":295,"line":428},[293,3241,1330],{"class":299},[178,3243,3245],{"title":3244,"variant":181},"Pair LSP with a Stop hook",[11,3246,3247,3248,3250,3251,3253],{},"The strongest feedback loop in 2026: LSP for compile-time, a ",[30,3249,1063],{}," hook that runs your unit tests, and a ",[30,3252,1037],{}," hook that runs your formatter. Claude now has three automatic verdicts on every turn: \"does it type?\", \"does it format?\", \"does it pass?\" The agent learns from the answers and fixes its own mistakes without you intervening.",[193,3255,3257],{"id":3256},"what-lsp-isnt","What LSP isn't",[11,3259,3260,3261,3263],{},"LSP gives Claude diagnostics for the language server's own checks — type errors, lint rules your IDE knows about, unresolved imports. It doesn't replace running your tests, and it doesn't replace a good ",[30,3262,32],{},". Think of it as a fourth sense, not a replacement for planning.",[3265,3266,3267],"style",{},"html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .shJU0, html code.shiki .shJU0{--shiki-default:#22863A}html pre.shiki code .surfw, html code.shiki .surfw{--shiki-default:#005CC5;--shiki-default-font-weight:bold}html pre.shiki code .sqxcx, html code.shiki .sqxcx{--shiki-default:#E36209}html pre.shiki code .sbYKK, html code.shiki .sbYKK{--shiki-default:#24292E;--shiki-default-font-weight:bold}",{"title":289,"searchDepth":303,"depth":303,"links":3269},[3270,3271,3272,3273,3274,3275,3276,3277,3278,3279,3280,3281,3282,3283,3284],{"id":195,"depth":317,"text":196},{"id":538,"depth":317,"text":539},{"id":591,"depth":317,"text":592},{"id":834,"depth":317,"text":835},{"id":861,"depth":317,"text":862},{"id":999,"depth":317,"text":1000},{"id":1800,"depth":317,"text":1801},{"id":2003,"depth":317,"text":2004},{"id":2025,"depth":317,"text":2026},{"id":2422,"depth":317,"text":2423},{"id":2670,"depth":317,"text":2671},{"id":3022,"depth":317,"text":3023},{"id":3099,"depth":317,"text":3100},{"id":3133,"depth":317,"text":3134},{"id":3256,"depth":317,"text":3257},"Skills, Commands, Hooks, Subagents, Agent Teams, MCP, Plugins, and LSP — when to reach for each, with a paste-ready example for every layer.","35 min","md","The 6 layers","LucidePuzzle",null,{},{"title":3293,"path":3294},"Token Mastery","\u002Ftokens","\u002Fextensions",{"title":3297,"path":3298},"Workflows","\u002Fworkflows",{"title":3300,"description":3301},"Extensions — Skills, Hooks, Subagents, MCP & More",{"The nine extension layers of Claude Code explained with paste-ready examples":3302,"keywords":3303,"proficiencyLevel":3308,"timeRequired":3309},"Skills, Commands, Hooks, Subagents, Agent Teams, MCP, Plugins, and LSP — with a decision framework for which to reach for when.",[3304,251,3305,986,1807,3306,2451,3307,2811,3113,2051],"claude code extensions","slash commands","agent teams","model context protocol","Intermediate","PT35M",[3311,3312,3313,3314,3315,3316,3317,3318,3319],{"id":24,"title":25,"level":303},{"id":251,"title":220,"level":303},{"id":604,"title":226,"level":303},{"id":986,"title":238,"level":303},{"id":1807,"title":1808,"level":303},{"id":2040,"title":2041,"level":303},{"id":2451,"title":2452,"level":303},{"id":2811,"title":2812,"level":303},{"id":3113,"title":3114,"level":303},"KIF6nKnngjGp3_4tkZN08QUBVYfrgQk0peYrbktN0fM",1777109528355]