{"owner":"luongnv89","repo":"claude-howto","hasSkills":true,"totalSkillsCount":84,"totalTokensCount":236430,"categories":["anthropic-skill","plugin-manifest","command-prompt","claude-rule"],"hasMcp":false,"mcpConfig":null,"found":[".claude/skills/lesson-quiz/README.md",".claude/skills/lesson-quiz/SKILL.md",".claude/skills/lesson-quiz/references/question-bank.md",".claude/skills/lesson-quiz/references/results-template.md",".claude/skills/self-assessment/README.md",".claude/skills/self-assessment/SKILL.md",".claude/skills/self-assessment/references/deep-assessment-rounds.md",".claude/skills/self-assessment/references/output-templates.md",".claude/skills/self-assessment/references/topic-recommendations.md","03-skills/blog-draft/SKILL.md","03-skills/brand-voice/SKILL.md","03-skills/claude-md/SKILL.md","03-skills/code-review-specialist/SKILL.md","03-skills/doc-generator/SKILL.md","03-skills/refactor/SKILL.md","03-skills/refactor/references/code-smells.md","03-skills/refactor/references/refactoring-catalog.md","07-plugins/README.md","07-plugins/devops-automation/.claude-plugin/plugin.json","07-plugins/devops-automation/README.md","07-plugins/documentation/.claude-plugin/plugin.json","07-plugins/documentation/README.md","07-plugins/documentation/commands/generate-readme.md","07-plugins/pr-review/.claude-plugin/plugin.json","07-plugins/pr-review/README.md","CLAUDE.md","ja/03-skills/blog-draft/SKILL.md","ja/03-skills/brand-voice/SKILL.md","ja/03-skills/claude-md/SKILL.md","ja/03-skills/code-review-specialist/SKILL.md","ja/03-skills/doc-generator/SKILL.md","ja/03-skills/refactor/SKILL.md","ja/03-skills/refactor/references/code-smells.md","ja/03-skills/refactor/references/refactoring-catalog.md","ja/07-plugins/README.md","ja/07-plugins/devops-automation/README.md","ja/07-plugins/documentation/README.md","ja/07-plugins/documentation/commands/generate-readme.md","ja/07-plugins/pr-review/README.md","ja/CLAUDE.md","uk/03-skills/blog-draft/SKILL.md","uk/03-skills/brand-voice/SKILL.md","uk/03-skills/claude-md/SKILL.md","uk/03-skills/code-review-specialist/SKILL.md","uk/03-skills/doc-generator/SKILL.md","uk/03-skills/refactor/SKILL.md","uk/03-skills/refactor/references/code-smells.md","uk/03-skills/refactor/references/refactoring-catalog.md","uk/07-plugins/README.md","uk/07-plugins/devops-automation/.claude-plugin/plugin.json","uk/07-plugins/devops-automation/README.md","uk/07-plugins/documentation/.claude-plugin/plugin.json","uk/07-plugins/documentation/README.md","uk/07-plugins/documentation/commands/generate-readme.md","uk/07-plugins/pr-review/.claude-plugin/plugin.json","uk/07-plugins/pr-review/README.md","uk/CLAUDE.md","vi/03-skills/blog-draft/SKILL.md","vi/03-skills/brand-voice/SKILL.md","vi/03-skills/claude-md/SKILL.md","vi/03-skills/code-review-specialist/SKILL.md","vi/03-skills/refactor/SKILL.md","vi/07-plugins/README.md","vi/07-plugins/devops-automation/.claude-plugin/plugin.json","vi/07-plugins/devops-automation/README.md","vi/07-plugins/documentation/.claude-plugin/plugin.json","vi/07-plugins/documentation/README.md","vi/07-plugins/documentation/commands/generate-readme.md","vi/07-plugins/pr-review/.claude-plugin/plugin.json","vi/07-plugins/pr-review/README.md","vi/CLAUDE.md","zh/03-skills/blog-draft/SKILL.md","zh/03-skills/brand-voice/SKILL.md","zh/03-skills/claude-md/SKILL.md","zh/03-skills/code-review-specialist/SKILL.md","zh/03-skills/doc-generator/SKILL.md","zh/03-skills/refactor/SKILL.md","zh/03-skills/refactor/references/code-smells.md","zh/03-skills/refactor/references/refactoring-catalog.md","zh/07-plugins/README.md","zh/07-plugins/devops-automation/README.md","zh/07-plugins/documentation/README.md","zh/07-plugins/documentation/commands/generate-readme.md","zh/07-plugins/pr-review/README.md"],"skills":{".claude/skills/lesson-quiz/README.md":"# Lesson Quiz\n\n> Interactive quiz that tests your understanding of a specific Claude Code lesson with 10 questions, per-question feedback, and targeted review guidance.\n\n## Highlights\n\n- 10 questions per lesson mixing conceptual understanding and practical application\n- Covers all 10 lessons (01-Slash Commands through 10-CLI)\n- Three timing modes: pre-test, progress check, or mastery verification\n- Per-question feedback with correct answers and explanations\n- Targeted review recommendations pointing to specific lesson sections\n- 100-question bank across all lessons in `references/question-bank.md`\n\n## When to Use\n\n| Say this... | Skill will... |\n|---|---|\n| \"quiz me on hooks\" | Run a 10-question quiz on Lesson 06: Hooks |\n| \"lesson quiz 03\" | Test your knowledge of Lesson 03: Skills |\n| \"do I understand MCP\" | Assess your understanding of Lesson 05: MCP |\n| \"practice quiz\" | Let you pick a lesson, then quiz you |\n\n## How It Works\n\n```mermaid\ngraph TD\n    A[\"Select lesson\"] --> B[\"Choose timing: pre/during/after\"]\n    B --> C[\"Answer 10 questions in 5 rounds\"]\n    C --> D[\"Score and review feedback\"]\n    style A fill:#4CAF50,color:#fff\n    style D fill:#2196F3,color:#fff\n```\n\n## Usage\n\n```\n/lesson-quiz [lesson-name-or-number]\n```\n\nExamples:\n```\n/lesson-quiz hooks\n/lesson-quiz 03\n/lesson-quiz advanced-features\n/lesson-quiz           # (prompts for lesson selection)\n```\n\n## Output\n\n### Score Report\n- Total score out of 10 with grade (Mastered / Proficient / Developing / Beginning)\n- Breakdown by question category (conceptual vs. practical)\n\n### Per-Question Feedback\nFor each incorrect answer:\n- What you answered vs. the correct answer\n- Explanation of why the correct answer is right\n- Specific section of the lesson to review\n\n### Timing-Aware Guidance\n- **Pre-test**: Establishes baseline, highlights areas to focus on while studying\n- **During**: Identifies what you've grasped and what to revisit\n- **After**: Confirms mastery or pinpoints remaining gaps\n\n## Resources\n\n| Path | Description |\n|---|---|\n| `references/question-bank.md` | 100 pre-written questions (10 per lesson) with answers, explanations, and review pointers |\n",".claude/skills/lesson-quiz/SKILL.md":"---\nname: lesson-quiz\ndescription: \"Test a learner on a single Claude Code tutorial lesson (01-10) with 10 questions, scoring answers and flagging weak spots. Use before, during, or after a lesson. Don't use for whole-tutorial assessment or explaining a topic instead of testing it.\"\neffort: high\nmetadata:\n  version: 1.6.2\n  author: Luong NGUYEN\n---\n\n# Lesson Quiz\n\nInteractive quiz that tests understanding of a specific Claude Code lesson with 10 questions, provides per-question feedback, and identifies areas to review.\n\n## Prerequisites\n\nThis skill requires:\n\n- The tutorial repo checked out, so the lesson directories `01-slash-commands/` … `10-cli/` and each `README.md` are readable.\n- `references/question-bank.md` present in this skill (the source of all questions).\n\nBefore starting, confirm the target lesson's `README.md` exists. If it is missing, do not fabricate questions — warn the user and ask them to check the repository structure (see Error Handling).\n\n**Guardrails:**\n\n- **Never invent questions or answers.** Ask only questions drawn from `references/question-bank.md` for the selected lesson; if the bank lacks entries for a lesson, say so rather than making them up.\n- **Score accurately.** Track which shuffled position holds the correct answer for every question and validate each response against it — never guess a score.\n- **Confirm timing before scoring.** The pre/during/after choice changes how results are framed; do not skip it.\n\n## Instructions\n\n### Step 1: Determine the Lesson\n\nIf the user provided a lesson as an argument (e.g., `/lesson-quiz hooks` or `/lesson-quiz 03`), map it to the lesson directory:\n\n**Lesson mapping:**\n- `01`, `slash-commands`, `commands` → 01-slash-commands\n- `02`, `memory` → 02-memory\n- `03`, `skills` → 03-skills\n- `04`, `subagents`, `agents` → 04-subagents\n- `05`, `mcp` → 05-mcp\n- `06`, `hooks` → 06-hooks\n- `07`, `plugins` → 07-plugins\n- `08`, `checkpoints`, `checkpoint` → 08-checkpoints\n- `09`, `advanced`, `advanced-features` → 09-advanced-features\n- `10`, `cli` → 10-cli\n\nIf no argument was provided, present a selection prompt using AskUserQuestion:\n\n**Question 1** (header: \"Lesson\"):\n\"Which lesson do you want to quiz on?\"\nOptions:\n1. \"Slash Commands (01)\" — Custom commands, skills, frontmatter, arguments\n2. \"Memory (02)\" — CLAUDE.md, memory hierarchy, rules, auto memory\n3. \"Skills (03)\" — Progressive disclosure, auto-invocation, SKILL.md\n4. \"Subagents (04)\" — Task delegation, agent config, isolation\n\n**Question 2** (header: \"Lesson\"):\n\"Which lesson do you want to quiz on? (continued)\"\nOptions:\n1. \"MCP (05)\" — External integration, transport, servers, tool search\n2. \"Hooks (06)\" — Event automation, PreToolUse, exit codes, JSON I/O\n3. \"Plugins (07)\" — Bundled solutions, marketplace, plugin.json\n4. \"More lessons...\" — Checkpoints, Advanced Features, CLI\n\nIf \"More lessons...\" is selected, present:\n\n**Question 3** (header: \"Lesson\"):\n\"Select your lesson:\"\nOptions:\n1. \"Checkpoints (08)\" — Rewind, restore, safe experimentation\n2. \"Advanced Features (09)\" — Planning, permissions, print mode, thinking\n3. \"CLI Reference (10)\" — Flags, output formats, scripting, piping\n\n### Step 2: Read the Lesson Content\n\nRead the lesson README.md file to refresh context:\n- Read file: `<lesson-directory>/README.md`\n\nThen use the question bank from `references/question-bank.md` for that lesson (10 pre-written questions with answers and explanations). To stay within the context budget, read only the one selected lesson's README — not all ten.\n\n### Step 3: Present the Quiz\n\nAsk the user about quiz timing context:\n\nUse AskUserQuestion (header: \"Timing\"):\n\"When are you taking this quiz relative to the lesson?\"\nOptions:\n1. \"Before (pre-test)\" — I haven't read the lesson yet, testing my prior knowledge\n2. \"During (progress check)\" — I'm partway through the lesson\n3. \"After (mastery check)\" — I've completed the lesson and want to verify understanding\n\nThis context affects how the results are framed (see Step 5).\n\n### Step 4: Present Questions in Rounds\n\nPresent 10 questions from the question bank in rounds of 2 questions each (5 rounds total). Each question uses AskUserQuestion with the question text and 3-4 answer options.\n\n**IMPORTANT**: Use AskUserQuestion with max 4 options per question, 2 questions per round.\n\nFor each round, present 2 questions. After the user answers each round, immediately show per-question feedback: whether each answer was correct or incorrect, and if incorrect, show the correct answer and a brief explanation. Then proceed to the next round. After all 5 rounds, proceed to final scoring.\n\n**Question format per round:**\n\nEach question from the question bank has:\n- `question`: The question text\n- `options`: 3-4 answer choices (one correct, labeled in the bank)\n- `correct`: The correct answer label\n- `explanation`: Why the answer is correct\n- `category`: \"conceptual\" or \"practical\"\n\n**CRITICAL — Shuffle answer options**: For each question, you MUST randomize the order of the answer options before presenting them via AskUserQuestion. Do NOT present them in the order they appear in the question bank (A, B, C, D), and do NOT place the correct answer first. Use a different random permutation for each question. Track which shuffled position contains the correct answer so you can score accurately.\n\nExample: If the question bank lists options A (correct), B, C, D — you might present them as: C, A, D, B. The correct answer is now in position 2.\n\nPresent each question using AskUserQuestion. Record the user's answer for each.\n\n### Step 5: Score and Present Results\n\nAfter all rounds, calculate the score and present results.\n\n**Scoring:**\n- Each correct answer = 1 point\n- Total possible = 10 points\n\n**Grade scale:**\n- 9-10: Mastered — Excellent understanding\n- 7-8: Proficient — Good grasp, minor gaps\n- 5-6: Developing — Fundamentals understood, needs review\n- 3-4: Beginning — Significant gaps, review recommended\n- 0-2: Not yet — Start from the beginning of this lesson\n\n**Output format:** Follow the report template in `references/results-template.md`. It defines the score line, the per-question results table, the \"Incorrect Answers — Review These\" block, the timing-specific message (pre-test / during / after), and the \"Recommended Next Steps\" section. Fill its bracketed placeholders with this run's data.\n\n### Step 6: Offer Follow-up\n\nAfter presenting results, use AskUserQuestion:\n\n\"What would you like to do next?\"\nOptions:\n1. \"Retake this quiz\" — Try the same lesson quiz again\n2. \"Quiz another lesson\" — Switch to a different lesson\n3. \"Explain a topic I missed\" — Get a detailed explanation of an incorrect answer\n4. \"Done\" — End the quiz session\n\nIf **Retake**: Go back to Step 4 (skip timing question, use same timing).\nIf **Quiz another lesson**: Go back to Step 1.\nIf **Explain a topic**: Ask which question number, then read the relevant section from the lesson README.md and explain it with examples.\n\n## Acceptance Criteria\n\nA completed quiz run must satisfy all of these — verify each before presenting final results:\n\n- Exactly one lesson (01-10) was resolved before any question was asked.\n- The timing context (before / during / after) was captured via AskUserQuestion.\n- 10 questions from `references/question-bank.md` for that lesson were presented, in 5 rounds of 2, with answer options shuffled per question.\n- Every answer was scored against the tracked correct-position, producing an integer score in the range 0-10.\n- **Expected output**: a `## Lesson Quiz Results` report containing the score line (`Score: N/10` with a grade label), the per-question results table, an \"Incorrect Answers — Review These\" block for each miss, and a timing-specific message.\n- The follow-up prompt (retake / another lesson / explain / done) was offered.\n\nExample: for a 7/10 \"after\" run on Hooks, the report asserts `Score: 7/10 — Proficient`, lists all 10 rows in the results table, and expands the 3 incorrect questions with correct answer, explanation, and a review pointer.\n\n## Edge Cases & Error Handling\n\n### Invalid lesson argument\nIf the argument doesn't match any lesson, show the valid lesson list and ask the user to pick one.\n\n### User wants to quit mid-quiz\nIf the user indicates they want to stop during any round, present partial results for the questions answered so far (score out of the number attempted, not out of 10).\n\n### Lesson README not found\nIf the README.md file doesn't exist at the expected path, inform the user and suggest checking the repository structure. Do not proceed with fabricated content.\n\n### Question bank missing entries for a lesson\nIf `references/question-bank.md` has no questions for the resolved lesson, tell the user and stop — never invent questions to fill the gap.\n\n## Validation\n\n### Triggering test suite\n\n**Should trigger:**\n- \"quiz me on hooks\"\n- \"lesson quiz\"\n- \"test my knowledge of lesson 3\"\n- \"practice quiz for MCP\"\n- \"do I understand skills\"\n- \"quiz me on slash commands\"\n- \"lesson-quiz 06\"\n- \"test me on checkpoints\"\n- \"how well do I know the CLI\"\n- \"quiz me before I start the memory lesson\"\n\n**Should NOT trigger:**\n- \"assess my overall level\" (use /self-assessment)\n- \"explain hooks to me\"\n- \"create a hook\"\n- \"what is MCP\"\n- \"review my code\"\n",".claude/skills/lesson-quiz/references/question-bank.md":"# Lesson Quiz — Question Bank\n\n10 questions per lesson. Each question has: category, question text, options (3-4), correct answer, explanation, and review section.\n\n---\n\n## Lesson 01: Slash Commands\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the four types of slash commands in Claude Code?\n- **Options**: A) Built-in, skills, plugin commands, MCP prompts | B) Built-in, custom, hook commands, API prompts | C) System, user, plugin, terminal commands | D) Core, extension, macro, script commands\n- **Correct**: A\n- **Explanation**: Claude Code has built-in commands (like /help, /compact), skills (SKILL.md files), plugin commands (namespaced plugin-name:command), and MCP prompts (/mcp__server__prompt).\n- **Review**: Overview section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you pass all user-provided arguments to a skill?\n- **Options**: A) Use `${args}` | B) Use `$ARGUMENTS` | C) Use `$@` | D) Use `$INPUT`\n- **Correct**: B\n- **Explanation**: `$ARGUMENTS` captures all text after the command name. For positional args, use `$0`, `$1`, etc.\n- **Review**: Arguments\n\n### Q3\n- **Category**: conceptual\n- **Question**: When both a skill (.claude/skills/name/SKILL.md) and a legacy command (.claude/commands/name.md) exist with the same name, which takes priority?\n- **Options**: A) The legacy command | B) The skill | C) Whichever was created first | D) Claude asks the user to choose\n- **Correct**: B\n- **Explanation**: Skills take precedence over legacy commands with the same name. The skill system supersedes the older command system.\n- **Review**: Skill vs Command Conflict section\n\n### Q4\n- **Category**: practical\n- **Question**: How do you inject live shell output into a skill's prompt?\n- **Options**: A) Use `$(command)` syntax | B) Use `!`command`` (backtick with !) syntax | C) Use `@shell:command` syntax | D) Use `{command}` syntax\n- **Correct**: B\n- **Explanation**: The `!`command`` syntax runs a shell command and injects its output into the skill prompt before Claude sees it.\n- **Review**: Dynamic Context with Shell Commands\n\n### Q5\n- **Category**: conceptual\n- **Question**: What does `disable-model-invocation: true` do in a skill's frontmatter?\n- **Options**: A) Prevents the skill from running entirely | B) Allows only the user to invoke it (Claude cannot auto-invoke) | C) Hides it from the /help menu | D) Disables the skill's AI processing\n- **Correct**: B\n- **Explanation**: `disable-model-invocation: true` means only the user can trigger the command via `/command-name`. Claude will never auto-invoke it, useful for skills with side effects like deployments.\n- **Review**: Frontmatter Reference section\n\n### Q6\n- **Category**: practical\n- **Question**: You want to create a skill that only Claude can invoke automatically (hidden from the user's / menu). Which frontmatter field do you set?\n- **Options**: A) `disable-model-invocation: true` | B) `user-invocable: false` | C) `hidden: true` | D) `auto-only: true`\n- **Correct**: B\n- **Explanation**: `user-invocable: false` hides the skill from the user's slash menu but allows Claude to invoke it automatically based on context.\n- **Review**: Frontmatter Reference section\n\n### Q7\n- **Category**: practical\n- **Question**: What is the correct directory structure for a new custom skill called \"deploy\"?\n- **Options**: A) `.claude/commands/deploy.md` | B) `.claude/skills/deploy/SKILL.md` | C) `.claude/skills/deploy.md` | D) `.claude/deploy/SKILL.md`\n- **Correct**: B\n- **Explanation**: Skills live in a directory under `.claude/skills/` with a `SKILL.md` file inside. The directory name matches the command name.\n- **Review**: Creating a Custom Command as a Skill section\n\n### Q8\n- **Category**: conceptual\n- **Question**: How do plugin commands avoid name conflicts with user commands?\n- **Options**: A) They use a `plugin-name:command-name` namespace | B) They have a special .plugin extension | C) They are prefixed with `p/` | D) They override user commands automatically\n- **Correct**: A\n- **Explanation**: Plugin commands use a namespace like `pr-review:check-security` to avoid conflicts with standalone user commands.\n- **Review**: Plugin commands section\n\n### Q9\n- **Category**: practical\n- **Question**: You want a skill to use certain tools without asking for permission each time. Which frontmatter field do you add?\n- **Options**: A) `tools: [Read, Grep]` | B) `allowed-tools: [Read, Grep]` | C) `permissions: [Read, Grep]` | D) `restrict-tools: [Read, Grep]`\n- **Correct**: B\n- **Explanation**: `allowed-tools` pre-approves the listed tools during the turn that invokes the skill, so Claude can use them without a permission prompt; the grant clears when you send your next message. It does not restrict which tools are available — to remove tools while a skill is active, use `disallowed-tools`.\n- **Review**: Frontmatter Reference\n\n### Q10\n- **Category**: conceptual\n- **Question**: What is the `@file` syntax used for in a skill?\n- **Options**: A) Importing another skill | B) Referencing a file to include its content in the prompt | C) Creating a symlink | D) Setting file permissions\n- **Correct**: B\n- **Explanation**: The `@path/to/file` syntax in a skill includes the referenced file's content into the prompt, allowing skills to pull in templates or context files.\n- **Review**: File references section\n\n---\n\n## Lesson 02: Memory\n\n### Q1\n- **Category**: conceptual\n- **Question**: How do CLAUDE.md memory files relate to each other, and what has the highest authority?\n- **Options**: A) Higher tiers override lower tiers entirely | B) They are concatenated into context; Managed Policy loads first and cannot be excluded | C) The most recently modified file wins | D) Project Memory has the highest priority\n- **Correct**: B\n- **Explanation**: CLAUDE.md files are concatenated into context rather than overriding each other — load order sets position in context, not precedence. Managed Policy (admin-managed) loads first and cannot be excluded by individual settings. Auto memory is a separate mechanism.\n- **Review**: Memory hierarchy section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you quickly add a new rule to memory during a conversation?\n- **Options**: A) Use the `/memory` slash command or ask conversationally | B) Prefix your message with `#` (e.g., `# always use TypeScript`) | C) Type `/rule \"rule text\"` | D) Use `@add-memory \"rule text\"`\n- **Correct**: A\n- **Explanation**: Use `/memory` to open your CLAUDE.md and auto memory files in your editor, or ask Claude conversationally. Asking Claude to \"remember\" something (e.g., \"remember that we always use TypeScript strict mode\") saves it to auto memory; to put it in CLAUDE.md instead, say \"add this to CLAUDE.md\". The `#` prefix was discontinued and no longer works.\n- **Review**: Quick memory updates section in README\n\n### Q3\n- **Category**: conceptual\n- **Question**: What is the maximum depth for `@path/to/file` imports in CLAUDE.md?\n- **Options**: A) 3 levels deep | B) 4 levels deep | C) 10 levels deep | D) Unlimited\n- **Correct**: B\n- **Explanation**: The `@path` import syntax supports recursive imports up to a maximum depth of 4 hops to prevent infinite loops.\n- **Review**: The /memory Command section (Import features)\n\n### Q4\n- **Category**: practical\n- **Question**: How do you scope a rule file to only apply to files in `src/api/`?\n- **Options**: A) Put the rule in `src/api/CLAUDE.md` | B) Add `paths: src/api/**` YAML frontmatter to a `.claude/rules/*.md` file | C) Name the file `.claude/rules/api.md` | D) Use `@scope: src/api` in the rule file\n- **Correct**: B\n- **Explanation**: Files in `.claude/rules/` support a `paths:` frontmatter field with glob patterns to scope rules to specific directories.\n- **Review**: Path-specific rules section\n\n### Q5\n- **Category**: conceptual\n- **Question**: How many lines of Auto Memory's MEMORY.md are loaded at session start?\n- **Options**: A) All lines | B) First 100 lines | C) First 200 lines | D) First 500 lines\n- **Correct**: C\n- **Explanation**: The first 200 lines of MEMORY.md — or the first 25 KB, whichever comes first — are auto-loaded into context at session start. Topic files referenced from MEMORY.md are loaded on demand.\n- **Review**: Auto Memory section\n\n### Q6\n- **Category**: practical\n- **Question**: You want personal project preferences that are NOT committed to git. Which file should you use?\n- **Options**: A) `~/.claude/CLAUDE.md` | B) `CLAUDE.local.md` | C) `.claude/rules/personal.md` | D) `.claude/memory/personal.md`\n- **Correct**: B\n- **Explanation**: `CLAUDE.local.md` in the project root is for personal project-specific preferences. It should be git-ignored.\n- **Review**: Memory Locations Table\n\n### Q7\n- **Category**: conceptual\n- **Question**: What does the `/init` command do?\n- **Options**: A) Initializes a new Claude Code project from scratch | B) Generates a template CLAUDE.md based on your project structure | C) Resets all memory to defaults | D) Creates a new session\n- **Correct**: B\n- **Explanation**: `/init` analyzes your project and generates a template CLAUDE.md with suggested rules and standards. Re-running it on an existing CLAUDE.md suggests improvements.\n- **Review**: /init command section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you disable Auto Memory completely?\n- **Options**: A) Delete the ~/.claude/projects directory | B) Set `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1` | C) Add `auto-memory: false` to CLAUDE.md | D) Use `/memory disable auto`\n- **Correct**: B\n- **Explanation**: Setting `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1` disables auto memory. Value `0` forces it on. Unset = default on.\n- **Review**: Turning Auto Memory On or Off\n\n### Q9\n- **Category**: conceptual\n- **Question**: Can a lower-priority memory tier override rules from a higher-priority tier?\n- **Options**: A) Yes, the most recent rule always wins | B) No — CLAUDE.md files are concatenated into context, not overridden; load order sets position, not precedence | C) Yes, if the lower tier uses the `!important` flag | D) It depends on the rule type\n- **Correct**: B\n- **Explanation**: CLAUDE.md files (user, project, local, rules) are concatenated into context rather than overriding each other — later files appear later in context, not \"instead of\" earlier ones. Only Managed Policy is special: it loads first and cannot be excluded by individual settings. Auto memory is a separate mechanism, not part of the concatenation order.\n- **Review**: Memory hierarchy section\n\n### Q10\n- **Category**: practical\n- **Question**: You work across two repositories and want Claude to load CLAUDE.md from both. What flag do you use?\n- **Options**: A) `claude --multi-repo /path/to/other` | B) `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 claude --add-dir /path/to/other` | C) `claude --add-dir /path/to/other` on its own | D) `claude --include /path/to/other`\n- **Correct**: B\n- **Explanation**: `--add-dir` on its own only grants file access to the extra directory — its CLAUDE.md is not loaded by default. Setting `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1` makes Claude Code also load CLAUDE.md from directories added with `--add-dir`.\n- **Review**: Additional directories section\n\n---\n\n## Lesson 03: Skills\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the 3 levels of progressive disclosure in the skill system?\n- **Options**: A) Metadata, instructions, resources | B) Name, body, attachments | C) Header, content, scripts | D) Summary, details, data\n- **Correct**: A\n- **Explanation**: Level 1: Metadata (~100 tokens, always loaded), Level 2: SKILL.md body (<5k tokens, loaded on trigger), Level 3: Bundled resources (scripts/references/assets, loaded on demand).\n- **Review**: How Skills Work: Progressive Disclosure\n\n### Q2\n- **Category**: practical\n- **Question**: What is the most important factor for a skill to be auto-invoked by Claude?\n- **Options**: A) The skill's file name | B) The `description` field in frontmatter with when-to-use keywords | C) The skill's directory location | D) The `auto-invoke: true` frontmatter field\n- **Correct**: B\n- **Explanation**: Claude decides whether to auto-invoke a skill based on its `description` (plus optional `when_to_use`). It must include specific trigger phrases and scenarios.\n- **Review**: Controlling Skill Invocation section\n\n### Q3\n- **Category**: conceptual\n- **Question**: What is the maximum recommended length for a SKILL.md file?\n- **Options**: A) 100 lines | B) 250 lines | C) 500 lines | D) 1000 lines\n- **Correct**: C\n- **Explanation**: SKILL.md should be kept under 500 lines. Larger reference material belongs in `references/` subdirectory files.\n- **Review**: Keep SKILL.md Under 500 Lines section\n\n### Q4\n- **Category**: practical\n- **Question**: How do you make a skill run in an isolated subagent with its own context?\n- **Options**: A) Set `isolation: true` in frontmatter | B) Set `context: fork` with an `agent` field in frontmatter | C) Set `subagent: true` in frontmatter | D) Put the skill in `.claude/agents/`\n- **Correct**: B\n- **Explanation**: `context: fork` runs the skill in a separate context, and the `agent` field specifies which agent type (e.g., `Explore`, `Plan`, custom agent) to use.\n- **Review**: Running skills in subagents section\n\n### Q5\n- **Category**: conceptual\n- **Question**: What is the approximate context budget allocated to skill metadata (Level 1)?\n- **Options**: A) 0.5% of context window | B) 1% of context window | C) 5% of context window | D) 10% of context window\n- **Correct**: B\n- **Explanation**: Skill metadata occupies about 1% of the context window (fallback: 8,000 characters). This is configurable with `SLASH_COMMAND_TOOL_CHAR_BUDGET` or the `skillListingBudgetFraction` setting.\n- **Review**: the \"Description budget\" paragraph under Automatic Discovery\n\n### Q6\n- **Category**: practical\n- **Question**: A skill needs to reference a large API specification. Where should you put it?\n- **Options**: A) Inline in SKILL.md | B) In a `references/api-spec.md` file inside the skill directory | C) In the project's CLAUDE.md | D) In a separate `.claude/rules/` file\n- **Correct**: B\n- **Explanation**: Large reference material belongs in the `references/` subdirectory. Claude loads Level 3 resources on demand, keeping SKILL.md lean.\n- **Review**: Supporting files structure section\n\n### Q7\n- **Category**: conceptual\n- **Question**: What is the difference between Reference Content and Task Content in a skill?\n- **Options**: A) Reference is read-only, Task is read-write | B) Reference adds knowledge to context, Task provides step-by-step instructions | C) Reference is for documentation, Task is for code | D) There is no difference\n- **Correct**: B\n- **Explanation**: Reference Content adds domain knowledge to Claude's context (e.g., brand guidelines). Task Content provides actionable step-by-step instructions for a workflow.\n- **Review**: Skill content types section\n\n### Q8\n- **Category**: practical\n- **Question**: What characters are allowed in the `name` field of a skill's frontmatter for a skill you plan to share via claude.ai or the Skills API (Agent Skills spec)?\n- **Options**: A) Any characters | B) Lowercase letters, numbers, and hyphens only (max 64 chars) | C) Letters and underscores | D) Alphanumeric only\n- **Correct**: B\n- **Explanation**: The name must be kebab-case (lowercase, hyphens), max 64 characters. `name` is itself optional — if omitted it defaults to the skill's directory name — but when supplied it must follow these rules. In Claude Code, the `anthropic-skills` name and namespace are reserved for skills synced from claude.ai, so a skill with that name doesn't load; the broader ban on \"anthropic\" or \"claude\" applies to claude.ai skill uploads and the Skills API. Claude Code itself (v2.1.299) refuses only names that contain hidden, direction-changing or blank-like characters, `<` or `>`, or that are over 256 characters.\n- **Review**: SKILL.md format section\n\n### Q9\n- **Category**: conceptual\n- **Question**: In what order does Claude search for skills?\n- **Options**: A) User > Project > Enterprise | B) Enterprise > Personal > Project (plugin uses namespace) | C) Project > User > Enterprise | D) Alphabetical order\n- **Correct**: B\n- **Explanation**: Priority order is: Enterprise > Personal > Project. Plugin skills use a namespace (plugin-name:skill) so they don't conflict.\n- **Review**: Skill Types & Locations\n\n### Q10\n- **Category**: practical\n- **Question**: How do you prevent Claude from automatically invoking a skill while still allowing users to use it manually?\n- **Options**: A) Set `user-invocable: false` | B) Set `disable-model-invocation: true` | C) Remove the description field | D) Set `auto-invoke: false`\n- **Correct**: B\n- **Explanation**: `disable-model-invocation: true` prevents Claude from auto-invoking but keeps the skill available in the user's `/` menu for manual use.\n- **Review**: Controlling Skill Invocation\n\n---\n\n## Lesson 04: Subagents\n\n### Q1\n- **Category**: conceptual\n- **Question**: What is the main advantage of subagents over inline conversation?\n- **Options**: A) They are faster | B) They operate in a separate, clean context window preventing context pollution | C) They can use more tools | D) They have better error handling\n- **Correct**: B\n- **Explanation**: Subagents get a fresh context window, receiving only what the main agent passes. This prevents the main conversation from being polluted with task-specific details.\n- **Review**: Overview section\n\n### Q2\n- **Category**: practical\n- **Question**: What is the priority order for agent definitions?\n- **Options**: A) Project > User > CLI | B) CLI > Project > User | C) User > Project > CLI | D) They all have equal priority\n- **Correct**: B\n- **Explanation**: Full order is managed settings > `--agents` flag > project (`.claude/agents/`) > user (`~/.claude/agents/`) > plugin. Of the options listed, CLI > Project > User is the correct relative ordering.\n- **Review**: File locations section\n\n### Q3\n- **Category**: conceptual\n- **Question**: Which built-in subagent is optimized for read-only codebase exploration?\n- **Options**: A) general-purpose | B) Plan | C) Explore | D) Bash\n- **Correct**: C\n- **Explanation**: The Explore subagent is the read-only codebase search agent. Since v2.1.198 it inherits the session model, capped at Opus on the Claude API — `model: haiku` is opt-in, not the default. It supports three thoroughness levels: quick, medium, very thorough.\n- **Review**: Built-in subagents section\n\n### Q4\n- **Category**: practical\n- **Question**: How do you restrict which subagents a coordinator agent can spawn?\n- **Options**: A) Use `allowed-agents:` field | B) Use `Agent(agent_name)` syntax in the `tools` field | C) Set `spawn-limit: 2` | D) Use `restrict-agents: [name1, name2]`\n- **Correct**: B\n- **Explanation**: For an agent running as the main thread with `claude --agent`, `tools: Agent(worker, researcher)` creates an allowlist — it can only spawn subagents named \"worker\" or \"researcher\". `Task(...)` still works as an alias (the Task tool was renamed Agent in v2.1.63).\n- **Review**: Restrict spawnable subagents section\n\n### Q5\n- **Category**: conceptual\n- **Question**: What does `isolation: worktree` do for a subagent?\n- **Options**: A) Runs the agent in a Docker container | B) Gives the agent its own git worktree so changes don't affect the main tree | C) Prevents the agent from reading any files | D) Runs the agent in a sandbox\n- **Correct**: B\n- **Explanation**: Worktree isolation creates a separate git worktree. If the agent makes no changes, it auto-cleans up. If changes are made, the worktree path and branch are returned.\n- **Review**: Worktree isolation section\n\n### Q6\n- **Category**: practical\n- **Question**: How do you force a subagent to always run in the background (never inline)?\n- **Options**: A) Set `background: true` in the agent config | B) Use `async: true` in the agent config | C) Press Ctrl+D after starting it | D) Use `--background` CLI flag\n- **Correct**: A\n- **Explanation**: `background: true` in the agent configuration makes the subagent always run as a background task and prevents it from running inline. Subagents Claude spawns from the main conversation already run in the background by default (v2.1.198; always, in the desktop app and VS Code, since v2.1.302), but a subagent's own nested Agent calls run in the foreground by default in `claude -p`, the Agent SDK, the desktop app and VS Code. Users can also press Ctrl+B to send a running foreground task to the background.\n- **Review**: Background subagents section\n\n### Q7\n- **Category**: conceptual\n- **Question**: What does the `memory` field with scope `project` do for a subagent?\n- **Options**: A) Gives read access to the project CLAUDE.md | B) Creates a persistent memory directory scoped to the current project | C) Shares the main agent's conversation history | D) Loads the project's git history\n- **Correct**: B\n- **Explanation**: The `memory` field creates a persistent directory for the subagent. Scope `project` means the memory is tied to the current project. The first 200 lines or 25KB of the agent's MEMORY.md, whichever comes first, auto-load.\n- **Review**: Persistent memory section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you include a phrase in a subagent's description to encourage Claude to automatically delegate tasks to it?\n- **Options**: A) Add \"priority: high\" | B) Include \"use PROACTIVELY\" or \"MUST BE USED\" in the description | C) Set `auto-delegate: true` | D) Add \"trigger: always\"\n- **Correct**: B\n- **Explanation**: Including phrases like \"use PROACTIVELY\" or \"MUST BE USED\" in the description strongly encourages Claude to automatically delegate matching tasks.\n- **Review**: Automatic delegation section\n\n### Q9\n- **Category**: conceptual\n- **Question**: What are the valid `permissionMode` values for a subagent?\n- **Options**: A) read, write, admin | B) manual, acceptEdits, bypassPermissions, plan, dontAsk, auto | C) safe, normal, dangerous | D) restricted, standard, elevated\n- **Correct**: B\n- **Explanation**: Subagents support six permission modes: manual (runs reads without asking and prompts for everything else — shown as Manual; its config value is `default`, and manual is accepted as an alias since v2.1.200), acceptEdits (auto-accepts file edits), bypassPermissions (skips all), plan (read-only), dontAsk (auto-denies unless pre-approved), auto (background classifier decides).\n- **Review**: Configuration fields section\n\n### Q10\n- **Category**: practical\n- **Question**: How do you resume a subagent that returned an agentId from a previous run?\n- **Options**: A) Use `/resume agent-id` | B) Ask Claude to resume it — Claude messages the subagent with the SendMessage tool, using its agent ID or name | C) Use `claude -r agent-id` | D) Subagents cannot be resumed\n- **Correct**: B\n- **Explanation**: Each invocation starts a new instance. To continue earlier work, ask Claude to resume the subagent: Claude uses the SendMessage tool with the agent's ID or name, and the subagent resumes with its full conversation history. The built-in Explore and Plan agents are one-shot and can't be resumed.\n- **Review**: Resumable agents section\n\n---\n\n## Lesson 05: MCP\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the four MCP transport protocols, and which is recommended?\n- **Options**: A) HTTP (recommended), Stdio, SSE (deprecated), WebSocket (`ws`) | B) REST (recommended), GraphQL, gRPC, Thrift | C) TCP, UDP, HTTP | D) Stdio (recommended), HTTP, SSE\n- **Correct**: A\n- **Explanation**: HTTP is recommended for remote servers. Stdio is for local processes (most common currently). SSE is deprecated but still supported. WebSocket (`type: \"ws\"`) holds a persistent bidirectional connection for servers that push events unprompted; it is added with `claude mcp add-json` or `.mcp.json`, not with `--transport`, and supports header-only auth.\n- **Review**: MCP Installation Methods section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you add a GitHub MCP server via CLI?\n- **Options**: A) `claude mcp install github` | B) `claude mcp add --transport http github https://api.githubcopilot.com/mcp/` | C) `claude plugin add github-mcp` | D) `claude connect github`\n- **Correct**: B\n- **Explanation**: Use `claude mcp add` with the `--transport` flag, a name, and the server URL. GitHub's remote server also needs an auth header: `claude mcp add --transport http github https://api.githubcopilot.com/mcp/ --header \"Authorization: Bearer YOUR_GITHUB_PAT\"`.\n- **Review**: MCP configuration management section\n\n### Q3\n- **Category**: conceptual\n- **Question**: With `ENABLE_TOOL_SEARCH=auto`, what happens when MCP tool definitions reach 10% of the context window?\n- **Options**: A) They are truncated | B) Tool search kicks in: MCP tools are deferred and discovered on demand | C) Claude shows an error | D) Extra tools are disabled\n- **Correct**: B\n- **Explanation**: By default (`ENABLE_TOOL_SEARCH` unset) tool search is already on and all MCP tools are deferred. `auto` is threshold mode: tools load upfront until their definitions reach 10% of the context window, then all are deferred (`auto:N` sets a custom percentage). Tool search needs a model that supports `tool_reference` blocks: Opus 4, Sonnet 4, Haiku 4.5 and later.\n- **Review**: MCP Tool Search section\n\n### Q4\n- **Category**: practical\n- **Question**: How do you use environment variable fallbacks in MCP config?\n- **Options**: A) `${VAR || \"default\"}` | B) `${VAR:-default}` | C) `${VAR:default}` | D) `${VAR ? \"default\"}`\n- **Correct**: B\n- **Explanation**: `${VAR:-default}` provides a fallback value if the environment variable is not set. If `VAR` is unset and has no default, the server still loads with the literal `${VAR}` text, and `claude mcp list` and `/mcp` warn about the missing variable.\n- **Review**: Environment variable expansion section\n\n### Q5\n- **Category**: conceptual\n- **Question**: What is the difference between MCP and Memory for data access?\n- **Options**: A) MCP is faster, Memory is slower | B) MCP is for live/changing external data, Memory is for persistent/static preferences | C) MCP is for code, Memory is for text | D) They are interchangeable\n- **Correct**: B\n- **Explanation**: MCP connects to live, changing external data sources (APIs, databases). Memory stores persistent, static project context and preferences.\n- **Review**: MCP vs Memory section\n\n### Q6\n- **Category**: practical\n- **Question**: What happens when a team member first encounters a project-scoped `.mcp.json`?\n- **Options**: A) It loads automatically | B) They get an approval prompt to trust the project's MCP servers | C) It's ignored unless they opt in via settings | D) Claude asks the admin to approve\n- **Correct**: B\n- **Explanation**: Project-scoped `.mcp.json` triggers a security approval prompt on each team member's first use. This is intentional — it prevents untrusted MCP servers.\n- **Review**: MCP Scopes section\n\n### Q7\n- **Category**: conceptual\n- **Question**: What does `claude mcp serve` do?\n- **Options**: A) Starts an MCP server dashboard | B) Makes Claude Code itself act as an MCP server for other applications | C) Serves MCP documentation | D) Tests MCP server connections\n- **Correct**: B\n- **Explanation**: `claude mcp serve` turns Claude Code into an MCP server, enabling multi-agent orchestration where one Claude instance can be controlled by another.\n- **Review**: Claude as MCP Server section\n\n### Q8\n- **Category**: practical\n- **Question**: What is the default maximum output size for MCP tools?\n- **Options**: A) 5,000 tokens | B) 10,000 tokens | C) 25,000 tokens | D) 50,000 tokens\n- **Correct**: C\n- **Explanation**: Default max is 25,000 tokens (`MAX_MCP_OUTPUT_TOKENS`). A warning appears at 10k tokens. Text results over 50,000 characters are saved to a file.\n- **Review**: MCP Output Limits section\n\n### Q9\n- **Category**: conceptual\n- **Question**: When both `allowedMcpServers` and `deniedMcpServers` match a server in managed config, which wins?\n- **Options**: A) Allowed wins | B) Denied wins | C) The last one configured wins | D) Both are applied independently\n- **Correct**: B\n- **Explanation**: In managed MCP configuration, deny rules always take precedence over allow rules.\n- **Review**: Managed MCP Configuration section\n\n### Q10\n- **Category**: practical\n- **Question**: How do you reference an MCP resource in a conversation?\n- **Options**: A) Use `/mcp resource-name` | B) Use `@server-name:protocol://resource/path` mention syntax | C) Use `mcp.get(\"resource\")` | D) Resources are auto-loaded\n- **Correct**: B\n- **Explanation**: MCP resources are accessed via `@server-name:protocol://resource/path` mention syntax in conversation.\n- **Review**: MCP Resources section\n\n---\n\n## Lesson 06: Hooks\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the five types of hooks in Claude Code?\n- **Options**: A) Pre, Post, Error, Filter, and Transform hooks | B) Command, HTTP, MCP Tool, Prompt, and Agent hooks | C) Before, After, Around, Through, and Beside hooks | D) Input, Output, Filter, Transform, and Validate hooks\n- **Correct**: B\n- **Explanation**: Command hooks run shell scripts, HTTP hooks call webhook endpoints, MCP Tool hooks invoke an MCP tool, Prompt hooks use single-turn LLM evaluation, and Agent hooks use subagent-based verification. Agent hooks are experimental and may change.\n- **Review**: Hook types section\n\n### Q2\n- **Category**: practical\n- **Question**: A hook script exits with code 2. What happens?\n- **Options**: A) Non-blocking warning shown | B) Blocking error — stderr is shown as an error to Claude, tool use is prevented | C) Hook is retried | D) Session ends\n- **Correct**: B\n- **Explanation**: Exit code 0 = success/continue, exit code 2 = blocking error (stderr shown as error), any other non-zero = non-blocking error (a `<hook name> hook error` notice with the first line of stderr appears in the transcript, and the action goes ahead). Since v2.1.295, setting `\"onFailure\": \"block\"` on a command or HTTP hook makes such failures block like exit 2.\n- **Review**: Exit codes section\n\n### Q3\n- **Category**: conceptual\n- **Question**: What JSON fields does a PreToolUse hook receive on stdin?\n- **Options**: A) `tool_name` and `tool_output` | B) `session_id`, `tool_name`, `tool_input`, `hook_event_name`, `cwd`, and more | C) Only `tool_name` | D) The full conversation history\n- **Correct**: B\n- **Explanation**: Hooks receive a JSON object on stdin with: session_id, transcript_path, hook_event_name, tool_name, tool_input, tool_use_id, cwd, and permission_mode.\n- **Review**: JSON Input (via stdin)\n\n### Q4\n- **Category**: practical\n- **Question**: How can a PreToolUse hook modify the tool's input parameters before execution?\n- **Options**: A) Return modified JSON on stderr | B) Return JSON with `updatedInput` field on stdout (exit code 0) | C) Write to a temp file | D) Hooks cannot modify inputs\n- **Correct**: B\n- **Explanation**: A PreToolUse hook can output JSON with `\"updatedInput\": {...}` on stdout (with exit 0) to modify the tool's parameters before Claude uses them. `updatedInput` goes under `hookSpecificOutput` and replaces the whole input object; since v2.1.300 it is validated like Claude's own input, so unknown keys are dropped and input the tool rejects denies the call.\n- **Review**: PreToolUse section\n\n### Q5\n- **Category**: conceptual\n- **Question**: Which hook event supports `CLAUDE_ENV_FILE` for persisting environment variables into the session?\n- **Options**: A) PreToolUse | B) UserPromptSubmit | C) SessionStart | D) All events\n- **Correct**: C\n- **Explanation**: `CLAUDE_ENV_FILE` is available to SessionStart, Setup, CwdChanged, and FileChanged hooks, which use it to persist environment variables into the session. Of the options listed, SessionStart is the one that supports it — PreToolUse and UserPromptSubmit do not, and it is not available to all events.\n- **Review**: SessionStart section\n\n### Q6\n- **Category**: practical\n- **Question**: You want a hook that only runs once when a skill is first loaded, not on every tool call. What field do you add?\n- **Options**: A) `run-once: true` | B) `once: true` on a hook in the skill's frontmatter | C) `single: true` | D) `max-runs: 1`\n- **Correct**: B\n- **Explanation**: Hooks declared in a skill's frontmatter support `once: true` — Claude Code removes the hook after its first successful run (a run that fails, blocks, or times out leaves it in place). `once` is honored only in skill frontmatter.\n- **Review**: Component-scoped hooks section\n\n### Q7\n- **Category**: conceptual\n- **Question**: A Stop hook is defined in a subagent's frontmatter. What does it automatically convert to?\n- **Options**: A) A PostToolUse hook | B) A SubagentStop hook | C) A SessionEnd hook | D) It stays as a Stop hook\n- **Correct**: B\n- **Explanation**: When a Stop hook is placed in a subagent's frontmatter, it auto-converts to SubagentStop so it runs when that specific subagent finishes.\n- **Review**: Component-scoped hooks section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you match a hook to all MCP tools from a specific server?\n- **Options**: A) `matcher: \"mcp_github\"` | B) `matcher: \"mcp__github__.*\"` (regex pattern) | C) `matcher: \"mcp:github:*\"` | D) `matcher: \"github-mcp\"`\n- **Correct**: B\n- **Explanation**: Use regex patterns for matchers. MCP tools follow the `mcp__server__tool` naming convention, so `mcp__github__.*` matches all GitHub MCP tools.\n- **Review**: Matcher patterns section\n\n### Q9\n- **Category**: conceptual\n- **Question**: How many hook events does Claude Code support in total?\n- **Options**: A) 16 | B) 25 | C) 33 | D) 40\n- **Correct**: C\n- **Explanation**: Claude Code supports 33 hook events. They fall into four groups: session lifecycle (`SessionStart`, `Setup`, `SessionEnd`), prompt and message handling (`UserPromptSubmit`, `UserPromptExpansion`, `MessageDisplay`), tool use and permissions (`PreToolUse`, `PostToolUse`, `PermissionRequest`, …), and agent, task, and environment coordination (`SubagentStart`, `TaskCreated`, `CwdChanged`, `WorktreeCreate`, `PreModelSwitch`, `PostModelSwitch`, …).\n- **Review**: Hook events table\n\n### Q10\n- **Category**: practical\n- **Question**: You want to debug why a hook isn't firing. What's the best approach?\n- **Options**: A) Add print statements to the hook script | B) Use the `--debug` flag and `Ctrl+O` to open the transcript viewer | C) Check the system log | D) Hooks don't have debugging tools\n- **Correct**: B\n- **Explanation**: `claude --debug` (or `--debug-file <path>`, or `/debug` mid-session) logs hook runs to the debug log, including which hooks fire, their inputs, and outputs; `Ctrl+O` opens the transcript view to see hook outcomes.\n- **Review**: Debugging section\n\n---\n\n## Lesson 07: Plugins\n\n### Q1\n- **Category**: conceptual\n- **Question**: What is the core manifest file for a plugin and where does it live?\n- **Options**: A) `plugin.yaml` in the root directory | B) `.claude-plugin/plugin.json` | C) `package.json` with a \"claude\" key | D) `.claude/plugin.md`\n- **Correct**: B\n- **Explanation**: The plugin manifest lives at `.claude-plugin/plugin.json`. The manifest is optional; when present, `name` (kebab-case identifier) is its only required key; `description`, `version`, `author`, `homepage`, `repository` and `license` are optional metadata.\n- **Review**: Plugin definition structure section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you load a plugin from a local directory so you can try it in a session before publishing?\n- **Options**: A) Use `/plugin test ./my-plugin` | B) Use `claude --plugin-dir ./my-plugin` | C) Use `claude plugin validate ./my-plugin` | D) Copy it to ~/.claude/plugins/\n- **Correct**: B\n- **Explanation**: The `--plugin-dir` flag loads a plugin from a local directory for testing. It's repeatable for loading multiple plugins. `claude plugin validate ./my-plugin` checks the manifest and components but doesn't load the plugin into a session.\n- **Review**: Testing section\n\n### Q3\n- **Category**: conceptual\n- **Question**: What environment variable is available inside plugin hooks and MCP configs to reference the plugin's installation directory?\n- **Options**: A) `$PLUGIN_HOME` | B) `${CLAUDE_PLUGIN_ROOT}` | C) `$PLUGIN_DIR` | D) `${CLAUDE_PLUGIN_PATH}`\n- **Correct**: B\n- **Explanation**: `${CLAUDE_PLUGIN_ROOT}` resolves to the plugin's installed directory, enabling portable path references in hooks and MCP configs.\n- **Review**: Plugin-Provided MCP Servers section in Lesson 05 (MCP)\n\n### Q4\n- **Category**: practical\n- **Question**: A plugin has a command called \"check-security\" in the \"pr-review\" plugin. How does a user invoke it?\n- **Options**: A) `/check-security` | B) `/pr-review:check-security` | C) `/plugin pr-review check-security` | D) `/pr-review/check-security`\n- **Correct**: B\n- **Explanation**: Plugin commands use a `plugin-name:command-name` namespace to avoid conflicts with user commands and other plugins.\n- **Review**: Plugin Commands section in Lesson 01 (Slash Commands)\n\n### Q5\n- **Category**: conceptual\n- **Question**: Which components can a plugin bundle?\n- **Options**: A) Only commands and settings | B) Skills, agents, commands, hooks, MCP servers, LSP config, settings, templates, scripts | C) Only commands, hooks, and MCP servers | D) Only skills and agents\n- **Correct**: B\n- **Explanation**: Plugins can bundle: skills/, agents/, commands/, hooks/hooks.json, .mcp.json, .lsp.json, settings.json, templates/, scripts/, docs/, tests/. Note that `commands/` is legacy — official guidance is to use `skills/` for new plugins, though existing `commands/` directories keep working.\n- **Review**: Plugin Structure Example section\n\n### Q6\n- **Category**: practical\n- **Question**: How do you install a plugin from GitHub?\n- **Options**: A) `claude plugin add github:username/repo` | B) `/plugin marketplace add username/repo`, then `/plugin install plugin-name@marketplace-name` | C) `npm install @claude/username-repo` | D) `git clone` then `claude plugin register`\n- **Correct**: B\n- **Explanation**: Add the GitHub repo as a marketplace with `/plugin marketplace add username/repo`, then install with `/plugin install plugin-name@marketplace-name`. You can also do both in one step: `/plugin install plugin-name --marketplace username/repo` inside a session (v2.1.275+), or `claude plugin install plugin-name --marketplace username/repo` from your shell (v2.1.292+). There is no `github:` install form.\n- **Review**: Installation methods section\n\n### Q7\n- **Category**: conceptual\n- **Question**: What does the `settings.json` `agent` key do in a plugin?\n- **Options**: A) Specifies authentication credentials | B) Sets the main thread agent for the plugin | C) Lists available subagents | D) Configures agent permissions\n- **Correct**: B\n- **Explanation**: The `agent` key in a plugin's settings.json specifies which agent definition to use as the main thread agent when the plugin is active.\n- **Review**: Plugin Settings section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you manage plugin lifecycle (enable/disable/update)?\n- **Options**: A) Edit a config file manually | B) Use `/plugin enable`, `/plugin disable`, `claude plugin update <name>` | C) Use `claude plugin-manager` | D) Reinstall the plugin\n- **Correct**: B\n- **Explanation**: `/plugin enable` and `/plugin disable` are real slash commands. For updating an installed plugin, `claude plugin update <name>` is the form documented in the plugins reference, and the one Claude Code points you to when an update is available.\n- **Review**: Plugin CLI Commands section\n\n### Q9\n- **Category**: conceptual\n- **Question**: What is the main advantage of a plugin over standalone skills/hooks/MCP?\n- **Options**: A) Plugins are faster | B) Single-command install, versioned, marketplace distribution, bundles everything together | C) Plugins have more permissions | D) Plugins work offline\n- **Correct**: B\n- **Explanation**: Plugins package multiple components into one installable unit with versioning, marketplace distribution, and automatic updates — vs. manual setup of standalone components.\n- **Review**: Standalone vs Plugin Approach\n\n### Q10\n- **Category**: practical\n- **Question**: Where do plugin hooks configuration live within the plugin directory?\n- **Options**: A) `.claude-plugin/hooks.json` | B) `hooks/hooks.json` | C) `plugin.json` hooks section | D) `.claude/settings.json`\n- **Correct**: B\n- **Explanation**: Plugin hooks are configured in `hooks/hooks.json` within the plugin directory structure.\n- **Review**: Plugin Structure Example\n\n---\n\n## Lesson 08: Checkpoints\n\n### Q1\n- **Category**: conceptual\n- **Question**: What four things do checkpoints capture?\n- **Options**: A) Git commits, branches, tags, stashes | B) Messages, file modifications, tool usage history, session context | C) Code, tests, logs, configs | D) Inputs, outputs, errors, timing\n- **Correct**: B\n- **Explanation**: Checkpoints capture conversation messages, file modifications made by Claude's tools, tool usage history, and session context.\n- **Review**: Overview section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you access the checkpoint browser?\n- **Options**: A) Use `/restore` command | B) Press `Esc + Esc` (double-escape) or use `/rewind` | C) Use `/history` command | D) Press `Ctrl+Z`\n- **Correct**: B\n- **Explanation**: Double-escape (Esc+Esc) or the `/rewind` command opens the checkpoint browser to select a restore point.\n- **Review**: Accessing checkpoints section\n\n### Q3\n- **Category**: conceptual\n- **Question**: How many rewind options are available, and what are they?\n- **Options**: A) 3: Undo, Redo, Reset | B) 6: Restore code+conversation, Restore conversation, Restore code, Summarize from here, Summarize up to here, Never mind | C) 2: Full restore, Partial restore | D) 4: Code, Messages, Both, Cancel\n- **Correct**: B\n- **Explanation**: The 6 options are: Restore code and conversation (full rollback), Restore conversation only, Restore code only, Summarize from here (compress forward), Summarize up to here (compress backward), Never mind (cancel). The two summary options give bidirectional context compaction.\n- **Review**: Rewind options section\n\n### Q4\n- **Category**: practical\n- **Question**: You used `rm -rf temp/` via Bash in Claude Code, then want to rewind. Will the checkpoint restore those files?\n- **Options**: A) Yes, checkpoints capture everything | B) No, Bash filesystem operations (rm, mv, cp) are not tracked by checkpoints | C) Only if you used the Edit tool instead | D) Only if autoCheckpoint was enabled\n- **Correct**: B\n- **Explanation**: Checkpoints track file changes made by Claude's own Write/Edit tools in the main thread. Bash commands (rm, mv, cp), subagent edits (except a foreground `context: fork` skill), edits made outside Claude Code, and symlinked/hardlinked paths are all outside checkpoint tracking.\n- **Review**: Limitations section\n\n### Q5\n- **Category**: conceptual\n- **Question**: How long are checkpoints retained?\n- **Options**: A) Until session ends | B) 7 days | C) 30 days | D) Indefinitely\n- **Correct**: C\n- **Explanation**: Checkpoints are saved with the session, so `/rewind` works after you resume it; snapshots are deleted about 30 days after the session last saved one (`cleanupPeriodDays`); only the 100 most recent checkpoints keep file snapshots. The window is governed by `cleanupPeriodDays`.\n- **Review**: Checkpoint Retention section\n\n### Q6\n- **Category**: practical\n- **Question**: What does \"Summarize from here\" do when rewinding?\n- **Options**: A) Deletes the conversation from that point | B) Compresses the conversation into an AI-generated summary while preserving the original in the transcript | C) Creates a bullet-point list of changes | D) Exports the conversation to a file\n- **Correct**: B\n- **Explanation**: Summarize compresses the conversation into a shorter AI-generated summary. The original full text is preserved in the transcript file.\n- **Review**: Rewind Options section\n\n### Q7\n- **Category**: conceptual\n- **Question**: When are checkpoints created automatically?\n- **Options**: A) Every 5 minutes | B) On every user prompt | C) Only when you manually save | D) After every tool use\n- **Correct**: B\n- **Explanation**: Automatic checkpoints are created with every user prompt, capturing the state before Claude processes the request.\n- **Review**: Automatic checkpoints section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you disable automatic checkpoint creation?\n- **Options**: A) Use `--no-checkpoints` flag | B) Set `fileCheckpointingEnabled: false` in settings | C) Delete the checkpoints directory | D) Checkpoints cannot be disabled\n- **Correct**: B\n- **Explanation**: Set `fileCheckpointingEnabled: false` in your configuration to disable automatic checkpoint creation (default is true; requires v2.1.119+). Env equivalent: `CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING`.\n- **Review**: Configuration section\n\n### Q9\n- **Category**: conceptual\n- **Question**: Are checkpoints a replacement for git commits?\n- **Options**: A) Yes, they're more powerful | B) No, they are complementary — checkpoints are session-scoped and expire, git is permanent and shareable | C) Yes, for small projects | D) Only in solo development\n- **Correct**: B\n- **Explanation**: Checkpoints are temporary (30-day retention), session-scoped, and cannot be shared. Git commits are permanent, auditable, and shareable. Use both together.\n- **Review**: Integration with git section\n\n### Q10\n- **Category**: practical\n- **Question**: You want to compare two different approaches. What's the recommended checkpoint workflow?\n- **Options**: A) Create two separate sessions | B) Checkpoint before approach A, try it, rewind to checkpoint, try approach B, compare results | C) Use git branches instead | D) There's no good way to compare approaches\n- **Correct**: B\n- **Explanation**: The branching strategy: checkpoint at clean state, try approach A, note results, rewind to the same checkpoint, try approach B. Compare both outcomes.\n- **Review**: Workflow patterns section\n\n---\n\n## Lesson 09: Advanced Features\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the six permission modes in Claude Code?\n- **Options**: A) read, write, execute, admin, root, sudo | B) manual, acceptEdits, plan, auto, dontAsk, bypassPermissions | C) safe, normal, elevated, admin, unrestricted, god | D) view, edit, run, deploy, full, bypass\n- **Correct**: B\n- **Explanation**: The six modes are: manual (runs reads without asking and prompts for everything else — shown as Manual; its config value is `default`, and manual is accepted as an alias since v2.1.200), acceptEdits (auto-accepts file edits), plan (read-only analysis), auto (background classifier decides), dontAsk (auto-denies unless pre-approved), bypassPermissions (skips all checks).\n- **Review**: Permission Modes section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you activate planning mode?\n- **Options**: A) Only via `/plan` command | B) Via `/plan`, `Shift+Tab`/`Alt+M`, `--permission-mode plan` flag, or default config | C) Via `--planning` flag only | D) Planning is always on\n- **Correct**: B\n- **Explanation**: Planning mode can be activated multiple ways: /plan command, Shift+Tab/Alt+M keyboard shortcut, --permission-mode plan CLI flag, or as a default in config.\n- **Review**: Planning Mode section\n\n### Q3\n- **Category**: conceptual\n- **Question**: What does the `opusplan` model alias do?\n- **Options**: A) Uses only Opus for everything | B) Uses Opus for planning phase and Sonnet for implementation | C) Uses a special planning-optimized model | D) Enables plan mode automatically\n- **Correct**: B\n- **Explanation**: `opusplan` is a model alias that uses Opus for the planning phase (higher quality analysis) and Sonnet for the execution phase (faster implementation).\n- **Review**: Planning Mode section\n\n### Q4\n- **Category**: practical\n- **Question**: On a model where thinking can be turned off (for example Sonnet 5), how do you toggle extended thinking on or off during a session?\n- **Options**: A) Type `/effort max` | B) Press `Option+T` (macOS) or `Alt+T` | C) Include \"ultrathink\" in prompt | D) It's always enabled and cannot be toggled\n- **Correct**: B\n- **Explanation**: Option+T (macOS) or Alt+T toggles extended thinking on/off for the session. (`Ctrl+O` toggles verbose mode to show/hide the reasoning text.) On Opus 5.5 (the default model since v2.1.280), Sonnet 5.5 (what the `sonnet` alias resolves to on the Anthropic API since v2.1.284), Haiku 5.5 (what the `haiku` alias resolves to on the Anthropic API since v2.1.293), and the Fable models, thinking can't be turned off: the toggle, `alwaysThinkingEnabled` and `MAX_THINKING_TOKENS=0` have no effect there. For one-off deep reasoning, include \"ultrathink\" in your prompt; for session-level control, use the `/effort` command.\n- **Review**: Extended Thinking section\n\n### Q5\n- **Category**: conceptual\n- **Question**: Does the \"ultrathink\" keyword trigger deep reasoning?\n- **Options**: A) Yes, it triggers deep reasoning for one response without changing session settings | B) No, it's treated as regular prompt text | C) Yes, but only on Opus 4.6 | D) Yes, and it permanently changes the effort level\n- **Correct**: A\n- **Explanation**: Including \"ultrathink\" in your prompt adds an in-context instruction for the model to reason more on that turn. It does not change the effort level sent to the API—use `/effort max` for session-level deep reasoning.\n- **Review**: Extended Thinking section\n\n### Q6\n- **Category**: practical\n- **Question**: How do you run Claude in a CI/CD pipeline with structured JSON output and a turn limit?\n- **Options**: A) `claude --ci --json --limit 3` | B) `claude -p --output-format json --max-t\n\n<!-- [TRUNCATED AT 50KB] -->",".claude/skills/lesson-quiz/references/results-template.md":"# Results Report Template\n\nThe output format for Step 5 (\"Score and Present Results\"). Fill the bracketed placeholders; keep the headings and table columns as shown.\n\n```markdown\n## Lesson Quiz Results: [Lesson Name]\n\n**Score: N/10** — [Grade label]\n**Quiz timing**: [Before / During / After] the lesson\n**Question breakdown**: N conceptual correct, N practical correct\n\n### Per-Question Results\n\n| # | Category | Question (short) | Your Answer | Result |\n|---|----------|-----------------|-------------|--------|\n| 1 | Conceptual | [abbreviated question] | [their answer] | [Correct / Incorrect] |\n| 2 | Practical | ... | ... | ... |\n| ... | ... | ... | ... | ... |\n\n### Incorrect Answers — Review These\n\n[For each incorrect answer, show:]\n\n**Q[N]: [Full question text]**\n- Your answer: [what they chose]\n- Correct answer: [correct option]\n- Explanation: [why it's correct]\n- Review: [specific section of the lesson README to re-read]\n\n### [Timing-specific message]\n\n[If pre-test]:\n**Pre-test score: N/10.** This gives you a baseline! Focus your study on the topics you missed. After completing the lesson, retake the quiz to measure your improvement.\n\n[If during]:\n**Progress check: N/10.** [If 7 or above: Great progress — keep going! If 5-6: Review the incorrect topics before continuing. If 0-4: Consider re-reading from the beginning.]\n\n[If after]:\n**Mastery check: N/10.** [If 9-10: You've mastered this lesson! Move on to the next. If 7-8: Almost there — review the missed topics and retake. If <7: Spend more time with the lesson, especially the sections marked above.]\n\n### Recommended Next Steps\n\n[Based on score and timing:]\n- [If mastered]: Proceed to the next lesson in the roadmap: [next lesson link]\n- [If proficient]: Review these specific sections, then retake: [list sections]\n- [If developing or below]: Re-read the full lesson: [lesson link]. Focus on: [list weak categories]\n- [Offer]: \"Would you like to retake this quiz, try a different lesson, or get help with a specific topic?\"\n```\n\n---\n\n**Last Updated**: September 2, 2026\n**Claude Code Version**: 2.1.257\n**Sources**:\n- https://code.claude.com/docs/en/overview\n",".claude/skills/self-assessment/README.md":"# Self-Assessment & Learning Path Advisor\n\n> Comprehensive Claude Code proficiency assessment that evaluates 10 feature areas, identifies skill gaps, and generates a personalized learning path to level up.\n\n## Highlights\n\n- Two assessment modes: Quick (8 questions, 2 min) and Deep (5 rounds, 5 min)\n- Evaluates 10 feature areas: Slash Commands, Memory, Skills, Hooks, MCP, Subagents, Checkpoints, Advanced Features, Plugins, CLI\n- Per-topic scoring with mastery levels (None / Basic / Proficient)\n- Gap analysis with dependency-aware prioritization\n- Personalized learning path with specific exercises and success criteria\n- Follow-up actions: start learning, deep dive, practice project, or retake\n\n## When to Use\n\n| Say this... | Skill will... |\n|---|---|\n| \"assess my level\" | Run the assessment quiz and determine your level |\n| \"where should I start\" | Evaluate your experience and suggest a starting point |\n| \"check my skills\" | Produce a detailed skill profile across all 10 areas |\n| \"what should I learn next\" | Identify gaps and build a prioritized learning path |\n\n## How It Works\n\n```mermaid\ngraph TD\n    A[\"Choose assessment mode\"] --> B[\"Answer quiz questions\"]\n    B --> C[\"Score per-topic proficiency\"]\n    C --> D[\"Generate personalized learning path\"]\n    D --> E[\"Start learning or deep dive\"]\n    style A fill:#4CAF50,color:#fff\n    style E fill:#2196F3,color:#fff\n```\n\n## Assessment Modes\n\n### Quick Assessment (~2 min)\n- 8 yes/no experience questions across 2 rounds\n- Determines overall level: Beginner / Intermediate / Advanced\n- Lists specific gaps with tutorial links\n- Best for: first-time users, quick check-ins\n\n### Deep Assessment (~5 min)\n- 5 rounds of questions covering 10 feature areas (2 topics per round)\n- Per-topic scoring (0-2 points each, 20 points maximum — Checkpoints contributes 0-1, Advanced Features 0-3)\n- Mastery table with strength areas, priority gaps, and review items\n- Dependency-aware learning path with phases and time estimates\n- Recommended practice projects combining gap topics\n- Best for: experienced users wanting to level up, periodic skill reviews\n\n## Usage\n\n```text\n/self-assessment\n```\n\n## Output\n\n### Skill Profile Table\nShows per-topic score, mastery level, and status (Learn / Review / Mastered).\n\n### Personalized Learning Path\n- Organized into phases based on dependency order\n- Each topic includes: tutorial link, focus areas, key exercise, success criterion\n- Time estimate adjusted for topics already mastered\n- Practice projects combining multiple gap areas\n\n### Follow-up Actions\nAfter results, choose to:\n- Start the first gap tutorial with guided exercises\n- Deep dive into a specific gap area\n- Set up a practice project covering your gaps\n- Retake in a different assessment mode\n",".claude/skills/self-assessment/SKILL.md":"---\nname: self-assessment\nversion: 2.5.5\ndescription: Comprehensive Claude Code self-assessment and learning path advisor. Runs a multi-category quiz covering 10 feature areas, produces a detailed skill profile with per-topic scores, identifies specific gaps, and generates a personalized learning path with prioritized next steps. Use when asked to \"assess my level\", \"take the quiz\", \"find my level\", \"where should I start\", \"what should I learn next\", \"check my skills\", \"skill check\", or \"level up\".\n---\n\n# Self-Assessment & Learning Path Advisor\n\nComprehensive interactive assessment that evaluates Claude Code proficiency across 10 feature areas, identifies specific skill gaps, and generates a personalized learning path to level up.\n\n## Instructions\n\n### Step 1: Welcome & Choose Assessment Mode\n\nPresent the user with a choice of assessment depth:\n\nUse AskUserQuestion with these options:\n- **Quick Assessment** — \"2 multi-select questions (8 items), ~2 minutes. Determines your overall level (Beginner/Intermediate/Advanced) and gives a learning path.\"\n- **Deep Assessment** — \"5 categories with detailed questions, ~5 minutes. Gives per-topic skill scores, identifies specific gaps, and builds a prioritized learning path.\"\n\nIf user chooses **Quick Assessment**, go to Step 2A.\nIf user chooses **Deep Assessment**, go to Step 2B.\n\n---\n\n### Step 2A: Quick Assessment\n\nPresent TWO multi-select questions (AskUserQuestion supports max 4 options each):\n\n**Question 1** (header: \"Basics\"):\n\"Part 1/2: Which of these Claude Code skills do you already have?\"\nOptions:\n1. \"Start Claude Code and chat\" — I can run `claude` and interact with it\n2. \"Created/edited CLAUDE.md\" — I have set up project or user memory\n3. \"Used 3+ slash commands\" — e.g., /help, /compact, /model, /clear\n4. \"Created custom command/skill\" — Written a SKILL.md or custom command file\n\n**Question 2** (header: \"Advanced\"):\n\"Part 2/2: Which of these advanced skills do you have?\"\nOptions:\n1. \"Configured an MCP server\" — e.g., GitHub, database, or other external data source\n2. \"Set up hooks\" — Configured hooks in a settings file (e.g. ~/.claude/settings.json or .claude/settings.json)\n3. \"Created/used subagents\" — Used .claude/agents/ for task delegation\n4. \"Used print mode (claude -p)\" — Used `claude -p` for non-interactive or CI/CD use\n\n**Scoring:**\n- 0-2 total = Level 1: Beginner\n- 3-5 total = Level 2: Intermediate\n- 6-8 total = Level 3: Advanced\n\nGo to Step 3 with the level result, listing which specific items were NOT checked as gaps.\n\n---\n\n### Step 2B: Deep Assessment\n\nPresent 5 rounds of questions, one AskUserQuestion call per round. Each round covers 2 related feature areas. Use multi-select for all rounds.\n\n**IMPORTANT**: AskUserQuestion supports max 4 options per question. Each round has exactly 1 question with 4 options covering 2 topics (2 options per topic).\n\n---\n\n**Round 1 — Slash Commands & Memory** (header: \"Commands\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Created a custom slash command or skill\" — Written a SKILL.md file with frontmatter, or created .claude/commands/ files\n2. \"Used dynamic context in commands\" — Used `$ARGUMENTS`, `$0`/`$1`, backtick `!command` syntax, or `@file` references in skill/command files\n3. \"Set up project + personal memory\" — Created both a project CLAUDE.md and personal ~/.claude/CLAUDE.md (or CLAUDE.local.md)\n4. \"Used memory hierarchy features\" — Understand how the 7 memory locations are concatenated into context (loaded root-down, CLAUDE.local.md appended after CLAUDE.md at each level, subdirectory files loaded on demand), used .claude/rules/ directory, path-specific rules, or @import syntax\n\n**Scoring for Round 1:**\n- Options 1-2 map to **Slash Commands** (0-2 points)\n- Options 3-4 map to **Memory** (0-2 points)\n\n---\n\n**Round 2 — Skills & Hooks** (header: \"Automation\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Installed and used an auto-invoked skill\" — A skill that triggers automatically based on its description, without manual /command invocation\n2. \"Controlled skill invocation behavior\" — Used `disable-model-invocation`, `user-invocable`, or `context: fork` with agent field in SKILL.md frontmatter\n3. \"Set up a PreToolUse or PostToolUse hook\" — Configured a hook that runs before/after tool execution (e.g., command validator, auto-formatter)\n4. \"Used advanced hook features\" — Configured prompt-type hooks, skill-frontmatter hooks, HTTP hooks, or hooks with custom JSON output (updatedInput, systemMessage)\n\n**Scoring for Round 2:**\n- Options 1-2 map to **Skills** (0-2 points)\n- Options 3-4 map to **Hooks** (0-2 points)\n\n---\n\n**Round 3 — MCP & Subagents** (header: \"Integration\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Connected an MCP server and used its tools\" — e.g., GitHub MCP for PRs/issues, database MCP for queries, or any external data source\n2. \"Used advanced MCP features\" — Project-scope .mcp.json, OAuth authentication, MCP resources with @mentions, Tool Search, or `claude mcp serve`\n3. \"Created or configured custom subagents\" — Defined agents in .claude/agents/ with custom tools, model, or permissions\n4. \"Used advanced subagent features\" — Worktree isolation, persistent agent memory, background tasks with Ctrl+B, agent allowlists with `Agent(agent_type)` for an agent run as the main thread with `claude --agent` (the `Task(...)` form is a back-compat alias), or agent teams\n\n**Scoring for Round 3:**\n- Options 1-2 map to **MCP** (0-2 points)\n- Options 3-4 map to **Subagents** (0-2 points)\n\n---\n\n**Round 4 — Checkpoints & Advanced Features** (header: \"Power User\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Used checkpoints for safe experimentation\" — Rewound to a checkpoint with Esc+Esc or /rewind, restored code and/or conversation, or used either Summarize option (summarize from here / summarize up to here)\n2. \"Used planning mode or extended thinking\" — Activated planning via /plan, Shift+Tab, or --permission-mode plan; toggled extended thinking with Alt+T/Option+T on a model that allows it, or set reasoning depth with `/effort`\n3. \"Configured permission modes\" — Used any of the six modes — manual (config value `default`; shown as Manual since v2.1.200), acceptEdits, plan, auto, dontAsk, or bypassPermissions — via CLI flags, keyboard shortcuts, or settings (just starting in the built-in auto default doesn't count)\n4. \"Used remote/desktop/web features\" — Used `claude --remote-control`, `claude --cloud`, `/teleport`, `/desktop`, or worktrees with `claude -w`\n\n**Scoring for Round 4:**\n- Option 1 maps to **Checkpoints** (0-1 point)\n- Options 2-4 map to **Advanced Features** (0-3 points)\n\n---\n\n**Round 5 — Plugins & CLI** (header: \"Mastery\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Installed or created a plugin\" — Used a bundled plugin from marketplace, or created a .claude-plugin/ directory with plugin.json manifest\n2. \"Used plugin advanced features\" — Plugin skills (`skills/` — the preferred form; namespaced `commands/` is legacy but still works), plugin hooks, plugin MCP servers, LSP configuration, or --plugin-dir flag for testing\n3. \"Used print mode in scripts or CI/CD\" — Used `claude -p` with --output-format json, --max-turns, piped input, or integrated into GitHub Actions / CI pipelines\n4. \"Used advanced CLI features\" — Session resumption (-c/-r), --agents flag, --json-schema for structured output, --fallback-model, --from-pr, or batch processing loops\n\n**Scoring for Round 5:**\n- Options 1-2 map to **Plugins** (0-2 points)\n- Options 3-4 map to **CLI** (0-2 points)\n\n---\n\n### Step 3: Calculate & Present Results\n\n#### 3A: For Quick Assessment\n\nCount total selections and determine level. Then present:\n\n```markdown\n## Claude Code Skill Assessment Results\n\n### Your Level: [Level 1: Beginner / Level 2: Intermediate / Level 3: Advanced]\n\nYou checked **N/8** items.\n\n[One-line motivational summary based on level]\n\n### Your Skill Profile\n\n| Area | Status |\n|------|--------|\n| Basic CLI & Conversations | [Checked/Gap] |\n| CLAUDE.md & Memory | [Checked/Gap] |\n| Slash Commands (built-in) | [Checked/Gap] |\n| Custom Commands & Skills | [Checked/Gap] |\n| MCP Servers | [Checked/Gap] |\n| Hooks | [Checked/Gap] |\n| Subagents | [Checked/Gap] |\n| Print Mode & CI/CD | [Checked/Gap] |\n\n### Identified Gaps\n\n[For each unchecked item, provide a 1-line description of what to learn and a link to the tutorial]\n\n### Your Personalized Learning Path\n\n[Output the level-specific learning path — see Step 4]\n```\n\n#### 3B: For Deep Assessment\n\nCalculate per-topic scores from the 5 rounds. Each topic gets 0-2 points, except Advanced Features (0-3) and Checkpoints (0-1). Then present:\n\n```markdown\n## Claude Code Skill Assessment Results\n\n### Overall Level: [Level 1 / Level 2 / Level 3]\n\n**Total Score: N/20 points**\n\n[One-line motivational summary]\n\n### Your Skill Profile\n\n| Feature Area | Score | Mastery | Status |\n|-------------|-------|---------|--------|\n| Slash Commands | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Memory | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Skills | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Hooks | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| MCP | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Subagents | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Checkpoints | N/1 | [None/Proficient] | [Learn/Mastered] |\n| Advanced Features | N/3 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Plugins | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| CLI | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n\n**Mastery key:** 0 = None, 1 = Basic, 2 = Proficient\n\n### Strength Areas\n[List topics with score 2/2 — these are mastered]\n\n### Priority Gaps (Learn Next)\n[List topics with score 0 — these need attention first, ordered by dependency]\n\n### Review Areas\n[List topics with score 1/2 — basics known but advanced features not yet used]\n\n### Your Personalized Learning Path\n\n[Output gap-specific learning path — see Step 4]\n```\n\n**Overall level calculation for Deep Assessment:**\n- 0-6 total points = Level 1: Beginner\n- 7-13 total points = Level 2: Intermediate\n- 14-20 total points = Level 3: Advanced\n\n---\n\n### Step 4: Generate Personalized Learning Path\n\nBased on the assessment results, generate a learning path that is specific to the user's gaps. Do NOT just repeat the generic level path — adapt it.\n\n#### Rules for Path Generation\n\n1. **Skip mastered topics**: If a topic scored 2/2, do not include it in the path.\n2. **Prioritize by dependency order**: Slash Commands before Skills, Memory before Subagents, etc. The dependency order is:\n   - Slash Commands (no deps) -> Skills (depends on Slash Commands)\n   - Memory (no deps) -> Subagents (depends on Memory)\n   - CLI Basics (no deps) -> CLI Mastery (depends on all)\n   - Checkpoints (no deps)\n   - Hooks (depends on Slash Commands)\n   - MCP (no deps) -> Plugins (depends on MCP, Skills, Hooks)\n   - Advanced Features (depends on all previous)\n3. **For score 1/2 topics**: Recommend the \"deep dive\" — link to the specific advanced section they're missing.\n4. **Estimate time**: Sum only the topics they need to learn/review.\n5. **Group into phases**: Organize remaining topics into logical phases of 2-3 topics each.\n\n#### Path Output Format\n\n```markdown\n### Your Personalized Learning Path\n\n**Estimated time**: ~N hours (adjusted for your current skills)\n\n#### Phase 1: [Phase Name] (~N hours)\n[Only if they have gaps in these areas]\n\n**[Topic Name]** — [Learn from scratch / Deep dive into advanced features]\n- Tutorial: [link to tutorial directory]\n- Focus on: [specific sections/concepts they need]\n- Key exercise: [one concrete exercise to do]\n- You'll know it's done when: [specific success criterion]\n\n**[Topic Name]** — ...\n\n---\n\n#### Phase 2: [Phase Name] (~N hours)\n...\n\n---\n\n### Recommended Practice Projects\n\nBased on your gaps, try these real-world exercises to solidify your learning:\n\n1. **[Project name]**: [1-line description combining 2-3 gap topics]\n2. **[Project name]**: [1-line description]\n3. **[Project name]**: [1-line description]\n```\n\n#### Topic-Specific Recommendations\n\nUse these specific recommendations when a topic is a gap:\n\n**Slash Commands (score 0)**:\n- Tutorial: [01-slash-commands/](../../../01-slash-commands/)\n- Focus on: Built-in commands reference, creating your first SKILL.md, `$ARGUMENTS` syntax\n- Key exercise: Create a `/optimize` command and test it\n- Done when: You can create a custom skill with arguments and dynamic context\n\n**Slash Commands (score 1 — review)**:\n- Focus on: Dynamic context with the ``!`command` `` syntax, `@file` references, `disable-model-invocation` vs `user-invocable` control\n- Done when: You can create a skill that injects live command output and controls its own invocation behavior\n\n**Memory (score 0)**:\n- Tutorial: [02-memory/](../../../02-memory/)\n- Focus on: CLAUDE.md creation, `/init` and `/memory` commands, and the difference from auto memory (asking Claude to remember something saves it to auto memory; to put it in CLAUDE.md, say \"add this to CLAUDE.md\" or edit via `/memory` — the old `#` shortcut was removed)\n- Key exercise: Create a project CLAUDE.md with your coding standards\n- Done when: Claude remembers your preferences across sessions\n\n**Memory (score 1 — review)**:\n- Focus on: the 7 memory locations and how they are concatenated into context (loaded root-down, not overridden), .claude/rules/ directory with path-specific rules, `@import` syntax (max depth 4), Auto Memory MEMORY.md (Claude loads its first 200 lines or 25 KB, whichever comes first — a load cap, not a file-size limit)\n- Done when: You have modular rules for different directories and understand how every memory file is concatenated into context\n\n**Skills (score 0)**:\n- Tutorial: [03-skills/](../../../03-skills/)\n- Focus on: SKILL.md format, auto-invocation via description field, progressive disclosure (3 loading levels)\n- Key exercise: Install `03-skills/code-review-specialist` and verify it auto-triggers\n- Done when: A skill automatically activates based on conversation context\n\n**Skills (score 1 — review)**:\n- Focus on: `context: fork` with `agent` field for subagent execution, `disable-model-invocation` vs `user-invocable`, the skill-listing budget (1% of the context window, fallback 8,000 characters; each entry's `description` + `when_to_use` capped at 1,536 characters by default via `skillListingMaxDescChars`), bundled resources (scripts/, references/, assets/)\n- Done when: You can create a skill that runs in a subagent with forked context\n\n**Hooks (score 0)**:\n- Tutorial: [06-hooks/](../../../06-hooks/)\n- Focus on: Configuration structure (matcher + hooks array), PreToolUse/PostToolUse events, exit codes (0=success, 2=block), JSON input/output format\n- Key exercise: Create a PreToolUse hook that validates Bash commands\n- Done when: A hook blocks dangerous commands before execution\n\n**Hooks (score 1 — review)**:\n- Focus on: All 33 hook events (including PostToolUseFailure, StopFailure, TaskCreated, CwdChanged, FileChanged, PostCompact, Elicitation, ElicitationResult, Setup, UserPromptExpansion, MessageDisplay, PreModelSwitch, PostModelSwitch — the last two added in v2.1.251), 5 hook types (command, http, mcp_tool, prompt, agent — agent hooks are experimental and may change), hooks in SKILL.md frontmatter (they persist for the session after invocation; subagent-frontmatter hooks end with the subagent), HTTP hooks with allowedEnvVars, `onFailure: \"block\"` to block the action when a command or HTTP hook fails (v2.1.295+), `CLAUDE_ENV_FILE` for SessionStart, Setup, CwdChanged and FileChanged\n- Done when: You can create a prompt-based Stop hook and a hook in a skill's frontmatter (and you know it stays registered for the rest of the session)\n\n**MCP (score 0)**:\n- Tutorial: [05-mcp/](../../../05-mcp/)\n- Focus on: `claude mcp add` command, transport types (`http` recommended, `stdio`, `ws` for push-style servers, and the deprecated `sse` — note `--transport` does not accept `ws`, so add WebSocket servers with `claude mcp add-json`), GitHub MCP setup, environment variable expansion\n- Key exercise: Add GitHub MCP server and query PRs\n- Done when: You can query live data from an external service via MCP\n\n**MCP (score 1 — review)**:\n- Focus on: Project-scope .mcp.json (each user approves it on first use; workspace trust applies), OAuth 2.0 auth, MCP resources with `@server:resource` mentions, Tool Search (ENABLE_TOOL_SEARCH), `claude mcp serve`, output limits (10,000 tokens warning; 25,000 tokens default max via `MAX_MCP_OUTPUT_TOKENS`; 50,000 characters disk-persistence threshold)\n- Done when: You have a project .mcp.json and understand how tool search defers MCP tools by default and what `ENABLE_TOOL_SEARCH=auto`/`false` change\n\n**Subagents (score 0)**:\n- Tutorial: [04-subagents/](../../../04-subagents/)\n- Focus on: Agent file format (.claude/agents/*.md), built-in agents (Explore, Plan, general-purpose, claude, statusline-setup, claude-code-guide), tools/model/permissionMode config, spawn limits (depth default 3 since v2.1.219, concurrency default 20, and the 200-per-session spawn cap removed in v2.1.224)\n- Key exercise: Create a code-reviewer subagent and test delegation\n- Done when: Claude delegates code review to your custom agent\n\n**Subagents (score 1 — review)**:\n- Focus on: Worktree isolation (`isolation: worktree`), persistent agent memory (`memory` field with scopes), background agents (Ctrl+B to background; Ctrl+X Ctrl+K twice to stop them all), agent allowlists with `Agent(agent_type)` for a main-thread agent started with `claude --agent` (`Task(...)` remains a back-compat alias; in a subagent's own `tools` the type list is ignored), agent teams (`--teammate-mode`)\n- Done when: You have a subagent with persistent memory running in worktree isolation\n\n**Checkpoints (score 0)**:\n- Tutorial: [08-checkpoints/](../../../08-checkpoints/)\n- Focus on: Esc+Esc and /rewind access, 6 rewind options (restore code and conversation, restore conversation, restore code, summarize from here, summarize up to here, never mind), limitations — bash filesystem ops, subagent edits (except a foreground `context: fork` skill), edits made outside Claude Code are untracked, and symlinked/hard-linked paths are skipped on restore\n- Key exercise: Make experimental changes, then rewind to restore\n- Done when: You can confidently experiment knowing you can rewind\n\n**Advanced Features (score 0)**:\n- Tutorial: [09-advanced-features/](../../../09-advanced-features/)\n- Focus on: Planning mode (/plan or Shift+Tab), permission modes (6 types: manual — config value `default`, shown as Manual since v2.1.200 — acceptEdits, plan, auto, dontAsk, bypassPermissions), extended thinking (Alt+T/Option+T toggle — no effect on Opus 5.5 (the default model), Sonnet 5.5, Haiku 5.5, or the Fable models, where thinking stays on)\n- Key exercise: Use planning mode to design a feature, then implement it\n- Done when: You can switch between planning and implementation modes fluently\n\n**Advanced Features (score 1 — review)**:\n- Focus on: Remote control (`claude --remote-control`, alias `--rc`), web sessions (`claude --cloud`; `--remote` is a deprecated alias), desktop handoff (`/desktop`), worktrees (`claude -w`), task lists (Ctrl+T), managed settings for enterprise\n- Done when: You can hand off sessions between CLI, web, and desktop\n\n**Plugins (score 0)**:\n- Tutorial: [07-plugins/](../../../07-plugins/)\n- Focus on: Plugin structure (.claude-plugin/plugin.json), what plugins bundle (skills, agents, MCP, hooks, settings — plus the legacy `commands/` directory, which still works but `skills/` is preferred for new plugins), installation from marketplace (`/plugin install`, or `claude plugin install <plugin> --marketplace <source>` from the shell)\n- Key exercise: Install a plugin and explore its components\n- Done when: You understand when to use a plugin vs standalone components\n\n**Plugins (score 1 — review)**:\n- Focus on: Creating plugin.json manifest, plugin hooks (hooks/hooks.json), LSP configuration (.lsp.json), `${CLAUDE_PLUGIN_ROOT}` variable, --plugin-dir for testing, marketplace publishing, mods (hooks modules shipped in a plugin that add panes, commands, and tool-call rules — v2.1.287+)\n- Done when: You can create and test a plugin for your team\n\n**CLI (score 0)**:\n- Tutorial: [10-cli/](../../../10-cli/)\n- Focus on: Interactive vs print mode, `claude -p` with piping, `--output-format json`, session management (-c/-r)\n- Key exercise: Pipe a file to `claude -p` and get JSON output\n- Done when: You can use Claude non-interactively in a script\n\n**CLI (score 1 — review)**:\n- Focus on: --agents flag with JSON config, --json-schema for structured output, --fallback-model, --from-pr, --strict-mcp-config, batch processing with for loops, `claude mcp serve`\n- Done when: You have a CI/CD script that uses Claude with structured JSON output\n\n---\n\n### Step 5: Offer Follow-up Actions\n\nAfter presenting results, ask the user what they'd like to do next:\n\nUse AskUserQuestion with these options:\n- **Start learning** — \"Help me begin the first topic in my learning path right now\"\n- **Deep dive on a gap** — \"Explain one of my gap areas in detail so I can learn it here\"\n- **Practice project** — \"Set up a practice project that covers my gap areas\"\n- **Retake assessment** — \"I want to retake the quiz (maybe the other mode)\"\n\nIf **Start learning**: Read the README.md of the first gap tutorial and walk the user through the first exercise.\nIf **Deep dive on a gap**: Ask which gap topic, then read the relevant tutorial README.md and explain the key concepts with examples.\nIf **Practice project**: Design a small project that combines 2-3 of their gap topics with concrete steps.\nIf **Retake assessment**: Go back to Step 1.\n\n## Error Handling\n\n### User selects no items in a round\nTreat as 0 points for that round's topics. Continue to next round.\n\n### User selects no items in any round\nAssign Level 1: Beginner. Encourage starting from the beginning. Output the full Level 1 path.\n\n### User wants to retake\nRe-run from Step 1 with a fresh assessment.\n\n### User disagrees with their level\nAcknowledge their preference. Ask which level they identify with. Present the path for their chosen level with a prerequisites check for topics they may have missed.\n\n### User asks about a specific topic\nIf the user says something like \"tell me about hooks\" or \"I want to learn MCP\" during the assessment, note it. After presenting results, highlight that topic in their learning path regardless of score.\n\n## Validation\n\n### Triggering test suite\n\n**Should trigger:**\n- \"assess my level\"\n- \"take the quiz\"\n- \"find my level\"\n- \"where should I start\"\n- \"what level am I\"\n- \"learning path quiz\"\n- \"self-assessment\"\n- \"what should I learn next\"\n- \"check my skills\"\n- \"skill check\"\n- \"level up\"\n- \"how good am I at Claude Code\"\n- \"evaluate my Claude Code knowledge\"\n\n**Should NOT trigger:**\n- \"review my code\"\n- \"create a skill\"\n- \"help me with MCP\"\n- \"explain slash commands\"\n- \"what is a checkpoint\"\n",".claude/skills/self-assessment/references/deep-assessment-rounds.md":"# Deep Assessment — Round Questions\n\nThe 5 rounds for Deep Assessment. Present one AskUserQuestion call per round (multi-select, max 4 options). Each round covers 2 feature areas with 2 options each. The scoring map for each round is duplicated in SKILL.md Step 2B so results can be computed without re-reading this file.\n\n---\n\n**Round 1 — Slash Commands & Memory** (header: \"Commands\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Created a custom slash command or skill\" — Written a SKILL.md file with frontmatter, or created .claude/commands/ files\n2. \"Used dynamic context in commands\" — Used `$ARGUMENTS`, `$0`/`$1`, backtick `!command` syntax, or `@file` references in skill/command files\n3. \"Set up project + personal memory\" — Created both a project CLAUDE.md and personal ~/.claude/CLAUDE.md (or CLAUDE.local.md)\n4. \"Used memory hierarchy features\" — Understand how the 7 memory locations are concatenated into context (loaded root-down, CLAUDE.local.md appended after CLAUDE.md at each level, subdirectory files loaded on demand), used .claude/rules/ directory, path-specific rules, or @import syntax\n\n**Scoring:** Options 1-2 → **Slash Commands** (0-2); Options 3-4 → **Memory** (0-2)\n\n---\n\n**Round 2 — Skills & Hooks** (header: \"Automation\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Installed and used an auto-invoked skill\" — A skill that triggers automatically based on its description, without manual /command invocation\n2. \"Controlled skill invocation behavior\" — Used `disable-model-invocation`, `user-invocable`, or `context: fork` with agent field in SKILL.md frontmatter\n3. \"Set up a PreToolUse or PostToolUse hook\" — Configured a hook that runs before/after tool execution (e.g., command validator, auto-formatter)\n4. \"Used advanced hook features\" — Configured prompt-type hooks, skill-frontmatter hooks, HTTP hooks, or hooks with custom JSON output (updatedInput, systemMessage)\n\n**Scoring:** Options 1-2 → **Skills** (0-2); Options 3-4 → **Hooks** (0-2)\n\n---\n\n**Round 3 — MCP & Subagents** (header: \"Integration\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Connected an MCP server and used its tools\" — e.g., GitHub MCP for PRs/issues, database MCP for queries, or any external data source\n2. \"Used advanced MCP features\" — Project-scope .mcp.json, OAuth authentication, MCP resources with @mentions, Tool Search, or `claude mcp serve`\n3. \"Created or configured custom subagents\" — Defined agents in .claude/agents/ with custom tools, model, or permissions\n4. \"Used advanced subagent features\" — Worktree isolation, persistent agent memory, background tasks with Ctrl+B, agent allowlists with `Agent(agent_type)` for an agent run as the main thread with `claude --agent` (the `Task(...)` form is a back-compat alias), or agent teams\n\n**Scoring:** Options 1-2 → **MCP** (0-2); Options 3-4 → **Subagents** (0-2)\n\n---\n\n**Round 4 — Checkpoints & Advanced Features** (header: \"Power User\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Used checkpoints for safe experimentation\" — Rewound to a checkpoint with Esc+Esc or /rewind, restored code and/or conversation, or used either Summarize option (summarize from here / summarize up to here)\n2. \"Used planning mode or extended thinking\" — Activated planning via /plan, Shift+Tab, or --permission-mode plan; toggled extended thinking with Alt+T/Option+T on a model that allows it, or set reasoning depth with `/effort`\n3. \"Configured permission modes\" — Used any of the six modes — manual (config value `default`; shown as Manual since v2.1.200), acceptEdits, plan, auto, dontAsk, or bypassPermissions — via CLI flags, keyboard shortcuts, or settings (just starting in the built-in auto default doesn't count)\n4. \"Used remote/desktop/web features\" — Used `claude --remote-control`, `claude --cloud`, `/teleport`, `/desktop`, or worktrees with `claude -w`\n\n**Scoring:** Option 1 → **Checkpoints** (0-1); Options 2-4 → **Advanced Features** (0-3)\n\n---\n\n**Round 5 — Plugins & CLI** (header: \"Mastery\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Installed or created a plugin\" — Used a bundled plugin from marketplace, or created a .claude-plugin/ directory with plugin.json manifest\n2. \"Used plugin advanced features\" — Plugin skills (`skills/` — the preferred form; namespaced `commands/` is legacy but still works), plugin hooks, plugin MCP servers, LSP configuration, or --plugin-dir flag for testing\n3. \"Used print mode in scripts or CI/CD\" — Used `claude -p` with --output-format json, --max-turns, piped input, or integrated into GitHub Actions / CI pipelines\n4. \"Used advanced CLI features\" — Session resumption (-c/-r), --agents flag, --json-schema for structured output, --fallback-model, --from-pr, or batch processing loops\n\n**Scoring:** Options 1-2 → **Plugins** (0-2); Options 3-4 → **CLI** (0-2)\n\n---\n\n**Last Updated**: October 18, 2026\n**Claude Code Version**: 2.1.302\n**Sources**:\n- https://code.claude.com/docs/en/memory\n- https://code.claude.com/docs/en/sub-agents\n- https://code.claude.com/docs/en/permission-modes\n- https://code.claude.com/docs/en/checkpointing\n- https://code.claude.com/docs/en/plugins-reference\n- https://code.claude.com/docs/en/permission-modes#which-mode-a-session-starts-in\n- https://code.claude.com/docs/en/hooks#hooks-in-skills-and-agents\n- https://code.claude.com/docs/en/model-config#extended-thinking\n",".claude/skills/self-assessment/references/output-templates.md":"# Output Templates\n\nBlank markdown templates for the assessment results and learning path. The Step 3A/3B result templates and the Step 4 path-format template are duplicated verbatim in SKILL.md so results can be produced without re-reading this file.\n\n## Quick Assessment results (Step 3A)\n\n```markdown\n## Claude Code Skill Assessment Results\n\n### Your Level: [Level 1: Beginner / Level 2: Intermediate / Level 3: Advanced]\n\nYou checked **N/8** items.\n\n[One-line motivational summary based on level]\n\n### Your Skill Profile\n\n| Area | Status |\n|------|--------|\n| Basic CLI & Conversations | [Checked/Gap] |\n| CLAUDE.md & Memory | [Checked/Gap] |\n| Slash Commands (built-in) | [Checked/Gap] |\n| Custom Commands & Skills | [Checked/Gap] |\n| MCP Servers | [Checked/Gap] |\n| Hooks | [Checked/Gap] |\n| Subagents | [Checked/Gap] |\n| Print Mode & CI/CD | [Checked/Gap] |\n\n### Identified Gaps\n\n[For each unchecked item, provide a 1-line description of what to learn and a link to the tutorial]\n\n### Your Personalized Learning Path\n\n[Output the level-specific learning path — see Step 4]\n```\n\n## Deep Assessment results (Step 3B)\n\n```markdown\n## Claude Code Skill Assessment Results\n\n### Overall Level: [Level 1 / Level 2 / Level 3]\n\n**Total Score: N/20 points**\n\n[One-line motivational summary]\n\n### Your Skill Profile\n\n| Feature Area | Score | Mastery | Status |\n|-------------|-------|---------|--------|\n| Slash Commands | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Memory | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Skills | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Hooks | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| MCP | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Subagents | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Checkpoints | N/1 | [None/Proficient] | [Learn/Mastered] |\n| Advanced Features | N/3 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Plugins | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| CLI | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n\n**Mastery key:** 0 = None, 1 = Basic, 2 = Proficient\n\n### Strength Areas\n[List topics with score 2/2 — these are mastered]\n\n### Priority Gaps (Learn Next)\n[List topics with score 0 — these need attention first, ordered by dependency]\n\n### Review Areas\n[List topics with score 1/2 — basics known but advanced features not yet used]\n\n### Your Personalized Learning Path\n\n[Output gap-specific learning path — see Step 4]\n```\n\n## Learning Path (Step 4)\n\n```markdown\n### Your Personalized Learning Path\n\n**Estimated time**: ~N hours (adjusted for your current skills)\n\n#### Phase 1: [Phase Name] (~N hours)\n[Only if they have gaps in these areas]\n\n**[Topic Name]** — [Learn from scratch / Deep dive into advanced features]\n- Tutorial: [link to tutorial directory]\n- Focus on: [specific sections/concepts they need]\n- Key exercise: [one concrete exercise to do]\n- You'll know it's done when: [specific success criterion]\n\n**[Topic Name]** — ...\n\n---\n\n#### Phase 2: [Phase Name] (~N hours)\n...\n\n---\n\n### Recommended Practice Projects\n\nBased on your gaps, try these real-world exercises to solidify your learning:\n\n1. **[Project name]**: [1-line description combining 2-3 gap topics]\n2. **[Project name]**: [1-line description]\n3. **[Project name]**: [1-line description]\n```\n\n---\n\n**Last Updated**: September 2, 2026\n**Claude Code Version**: 2.1.257\n**Sources**:\n- https://code.claude.com/docs/en/overview\n",".claude/skills/self-assessment/references/topic-recommendations.md":"# Topic-Specific Recommendations\n\nUse these specific recommendations when a topic is a gap. Paths are relative to this reference file (`.claude/skills/self-assessment/references/`).\n\n**Slash Commands (score 0)**:\n- Tutorial: [01-slash-commands/](../../../../01-slash-commands/)\n- Focus on: Built-in commands reference, creating your first SKILL.md, `$ARGUMENTS` syntax\n- Key exercise: Create a `/optimize` command and test it\n- Done when: You can create a custom skill with arguments and dynamic context\n\n**Slash Commands (score 1 — review)**:\n- Focus on: Dynamic context with the ``!`command` `` syntax, `@file` references, `disable-model-invocation` vs `user-invocable` control\n- Done when: You can create a skill that injects live command output and controls its own invocation behavior\n\n**Memory (score 0)**:\n- Tutorial: [02-memory/](../../../../02-memory/)\n- Focus on: CLAUDE.md creation, `/init` and `/memory` commands, and the difference from auto memory (asking Claude to remember something saves it to auto memory; to put it in CLAUDE.md, say \"add this to CLAUDE.md\" or edit via `/memory` — the old `#` shortcut was removed)\n- Key exercise: Create a project CLAUDE.md with your coding standards\n- Done when: Claude remembers your preferences across sessions\n\n**Memory (score 1 — review)**:\n- Focus on: the 7 memory locations and how they are concatenated into context (loaded root-down, not overridden), .claude/rules/ directory with path-specific rules, `@import` syntax (max depth 4), Auto Memory MEMORY.md (Claude loads its first 200 lines or 25 KB, whichever comes first — a load cap, not a file-size limit)\n- Done when: You have modular rules for different directories and understand how every memory file is concatenated into context\n\n**Skills (score 0)**:\n- Tutorial: [03-skills/](../../../../03-skills/)\n- Focus on: SKILL.md format, auto-invocation via description field, progressive disclosure (3 loading levels)\n- Key exercise: Install `03-skills/code-review-specialist` and verify it auto-triggers\n- Done when: A skill automatically activates based on conversation context\n\n**Skills (score 1 — review)**:\n- Focus on: `context: fork` with `agent` field for subagent execution, `disable-model-invocation` vs `user-invocable`, the skill-listing budget (1% of the context window, fallback 8,000 characters; each entry's `description` + `when_to_use` capped at 1,536 characters by default via `skillListingMaxDescChars`), bundled resources (scripts/, references/, assets/)\n- Done when: You can create a skill that runs in a subagent with forked context\n\n**Hooks (score 0)**:\n- Tutorial: [06-hooks/](../../../../06-hooks/)\n- Focus on: Configuration structure (matcher + hooks array), PreToolUse/PostToolUse events, exit codes (0=success, 2=block), JSON input/output format\n- Key exercise: Create a PreToolUse hook that validates Bash commands\n- Done when: A hook blocks dangerous commands before execution\n\n**Hooks (score 1 — review)**:\n- Focus on: All 33 hook events (including PostToolUseFailure, StopFailure, TaskCreated, CwdChanged, FileChanged, PostCompact, Elicitation, ElicitationResult, Setup, UserPromptExpansion, MessageDisplay, PreModelSwitch, PostModelSwitch — the last two added in v2.1.251), 5 hook types (command, http, mcp_tool, prompt, agent — agent hooks are experimental and may change), hooks in SKILL.md frontmatter (they persist for the session after invocation; subagent-frontmatter hooks end with the subagent), HTTP hooks with allowedEnvVars, `onFailure: \"block\"` to block the action when a command or HTTP hook fails (v2.1.295+), `CLAUDE_ENV_FILE` for SessionStart, Setup, CwdChanged and FileChanged\n- Done when: You can create a prompt-based Stop hook and a hook in a skill's frontmatter (and you know it stays registered for the rest of the session)\n\n**MCP (score 0)**:\n- Tutorial: [05-mcp/](../../../../05-mcp/)\n- Focus on: `claude mcp add` command, transport types (`http` recommended, `stdio`, `ws` for push-style servers, and the deprecated `sse` — note `--transport` does not accept `ws`, so add WebSocket servers with `claude mcp add-json`), GitHub MCP setup, environment variable expansion\n- Key exercise: Add GitHub MCP server and query PRs\n- Done when: You can query live data from an external service via MCP\n\n**MCP (score 1 — review)**:\n- Focus on: Project-scope .mcp.json (each user approves it on first use; workspace trust applies), OAuth 2.0 auth, MCP resources with `@server:resource` mentions, Tool Search (ENABLE_TOOL_SEARCH), `claude mcp serve`, output limits (10,000 tokens warning; 25,000 tokens default max via `MAX_MCP_OUTPUT_TOKENS`; 50,000 characters disk-persistence threshold)\n- Done when: You have a project .mcp.json and understand how tool search defers MCP tools by default and what `ENABLE_TOOL_SEARCH=auto`/`false` change\n\n**Subagents (score 0)**:\n- Tutorial: [04-subagents/](../../../../04-subagents/)\n- Focus on: Agent file format (.claude/agents/*.md), built-in agents (Explore, Plan, general-purpose, claude, statusline-setup, claude-code-guide), tools/model/permissionMode config, spawn limits (depth default 3 since v2.1.219, concurrency default 20, and the 200-per-session spawn cap removed in v2.1.224)\n- Key exercise: Create a code-reviewer subagent and test delegation\n- Done when: Claude delegates code review to your custom agent\n\n**Subagents (score 1 — review)**:\n- Focus on: Worktree isolation (`isolation: worktree`), persistent agent memory (`memory` field with scopes), background agents (Ctrl+B to background; Ctrl+X Ctrl+K twice to stop them all), agent allowlists with `Agent(agent_type)` for a main-thread agent started with `claude --agent` (`Task(...)` remains a back-compat alias; in a subagent's own `tools` the type list is ignored), agent teams (`--teammate-mode`)\n- Done when: You have a subagent with persistent memory running in worktree isolation\n\n**Checkpoints (score 0)**:\n- Tutorial: [08-checkpoints/](../../../../08-checkpoints/)\n- Focus on: Esc+Esc and /rewind access, 6 rewind options (restore code and conversation, restore conversation, restore code, summarize from here, summarize up to here, never mind), limitations — bash filesystem ops, subagent edits (except a foreground `context: fork` skill), edits made outside Claude Code are untracked, and symlinked/hard-linked paths are skipped on restore\n- Key exercise: Make experimental changes, then rewind to restore\n- Done when: You can confidently experiment knowing you can rewind\n\n**Advanced Features (score 0)**:\n- Tutorial: [09-advanced-features/](../../../../09-advanced-features/)\n- Focus on: Planning mode (/plan or Shift+Tab), permission modes (6 types: manual — config value `default`, shown as Manual since v2.1.200 — acceptEdits, plan, auto, dontAsk, bypassPermissions), extended thinking (Alt+T/Option+T toggle — no effect on Opus 5.5 (the default model), Sonnet 5.5, Haiku 5.5, or the Fable models, where thinking stays on)\n- Key exercise: Use planning mode to design a feature, then implement it\n- Done when: You can switch between planning and implementation modes fluently\n\n**Advanced Features (score 1 — review)**:\n- Focus on: Remote control (`claude --remote-control`, alias `--rc`), web sessions (`claude --cloud`; `--remote` is a deprecated alias), desktop handoff (`/desktop`), worktrees (`claude -w`), task lists (Ctrl+T), managed settings for enterprise\n- Done when: You can hand off sessions between CLI, web, and desktop\n\n**Plugins (score 0)**:\n- Tutorial: [07-plugins/](../../../../07-plugins/)\n- Focus on: Plugin structure (.claude-plugin/plugin.json), what plugins bundle (skills, agents, MCP, hooks, settings — plus the legacy `commands/` directory, which still works but `skills/` is preferred for new plugins), installation from marketplace (`/plugin install`, or `claude plugin install <plugin> --marketplace <source>` from the shell)\n- Key exercise: Install a plugin and explore its components\n- Done when: You understand when to use a plugin vs standalone components\n\n**Plugins (score 1 — review)**:\n- Focus on: Creating plugin.json manifest, plugin hooks (hooks/hooks.json), LSP configuration (.lsp.json), `${CLAUDE_PLUGIN_ROOT}` variable, --plugin-dir for testing, marketplace publishing, mods (hooks modules shipped in a plugin that add panes, commands, and tool-call rules — v2.1.287+)\n- Done when: You can create and test a plugin for your team\n\n**CLI (score 0)**:\n- Tutorial: [10-cli/](../../../../10-cli/)\n- Focus on: Interactive vs print mode, `claude -p` with piping, `--output-format json`, session management (-c/-r)\n- Key exercise: Pipe a file to `claude -p` and get JSON output\n- Done when: You can use Claude non-interactively in a script\n\n**CLI (score 1 — review)**:\n- Focus on: --agents flag with JSON config, --json-schema for structured output, --fallback-model, --from-pr, --strict-mcp-config, batch processing with for loops, `claude mcp serve`\n- Done when: You have a CI/CD script that uses Claude with structured JSON output\n\n---\n\n**Last Updated**: October 18, 2026\n**Claude Code Version**: 2.1.302\n**Sources**:\n- https://code.claude.com/docs/en/hooks\n- https://code.claude.com/docs/en/memory\n- https://code.claude.com/docs/en/skills\n- https://code.claude.com/docs/en/mcp\n- https://code.claude.com/docs/en/sub-agents\n- https://code.claude.com/docs/en/checkpointing\n- https://code.claude.com/docs/en/permission-modes\n- https://code.claude.com/docs/en/plugins-reference\n- https://code.claude.com/docs/en/interactive-mode\n- https://code.claude.com/docs/en/model-config#extended-thinking\n- https://code.claude.com/docs/en/settings-reference\n- https://code.claude.com/docs/en/model-config\n- https://code.claude.com/docs/en/plugins/mods/overview\n- https://code.claude.com/docs/en/plugins/cli-reference\n- https://code.claude.com/docs/en/mcp#configure-tool-search\n- https://code.claude.com/docs/en/mcp#project-server-approvals-and-workspace-trust\n","03-skills/blog-draft/SKILL.md":"---\nname: blog-draft\ndescription: Draft a blog post from ideas and resources. Use when users want to write a blog post, create content from research, or draft articles. Guides through research, brainstorming, outlining, and iterative drafting with version control.\n---\n\n## User Input\n\n```text\n$ARGUMENTS\n```\n\nYou **MUST** consider the user input before proceeding. User should provide:\n- **Idea/Topic**: The main concept or theme for the blog post\n- **Resources**: URLs, files, or references to research (optional but recommended)\n- **Target audience**: Who the blog post is for (optional)\n- **Tone/Style**: Formal, casual, technical, etc. (optional)\n\n**IMPORTANT**: If the user is requesting updates to an **existing blog post**, skip steps 0-8 and start directly at **Step 9**. Read the existing draft file(s) first, then proceed with the iteration process.\n\n## Execution Flow\n\nFollow these steps sequentially. **Do not skip steps or proceed without user approval where indicated.**\n\n### Step 0: Create Project Folder\n\n1. Generate a folder name using format: `YYYY-MM-DD-short-topic-name`\n   - Use today's date\n   - Create a short, URL-friendly slug from the topic (lowercase, hyphens, max 5 words)\n\n2. Create the folder structure:\n   ```\n   blog-posts/\n   └── YYYY-MM-DD-short-topic-name/\n       └── resources/\n   ```\n\n3. Confirm folder creation with user before proceeding.\n\n### Step 1: Research & Resource Collection\n\n1. Create `resources/` subfolder in the blog post directory\n\n2. For each provided resource:\n   - **URLs**: Fetch and save key information to `resources/` as markdown files\n   - **Files**: Read and summarize in `resources/`\n   - **Topics**: Use web search to gather up-to-date information\n\n3. For each resource, create a summary file in `resources/`:\n   - `resources/source-1-[short-name].md`\n   - `resources/source-2-[short-name].md`\n   - etc.\n\n4. Each summary should include:\n   ```markdown\n   # Source: [Title/URL]\n\n   ## Key Points\n   - Point 1\n   - Point 2\n\n   ## Relevant Quotes/Data\n   - Quote or statistic 1\n   - Quote or statistic 2\n\n   ## How This Relates to Topic\n   Brief explanation of relevance\n   ```\n\n5. Present research summary to user.\n\n### Step 2: Brainstorm & Clarify\n\n1. Based on the idea and researched resources, present:\n   - **Main themes** identified from research\n   - **Potential angles** for the blog post\n   - **Key points** that should be covered\n   - **Gaps** in information that need clarification\n\n2. Ask clarifying questions:\n   - What is the main takeaway you want readers to have?\n   - Are there specific points from the research you want to emphasize?\n   - What's the target length? (short: 500-800 words, medium: 1000-1500, long: 2000+)\n   - Any points you want to exclude?\n\n3. **Wait for user responses before proceeding.**\n\n### Step 3: Propose Outline\n\n1. Create a structured outline including:\n\n   ```markdown\n   # Blog Post Outline: [Title]\n\n   ## Meta Information\n   - **Target Audience**: [who]\n   - **Tone**: [style]\n   - **Target Length**: [word count]\n   - **Main Takeaway**: [key message]\n\n   ## Proposed Structure\n\n   ### Hook/Introduction\n   - Opening hook idea\n   - Context setting\n   - Thesis statement\n\n   ### Section 1: [Title]\n   - Key point A\n   - Key point B\n   - Supporting evidence from [source]\n\n   ### Section 2: [Title]\n   - Key point A\n   - Key point B\n\n   [Continue for all sections...]\n\n   ### Conclusion\n   - Summary of key points\n   - Call to action or final thought\n\n   ## Sources to Cite\n   - Source 1\n   - Source 2\n   ```\n\n2. Present outline to user and **ask for approval or modifications**.\n\n### Step 4: Save Approved Outline\n\n1. Once user approves the outline, save it to `OUTLINE.md` in the blog post folder.\n\n2. Confirm the outline has been saved.\n\n### Step 5: Commit Outline (if in git repo)\n\n1. Check if current directory is a git repository.\n\n2. If yes:\n   - Stage the new files: blog post folder, resources, and OUTLINE.md\n   - Create commit with message: `docs: Add outline for blog post - [topic-name]`\n   - Push to remote\n\n3. If not a git repo, skip this step and inform user.\n\n### Step 6: Write Draft\n\n1. Based on the approved outline, write the full blog post draft.\n\n2. Follow the structure from OUTLINE.md exactly.\n\n3. Include:\n   - Engaging introduction with hook\n   - Clear section headers\n   - Supporting evidence and examples from research\n   - Smooth transitions between sections\n   - Strong conclusion with takeaway\n   - **Citations**: All comparisons, statistics, data points, and factual claims MUST cite the original source\n\n4. Save the draft as `draft-v0.1.md` in the blog post folder.\n\n5. Format:\n   ```markdown\n   # [Blog Post Title]\n\n   *[Optional: subtitle or tagline]*\n\n   [Full content with inline citations...]\n\n   ---\n\n   ## References\n   - [1] Source 1 Title - URL or Citation\n   - [2] Source 2 Title - URL or Citation\n   - [3] Source 3 Title - URL or Citation\n   ```\n\n6. **Citation Requirements**:\n   - Every data point, statistic, or comparison MUST have an inline citation\n   - Use numbered references [1], [2], etc., or named citations [Source Name]\n   - Link citations to the References section at the end\n   - Example: \"Studies show that 65% of developers prefer TypeScript [1]\"\n   - Example: \"React outperforms Vue in rendering speed by 20% [React Benchmarks 2024]\"\n\n### Step 7: Commit Draft (if in git repo)\n\n1. Check if in git repository.\n\n2. If yes:\n   - Stage the draft file\n   - Create commit with message: `docs: Add draft v0.1 for blog post - [topic-name]`\n   - Push to remote\n\n3. If not a git repo, skip and inform user.\n\n### Step 8: Present Draft for Review\n\n1. Present the draft content to user.\n\n2. Ask for feedback:\n   - Overall impression?\n   - Sections that need expansion or reduction?\n   - Tone adjustments needed?\n   - Missing information?\n   - Specific edits or rewrites?\n\n3. **Wait for user response.**\n\n### Step 9: Iterate or Finalize\n\n**If user requests changes:**\n1. Note all requested modifications\n2. Return to Step 6 with the following adjustments:\n   - Increment version number (v0.2, v0.3, etc.)\n   - Incorporate all feedback\n   - Save as `draft-v[X.Y].md`\n   - Repeat Steps 7-8\n\n**If user approves:**\n1. Confirm the final draft version\n2. Optionally rename to `final.md` if user requests\n3. Summarize the blog post creation process:\n   - Total versions created\n   - Key changes between versions\n   - Final word count\n   - Files created\n\n## Version Tracking\n\nAll drafts are preserved with incremental versioning:\n- `draft-v0.1.md` - Initial draft\n- `draft-v0.2.md` - After first round of feedback\n- `draft-v0.3.md` - After second round of feedback\n- etc.\n\nThis allows tracking the evolution of the blog post and reverting if needed.\n\n## Output Files Structure\n\n```\nblog-posts/\n└── YYYY-MM-DD-topic-name/\n    ├── resources/\n    │   ├── source-1-name.md\n    │   ├── source-2-name.md\n    │   └── ...\n    ├── OUTLINE.md\n    ├── draft-v0.1.md\n    ├── draft-v0.2.md (if iterations)\n    └── draft-v0.3.md (if more iterations)\n```\n\n## Tips for Quality\n\n- **Hook**: Start with a question, surprising fact, or relatable scenario\n- **Flow**: Each paragraph should connect to the next\n- **Evidence**: Support claims with data from research\n- **Citations**: ALWAYS cite sources for:\n  - All statistics and data points (e.g., \"According to [Source], 75% of...\")\n  - Comparisons between products, services, or approaches (e.g., \"X performs 2x faster than Y [Source]\")\n  - Factual claims about market trends, research findings, or benchmarks\n  - Use inline citations with format: [Source Name] or [Author, Year]\n- **Voice**: Maintain consistent tone throughout\n- **Length**: Respect the target word count\n- **Readability**: Use short paragraphs, bullet points where appropriate\n- **CTA**: End with a clear call-to-action or thought-provoking question\n\n## Notes\n\n- Always wait for user approval at outlined checkpoints\n- Preserve all draft versions for history\n- Use web search for up-to-date information when URLs are provided\n- If resources are insufficient, ask user for more or suggest additional research\n- Adapt tone based on target audience (technical, general, business, etc.)\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","03-skills/brand-voice/SKILL.md":"---\nname: brand-voice\ndescription: Ensure all communication matches brand voice and tone guidelines. Use when creating marketing copy, customer communications, public-facing content, or when users mention brand voice, tone, or writing style.\nuser-invocable: false\n---\n\n# Brand Voice Skill\n\n## Overview\nThis skill ensures all communications maintain consistent brand voice, tone, and messaging.\n\n## Brand Identity\n\n### Mission\nHelp teams automate their development workflows with AI\n\n### Values\n- **Simplicity**: Make complex things simple\n- **Reliability**: Rock-solid execution\n- **Empowerment**: Enable human creativity\n\n### Tone of Voice\n- **Friendly but professional** - approachable without being casual\n- **Clear and concise** - avoid jargon, explain technical concepts simply\n- **Confident** - we know what we're doing\n- **Empathetic** - understand user needs and pain points\n\n## Writing Guidelines\n\n### Do's ✅\n- Use \"you\" when addressing readers\n- Use active voice: \"Claude generates reports\" not \"Reports are generated by Claude\"\n- Start with value proposition\n- Use concrete examples\n- Keep sentences under 20 words\n- Use lists for clarity\n- Include calls-to-action\n\n### Don'ts ❌\n- Don't use corporate jargon\n- Don't patronize or oversimplify\n- Don't use \"we believe\" or \"we think\"\n- Don't use ALL CAPS except for emphasis\n- Don't create walls of text\n- Don't assume technical knowledge\n\n## Vocabulary\n\n### ✅ Preferred Terms\n- Claude (not \"the Claude AI\")\n- Code generation (not \"auto-coding\")\n- Agent (not \"bot\")\n- Streamline (not \"revolutionize\")\n- Integrate (not \"synergize\")\n\n### ❌ Avoid Terms\n- \"Cutting-edge\" (overused)\n- \"Game-changer\" (vague)\n- \"Leverage\" (corporate-speak)\n- \"Utilize\" (use \"use\")\n- \"Paradigm shift\" (unclear)\n\n## Examples\n\n### ✅ Good Example\n\"Claude automates your code review process. Instead of manually checking each PR, Claude reviews security, performance, and quality—saving your team hours every week.\"\n\nWhy it works: Clear value, specific benefits, action-oriented\n\n### ❌ Bad Example\n\"Claude leverages cutting-edge AI to provide comprehensive software development solutions.\"\n\nWhy it doesn't work: Vague, corporate jargon, no specific value\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","03-skills/claude-md/SKILL.md":"---\nname: claude-md\ndescription: Create or update CLAUDE.md files following best practices for optimal AI agent onboarding\n---\n\n## User Input\n\n```text\n$ARGUMENTS\n```\n\nYou **MUST** consider the user input before proceeding (if not empty). User may specify:\n- `create` - Create new CLAUDE.md from scratch\n- `update` - Improve existing CLAUDE.md\n- `audit` - Analyze and report on current CLAUDE.md quality\n- A specific path to create/update (e.g., `src/api/CLAUDE.md` for directory-specific instructions)\n\n## Core Principles\n\n**LLMs are stateless**: CLAUDE.md is the main project file loaded into every conversation (alongside auto memory and unscoped rules). It serves as the primary onboarding document for AI agents into your codebase.\n\n### The Golden Rules\n\n1. **Less is More**: Frontier LLMs can follow ~150-200 instructions. Claude Code's system prompt already uses ~50. Keep your CLAUDE.md focused and concise.\n\n2. **Universal Applicability**: Only include information relevant to EVERY session. Task-specific instructions belong in separate files.\n\n3. **Don't Use Claude as a Linter**: Style guidelines bloat context and degrade instruction-following. Use deterministic tools (prettier, eslint, etc.) instead.\n\n4. **Never Auto-Generate**: CLAUDE.md is the highest leverage point of the AI harness. Craft it manually with careful consideration.\n\n## Execution Flow\n\n### 1. Project Analysis\n\nFirst, analyze the current project state:\n\n1. Check for existing CLAUDE.md files:\n   - Root level: `./CLAUDE.md` or `.claude/CLAUDE.md`\n   - Directory-specific: `**/CLAUDE.md`\n   - Global user config: `~/.claude/CLAUDE.md`\n\n2. Identify the project structure:\n   - Technology stack (languages, frameworks)\n   - Project type (monorepo, single app, library)\n   - Development tools (package manager, build system, test runner)\n\n3. Review existing documentation:\n   - README.md\n   - CONTRIBUTING.md\n   - package.json, pyproject.toml, Cargo.toml, etc.\n\n### 2. Content Strategy (WHAT, WHY, HOW)\n\nStructure CLAUDE.md around three dimensions:\n\n#### WHAT - Technology & Structure\n- Technology stack overview\n- Project organization (especially important for monorepos)\n- Key directories and their purposes\n\n#### WHY - Purpose & Context\n- What the project does\n- Why certain architectural decisions were made\n- What each major component is responsible for\n\n#### HOW - Workflow & Conventions\n- Development workflow (bun vs node, pip vs uv, etc.)\n- Testing procedures and commands\n- Verification and build methods\n- Critical \"gotchas\" or non-obvious requirements\n\n### 3. Progressive Disclosure Strategy\n\nFor larger projects, recommend creating an `agent_docs/` folder:\n\n```\nagent_docs/\n  |- building_the_project.md\n  |- running_tests.md\n  |- code_conventions.md\n  |- architecture_decisions.md\n```\n\nIn CLAUDE.md, reference these files with instructions like:\n```markdown\nFor detailed build instructions, refer to `agent_docs/building_the_project.md`\n```\n\n**Important**: Use `file:line` references instead of code snippets to avoid outdated context.\n\n### 4. Quality Constraints\n\nWhen creating or updating CLAUDE.md:\n\n1. **Target Length**: Keep it under 200 lines; shorter is better\n2. **No Style Rules**: Remove any linting/formatting instructions\n3. **No Task-Specific Instructions**: Move to separate files\n4. **No Code Snippets**: Use file references instead\n5. **No Redundant Information**: Don't repeat what's in package.json or README\n\n### 5. Essential Sections\n\nA well-structured CLAUDE.md should include:\n\n```markdown\n# Project Name\n\nBrief one-line description.\n\n## Tech Stack\n- Primary language and version\n- Key frameworks/libraries\n- Database/storage (if any)\n\n## Project Structure\n[Only for monorepos or complex structures]\n- `apps/` - Application entry points\n- `packages/` - Shared libraries\n\n## Development Commands\n- Install: `command`\n- Test: `command`\n- Build: `command`\n\n## Critical Conventions\n[Only non-obvious, high-impact conventions]\n- Convention 1 with brief explanation\n- Convention 2 with brief explanation\n\n## Known Issues / Gotchas\n[Things that consistently trip up developers]\n- Issue 1\n- Issue 2\n```\n\n### 6. Anti-Patterns to Avoid\n\n**DO NOT include:**\n- Code style guidelines (use linters)\n- Documentation on how to use Claude\n- Long explanations of obvious patterns\n- Copy-pasted code examples\n- Generic best practices (\"write clean code\")\n- Instructions for specific tasks\n- Auto-generated content\n- Extensive TODO lists\n\n### 7. Validation Checklist\n\nBefore finalizing, verify:\n\n- [ ] Kept under 200 lines; shorter is better\n- [ ] Every line applies to ALL sessions\n- [ ] No style/formatting rules\n- [ ] No code snippets (use file references)\n- [ ] Commands are verified to work\n- [ ] Progressive disclosure used for complex projects\n- [ ] Critical gotchas are documented\n- [ ] No redundancy with README.md\n\n## Output Format\n\n### For `create` or default:\n\n1. Analyze the project\n2. Draft a CLAUDE.md following the structure above\n3. Present the draft for review\n4. Write to the appropriate location after approval\n\n### For `update`:\n\n1. Read existing CLAUDE.md\n2. Audit against best practices\n3. Identify:\n   - Content to remove (style rules, code snippets, task-specific)\n   - Content to condense\n   - Missing essential information\n4. Present changes for review\n5. Apply changes after approval\n\n### For `audit`:\n\n1. Read existing CLAUDE.md\n2. Generate a report with:\n   - Current line count vs target\n   - Percentage of universally-applicable content\n   - List of anti-patterns found\n   - Recommendations for improvement\n3. Do NOT modify the file, only report\n\n## AGENTS.md Handling\n\nIf the user requests AGENTS.md creation/update:\n\n**Since v2.1.277, Claude Code reads `AGENTS.md` directly as project instructions** — but only when the working directory and every directory above it contain no `CLAUDE.md`, `.claude/CLAUDE.md`, or `CLAUDE.local.md`. `~/.claude/CLAUDE.md`, managed CLAUDE.md, and `.claude/rules/` do not count for that check and keep loading alongside. Which files are read is controlled by **Project instructions** in `/config`: `claude-md-or-agents-md` (default), `claude-md-and-agents-md`, `claude-md`, or `managed-only`. Where direct reading is unavailable — versions before v2.1.277 (before v2.1.281 on Bedrock/Vertex/Foundry, LLM gateways, or with telemetry disabled), or the first session after upgrading — fall back to importing it from CLAUDE.md with `@AGENTS.md`, or symlinking `CLAUDE.md` to it.\n\nAGENTS.md is a cross-tool project-context file — the same *category* of document as CLAUDE.md, not an agent-definition format. It exists so several coding agents can share one set of project conventions:\n- Build, test, and lint commands\n- Code style and architectural conventions\n- Repository layout and where things live\n\nSubagents are defined separately, in `.claude/agents/*.md` — not in AGENTS.md.\n\nApply similar principles:\n- Keep focused and concise\n- Use progressive disclosure\n- Reference external docs instead of embedding content\n\n## Notes\n\n- Always verify commands work before including them\n- When in doubt, leave it out - less is more\n- The system reminder tells Claude that CLAUDE.md \"may or may not be relevant\" - the more noise, the more it gets ignored\n- Monorepos benefit most from clear WHAT/WHY/HOW structure\n- Directory-specific CLAUDE.md files should be even more focused\n\n---\n\n**Last Updated**: October 18, 2026\n**Claude Code Version**: 2.1.302\n**Sources**:\n- https://code.claude.com/docs/en/skills\n- https://code.claude.com/docs/en/memory#agents-md\n- https://code.claude.com/docs/en/memory#when-agents-md-support-is-unavailable\n- https://code.claude.com/docs/en/memory\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","03-skills/code-review-specialist/SKILL.md":"---\nname: code-review-specialist\ndescription: Comprehensive code review with security, performance, and quality analysis. Use when users ask to review code, analyze code quality, evaluate pull requests, or mention code review, security analysis, or performance optimization.\n---\n\n# Code Review Skill\n\nThis skill provides comprehensive code review capabilities focusing on:\n\n1. **Security Analysis**\n   - Authentication/authorization issues\n   - Data exposure risks\n   - Injection vulnerabilities\n   - Cryptographic weaknesses\n   - Sensitive data logging\n\n2. **Performance Review**\n   - Algorithm efficiency (Big O analysis)\n   - Memory optimization\n   - Database query optimization\n   - Caching opportunities\n   - Concurrency issues\n\n3. **Code Quality**\n   - SOLID principles\n   - Design patterns\n   - Naming conventions\n   - Documentation\n   - Test coverage\n\n4. **Maintainability**\n   - Code readability\n   - Function size (should be < 50 lines)\n   - Cyclomatic complexity\n   - Dependency management\n   - Type safety\n\n## Reference Files\n\nThis skill includes supporting files that you should read when performing reviews:\n\n- **`templates/review-checklist.md`** — Structured checklist covering security, performance, quality, and testing. Read this file and use it as a guide to ensure no category is missed during review.\n- **`templates/finding-template.md`** — Standard template for documenting individual findings with severity, location, code examples, and impact analysis. Read this file and use its format when reporting issues.\n- **`scripts/analyze-metrics.py`** — Python script that calculates code metrics (function count, class count, average line length, complexity score). Run this on the file under review to gather quantitative data.\n- **`scripts/compare-complexity.py`** — Python script that compares cyclomatic and cognitive complexity between two versions of a file. Run this with the before and after versions when reviewing refactoring changes.\n\n## Review Template\n\nFor each piece of code reviewed, provide:\n\n### Summary\n- Overall quality assessment (1-5)\n- Key findings count\n- Recommended priority areas\n\n### Critical Issues (if any)\n- **Issue**: Clear description\n- **Location**: File and line number\n- **Impact**: Why this matters\n- **Severity**: Critical/High/Medium\n- **Fix**: Code example\n\n### Findings by Category\n\n#### Security (if issues found)\nList security vulnerabilities with examples\n\n#### Performance (if issues found)\nList performance problems with complexity analysis\n\n#### Quality (if issues found)\nList code quality issues with refactoring suggestions\n\n#### Maintainability (if issues found)\nList maintainability problems with improvements\n\n## Version History\n\n- v1.0.0 (2024-12-10): Initial release with security, performance, quality, and maintainability analysis\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","03-skills/doc-generator/SKILL.md":"---\nname: doc-generator\ndescription: Generate comprehensive, accurate API documentation from source code. Use when creating or updating API documentation, generating OpenAPI specs, or when users mention API docs, endpoints, or documentation.\n---\n\n# API Documentation Generator Skill\n\n## Generates\n\n- OpenAPI/Swagger specifications\n- API endpoint documentation\n- SDK usage examples\n- Integration guides\n- Error code references\n- Authentication guides\n\n## Documentation Structure\n\n### For Each Endpoint\n\n````markdown\n## GET /api/v1/users/:id\n\n### Description\nBrief explanation of what this endpoint does\n\n### Parameters\n\n| Name | Type | Required | Description |\n|------|------|----------|-------------|\n| id | string | Yes | User ID |\n\n### Response\n\n**200 Success**\n```json\n{\n  \"id\": \"usr_123\",\n  \"name\": \"John Doe\",\n  \"email\": \"john@example.com\",\n  \"created_at\": \"2025-01-15T10:30:00Z\"\n}\n```\n\n**404 Not Found**\n```json\n{\n  \"error\": \"USER_NOT_FOUND\",\n  \"message\": \"User does not exist\"\n}\n```\n\n### Examples\n\n**cURL**\n```bash\ncurl -X GET \"https://api.example.com/api/v1/users/usr_123\" \\\n  -H \"Authorization: Bearer YOUR_TOKEN\"\n```\n\n**JavaScript**\n```javascript\nconst user = await fetch('/api/v1/users/usr_123', {\n  headers: { 'Authorization': 'Bearer token' }\n}).then(r => r.json());\n```\n\n**Python**\n```python\nresponse = requests.get(\n    'https://api.example.com/api/v1/users/usr_123',\n    headers={'Authorization': 'Bearer token'}\n)\nuser = response.json()\n```\n````\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","03-skills/refactor/SKILL.md":"---\nname: refactor\ndescription: Systematic code refactoring based on Martin Fowler's methodology. Use when users ask to refactor code, improve code structure, reduce technical debt, clean up legacy code, eliminate code smells, or improve code maintainability. This skill guides through a phased approach with research, planning, and safe incremental implementation.\n---\n\n# Code Refactoring Skill\n\nA systematic approach to refactoring code based on Martin Fowler's *Refactoring: Improving the Design of Existing Code* (2nd Edition). This skill emphasizes safe, incremental changes backed by tests.\n\n> \"Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure.\" — Martin Fowler\n\n## Core Principles\n\n1. **Behavior Preservation**: External behavior must remain unchanged\n2. **Small Steps**: Make tiny, testable changes\n3. **Test-Driven**: Tests are the safety net\n4. **Continuous**: Refactoring is ongoing, not a one-time event\n5. **Collaborative**: User approval required at each phase\n\n## Workflow Overview\n\n```\nPhase 1: Research & Analysis\n    ↓\nPhase 2: Test Coverage Assessment\n    ↓\nPhase 3: Code Smell Identification\n    ↓\nPhase 4: Refactoring Plan Creation\n    ↓\nPhase 5: Incremental Implementation\n    ↓\nPhase 6: Review & Iteration\n```\n\n---\n\n## Phase 1: Research & Analysis\n\n### Objectives\n- Understand the codebase structure and purpose\n- Identify the scope of refactoring\n- Gather context about business requirements\n\n### Questions to Ask User\nBefore starting, clarify:\n\n1. **Scope**: Which files/modules/functions need refactoring?\n2. **Goals**: What problems are you trying to solve? (readability, performance, maintainability)\n3. **Constraints**: Are there any areas that should NOT be changed?\n4. **Timeline pressure**: Is this blocking other work?\n5. **Test status**: Do tests exist? Are they passing?\n\n### Actions\n- [ ] Read and understand the target code\n- [ ] Identify dependencies and integrations\n- [ ] Document current architecture\n- [ ] Note any existing technical debt markers (TODOs, FIXMEs)\n\n### Output\nPresent findings to user:\n- Code structure summary\n- Identified problem areas\n- Initial recommendations\n- **Request approval to proceed**\n\n---\n\n## Phase 2: Test Coverage Assessment\n\n### Why Tests Matter\n> \"Refactoring without tests is like driving without a seatbelt.\" — Martin Fowler\n\nTests are the **key enabler** of safe refactoring. Without them, you risk introducing bugs.\n\n### Assessment Steps\n\n1. **Check for existing tests**\n   ```bash\n   # Look for test files\n   find . -name \"*test*\" -o -name \"*spec*\" | head -20\n   ```\n\n2. **Run existing tests**\n   ```bash\n   # JavaScript/TypeScript\n   npm test\n\n   # Python\n   pytest -v\n\n   # Java\n   mvn test\n   ```\n\n3. **Check coverage (if available)**\n   ```bash\n   # JavaScript\n   npm run test:coverage\n\n   # Python\n   pytest --cov=.\n   ```\n\n### Decision Point: Ask User\n\n**If tests exist and pass:**\n- Proceed to Phase 3\n\n**If tests are missing or incomplete:**\nPresent options:\n1. Write tests first (recommended)\n2. Add tests incrementally during refactoring\n3. Proceed without tests (risky - requires user acknowledgment)\n\n**If tests are failing:**\n- STOP. Fix failing tests before refactoring\n- Ask user: Should we fix tests first?\n\n### Test Writing Guidelines (if needed)\n\nFor each function being refactored, ensure tests cover:\n- Happy path (normal operation)\n- Edge cases (empty inputs, null, boundaries)\n- Error scenarios (invalid inputs, exceptions)\n\nUse the \"red-green-refactor\" cycle:\n1. Write failing test (red)\n2. Make it pass (green)\n3. Refactor\n\n---\n\n## Phase 3: Code Smell Identification\n\n### What Are Code Smells?\nSymptoms of deeper problems in code. They're not bugs, but indicators that the code could be improved.\n\n### Common Code Smells to Check\n\nSee [references/code-smells.md](references/code-smells.md) for the complete catalog.\n\n#### Quick Reference\n\n| Smell | Signs | Impact |\n|-------|-------|--------|\n| **Long Method** | Methods > 30-50 lines | Hard to understand, test, maintain |\n| **Duplicated Code** | Same logic in multiple places | Bug fixes needed in multiple places |\n| **Large Class** | Class with too many responsibilities | Violates Single Responsibility |\n| **Feature Envy** | Method uses another class's data more | Poor encapsulation |\n| **Primitive Obsession** | Overuse of primitives instead of objects | Missing domain concepts |\n| **Long Parameter List** | Methods with 4+ parameters | Hard to call correctly |\n| **Data Clumps** | Same data items appearing together | Missing abstraction |\n| **Switch Statements** | Complex switch/if-else chains | Hard to extend |\n| **Speculative Generality** | Code \"just in case\" | Unnecessary complexity |\n| **Dead Code** | Unused code | Confusion, maintenance burden |\n\n### Analysis Steps\n\n1. **Automated Analysis** (if scripts available)\n   ```bash\n   python scripts/detect-smells.py <file>\n   ```\n\n2. **Manual Review**\n   - Walk through code systematically\n   - Note each smell with location and severity\n   - Categorize by impact (Critical/High/Medium/Low)\n\n3. **Prioritization**\n   Focus on smells that:\n   - Block current development\n   - Cause bugs or confusion\n   - Affect most-changed code paths\n\n### Output: Smell Report\n\nPresent to user:\n- List of identified smells with locations\n- Severity assessment for each\n- Recommended priority order\n- **Request approval on priorities**\n\n---\n\n## Phase 4: Refactoring Plan Creation\n\n### Selecting Refactorings\n\nFor each smell, select an appropriate refactoring from the catalog.\n\nSee [references/refactoring-catalog.md](references/refactoring-catalog.md) for the complete list.\n\n#### Smell-to-Refactoring Mapping\n\n| Code Smell | Recommended Refactoring(s) |\n|------------|---------------------------|\n| Long Method | Extract Method, Replace Temp with Query |\n| Duplicated Code | Extract Method, Pull Up Method, Form Template Method |\n| Large Class | Extract Class, Extract Subclass |\n| Feature Envy | Move Method, Move Field |\n| Primitive Obsession | Replace Primitive with Object, Replace Type Code with Class |\n| Long Parameter List | Introduce Parameter Object, Preserve Whole Object |\n| Data Clumps | Extract Class, Introduce Parameter Object |\n| Switch Statements | Replace Conditional with Polymorphism |\n| Speculative Generality | Collapse Hierarchy, Inline Class, Remove Dead Code |\n| Dead Code | Remove Dead Code |\n\n### Plan Structure\n\nUse the template at [templates/refactoring-plan.md](templates/refactoring-plan.md).\n\nFor each refactoring:\n1. **Target**: What code will change\n2. **Smell**: What problem it addresses\n3. **Refactoring**: Which technique to apply\n4. **Steps**: Detailed micro-steps\n5. **Risks**: What could go wrong\n6. **Rollback**: How to undo if needed\n\n### Phased Approach\n\n**CRITICAL**: Introduce refactoring gradually in phases.\n\n**Phase A: Quick Wins** (Low risk, high value)\n- Rename variables for clarity\n- Extract obvious duplicate code\n- Remove dead code\n\n**Phase B: Structural Improvements** (Medium risk)\n- Extract methods from long functions\n- Introduce parameter objects\n- Move methods to appropriate classes\n\n**Phase C: Architectural Changes** (Higher risk)\n- Replace conditionals with polymorphism\n- Extract classes\n- Introduce design patterns\n\n### Decision Point: Present Plan to User\n\nBefore implementation:\n- Show complete refactoring plan\n- Explain each phase and its risks\n- Get explicit approval for each phase\n- **Ask**: \"Should I proceed with Phase A?\"\n\n---\n\n## Phase 5: Incremental Implementation\n\n### The Golden Rule\n> \"Change → Test → Green? → Commit → Next step\"\n\n### Implementation Rhythm\n\nFor each refactoring step:\n\n1. **Pre-check**\n   - Tests are passing (green)\n   - Code compiles\n\n2. **Make ONE small change**\n   - Follow the mechanics from the catalog\n   - Keep changes minimal\n\n3. **Verify**\n   - Run tests immediately\n   - Check for compilation errors\n\n4. **If tests pass (green)**\n   - Commit with descriptive message\n   - Move to next step\n\n5. **If tests fail (red)**\n   - STOP immediately\n   - Undo the change\n   - Analyze what went wrong\n   - Ask user if unclear\n\n### Commit Strategy\n\nEach commit should be:\n- **Atomic**: One logical change\n- **Reversible**: Easy to revert\n- **Descriptive**: Clear commit message\n\nExample commit messages:\n```\nrefactor: Extract calculateTotal() from processOrder()\nrefactor: Rename 'x' to 'customerCount' for clarity\nrefactor: Remove unused validateOldFormat() method\n```\n\n### Progress Reporting\n\nAfter each sub-phase, report to user:\n- Changes made\n- Tests still passing?\n- Any issues encountered\n- **Ask**: \"Continue with next batch?\"\n\n---\n\n## Phase 6: Review & Iteration\n\n### Post-Refactoring Checklist\n\n- [ ] All tests passing\n- [ ] No new warnings/errors\n- [ ] Code compiles successfully\n- [ ] Behavior unchanged (manual verification)\n- [ ] Documentation updated if needed\n- [ ] Commit history is clean\n\n### Metrics Comparison\n\nRun complexity analysis before and after:\n```bash\npython scripts/analyze-complexity.py <file>\n```\n\nPresent improvements:\n- Lines of code change\n- Cyclomatic complexity change\n- Maintainability index change\n\n### User Review\n\nPresent final results:\n- Summary of all changes\n- Before/after code comparison\n- Metrics improvements\n- Remaining technical debt\n- **Ask**: \"Are you satisfied with these changes?\"\n\n### Next Steps\n\nDiscuss with user:\n- Additional smells to address?\n- Schedule follow-up refactoring?\n- Apply similar changes elsewhere?\n\n---\n\n## Important Guidelines\n\n### When to STOP and Ask\n\nAlways pause and consult user when:\n- Unsure about business logic\n- Change might affect external APIs\n- Test coverage is inadequate\n- Significant architectural decision needed\n- Risk level increases\n- You encounter unexpected complexity\n\n### Safety Rules\n\n1. **Never refactor without tests** (unless user explicitly acknowledges risk)\n2. **Never make big changes** - break into tiny steps\n3. **Never skip the test run** after each change\n4. **Never continue if tests fail** - fix or rollback first\n5. **Never assume** - when in doubt, ask\n\n### What NOT to Do\n\n- Don't combine refactoring with feature additions\n- Don't refactor during production emergencies\n- Don't refactor code you don't understand\n- Don't over-engineer - keep it simple\n- Don't refactor everything at once\n\n---\n\n## Quick Start Example\n\n### Scenario: Long Method with Duplication\n\n**Before:**\n```javascript\nfunction processOrder(order) {\n  // 150 lines of code with:\n  // - Duplicated validation logic\n  // - Inline calculations\n  // - Mixed responsibilities\n}\n```\n\n**Refactoring Steps:**\n\n1. **Ensure tests exist** for processOrder()\n2. **Extract** validation into validateOrder()\n3. **Test** - should pass\n4. **Extract** calculation into calculateOrderTotal()\n5. **Test** - should pass\n6. **Extract** notification into notifyCustomer()\n7. **Test** - should pass\n8. **Review** - processOrder() now orchestrates 3 clear functions\n\n**After:**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const total = calculateOrderTotal(order);\n  notifyCustomer(order, total);\n  return { order, total };\n}\n```\n\n---\n\n## References\n\n- [Code Smells Catalog](references/code-smells.md) - Complete list of code smells\n- [Refactoring Catalog](references/refactoring-catalog.md) - Refactoring techniques\n- [Refactoring Plan Template](templates/refactoring-plan.md) - Planning template\n\n## Scripts\n\n- `scripts/analyze-complexity.py` - Analyze code complexity metrics\n- `scripts/detect-smells.py` - Automated smell detection\n\n## Version History\n\n- v1.0.0 (2025-01-15): Initial release with Fowler methodology, phased approach, user consultation points\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","03-skills/refactor/references/code-smells.md":"# Code Smells Catalog\n\nA comprehensive reference of code smells based on Martin Fowler's *Refactoring* (2nd Edition). Code smells are symptoms of deeper problems—they indicate that something might be wrong with your code's design.\n\n> \"A code smell is a surface indication that usually corresponds to a deeper problem in the system.\" — Martin Fowler\n\n---\n\n## Bloaters\n\nCode smells representing something that has grown too large to be handled effectively.\n\n### Long Method\n\n**Signs:**\n- Method exceeds 30-50 lines\n- Need to scroll to see the whole method\n- Multiple levels of nesting\n- Comments explaining what sections do\n\n**Why it's bad:**\n- Hard to understand\n- Difficult to test in isolation\n- Changes have unintended consequences\n- Duplicate logic hides inside\n\n**Refactorings:**\n- Extract Method\n- Replace Temp with Query\n- Introduce Parameter Object\n- Replace Method with Method Object\n- Decompose Conditional\n\n**Example (Before):**\n```javascript\nfunction processOrder(order) {\n  // Validate order (20 lines)\n  if (!order.items) throw new Error('No items');\n  if (order.items.length === 0) throw new Error('Empty order');\n  // ... more validation\n\n  // Calculate totals (30 lines)\n  let subtotal = 0;\n  for (const item of order.items) {\n    subtotal += item.price * item.quantity;\n  }\n  // ... tax, shipping, discounts\n\n  // Send notifications (20 lines)\n  // ... email logic\n}\n```\n\n**Example (After):**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const totals = calculateOrderTotals(order);\n  sendOrderNotifications(order, totals);\n  return { order, totals };\n}\n```\n\n---\n\n### Large Class\n\n**Signs:**\n- Class has many instance variables (>7-10)\n- Class has many methods (>15-20)\n- Class name is vague (Manager, Handler, Processor)\n- Methods don't use all instance variables\n\n**Why it's bad:**\n- Violates Single Responsibility Principle\n- Hard to test\n- Changes ripple through unrelated features\n- Difficult to reuse parts\n\n**Refactorings:**\n- Extract Class\n- Extract Subclass\n- Extract Interface\n\n**Detection:**\n```\nLines of code > 300\nNumber of methods > 15\nNumber of fields > 10\n```\n\n---\n\n### Primitive Obsession\n\n**Signs:**\n- Using primitives for domain concepts (string for email, int for money)\n- Arrays of primitives instead of objects\n- String constants for type codes\n- Magic numbers/strings\n\n**Why it's bad:**\n- No validation at type level\n- Logic scattered across codebase\n- Easy to pass wrong values\n- Missing domain concepts\n\n**Refactorings:**\n- Replace Primitive with Object\n- Replace Type Code with Class\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**Example (Before):**\n```javascript\nconst user = {\n  email: 'john@example.com',     // Just a string\n  phone: '1234567890',           // Just a string\n  status: 'active',              // Magic string\n  balance: 10050                 // Cents as integer\n};\n```\n\n**Example (After):**\n```javascript\nconst user = {\n  email: new Email('john@example.com'),\n  phone: new PhoneNumber('1234567890'),\n  status: UserStatus.ACTIVE,\n  balance: Money.cents(10050)\n};\n```\n\n---\n\n### Long Parameter List\n\n**Signs:**\n- Methods with 4+ parameters\n- Parameters that always appear together\n- Boolean flags changing method behavior\n- Null/undefined passed frequently\n\n**Why it's bad:**\n- Hard to call correctly\n- Parameter order confusion\n- Indicates method doing too much\n- Hard to add new parameters\n\n**Refactorings:**\n- Introduce Parameter Object\n- Preserve Whole Object\n- Replace Parameter with Method Call\n- Remove Flag Argument\n\n**Example (Before):**\n```javascript\nfunction createUser(firstName, lastName, email, phone,\n                    street, city, state, zip,\n                    isAdmin, isActive, createdBy) {\n  // ...\n}\n```\n\n**Example (After):**\n```javascript\nfunction createUser(personalInfo, address, options) {\n  // personalInfo: { firstName, lastName, email, phone }\n  // address: { street, city, state, zip }\n  // options: { isAdmin, isActive, createdBy }\n}\n```\n\n---\n\n### Data Clumps\n\n**Signs:**\n- Same 3+ fields appear together repeatedly\n- Parameters that always travel together\n- Classes with field subsets belonging together\n\n**Why it's bad:**\n- Duplicate handling logic\n- Missing abstraction\n- Harder to extend\n- Indicates hidden class\n\n**Refactorings:**\n- Extract Class\n- Introduce Parameter Object\n- Preserve Whole Object\n\n**Example:**\n```javascript\n// Data clump: (x, y, z) coordinates\nfunction movePoint(x, y, z, dx, dy, dz) { }\nfunction scalePoint(x, y, z, factor) { }\nfunction distanceBetween(x1, y1, z1, x2, y2, z2) { }\n\n// Extract Point3D class\nclass Point3D {\n  constructor(x, y, z) { }\n  move(delta) { }\n  scale(factor) { }\n  distanceTo(other) { }\n}\n```\n\n---\n\n## Object-Orientation Abusers\n\nSmells indicating incomplete or incorrect use of OOP principles.\n\n### Switch Statements\n\n**Signs:**\n- Long switch/case or if/else chains\n- Same switch in multiple places\n- Switch on type codes\n- Adding new cases requires changes everywhere\n\n**Why it's bad:**\n- Violates Open/Closed Principle\n- Changes ripple to all switch locations\n- Hard to extend\n- Often indicates missing polymorphism\n\n**Refactorings:**\n- Replace Conditional with Polymorphism\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**Example (Before):**\n```javascript\nfunction calculatePay(employee) {\n  switch (employee.type) {\n    case 'hourly':\n      return employee.hours * employee.rate;\n    case 'salaried':\n      return employee.salary / 12;\n    case 'commissioned':\n      return employee.sales * employee.commission;\n  }\n}\n```\n\n**Example (After):**\n```javascript\nclass HourlyEmployee {\n  calculatePay() {\n    return this.hours * this.rate;\n  }\n}\n\nclass SalariedEmployee {\n  calculatePay() {\n    return this.salary / 12;\n  }\n}\n```\n\n---\n\n### Temporary Field\n\n**Signs:**\n- Instance variables only used in some methods\n- Fields set conditionally\n- Complex initialization for certain cases\n\n**Why it's bad:**\n- Confusing—field exists but might be null\n- Hard to understand object state\n- Indicates conditional logic hiding\n\n**Refactorings:**\n- Extract Class\n- Introduce Null Object\n- Replace Temp Field with Local\n\n---\n\n### Refused Bequest\n\n**Signs:**\n- Subclass doesn't use inherited methods/data\n- Subclass overrides to do nothing\n- Inheritance used for code reuse, not IS-A relationship\n\n**Why it's bad:**\n- Wrong abstraction\n- Violates Liskov Substitution Principle\n- Misleading hierarchy\n\n**Refactorings:**\n- Push Down Method/Field\n- Replace Subclass with Delegate\n- Replace Inheritance with Delegation\n\n---\n\n### Alternative Classes with Different Interfaces\n\n**Signs:**\n- Two classes that do similar things\n- Different method names for same concept\n- Could be used interchangeably\n\n**Why it's bad:**\n- Duplicate implementations\n- No common interface\n- Hard to switch between\n\n**Refactorings:**\n- Rename Method\n- Move Method\n- Extract Superclass\n- Extract Interface\n\n---\n\n## Change Preventers\n\nSmells that make changes difficult—changing one thing requires changing many others.\n\n### Divergent Change\n\n**Signs:**\n- One class changed for multiple different reasons\n- Changes in different areas trigger same class edits\n- Class is a \"God class\"\n\n**Why it's bad:**\n- Violates Single Responsibility\n- High change frequency\n- Merge conflicts\n\n**Refactorings:**\n- Extract Class\n- Extract Superclass\n- Extract Subclass\n\n**Example:**\nA `User` class changes for:\n- Authentication changes\n- Profile changes\n- Billing changes\n- Notification changes\n\n→ Extract: `AuthService`, `ProfileService`, `BillingService`, `NotificationService`\n\n---\n\n### Shotgun Surgery\n\n**Signs:**\n- One change requires edits in many classes\n- Small feature needs touching 10+ files\n- Changes are scattered, hard to find all\n\n**Why it's bad:**\n- Easy to miss a spot\n- High coupling\n- Changes are error-prone\n\n**Refactorings:**\n- Move Method\n- Move Field\n- Inline Class\n\n**Detection:**\nLook for: adding one field requires changes in >5 files.\n\n---\n\n### Parallel Inheritance Hierarchies\n\n**Signs:**\n- Creating subclass in one hierarchy requires subclass in another\n- Class prefixes match (e.g., `DatabaseOrder`, `DatabaseProduct`)\n\n**Why it's bad:**\n- Double the maintenance\n- Coupling between hierarchies\n- Easy to forget one side\n\n**Refactorings:**\n- Move Method\n- Move Field\n- Eliminate one hierarchy\n\n---\n\n## Dispensables\n\nSomething unnecessary that should be removed.\n\n### Comments (Excessive)\n\n**Signs:**\n- Comments explaining what code does\n- Commented-out code\n- TODO/FIXME that linger forever\n- Apologies in comments\n\n**Why it's bad:**\n- Comments lie (get out of sync)\n- Code should be self-documenting\n- Dead code causes confusion\n\n**Refactorings:**\n- Extract Method (name explains what)\n- Rename (clarity without comments)\n- Remove commented code\n- Introduce Assertion\n\n**Good vs Bad Comments:**\n```javascript\n// BAD: Explaining what\n// Loop through users and check if active\nfor (const user of users) {\n  if (user.status === 'active') { }\n}\n\n// GOOD: Explaining why\n// Active users only - inactive are handled by cleanup job\nconst activeUsers = users.filter(u => u.isActive);\n```\n\n---\n\n### Duplicate Code\n\n**Signs:**\n- Same code in multiple places\n- Similar code with small variations\n- Copy-paste patterns\n\n**Why it's bad:**\n- Bug fixes needed in multiple places\n- Inconsistency risk\n- Bloated codebase\n\n**Refactorings:**\n- Extract Method\n- Extract Class\n- Pull Up Method (in hierarchies)\n- Form Template Method\n\n**Detection Rule:**\nAny code duplicated 3+ times should be extracted.\n\n---\n\n### Lazy Class\n\n**Signs:**\n- Class doesn't do enough to justify existence\n- Wrapper with no added value\n- Result of over-engineering\n\n**Why it's bad:**\n- Maintenance overhead\n- Unnecessary indirection\n- Complexity without benefit\n\n**Refactorings:**\n- Inline Class\n- Collapse Hierarchy\n\n---\n\n### Dead Code\n\n**Signs:**\n- Unreachable code\n- Unused variables/methods/classes\n- Commented-out code\n- Code behind impossible conditions\n\n**Why it's bad:**\n- Confusion\n- Maintenance burden\n- Slows down understanding\n\n**Refactorings:**\n- Remove Dead Code\n- Safe Delete\n\n**Detection:**\n```bash\n# Look for unused exports\n# Look for unreferenced functions\n# IDE \"unused\" warnings\n```\n\n---\n\n### Speculative Generality\n\n**Signs:**\n- Abstract classes with one subclass\n- Unused parameters \"for future use\"\n- Methods that only delegate\n- \"Framework\" for one use case\n\n**Why it's bad:**\n- Complexity without benefit\n- YAGNI (You Ain't Gonna Need It)\n- Harder to understand\n\n**Refactorings:**\n- Collapse Hierarchy\n- Inline Class\n- Remove Parameter\n- Rename Method\n\n---\n\n## Couplers\n\nSmells that represent excessive coupling between classes.\n\n### Feature Envy\n\n**Signs:**\n- Method uses more data from another class than its own\n- Many getter calls to another object\n- Data and behavior are separated\n\n**Why it's bad:**\n- Wrong location for behavior\n- Poor encapsulation\n- Hard to maintain\n\n**Refactorings:**\n- Move Method\n- Move Field\n- Extract Method (then move)\n\n**Example (Before):**\n```javascript\nclass Order {\n  getDiscountedPrice(customer) {\n    // Uses customer data heavily\n    if (customer.loyaltyYears > 5) {\n      return this.price * customer.discountRate;\n    }\n    return this.price;\n  }\n}\n```\n\n**Example (After):**\n```javascript\nclass Customer {\n  getDiscountedPriceFor(price) {\n    if (this.loyaltyYears > 5) {\n      return price * this.discountRate;\n    }\n    return price;\n  }\n}\n```\n\n---\n\n### Inappropriate Intimacy\n\n**Signs:**\n- Classes access each other's private parts\n- Bidirectional references\n- Subclasses know too much about parents\n\n**Why it's bad:**\n- High coupling\n- Changes cascade\n- Hard to modify one without other\n\n**Refactorings:**\n- Move Method\n- Move Field\n- Change Bidirectional to Unidirectional\n- Extract Class\n- Hide Delegate\n\n---\n\n### Message Chains\n\n**Signs:**\n- Long chains of method calls: `a.getB().getC().getD().getValue()`\n- Client depends on navigation structure\n- \"Train wreck\" code\n\n**Why it's bad:**\n- Fragile—any change breaks chain\n- Violates Law of Demeter\n- Coupling to structure\n\n**Refactorings:**\n- Hide Delegate\n- Extract Method\n- Move Method\n\n**Example:**\n```javascript\n// Bad: Message chain\nconst managerName = employee.getDepartment().getManager().getName();\n\n// Better: Hide delegation\nconst managerName = employee.getManagerName();\n```\n\n---\n\n### Middle Man\n\n**Signs:**\n- Class that only delegates to another\n- Half the methods are delegations\n- No added value\n\n**Why it's bad:**\n- Unnecessary indirection\n- Maintenance overhead\n- Confusing architecture\n\n**Refactorings:**\n- Remove Middle Man\n- Inline Method\n\n---\n\n## Smell Severity Guide\n\n| Severity | Description | Action |\n|----------|-------------|--------|\n| **Critical** | Blocks development, causes bugs | Fix immediately |\n| **High** | Significant maintenance burden | Fix in current sprint |\n| **Medium** | Noticeable but manageable | Plan for near future |\n| **Low** | Minor inconvenience | Fix opportunistically |\n\n---\n\n## Quick Detection Checklist\n\nUse this checklist when scanning code:\n\n- [ ] Any method > 30 lines?\n- [ ] Any class > 300 lines?\n- [ ] Any method with > 4 parameters?\n- [ ] Any duplicated code blocks?\n- [ ] Any switch/case on type codes?\n- [ ] Any unused code?\n- [ ] Any methods using another class's data heavily?\n- [ ] Any long chains of method calls?\n- [ ] Any comments explaining \"what\" not \"why\"?\n- [ ] Any primitives that should be objects?\n\n---\n\n## Further Reading\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Kerievsky, J. (2004). *Refactoring to Patterns*\n- Feathers, M. (2004). *Working Effectively with Legacy Code*\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","03-skills/refactor/references/refactoring-catalog.md":"# Refactoring Catalog\n\nA curated catalog of refactoring techniques from Martin Fowler's *Refactoring* (2nd Edition). Each refactoring includes motivation, step-by-step mechanics, and examples.\n\n> \"A refactoring is defined by its mechanics—the precise sequence of steps that you follow to carry out the change.\" — Martin Fowler\n\n---\n\n## How to Use This Catalog\n\n1. **Identify the smell** using the code smells reference\n2. **Find the matching refactoring** in this catalog\n3. **Follow the mechanics** step by step\n4. **Test after each step** to ensure behavior is preserved\n\n**Golden Rule**: If any step takes more than 10 minutes, break it into smaller steps.\n\n---\n\n## Most Common Refactorings\n\n### Extract Method\n\n**When to use**: Long method, duplicate code, need to name a concept\n\n**Motivation**: Turn a code fragment into a method whose name explains the purpose.\n\n**Mechanics**:\n1. Create a new method named for what it does (not how)\n2. Copy the code fragment into the new method\n3. Scan for local variables used in the fragment\n4. Pass local variables as parameters (or declare in method)\n5. Handle return values appropriately\n6. Replace the original fragment with a call to the new method\n7. Test\n\n**Before**:\n```javascript\nfunction printOwing(invoice) {\n  let outstanding = 0;\n\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n\n  // Calculate outstanding\n  for (const order of invoice.orders) {\n    outstanding += order.amount;\n  }\n\n  // Print details\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n**After**:\n```javascript\nfunction printOwing(invoice) {\n  printBanner();\n  const outstanding = calculateOutstanding(invoice);\n  printDetails(invoice, outstanding);\n}\n\nfunction printBanner() {\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n}\n\nfunction calculateOutstanding(invoice) {\n  return invoice.orders.reduce((sum, order) => sum + order.amount, 0);\n}\n\nfunction printDetails(invoice, outstanding) {\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n---\n\n### Inline Method\n\n**When to use**: Method body is as clear as its name, excessive delegation\n\n**Motivation**: Remove needless indirection when the method doesn't add value.\n\n**Mechanics**:\n1. Check that the method isn't polymorphic\n2. Find all calls to the method\n3. Replace each call with the method body\n4. Test after each replacement\n5. Remove the method definition\n\n**Before**:\n```javascript\nfunction getRating(driver) {\n  return moreThanFiveLateDeliveries(driver) ? 2 : 1;\n}\n\nfunction moreThanFiveLateDeliveries(driver) {\n  return driver.numberOfLateDeliveries > 5;\n}\n```\n\n**After**:\n```javascript\nfunction getRating(driver) {\n  return driver.numberOfLateDeliveries > 5 ? 2 : 1;\n}\n```\n\n---\n\n### Extract Variable\n\n**When to use**: Complex expression that is hard to understand\n\n**Motivation**: Give a name to a piece of a complex expression.\n\n**Mechanics**:\n1. Ensure the expression has no side effects\n2. Declare an immutable variable\n3. Set it to the result of the expression (or part)\n4. Replace the original expression with the variable\n5. Test\n\n**Before**:\n```javascript\nreturn order.quantity * order.itemPrice -\n  Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +\n  Math.min(order.quantity * order.itemPrice * 0.1, 100);\n```\n\n**After**:\n```javascript\nconst basePrice = order.quantity * order.itemPrice;\nconst quantityDiscount = Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;\nconst shipping = Math.min(basePrice * 0.1, 100);\nreturn basePrice - quantityDiscount + shipping;\n```\n\n---\n\n### Inline Variable\n\n**When to use**: Variable name doesn't communicate more than the expression\n\n**Motivation**: Remove unnecessary indirection.\n\n**Mechanics**:\n1. Check that the right-hand side has no side effects\n2. If variable isn't immutable, make it so and test\n3. Find the first reference and replace with the expression\n4. Test\n5. Repeat for all references\n6. Remove the declaration and assignment\n7. Test\n\n---\n\n### Rename Variable\n\n**When to use**: Name doesn't clearly communicate purpose\n\n**Motivation**: Good names are crucial for clean code.\n\n**Mechanics**:\n1. If variable is widely used, consider encapsulating\n2. Find all references\n3. Change each reference\n4. Test\n\n**Tips**:\n- Use intention-revealing names\n- Avoid abbreviations\n- Use domain terminology\n\n```javascript\n// Bad\nconst d = 30;\nconst x = users.filter(u => u.a);\n\n// Good\nconst daysSinceLastLogin = 30;\nconst activeUsers = users.filter(user => user.isActive);\n```\n\n---\n\n### Change Function Declaration\n\n**When to use**: Function name doesn't explain purpose, parameters need change\n\n**Motivation**: Good function names make code self-documenting.\n\n**Mechanics (Simple)**:\n1. Remove parameters not needed\n2. Change the name\n3. Add parameters needed\n4. Test\n\n**Mechanics (Migration - for complex changes)**:\n1. If removing parameter, make sure it's not used\n2. Create new function with desired declaration\n3. Have old function call new function\n4. Test\n5. Change callers to use new function\n6. Test after each\n7. Remove old function\n\n**Before**:\n```javascript\nfunction circum(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n**After**:\n```javascript\nfunction circumference(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n---\n\n### Encapsulate Variable\n\n**When to use**: Direct access to data from multiple places\n\n**Motivation**: Provide a clear access point for data manipulation.\n\n**Mechanics**:\n1. Create getter and setter functions\n2. Find all references\n3. Replace reads with getter\n4. Replace writes with setter\n5. Test after each change\n6. Restrict visibility of the variable\n\n**Before**:\n```javascript\nlet defaultOwner = { firstName: \"Martin\", lastName: \"Fowler\" };\n\n// Used in many places\nspaceship.owner = defaultOwner;\n```\n\n**After**:\n```javascript\nlet defaultOwnerData = { firstName: \"Martin\", lastName: \"Fowler\" };\n\nfunction defaultOwner() { return defaultOwnerData; }\nfunction setDefaultOwner(arg) { defaultOwnerData = arg; }\n\nspaceship.owner = defaultOwner();\n```\n\n---\n\n### Introduce Parameter Object\n\n**When to use**: Several parameters that frequently go together\n\n**Motivation**: Group data that naturally belongs together.\n\n**Mechanics**:\n1. Create a new class/structure for the grouped parameters\n2. Test\n3. Use Change Function Declaration to add the new object\n4. Test\n5. For each parameter in the group, remove it from the function and use the new object\n6. Test after each\n\n**Before**:\n```javascript\nfunction amountInvoiced(startDate, endDate) { ... }\nfunction amountReceived(startDate, endDate) { ... }\nfunction amountOverdue(startDate, endDate) { ... }\n```\n\n**After**:\n```javascript\nclass DateRange {\n  constructor(start, end) {\n    this.start = start;\n    this.end = end;\n  }\n}\n\nfunction amountInvoiced(dateRange) { ... }\nfunction amountReceived(dateRange) { ... }\nfunction amountOverdue(dateRange) { ... }\n```\n\n---\n\n### Combine Functions into Class\n\n**When to use**: Several functions operate on the same data\n\n**Motivation**: Group functions with the data they operate on.\n\n**Mechanics**:\n1. Apply Encapsulate Record to the common data\n2. Move each function into the class\n3. Test after each move\n4. Replace data arguments with uses of class fields\n\n**Before**:\n```javascript\nfunction base(reading) { ... }\nfunction taxableCharge(reading) { ... }\nfunction calculateBaseCharge(reading) { ... }\n```\n\n**After**:\n```javascript\nclass Reading {\n  constructor(data) { this._data = data; }\n\n  get base() { ... }\n  get taxableCharge() { ... }\n  get calculateBaseCharge() { ... }\n}\n```\n\n---\n\n### Split Phase\n\n**When to use**: Code deals with two different things\n\n**Motivation**: Separate code into distinct phases with clear boundaries.\n\n**Mechanics**:\n1. Create a second function for the second phase\n2. Test\n3. Introduce an intermediate data structure between phases\n4. Test\n5. Extract first phase into its own function\n6. Test\n\n**Before**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  const shippingPerCase = (basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = quantity * shippingPerCase;\n  return basePrice - discount + shippingCost;\n}\n```\n\n**After**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const priceData = calculatePricingData(product, quantity);\n  return applyShipping(priceData, shippingMethod);\n}\n\nfunction calculatePricingData(product, quantity) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  return { basePrice, quantity, discount };\n}\n\nfunction applyShipping(priceData, shippingMethod) {\n  const shippingPerCase = (priceData.basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = priceData.quantity * shippingPerCase;\n  return priceData.basePrice - priceData.discount + shippingCost;\n}\n```\n\n---\n\n## Moving Features\n\n### Move Method\n\n**When to use**: Method uses more features of another class than its own\n\n**Motivation**: Put functions with the data they use most.\n\n**Mechanics**:\n1. Examine all program elements used by method in its class\n2. Check if method is polymorphic\n3. Copy method to target class\n4. Adjust for new context\n5. Make original method delegate to target\n6. Test\n7. Consider removing original method\n\n---\n\n### Move Field\n\n**When to use**: Field is used more by another class\n\n**Motivation**: Keep data with the functions that use it.\n\n**Mechanics**:\n1. Encapsulate the field if not already\n2. Test\n3. Create field in target\n4. Update references to use target field\n5. Test\n6. Remove original field\n\n---\n\n### Move Statements into Function\n\n**When to use**: Same code always appears with a function call\n\n**Motivation**: Remove duplication by moving repeated code into the function.\n\n**Mechanics**:\n1. Extract the repeated code into a function if not already\n2. Move statements into that function\n3. Test\n4. If callers no longer need standalone statements, remove them\n\n---\n\n### Move Statements to Callers\n\n**When to use**: Common behavior varies between callers\n\n**Motivation**: When behavior needs to differ, move it out of the function.\n\n**Mechanics**:\n1. Use Extract Method on the code to move\n2. Use Inline Method on the original function\n3. Remove the now-inlined call\n4. Move extracted code to each caller\n5. Test\n\n---\n\n## Organizing Data\n\n### Replace Primitive with Object\n\n**When to use**: Data item needs more behavior than simple value\n\n**Motivation**: Encapsulate data with its behavior.\n\n**Mechanics**:\n1. Apply Encapsulate Variable\n2. Create a simple value class\n3. Change the setter to create a new instance\n4. Change the getter to return the value\n5. Test\n6. Add richer behavior to the new class\n\n**Before**:\n```javascript\nclass Order {\n  constructor(data) {\n    this.priority = data.priority; // string: \"high\", \"rush\", etc.\n  }\n}\n\n// Usage\nif (order.priority === \"high\" || order.priority === \"rush\") { ... }\n```\n\n**After**:\n```javascript\nclass Priority {\n  constructor(value) {\n    if (!Priority.legalValues().includes(value))\n      throw new Error(`Invalid priority: ${value}`);\n    this._value = value;\n  }\n\n  static legalValues() { return ['low', 'normal', 'high', 'rush']; }\n  get value() { return this._value; }\n\n  higherThan(other) {\n    return Priority.legalValues().indexOf(this._value) >\n           Priority.legalValues().indexOf(other._value);\n  }\n}\n\n// Usage\nif (order.priority.higherThan(new Priority(\"normal\"))) { ... }\n```\n\n---\n\n### Replace Temp with Query\n\n**When to use**: Temporary variable holds result of an expression\n\n**Motivation**: Make the code clearer by extracting the expression into a function.\n\n**Mechanics**:\n1. Check that the variable is assigned only once\n2. Extract the assignment's right-hand side into a method\n3. Replace references to the temp with the method call\n4. Test\n5. Remove the temp declaration and assignment\n\n**Before**:\n```javascript\nconst basePrice = this._quantity * this._itemPrice;\nif (basePrice > 1000) {\n  return basePrice * 0.95;\n} else {\n  return basePrice * 0.98;\n}\n```\n\n**After**:\n```javascript\nget basePrice() {\n  return this._quantity * this._itemPrice;\n}\n\n// In the method\nif (this.basePrice > 1000) {\n  return this.basePrice * 0.95;\n} else {\n  return this.basePrice * 0.98;\n}\n```\n\n---\n\n## Simplifying Conditional Logic\n\n### Decompose Conditional\n\n**When to use**: Complex conditional (if-then-else) statement\n\n**Motivation**: Make the intention clear by extracting conditions and actions.\n\n**Mechanics**:\n1. Apply Extract Method on the condition\n2. Apply Extract Method on the then-branch\n3. Apply Extract Method on the else-branch (if present)\n\n**Before**:\n```javascript\nif (!aDate.isBefore(plan.summerStart) && !aDate.isAfter(plan.summerEnd)) {\n  charge = quantity * plan.summerRate;\n} else {\n  charge = quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n**After**:\n```javascript\nif (isSummer(aDate, plan)) {\n  charge = summerCharge(quantity, plan);\n} else {\n  charge = regularCharge(quantity, plan);\n}\n\nfunction isSummer(date, plan) {\n  return !date.isBefore(plan.summerStart) && !date.isAfter(plan.summerEnd);\n}\n\nfunction summerCharge(quantity, plan) {\n  return quantity * plan.summerRate;\n}\n\nfunction regularCharge(quantity, plan) {\n  return quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n---\n\n### Consolidate Conditional Expression\n\n**When to use**: Multiple conditions with the same result\n\n**Motivation**: Make it clear that conditions are a single check.\n\n**Mechanics**:\n1. Verify no side effects in conditions\n2. Combine conditions using `and` or `or`\n3. Consider Extract Method on the combined condition\n\n**Before**:\n```javascript\nif (employee.seniority < 2) return 0;\nif (employee.monthsDisabled > 12) return 0;\nif (employee.isPartTime) return 0;\n```\n\n**After**:\n```javascript\nif (isNotEligibleForDisability(employee)) return 0;\n\nfunction isNotEligibleForDisability(employee) {\n  return employee.seniority < 2 ||\n         employee.monthsDisabled > 12 ||\n         employee.isPartTime;\n}\n```\n\n---\n\n### Replace Nested Conditional with Guard Clauses\n\n**When to use**: Deeply nested conditionals making flow hard to follow\n\n**Motivation**: Use guard clauses for special cases, keeping normal flow clear.\n\n**Mechanics**:\n1. Find the special case conditions\n2. Replace them with guard clauses that return early\n3. Test after each change\n\n**Before**:\n```javascript\nfunction payAmount(employee) {\n  let result;\n  if (employee.isSeparated) {\n    result = { amount: 0, reasonCode: \"SEP\" };\n  } else {\n    if (employee.isRetired) {\n      result = { amount: 0, reasonCode: \"RET\" };\n    } else {\n      result = calculateNormalPay(employee);\n    }\n  }\n  return result;\n}\n```\n\n**After**:\n```javascript\nfunction payAmount(employee) {\n  if (employee.isSeparated) return { amount: 0, reasonCode: \"SEP\" };\n  if (employee.isRetired) return { amount: 0, reasonCode: \"RET\" };\n  return calculateNormalPay(employee);\n}\n```\n\n---\n\n### Replace Conditional with Polymorphism\n\n**When to use**: Switch/case based on type, conditional logic varying by type\n\n**Motivation**: Let objects handle their own behavior.\n\n**Mechanics**:\n1. Create class hierarchy (if not exists)\n2. Use Factory Function for object creation\n3. Move conditional logic into superclass method\n4. Create subclass method for each case\n5. Remove original conditional\n\n**Before**:\n```javascript\nfunction plumages(birds) {\n  return birds.map(b => plumage(b));\n}\n\nfunction plumage(bird) {\n  switch (bird.type) {\n    case 'EuropeanSwallow':\n      return \"average\";\n    case 'AfricanSwallow':\n      return (bird.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n    case 'NorwegianBlueParrot':\n      return (bird.voltage > 100) ? \"scorched\" : \"beautiful\";\n    default:\n      return \"unknown\";\n  }\n}\n```\n\n**After**:\n```javascript\nclass Bird {\n  get plumage() { return \"unknown\"; }\n}\n\nclass EuropeanSwallow extends Bird {\n  get plumage() { return \"average\"; }\n}\n\nclass AfricanSwallow extends Bird {\n  get plumage() {\n    return (this.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n  }\n}\n\nclass NorwegianBlueParrot extends Bird {\n  get plumage() {\n    return (this.voltage > 100) ? \"scorched\" : \"beautiful\";\n  }\n}\n\nfunction createBird(data) {\n  switch (data.type) {\n    case 'EuropeanSwallow': return new EuropeanSwallow(data);\n    case 'AfricanSwallow': return new AfricanSwallow(data);\n    case 'NorwegianBlueParrot': return new NorwegianBlueParrot(data);\n    default: return new Bird(data);\n  }\n}\n```\n\n---\n\n### Introduce Special Case (Null Object)\n\n**When to use**: Repeated null checks for special cases\n\n**Motivation**: Return a special object that handles the special case.\n\n**Mechanics**:\n1. Create special case class with expected interface\n2. Add isSpecialCase check\n3. Introduce factory method\n4. Replace null checks with special case object usage\n5. Test\n\n**Before**:\n```javascript\nconst customer = site.customer;\n// ... many places checking\nif (customer === \"unknown\") {\n  customerName = \"occupant\";\n} else {\n  customerName = customer.name;\n}\n```\n\n**After**:\n```javascript\nclass UnknownCustomer {\n  get name() { return \"occupant\"; }\n  get billingPlan() { return registry.defaultPlan; }\n}\n\n// Factory method\nfunction customer(site) {\n  return site.customer === \"unknown\"\n    ? new UnknownCustomer()\n    : site.customer;\n}\n\n// Usage - no null checks needed\nconst customerName = customer.name;\n```\n\n---\n\n## Refactoring APIs\n\n### Separate Query from Modifier\n\n**When to use**: Function both returns a value and has side effects\n\n**Motivation**: Make it clear which operations have side effects.\n\n**Mechanics**:\n1. Create a new query function\n2. Copy original function's return logic\n3. Modify original to return void\n4. Replace calls that use return value\n5. Test\n\n**Before**:\n```javascript\nfunction alertForMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") {\n      setOffAlarms();\n      return \"Don\";\n    }\n    if (p === \"John\") {\n      setOffAlarms();\n      return \"John\";\n    }\n  }\n  return \"\";\n}\n```\n\n**After**:\n```javascript\nfunction findMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") return \"Don\";\n    if (p === \"John\") return \"John\";\n  }\n  return \"\";\n}\n\nfunction alertForMiscreant(people) {\n  if (findMiscreant(people) !== \"\") setOffAlarms();\n}\n```\n\n---\n\n### Parameterize Function\n\n**When to use**: Several functions doing similar things with different values\n\n**Motivation**: Remove duplication by adding a parameter.\n\n**Mechanics**:\n1. Select one function\n2. Add parameter for the varying literal\n3. Change body to use the parameter\n4. Test\n5. Change callers to use the parameterized version\n6. Remove now-unused functions\n\n**Before**:\n```javascript\nfunction tenPercentRaise(person) {\n  person.salary = person.salary * 1.10;\n}\n\nfunction fivePercentRaise(person) {\n  person.salary = person.salary * 1.05;\n}\n```\n\n**After**:\n```javascript\nfunction raise(person, factor) {\n  person.salary = person.salary * (1 + factor);\n}\n\n// Usage\nraise(person, 0.10);\nraise(person, 0.05);\n```\n\n---\n\n### Remove Flag Argument\n\n**When to use**: Boolean parameter that changes function behavior\n\n**Motivation**: Make the behavior explicit through separate functions.\n\n**Mechanics**:\n1. Create explicit function for each flag value\n2. Replace each call with appropriate new function\n3. Test after each change\n4. Remove original function\n\n**Before**:\n```javascript\nfunction bookConcert(customer, isPremium) {\n  if (isPremium) {\n    // premium booking logic\n  } else {\n    // regular booking logic\n  }\n}\n\nbookConcert(customer, true);\nbookConcert(customer, false);\n```\n\n**After**:\n```javascript\nfunction bookPremiumConcert(customer) {\n  // premium booking logic\n}\n\nfunction bookRegularConcert(customer) {\n  // regular booking logic\n}\n\nbookPremiumConcert(customer);\nbookRegularConcert(customer);\n```\n\n---\n\n## Dealing with Inheritance\n\n### Pull Up Method\n\n**When to use**: Same method in multiple subclasses\n\n**Motivation**: Remove duplication in class hierarchy.\n\n**Mechanics**:\n1. Inspect methods to ensure they are identical\n2. Check signatures are the same\n3. Create new method in superclass\n4. Copy body from one subclass\n5. Delete one subclass method, test\n6. Delete other subclass methods, test each\n\n---\n\n### Push Down Method\n\n**When to use**: Behavior relevant only to a subset of subclasses\n\n**Motivation**: Put method where it's used.\n\n**Mechanics**:\n1. Copy method to each subclass that needs it\n2. Remove method from superclass\n3. Test\n4. Remove from subclasses that don't need it\n5. Test\n\n---\n\n### Replace Subclass with Delegate\n\n**When to use**: Inheritance is being used incorrectly, need more flexibility\n\n**Motivation**: Prefer composition over inheritance when appropriate.\n\n**Mechanics**:\n1. Create empty class for delegate\n2. Add field to host class holding delegate\n3. Create constructor for delegate, called from host\n4. Move features to delegate\n5. Test after each move\n6. Replace inheritance with delegation\n\n---\n\n## Extract Class\n\n**When to use**: Large class with multiple responsibilities\n\n**Motivation**: Split class to maintain single responsibility.\n\n**Mechanics**:\n1. Decide how to split responsibilities\n2. Create new class\n3. Move field from original to new class\n4. Test\n5. Move methods from original to new class\n6. Test after each move\n7. Review and rename both classes\n8. Decide how to expose new class\n\n**Before**:\n```javascript\nclass Person {\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get officeAreaCode() { return this._officeAreaCode; }\n  set officeAreaCode(arg) { this._officeAreaCode = arg; }\n  get officeNumber() { return this._officeNumber; }\n  set officeNumber(arg) { this._officeNumber = arg; }\n\n  get telephoneNumber() {\n    return `(${this._officeAreaCode}) ${this._officeNumber}`;\n  }\n}\n```\n\n**After**:\n```javascript\nclass Person {\n  constructor() {\n    this._telephoneNumber = new TelephoneNumber();\n  }\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get telephoneNumber() { return this._telephoneNumber.toString(); }\n  get officeAreaCode() { return this._telephoneNumber.areaCode; }\n  set officeAreaCode(arg) { this._telephoneNumber.areaCode = arg; }\n}\n\nclass TelephoneNumber {\n  get areaCode() { return this._areaCode; }\n  set areaCode(arg) { this._areaCode = arg; }\n  get number() { return this._number; }\n  set number(arg) { this._number = arg; }\n  toString() { return `(${this._areaCode}) ${this._number}`; }\n}\n```\n\n---\n\n## Quick Reference: Smell to Refactoring\n\n| Code Smell | Primary Refactoring | Alternative |\n|------------|-------------------|-------------|\n| Long Method | Extract Method | Replace Temp with Query |\n| Duplicate Code | Extract Method | Pull Up Method |\n| Large Class | Extract Class | Extract Subclass |\n| Long Parameter List | Introduce Parameter Object | Preserve Whole Object |\n| Feature Envy | Move Method | Extract Method + Move |\n| Data Clumps | Extract Class | Introduce Parameter Object |\n| Primitive Obsession | Replace Primitive with Object | Replace Type Code |\n| Switch Statements | Replace Conditional with Polymorphism | Replace Type Code |\n| Temporary Field | Extract Class | Introduce Null Object |\n| Message Chains | Hide Delegate | Extract Method |\n| Middle Man | Remove Middle Man | Inline Method |\n| Divergent Change | Extract Class | Split Phase |\n| Shotgun Surgery | Move Method | Inline Class |\n| Dead Code | Remove Dead Code | - |\n| Speculative Generality | Collapse Hierarchy | Inline Class |\n\n---\n\n## Further Reading\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Online catalog: https://refactoring.com/catalog/\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","07-plugins/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2FREADME.md -->","07-plugins/devops-automation/.claude-plugin/plugin.json":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fdevops-automation%2F.claude-plugin%2Fplugin.json -->","07-plugins/devops-automation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fdevops-automation%2FREADME.md -->","07-plugins/documentation/.claude-plugin/plugin.json":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fdocumentation%2F.claude-plugin%2Fplugin.json -->","07-plugins/documentation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fdocumentation%2FREADME.md -->","07-plugins/documentation/commands/generate-readme.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fdocumentation%2Fcommands%2Fgenerate-readme.md -->","07-plugins/pr-review/.claude-plugin/plugin.json":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fpr-review%2F.claude-plugin%2Fplugin.json -->","07-plugins/pr-review/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fpr-review%2FREADME.md -->","CLAUDE.md":"# CLAUDE.md\n\nTutorial repo. Output is markdown in numbered modules `01-` through `10-`, not an app. Scripts in `scripts/` exist only to validate docs and build the EPUB.\n\nSee also `.claude/CLAUDE.md` for stack/commands and `STYLE_GUIDE.md` for lesson structure.\n\n## Critical commands\n\n```bash\n# Quality gate (also runs on commit via pre-commit hooks)\npre-commit run --all-files\n\n# Tests\npytest scripts/tests/ -v\n\n# EPUB build (renders Mermaid with Pele — needs Node.js >= 20; the pinned bundle downloads once, then works offline)\nuv run scripts/build_epub.py\n\n# Python tooling\nruff check scripts/ && ruff format scripts/\nmypy scripts/ --ignore-missing-imports\nbandit -c scripts/pyproject.toml -r scripts/ --exclude scripts/tests/\n```\n\nPre-commit runs 5 doc checks on `.md` changes: markdown-lint, cross-references, mermaid-syntax, link-check, markdown-rendering. All must pass. The EPUB build is **not** a pre-commit hook — it runs in CI only (`build-epub` job in `.github/workflows/test.yml`), because it is a slow full-book build; the mermaid-syntax hook already renders every diagram with the same Pele bundle.\n\n## Architecture map\n\n- `01-` … `10-` — tutorial modules. **Numbered prefix = learning order**, not alphabetical. Do not reorganize.\n- Each module: `README.md` + copy-paste templates (`.md`, `.json`, `.sh`).\n- `scripts/` — utilities (EPUB builder, link/mermaid/cross-ref validators). Not the product.\n- `02-memory/*.md` — CLAUDE.md templates users copy into their own projects. Don't confuse with this file.\n- `openspec/` — spec-driven change proposals.\n\n## Hard rules\n\n- **YOU MUST NOT commit or push without explicit user request.**\n- **YOU MUST NOT add `Co-Authored-By: Claude`** to any commit message.\n- Always activate `.venv` before running Python scripts (check `venv/`, `.venv/`, `env/`).\n- Internal links use **relative paths** (e.g. `01-slash-commands/README.md`); anchors use `#heading-name`.\n- Code fences **must** declare a language (`bash`, `python`, `json`, …) — the cross-reference check fails otherwise.\n- External URLs must be reachable and stable. No ephemeral links.\n- Mermaid diagrams must render with Pele. The pre-commit mermaid hooks get Node.js 22 from pre-commit and run strict, so they fail instead of skipping; the first run needs network to download Node.js and the pinned Pele bundle (offline: `SKIP=mermaid,vietnamese-mermaid,japanese-mermaid`). Run by hand, `scripts/check_mermaid.py` only warns without Node.js >= 20, and fails under `--strict` or in CI. A broken EPUB build is usually invalid Mermaid, a missing Node.js >= 20, or a failed bundle download.\n- Commit format: `type(scope): subject` where `scope` matches the module folder (e.g. `feat(slash-commands):`, `docs(memory):`, `fix(README):`).\n- Do not reorganize the `01-`–`10-` numbering. The order is the curriculum.\n\n## Workflow preferences\n\n- For lesson edits, follow `STYLE_GUIDE.md` for structure/naming/diagrams.\n- Small fixes → minimal diff. Don't rewrite a section to fix a typo.\n- When adding a module page: README + templates first, then update root `README.md` index and `LEARNING-ROADMAP.md` if order/timing changes.\n- Tutorial > library: prioritize clear explanations and copy-paste examples over reusable abstractions.\n- If a quality check fails, fix the underlying issue. Don't bypass with `--no-verify`.\n\n## Token Efficiency\n- Never re-read files you just wrote or edited. You know the contents.\n- Never re-run commands to \"verify\" unless the outcome was uncertain.\n- Don't echo back large blocks of code or file contents unless asked.\n- Batch related edits into single operations. Don't make 5 edits when 1 handles it.\n- Skip confirmations like \"I'll continue...\" Just do it.\n- If a task needs 1 tool call, don't use 3. Plan before acting.\n- Do not summarize what you just did unless the result is ambiguous or you need additional input.\n","ja/03-skills/blog-draft/SKILL.md":"<!-- i18n-source: 03-skills/blog-draft/SKILL.md -->\n<!-- i18n-source-sha: f396788 -->\n<!-- i18n-date: 2026-04-27 -->\n\n---\nname: blog-draft\ndescription: アイデアとリソースからブログ記事の下書きを作成する。ブログ記事の執筆、リサーチからのコンテンツ作成、記事の下書き作成時に使用する。リサーチ、ブレインストーミング、アウトライン作成、バージョン管理付きの反復的な下書き作成を案内する。\n---\n\n## ユーザー入力\n\n```text\n$ARGUMENTS\n```\n\n進める前にユーザー入力を**必ず**考慮する。ユーザーは以下を提供すべきである。\n- **Idea/Topic**: ブログ記事の主要なコンセプトやテーマ\n- **Resources**: URL、ファイル、リサーチ用の参考情報（任意だが推奨）\n- **Target audience**: ブログ記事の対象読者（任意）\n- **Tone/Style**: フォーマル、カジュアル、技術的、など（任意）\n\n**重要**: ユーザーが**既存のブログ記事**の更新を要求している場合、ステップ 0-8 をスキップして直接**ステップ 9**から開始する。まず既存の下書きファイルを読み、その後で反復プロセスを進める。\n\n## 実行フロー\n\n以下のステップを順次実行する。**ステップをスキップしたり、指示された箇所でユーザー承認なしに進めたりしてはならない。**\n\n### Step 0: プロジェクトフォルダの作成\n\n1. 次の形式でフォルダ名を生成する: `YYYY-MM-DD-short-topic-name`\n   - 今日の日付を使用\n   - トピックから短く URL フレンドリーなスラッグを作成（小文字、ハイフン、最大 5 単語）\n\n2. フォルダ構造を作成:\n   ```\n   blog-posts/\n   └── YYYY-MM-DD-short-topic-name/\n       └── resources/\n   ```\n\n3. 進める前にフォルダ作成をユーザーに確認する。\n\n### Step 1: リサーチとリソース収集\n\n1. ブログ記事ディレクトリ内に `resources/` サブフォルダを作成\n\n2. 提供された各リソースに対して:\n   - **URLs**: 取得して主要情報を `resources/` にマークダウンファイルとして保存\n   - **Files**: 読み込んで `resources/` に要約\n   - **Topics**: ウェブ検索を使用して最新情報を収集\n\n3. 各リソースについて、`resources/` に要約ファイルを作成:\n   - `resources/source-1-[short-name].md`\n   - `resources/source-2-[short-name].md`\n   - など\n\n4. 各要約には以下を含める:\n   ```markdown\n   # Source: [Title/URL]\n\n   ## Key Points\n   - Point 1\n   - Point 2\n\n   ## Relevant Quotes/Data\n   - Quote or statistic 1\n   - Quote or statistic 2\n\n   ## How This Relates to Topic\n   関連性の簡潔な説明\n   ```\n\n5. リサーチの要約をユーザーに提示する。\n\n### Step 2: ブレインストーミングと明確化\n\n1. アイデアとリサーチしたリソースに基づき、以下を提示:\n   - リサーチから特定された**主要テーマ**\n   - ブログ記事の**取りうる切り口**\n   - カバーすべき**重要ポイント**\n   - 明確化が必要な情報の**ギャップ**\n\n2. 明確化のための質問:\n   - 読者に持って帰ってほしい主要なテイクアウェイは何か？\n   - リサーチの中で特に強調したい点はあるか？\n   - 目標の長さは？（short: 500-800 words、medium: 1000-1500、long: 2000+）\n   - 除外したい点はあるか？\n\n3. **進める前にユーザー応答を待つ。**\n\n### Step 3: アウトライン提案\n\n1. 以下を含む構造化されたアウトラインを作成:\n\n   ```markdown\n   # Blog Post Outline: [Title]\n\n   ## Meta Information\n   - **Target Audience**: [who]\n   - **Tone**: [style]\n   - **Target Length**: [word count]\n   - **Main Takeaway**: [key message]\n\n   ## Proposed Structure\n\n   ### Hook/Introduction\n   - Opening hook idea\n   - Context setting\n   - Thesis statement\n\n   ### Section 1: [Title]\n   - Key point A\n   - Key point B\n   - Supporting evidence from [source]\n\n   ### Section 2: [Title]\n   - Key point A\n   - Key point B\n\n   [全セクションについて続ける...]\n\n   ### Conclusion\n   - Summary of key points\n   - Call to action or final thought\n\n   ## Sources to Cite\n   - Source 1\n   - Source 2\n   ```\n\n2. アウトラインをユーザーに提示し、**承認または修正を求める**。\n\n### Step 4: 承認されたアウトラインの保存\n\n1. ユーザーがアウトラインを承認したら、ブログ記事フォルダ内の `OUTLINE.md` に保存する。\n\n2. アウトラインが保存されたことを確認する。\n\n### Step 5: アウトラインのコミット（git リポジトリの場合）\n\n1. カレントディレクトリが git リポジトリかどうか確認する。\n\n2. はいの場合:\n   - 新しいファイル（ブログ記事フォルダ、resources、OUTLINE.md）をステージング\n   - 次のメッセージでコミットを作成: `docs: Add outline for blog post - [topic-name]`\n   - リモートへプッシュ\n\n3. git リポジトリでない場合は、このステップをスキップしユーザーに伝える。\n\n### Step 6: 下書き作成\n\n1. 承認されたアウトラインに基づき、ブログ記事の下書き全文を作成する。\n\n2. OUTLINE.md の構造に厳密に従う。\n\n3. 含めるもの:\n   - フック付きの魅力的な導入\n   - 明確なセクション見出し\n   - リサーチからの裏付けとなる証拠と例\n   - セクション間の滑らかな遷移\n   - テイクアウェイのある力強い結論\n   - **Citations**: すべての比較、統計、データポイント、事実主張は元のソースを必ず引用すること\n\n4. 下書きをブログ記事フォルダ内に `draft-v0.1.md` として保存する。\n\n5. フォーマット:\n   ```markdown\n   # [Blog Post Title]\n\n   *[Optional: subtitle or tagline]*\n\n   [インライン引用付きの本文...]\n\n   ---\n\n   ## References\n   - [1] Source 1 Title - URL or Citation\n   - [2] Source 2 Title - URL or Citation\n   - [3] Source 3 Title - URL or Citation\n   ```\n\n6. **引用要件**:\n   - すべてのデータポイント、統計、比較にはインライン引用を必ず付ける\n   - [1]、[2] などの番号引用、または [Source Name] のような名前付き引用を使用\n   - 引用を末尾の References セクションへリンクする\n   - 例: \"Studies show that 65% of developers prefer TypeScript [1]\"\n   - 例: \"React outperforms Vue in rendering speed by 20% [React Benchmarks 2024]\"\n\n### Step 7: 下書きのコミット（git リポジトリの場合）\n\n1. git リポジトリかどうか確認する。\n\n2. はいの場合:\n   - 下書きファイルをステージング\n   - 次のメッセージでコミットを作成: `docs: Add draft v0.1 for blog post - [topic-name]`\n   - リモートへプッシュ\n\n3. git リポジトリでない場合は、スキップしてユーザーに伝える。\n\n### Step 8: レビュー用に下書きを提示\n\n1. 下書きの内容をユーザーに提示する。\n\n2. フィードバックを求める:\n   - 全体の印象は？\n   - 拡張または削減が必要なセクションは？\n   - トーン調整は必要か？\n   - 不足している情報は？\n   - 具体的な編集や書き直しは？\n\n3. **ユーザー応答を待つ。**\n\n### Step 9: 反復または最終化\n\n**ユーザーが変更を要求した場合:**\n1. すべての要望を記録する\n2. 以下の調整を加えてステップ 6 へ戻る:\n   - バージョン番号を増加（v0.2、v0.3 など）\n   - すべてのフィードバックを反映\n   - `draft-v[X.Y].md` として保存\n   - ステップ 7-8 を繰り返す\n\n**ユーザーが承認した場合:**\n1. 最終下書きのバージョンを確認\n2. ユーザーが要求すれば任意で `final.md` にリネーム\n3. ブログ記事作成プロセスを要約:\n   - 作成したバージョンの総数\n   - バージョン間の主要な変更\n   - 最終ワード数\n   - 作成したファイル\n\n## バージョン追跡\n\nすべての下書きは段階的なバージョン番号付きで保持する:\n- `draft-v0.1.md` - 初回下書き\n- `draft-v0.2.md` - 1 回目のフィードバック反映後\n- `draft-v0.3.md` - 2 回目のフィードバック反映後\n- など\n\nこれによりブログ記事の進化を追跡し、必要に応じて差し戻すことができる。\n\n## 出力ファイル構造\n\n```\nblog-posts/\n└── YYYY-MM-DD-topic-name/\n    ├── resources/\n    │   ├── source-1-name.md\n    │   ├── source-2-name.md\n    │   └── ...\n    ├── OUTLINE.md\n    ├── draft-v0.1.md\n    ├── draft-v0.2.md (反復した場合)\n    └── draft-v0.3.md (さらに反復した場合)\n```\n\n## 品質のためのヒント\n\n- **Hook**: 質問、意外な事実、共感できるシナリオで始める\n- **Flow**: 各段落は次の段落と接続させる\n- **Evidence**: リサーチデータで主張を裏付ける\n- **Citations**: 以下については必ずソースを引用する:\n  - すべての統計とデータポイント（例: \"According to [Source], 75% of...\"）\n  - 製品、サービス、アプローチ間の比較（例: \"X performs 2x faster than Y [Source]\"）\n  - 市場トレンド、リサーチ結果、ベンチマークについての事実主張\n  - 形式: [Source Name] または [Author, Year] のインライン引用を使用\n- **Voice**: 全体を通じて一貫したトーンを保つ\n- **Length**: 目標ワード数を尊重\n- **Readability**: 短い段落、適切な箇所での箇条書きを使用\n- **CTA**: 明確な CTA または考えさせる問いで終える\n\n## 注意事項\n\n- 指定されたチェックポイントでは必ずユーザー承認を待つ\n- 履歴のためすべての下書きバージョンを保持する\n- URL が提供された場合は最新情報のためウェブ検索を使用する\n- リソースが不十分な場合はユーザーに追加を求めるか、追加リサーチを提案する\n- 対象読者（技術系、一般、ビジネスなど）に応じてトーンを適応させる\n","ja/03-skills/brand-voice/SKILL.md":"<!-- i18n-source: 03-skills/brand-voice/SKILL.md -->\n<!-- i18n-source-sha: a6380d8 -->\n<!-- i18n-date: 2026-04-27 -->\n\n---\nname: brand-voice\ndescription: すべてのコミュニケーションがブランドボイスとトーンのガイドラインに沿うことを保証する。マーケティングコピー、顧客向け連絡、公開コンテンツの作成時、またはブランドボイス、トーン、文体について言及がある場合に使用する。\nuser-invocable: false\n---\n\n# ブランドボイス・スキル\n\n## 概要\nこのスキルは、すべてのコミュニケーションにおいて一貫したブランドボイス、トーン、メッセージングを維持する。\n\n## ブランドアイデンティティ\n\n### ミッション\nチームが AI で開発ワークフローを自動化することを支援する\n\n### バリュー\n- **シンプリシティ**: 複雑なものをシンプルにする\n- **信頼性**: 揺るぎない実行\n- **エンパワーメント**: 人間の創造性を引き出す\n\n### トーン・オブ・ボイス\n- **フレンドリーかつプロフェッショナル** - カジュアルにならず、親しみやすい\n- **明快で簡潔** - 専門用語を避け、技術的な概念をわかりやすく説明する\n- **自信を持って** - 自分たちが何をしているかを理解している\n- **共感的** - ユーザーのニーズと痛みを理解する\n\n## 執筆ガイドライン\n\n### やるべきこと ✅\n- 読者を指す際には「you」を使用\n- 能動態を使用: 「Claude generates reports」とし、「Reports are generated by Claude」としない\n- 価値提案から始める\n- 具体例を用いる\n- 1 文を 20 語未満に保つ\n- 明確化のためリストを使用\n- CTA（行動喚起）を含める\n\n### 避けるべきこと ❌\n- 企業ジャーゴンを使わない\n- 見下したり過度に単純化したりしない\n- 「we believe」や「we think」を使わない\n- 強調以外で全大文字を使わない\n- 文章の壁を作らない\n- 技術的な前提知識を仮定しない\n\n## ボキャブラリー\n\n### ✅ 推奨用語\n- Claude（「the Claude AI」ではなく）\n- Code generation（「auto-coding」ではなく）\n- Agent（「bot」ではなく）\n- Streamline（「revolutionize」ではなく）\n- Integrate（「synergize」ではなく）\n\n### ❌ 避ける用語\n- 「Cutting-edge」（使い古されている）\n- 「Game-changer」（曖昧）\n- 「Leverage」（企業用語的）\n- 「Utilize」（「use」を使う）\n- 「Paradigm shift」（不明瞭）\n\n## 例\n\n### ✅ 良い例\n\"Claude automates your code review process. Instead of manually checking each PR, Claude reviews security, performance, and quality—saving your team hours every week.\"\n\nなぜ機能するか: 明確な価値、具体的なメリット、行動志向\n\n### ❌ 悪い例\n\"Claude leverages cutting-edge AI to provide comprehensive software development solutions.\"\n\nなぜ機能しないか: 曖昧、企業ジャーゴン、具体的な価値がない\n","ja/03-skills/claude-md/SKILL.md":"<!-- i18n-source: 03-skills/claude-md/SKILL.md -->\n<!-- i18n-source-sha: f78c094 -->\n<!-- i18n-date: 2026-04-27 -->\n---\nname: claude-md\ndescription: Create or update CLAUDE.md files following best practices for optimal AI agent onboarding\n---\n\n## ユーザー入力\n\n```text\n$ARGUMENTS\n```\n\nユーザー入力が空でない場合、進める前に **必ず** 内容を考慮すること。ユーザーは以下を指定する場合がある:\n- `create` - 新しい CLAUDE.md をゼロから作成\n- `update` - 既存 CLAUDE.md を改善\n- `audit` - 現在の CLAUDE.md の品質を分析しレポート\n- 作成・更新する具体的なパス（例: ディレクトリ固有命令向けの `src/api/CLAUDE.md`）\n\n## 基本原則\n\n**LLM はステートレス**: CLAUDE.md は、すべての会話に読み込まれる主要なプロジェクトファイルである（自動メモリやスコープなしのルールと並んで読み込まれる）。コードベースに対する AI エージェントの主要なオンボーディングドキュメントとして機能する。\n\n### ゴールデンルール\n\n1. **少ないほど良い**: フロンティア LLM は約 150〜200 個の命令に従える。Claude Code のシステムプロンプトはすでに約 50 個を使用している。CLAUDE.md は焦点を絞り簡潔に保つこと。\n\n2. **普遍的な適用性**: あらゆるセッションに関係する情報のみを含める。タスク固有の命令は別ファイルに置く。\n\n3. **Claude をリンターとして使わない**: スタイルガイドラインはコンテキストを膨張させ命令の遵守を低下させる。代わりに決定論的なツール（prettier, eslint など）を使う。\n\n4. **絶対に自動生成しない**: CLAUDE.md は AI ハーネスにおける最も影響力の高いポイントである。慎重に手作業で作り上げること。\n\n## 実行フロー\n\n### 1. プロジェクト分析\n\nまず現在のプロジェクト状態を分析する:\n\n1. 既存の CLAUDE.md ファイルを確認:\n   - ルートレベル: `./CLAUDE.md` または `.claude/CLAUDE.md`\n   - ディレクトリ固有: `**/CLAUDE.md`\n   - グローバルユーザー設定: `~/.claude/CLAUDE.md`\n\n2. プロジェクト構造を特定:\n   - 技術スタック（言語、フレームワーク）\n   - プロジェクト種別（モノレポ、単一アプリ、ライブラリ）\n   - 開発ツール（パッケージマネージャー、ビルドシステム、テストランナー）\n\n3. 既存ドキュメントをレビュー:\n   - README.md\n   - CONTRIBUTING.md\n   - package.json, pyproject.toml, Cargo.toml など\n\n### 2. コンテンツ戦略（WHAT, WHY, HOW）\n\nCLAUDE.md を 3 つの観点で構成する:\n\n#### WHAT - 技術と構造\n- 技術スタックの概要\n- プロジェクトの編成（モノレポでは特に重要）\n- 主要ディレクトリとその目的\n\n#### WHY - 目的と背景\n- プロジェクトが何をするか\n- なぜ特定の設計判断が下されたのか\n- 各主要コンポーネントが何を担当するか\n\n#### HOW - ワークフローと規約\n- 開発ワークフロー（bun と node、pip と uv など）\n- テスト手順とコマンド\n- 検証およびビルド手段\n- 重要な「ハマりどころ」や明示されない要件\n\n### 3. プログレッシブディスクロージャ戦略\n\n大規模プロジェクトでは `agent_docs/` フォルダの作成を推奨する:\n\n```\nagent_docs/\n  |- building_the_project.md\n  |- running_tests.md\n  |- code_conventions.md\n  |- architecture_decisions.md\n```\n\nCLAUDE.md からは以下のような命令でこれらのファイルを参照する:\n```markdown\nFor detailed build instructions, refer to `agent_docs/building_the_project.md`\n```\n\n**重要**: 古くなるコンテキストを避けるため、コードスニペットではなく `file:line` 参照を用いる。\n\n### 4. 品質制約\n\nCLAUDE.md を作成・更新する際:\n\n1. **目標の長さ**: 200 行未満\n2. **スタイルルールなし**: lint やフォーマットの命令は除く\n3. **タスク固有命令なし**: 別ファイルへ移す\n4. **コードスニペットなし**: ファイル参照を用いる\n5. **冗長情報なし**: package.json や README にあるものを繰り返さない\n\n### 5. 必須セクション\n\n良く構成された CLAUDE.md には以下を含めるべきである:\n\n```markdown\n# Project Name\n\nBrief one-line description.\n\n## Tech Stack\n- Primary language and version\n- Key frameworks/libraries\n- Database/storage (if any)\n\n## Project Structure\n[Only for monorepos or complex structures]\n- `apps/` - Application entry points\n- `packages/` - Shared libraries\n\n## Development Commands\n- Install: `command`\n- Test: `command`\n- Build: `command`\n\n## Critical Conventions\n[Only non-obvious, high-impact conventions]\n- Convention 1 with brief explanation\n- Convention 2 with brief explanation\n\n## Known Issues / Gotchas\n[Things that consistently trip up developers]\n- Issue 1\n- Issue 2\n```\n\n### 6. 避けるべきアンチパターン\n\n**含めてはいけないもの:**\n- コードスタイルガイドライン（リンターを使う）\n- Claude の使い方に関するドキュメント\n- 自明なパターンへの長い説明\n- コピー＆ペーストされたコード例\n- 一般的なベストプラクティス（\"write clean code\"）\n- 特定タスク向けの命令\n- 自動生成された内容\n- 大量の TODO リスト\n\n### 7. 検証チェックリスト\n\n最終化前に確認:\n\n- [ ] 200 行未満\n- [ ] すべての行があらゆるセッションに適用される\n- [ ] スタイルやフォーマットのルールがない\n- [ ] コードスニペットがない（ファイル参照を使う）\n- [ ] コマンドが動作することを検証済み\n- [ ] 複雑なプロジェクトでプログレッシブディスクロージャを利用\n- [ ] 重要なハマりどころがドキュメント化されている\n- [ ] README.md と内容が重複していない\n\n## 出力形式\n\n### `create` または既定の場合:\n\n1. プロジェクトを分析する\n2. 上記の構造に従って CLAUDE.md の草案を作る\n3. 草案をレビュー用に提示する\n4. 承認後、適切な場所へ書き込む\n\n### `update` の場合:\n\n1. 既存 CLAUDE.md を読む\n2. ベストプラクティスに照らして監査する\n3. 以下を特定する:\n   - 削除する内容（スタイルルール、コードスニペット、タスク固有）\n   - 凝縮する内容\n   - 不足している必須情報\n4. 変更内容をレビュー用に提示する\n5. 承認後、変更を適用する\n\n### `audit` の場合:\n\n1. 既存 CLAUDE.md を読む\n2. 以下を含むレポートを生成する:\n   - 現在の行数と目標値\n   - 普遍的に適用可能なコンテンツの割合\n   - 検出されたアンチパターンの一覧\n   - 改善のための推奨\n3. ファイルを変更しない、レポートのみを行う\n\n## AGENTS.md の取り扱い\n\nユーザーが AGENTS.md の作成・更新を求めた場合:\n\n**v2.1.277 以降、Claude Code は `AGENTS.md` をプロジェクト指示として直接読み込む。** ただし、作業ディレクトリとその上位すべてのディレクトリに `CLAUDE.md`、`.claude/CLAUDE.md`、`CLAUDE.local.md` のいずれも存在しない場合に限る。`~/.claude/CLAUDE.md`、管理 CLAUDE.md、`.claude/rules/` はこの判定の対象外であり、引き続き併せて読み込まれる。この挙動は `/config` の **Project instructions** で制御する: `claude-md-or-agents-md`（デフォルト）、`claude-md-and-agents-md`、`claude-md`、`managed-only`。直接読み込みが利用できない環境 — v2.1.277 より前のバージョン（Bedrock/Vertex/Foundry、LLM ゲートウェイ、テレメトリ無効の場合は v2.1.281 より前）、またはアップグレード後の最初のセッション — では、CLAUDE.md から `@AGENTS.md` でインポートするか、`CLAUDE.md` をこのファイルへのシンボリックリンクにするフォールバックを使う。\n\nAGENTS.md はツール横断のプロジェクトコンテキストファイルであり、CLAUDE.md と同じ *種類* のドキュメントである。エージェント定義フォーマットではない。複数のコーディングエージェントが 1 つのプロジェクト規約を共有できるようにするために存在する:\n- ビルド、テスト、リントのコマンド\n- コードスタイルとアーキテクチャ上の規約\n- リポジトリの構成と各要素の所在\n\nサブエージェントは AGENTS.md ではなく、`.claude/agents/*.md` で別途定義する。\n\n同様の原則を適用する:\n- 焦点を絞り簡潔に保つ\n- プログレッシブディスクロージャを用いる\n- 内容を埋め込むのではなく外部ドキュメントを参照する\n\n## 注意事項\n\n- コマンドを含める前に必ず動作確認する\n- 迷ったら省略する。少ないほど良い\n- システムリマインダーは Claude に対して CLAUDE.md は「関係があるかどうかわからない」と告げている。ノイズが多いほど無視されやすい\n- モノレポは明確な WHAT/WHY/HOW 構造の恩恵が最も大きい\n- ディレクトリ固有の CLAUDE.md ファイルはさらに焦点を絞るべきである\n\n---\n\n**最終更新**: 2026 年 10 月 18 日\n**Claude Code バージョン**: 2.1.302\n**Sources**:\n- https://code.claude.com/docs/en/memory\n","ja/03-skills/code-review-specialist/SKILL.md":"<!-- i18n-source: 03-skills/code-review-specialist/SKILL.md -->\n<!-- i18n-source-sha: e978c49 -->\n<!-- i18n-date: 2026-04-27 -->\n\n---\nname: code-review-specialist\ndescription: セキュリティ、パフォーマンス、品質分析を含む包括的なコードレビュー。コードレビュー、コード品質分析、プルリクエスト評価の依頼があった場合、またはコードレビュー、セキュリティ分析、パフォーマンス最適化について言及がある場合に使用する。\n---\n\n# コードレビュー・スキル\n\nこのスキルは、以下に焦点を当てた包括的なコードレビュー機能を提供する。\n\n1. **セキュリティ分析**\n   - 認証・認可の問題\n   - データ漏洩リスク\n   - インジェクション脆弱性\n   - 暗号の弱点\n   - 機密データのロギング\n\n2. **パフォーマンス・レビュー**\n   - アルゴリズム効率（Big O 分析）\n   - メモリ最適化\n   - データベースクエリ最適化\n   - キャッシュ機会\n   - 並行性の問題\n\n3. **コード品質**\n   - SOLID 原則\n   - デザインパターン\n   - 命名規則\n   - ドキュメント\n   - テストカバレッジ\n\n4. **保守性**\n   - コードの可読性\n   - 関数サイズ（50 行未満が望ましい）\n   - 循環的複雑度\n   - 依存関係管理\n   - 型安全性\n\n## レビュー・テンプレート\n\nレビューしたコードごとに、以下を提供する。\n\n### サマリー\n- 全体品質評価（1-5）\n- 主要な指摘件数\n- 推奨される優先領域\n\n### クリティカルな問題（あれば）\n- **Issue**: 明確な説明\n- **Location**: ファイルと行番号\n- **Impact**: なぜ重要か\n- **Severity**: Critical/High/Medium\n- **Fix**: コード例\n\n### カテゴリ別の指摘事項\n\n#### セキュリティ（問題が見つかった場合）\nセキュリティ脆弱性を例示しながら列挙\n\n#### パフォーマンス（問題が見つかった場合）\n複雑度分析を含めパフォーマンス問題を列挙\n\n#### 品質（問題が見つかった場合）\nリファクタリング提案を含めコード品質の問題を列挙\n\n#### 保守性（問題が見つかった場合）\n改善案を含め保守性の問題を列挙\n\n## バージョン履歴\n\n- v1.0.0 (2024-12-10): セキュリティ、パフォーマンス、品質、保守性分析を含む初回リリース\n","ja/03-skills/doc-generator/SKILL.md":"<!-- i18n-source: 03-skills/doc-generator/SKILL.md -->\n<!-- i18n-source-sha: a6380d8 -->\n<!-- i18n-date: 2026-04-27 -->\n\n---\nname: doc-generator\ndescription: ソースコードから包括的かつ正確な API ドキュメントを生成する。API ドキュメントの作成・更新、OpenAPI 仕様の生成時、または API ドキュメント、エンドポイント、ドキュメントについて言及がある場合に使用する。\n---\n\n# API ドキュメント生成スキル\n\n## 生成するもの\n\n- OpenAPI/Swagger 仕様\n- API エンドポイントのドキュメント\n- SDK 利用例\n- 統合ガイド\n- エラーコード・リファレンス\n- 認証ガイド\n\n## ドキュメント構造\n\n### 各エンドポイントごと\n\n````markdown\n## GET /api/v1/users/:id\n\n### Description\nこのエンドポイントの動作を簡潔に説明\n\n### Parameters\n\n| Name | Type | Required | Description |\n|------|------|----------|-------------|\n| id | string | Yes | User ID |\n\n### Response\n\n**200 Success**\n```json\n{\n  \"id\": \"usr_123\",\n  \"name\": \"John Doe\",\n  \"email\": \"john@example.com\",\n  \"created_at\": \"2025-01-15T10:30:00Z\"\n}\n```\n\n**404 Not Found**\n```json\n{\n  \"error\": \"USER_NOT_FOUND\",\n  \"message\": \"User does not exist\"\n}\n```\n\n### Examples\n\n**cURL**\n```bash\ncurl -X GET \"https://api.example.com/api/v1/users/usr_123\" \\\n  -H \"Authorization: Bearer YOUR_TOKEN\"\n```\n\n**JavaScript**\n```javascript\nconst user = await fetch('/api/v1/users/usr_123', {\n  headers: { 'Authorization': 'Bearer token' }\n}).then(r => r.json());\n```\n\n**Python**\n```python\nresponse = requests.get(\n    'https://api.example.com/api/v1/users/usr_123',\n    headers={'Authorization': 'Bearer token'}\n)\nuser = response.json()\n```\n````\n","ja/03-skills/refactor/SKILL.md":"<!-- i18n-source: 03-skills/refactor/SKILL.md -->\n<!-- i18n-source-sha: 245272f -->\n<!-- i18n-date: 2026-04-27 -->\n---\nname: refactor\ndescription: Martin Fowler の方法論に基づく体系的なコードリファクタリング。ユーザーがコードのリファクタリング、コード構造の改善、技術的負債の削減、レガシーコードのクリーンアップ、コードスメルの解消、コード保守性の向上を求めた際に使用する。本スキルは、リサーチ・計画・安全な段階的実装からなる段階的アプローチを案内する。\n---\n\n# コードリファクタリングスキル\n\nMartin Fowler 著『Refactoring: Improving the Design of Existing Code』(第 2 版) に基づくコードリファクタリングへの体系的アプローチ。本スキルは、テストに支えられた安全で段階的な変更を重視する。\n\n> \"Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure.\" — Martin Fowler\n\n## 中核となる原則\n\n1. **振る舞いの保全**: 外部から見える振る舞いは変えてはならない\n2. **小さなステップ**: テスト可能な微小な変更を積み重ねる\n3. **テスト駆動**: テストはセーフティネットである\n4. **継続的**: リファクタリングは一度きりの作業ではなく継続的に行う\n5. **協調的**: 各フェーズでユーザーの承認が必要\n\n## ワークフロー概要\n\n```\nPhase 1: Research & Analysis\n    ↓\nPhase 2: Test Coverage Assessment\n    ↓\nPhase 3: Code Smell Identification\n    ↓\nPhase 4: Refactoring Plan Creation\n    ↓\nPhase 5: Incremental Implementation\n    ↓\nPhase 6: Review & Iteration\n```\n\n---\n\n## フェーズ 1: リサーチと分析\n\n### 目的\n- コードベースの構造と目的を把握する\n- リファクタリングの範囲を特定する\n- ビジネス要件に関するコンテキストを収集する\n\n### ユーザーへの確認事項\n開始前に次の点を明確化する。\n\n1. **範囲**: どのファイル/モジュール/関数をリファクタリングするのか?\n2. **目標**: 何を解決したいのか?(可読性、性能、保守性)\n3. **制約**: 変更してはいけない領域はあるか?\n4. **時間的圧力**: 他作業のブロッカーになっているか?\n5. **テスト状況**: テストは存在するか?パスしているか?\n\n### アクション\n- [ ] 対象コードを読み、理解する\n- [ ] 依存関係と統合箇所を洗い出す\n- [ ] 現行アーキテクチャを文書化する\n- [ ] 既存の技術的負債マーカー(TODO、FIXME)を控える\n\n### 出力\nユーザーへの提示内容:\n- コード構造のサマリー\n- 検出された問題箇所\n- 初期推奨事項\n- **着手の承認を依頼する**\n\n---\n\n## フェーズ 2: テストカバレッジの評価\n\n### なぜテストが重要か\n> \"Refactoring without tests is like driving without a seatbelt.\" — Martin Fowler\n\nテストは安全なリファクタリングを可能にする**鍵となる要素**である。テストがなければ、バグを混入させるリスクがある。\n\n### 評価ステップ\n\n1. **既存テストの確認**\n   ```bash\n   # テストファイルを探す\n   find . -name \"*test*\" -o -name \"*spec*\" | head -20\n   ```\n\n2. **既存テストの実行**\n   ```bash\n   # JavaScript/TypeScript\n   npm test\n\n   # Python\n   pytest -v\n\n   # Java\n   mvn test\n   ```\n\n3. **カバレッジの確認(可能な場合)**\n   ```bash\n   # JavaScript\n   npm run test:coverage\n\n   # Python\n   pytest --cov=.\n   ```\n\n### 判断ポイント: ユーザーへの確認\n\n**テストが存在し、かつパスしている場合:**\n- フェーズ 3 へ進む\n\n**テストが不足、または不完全な場合:**\n次の選択肢を提示する。\n1. 先にテストを書く(推奨)\n2. リファクタリング中に段階的にテストを追加する\n3. テストなしで進める(リスクあり、ユーザーの明示的同意が必要)\n\n**テストが失敗している場合:**\n- STOP。リファクタリング前に失敗テストを修正する\n- ユーザーに確認: 先にテストを直すべきか?\n\n### テスト作成のガイドライン(必要時)\n\nリファクタリング対象の各関数について、以下をテストでカバーする。\n- ハッピーパス(通常動作)\n- エッジケース(空入力、null、境界値)\n- エラーシナリオ(無効入力、例外)\n\n「red-green-refactor」サイクルを用いる。\n1. 失敗するテストを書く(red)\n2. パスさせる(green)\n3. リファクタリングする\n\n---\n\n## フェーズ 3: コードスメルの特定\n\n### コードスメルとは?\nコードに潜むより深い問題の症状である。バグそのものではないが、コード改善の余地を示す指標となる。\n\n### よくチェックすべきコードスメル\n\n完全なカタログは [references/code-smells.md](references/code-smells.md) を参照。\n\n#### クイックリファレンス\n\n| スメル | 兆候 | 影響 |\n|-------|-------|--------|\n| **Long Method（長すぎる関数）** | メソッドが 30〜50 行を超える | 理解、テスト、保守が困難 |\n| **Duplicated Code（重複したコード）** | 同じロジックが複数箇所に存在 | バグ修正を複数箇所で行う必要がある |\n| **Large Class（巨大なクラス）** | 責務が多すぎるクラス | 単一責任原則に違反 |\n| **Feature Envy（機能の横恋慕）** | 他クラスのデータを多く使用するメソッド | カプセル化が不十分 |\n| **Primitive Obsession（プリミティブ型への執着）** | オブジェクト化すべき所をプリミティブで多用 | ドメイン概念が欠落 |\n| **Long Parameter List（長すぎるパラメータリスト）** | パラメータが 4 個以上 | 正しく呼び出すのが困難 |\n| **Data Clumps（データの群れ）** | 同じデータ項目が常に一緒に現れる | 抽象化が欠落 |\n| **Switch Statements（スイッチ文)** | 複雑な switch / if-else の連鎖 | 拡張が困難 |\n| **Speculative Generality（投機的一般化）** | 「念のため」のコード | 不要な複雑さ |\n| **Dead Code（デッドコード）** | 使われていないコード | 混乱と保守負担 |\n\n### 分析ステップ\n\n1. **自動分析**(スクリプトが利用可能な場合)\n   ```bash\n   python scripts/detect-smells.py <file>\n   ```\n\n2. **手動レビュー**\n   - コードを体系的に読み進める\n   - 各スメルを場所と深刻度とともに記録する\n   - 影響度別に分類する(Critical / High / Medium / Low)\n\n3. **優先順位付け**\n   次のようなスメルに注力する。\n   - 現在の開発をブロックしているもの\n   - バグや混乱を引き起こしているもの\n   - 変更頻度が高いコードパスに影響するもの\n\n### 出力: スメルレポート\n\nユーザーへの提示内容:\n- 検出されたスメルの一覧と場所\n- 各スメルの深刻度評価\n- 推奨される優先順位\n- **優先順位の承認を依頼する**\n\n---\n\n## フェーズ 4: リファクタリング計画の作成\n\n### リファクタリング技法の選定\n\n各スメルに対して、カタログから適切なリファクタリング技法を選ぶ。\n\n完全な一覧は [references/refactoring-catalog.md](references/refactoring-catalog.md) を参照。\n\n#### スメル別の推奨リファクタリング\n\n| コードスメル | 推奨リファクタリング |\n|------------|---------------------------|\n| Long Method（長すぎる関数） | メソッドの抽出、Replace Temp with Query |\n| Duplicated Code（重複したコード） | メソッドの抽出、Pull Up Method、Form Template Method |\n| Large Class（巨大なクラス） | クラスの抽出、Extract Subclass |\n| Feature Envy（機能の横恋慕） | Move Method、Move Field |\n| Primitive Obsession（プリミティブ型への執着） | Replace Primitive with Object、Replace Type Code with Class |\n| Long Parameter List（長すぎるパラメータリスト） | パラメータオブジェクトの導入、Preserve Whole Object |\n| Data Clumps（データの群れ） | クラスの抽出、パラメータオブジェクトの導入 |\n| Switch Statements（スイッチ文） | ポリモーフィズムによる条件記述の置き換え |\n| Speculative Generality（投機的一般化） | Collapse Hierarchy、Inline Class、デッドコードの削除 |\n| Dead Code（デッドコード） | デッドコードの削除 |\n\n### 計画の構成\n\n[templates/refactoring-plan.md](templates/refactoring-plan.md) のテンプレートを使用する。\n\n各リファクタリングごとに次の項目を埋める。\n1. **対象**: 何を変更するか\n2. **スメル**: どの問題に対処するか\n3. **リファクタリング**: どの技法を適用するか\n4. **手順**: 細かいマイクロステップ\n5. **リスク**: 何が失敗しうるか\n6. **ロールバック**: 取り消す方法\n\n### 段階的アプローチ\n\n**重要**: リファクタリングはフェーズに分けて段階的に導入する。\n\n**フェーズ A: クイックウィン**(低リスク、高価値)\n- 明確化のための変数名変更\n- 明らかな重複コードの抽出\n- デッドコードの削除\n\n**フェーズ B: 構造改善**(中リスク)\n- 長すぎる関数からのメソッド抽出\n- パラメータオブジェクトの導入\n- メソッドを適切なクラスへ移動\n\n**フェーズ C: アーキテクチャ変更**(高リスク)\n- 条件分岐をポリモーフィズムで置換\n- クラスの抽出\n- デザインパターンの導入\n\n### 判断ポイント: ユーザーへの計画提示\n\n実装前に:\n- 完全なリファクタリング計画を提示する\n- 各フェーズの内容とリスクを説明する\n- 各フェーズについて明示的な承認を得る\n- **質問**: 「フェーズ A を進めてもよいか?」\n\n---\n\n## フェーズ 5: 段階的な実装\n\n### ゴールデンルール\n> \"Change → Test → Green? → Commit → Next step\"\n\n### 実装のリズム\n\n各リファクタリングステップで:\n\n1. **事前チェック**\n   - テストがパスしている(green)\n   - コードがコンパイルできる\n\n2. **小さな変更を 1 つだけ行う**\n   - カタログのメカニクスに従う\n   - 変更は最小限に保つ\n\n3. **検証**\n   - 直ちにテストを実行\n   - コンパイルエラーがないか確認\n\n4. **テストがパス(green)した場合**\n   - 説明的なコミットメッセージでコミット\n   - 次のステップへ進む\n\n5. **テストが失敗(red)した場合**\n   - 直ちに STOP\n   - 変更を取り消す\n   - 何が起きたかを分析する\n   - 不明な場合はユーザーに確認する\n\n### コミット戦略\n\n各コミットは次の性質を満たすこと。\n- **アトミック**: 論理的に 1 つの変更\n- **可逆**: 容易に revert できる\n- **説明的**: 明確なコミットメッセージ\n\nコミットメッセージ例:\n```\nrefactor: Extract calculateTotal() from processOrder()\nrefactor: Rename 'x' to 'customerCount' for clarity\nrefactor: Remove unused validateOldFormat() method\n```\n\n### 進捗報告\n\nサブフェーズごとに、ユーザーへ次を報告する。\n- 行った変更\n- テストはまだパスしているか\n- 発生した問題\n- **質問**: 「次のバッチへ進めてもよいか?」\n\n---\n\n## フェーズ 6: レビューと反復\n\n### リファクタリング後チェックリスト\n\n- [ ] 全テストがパスする\n- [ ] 新たな警告/エラーが出ていない\n- [ ] コードが正常にコンパイルできる\n- [ ] 振る舞いが変わっていない(手動検証)\n- [ ] 必要に応じてドキュメントが更新されている\n- [ ] コミット履歴が整理されている\n\n### メトリクス比較\n\nリファクタリング前後で複雑度解析を実施する。\n```bash\npython scripts/analyze-complexity.py <file>\n```\n\n改善点を提示する。\n- コード行数の変化\n- 循環的複雑度の変化\n- 保守性指数の変化\n\n### ユーザーレビュー\n\n最終結果を提示する。\n- 全変更のサマリー\n- Before / After のコード比較\n- メトリクスの改善\n- 残る技術的負債\n- **質問**: 「この変更内容で問題ないか?」\n\n### 次のステップ\n\nユーザーと議論する。\n- 追加で対処すべきスメルはあるか?\n- フォローアップのリファクタリングを計画するか?\n- 同様の変更を他箇所にも適用するか?\n\n---\n\n## 重要なガイドライン\n\n### STOP してユーザーに相談すべきタイミング\n\n次の場合、必ず一旦止まりユーザーに相談する。\n- ビジネスロジックに不確実性がある\n- 外部 API に影響しうる変更\n- テストカバレッジが不十分\n- 重大なアーキテクチャ判断が必要\n- リスクレベルが上昇する\n- 想定外の複雑さに遭遇した\n\n### 安全のためのルール\n\n1. **テストなしでリファクタリングしない**(ユーザーが明示的にリスクを受容しない限り)\n2. **大きな変更を一度にしない** - 微小なステップに分割する\n3. **各変更後のテスト実行を省略しない**\n4. **テスト失敗時は続行しない** - 修正かロールバックを先に行う\n5. **思い込みで進めない** - 疑問があれば確認する\n\n### やってはいけないこと\n\n- リファクタリングと機能追加を同時に行わない\n- 本番障害対応中にリファクタリングしない\n- 理解していないコードをリファクタリングしない\n- 過剰設計をしない - シンプルに保つ\n- 全てを一度にリファクタリングしない\n\n---\n\n## クイックスタート例\n\n### シナリオ: 重複を含む長い関数\n\n**Before:**\n```javascript\nfunction processOrder(order) {\n  // 150 行のコードに以下が混在:\n  // - 重複したバリデーションロジック\n  // - インラインの計算処理\n  // - 複数の責務\n}\n```\n\n**リファクタリング手順:**\n\n1. processOrder() に対する**テストの存在を確認**\n2. バリデーションを validateOrder() に**抽出**\n3. **テスト** - パスすること\n4. 計算を calculateOrderTotal() に**抽出**\n5. **テスト** - パスすること\n6. 通知を notifyCustomer() に**抽出**\n7. **テスト** - パスすること\n8. **レビュー** - processOrder() は明確な 3 関数の調整役となる\n\n**After:**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const total = calculateOrderTotal(order);\n  notifyCustomer(order, total);\n  return { order, total };\n}\n```\n\n---\n\n## 参考文献\n\n- [Code Smells Catalog](references/code-smells.md) - コードスメルの完全な一覧\n- [Refactoring Catalog](references/refactoring-catalog.md) - リファクタリング技法\n- [Refactoring Plan Template](templates/refactoring-plan.md) - 計画用テンプレート\n\n## スクリプト\n\n- `scripts/analyze-complexity.py` - コード複雑度メトリクスの分析\n- `scripts/detect-smells.py` - スメルの自動検出\n\n## バージョン履歴\n\n- v1.0.0 (2025-01-15): Fowler の方法論、段階的アプローチ、ユーザー相談ポイントを備えた初版リリース\n","ja/03-skills/refactor/references/code-smells.md":"<!-- i18n-source: 03-skills/refactor/references/code-smells.md -->\n<!-- i18n-source-sha: 245272f -->\n<!-- i18n-date: 2026-04-27 -->\n# コードスメルカタログ\n\nMartin Fowler 著『Refactoring』(第 2 版) に基づく、コードスメルの包括的なリファレンスである。コードスメルはより深い問題の症状であり、コード設計に何か問題がある可能性を示す指標となる。\n\n> \"A code smell is a surface indication that usually corresponds to a deeper problem in the system.\" — Martin Fowler\n\n---\n\n## Bloaters（肥満児）\n\n効果的に扱うには大きくなりすぎたものを表すコードスメル群である。\n\n### Long Method（長すぎる関数）\n\n**兆候:**\n- メソッドが 30〜50 行を超える\n- メソッド全体を見るのにスクロールが必要\n- ネストが多重になっている\n- セクションごとに何をしているかを説明するコメントがある\n\n**なぜ悪いか:**\n- 理解しづらい\n- 単独でテストするのが難しい\n- 変更が予期しない影響を及ぼす\n- 内部に重複ロジックが隠れる\n\n**リファクタリング:**\n- メソッドの抽出\n- Replace Temp with Query\n- パラメータオブジェクトの導入\n- Replace Method with Method Object\n- 条件記述の分解\n\n**例（Before）:**\n```javascript\nfunction processOrder(order) {\n  // 注文の検証 (20 行)\n  if (!order.items) throw new Error('No items');\n  if (order.items.length === 0) throw new Error('Empty order');\n  // ... さらに検証\n\n  // 合計金額の計算 (30 行)\n  let subtotal = 0;\n  for (const item of order.items) {\n    subtotal += item.price * item.quantity;\n  }\n  // ... 税、送料、割引\n\n  // 通知の送信 (20 行)\n  // ... メール送信ロジック\n}\n```\n\n**例（After）:**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const totals = calculateOrderTotals(order);\n  sendOrderNotifications(order, totals);\n  return { order, totals };\n}\n```\n\n---\n\n### Large Class（巨大なクラス）\n\n**兆候:**\n- クラスのインスタンス変数が多い(7〜10 個超)\n- クラスのメソッドが多い(15〜20 個超)\n- クラス名が漠然としている(Manager、Handler、Processor)\n- 全インスタンス変数を使わないメソッドがある\n\n**なぜ悪いか:**\n- 単一責任原則に違反する\n- テストが困難\n- 変更が無関係な機能にも波及する\n- 部分的な再利用が難しい\n\n**リファクタリング:**\n- クラスの抽出\n- Extract Subclass\n- Extract Interface\n\n**検出基準:**\n```\nコード行数 > 300\nメソッド数 > 15\nフィールド数 > 10\n```\n\n---\n\n### Primitive Obsession（プリミティブ型への執着）\n\n**兆候:**\n- ドメイン概念にプリミティブを使う(メールに string、金額に int)\n- オブジェクトでなくプリミティブの配列を使う\n- タイプコードに文字列定数を使う\n- マジックナンバーやマジックストリング\n\n**なぜ悪いか:**\n- 型レベルでの検証ができない\n- ロジックがコードベース全体に散らばる\n- 誤った値を渡しやすい\n- ドメイン概念が欠落する\n\n**リファクタリング:**\n- Replace Primitive with Object\n- Replace Type Code with Class\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**例（Before）:**\n```javascript\nconst user = {\n  email: 'john@example.com',     // 単なる文字列\n  phone: '1234567890',           // 単なる文字列\n  status: 'active',              // マジックストリング\n  balance: 10050                 // セント単位の整数\n};\n```\n\n**例（After）:**\n```javascript\nconst user = {\n  email: new Email('john@example.com'),\n  phone: new PhoneNumber('1234567890'),\n  status: UserStatus.ACTIVE,\n  balance: Money.cents(10050)\n};\n```\n\n---\n\n### Long Parameter List（長すぎるパラメータリスト）\n\n**兆候:**\n- パラメータが 4 個以上のメソッド\n- 常に一緒に現れるパラメータ\n- メソッドの振る舞いを切り替える真偽値フラグ\n- null/undefined が頻繁に渡される\n\n**なぜ悪いか:**\n- 正しく呼び出すのが難しい\n- 引数順序の混乱を招く\n- メソッドが多くを抱え込んでいるサイン\n- パラメータの追加が難しい\n\n**リファクタリング:**\n- パラメータオブジェクトの導入\n- Preserve Whole Object\n- Replace Parameter with Method Call\n- Remove Flag Argument\n\n**例（Before）:**\n```javascript\nfunction createUser(firstName, lastName, email, phone,\n                    street, city, state, zip,\n                    isAdmin, isActive, createdBy) {\n  // ...\n}\n```\n\n**例（After）:**\n```javascript\nfunction createUser(personalInfo, address, options) {\n  // personalInfo: { firstName, lastName, email, phone }\n  // address: { street, city, state, zip }\n  // options: { isAdmin, isActive, createdBy }\n}\n```\n\n---\n\n### Data Clumps（データの群れ）\n\n**兆候:**\n- 同じ 3 個以上のフィールドが繰り返し一緒に現れる\n- 常に一緒に渡されるパラメータ群\n- 一塊として属するべきフィールド集合を持つクラス\n\n**なぜ悪いか:**\n- 取り扱いロジックが重複する\n- 抽象化が欠けている\n- 拡張しづらい\n- 隠れたクラスの存在を示す\n\n**リファクタリング:**\n- クラスの抽出\n- パラメータオブジェクトの導入\n- Preserve Whole Object\n\n**例:**\n```javascript\n// データの群れ: (x, y, z) 座標\nfunction movePoint(x, y, z, dx, dy, dz) { }\nfunction scalePoint(x, y, z, factor) { }\nfunction distanceBetween(x1, y1, z1, x2, y2, z2) { }\n\n// Point3D クラスを抽出\nclass Point3D {\n  constructor(x, y, z) { }\n  move(delta) { }\n  scale(factor) { }\n  distanceTo(other) { }\n}\n```\n\n---\n\n## Object-Orientation Abusers（オブジェクト指向の濫用者）\n\nオブジェクト指向の原則を不完全または誤って使っていることを示すスメル群である。\n\n### Switch Statements（スイッチ文）\n\n**兆候:**\n- 長い switch/case や if/else の連鎖\n- 同じ switch が複数箇所に存在\n- タイプコードに対する switch\n- 新ケース追加で各所を変更する必要がある\n\n**なぜ悪いか:**\n- 開放閉鎖原則に違反する\n- 全ての switch 箇所に変更が波及する\n- 拡張が困難\n- ポリモーフィズム不在のサインであることが多い\n\n**リファクタリング:**\n- ポリモーフィズムによる条件記述の置き換え\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**例（Before）:**\n```javascript\nfunction calculatePay(employee) {\n  switch (employee.type) {\n    case 'hourly':\n      return employee.hours * employee.rate;\n    case 'salaried':\n      return employee.salary / 12;\n    case 'commissioned':\n      return employee.sales * employee.commission;\n  }\n}\n```\n\n**例（After）:**\n```javascript\nclass HourlyEmployee {\n  calculatePay() {\n    return this.hours * this.rate;\n  }\n}\n\nclass SalariedEmployee {\n  calculatePay() {\n    return this.salary / 12;\n  }\n}\n```\n\n---\n\n### Temporary Field（一時的フィールド）\n\n**兆候:**\n- 一部のメソッドでのみ使用されるインスタンス変数\n- 条件付きで設定されるフィールド\n- 特定ケースのために複雑な初期化を要する\n\n**なぜ悪いか:**\n- 紛らわしい - フィールドが存在するが null の場合がある\n- オブジェクトの状態が理解しづらい\n- 隠れた条件分岐ロジックを示す\n\n**リファクタリング:**\n- クラスの抽出\n- Introduce Null Object\n- Replace Temp Field with Local\n\n---\n\n### Refused Bequest（相続拒否）\n\n**兆候:**\n- サブクラスが継承したメソッド/データを使わない\n- サブクラスがオーバーライドして何もしない\n- IS-A 関係ではなくコード再利用目的の継承\n\n**なぜ悪いか:**\n- 抽象化が誤っている\n- リスコフの置換原則に違反する\n- 階層が誤解を招く\n\n**リファクタリング:**\n- Push Down Method/Field\n- Replace Subclass with Delegate\n- Replace Inheritance with Delegation\n\n---\n\n### Alternative Classes with Different Interfaces（異なるインターフェイスの代替クラス）\n\n**兆候:**\n- 似たことをする 2 つのクラス\n- 同じ概念に異なるメソッド名を使っている\n- 互いに置換可能だが共通インターフェイスがない\n\n**なぜ悪いか:**\n- 実装が重複する\n- 共通インターフェイスがない\n- 切り替えが難しい\n\n**リファクタリング:**\n- Rename Method\n- Move Method\n- Extract Superclass\n- Extract Interface\n\n---\n\n## Change Preventers（変更の妨げ）\n\n変更を困難にするスメル群 - ある変更のために他の多くを変える必要が生じる。\n\n### Divergent Change（変更の発散）\n\n**兆候:**\n- 1 つのクラスが異なる複数の理由で変更される\n- 異なる領域の変更が同じクラスへの編集を引き起こす\n- そのクラスは「神クラス」化している\n\n**なぜ悪いか:**\n- 単一責任原則に違反する\n- 変更頻度が高くなる\n- マージコンフリクトを招く\n\n**リファクタリング:**\n- クラスの抽出\n- Extract Superclass\n- Extract Subclass\n\n**例:**\n`User` クラスが次の理由で変更される:\n- 認証の変更\n- プロフィールの変更\n- 課金の変更\n- 通知の変更\n\n→ 抽出: `AuthService`、`ProfileService`、`BillingService`、`NotificationService`\n\n---\n\n### Shotgun Surgery（散弾銃手術）\n\n**兆候:**\n- 1 つの変更で多くのクラスへの編集が必要\n- 小さな機能でも 10 ファイル以上に手を入れる\n- 変更箇所が散在し、すべてを見つけにくい\n\n**なぜ悪いか:**\n- 修正漏れが起きやすい\n- 結合度が高い\n- 変更がエラーを誘発しやすい\n\n**リファクタリング:**\n- Move Method\n- Move Field\n- Inline Class\n\n**検出基準:**\n1 フィールドの追加で 5 ファイル以上の変更が必要かを確認する。\n\n---\n\n### Parallel Inheritance Hierarchies（並行継承階層）\n\n**兆候:**\n- 一方の階層にサブクラスを作ると、もう一方にも作る必要がある\n- クラス名のプレフィックスが揃っている(例: `DatabaseOrder`、`DatabaseProduct`)\n\n**なぜ悪いか:**\n- 保守コストが倍になる\n- 階層間の結合度が高い\n- 片側を忘れやすい\n\n**リファクタリング:**\n- Move Method\n- Move Field\n- 一方の階層を削除する\n\n---\n\n## Dispensables（不要物）\n\n不要であり削除すべきものを表すスメル群である。\n\n### Comments（過剰なコメント）\n\n**兆候:**\n- コードが何をしているかを説明するコメント\n- コメントアウトされたコード\n- 永遠に残る TODO/FIXME\n- 言い訳のコメント\n\n**なぜ悪いか:**\n- コメントは嘘をつく(コードと乖離する)\n- コードは自己文書化されているべき\n- 死んだコードは混乱を生む\n\n**リファクタリング:**\n- メソッドの抽出(名前で「何」を表す)\n- Rename(コメントなしで明確化)\n- コメントアウトされたコードの削除\n- Introduce Assertion\n\n**良いコメントと悪いコメント:**\n```javascript\n// 悪い: 「何」を説明している\n// users をループしてアクティブかどうか確認\nfor (const user of users) {\n  if (user.status === 'active') { }\n}\n\n// 良い: 「なぜ」を説明している\n// アクティブなユーザーのみ。非アクティブはクリーンアップジョブで処理される\nconst activeUsers = users.filter(u => u.isActive);\n```\n\n---\n\n### Duplicate Code（重複したコード）\n\n**兆候:**\n- 同じコードが複数箇所にある\n- わずかな違いだけの似たコード\n- コピペのパターン\n\n**なぜ悪いか:**\n- バグ修正を複数箇所で行う必要がある\n- 不整合のリスク\n- コードベースが肥大化する\n\n**リファクタリング:**\n- メソッドの抽出\n- クラスの抽出\n- Pull Up Method(階層内)\n- Form Template Method\n\n**検出ルール:**\n3 回以上重複するコードは抽出すべきである。\n\n---\n\n### Lazy Class（怠け者のクラス）\n\n**兆候:**\n- クラスが存在を正当化できるほど働いていない\n- 付加価値のないラッパー\n- 過剰設計の結果\n\n**なぜ悪いか:**\n- 保守オーバーヘッド\n- 不要な間接参照\n- メリットなき複雑さ\n\n**リファクタリング:**\n- Inline Class\n- Collapse Hierarchy\n\n---\n\n### Dead Code（デッドコード）\n\n**兆候:**\n- 到達不能なコード\n- 使われていない変数/メソッド/クラス\n- コメントアウトされたコード\n- 起こり得ない条件下にあるコード\n\n**なぜ悪いか:**\n- 混乱を招く\n- 保守の負担\n- 理解の速度を落とす\n\n**リファクタリング:**\n- デッドコードの削除\n- Safe Delete\n\n**検出基準:**\n```bash\n# 未使用のエクスポートを探す\n# 参照されない関数を探す\n# IDE の「未使用」警告を確認\n```\n\n---\n\n### Speculative Generality（投機的一般化）\n\n**兆候:**\n- サブクラスが 1 つしかない抽象クラス\n- 「将来のため」の未使用パラメータ\n- 委譲のみのメソッド\n- 1 用途しかない「フレームワーク」\n\n**なぜ悪いか:**\n- メリットなき複雑さ\n- YAGNI(You Ain't Gonna Need It)\n- 理解しづらい\n\n**リファクタリング:**\n- Collapse Hierarchy\n- Inline Class\n- Remove Parameter\n- Rename Method\n\n---\n\n## Couplers（結合の問題）\n\nクラス間の過剰な結合を表すスメル群である。\n\n### Feature Envy（機能の横恋慕）\n\n**兆候:**\n- メソッドが自クラスより他クラスのデータを多く使う\n- 他オブジェクトへの getter 呼び出しが多い\n- データと振る舞いが分離している\n\n**なぜ悪いか:**\n- 振る舞いの置き場所が誤っている\n- カプセル化が不十分\n- 保守が難しい\n\n**リファクタリング:**\n- Move Method\n- Move Field\n- メソッドの抽出(その後 move)\n\n**例（Before）:**\n```javascript\nclass Order {\n  getDiscountedPrice(customer) {\n    // customer のデータを多く使っている\n    if (customer.loyaltyYears > 5) {\n      return this.price * customer.discountRate;\n    }\n    return this.price;\n  }\n}\n```\n\n**例（After）:**\n```javascript\nclass Customer {\n  getDiscountedPriceFor(price) {\n    if (this.loyaltyYears > 5) {\n      return price * this.discountRate;\n    }\n    return price;\n  }\n}\n```\n\n---\n\n### Inappropriate Intimacy（不適切な親密さ）\n\n**兆候:**\n- クラスが互いのプライベート部分にアクセスする\n- 双方向の参照\n- サブクラスが親について詳しすぎる\n\n**なぜ悪いか:**\n- 結合度が高い\n- 変更が連鎖する\n- 一方を変えると他方も変える必要がある\n\n**リファクタリング:**\n- Move Method\n- Move Field\n- Change Bidirectional to Unidirectional\n- クラスの抽出\n- Hide Delegate\n\n---\n\n### Message Chains（メッセージの連鎖）\n\n**兆候:**\n- メソッド呼び出しの長い連鎖: `a.getB().getC().getD().getValue()`\n- クライアントがナビゲーション構造に依存している\n- 「列車事故」コード\n\n**なぜ悪いか:**\n- 脆弱 - 連鎖中のいずれかが変わると壊れる\n- デメテルの法則に違反する\n- 構造への結合\n\n**リファクタリング:**\n- Hide Delegate\n- メソッドの抽出\n- Move Method\n\n**例:**\n```javascript\n// 悪い: メッセージの連鎖\nconst managerName = employee.getDepartment().getManager().getName();\n\n// 良い: 委譲を隠す\nconst managerName = employee.getManagerName();\n```\n\n---\n\n### Middle Man（仲介人）\n\n**兆候:**\n- 他クラスへ委譲するだけのクラス\n- メソッドの半数が委譲\n- 付加価値がない\n\n**なぜ悪いか:**\n- 不要な間接参照\n- 保守オーバーヘッド\n- アーキテクチャが分かりにくい\n\n**リファクタリング:**\n- Remove Middle Man\n- メソッドのインライン化\n\n---\n\n## スメル深刻度ガイド\n\n| 深刻度 | 説明 | 対応 |\n|----------|-------------|--------|\n| **Critical** | 開発をブロックし、バグの原因となる | 直ちに修正 |\n| **High** | 保守負担が大きい | 当該スプリント中に修正 |\n| **Medium** | 目に付くが許容範囲 | 近い将来に計画 |\n| **Low** | 軽微な不便 | 機会があれば修正 |\n\n---\n\n## 簡易検出チェックリスト\n\nコードをスキャンする際に使うチェックリストである。\n\n- [ ] 30 行を超えるメソッドはあるか?\n- [ ] 300 行を超えるクラスはあるか?\n- [ ] 4 個を超えるパラメータを持つメソッドはあるか?\n- [ ] 重複したコードブロックはあるか?\n- [ ] タイプコードに対する switch/case はあるか?\n- [ ] 使われていないコードはあるか?\n- [ ] 他クラスのデータを多く使っているメソッドはあるか?\n- [ ] メソッド呼び出しの長い連鎖はあるか?\n- [ ] 「なぜ」ではなく「何」を説明しているコメントはあるか?\n- [ ] オブジェクト化すべきプリミティブはあるか?\n\n---\n\n## 参考文献\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Kerievsky, J. (2004). *Refactoring to Patterns*\n- Feathers, M. (2004). *Working Effectively with Legacy Code*\n","ja/03-skills/refactor/references/refactoring-catalog.md":"<!-- i18n-source: 03-skills/refactor/references/refactoring-catalog.md -->\n<!-- i18n-source-sha: 245272f -->\n<!-- i18n-date: 2026-04-27 -->\n\n# リファクタリングカタログ\n\nMartin Fowler 著『Refactoring』(第 2 版) から厳選したリファクタリング技法のカタログである。各リファクタリングには動機、手順、例を掲載している。\n\n> 「リファクタリングは、その手順、すなわち変更を実施するための正確なステップ列によって定義される。」 — Martin Fowler\n\n---\n\n## このカタログの使い方\n\n1. コードスメルのリファレンスを使って **コードスメルを特定する**\n2. このカタログから **対応するリファクタリングを探す**\n3. **手順に沿って一段ずつ進める**\n4. **各ステップごとにテスト** を実行し、振る舞いが保たれていることを確認する\n\n**鉄則**: ある手順に 10 分以上かかるのであれば、もっと小さなステップに分割すること。\n\n---\n\n## 最も頻出するリファクタリング\n\n### メソッドの抽出 (Extract Method)\n\n**使う場面**: 長いメソッド、重複コード、概念に名前を付けたいとき\n\n**動機**: コード片を、目的を表す名前を持つメソッドに切り出す。\n\n**手順**:\n1. やっていること(どうやってではなく)にちなんだ名前で新しいメソッドを作成する\n2. コード片を新しいメソッドへコピーする\n3. コード片で使われているローカル変数を洗い出す\n4. ローカル変数をパラメータとして渡す(あるいはメソッド内で宣言する)\n5. 戻り値を適切に処理する\n6. 元のコード片を新しいメソッドの呼び出しに置き換える\n7. テストする\n\n**Before**:\n```javascript\nfunction printOwing(invoice) {\n  let outstanding = 0;\n\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n\n  // 未払額の計算\n  for (const order of invoice.orders) {\n    outstanding += order.amount;\n  }\n\n  // 詳細の出力\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n**After**:\n```javascript\nfunction printOwing(invoice) {\n  printBanner();\n  const outstanding = calculateOutstanding(invoice);\n  printDetails(invoice, outstanding);\n}\n\nfunction printBanner() {\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n}\n\nfunction calculateOutstanding(invoice) {\n  return invoice.orders.reduce((sum, order) => sum + order.amount, 0);\n}\n\nfunction printDetails(invoice, outstanding) {\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n---\n\n### メソッドのインライン化 (Inline Method)\n\n**使う場面**: メソッド本体が名前と同じくらい明快な場合、過度な委譲が見られる場合\n\n**動機**: メソッドが価値を加えていない場合、不要な間接参照を取り除く。\n\n**手順**:\n1. メソッドがポリモーフィックでないことを確認する\n2. メソッドの呼び出し箇所をすべて見つける\n3. 各呼び出しをメソッド本体で置き換える\n4. 置き換えるたびにテストする\n5. メソッド定義を削除する\n\n**Before**:\n```javascript\nfunction getRating(driver) {\n  return moreThanFiveLateDeliveries(driver) ? 2 : 1;\n}\n\nfunction moreThanFiveLateDeliveries(driver) {\n  return driver.numberOfLateDeliveries > 5;\n}\n```\n\n**After**:\n```javascript\nfunction getRating(driver) {\n  return driver.numberOfLateDeliveries > 5 ? 2 : 1;\n}\n```\n\n---\n\n### 変数の抽出 (Extract Variable)\n\n**使う場面**: 複雑で理解しづらい式があるとき\n\n**動機**: 複雑な式の一部に名前を付ける。\n\n**手順**:\n1. 式に副作用がないことを確認する\n2. イミュータブルな変数を宣言する\n3. 式(または式の一部)の結果をその変数に代入する\n4. 元の式を変数で置き換える\n5. テストする\n\n**Before**:\n```javascript\nreturn order.quantity * order.itemPrice -\n  Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +\n  Math.min(order.quantity * order.itemPrice * 0.1, 100);\n```\n\n**After**:\n```javascript\nconst basePrice = order.quantity * order.itemPrice;\nconst quantityDiscount = Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;\nconst shipping = Math.min(basePrice * 0.1, 100);\nreturn basePrice - quantityDiscount + shipping;\n```\n\n---\n\n### 変数のインライン化 (Inline Variable)\n\n**使う場面**: 変数名が式以上の情報を伝えていないとき\n\n**動機**: 不要な間接参照を取り除く。\n\n**手順**:\n1. 右辺に副作用がないことを確認する\n2. 変数がイミュータブルでなければイミュータブルにし、テストする\n3. 最初の参照箇所を見つけて式で置き換える\n4. テストする\n5. すべての参照箇所について繰り返す\n6. 宣言と代入を削除する\n7. テストする\n\n---\n\n### 変数名の変更 (Rename Variable)\n\n**使う場面**: 名前が目的を明確に伝えていないとき\n\n**動機**: クリーンなコードには良い名前が不可欠である。\n\n**手順**:\n1. 変数が広く使われている場合は、カプセル化を検討する\n2. すべての参照箇所を見つける\n3. 各参照箇所を変更する\n4. テストする\n\n**Tips**:\n- 意図を明らかにする名前を使う\n- 略語を避ける\n- ドメイン用語を用いる\n\n```javascript\n// 悪い例\nconst d = 30;\nconst x = users.filter(u => u.a);\n\n// 良い例\nconst daysSinceLastLogin = 30;\nconst activeUsers = users.filter(user => user.isActive);\n```\n\n---\n\n### 関数宣言の変更 (Change Function Declaration)\n\n**使う場面**: 関数名が目的を表していない、パラメータの変更が必要な場合\n\n**動機**: 良い関数名はコードを自己説明的にする。\n\n**手順 (シンプル版)**:\n1. 不要なパラメータを削除する\n2. 名前を変更する\n3. 必要なパラメータを追加する\n4. テストする\n\n**手順 (マイグレーション版 — 複雑な変更向け)**:\n1. パラメータを削除する場合、それが使われていないことを確認する\n2. 望ましい宣言の新しい関数を作成する\n3. 古い関数から新しい関数を呼び出すようにする\n4. テストする\n5. 呼び出し側を新しい関数を使うように変更する\n6. 各変更後にテストする\n7. 古い関数を削除する\n\n**Before**:\n```javascript\nfunction circum(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n**After**:\n```javascript\nfunction circumference(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n---\n\n### 変数のカプセル化 (Encapsulate Variable)\n\n**使う場面**: データに複数箇所から直接アクセスしているとき\n\n**動機**: データ操作のための明確なアクセスポイントを提供する。\n\n**手順**:\n1. getter と setter 関数を作成する\n2. すべての参照箇所を見つける\n3. 読み取りを getter で置き換える\n4. 書き込みを setter で置き換える\n5. 各変更後にテストする\n6. 変数の可視性を制限する\n\n**Before**:\n```javascript\nlet defaultOwner = { firstName: \"Martin\", lastName: \"Fowler\" };\n\n// 多くの場所で利用される\nspaceship.owner = defaultOwner;\n```\n\n**After**:\n```javascript\nlet defaultOwnerData = { firstName: \"Martin\", lastName: \"Fowler\" };\n\nfunction defaultOwner() { return defaultOwnerData; }\nfunction setDefaultOwner(arg) { defaultOwnerData = arg; }\n\nspaceship.owner = defaultOwner();\n```\n\n---\n\n### パラメータオブジェクトの導入 (Introduce Parameter Object)\n\n**使う場面**: いくつかのパラメータがしばしばまとまって登場する場合\n\n**動機**: 自然にまとまるべきデータをグループ化する。\n\n**手順**:\n1. グループ化したパラメータ用の新しいクラス/構造体を作成する\n2. テストする\n3. 「関数宣言の変更」で新しいオブジェクトを追加する\n4. テストする\n5. グループ内の各パラメータについて、関数から取り除き新しいオブジェクトを使うようにする\n6. 各変更後にテストする\n\n**Before**:\n```javascript\nfunction amountInvoiced(startDate, endDate) { ... }\nfunction amountReceived(startDate, endDate) { ... }\nfunction amountOverdue(startDate, endDate) { ... }\n```\n\n**After**:\n```javascript\nclass DateRange {\n  constructor(start, end) {\n    this.start = start;\n    this.end = end;\n  }\n}\n\nfunction amountInvoiced(dateRange) { ... }\nfunction amountReceived(dateRange) { ... }\nfunction amountOverdue(dateRange) { ... }\n```\n\n---\n\n### 関数群のクラス化 (Combine Functions into Class)\n\n**使う場面**: 複数の関数が同じデータを操作している場合\n\n**動機**: 関数を、それらが操作するデータと共にまとめる。\n\n**手順**:\n1. 共通データに「レコードのカプセル化 (Encapsulate Record)」を適用する\n2. 各関数をクラス内に移動する\n3. 移動するたびにテストする\n4. データ引数をクラスのフィールド利用に置き換える\n\n**Before**:\n```javascript\nfunction base(reading) { ... }\nfunction taxableCharge(reading) { ... }\nfunction calculateBaseCharge(reading) { ... }\n```\n\n**After**:\n```javascript\nclass Reading {\n  constructor(data) { this._data = data; }\n\n  get base() { ... }\n  get taxableCharge() { ... }\n  get calculateBaseCharge() { ... }\n}\n```\n\n---\n\n### 段階の分割 (Split Phase)\n\n**使う場面**: コードが 2 つの異なる事柄を扱っている場合\n\n**動機**: コードを明確な境界を持つ別々のフェーズに分離する。\n\n**手順**:\n1. 第 2 フェーズ用の関数を作成する\n2. テストする\n3. フェーズ間の中間データ構造を導入する\n4. テストする\n5. 第 1 フェーズを独立した関数として抽出する\n6. テストする\n\n**Before**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  const shippingPerCase = (basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = quantity * shippingPerCase;\n  return basePrice - discount + shippingCost;\n}\n```\n\n**After**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const priceData = calculatePricingData(product, quantity);\n  return applyShipping(priceData, shippingMethod);\n}\n\nfunction calculatePricingData(product, quantity) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  return { basePrice, quantity, discount };\n}\n\nfunction applyShipping(priceData, shippingMethod) {\n  const shippingPerCase = (priceData.basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = priceData.quantity * shippingPerCase;\n  return priceData.basePrice - priceData.discount + shippingCost;\n}\n```\n\n---\n\n## 機能の移動\n\n### メソッドの移動 (Move Method)\n\n**使う場面**: メソッドが自分のクラスより他のクラスの機能を多く使っている場合\n\n**動機**: 関数を、最もよく利用するデータの近くに置く。\n\n**手順**:\n1. 自クラス内でメソッドが利用しているプログラム要素をすべて調べる\n2. メソッドがポリモーフィックかどうか確認する\n3. 移動先クラスにメソッドをコピーする\n4. 新しいコンテキストに合わせて調整する\n5. 元のメソッドが移動先に委譲するようにする\n6. テストする\n7. 元のメソッドの削除を検討する\n\n---\n\n### フィールドの移動 (Move Field)\n\n**使う場面**: フィールドが他のクラスでより多く使われている場合\n\n**動機**: データを、それを使う関数と共に保持する。\n\n**手順**:\n1. まだの場合はフィールドをカプセル化する\n2. テストする\n3. 移動先にフィールドを作成する\n4. 参照箇所を移動先のフィールドを使うように更新する\n5. テストする\n6. 元のフィールドを削除する\n\n---\n\n### 関数への文の移動 (Move Statements into Function)\n\n**使う場面**: 同じコードが必ずある関数呼び出しと一緒に現れる場合\n\n**動機**: 繰り返しコードを関数内に移動して重複を取り除く。\n\n**手順**:\n1. まだの場合は繰り返しコードを関数として抽出する\n2. その関数の中に文を移動する\n3. テストする\n4. 呼び出し側で単独の文が不要になったら削除する\n\n---\n\n### 呼び出し側への文の移動 (Move Statements to Callers)\n\n**使う場面**: 共通の振る舞いが呼び出し側ごとに異なる場合\n\n**動機**: 振る舞いを変える必要があるなら、関数の外に移す。\n\n**手順**:\n1. 移動するコードに「メソッドの抽出」を適用する\n2. 元の関数に「メソッドのインライン化」を適用する\n3. インライン化された呼び出しを削除する\n4. 抽出したコードを各呼び出し側に移動する\n5. テストする\n\n---\n\n## データの再編成\n\n### プリミティブをオブジェクトで置き換える (Replace Primitive with Object)\n\n**使う場面**: データ項目に単純な値以上の振る舞いが必要な場合\n\n**動機**: データを振る舞いと共にカプセル化する。\n\n**手順**:\n1. 「変数のカプセル化」を適用する\n2. シンプルな値クラスを作成する\n3. setter を新しいインスタンス生成に変更する\n4. getter を値の返却に変更する\n5. テストする\n6. 新しいクラスにより豊かな振る舞いを追加する\n\n**Before**:\n```javascript\nclass Order {\n  constructor(data) {\n    this.priority = data.priority; // 文字列: \"high\"、\"rush\" など\n  }\n}\n\n// 利用箇所\nif (order.priority === \"high\" || order.priority === \"rush\") { ... }\n```\n\n**After**:\n```javascript\nclass Priority {\n  constructor(value) {\n    if (!Priority.legalValues().includes(value))\n      throw new Error(`Invalid priority: ${value}`);\n    this._value = value;\n  }\n\n  static legalValues() { return ['low', 'normal', 'high', 'rush']; }\n  get value() { return this._value; }\n\n  higherThan(other) {\n    return Priority.legalValues().indexOf(this._value) >\n           Priority.legalValues().indexOf(other._value);\n  }\n}\n\n// 利用箇所\nif (order.priority.higherThan(new Priority(\"normal\"))) { ... }\n```\n\n---\n\n### 一時変数を問い合わせで置き換える (Replace Temp with Query)\n\n**使う場面**: 一時変数が式の結果を保持している場合\n\n**動機**: 式を関数として切り出すことでコードを明快にする。\n\n**手順**:\n1. 変数が一度だけ代入されていることを確認する\n2. 代入の右辺をメソッドとして抽出する\n3. 一時変数の参照箇所をメソッド呼び出しで置き換える\n4. テストする\n5. 一時変数の宣言と代入を削除する\n\n**Before**:\n```javascript\nconst basePrice = this._quantity * this._itemPrice;\nif (basePrice > 1000) {\n  return basePrice * 0.95;\n} else {\n  return basePrice * 0.98;\n}\n```\n\n**After**:\n```javascript\nget basePrice() {\n  return this._quantity * this._itemPrice;\n}\n\n// メソッド内\nif (this.basePrice > 1000) {\n  return this.basePrice * 0.95;\n} else {\n  return this.basePrice * 0.98;\n}\n```\n\n---\n\n## 条件記述の単純化\n\n### 条件記述の分解 (Decompose Conditional)\n\n**使う場面**: 複雑な条件分岐 (if-then-else) があるとき\n\n**動機**: 条件と動作を抽出して意図を明確にする。\n\n**手順**:\n1. 条件部分に「メソッドの抽出」を適用する\n2. then 節に「メソッドの抽出」を適用する\n3. else 節 (もしあれば) に「メソッドの抽出」を適用する\n\n**Before**:\n```javascript\nif (!aDate.isBefore(plan.summerStart) && !aDate.isAfter(plan.summerEnd)) {\n  charge = quantity * plan.summerRate;\n} else {\n  charge = quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n**After**:\n```javascript\nif (isSummer(aDate, plan)) {\n  charge = summerCharge(quantity, plan);\n} else {\n  charge = regularCharge(quantity, plan);\n}\n\nfunction isSummer(date, plan) {\n  return !date.isBefore(plan.summerStart) && !date.isAfter(plan.summerEnd);\n}\n\nfunction summerCharge(quantity, plan) {\n  return quantity * plan.summerRate;\n}\n\nfunction regularCharge(quantity, plan) {\n  return quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n---\n\n### 条件式の統合 (Consolidate Conditional Expression)\n\n**使う場面**: 同じ結果を返す条件が複数あるとき\n\n**動機**: それらの条件が単一のチェックであることを明らかにする。\n\n**手順**:\n1. 条件に副作用がないことを確認する\n2. 条件を `and` または `or` で結合する\n3. 結合した条件に「メソッドの抽出」を検討する\n\n**Before**:\n```javascript\nif (employee.seniority < 2) return 0;\nif (employee.monthsDisabled > 12) return 0;\nif (employee.isPartTime) return 0;\n```\n\n**After**:\n```javascript\nif (isNotEligibleForDisability(employee)) return 0;\n\nfunction isNotEligibleForDisability(employee) {\n  return employee.seniority < 2 ||\n         employee.monthsDisabled > 12 ||\n         employee.isPartTime;\n}\n```\n\n---\n\n### ガード節による入れ子の条件記述の置き換え (Replace Nested Conditional with Guard Clauses)\n\n**使う場面**: 入れ子の条件分岐が深く、流れを追いにくいとき\n\n**動機**: 特殊ケースにガード節を使い、通常フローを明確に保つ。\n\n**手順**:\n1. 特殊ケースの条件を見つける\n2. それらを早期 return するガード節で置き換える\n3. 各変更後にテストする\n\n**Before**:\n```javascript\nfunction payAmount(employee) {\n  let result;\n  if (employee.isSeparated) {\n    result = { amount: 0, reasonCode: \"SEP\" };\n  } else {\n    if (employee.isRetired) {\n      result = { amount: 0, reasonCode: \"RET\" };\n    } else {\n      result = calculateNormalPay(employee);\n    }\n  }\n  return result;\n}\n```\n\n**After**:\n```javascript\nfunction payAmount(employee) {\n  if (employee.isSeparated) return { amount: 0, reasonCode: \"SEP\" };\n  if (employee.isRetired) return { amount: 0, reasonCode: \"RET\" };\n  return calculateNormalPay(employee);\n}\n```\n\n---\n\n### ポリモーフィズムによる条件記述の置き換え (Replace Conditional with Polymorphism)\n\n**使う場面**: 型に基づく switch/case、型ごとに変化する条件ロジック\n\n**動機**: オブジェクト自身に振る舞いを担わせる。\n\n**手順**:\n1. クラス階層を作成する (なければ)\n2. オブジェクト生成にファクトリ関数を使う\n3. 条件ロジックをスーパークラスのメソッドに移す\n4. ケースごとにサブクラスのメソッドを作成する\n5. 元の条件記述を削除する\n\n**Before**:\n```javascript\nfunction plumages(birds) {\n  return birds.map(b => plumage(b));\n}\n\nfunction plumage(bird) {\n  switch (bird.type) {\n    case 'EuropeanSwallow':\n      return \"average\";\n    case 'AfricanSwallow':\n      return (bird.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n    case 'NorwegianBlueParrot':\n      return (bird.voltage > 100) ? \"scorched\" : \"beautiful\";\n    default:\n      return \"unknown\";\n  }\n}\n```\n\n**After**:\n```javascript\nclass Bird {\n  get plumage() { return \"unknown\"; }\n}\n\nclass EuropeanSwallow extends Bird {\n  get plumage() { return \"average\"; }\n}\n\nclass AfricanSwallow extends Bird {\n  get plumage() {\n    return (this.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n  }\n}\n\nclass NorwegianBlueParrot extends Bird {\n  get plumage() {\n    return (this.voltage > 100) ? \"scorched\" : \"beautiful\";\n  }\n}\n\nfunction createBird(data) {\n  switch (data.type) {\n    case 'EuropeanSwallow': return new EuropeanSwallow(data);\n    case 'AfricanSwallow': return new AfricanSwallow(data);\n    case 'NorwegianBlueParrot': return new NorwegianBlueParrot(data);\n    default: return new Bird(data);\n  }\n}\n```\n\n---\n\n### 特殊ケースの導入 (Introduce Special Case / Null Object)\n\n**使う場面**: 特殊ケースに対する null チェックが繰り返される場合\n\n**動機**: 特殊ケースを処理する特殊オブジェクトを返す。\n\n**手順**:\n1. 期待されるインターフェースを持つ特殊ケースクラスを作成する\n2. isSpecialCase チェックを追加する\n3. ファクトリメソッドを導入する\n4. null チェックを特殊ケースオブジェクトの利用で置き換える\n5. テストする\n\n**Before**:\n```javascript\nconst customer = site.customer;\n// ... 多数の箇所でチェック\nif (customer === \"unknown\") {\n  customerName = \"occupant\";\n} else {\n  customerName = customer.name;\n}\n```\n\n**After**:\n```javascript\nclass UnknownCustomer {\n  get name() { return \"occupant\"; }\n  get billingPlan() { return registry.defaultPlan; }\n}\n\n// ファクトリメソッド\nfunction customer(site) {\n  return site.customer === \"unknown\"\n    ? new UnknownCustomer()\n    : site.customer;\n}\n\n// 利用箇所 — null チェック不要\nconst customerName = customer.name;\n```\n\n---\n\n## API のリファクタリング\n\n### 問い合わせと変更の分離 (Separate Query from Modifier)\n\n**使う場面**: 関数が値を返すと同時に副作用も持つ場合\n\n**動機**: どの操作に副作用があるのかを明確にする。\n\n**手順**:\n1. 新しい問い合わせ関数を作成する\n2. 元の関数の戻り値ロジックをコピーする\n3. 元の関数を void を返すように変更する\n4. 戻り値を使っていた呼び出しを置き換える\n5. テストする\n\n**Before**:\n```javascript\nfunction alertForMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") {\n      setOffAlarms();\n      return \"Don\";\n    }\n    if (p === \"John\") {\n      setOffAlarms();\n      return \"John\";\n    }\n  }\n  return \"\";\n}\n```\n\n**After**:\n```javascript\nfunction findMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") return \"Don\";\n    if (p === \"John\") return \"John\";\n  }\n  return \"\";\n}\n\nfunction alertForMiscreant(people) {\n  if (findMiscreant(people) !== \"\") setOffAlarms();\n}\n```\n\n---\n\n### 関数のパラメータ化 (Parameterize Function)\n\n**使う場面**: 似たような処理を異なる値で行う関数が複数あるとき\n\n**動機**: パラメータを追加することで重複を取り除く。\n\n**手順**:\n1. 一つの関数を選ぶ\n2. 変動するリテラル用のパラメータを追加する\n3. 本体をそのパラメータを使うように変更する\n4. テストする\n5. 呼び出し側をパラメータ化された版を使うように変更する\n6. 不要になった関数を削除する\n\n**Before**:\n```javascript\nfunction tenPercentRaise(person) {\n  person.salary = person.salary * 1.10;\n}\n\nfunction fivePercentRaise(person) {\n  person.salary = person.salary * 1.05;\n}\n```\n\n**After**:\n```javascript\nfunction raise(person, factor) {\n  person.salary = person.salary * (1 + factor);\n}\n\n// 利用箇所\nraise(person, 0.10);\nraise(person, 0.05);\n```\n\n---\n\n### フラグ引数の削除 (Remove Flag Argument)\n\n**使う場面**: 関数の振る舞いを切り替えるブール型パラメータがある場合\n\n**動機**: 別々の関数を通して振る舞いを明示的にする。\n\n**手順**:\n1. フラグの値ごとに明示的な関数を作成する\n2. 各呼び出しを適切な新しい関数で置き換える\n3. 各変更後にテストする\n4. 元の関数を削除する\n\n**Before**:\n```javascript\nfunction bookConcert(customer, isPremium) {\n  if (isPremium) {\n    // プレミアム予約のロジック\n  } else {\n    // 通常予約のロジック\n  }\n}\n\nbookConcert(customer, true);\nbookConcert(customer, false);\n```\n\n**After**:\n```javascript\nfunction bookPremiumConcert(customer) {\n  // プレミアム予約のロジック\n}\n\nfunction bookRegularConcert(customer) {\n  // 通常予約のロジック\n}\n\nbookPremiumConcert(customer);\nbookRegularConcert(customer);\n```\n\n---\n\n## 継承の取り扱い\n\n### メソッドの引き上げ (Pull Up Method)\n\n**使う場面**: 同じメソッドが複数のサブクラスにあるとき\n\n**動機**: クラス階層内の重複を取り除く。\n\n**手順**:\n1. メソッド同士が同一であることを確認する\n2. シグネチャが同じであることを確認する\n3. スーパークラスに新しいメソッドを作成する\n4. 一つのサブクラスから本体をコピーする\n5. 一つのサブクラスからメソッドを削除し、テストする\n6. 他のサブクラスのメソッドも順次削除し、その都度テストする\n\n---\n\n### メソッドの押し下げ (Push Down Method)\n\n**使う場面**: サブクラスの一部のみに関係する振る舞いがあるとき\n\n**動機**: メソッドを使われる場所に置く。\n\n**手順**:\n1. メソッドを必要とする各サブクラスにコピーする\n2. スーパークラスからメソッドを削除する\n3. テストする\n4. 必要としないサブクラスからは削除する\n5. テストする\n\n---\n\n### サブクラスを委譲で置き換える (Replace Subclass with Delegate)\n\n**使う場面**: 継承が誤って使われている、もしくはより柔軟性が必要な場合\n\n**動機**: 適切な場面では継承よりコンポジションを優先する。\n\n**手順**:\n1. 委譲先用の空クラスを作成する\n2. 委譲先を保持するフィールドをホストクラスに追加する\n3. ホストから呼ばれる委譲先のコンストラクタを作成する\n4. 機能を委譲先へ移動する\n5. 移動するたびにテストする\n6. 継承を委譲で置き換える\n\n---\n\n## クラスの抽出 (Extract Class)\n\n**使う場面**: 複数の責務を持つ大きなクラスがあるとき\n\n**動機**: クラスを分割して単一責務を保つ。\n\n**手順**:\n1. 責務をどう分けるか決める\n2. 新しいクラスを作成する\n3. フィールドを元のクラスから新しいクラスへ移動する\n4. テストする\n5. メソッドを元のクラスから新しいクラスへ移動する\n6. 移動するたびにテストする\n7. 両クラスを見直して必要なら名前を変更する\n8. 新しいクラスをどう公開するかを決める\n\n**Before**:\n```javascript\nclass Person {\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get officeAreaCode() { return this._officeAreaCode; }\n  set officeAreaCode(arg) { this._officeAreaCode = arg; }\n  get officeNumber() { return this._officeNumber; }\n  set officeNumber(arg) { this._officeNumber = arg; }\n\n  get telephoneNumber() {\n    return `(${this._officeAreaCode}) ${this._officeNumber}`;\n  }\n}\n```\n\n**After**:\n```javascript\nclass Person {\n  constructor() {\n    this._telephoneNumber = new TelephoneNumber();\n  }\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get telephoneNumber() { return this._telephoneNumber.toString(); }\n  get officeAreaCode() { return this._telephoneNumber.areaCode; }\n  set officeAreaCode(arg) { this._telephoneNumber.areaCode = arg; }\n}\n\nclass TelephoneNumber {\n  get areaCode() { return this._areaCode; }\n  set areaCode(arg) { this._areaCode = arg; }\n  get number() { return this._number; }\n  set number(arg) { this._number = arg; }\n  toString() { return `(${this._areaCode}) ${this._number}`; }\n}\n```\n\n---\n\n## クイックリファレンス: スメルからリファクタリングへ\n\n| コードスメル | 主なリファクタリング | 代替 |\n|------------|-------------------|-------------|\n| 長すぎるメソッド (Long Method) | メソッドの抽出 | 一時変数を問い合わせで置き換える |\n| 重複コード (Duplicate Code) | メソッドの抽出 | メソッドの引き上げ |\n| 大きすぎるクラス (Large Class) | クラスの抽出 | サブクラスの抽出 |\n| 長すぎるパラメータリスト (Long Parameter List) | パラメータオブジェクトの導入 | オブジェクトそのものの受け渡し |\n| 機能の横恋慕 (Feature Envy) | メソッドの移動 | メソッドの抽出 + 移動 |\n| データのかたまり (Data Clumps) | クラスの抽出 | パラメータオブジェクトの導入 |\n| プリミティブ依存症 (Primitive Obsession) | プリミティブをオブジェクトで置き換える | タイプコードの置き換え |\n| switch 文 (Switch Statements) | ポリモーフィズムによる条件記述の置き換え | タイプコードの置き換え |\n| 一時的属性 (Temporary Field) | クラスの抽出 | Null オブジェクトの導入 |\n| メッセージの連鎖 (Message Chains) | 委譲の隠蔽 | メソッドの抽出 |\n| 仲介人 (Middle Man) | 中間者の除去 | メソッドのインライン化 |\n| 変更の分散 (Divergent Change) | クラスの抽出 | 段階の分割 |\n| 散弾銃手術 (Shotgun Surgery) | メソッドの移動 | クラスのインライン化 |\n| 死せるコード (Dead Code) | 死せるコードの除去 | - |\n| 投機的一般性 (Speculative Generality) | 階層の平坦化 | クラスのインライン化 |\n\n---\n\n## 参考文献\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- オンラインカタログ: https://refactoring.com/catalog/\n","ja/07-plugins/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=ja%2F07-plugins%2FREADME.md -->","ja/07-plugins/devops-automation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=ja%2F07-plugins%2Fdevops-automation%2FREADME.md -->","ja/07-plugins/documentation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=ja%2F07-plugins%2Fdocumentation%2FREADME.md -->","ja/07-plugins/documentation/commands/generate-readme.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=ja%2F07-plugins%2Fdocumentation%2Fcommands%2Fgenerate-readme.md -->","ja/07-plugins/pr-review/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=ja%2F07-plugins%2Fpr-review%2FREADME.md -->","ja/CLAUDE.md":"<!-- i18n-source: CLAUDE.md -->\n<!-- i18n-source-sha: a70777e -->\n<!-- i18n-date: 2026-04-27 -->\n\n# CLAUDE.md\n\nこのファイルは、本リポジトリ内のコードを扱う際の Claude Code（claude.ai/code）向けガイドである。\n\n## プロジェクト概要\n\nClaude How To は Claude Code 機能のチュートリアルリポジトリである。これは **ドキュメント・アズ・コード** であり、主な成果物は実行可能アプリケーションではなく、番号付きの学習モジュールに整理された Markdown ファイルである。\n\n**アーキテクチャ：** 各モジュール（01〜10）は Claude Code の特定の機能を、コピー＆ペースト可能なテンプレート、Mermaid 図、サンプルとともに解説する。ビルドシステムはドキュメントの品質を検証し、EPUB 電子書籍を生成する。\n\n## よく使うコマンド\n\n### pre-commit 品質チェック\n\nすべてのドキュメントは、コミット前に 5 つの品質チェックを通過しなければならない（pre-commit フックで自動実行される）：\n\n```bash\n# pre-commit フックをインストール（毎コミットで実行）\npre-commit install\n\n# 全チェックを手動で実行\npre-commit run --all-files\n```\n\n5 つのチェックは以下のとおり：\n1. **markdown-lint** — `markdownlint` による Markdown 構造とフォーマット\n2. **cross-references** — 内部リンク、アンカー、コードフェンスの構文（Python スクリプト）\n3. **mermaid-syntax** — すべての Mermaid 図が正しくパースされるかを検証（Python スクリプト）\n4. **link-check** — 外部 URL が到達可能か（Python スクリプト）\n5. **markdown-rendering** — Markdown が壊れずにレンダリングされるか（Python スクリプト）\n\nEPUB ビルドは pre-commit フック **ではない** — CI のみで実行される（`.github/workflows/test.yml` の `build-epub` ジョブ）。本全体をビルドするため時間がかかるからである。mermaid-syntax フックが同じ Pele バンドルですべての図をすでにレンダリングしている。\n\n### 開発環境のセットアップ\n\n```bash\n# uv（Python パッケージマネージャ）をインストール\npip install uv\n\n# 仮想環境を作成して Python 依存関係をインストール\nuv venv\nsource .venv/bin/activate\nuv pip install -r scripts/requirements-dev.txt\n\n# Node.js ツール（Markdown リンタ）をインストール\nnpm install -g markdownlint-cli\n\n# Mermaid 図は Pele でレンダリングする（Node.js >= 20 が必要。グローバルインストールは不要）\nnode --version\n\n# pre-commit フックをインストール\nuv pip install pre-commit\npre-commit install\n```\n\n### テスト\n\n`scripts/` 内の Python スクリプトはユニットテストを持つ：\n\n```bash\n# 全テストを実行\npytest scripts/tests/ -v\n\n# カバレッジ付きで実行\npytest scripts/tests/ -v --cov=scripts --cov-report=html\n\n# 特定のテストを実行\npytest scripts/tests/test_build_epub.py -v\n```\n\n### コード品質\n\n```bash\n# Python コードをリント・整形\nruff check scripts/\nruff format scripts/\n\n# セキュリティスキャン\nbandit -c scripts/pyproject.toml -r scripts/ --exclude scripts/tests/\n\n# 型チェック\nmypy scripts/ --ignore-missing-imports\n```\n\n### EPUB ビルド\n\n```bash\n# 電子書籍を生成（Mermaid 図は Pele でレンダリング／Node.js >= 20 が必要。固定バンドルは初回のみダウンロード）\nuv run scripts/build_epub.py\n\n# オプション付き\nuv run scripts/build_epub.py --verbose --output custom-name.epub --lang ja\n```\n\n## ディレクトリ構造\n\n```\n├── 01-slash-commands/      # ユーザーが起動するショートカット\n├── 02-memory/              # 永続コンテキストの例\n├── 03-skills/              # 再利用可能な能力\n├── 04-subagents/           # 専門 AI アシスタント\n├── 05-mcp/                 # Model Context Protocol の例\n├── 06-hooks/               # イベント駆動の自動化\n├── 07-plugins/             # バンドル機能\n├── 08-checkpoints/         # セッションのスナップショット\n├── 09-advanced-features/   # プランニング、シンキング、バックグラウンド\n├── 10-cli/                 # CLI リファレンス\n├── scripts/\n│   ├── build_epub.py           # EPUB ジェネレータ（Mermaid を Pele でレンダリング）\n│   ├── check_cross_references.py   # 内部リンクを検証\n│   ├── check_links.py          # 外部 URL を検証\n│   ├── check_mermaid.py        # Mermaid 構文を検証\n│   └── tests/                  # スクリプトのユニットテスト\n├── .pre-commit-config.yaml    # 品質チェック定義\n└── README.md               # メインガイド（モジュール索引も兼ねる）\n```\n\n## コンテンツ作成ガイド\n\n### モジュール構造\n番号付きフォルダはいずれも以下のパターンに従う：\n- **README.md** — 機能の概要と例\n- **サンプルファイル** — コピー＆ペースト可能なテンプレート（コマンドは `.md`、設定は `.json`、フックは `.sh`）\n- ファイルは機能の複雑さと依存関係に従って整理されている\n\n### Mermaid 図\n- すべての図は正常にパースできること（pre-commit フックで検査）\n- EPUB ビルドは Pele で図をレンダリングする（Node.js >= 20 が必要。固定バンドルは初回のみダウンロードされ、以降はオフラインで動作する）\n- フローチャート、シーケンス図、アーキテクチャ可視化に Mermaid を使用する\n\n### 相互参照\n- 内部リンクは相対パスを使う（例：`(01-slash-commands/README.md)`）\n- コードフェンスは言語指定が必須（例：` ```bash `、` ```python `）\n- アンカーリンクは `#heading-name` 形式\n\n### リンク検証\n- 外部 URL は到達可能であること（pre-commit フックで検査）\n- 一時的なコンテンツへのリンクは避ける\n- 可能な限りパーマリンクを使用する\n\n## 主要なアーキテクチャ上のポイント\n\n1. **番号付きフォルダは学習順序を示す** — 01〜10 のプレフィックスは Claude Code 機能の推奨学習順序を表す。この番号付けは意図的なものなので、アルファベット順に並べ替えてはならない。\n\n2. **スクリプトはユーティリティであり製品ではない** — `scripts/` の Python スクリプトはドキュメント品質と EPUB 生成を支援するものである。実際のコンテンツは番号付きモジュールフォルダにある。\n\n3. **pre-commit がゲートキーパー** — PR が承認される前に 5 つの品質チェックがすべて通過しなければならない。CI パイプラインは同じチェックを 2 回目のパスとして実行する。\n\n4. **Mermaid のレンダリングには Node.js >= 20 が必要** — EPUB ビルドは固定バージョンの Pele バンドルを Node.js で実行して図をレンダリングする（バンドルは初回のみダウンロードされ、sha256 で検証してキャッシュされる）。ここでビルドが失敗する場合は、Node.js >= 20 が未インストールか、バンドルのダウンロード失敗か、Mermaid 構文エラーが典型的な原因である。pre-commit の mermaid フックは pre-commit が用意する Node.js 22 で厳格モードで実行され、スキップせずに失敗する。EPUB ビルド自体は pre-commit では実行されず、CI のみで実行される。\n\n5. **これはチュートリアルでありライブラリではない** — コンテンツを追加する際は、明快な解説、コピー＆ペースト可能な例、視覚的な図を重視する。価値は概念を教えることにあり、再利用可能なコードを提供することではない。\n\n## コミット規約\n\nConventional Commits 形式に従う：\n- `feat(slash-commands): Add API documentation generator`\n- `docs(memory): Improve personal preferences example`\n- `fix(README): Correct table of contents link`\n- `refactor(hooks): Simplify hook configuration examples`\n\nスコープは該当するフォルダ名に合わせる。\n","uk/03-skills/blog-draft/SKILL.md":"---\nname: blog-draft\ndescription: Створення чернетки блог-посту з ідей та ресурсів. Використовуйте, коли користувачі хочуть написати блог-пост, створити контент з дослідження або підготувати статтю. Проводить через дослідження, мозковий штурм, складання плану та ітеративне написання з контролем версій.\n---\n\n## Введення користувача\n\n```text\n$ARGUMENTS\n```\n\nВи **ПОВИННІ** врахувати введення користувача перед продовженням. Користувач має надати:\n- **Ідея/Тема**: Основна концепція або тематика блог-посту\n- **Ресурси**: URL, файли або посилання на дослідження (необовʼязково, але рекомендовано)\n- **Цільова аудиторія**: Для кого блог-пост (необовʼязково)\n- **Тон/Стиль**: Формальний, невимушений, технічний тощо (необовʼязково)\n\n**ВАЖЛИВО**: Якщо користувач запитує оновлення **існуючого блог-посту**, пропустіть кроки 0-8 і починайте безпосередньо з **Кроку 9**. Спочатку прочитайте існуючий файл(и) чернетки, потім продовжуйте з процесом ітерації.\n\n## Потік виконання\n\nВиконуйте ці кроки послідовно. **Не пропускайте кроки та не продовжуйте без затвердження користувача, де це зазначено.**\n\n### Крок 0: Створення папки проєкту\n\n1. Згенерувати назву папки у форматі: `YYYY-MM-DD-short-topic-name`\n   - Використати сьогоднішню дату\n   - Створити короткий, URL-дружній slug з теми (малі літери, дефіси, макс. 5 слів)\n\n2. Створити структуру папок:\n   ```\n   blog-posts/\n   └── YYYY-MM-DD-short-topic-name/\n       └── resources/\n   ```\n\n3. Підтвердити створення папки з користувачем перед продовженням.\n\n### Крок 1: Дослідження та збір ресурсів\n\n1. Створити підпапку `resources/` у каталозі блог-посту\n\n2. Для кожного наданого ресурсу:\n   - **URL-адреси**: Отримати та зберегти ключову інформацію до `resources/` як markdown-файли\n   - **Файли**: Прочитати та підсумувати в `resources/`\n   - **Теми**: Використати веб-пошук для збору актуальної інформації\n\n3. Для кожного ресурсу створити файл резюме в `resources/`:\n   - `resources/source-1-[short-name].md`\n   - `resources/source-2-[short-name].md`\n   - тощо\n\n4. Кожне резюме має включати:\n   ```markdown\n   # Джерело: [Назва/URL]\n\n   ## Ключові тези\n   - Теза 1\n   - Теза 2\n\n   ## Релевантні цитати/дані\n   - Цитата або статистика 1\n   - Цитата або статистика 2\n\n   ## Як це стосується теми\n   Короткий опис релевантності\n   ```\n\n5. Представити резюме дослідження користувачу.\n\n### Крок 2: Мозковий штурм та уточнення\n\n1. На основі ідеї та досліджених ресурсів представити:\n   - **Основні теми**, виявлені з дослідження\n   - **Потенційні ракурси** для блог-посту\n   - **Ключові тези**, які слід розкрити\n   - **Прогалини** в інформації, що потребують уточнення\n\n2. Поставити уточнюючі запитання:\n   - Який головний висновок ви хочете донести до читачів?\n   - Чи є конкретні тези з дослідження, які хочете виділити?\n   - Яка цільова довжина? (коротка: 500-800 слів, середня: 1000-1500, довга: 2000+)\n   - Щось хочете виключити?\n\n3. **Чекати відповідей користувача перед продовженням.**\n\n### Крок 3: Запропонувати план\n\n1. Створити структурований план, що включає:\n\n   ```markdown\n   # План блог-посту: [Назва]\n\n   ## Метаінформація\n   - **Цільова аудиторія**: [хто]\n   - **Тон**: [стиль]\n   - **Цільова довжина**: [кількість слів]\n   - **Головний висновок**: [ключове повідомлення]\n\n   ## Запропонована структура\n\n   ### Зачіпка/Вступ\n   - Ідея вступної зачіпки\n   - Встановлення контексту\n   - Теза\n\n   ### Розділ 1: [Назва]\n   - Ключова теза A\n   - Ключова теза B\n   - Підтверджуючі докази з [джерела]\n\n   ### Розділ 2: [Назва]\n   - Ключова теза A\n   - Ключова теза B\n\n   [Продовжити для всіх розділів...]\n\n   ### Висновок\n   - Резюме ключових тез\n   - Заклик до дії або завершальна думка\n\n   ## Джерела для цитування\n   - Джерело 1\n   - Джерело 2\n   ```\n\n2. Представити план користувачу та **запитати затвердження або модифікації**.\n\n### Крок 4: Зберегти затверджений план\n\n1. Після затвердження плану користувачем зберегти його як `OUTLINE.md` у папці блог-посту.\n\n2. Підтвердити збереження плану.\n\n### Крок 5: Закомітити план (якщо в git-репо)\n\n1. Перевірити, чи поточний каталог є git-репозиторієм.\n\n2. Якщо так:\n   - Додати нові файли до індексу: папку блог-посту, ресурси та OUTLINE.md\n   - Створити коміт з повідомленням: `docs: Add outline for blog post - [topic-name]`\n   - Відправити на віддалений сервер\n\n3. Якщо не git-репо, пропустити цей крок та повідомити користувача.\n\n### Крок 6: Написати чернетку\n\n1. На основі затвердженого плану написати повну чернетку блог-посту.\n\n2. Точно дотримуватися структури з OUTLINE.md.\n\n3. Включити:\n   - Захопливий вступ із зачіпкою\n   - Чіткі заголовки розділів\n   - Підтверджуючі докази та приклади з дослідження\n   - Плавні переходи між розділами\n   - Сильний висновок з головною тезою\n   - **Цитування**: Усі порівняння, статистика, дані та фактичні твердження ПОВИННІ цитувати оригінальне джерело\n\n4. Зберегти чернетку як `draft-v0.1.md` у папці блог-посту.\n\n5. Формат:\n   ```markdown\n   # [Назва блог-посту]\n\n   *[Необовʼязково: підзаголовок або слоган]*\n\n   [Повний вміст з інлайн-цитатами...]\n\n   ---\n\n   ## Список джерел\n   - [1] Назва джерела 1 - URL або цитата\n   - [2] Назва джерела 2 - URL або цитата\n   - [3] Назва джерела 3 - URL або цитата\n   ```\n\n6. **Вимоги до цитування**:\n   - Кожна точка даних, статистика або порівняння ПОВИННІ мати інлайн-цитату\n   - Використовуйте нумеровані посилання [1], [2] тощо, або іменовані цитати [Назва джерела]\n   - Звʼязуйте цитати з розділом Список джерел наприкінці\n   - Приклад: «Дослідження показують, що 65% розробників віддають перевагу TypeScript [1]»\n   - Приклад: «React перевершує Vue за швидкістю рендерингу на 20% [React Benchmarks 2024]»\n\n### Крок 7: Закомітити чернетку (якщо в git-репо)\n\n1. Перевірити, чи в git-репозиторії.\n\n2. Якщо так:\n   - Додати файл чернетки до індексу\n   - Створити коміт з повідомленням: `docs: Add draft v0.1 for blog post - [topic-name]`\n   - Відправити на віддалений сервер\n\n3. Якщо не git-репо, пропустити та повідомити користувача.\n\n### Крок 8: Представити чернетку для перегляду\n\n1. Представити вміст чернетки користувачу.\n\n2. Запитати зворотний звʼязок:\n   - Загальне враження?\n   - Розділи, що потребують розширення або скорочення?\n   - Потрібні корекції тону?\n   - Відсутня інформація?\n   - Конкретні правки або переписування?\n\n3. **Чекати відповіді користувача.**\n\n### Крок 9: Ітерація або фіналізація\n\n**Якщо користувач запитує зміни:**\n1. Зафіксувати всі запитані модифікації\n2. Повернутися до Кроку 6 з такими змінами:\n   - Збільшити номер версії (v0.2, v0.3 тощо)\n   - Врахувати всі зауваження\n   - Зберегти як `draft-v[X.Y].md`\n   - Повторити Кроки 7-8\n\n**Якщо користувач затверджує:**\n1. Підтвердити фінальну версію чернетки\n2. За бажанням перейменувати на `final.md`\n3. Підсумувати процес створення блог-посту:\n   - Загальна кількість створених версій\n   - Ключові зміни між версіями\n   - Фінальна кількість слів\n   - Створені файли\n\n## Відстеження версій\n\nУсі чернетки зберігаються з інкрементальним версіонуванням:\n- `draft-v0.1.md` — початкова чернетка\n- `draft-v0.2.md` — після першого раунду зауважень\n- `draft-v0.3.md` — після другого раунду зауважень\n- тощо\n\nЦе дозволяє відстежувати еволюцію блог-посту та повертатися до попередніх версій за потреби.\n\n## Структура вихідних файлів\n\n```\nblog-posts/\n└── YYYY-MM-DD-topic-name/\n    ├── resources/\n    │   ├── source-1-name.md\n    │   ├── source-2-name.md\n    │   └── ...\n    ├── OUTLINE.md\n    ├── draft-v0.1.md\n    ├── draft-v0.2.md (якщо ітерації)\n    └── draft-v0.3.md (якщо більше ітерацій)\n```\n\n## Поради щодо якості\n\n- **Зачіпка**: Починайте з питання, дивовижного факту або знайомого сценарію\n- **Потік**: Кожен абзац має зʼєднуватися з наступним\n- **Докази**: Підтверджуйте твердження даними з дослідження\n- **Цитування**: ЗАВЖДИ цитуйте джерела для:\n  - Усіх статистик та даних (напр., «За даними [Джерело], 75%...»)\n  - Порівнянь між продуктами, сервісами або підходами (напр., «X працює у 2 рази швидше за Y [Джерело]»)\n  - Фактичних тверджень про ринкові тенденції, результати досліджень або бенчмарки\n  - Використовуйте інлайн-цитати у форматі: [Назва джерела] або [Автор, Рік]\n- **Голос**: Підтримуйте послідовний тон протягом усього тексту\n- **Довжина**: Дотримуйтесь цільової кількості слів\n- **Читабельність**: Використовуйте короткі абзаци, маркери де доречно\n- **CTA**: Завершуйте чітким закликом до дії або питанням, що провокує думки\n\n## Примітки\n\n- Завжди чекайте затвердження користувача у зазначених контрольних точках\n- Зберігайте всі версії чернеток для історії\n- Використовуйте веб-пошук для актуальної інформації, коли надані URL\n- Якщо ресурсів недостатньо, попросіть користувача надати більше або запропонуйте додаткове дослідження\n- Адаптуйте тон відповідно до цільової аудиторії (технічна, загальна, бізнес тощо)\n","uk/03-skills/brand-voice/SKILL.md":"---\nname: brand-voice\ndescription: Забезпечення відповідності всіх комунікацій голосу та тону бренду. Використовуйте при створенні маркетингових текстів, клієнтських комунікацій, публічного контенту, або коли користувачі згадують голос бренду, тон чи стиль написання.\nuser-invocable: false\n---\n\n# Навичка голосу бренду\n\n## Огляд\nЦя навичка забезпечує послідовність голосу бренду, тону та повідомлень у всіх комунікаціях.\n\n## Ідентичність бренду\n\n### Місія\nДопомогти командам автоматизувати робочі процеси розробки за допомогою AI\n\n### Цінності\n- **Простота**: Робити складне простим\n- **Надійність**: Непохитне виконання\n- **Розширення можливостей**: Дати простір людській креативності\n\n### Тон голосу\n- **Дружній, але професійний** — доступний, але не панібратський\n- **Зрозумілий і лаконічний** — уникати жаргону, пояснювати технічні концепції просто\n- **Впевнений** — ми знаємо, що робимо\n- **Емпатичний** — розуміємо потреби та болі користувачів\n\n## Рекомендації щодо написання\n\n### Рекомендовано ✅\n- Використовуйте «ви» при зверненні до читачів\n- Використовуйте активний стан: «Claude генерує звіти», а не «Звіти генеруються Claude»\n- Починайте з ціннісної пропозиції\n- Використовуйте конкретні приклади\n- Тримайте речення до 20 слів\n- Використовуйте списки для ясності\n- Включайте заклики до дії\n\n### Не рекомендовано ❌\n- Не використовуйте корпоративний жаргон\n- Не будьте поблажливими та не надмірно спрощуйте\n- Не використовуйте «ми вважаємо» або «ми думаємо»\n- Не використовуйте ВСІ ВЕЛИКІ ЛІТЕРИ, крім виділення\n- Не створюйте стіни тексту\n- Не припускайте наявність технічних знань\n\n## Словник\n\n### ✅ Бажані терміни\n- Claude (не «AI Claude»)\n- Генерація коду (не «автокодування»)\n- Агент (не «бот»)\n- Оптимізувати (не «революціонізувати»)\n- Інтегрувати (не «синергізувати»)\n\n### ❌ Уникати\n- «Передовий» (заїжджено)\n- «Проривний» (розмито)\n- «Левериджити» (корпоративний жаргон)\n- «Утилізувати» (використовуйте «використовувати»)\n- «Зміна парадигми» (незрозуміло)\n\n## Приклади\n\n### ✅ Вдалий приклад\n«Claude автоматизує ваш процес код-рев'ю. Замість ручної перевірки кожного PR, Claude перевіряє безпеку, продуктивність та якість — заощаджуючи вашій команді години щотижня.»\n\nЧому працює: Зрозуміла цінність, конкретні переваги, орієнтація на дію\n\n### ❌ Невдалий приклад\n«Claude левериджить передовий AI для надання комплексних рішень розробки програмного забезпечення.»\n\nЧому не працює: Розмито, корпоративний жаргон, немає конкретної цінності\n","uk/03-skills/claude-md/SKILL.md":"---\nname: claude-md\ndescription: Створення або оновлення файлів CLAUDE.md відповідно до найкращих практик для оптимального онбордингу AI-агента\n---\n\n## Введення користувача\n\n```text\n$ARGUMENTS\n```\n\nВи **ПОВИННІ** врахувати введення користувача перед продовженням (якщо не порожнє). Користувач може вказати:\n- `create` — створити новий CLAUDE.md з нуля\n- `update` — покращити існуючий CLAUDE.md\n- `audit` — проаналізувати та звітувати про якість поточного CLAUDE.md\n- Конкретний шлях для створення/оновлення (напр., `src/api/CLAUDE.md` для інструкцій, специфічних для каталогу)\n\n## Основні принципи\n\n**LLM не мають стану**: CLAUDE.md — головний файл проєкту, що завантажується в кожну розмову (разом з автоматичною пам'яттю та правилами без обмеження області). Він слугує головним документом онбордингу AI-агентів у вашу кодову базу.\n\n### Золоті правила\n\n1. **Менше — краще**: Найсучасніші LLM можуть дотримуватись ~150-200 інструкцій. Системний промпт Claude Code вже використовує ~50. Тримайте CLAUDE.md зосередженим та лаконічним.\n\n2. **Універсальна застосовність**: Включайте лише інформацію, релевантну для КОЖНОЇ сесії. Інструкції для конкретних завдань належать до окремих файлів.\n\n3. **Не використовуйте Claude як лінтер**: Рекомендації зі стилю роздувають контекст та погіршують дотримання інструкцій. Використовуйте натомість детерміністичні інструменти (prettier, eslint тощо).\n\n4. **Ніколи не генеруйте автоматично**: CLAUDE.md — найвпливовіша точка AI-системи. Створюйте його вручну з ретельним обмірковуванням.\n\n## Потік виконання\n\n### 1. Аналіз проєкту\n\nСпочатку проаналізуйте поточний стан проєкту:\n\n1. Перевірити наявні файли CLAUDE.md:\n   - Кореневий рівень: `./CLAUDE.md` або `.claude/CLAUDE.md`\n   - Специфічні для каталогу: `**/CLAUDE.md`\n   - Глобальний конфіг користувача: `~/.claude/CLAUDE.md`\n\n2. Визначити структуру проєкту:\n   - Технологічний стек (мови, фреймворки)\n   - Тип проєкту (монорепо, окремий додаток, бібліотека)\n   - Інструменти розробки (пакетний менеджер, система збірки, тест-раннер)\n\n3. Переглянути існуючу документацію:\n   - README.md\n   - CONTRIBUTING.md\n   - package.json, pyproject.toml, Cargo.toml тощо\n\n### 2. Стратегія контенту (ЩО, ЧОМУ, ЯК)\n\nСтруктуруйте CLAUDE.md навколо трьох вимірів:\n\n#### ЩО — Технологія та структура\n- Огляд технологічного стеку\n- Організація проєкту (особливо важливо для монорепо)\n- Ключові каталоги та їхнє призначення\n\n#### ЧОМУ — Призначення та контекст\n- Що робить проєкт\n- Чому були прийняті певні архітектурні рішення\n- За що відповідає кожен основний компонент\n\n#### ЯК — Робочий процес та конвенції\n- Робочий процес розробки (bun vs node, pip vs uv тощо)\n- Процедури та команди тестування\n- Методи верифікації та збірки\n- Критичні «підводні камені» або неочевидні вимоги\n\n### 3. Стратегія поступового розкриття\n\nДля великих проєктів рекомендуйте створити папку `agent_docs/`:\n\n```\nagent_docs/\n  |- building_the_project.md\n  |- running_tests.md\n  |- code_conventions.md\n  |- architecture_decisions.md\n```\n\nУ CLAUDE.md посилайтесь на ці файли інструкціями:\n```markdown\nFor detailed build instructions, refer to `agent_docs/building_the_project.md`\n```\n\n**Важливо**: Використовуйте посилання `файл:рядок` замість фрагментів коду, щоб уникнути застарілого контексту.\n\n### 4. Обмеження якості\n\nПри створенні або оновленні CLAUDE.md:\n\n1. **Цільова довжина**: Менше 200 рядків\n2. **Без правил стилю**: Видалити будь-які інструкції лінтингу/форматування\n3. **Без інструкцій для конкретних завдань**: Перемістити до окремих файлів\n4. **Без фрагментів коду**: Використовувати посилання на файли замість цього\n5. **Без надлишкової інформації**: Не повторювати те, що є в package.json або README\n\n### 5. Обовʼязкові секції\n\nДобре структурований CLAUDE.md має включати:\n\n```markdown\n# Назва проєкту\n\nКороткий однорядковий опис.\n\n## Технологічний стек\n- Основна мова та версія\n- Ключові фреймворки/бібліотеки\n- База даних/сховище (якщо є)\n\n## Структура проєкту\n[Лише для монорепо або складних структур]\n- `apps/` - Точки входу додатків\n- `packages/` - Спільні бібліотеки\n\n## Команди розробки\n- Встановлення: `команда`\n- Тестування: `команда`\n- Збірка: `команда`\n\n## Критичні конвенції\n[Лише неочевидні, високовпливові конвенції]\n- Конвенція 1 з коротким поясненням\n- Конвенція 2 з коротким поясненням\n\n## Відомі проблеми / Підводні камені\n[Речі, що постійно створюють труднощі розробникам]\n- Проблема 1\n- Проблема 2\n```\n\n### 6. Антипатерни, яких слід уникати\n\n**НЕ включайте:**\n- Рекомендації зі стилю коду (використовуйте лінтери)\n- Документацію щодо використання Claude\n- Довгі пояснення очевидних патернів\n- Скопійовані приклади коду\n- Загальні найкращі практики («пишіть чистий код»)\n- Інструкції для конкретних завдань\n- Автозгенерований контент\n- Розлогі списки TODO\n\n### 7. Контрольний список валідації\n\nПеред фіналізацією перевірте:\n\n- [ ] Менше 200 рядків\n- [ ] Кожен рядок застосовний до ВСІХ сесій\n- [ ] Без правил стилю/форматування\n- [ ] Без фрагментів коду (використані посилання на файли)\n- [ ] Команди перевірені на працездатність\n- [ ] Поступове розкриття використано для складних проєктів\n- [ ] Критичні підводні камені задокументовані\n- [ ] Немає надлишковості з README.md\n\n## Формат виводу\n\n### Для `create` або за замовчуванням:\n\n1. Проаналізувати проєкт\n2. Створити чернетку CLAUDE.md за структурою вище\n3. Представити чернетку для перегляду\n4. Записати у відповідне місце після затвердження\n\n### Для `update`:\n\n1. Прочитати існуючий CLAUDE.md\n2. Аудит за найкращими практиками\n3. Визначити:\n   - Контент для видалення (правила стилю, фрагменти коду, специфічне для завдань)\n   - Контент для скорочення\n   - Відсутню важливу інформацію\n4. Представити зміни для перегляду\n5. Застосувати зміни після затвердження\n\n### Для `audit`:\n\n1. Прочитати існуючий CLAUDE.md\n2. Згенерувати звіт з:\n   - Поточна кількість рядків vs ціль\n   - Відсоток універсально застосовного контенту\n   - Список знайдених антипатернів\n   - Рекомендації для покращення\n3. НЕ модифікувати файл, лише звітувати\n\n## Обробка AGENTS.md\n\nЯкщо користувач запитує створення/оновлення AGENTS.md:\n\n**Починаючи з v2.1.277, Claude Code читає `AGENTS.md` напряму як інструкції проєкту** — але лише тоді, коли ні в робочому каталозі, ні в жодному каталозі вище немає `CLAUDE.md`, `.claude/CLAUDE.md` чи `CLAUDE.local.md`. `~/.claude/CLAUDE.md`, керований CLAUDE.md і `.claude/rules/` не враховуються в цій перевірці та завантажуються паралельно. Поведінку визначає **Project instructions** у `/config`: `claude-md-or-agents-md` (за замовчуванням), `claude-md-and-agents-md`, `claude-md` або `managed-only`. Там, де пряме читання недоступне — версії до v2.1.277 (до v2.1.281 на Bedrock/Vertex/Foundry, за LLM-шлюзами або з вимкненою телеметрією) або перша сесія після оновлення — використовуйте запасний варіант: імпортуйте файл з CLAUDE.md через `@AGENTS.md` або зробіть `CLAUDE.md` символічним посиланням на нього.\n\nAGENTS.md — це міжінструментальний файл контексту проєкту, тобто документ тієї ж *категорії*, що й CLAUDE.md, а не формат визначення агентів. Він існує для того, щоб кілька кодових агентів могли користуватися спільним набором конвенцій проєкту:\n- Команди збірки, тестування та лінтингу\n- Стиль коду та архітектурні конвенції\n- Структура репозиторію та розташування компонентів\n\nСубагенти визначаються окремо — у `.claude/agents/*.md`, а не в AGENTS.md.\n\nЗастосовуйте аналогічні принципи:\n- Тримайте зосередженим та лаконічним\n- Використовуйте поступове розкриття\n- Посилайтесь на зовнішні документи замість вбудовування контенту\n\n## Примітки\n\n- Завжди перевіряйте працездатність команд перед їх включенням\n- Якщо сумніваєтесь — не включайте; менше — краще\n- Системне нагадування повідомляє Claude, що CLAUDE.md «може бути або не бути релевантним» — чим більше шуму, тим більше він ігнорується\n- Монорепо найбільше виграють від чіткої структури ЩО/ЧОМУ/ЯК\n- Файли CLAUDE.md для конкретних каталогів мають бути ще більш зосередженими\n\n---\n\n**Останнє оновлення**: 18 жовтня 2026\n**Версія Claude Code**: 2.1.302\n**Джерела**:\n- https://code.claude.com/docs/en/memory\n","uk/03-skills/code-review-specialist/SKILL.md":"---\nname: code-review-specialist\ndescription: Комплексне код-рев'ю з аналізом безпеки, продуктивності та якості. Використовуйте, коли користувачі просять переглянути код, проаналізувати якість коду, оцінити pull request, або згадують код-рев'ю, аналіз безпеки чи оптимізацію продуктивності.\n---\n\n# Навичка код-рев'ю\n\nЦя навичка забезпечує комплексні можливості код-рев'ю з фокусом на:\n\n1. **Аналіз безпеки**\n   - Проблеми автентифікації/авторизації\n   - Ризики розкриття даних\n   - Вразливості інʼєкцій\n   - Криптографічні слабкості\n   - Логування чутливих даних\n\n2. **Аналіз продуктивності**\n   - Ефективність алгоритмів (аналіз Big O)\n   - Оптимізація памʼяті\n   - Оптимізація запитів до БД\n   - Можливості кешування\n   - Проблеми конкурентності\n\n3. **Якість коду**\n   - Принципи SOLID\n   - Патерни проєктування\n   - Конвенції іменування\n   - Документація\n   - Покриття тестами\n\n4. **Супровідність**\n   - Читабельність коду\n   - Розмір функцій (має бути < 50 рядків)\n   - Цикломатична складність\n   - Управління залежностями\n   - Безпека типів\n\n## Шаблон рев'ю\n\nДля кожного фрагмента перевіреного коду надати:\n\n### Резюме\n- Загальна оцінка якості (1-5)\n- Кількість виявлених проблем\n- Рекомендовані пріоритетні зони\n\n### Критичні проблеми (якщо є)\n- **Проблема**: Чіткий опис\n- **Розташування**: Файл і номер рядка\n- **Вплив**: Чому це важливо\n- **Серйозність**: Критична/Висока/Середня\n- **Виправлення**: Приклад коду\n\n### Знахідки за категоріями\n\n#### Безпека (якщо знайдено проблеми)\nПерелік вразливостей безпеки з прикладами\n\n#### Продуктивність (якщо знайдено проблеми)\nПерелік проблем продуктивності з аналізом складності\n\n#### Якість (якщо знайдено проблеми)\nПерелік проблем якості коду з пропозиціями рефакторингу\n\n#### Супровідність (якщо знайдено проблеми)\nПерелік проблем супровідності з покращеннями\n\n## Історія версій\n\n- v1.0.0 (2024-12-10): Початковий випуск з аналізом безпеки, продуктивності, якості та супровідності\n","uk/03-skills/doc-generator/SKILL.md":"---\nname: doc-generator\ndescription: Генерація вичерпної, точної документації API з вихідного коду. Використовуйте при створенні або оновленні документації API, генерації специфікацій OpenAPI, або коли користувачі згадують документацію API, ендпоінти чи документацію.\n---\n\n# Навичка генерації документації API\n\n## Генерує\n\n- Специфікації OpenAPI/Swagger\n- Документацію ендпоінтів API\n- Приклади використання SDK\n- Посібники з інтеграції\n- Довідники кодів помилок\n- Посібники з автентифікації\n\n## Структура документації\n\n### Для кожного ендпоінту\n\n````markdown\n## GET /api/v1/users/:id\n\n### Опис\nКороткий опис призначення цього ендпоінту\n\n### Параметри\n\n| Назва | Тип | Обовʼязковий | Опис |\n|-------|-----|-------------|------|\n| id | string | Так | ID користувача |\n\n### Відповідь\n\n**200 Успіх**\n```json\n{\n  \"id\": \"usr_123\",\n  \"name\": \"John Doe\",\n  \"email\": \"john@example.com\",\n  \"created_at\": \"2025-01-15T10:30:00Z\"\n}\n```\n\n**404 Не знайдено**\n```json\n{\n  \"error\": \"USER_NOT_FOUND\",\n  \"message\": \"Користувач не існує\"\n}\n```\n\n### Приклади\n\n**cURL**\n```bash\ncurl -X GET \"https://api.example.com/api/v1/users/usr_123\" \\\n  -H \"Authorization: Bearer YOUR_TOKEN\"\n```\n\n**JavaScript**\n```javascript\nconst user = await fetch('/api/v1/users/usr_123', {\n  headers: { 'Authorization': 'Bearer token' }\n}).then(r => r.json());\n```\n\n**Python**\n```python\nresponse = requests.get(\n    'https://api.example.com/api/v1/users/usr_123',\n    headers={'Authorization': 'Bearer token'}\n)\nuser = response.json()\n```\n````\n","uk/03-skills/refactor/SKILL.md":"---\nname: refactor\ndescription: Систематичний рефакторинг коду на основі методології Мартіна Фаулера. Використовуйте, коли користувачі просять рефакторити код, покращити структуру коду, зменшити технічний борг, очистити застарілий код, усунути запахи коду (code smells) або покращити супровідність коду. Ця навичка проводить через поетапний підхід з дослідженням, плануванням та безпечною інкрементальною реалізацією.\n---\n\n# Навичка рефакторингу коду\n\nСистематичний підхід до рефакторингу коду на основі книги Мартіна Фаулера *Refactoring: Improving the Design of Existing Code* (2-ге видання). Ця навичка наголошує на безпечних, інкрементальних змінах, підкріплених тестами.\n\n> «Рефакторинг — це процес зміни програмної системи таким чином, що не змінює зовнішню поведінку коду, але покращує його внутрішню структуру.» — Мартін Фаулер\n\n## Основні принципи\n\n1. **Збереження поведінки**: Зовнішня поведінка повинна залишатися незмінною\n2. **Малі кроки**: Робити крихітні, тестовані зміни\n3. **Тест-орієнтованість**: Тести — це страхувальна сітка\n4. **Безперервність**: Рефакторинг — постійний процес, а не одноразова подія\n5. **Співпраця**: Затвердження користувача потрібне на кожній фазі\n\n## Огляд робочого процесу\n\n```\nФаза 1: Дослідження та аналіз\n    ↓\nФаза 2: Оцінка покриття тестами\n    ↓\nФаза 3: Виявлення запахів коду\n    ↓\nФаза 4: Створення плану рефакторингу\n    ↓\nФаза 5: Інкрементальна реалізація\n    ↓\nФаза 6: Перегляд та ітерація\n```\n\n---\n\n## Фаза 1: Дослідження та аналіз\n\n### Цілі\n- Зрозуміти структуру та призначення кодової бази\n- Визначити обсяг рефакторингу\n- Зібрати контекст про бізнес-вимоги\n\n### Запитання до користувача\nПеред початком уточніть:\n\n1. **Обсяг**: Які файли/модулі/функції потребують рефакторингу?\n2. **Цілі**: Які проблеми ви намагаєтесь вирішити? (читабельність, продуктивність, супровідність)\n3. **Обмеження**: Чи є зони, які НЕ слід змінювати?\n4. **Тиск термінів**: Чи блокує це іншу роботу?\n5. **Стан тестів**: Чи існують тести? Чи проходять вони?\n\n### Дії\n- [ ] Прочитати та зрозуміти цільовий код\n- [ ] Виявити залежності та інтеграції\n- [ ] Задокументувати поточну архітектуру\n- [ ] Зафіксувати існуючі маркери технічного боргу (TODOs, FIXMEs)\n\n### Вивід\nПредставити знахідки користувачу:\n- Резюме структури коду\n- Виявлені проблемні зони\n- Початкові рекомендації\n- **Запросити затвердження для продовження**\n\n---\n\n## Фаза 2: Оцінка покриття тестами\n\n### Чому тести важливі\n> «Рефакторинг без тестів — як їзда без пасків безпеки.» — Мартін Фаулер\n\nТести — **ключовий засіб** безпечного рефакторингу. Без них ви ризикуєте внести помилки.\n\n### Кроки оцінки\n\n1. **Перевірити наявні тести**\n   ```bash\n   # Пошук файлів тестів\n   find . -name \"*test*\" -o -name \"*spec*\" | head -20\n   ```\n\n2. **Запустити існуючі тести**\n   ```bash\n   # JavaScript/TypeScript\n   npm test\n\n   # Python\n   pytest -v\n\n   # Java\n   mvn test\n   ```\n\n3. **Перевірити покриття (якщо доступно)**\n   ```bash\n   # JavaScript\n   npm run test:coverage\n\n   # Python\n   pytest --cov=.\n   ```\n\n### Точка рішення: Запитати користувача\n\n**Якщо тести існують та проходять:**\n- Перейти до Фази 3\n\n**Якщо тести відсутні або неповні:**\nПредставити варіанти:\n1. Спочатку написати тести (рекомендовано)\n2. Додавати тести інкрементально під час рефакторингу\n3. Продовжити без тестів (ризиковано — потребує підтвердження користувача)\n\n**Якщо тести не проходять:**\n- ЗУПИНИТИСЯ. Виправити тести перед рефакторингом\n- Запитати користувача: Чи слід спочатку виправити тести?\n\n### Рекомендації щодо написання тестів (якщо потрібно)\n\nДля кожної функції, що рефакториться, забезпечити тести для:\n- Успішний шлях (нормальна робота)\n- Граничні випадки (порожні введення, null, межі)\n- Сценарії помилок (невалідні введення, виключення)\n\nВикористовуйте цикл «red-green-refactor»:\n1. Написати тест, що не проходить (red)\n2. Зробити так, щоб пройшов (green)\n3. Рефакторити\n\n---\n\n## Фаза 3: Виявлення запахів коду\n\n### Що таке запахи коду?\nСимптоми глибших проблем у коді. Це не помилки, а індикатори того, що код можна покращити.\n\n### Типові запахи коду для перевірки\n\nДив. [references/code-smells.md](references/code-smells.md) для повного каталогу.\n\n#### Короткий довідник\n\n| Запах | Ознаки | Вплив |\n|-------|--------|-------|\n| **Довгий метод** | Методи > 30-50 рядків | Важко зрозуміти, тестувати, супроводжувати |\n| **Дубльований код** | Та сама логіка в кількох місцях | Виправлення помилок потрібне в кількох місцях |\n| **Великий клас** | Клас з занадто багатьма відповідальностями | Порушує принцип єдиної відповідальності |\n| **Заздрість до функцій** | Метод використовує дані іншого класу більше | Погана інкапсуляція |\n| **Одержимість примітивами** | Надмірне використання примітивів замість обʼєктів | Відсутні доменні концепції |\n| **Довгий список параметрів** | Методи з 4+ параметрами | Складно викликати правильно |\n| **Групи даних** | Ті самі елементи даних зʼявляються разом | Відсутня абстракція |\n| **Оператори Switch** | Складні ланцюжки switch/if-else | Важко розширювати |\n| **Спекулятивна загальність** | Код «на всякий випадок» | Зайва складність |\n| **Мертвий код** | Невикористаний код | Плутанина, тягар супровідності |\n\n### Кроки аналізу\n\n1. **Автоматичний аналіз** (якщо скрипти доступні)\n   ```bash\n   python scripts/detect-smells.py <file>\n   ```\n\n2. **Ручний перегляд**\n   - Систематично пройти код\n   - Зафіксувати кожен запах з розташуванням та серйозністю\n   - Категоризувати за впливом (Критичний/Високий/Середній/Низький)\n\n3. **Пріоритезація**\n   Зосередитися на запахах, які:\n   - Блокують поточну розробку\n   - Спричиняють помилки або плутанину\n   - Впливають на найчастіше змінювані шляхи коду\n\n### Вивід: Звіт про запахи\n\nПредставити користувачу:\n- Список виявлених запахів з розташуванням\n- Оцінку серйозності для кожного\n- Рекомендований порядок пріоритету\n- **Запросити затвердження пріоритетів**\n\n---\n\n## Фаза 4: Створення плану рефакторингу\n\n### Вибір рефакторингів\n\nДля кожного запаху обрати відповідний рефакторинг з каталогу.\n\nДив. [references/refactoring-catalog.md](references/refactoring-catalog.md) для повного списку.\n\n#### Відповідність запахів рефакторингам\n\n| Запах коду | Рекомендований рефакторинг |\n|------------|---------------------------|\n| Long Method | Extract Method, Replace Temp with Query |\n| Duplicated Code | Extract Method, Pull Up Method, Form Template Method |\n| Large Class | Extract Class, Extract Subclass |\n| Feature Envy | Move Method, Move Field |\n| Primitive Obsession | Replace Primitive with Object, Replace Type Code with Class |\n| Long Parameter List | Introduce Parameter Object, Preserve Whole Object |\n| Data Clumps | Extract Class, Introduce Parameter Object |\n| Switch Statements | Replace Conditional with Polymorphism |\n| Speculative Generality | Collapse Hierarchy, Inline Class, Remove Dead Code |\n| Dead Code | Remove Dead Code |\n\n### Структура плану\n\nВикористовуйте шаблон [templates/refactoring-plan.md](templates/refactoring-plan.md).\n\nДля кожного рефакторингу:\n1. **Ціль**: Який код зміниться\n2. **Запах**: Яку проблему вирішує\n3. **Рефакторинг**: Яку техніку застосувати\n4. **Кроки**: Детальні мікрокроки\n5. **Ризики**: Що може піти не так\n6. **Відкат**: Як скасувати за потреби\n\n### Поетапний підхід\n\n**КРИТИЧНО**: Впроваджуйте рефакторинг поступово, фазами.\n\n**Фаза A: Швидкі перемоги** (Низький ризик, висока цінність)\n- Перейменування змінних для ясності\n- Витяг очевидного дубльованого коду\n- Видалення мертвого коду\n\n**Фаза B: Структурні покращення** (Середній ризик)\n- Витяг методів з довгих функцій\n- Введення обʼєктів параметрів\n- Переміщення методів до відповідних класів\n\n**Фаза C: Архітектурні зміни** (Вищий ризик)\n- Заміна умовних конструкцій поліморфізмом\n- Витяг класів\n- Введення патернів проєктування\n\n### Точка рішення: Представити план користувачу\n\nПеред реалізацією:\n- Показати повний план рефакторингу\n- Пояснити кожну фазу та її ризики\n- Отримати явне затвердження для кожної фази\n- **Запитати**: «Чи продовжити з Фазою A?»\n\n---\n\n## Фаза 5: Інкрементальна реалізація\n\n### Золоте правило\n> «Зміна → Тест → Зелений? → Коміт → Наступний крок»\n\n### Ритм реалізації\n\nДля кожного кроку рефакторингу:\n\n1. **Попередня перевірка**\n   - Тести проходять (зелені)\n   - Код компілюється\n\n2. **Зробити ОДНУ малу зміну**\n   - Дотримуватися механіки з каталогу\n   - Тримати зміни мінімальними\n\n3. **Верифікація**\n   - Негайно запустити тести\n   - Перевірити на помилки компіляції\n\n4. **Якщо тести проходять (зелені)**\n   - Закомітити з описовим повідомленням\n   - Перейти до наступного кроку\n\n5. **Якщо тести не проходять (червоні)**\n   - ЗУПИНИТИСЯ негайно\n   - Скасувати зміну\n   - Проаналізувати, що пішло не так\n   - Запитати користувача, якщо незрозуміло\n\n### Стратегія комітів\n\nКожен коміт має бути:\n- **Атомарний**: Одна логічна зміна\n- **Оборотний**: Легко відкатити\n- **Описовий**: Зрозуміле повідомлення коміту\n\nПриклади повідомлень комітів:\n```\nrefactor: Extract calculateTotal() from processOrder()\nrefactor: Rename 'x' to 'customerCount' for clarity\nrefactor: Remove unused validateOldFormat() method\n```\n\n### Звіт про прогрес\n\nПісля кожної підфази звітувати користувачу:\n- Внесені зміни\n- Тести досі проходять?\n- Виявлені проблеми\n- **Запитати**: «Продовжити з наступною порцією?»\n\n---\n\n## Фаза 6: Перегляд та ітерація\n\n### Контрольний список після рефакторингу\n\n- [ ] Усі тести проходять\n- [ ] Немає нових попереджень/помилок\n- [ ] Код успішно компілюється\n- [ ] Поведінка не змінилася (ручна верифікація)\n- [ ] Документація оновлена за потреби\n- [ ] Історія комітів чиста\n\n### Порівняння метрик\n\nЗапустити аналіз складності до і після:\n```bash\npython scripts/analyze-complexity.py <file>\n```\n\nПредставити покращення:\n- Зміна кількості рядків коду\n- Зміна цикломатичної складності\n- Зміна індексу супровідності\n\n### Перегляд користувачем\n\nПредставити фінальні результати:\n- Резюме всіх змін\n- Порівняння коду до/після\n- Покращення метрик\n- Залишковий технічний борг\n- **Запитати**: «Чи задоволені ви цими змінами?»\n\n### Наступні кроки\n\nОбговорити з користувачем:\n- Додаткові запахи для усунення?\n- Запланувати подальший рефакторинг?\n- Застосувати аналогічні зміни в інших місцях?\n\n---\n\n## Важливі рекомендації\n\n### Коли ЗУПИНИТИСЯ та запитати\n\nЗавжди паузу та консультацію з користувачем, коли:\n- Невпевненість щодо бізнес-логіки\n- Зміна може вплинути на зовнішні API\n- Покриття тестами недостатнє\n- Потрібне значне архітектурне рішення\n- Рівень ризику зростає\n- Зустрічаєте неочікувану складність\n\n### Правила безпеки\n\n1. **Ніколи не рефакторити без тестів** (якщо користувач явно не підтвердив ризик)\n2. **Ніколи не робити великих змін** — розбивати на крихітні кроки\n3. **Ніколи не пропускати запуск тестів** після кожної зміни\n4. **Ніколи не продовжувати, якщо тести не проходять** — виправити або відкатити\n5. **Ніколи не припускати** — якщо сумніваєтесь, запитайте\n\n### Чого НЕ робити\n\n- Не поєднуйте рефакторинг з додаванням функцій\n- Не рефакторте під час аварій на продакшні\n- Не рефакторте код, який не розумієте\n- Не переускладнюйте — тримайте просто\n- Не рефакторте все одразу\n\n---\n\n## Приклад швидкого старту\n\n### Сценарій: Довгий метод з дублюванням\n\n**До:**\n```javascript\nfunction processOrder(order) {\n  // 150 рядків коду з:\n  // - Дубльованою логікою валідації\n  // - Інлайн-обчисленнями\n  // - Змішаними відповідальностями\n}\n```\n\n**Кроки рефакторингу:**\n\n1. **Переконатися, що тести існують** для processOrder()\n2. **Витягти** валідацію у validateOrder()\n3. **Тест** — має пройти\n4. **Витягти** обчислення у calculateOrderTotal()\n5. **Тест** — має пройти\n6. **Витягти** сповіщення у notifyCustomer()\n7. **Тест** — має пройти\n8. **Перегляд** — processOrder() тепер оркеструє 3 чіткі функції\n\n**Після:**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const total = calculateOrderTotal(order);\n  notifyCustomer(order, total);\n  return { order, total };\n}\n```\n\n---\n\n## Довідники\n\n- [Каталог запахів коду](references/code-smells.md) — повний список запахів коду\n- [Каталог рефакторингів](references/refactoring-catalog.md) — техніки рефакторингу\n- [Шаблон плану рефакторингу](templates/refactoring-plan.md) — шаблон планування\n\n## Скрипти\n\n- `scripts/analyze-complexity.py` — аналіз метрик складності коду\n- `scripts/detect-smells.py` — автоматичне виявлення запахів\n\n## Історія версій\n\n- v1.0.0 (2025-01-15): Початковий випуск з методологією Фаулера, поетапним підходом, точками консультації з користувачем\n","uk/03-skills/refactor/references/code-smells.md":"# Каталог запахів коду\n\nКомплексний довідник запахів коду на основі книги Мартіна Фаулера *Refactoring* (2-ге видання). Запахи коду — це симптоми глибших проблем; вони вказують на те, що щось може бути не так з дизайном вашого коду.\n\n> «Запах коду — це поверхнева ознака, яка зазвичай відповідає глибшій проблемі в системі.» — Мартін Фаулер\n\n---\n\n## Роздуті елементи (Bloaters)\n\nЗапахи коду, що представляють щось, що розрослося занадто великим для ефективної роботи.\n\n### Long Method (Довгий метод)\n\n**Ознаки:**\n- Метод перевищує 30-50 рядків\n- Потрібно прокручувати, щоб побачити весь метод\n- Кілька рівнів вкладеності\n- Коментарі пояснюють, що роблять секції\n\n**Чому це погано:**\n- Важко зрозуміти\n- Складно тестувати ізольовано\n- Зміни мають непередбачувані наслідки\n- Дубльована логіка ховається всередині\n\n**Рефакторинги:**\n- Extract Method\n- Replace Temp with Query\n- Introduce Parameter Object\n- Replace Method with Method Object\n- Decompose Conditional\n\n**Приклад (до):**\n```javascript\nfunction processOrder(order) {\n  // Валідація замовлення (20 рядків)\n  if (!order.items) throw new Error('No items');\n  if (order.items.length === 0) throw new Error('Empty order');\n  // ... ще валідація\n\n  // Обчислення підсумків (30 рядків)\n  let subtotal = 0;\n  for (const item of order.items) {\n    subtotal += item.price * item.quantity;\n  }\n  // ... податок, доставка, знижки\n\n  // Надсилання сповіщень (20 рядків)\n  // ... логіка email\n}\n```\n\n**Приклад (після):**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const totals = calculateOrderTotals(order);\n  sendOrderNotifications(order, totals);\n  return { order, totals };\n}\n```\n\n---\n\n### Large Class (Великий клас)\n\n**Ознаки:**\n- Клас має багато полів екземпляра (>7-10)\n- Клас має багато методів (>15-20)\n- Назва класу розмита (Manager, Handler, Processor)\n- Методи не використовують усі поля екземпляра\n\n**Чому це погано:**\n- Порушує принцип єдиної відповідальності\n- Важко тестувати\n- Зміни поширюються на неповʼязані функції\n- Складно повторно використовувати частини\n\n**Рефакторинги:**\n- Extract Class\n- Extract Subclass\n- Extract Interface\n\n**Виявлення:**\n```\nРядків коду > 300\nКількість методів > 15\nКількість полів > 10\n```\n\n---\n\n### Primitive Obsession (Одержимість примітивами)\n\n**Ознаки:**\n- Використання примітивів для доменних концепцій (string для email, int для грошей)\n- Масиви примітивів замість обʼєктів\n- Рядкові константи для кодів типів\n- Магічні числа/рядки\n\n**Чому це погано:**\n- Немає валідації на рівні типу\n- Логіка розкидана по кодовій базі\n- Легко передати неправильні значення\n- Відсутні доменні концепції\n\n**Рефакторинги:**\n- Replace Primitive with Object\n- Replace Type Code with Class\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**Приклад (до):**\n```javascript\nconst user = {\n  email: 'john@example.com',     // Просто рядок\n  phone: '1234567890',           // Просто рядок\n  status: 'active',              // Магічний рядок\n  balance: 10050                 // Копійки як ціле число\n};\n```\n\n**Приклад (після):**\n```javascript\nconst user = {\n  email: new Email('john@example.com'),\n  phone: new PhoneNumber('1234567890'),\n  status: UserStatus.ACTIVE,\n  balance: Money.cents(10050)\n};\n```\n\n---\n\n### Long Parameter List (Довгий список параметрів)\n\n**Ознаки:**\n- Методи з 4+ параметрами\n- Параметри, що завжди зʼявляються разом\n- Булеві прапорці, що змінюють поведінку методу\n- Часте передавання null/undefined\n\n**Чому це погано:**\n- Важко викликати правильно\n- Плутанина з порядком параметрів\n- Вказує, що метод робить занадто багато\n- Важко додавати нові параметри\n\n**Рефакторинги:**\n- Introduce Parameter Object\n- Preserve Whole Object\n- Replace Parameter with Method Call\n- Remove Flag Argument\n\n**Приклад (до):**\n```javascript\nfunction createUser(firstName, lastName, email, phone,\n                    street, city, state, zip,\n                    isAdmin, isActive, createdBy) {\n  // ...\n}\n```\n\n**Приклад (після):**\n```javascript\nfunction createUser(personalInfo, address, options) {\n  // personalInfo: { firstName, lastName, email, phone }\n  // address: { street, city, state, zip }\n  // options: { isAdmin, isActive, createdBy }\n}\n```\n\n---\n\n### Data Clumps (Групи даних)\n\n**Ознаки:**\n- Ті самі 3+ поля зʼявляються разом повторно\n- Параметри, що завжди подорожують разом\n- Класи з підмножинами полів, що належать один одному\n\n**Чому це погано:**\n- Дубльована логіка обробки\n- Відсутня абстракція\n- Важче розширювати\n- Вказує на прихований клас\n\n**Рефакторинги:**\n- Extract Class\n- Introduce Parameter Object\n- Preserve Whole Object\n\n**Приклад:**\n```javascript\n// Група даних: координати (x, y, z)\nfunction movePoint(x, y, z, dx, dy, dz) { }\nfunction scalePoint(x, y, z, factor) { }\nfunction distanceBetween(x1, y1, z1, x2, y2, z2) { }\n\n// Витяг класу Point3D\nclass Point3D {\n  constructor(x, y, z) { }\n  move(delta) { }\n  scale(factor) { }\n  distanceTo(other) { }\n}\n```\n\n---\n\n## Зловживання обʼєктною орієнтацією (OO Abusers)\n\nЗапахи, що вказують на неповне або некоректне використання принципів ООП.\n\n### Switch Statements (Оператори Switch)\n\n**Ознаки:**\n- Довгі ланцюжки switch/case або if/else\n- Той самий switch у кількох місцях\n- Switch за кодами типів\n- Додавання нових випадків вимагає змін всюди\n\n**Чому це погано:**\n- Порушує принцип відкритості/закритості\n- Зміни поширюються на всі місця з switch\n- Важко розширювати\n- Часто вказує на відсутній поліморфізм\n\n**Рефакторинги:**\n- Replace Conditional with Polymorphism\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**Приклад (до):**\n```javascript\nfunction calculatePay(employee) {\n  switch (employee.type) {\n    case 'hourly':\n      return employee.hours * employee.rate;\n    case 'salaried':\n      return employee.salary / 12;\n    case 'commissioned':\n      return employee.sales * employee.commission;\n  }\n}\n```\n\n**Приклад (після):**\n```javascript\nclass HourlyEmployee {\n  calculatePay() {\n    return this.hours * this.rate;\n  }\n}\n\nclass SalariedEmployee {\n  calculatePay() {\n    return this.salary / 12;\n  }\n}\n```\n\n---\n\n### Temporary Field (Тимчасове поле)\n\n**Ознаки:**\n- Поля екземпляра, що використовуються лише в деяких методах\n- Поля, що встановлюються умовно\n- Складна ініціалізація для певних випадків\n\n**Чому це погано:**\n- Плутанина — поле існує, але може бути null\n- Важко зрозуміти стан обʼєкта\n- Вказує на приховану умовну логіку\n\n**Рефакторинги:**\n- Extract Class\n- Introduce Null Object\n- Replace Temp Field with Local\n\n---\n\n### Refused Bequest (Відхилена спадщина)\n\n**Ознаки:**\n- Підклас не використовує успадковані методи/дані\n- Підклас перевизначає, щоб нічого не робити\n- Успадкування використовується для повторного використання коду, а не для відношення IS-A\n\n**Чому це погано:**\n- Неправильна абстракція\n- Порушує принцип підстановки Лісков\n- Оманлива ієрархія\n\n**Рефакторинги:**\n- Push Down Method/Field\n- Replace Subclass with Delegate\n- Replace Inheritance with Delegation\n\n---\n\n### Alternative Classes with Different Interfaces (Альтернативні класи з різними інтерфейсами)\n\n**Ознаки:**\n- Два класи, що роблять схожі речі\n- Різні назви методів для тієї самої концепції\n- Можуть використовуватися взаємозамінно\n\n**Чому це погано:**\n- Дубльовані реалізації\n- Немає спільного інтерфейсу\n- Важко перемикатися між ними\n\n**Рефакторинги:**\n- Rename Method\n- Move Method\n- Extract Superclass\n- Extract Interface\n\n---\n\n## Перешкоди для змін (Change Preventers)\n\nЗапахи, що ускладнюють зміни — зміна однієї речі вимагає зміни багатьох інших.\n\n### Divergent Change (Дивергентна зміна)\n\n**Ознаки:**\n- Один клас змінюється з кількох різних причин\n- Зміни в різних областях запускають редагування того самого класу\n- Клас є «God-класом»\n\n**Чому це погано:**\n- Порушує принцип єдиної відповідальності\n- Висока частота змін\n- Конфлікти злиття\n\n**Рефакторинги:**\n- Extract Class\n- Extract Superclass\n- Extract Subclass\n\n**Приклад:**\nКлас `User` змінюється через:\n- Зміни автентифікації\n- Зміни профілю\n- Зміни білінгу\n- Зміни сповіщень\n\n→ Витягти: `AuthService`, `ProfileService`, `BillingService`, `NotificationService`\n\n---\n\n### Shotgun Surgery (Хірургія дробовиком)\n\n**Ознаки:**\n- Одна зміна вимагає редагування в багатьох класах\n- Мала функція потребує правок у 10+ файлах\n- Зміни розкидані, важко знайти всі\n\n**Чому це погано:**\n- Легко пропустити місце\n- Високий звʼязок (coupling)\n- Зміни схильні до помилок\n\n**Рефакторинги:**\n- Move Method\n- Move Field\n- Inline Class\n\n**Виявлення:**\nШукайте: додавання одного поля вимагає змін у >5 файлах.\n\n---\n\n### Parallel Inheritance Hierarchies (Паралельні ієрархії успадкування)\n\n**Ознаки:**\n- Створення підкласу в одній ієрархії вимагає підкласу в іншій\n- Префікси класів збігаються (напр., `DatabaseOrder`, `DatabaseProduct`)\n\n**Чому це погано:**\n- Подвійне обслуговування\n- Звʼязок між ієрархіями\n- Легко забути одну сторону\n\n**Рефакторинги:**\n- Move Method\n- Move Field\n- Усунути одну ієрархію\n\n---\n\n## Непотрібне (Dispensables)\n\nЩось непотрібне, що слід видалити.\n\n### Comments (Надмірні коментарі)\n\n**Ознаки:**\n- Коментарі, що пояснюють, що робить код\n- Закоментований код\n- TODO/FIXME, що залишаються назавжди\n- Вибачення в коментарях\n\n**Чому це погано:**\n- Коментарі брешуть (розсинхронізуються)\n- Код має бути самодокументованим\n- Мертвий код створює плутанину\n\n**Рефакторинги:**\n- Extract Method (назва пояснює що)\n- Rename (ясність без коментарів)\n- Видалити закоментований код\n- Introduce Assertion\n\n**Хороші vs погані коментарі:**\n```javascript\n// ПОГАНО: Пояснює що\n// Цикл по користувачах і перевірка чи активні\nfor (const user of users) {\n  if (user.status === 'active') { }\n}\n\n// ДОБРЕ: Пояснює чому\n// Лише активні — неактивні обробляються задачею очищення\nconst activeUsers = users.filter(u => u.isActive);\n```\n\n---\n\n### Duplicate Code (Дубльований код)\n\n**Ознаки:**\n- Той самий код у кількох місцях\n- Схожий код з малими варіаціями\n- Патерни копі-пасту\n\n**Чому це погано:**\n- Виправлення помилок потрібне в кількох місцях\n- Ризик неконсистентності\n- Роздута кодова база\n\n**Рефакторинги:**\n- Extract Method\n- Extract Class\n- Pull Up Method (в ієрархіях)\n- Form Template Method\n\n**Правило виявлення:**\nБудь-який код, дубльований 3+ разів, слід витягти.\n\n---\n\n### Lazy Class (Ледачий клас)\n\n**Ознаки:**\n- Клас не робить достатньо для виправдання свого існування\n- Обгортка без доданої цінності\n- Результат надмірної інженерії\n\n**Чому це погано:**\n- Накладні витрати обслуговування\n- Непотрібна непрямість\n- Складність без користі\n\n**Рефакторинги:**\n- Inline Class\n- Collapse Hierarchy\n\n---\n\n### Dead Code (Мертвий код)\n\n**Ознаки:**\n- Недосяжний код\n- Невикористані змінні/методи/класи\n- Закоментований код\n- Код за неможливими умовами\n\n**Чому це погано:**\n- Плутанина\n- Тягар обслуговування\n- Уповільнює розуміння\n\n**Рефакторинги:**\n- Remove Dead Code\n- Safe Delete\n\n**Виявлення:**\n```bash\n# Шукати невикористані експорти\n# Шукати невикористані функції\n# Попередження IDE \"unused\"\n```\n\n---\n\n### Speculative Generality (Спекулятивна загальність)\n\n**Ознаки:**\n- Абстрактні класи з одним підкласом\n- Невикористані параметри «на майбутнє»\n- Методи, що лише делегують\n- «Фреймворк» для одного випадку\n\n**Чому це погано:**\n- Складність без користі\n- YAGNI (You Ain't Gonna Need It — Вам це не знадобиться)\n- Важче зрозуміти\n\n**Рефакторинги:**\n- Collapse Hierarchy\n- Inline Class\n- Remove Parameter\n- Rename Method\n\n---\n\n## Звʼязувачі (Couplers)\n\nЗапахи, що представляють надмірний звʼязок між класами.\n\n### Feature Envy (Заздрість до функцій)\n\n**Ознаки:**\n- Метод використовує більше даних іншого класу, ніж свого\n- Багато викликів геттерів іншого обʼєкта\n- Дані та поведінка розділені\n\n**Чому це погано:**\n- Неправильне розташування поведінки\n- Погана інкапсуляція\n- Важко супроводжувати\n\n**Рефакторинги:**\n- Move Method\n- Move Field\n- Extract Method (потім перемістити)\n\n**Приклад (до):**\n```javascript\nclass Order {\n  getDiscountedPrice(customer) {\n    // Інтенсивно використовує дані customer\n    if (customer.loyaltyYears > 5) {\n      return this.price * customer.discountRate;\n    }\n    return this.price;\n  }\n}\n```\n\n**Приклад (після):**\n```javascript\nclass Customer {\n  getDiscountedPriceFor(price) {\n    if (this.loyaltyYears > 5) {\n      return price * this.discountRate;\n    }\n    return price;\n  }\n}\n```\n\n---\n\n### Inappropriate Intimacy (Недоречна інтимність)\n\n**Ознаки:**\n- Класи отримують доступ до приватних частин один одного\n- Двосторонні посилання\n- Підкласи знають занадто багато про батьків\n\n**Чому це погано:**\n- Високий звʼязок\n- Зміни каскадуються\n- Важко модифікувати один без іншого\n\n**Рефакторинги:**\n- Move Method\n- Move Field\n- Change Bidirectional to Unidirectional\n- Extract Class\n- Hide Delegate\n\n---\n\n### Message Chains (Ланцюжки повідомлень)\n\n**Ознаки:**\n- Довгі ланцюжки викликів: `a.getB().getC().getD().getValue()`\n- Клієнт залежить від структури навігації\n- Код типу «потяг-катастрофа» (train wreck)\n\n**Чому це погано:**\n- Крихкий — будь-яка зміна ламає ланцюжок\n- Порушує Закон Деметри\n- Звʼязок зі структурою\n\n**Рефакторинги:**\n- Hide Delegate\n- Extract Method\n- Move Method\n\n**Приклад:**\n```javascript\n// Погано: Ланцюжок повідомлень\nconst managerName = employee.getDepartment().getManager().getName();\n\n// Краще: Приховати делегування\nconst managerName = employee.getManagerName();\n```\n\n---\n\n### Middle Man (Посередник)\n\n**Ознаки:**\n- Клас, що лише делегує іншому\n- Половина методів — делегування\n- Немає доданої цінності\n\n**Чому це погано:**\n- Непотрібна непрямість\n- Накладні витрати обслуговування\n- Заплутана архітектура\n\n**Рефакторинги:**\n- Remove Middle Man\n- Inline Method\n\n---\n\n## Посібник серйозності запахів\n\n| Серйозність | Опис | Дія |\n|-------------|------|-----|\n| **Критичний** | Блокує розробку, спричиняє помилки | Виправити негайно |\n| **Високий** | Значний тягар обслуговування | Виправити в поточному спринті |\n| **Середній** | Помітний, але керований | Запланувати на найближче майбутнє |\n| **Низький** | Незначна незручність | Виправляти при нагоді |\n\n---\n\n## Контрольний список швидкого виявлення\n\nВикористовуйте цей список при скануванні коду:\n\n- [ ] Є методи > 30 рядків?\n- [ ] Є класи > 300 рядків?\n- [ ] Є методи з > 4 параметрами?\n- [ ] Є дубльовані блоки коду?\n- [ ] Є switch/case за кодами типів?\n- [ ] Є невикористаний код?\n- [ ] Є методи, що інтенсивно використовують дані іншого класу?\n- [ ] Є довгі ланцюжки викликів?\n- [ ] Є коментарі, що пояснюють «що», а не «чому»?\n- [ ] Є примітиви, що мають бути обʼєктами?\n\n---\n\n## Додаткове читання\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Kerievsky, J. (2004). *Refactoring to Patterns*\n- Feathers, M. (2004). *Working Effectively with Legacy Code*\n","uk/03-skills/refactor/references/refactoring-catalog.md":"# Каталог рефакторингів\n\nКурований каталог технік рефакторингу з книги Мартіна Фаулера *Refactoring* (2-ге видання). Кожен рефакторинг включає мотивацію, покрокову механіку та приклади.\n\n> «Рефакторинг визначається своєю механікою — точною послідовністю кроків, яких ви дотримуєтесь для здійснення зміни.» — Мартін Фаулер\n\n---\n\n## Як використовувати цей каталог\n\n1. **Виявити запах** за допомогою довідника запахів коду\n2. **Знайти відповідний рефакторинг** у цьому каталозі\n3. **Дотримуватися механіки** крок за кроком\n4. **Тестувати після кожного кроку** для збереження поведінки\n\n**Золоте правило**: Якщо будь-який крок займає більше 10 хвилин, розбийте його на менші кроки.\n\n---\n\n## Найпоширеніші рефакторинги\n\n### Extract Method\n\n**Коли використовувати**: Довгий метод, дубльований код, потрібно назвати концепцію\n\n**Мотивація**: Перетворити фрагмент коду на метод, назва якого пояснює призначення.\n\n**Механіка**:\n1. Створити новий метод, названий за тим, що він робить (не як)\n2. Скопіювати фрагмент коду в новий метод\n3. Просканувати локальні змінні, використані у фрагменті\n4. Передати локальні змінні як параметри (або оголосити в методі)\n5. Обробити повернені значення належним чином\n6. Замінити оригінальний фрагмент викликом нового методу\n7. Тестувати\n\n**До**:\n```javascript\nfunction printOwing(invoice) {\n  let outstanding = 0;\n\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n\n  // Обчислення заборгованості\n  for (const order of invoice.orders) {\n    outstanding += order.amount;\n  }\n\n  // Друк деталей\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n**Після**:\n```javascript\nfunction printOwing(invoice) {\n  printBanner();\n  const outstanding = calculateOutstanding(invoice);\n  printDetails(invoice, outstanding);\n}\n\nfunction printBanner() {\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n}\n\nfunction calculateOutstanding(invoice) {\n  return invoice.orders.reduce((sum, order) => sum + order.amount, 0);\n}\n\nfunction printDetails(invoice, outstanding) {\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n---\n\n### Inline Method\n\n**Коли використовувати**: Тіло методу таке ж зрозуміле, як його назва; надмірне делегування\n\n**Мотивація**: Видалити непотрібну непрямість, коли метод не додає цінності.\n\n**Механіка**:\n1. Перевірити, що метод не є поліморфним\n2. Знайти всі виклики методу\n3. Замінити кожен виклик тілом методу\n4. Тестувати після кожної заміни\n5. Видалити визначення методу\n\n**До**:\n```javascript\nfunction getRating(driver) {\n  return moreThanFiveLateDeliveries(driver) ? 2 : 1;\n}\n\nfunction moreThanFiveLateDeliveries(driver) {\n  return driver.numberOfLateDeliveries > 5;\n}\n```\n\n**Після**:\n```javascript\nfunction getRating(driver) {\n  return driver.numberOfLateDeliveries > 5 ? 2 : 1;\n}\n```\n\n---\n\n### Extract Variable\n\n**Коли використовувати**: Складний вираз, важкий для розуміння\n\n**Мотивація**: Дати назву частині складного виразу.\n\n**Механіка**:\n1. Переконатися, що вираз не має побічних ефектів\n2. Оголосити незмінну змінну\n3. Встановити її як результат виразу (або частини)\n4. Замінити оригінальний вираз змінною\n5. Тестувати\n\n**До**:\n```javascript\nreturn order.quantity * order.itemPrice -\n  Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +\n  Math.min(order.quantity * order.itemPrice * 0.1, 100);\n```\n\n**Після**:\n```javascript\nconst basePrice = order.quantity * order.itemPrice;\nconst quantityDiscount = Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;\nconst shipping = Math.min(basePrice * 0.1, 100);\nreturn basePrice - quantityDiscount + shipping;\n```\n\n---\n\n### Inline Variable\n\n**Коли використовувати**: Назва змінної не передає більше, ніж вираз\n\n**Мотивація**: Видалити непотрібну непрямість.\n\n**Механіка**:\n1. Перевірити, що права частина не має побічних ефектів\n2. Якщо змінна не незмінна, зробити її такою і тестувати\n3. Знайти перше посилання та замінити виразом\n4. Тестувати\n5. Повторити для всіх посилань\n6. Видалити оголошення та присвоєння\n7. Тестувати\n\n---\n\n### Rename Variable\n\n**Коли використовувати**: Назва не чітко передає призначення\n\n**Мотивація**: Хороші назви критичні для чистого коду.\n\n**Механіка**:\n1. Якщо змінна широко використовується, розглянути інкапсуляцію\n2. Знайти всі посилання\n3. Змінити кожне посилання\n4. Тестувати\n\n**Поради**:\n- Використовуйте назви, що розкривають намір\n- Уникайте абревіатур\n- Використовуйте доменну термінологію\n\n```javascript\n// Погано\nconst d = 30;\nconst x = users.filter(u => u.a);\n\n// Добре\nconst daysSinceLastLogin = 30;\nconst activeUsers = users.filter(user => user.isActive);\n```\n\n---\n\n### Change Function Declaration\n\n**Коли використовувати**: Назва функції не пояснює призначення, параметри потребують зміни\n\n**Мотивація**: Хороші назви функцій роблять код самодокументованим.\n\n**Механіка (проста)**:\n1. Видалити непотрібні параметри\n2. Змінити назву\n3. Додати потрібні параметри\n4. Тестувати\n\n**Механіка (міграція — для складних змін)**:\n1. Якщо видаляєте параметр, переконайтеся, що він не використовується\n2. Створити нову функцію з бажаним оголошенням\n3. Зробити так, щоб стара функція викликала нову\n4. Тестувати\n5. Змінити виклики на нову функцію\n6. Тестувати після кожного\n7. Видалити стару функцію\n\n**До**:\n```javascript\nfunction circum(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n**Після**:\n```javascript\nfunction circumference(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n---\n\n### Encapsulate Variable\n\n**Коли використовувати**: Прямий доступ до даних з кількох місць\n\n**Мотивація**: Забезпечити чітку точку доступу для маніпуляції даними.\n\n**Механіка**:\n1. Створити функції getter та setter\n2. Знайти всі посилання\n3. Замінити читання на getter\n4. Замінити записи на setter\n5. Тестувати після кожної зміни\n6. Обмежити видимість змінної\n\n**До**:\n```javascript\nlet defaultOwner = { firstName: \"Martin\", lastName: \"Fowler\" };\n\n// Використовується в багатьох місцях\nspaceship.owner = defaultOwner;\n```\n\n**Після**:\n```javascript\nlet defaultOwnerData = { firstName: \"Martin\", lastName: \"Fowler\" };\n\nfunction defaultOwner() { return defaultOwnerData; }\nfunction setDefaultOwner(arg) { defaultOwnerData = arg; }\n\nspaceship.owner = defaultOwner();\n```\n\n---\n\n### Introduce Parameter Object\n\n**Коли використовувати**: Кілька параметрів, що часто зʼявляються разом\n\n**Мотивація**: Згрупувати дані, що природно належать разом.\n\n**Механіка**:\n1. Створити новий клас/структуру для згрупованих параметрів\n2. Тестувати\n3. Використати Change Function Declaration для додавання нового обʼєкта\n4. Тестувати\n5. Для кожного параметра в групі видалити його з функції та використати новий обʼєкт\n6. Тестувати після кожного\n\n**До**:\n```javascript\nfunction amountInvoiced(startDate, endDate) { ... }\nfunction amountReceived(startDate, endDate) { ... }\nfunction amountOverdue(startDate, endDate) { ... }\n```\n\n**Після**:\n```javascript\nclass DateRange {\n  constructor(start, end) {\n    this.start = start;\n    this.end = end;\n  }\n}\n\nfunction amountInvoiced(dateRange) { ... }\nfunction amountReceived(dateRange) { ... }\nfunction amountOverdue(dateRange) { ... }\n```\n\n---\n\n### Combine Functions into Class\n\n**Коли використовувати**: Кілька функцій оперують тими самими даними\n\n**Мотивація**: Згрупувати функції з даними, над якими вони працюють.\n\n**Механіка**:\n1. Застосувати Encapsulate Record до спільних даних\n2. Перемістити кожну функцію в клас\n3. Тестувати після кожного переміщення\n4. Замінити аргументи даних використанням полів класу\n\n**До**:\n```javascript\nfunction base(reading) { ... }\nfunction taxableCharge(reading) { ... }\nfunction calculateBaseCharge(reading) { ... }\n```\n\n**Після**:\n```javascript\nclass Reading {\n  constructor(data) { this._data = data; }\n\n  get base() { ... }\n  get taxableCharge() { ... }\n  get calculateBaseCharge() { ... }\n}\n```\n\n---\n\n### Split Phase\n\n**Коли використовувати**: Код працює з двома різними речами\n\n**Мотивація**: Розділити код на окремі фази з чіткими межами.\n\n**Механіка**:\n1. Створити другу функцію для другої фази\n2. Тестувати\n3. Ввести проміжну структуру даних між фазами\n4. Тестувати\n5. Витягти першу фазу в окрему функцію\n6. Тестувати\n\n**До**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  const shippingPerCase = (basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = quantity * shippingPerCase;\n  return basePrice - discount + shippingCost;\n}\n```\n\n**Після**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const priceData = calculatePricingData(product, quantity);\n  return applyShipping(priceData, shippingMethod);\n}\n\nfunction calculatePricingData(product, quantity) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  return { basePrice, quantity, discount };\n}\n\nfunction applyShipping(priceData, shippingMethod) {\n  const shippingPerCase = (priceData.basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = priceData.quantity * shippingPerCase;\n  return priceData.basePrice - priceData.discount + shippingCost;\n}\n```\n\n---\n\n## Переміщення функцій (Moving Features)\n\n### Move Method\n\n**Коли використовувати**: Метод використовує більше можливостей іншого класу, ніж свого\n\n**Мотивація**: Розміщувати функції разом з даними, які вони використовують найбільше.\n\n**Механіка**:\n1. Дослідити всі елементи програми, використані методом у своєму класі\n2. Перевірити, чи метод є поліморфним\n3. Скопіювати метод у цільовий клас\n4. Адаптувати до нового контексту\n5. Зробити оригінальний метод делегуючим до цільового\n6. Тестувати\n7. Розглянути видалення оригінального методу\n\n---\n\n### Move Field\n\n**Коли використовувати**: Поле використовується більше іншим класом\n\n**Мотивація**: Тримати дані разом з функціями, що їх використовують.\n\n**Механіка**:\n1. Інкапсулювати поле, якщо ще не зроблено\n2. Тестувати\n3. Створити поле в цільовому класі\n4. Оновити посилання на використання цільового поля\n5. Тестувати\n6. Видалити оригінальне поле\n\n---\n\n### Move Statements into Function\n\n**Коли використовувати**: Той самий код завжди зʼявляється разом з викликом функції\n\n**Мотивація**: Видалити дублювання, перемістивши повторюваний код у функцію.\n\n**Механіка**:\n1. Витягти повторюваний код у функцію, якщо ще не зроблено\n2. Перемістити оператори в цю функцію\n3. Тестувати\n4. Якщо виклики більше не потребують окремих операторів, видалити їх\n\n---\n\n### Move Statements to Callers\n\n**Коли використовувати**: Загальна поведінка різниться між викликачами\n\n**Мотивація**: Коли поведінка має відрізнятися, перемістити її з функції.\n\n**Механіка**:\n1. Використати Extract Method на коді для переміщення\n2. Використати Inline Method на оригінальній функції\n3. Видалити тепер вбудований виклик\n4. Перемістити витягнутий код до кожного виклику\n5. Тестувати\n\n---\n\n## Організація даних (Organizing Data)\n\n### Replace Primitive with Object\n\n**Коли використовувати**: Елемент даних потребує більше поведінки, ніж просте значення\n\n**Мотивація**: Інкапсулювати дані разом з їхньою поведінкою.\n\n**Механіка**:\n1. Застосувати Encapsulate Variable\n2. Створити простий клас значення\n3. Змінити setter для створення нового екземпляра\n4. Змінити getter для повернення значення\n5. Тестувати\n6. Додати багатшу поведінку до нового класу\n\n**До**:\n```javascript\nclass Order {\n  constructor(data) {\n    this.priority = data.priority; // рядок: \"high\", \"rush\" тощо\n  }\n}\n\n// Використання\nif (order.priority === \"high\" || order.priority === \"rush\") { ... }\n```\n\n**Після**:\n```javascript\nclass Priority {\n  constructor(value) {\n    if (!Priority.legalValues().includes(value))\n      throw new Error(`Invalid priority: ${value}`);\n    this._value = value;\n  }\n\n  static legalValues() { return ['low', 'normal', 'high', 'rush']; }\n  get value() { return this._value; }\n\n  higherThan(other) {\n    return Priority.legalValues().indexOf(this._value) >\n           Priority.legalValues().indexOf(other._value);\n  }\n}\n\n// Використання\nif (order.priority.higherThan(new Priority(\"normal\"))) { ... }\n```\n\n---\n\n### Replace Temp with Query\n\n**Коли використовувати**: Тимчасова змінна зберігає результат виразу\n\n**Мотивація**: Зробити код зрозумілішим, витягнувши вираз у функцію.\n\n**Механіка**:\n1. Перевірити, що змінна присвоюється лише один раз\n2. Витягти праву частину присвоєння в метод\n3. Замінити посилання на тимчасову змінну викликом методу\n4. Тестувати\n5. Видалити оголошення та присвоєння тимчасової змінної\n\n**До**:\n```javascript\nconst basePrice = this._quantity * this._itemPrice;\nif (basePrice > 1000) {\n  return basePrice * 0.95;\n} else {\n  return basePrice * 0.98;\n}\n```\n\n**Після**:\n```javascript\nget basePrice() {\n  return this._quantity * this._itemPrice;\n}\n\n// В методі\nif (this.basePrice > 1000) {\n  return this.basePrice * 0.95;\n} else {\n  return this.basePrice * 0.98;\n}\n```\n\n---\n\n## Спрощення умовної логіки (Simplifying Conditional Logic)\n\n### Decompose Conditional\n\n**Коли використовувати**: Складний умовний оператор (if-then-else)\n\n**Мотивація**: Зробити намір зрозумілим, витягнувши умови та дії.\n\n**Механіка**:\n1. Застосувати Extract Method на умові\n2. Застосувати Extract Method на then-гілці\n3. Застосувати Extract Method на else-гілці (якщо є)\n\n**До**:\n```javascript\nif (!aDate.isBefore(plan.summerStart) && !aDate.isAfter(plan.summerEnd)) {\n  charge = quantity * plan.summerRate;\n} else {\n  charge = quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n**Після**:\n```javascript\nif (isSummer(aDate, plan)) {\n  charge = summerCharge(quantity, plan);\n} else {\n  charge = regularCharge(quantity, plan);\n}\n\nfunction isSummer(date, plan) {\n  return !date.isBefore(plan.summerStart) && !date.isAfter(plan.summerEnd);\n}\n\nfunction summerCharge(quantity, plan) {\n  return quantity * plan.summerRate;\n}\n\nfunction regularCharge(quantity, plan) {\n  return quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n---\n\n### Consolidate Conditional Expression\n\n**Коли використовувати**: Кілька умов з однаковим результатом\n\n**Мотивація**: Зробити зрозумілим, що умови є однією перевіркою.\n\n**Механіка**:\n1. Перевірити відсутність побічних ефектів в умовах\n2. Обʼєднати умови за допомогою `and` або `or`\n3. Розглянути Extract Method на обʼєднаній умові\n\n**До**:\n```javascript\nif (employee.seniority < 2) return 0;\nif (employee.monthsDisabled > 12) return 0;\nif (employee.isPartTime) return 0;\n```\n\n**Після**:\n```javascript\nif (isNotEligibleForDisability(employee)) return 0;\n\nfunction isNotEligibleForDisability(employee) {\n  return employee.seniority < 2 ||\n         employee.monthsDisabled > 12 ||\n         employee.isPartTime;\n}\n```\n\n---\n\n### Replace Nested Conditional with Guard Clauses\n\n**Коли використовувати**: Глибоко вкладені умови ускладнюють відстеження потоку\n\n**Мотивація**: Використовувати захисні вирази (guard clauses) для спеціальних випадків, зберігаючи нормальний потік зрозумілим.\n\n**Механіка**:\n1. Знайти умови спеціальних випадків\n2. Замінити їх захисними виразами з раннім поверненням\n3. Тестувати після кожної зміни\n\n**До**:\n```javascript\nfunction payAmount(employee) {\n  let result;\n  if (employee.isSeparated) {\n    result = { amount: 0, reasonCode: \"SEP\" };\n  } else {\n    if (employee.isRetired) {\n      result = { amount: 0, reasonCode: \"RET\" };\n    } else {\n      result = calculateNormalPay(employee);\n    }\n  }\n  return result;\n}\n```\n\n**Після**:\n```javascript\nfunction payAmount(employee) {\n  if (employee.isSeparated) return { amount: 0, reasonCode: \"SEP\" };\n  if (employee.isRetired) return { amount: 0, reasonCode: \"RET\" };\n  return calculateNormalPay(employee);\n}\n```\n\n---\n\n### Replace Conditional with Polymorphism\n\n**Коли використовувати**: Switch/case за типом, умовна логіка що варіюється за типом\n\n**Мотивація**: Дозволити обʼєктам обробляти свою поведінку самостійно.\n\n**Механіка**:\n1. Створити ієрархію класів (якщо не існує)\n2. Використати фабричну функцію для створення обʼєктів\n3. Перемістити умовну логіку в метод суперкласу\n4. Створити метод підкласу для кожного випадку\n5. Видалити оригінальну умову\n\n**До**:\n```javascript\nfunction plumage(bird) {\n  switch (bird.type) {\n    case 'EuropeanSwallow':\n      return \"average\";\n    case 'AfricanSwallow':\n      return (bird.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n    case 'NorwegianBlueParrot':\n      return (bird.voltage > 100) ? \"scorched\" : \"beautiful\";\n    default:\n      return \"unknown\";\n  }\n}\n```\n\n**Після**:\n```javascript\nclass Bird {\n  get plumage() { return \"unknown\"; }\n}\n\nclass EuropeanSwallow extends Bird {\n  get plumage() { return \"average\"; }\n}\n\nclass AfricanSwallow extends Bird {\n  get plumage() {\n    return (this.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n  }\n}\n\nclass NorwegianBlueParrot extends Bird {\n  get plumage() {\n    return (this.voltage > 100) ? \"scorched\" : \"beautiful\";\n  }\n}\n\nfunction createBird(data) {\n  switch (data.type) {\n    case 'EuropeanSwallow': return new EuropeanSwallow(data);\n    case 'AfricanSwallow': return new AfricanSwallow(data);\n    case 'NorwegianBlueParrot': return new NorwegianBlueParrot(data);\n    default: return new Bird(data);\n  }\n}\n```\n\n---\n\n### Introduce Special Case (Null Object)\n\n**Коли використовувати**: Повторні перевірки на null для спеціальних випадків\n\n**Мотивація**: Повертати спеціальний обʼєкт, що обробляє спеціальний випадок.\n\n**Механіка**:\n1. Створити клас спеціального випадку з очікуваним інтерфейсом\n2. Додати перевірку isSpecialCase\n3. Ввести фабричний метод\n4. Замінити перевірки на null використанням обʼєкта спеціального випадку\n5. Тестувати\n\n**До**:\n```javascript\nconst customer = site.customer;\n// ... багато місць з перевіркою\nif (customer === \"unknown\") {\n  customerName = \"occupant\";\n} else {\n  customerName = customer.name;\n}\n```\n\n**Після**:\n```javascript\nclass UnknownCustomer {\n  get name() { return \"occupant\"; }\n  get billingPlan() { return registry.defaultPlan; }\n}\n\n// Фабричний метод\nfunction customer(site) {\n  return site.customer === \"unknown\"\n    ? new UnknownCustomer()\n    : site.customer;\n}\n\n// Використання — перевірки на null не потрібні\nconst customerName = customer.name;\n```\n\n---\n\n## Рефакторинг API (Refactoring APIs)\n\n### Separate Query from Modifier\n\n**Коли використовувати**: Функція і повертає значення, і має побічні ефекти\n\n**Мотивація**: Зробити зрозумілим, які операції мають побічні ефекти.\n\n**Механіка**:\n1. Створити нову функцію-запит\n2. Скопіювати логіку повернення оригінальної функції\n3. Змінити оригінал, щоб повертав void\n4. Замінити виклики, що використовують повернене значення\n5. Тестувати\n\n**До**:\n```javascript\nfunction alertForMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") {\n      setOffAlarms();\n      return \"Don\";\n    }\n    if (p === \"John\") {\n      setOffAlarms();\n      return \"John\";\n    }\n  }\n  return \"\";\n}\n```\n\n**Після**:\n```javascript\nfunction findMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") return \"Don\";\n    if (p === \"John\") return \"John\";\n  }\n  return \"\";\n}\n\nfunction alertForMiscreant(people) {\n  if (findMiscreant(people) !== \"\") setOffAlarms();\n}\n```\n\n---\n\n### Parameterize Function\n\n**Коли використовувати**: Кілька функцій роблять схожі речі з різними значеннями\n\n**Мотивація**: Видалити дублювання додаванням параметра.\n\n**Механіка**:\n1. Обрати одну функцію\n2. Додати параметр для варійованого літерала\n3. Змінити тіло для використання параметра\n4. Тестувати\n5. Змінити виклики на параметризовану версію\n6. Видалити тепер невикористані функції\n\n**До**:\n```javascript\nfunction tenPercentRaise(person) {\n  person.salary = person.salary * 1.10;\n}\n\nfunction fivePercentRaise(person) {\n  person.salary = person.salary * 1.05;\n}\n```\n\n**Після**:\n```javascript\nfunction raise(person, factor) {\n  person.salary = person.salary * (1 + factor);\n}\n\n// Використання\nraise(person, 0.10);\nraise(person, 0.05);\n```\n\n---\n\n### Remove Flag Argument\n\n**Коли використовувати**: Булевий параметр, що змінює поведінку функції\n\n**Мотивація**: Зробити поведінку явною через окремі функції.\n\n**Механіка**:\n1. Створити явну функцію для кожного значення прапорця\n2. Замінити кожен виклик відповідною новою функцією\n3. Тестувати після кожної зміни\n4. Видалити оригінальну функцію\n\n**До**:\n```javascript\nfunction bookConcert(customer, isPremium) {\n  if (isPremium) {\n    // логіка преміум-бронювання\n  } else {\n    // логіка звичайного бронювання\n  }\n}\n\nbookConcert(customer, true);\nbookConcert(customer, false);\n```\n\n**Після**:\n```javascript\nfunction bookPremiumConcert(customer) {\n  // логіка преміум-бронювання\n}\n\nfunction bookRegularConcert(customer) {\n  // логіка звичайного бронювання\n}\n\nbookPremiumConcert(customer);\nbookRegularConcert(customer);\n```\n\n---\n\n## Робота з успадкуванням (Dealing with Inheritance)\n\n### Pull Up Method\n\n**Коли використовувати**: Той самий метод у кількох підкласах\n\n**Мотивація**: Видалити дублювання в ієрархії класів.\n\n**Механіка**:\n1. Перевірити, що методи ідентичні\n2. Перевірити, що сигнатури однакові\n3. Створити новий метод у суперкласі\n4. Скопіювати тіло з одного підкласу\n5. Видалити один метод підкласу, тестувати\n6. Видалити інші методи підкласів, тестувати кожен\n\n---\n\n### Push Down Method\n\n**Коли використовувати**: Поведінка релевантна лише для підмножини підкласів\n\n**Мотивація**: Розмістити метод там, де він використовується.\n\n**Механіка**:\n1. Скопіювати метод у кожен підклас, що його потребує\n2. Видалити метод із суперкласу\n3. Тестувати\n4. Видалити з підкласів, що його не потребують\n5. Тестувати\n\n---\n\n### Replace Subclass with Delegate\n\n**Коли використовувати**: Успадкування використовується некоректно, потрібна більша гнучкість\n\n**Мотивація**: Віддавати перевагу композиції над успадкуванням, коли доречно.\n\n**Механіка**:\n1. Створити порожній клас для делегата\n2. Додати поле в клас-хост для утримання делегата\n3. Створити конструктор для делегата, що викликається з хоста\n4. Перемістити функціональність до делегата\n5. Тестувати після кожного переміщення\n6. Замінити успадкування делегуванням\n\n---\n\n## Extract Class\n\n**Коли використовувати**: Великий клас з кількома відповідальностями\n\n**Мотивація**: Розділити клас для збереження єдиної відповідальності.\n\n**Механіка**:\n1. Вирішити, як розділити відповідальності\n2. Створити новий клас\n3. Перемістити поле з оригіналу до нового класу\n4. Тестувати\n5. Перемістити методи з оригіналу до нового класу\n6. Тестувати після кожного переміщення\n7. Переглянути та перейменувати обидва класи\n8. Вирішити, як відкрити новий клас\n\n**До**:\n```javascript\nclass Person {\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get officeAreaCode() { return this._officeAreaCode; }\n  set officeAreaCode(arg) { this._officeAreaCode = arg; }\n  get officeNumber() { return this._officeNumber; }\n  set officeNumber(arg) { this._officeNumber = arg; }\n\n  get telephoneNumber() {\n    return `(${this._officeAreaCode}) ${this._officeNumber}`;\n  }\n}\n```\n\n**Після**:\n```javascript\nclass Person {\n  constructor() {\n    this._telephoneNumber = new TelephoneNumber();\n  }\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get telephoneNumber() { return this._telephoneNumber.toString(); }\n  get officeAreaCode() { return this._telephoneNumber.areaCode; }\n  set officeAreaCode(arg) { this._telephoneNumber.areaCode = arg; }\n}\n\nclass TelephoneNumber {\n  get areaCode() { return this._areaCode; }\n  set areaCode(arg) { this._areaCode = arg; }\n  get number() { return this._number; }\n  set number(arg) { this._number = arg; }\n  toString() { return `(${this._areaCode}) ${this._number}`; }\n}\n```\n\n---\n\n## Короткий довідник: Запах → Рефакторинг\n\n| Запах коду | Основний рефакторинг | Альтернатива |\n|------------|---------------------|--------------|\n| Long Method | Extract Method | Replace Temp with Query |\n| Duplicate Code | Extract Method | Pull Up Method |\n| Large Class | Extract Class | Extract Subclass |\n| Long Parameter List | Introduce Parameter Object | Preserve Whole Object |\n| Feature Envy | Move Method | Extract Method + Move |\n| Data Clumps | Extract Class | Introduce Parameter Object |\n| Primitive Obsession | Replace Primitive with Object | Replace Type Code |\n| Switch Statements | Replace Conditional with Polymorphism | Replace Type Code |\n| Temporary Field | Extract Class | Introduce Null Object |\n| Message Chains | Hide Delegate | Extract Method |\n| Middle Man | Remove Middle Man | Inline Method |\n| Divergent Change | Extract Class | Split Phase |\n| Shotgun Surgery | Move Method | Inline Class |\n| Dead Code | Remove Dead Code | - |\n| Speculative Generality | Collapse Hierarchy | Inline Class |\n\n---\n\n## Додаткове читання\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Онлайн-каталог: https://refactoring.com/catalog/\n","uk/07-plugins/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2FREADME.md -->","uk/07-plugins/devops-automation/.claude-plugin/plugin.json":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fdevops-automation%2F.claude-plugin%2Fplugin.json -->","uk/07-plugins/devops-automation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fdevops-automation%2FREADME.md -->","uk/07-plugins/documentation/.claude-plugin/plugin.json":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fdocumentation%2F.claude-plugin%2Fplugin.json -->","uk/07-plugins/documentation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fdocumentation%2FREADME.md -->","uk/07-plugins/documentation/commands/generate-readme.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fdocumentation%2Fcommands%2Fgenerate-readme.md -->","uk/07-plugins/pr-review/.claude-plugin/plugin.json":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fpr-review%2F.claude-plugin%2Fplugin.json -->","uk/07-plugins/pr-review/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fpr-review%2FREADME.md -->","uk/CLAUDE.md":"<!-- i18n-source: CLAUDE.md -->\n<!-- i18n-source-sha: 63a1416 -->\n<!-- i18n-date: 2026-04-10 -->\n\n# CLAUDE.md\n\nЦей файл надає настанови для Claude Code (claude.ai/code) при роботі з кодом у цьому репозиторії.\n\n## Огляд проєкту\n\nClaude How To — це навчальний репозиторій з функцій Claude Code. Це **документація-як-код** — основний продукт — markdown-файли, організовані в пронумеровані навчальні модулі, а не виконуваний додаток.\n\n**Архітектура**: Кожен модуль (01-10) охоплює конкретну функцію Claude Code з готовими шаблонами для копіювання, Mermaid-діаграмами та прикладами. Система збірки валідує якість документації та генерує EPUB-книгу.\n\n## Типові команди\n\n### Перевірки якості pre-commit\n\nУся документація повинна пройти п'ять перевірок якості перед комітами (запускаються автоматично через pre-commit хуки):\n\n```bash\n# Install pre-commit hooks (runs on every commit)\npre-commit install\n\n# Run all checks manually\npre-commit run --all-files\n```\n\nП'ять перевірок:\n1. **markdown-lint** — Структура та форматування Markdown через `markdownlint`\n2. **cross-references** — Внутрішні посилання, якорі, синтаксис блоків коду (Python-скрипт)\n3. **mermaid-syntax** — Валідація коректного парсингу всіх Mermaid-діаграм (Python-скрипт)\n4. **link-check** — Доступність зовнішніх URL (Python-скрипт)\n5. **markdown-rendering** — Markdown рендериться без помилок (Python-скрипт)\n\nЗбірка EPUB **не є** pre-commit хуком — вона виконується лише в CI (джоб `build-epub` у `.github/workflows/test.yml`), бо це повільна збірка всієї книги; хук mermaid-syntax уже рендерить кожну діаграму тим самим бандлом Pele.\n\n### Налаштування середовища розробки\n\n```bash\n# Install uv (Python package manager)\npip install uv\n\n# Create virtual environment and install Python dependencies\nuv venv\nsource .venv/bin/activate\nuv pip install -r scripts/requirements-dev.txt\n\n# Install Node.js tools (markdown linter)\nnpm install -g markdownlint-cli\n\n# Mermaid diagrams render with Pele: needs Node.js >= 20, no global package\nnode --version\n\n# Install pre-commit hooks\nuv pip install pre-commit\npre-commit install\n```\n\n### Тестування\n\nPython-скрипти в `scripts/` мають юніт-тести:\n\n```bash\n# Run all tests\npytest scripts/tests/ -v\n\n# Run with coverage\npytest scripts/tests/ -v --cov=scripts --cov-report=html\n\n# Run specific test\npytest scripts/tests/test_build_epub.py -v\n```\n\n### Якість коду\n\n```bash\n# Lint and format Python code\nruff check scripts/\nruff format scripts/\n\n# Security scan\nbandit -c scripts/pyproject.toml -r scripts/ --exclude scripts/tests/\n\n# Type checking\nmypy scripts/ --ignore-missing-imports\n```\n\n### Збірка EPUB\n\n```bash\n# Generate ebook (renders Mermaid diagrams with Pele — needs Node.js >= 20; the pinned bundle downloads once)\nuv run scripts/build_epub.py\n\n# With options\nuv run scripts/build_epub.py --verbose --output custom-name.epub\n```\n\n## Структура каталогів\n\n```\n├── 01-slash-commands/      # Ярлики, ініційовані користувачем\n├── 02-memory/              # Приклади постійного контексту\n├── 03-skills/              # Повторно використовувані можливості\n├── 04-subagents/           # Спеціалізовані AI-асистенти\n├── 05-mcp/                 # Приклади Model Context Protocol\n├── 06-hooks/               # Автоматизація на основі подій\n├── 07-plugins/             # Пакетні функції\n├── 08-checkpoints/         # Знімки сесій\n├── 09-advanced-features/   # Планування, мислення, фони\n├── 10-cli/                 # Довідник CLI\n├── scripts/\n│   ├── build_epub.py           # Генератор EPUB (рендерить Mermaid через Pele)\n│   ├── check_cross_references.py   # Валідація внутрішніх посилань\n│   ├── check_links.py          # Перевірка зовнішніх URL\n│   ├── check_mermaid.py        # Валідація синтаксису Mermaid\n│   └── tests/                  # Юніт-тести для скриптів\n├── .pre-commit-config.yaml    # Визначення перевірок якості\n└── README.md               # Основний довідник (також індекс модулів)\n```\n\n## Настанови щодо контенту\n\n### Структура модуля\nКожна пронумерована папка дотримується патерну:\n- **README.md** — Огляд функції з прикладами\n- **Файли прикладів** — Готові шаблони для копіювання (`.md` для команд, `.json` для конфігурацій, `.sh` для хуків)\n- Файли організовані за складністю функцій та залежностями\n\n### Mermaid-діаграми\n- Усі діаграми повинні успішно парситися (перевіряється pre-commit хуком)\n- Збірка EPUB рендерить діаграми через Pele (потрібен Node.js >= 20; закріплений бандл завантажується лише під час першого запуску, далі все працює офлайн)\n- Використовуйте Mermaid для блок-схем, діаграм послідовностей та архітектурних візуалізацій\n\n### Перехресні посилання\n- Використовуйте відносні шляхи для внутрішніх посилань (напр., `(01-slash-commands/README.md)`)\n- Блоки коду повинні вказувати мову (напр., ` ```bash `, ` ```python `)\n- Якірні посилання використовують формат `#heading-name`\n\n### Валідація посилань\n- Зовнішні URL повинні бути доступні (перевіряється pre-commit хуком)\n- Уникайте посилань на тимчасовий контент\n- Використовуйте пермалінки де можливо\n\n## Ключові архітектурні рішення\n\n1. **Пронумеровані папки вказують порядок навчання** — Префікс 01-10 відображає рекомендовану послідовність вивчення функцій Claude Code. Ця нумерація навмисна; не реорганізовуйте за алфавітом.\n\n2. **Скрипти — утиліти, а не продукт** — Python-скрипти в `scripts/` підтримують якість документації та генерацію EPUB. Фактичний контент — у пронумерованих папках модулів.\n\n3. **Pre-commit — привратник** — Усі перевірки якості повинні пройти перед прийняттям PR. CI-конвеєр запускає ці ж перевірки як другий прохід.\n\n4. **Рендеринг Mermaid потребує Node.js >= 20** — Збірка EPUB запускає закріплений бандл Pele через Node.js для рендерингу діаграм (бандл завантажується лише під час першого запуску, перевіряється за sha256 і кешується). Помилки збірки тут зазвичай пов'язані з відсутнім Node.js >= 20, невдалим завантаженням бандла або невалідним синтаксисом Mermaid. Хуки mermaid у pre-commit працюють у суворому режимі з Node.js 22, який надає сам pre-commit, тож вони падають, а не пропускають перевірку. Сама збірка EPUB не виконується у pre-commit — лише в CI.\n\n5. **Це туторіал, а не бібліотека** — При додаванні контенту зосереджуйтесь на чітких поясненнях, готових прикладах та візуальних діаграмах. Цінність — у навчанні концепцій, а не у наданні повторно використовуваного коду.\n\n## Конвенції комітів\n\nДотримуйтесь формату conventional commits:\n- `feat(slash-commands): Add API documentation generator`\n- `docs(memory): Improve personal preferences example`\n- `fix(README): Correct table of contents link`\n- `refactor(hooks): Simplify hook configuration examples`\n\nСкоуп повинен відповідати назві папки де можливо.\n","vi/03-skills/blog-draft/SKILL.md":"---\nname: blog-draft\ndescription: Soạn thảo bài đăng blog từ ý tưởng và tài nguyên. Sử dụng khi người dùng muốn viết bài blog, tạo nội dung từ nghiên cứu, hoặc soạn thảo bài viết. Hướng dẫn qua nghiên cứu, động não, lập dàn ý, và soạn thảo lặp lại với kiểm soát phiên bản.\n---\n\n## Đầu Vào Người Dùng\n\n```text\n$ARGUMENTS\n```\n\nBạn **BẮT BUỘC** phải xem xét đầu vào của người dùng trước khi tiếp tục. Người dùng nên cung cấp:\n- **Ý tưởng/Chủ đề**: Khái niệm hoặc chủ đề chính cho bài đăng blog\n- **Tài nguyên**: URLs, files, hoặc tài liệu tham khảo để nghiên cứu (tùy chọn nhưng được khuyến nghị)\n- **Đối tượng mục tiêu**: Bài đăng blog dành cho ai (tùy chọn)\n- **Giọng điệu/Phong cách**: Trang trọng, thân mật, kỹ thuật, v.v. (tùy chọn)\n\n**QUAN TRỌNG**: Nếu người dùng đang yêu cầu cập nhật cho một **bài đăng blog hiện có**, bỏ qua các bước 0-8 và bắt đầu trực tiếp tại **Bước 9**. Đọc các file draft hiện có trước, sau đó tiếp tục với quy trình lặp lại.\n\n## Quy Trình Thực Thi\n\nLàm theo các bước này tuần tự. **Đừng bỏ qua bước hoặc tiếp tục mà không có sự chấp thuận của người dùng nơi được chỉ ra.**\n\n### Bước 0: Tạo Thư Mục Dự Án\n\n1. Tạo tên thư mục sử dụng định dạng: `YYYY-MM-DD-ten-chu-de-ngan`\n   - Sử dụng ngày hôm nay\n   - Tạo một slug ngắn, thân thiện với URL từ chủ đề (chữ thường, gạch ngang, tối đa 5 từ)\n\n2. Tạo cấu trúc thư mục:\n   ```\n   blog-posts/\n   └── YYYY-MM-DD-ten-chu-de-ngan/\n       └── resources/\n   ```\n\n3. Xác nhận việc tạo thư mục với người dùng trước khi tiếp tục.\n\n### Bước 1: Nghiên Cứu & Thu Thập Tài Nguyên\n\n1. Tạo thư mục con `resources/` trong thư mục bài đăng blog\n\n2. Với mỗi tài nguyên được cung cấp:\n   - **URLs**: Lấy và lưu thông tin chính vào `resources/` dưới dạng files markdown\n   - **Files**: Đọc và tóm tắt trong `resources/`\n   - **Chủ đề**: Sử dụng tìm kiếm web để thu thập thông tin cập nhật\n\n3. Với mỗi tài nguyên, tạo một file tóm tắt trong `resources/`:\n   - `resources/source-1-[ten-ngan].md`\n   - `resources/source-2-[ten-ngan].md`\n   - v.v.\n\n4. Mỗi tóm tắt nên bao gồm:\n   ```markdown\n   # Nguồn: [Tiêu Đề/URL]\n\n   ## Các Điểm Chính\n   - Điểm 1\n   - Điểm 2\n\n   ## Trích Dẫn/Dữ Liệu Liên Quan\n   - Trích dẫn hoặc thống kê 1\n   - Trích dẫn hoặc thống kê 2\n\n   ## Cái Này Liên Quan Đến Chủ Đề Như Thế Nào\n   Giải thích ngắn về sự liên quan\n   ```\n\n5. Trình bày tóm tắt nghiên cứu cho người dùng.\n\n### Bước 2: Động Não & Làm Rõ\n\n1. Dựa trên ý tưởng và các tài nguyên đã nghiên cứu, trình bày:\n   - **Chủ đề chính** được xác định từ nghiên cứu\n   - **Góc độ tiềm năng** cho bài đăng blog\n   - **Các điểm chính** nên được bao phủ\n   - **Khoảng trống** trong thông tin cần làm rõ\n\n2. Đặt các câu hỏi làm rõ:\n   - Điều chính bạn muốn người đọc nhận được là gì?\n   - Có điểm cụ thể nào từ nghiên cứu bạn muốn nhấn mạnh không?\n   - Độ dài mục tiêu là bao nhiêu? (ngắn: 500-800 từ, trung bình: 1000-1500, dài: 2000+)\n   - Có điểm nào bạn muốn loại bỏ không?\n\n3. **Chờ phản hồi của người dùng trước khi tiếp tục.**\n\n### Bước 3: Đề Xuất Dàn Ý\n\n1. Tạo một dàn ý có cấu trúc bao gồm:\n\n   ```markdown\n   # Dàn Ý Bài Đăng Blog: [Tiêu Đề]\n\n   ## Thông Tin Meta\n   - **Đối Tượng Mục Tiêu**: [ai]\n   - **Giọng Điệu**: [phong cách]\n   - **Độ Dài Mục Tiêu**: [số lượng từ]\n   - **Điểm Chính Lấy Được**: [thông điệp chính]\n\n   ## Cấu Trúc Được Đề Xuất\n\n   ### Mở Bài/Giới Thiệu\n   - Ý tưởng mở bài hấp dẫn\n   - Thiết lập bối cảnh\n   - Tuyên bố luận điểm\n\n   ### Phần 1: [Tiêu Đề]\n   - Điểm chính A\n   - Điểm chính B\n   - Bằng chứng hỗ trợ từ [nguồn]\n\n   ### Phần 2: [Tiêu Đề]\n   - Điểm chính A\n   - Điểm chính B\n\n   [Tiếp tục cho tất cả các phần...]\n\n   ### Kết Luận\n   - Tóm tắt các điểm chính\n   - Kêu gọi hành động hoặc suy nghĩ cuối cùng\n\n   ## Nguồn Để Trích Dẫn\n   - Nguồn 1\n   - Nguồn 2\n   ```\n\n2. Trình bày dàn ý cho người dùng và **yêu cầu chấp thuận hoặc chỉnh sửa**.\n\n### Bước 4: Lưu Dàn Ý Được Chấp Thuận\n\n1. Khi người dùng chấp thuận dàn ý, lưu nó vào `OUTLINE.md` trong thư mục bài đăng blog.\n\n2. Xác nhận dàn ý đã được lưu.\n\n### Bước 5: Commit Dàn Ý (nếu trong git repo)\n\n1. Kiểm tra xem thư mục hiện tại có phải là một git repository không.\n\n2. Nếu có:\n   - Stage các file mới: thư mục bài đăng blog, resources, và OUTLINE.md\n   - Tạo commit với thông điệp: `docs: Add outline for blog post - [ten-chu-de]`\n   - Push đến remote\n\n3. Nếu không phải là git repo, bỏ qua bước này và thông báo cho người dùng.\n\n### Bước 6: Viết Bản Nháp\n\n1. Dựa trên dàn ý được chấp thuận, viết bản nháp bài đăng blog đầy đủ.\n\n2. Làm theo cấu trúc từ OUTLINE.md chính xác.\n\n3. Bao gồm:\n   - Giới thiệu hấp dẫn với mở bài\n   - Các tiêu đề phần rõ ràng\n   - Bằng chứng hỗ trợ và ví dụ từ nghiên cứu\n   - Chuyển tiếp mượt mà giữa các phần\n   - Kết luận mạnh mẽ với điểm chính\n   - **Trích dẫn**: Tất cả các so sánh, thống kê, dữ liệu, và yêu cầu thực tế PHẢI trích dẫn nguồn gốc\n\n4. Lưu bản nháp dưới dạng `draft-v0.1.md` trong thư mục bài đăng blog.\n\n5. Định dạng:\n   ```markdown\n   # [Tiêu Đề Bài Đăng Blog]\n\n   *[Tùy chọn: phụ đề hoặc câu khẩu hiệu]*\n\n   [Nội dung đầy đủ với các trích dẫn nội tuyến...]\n\n   ---\n\n   ## Tài Liệu Tham Khảo\n   - [1] Tiêu Đề Nguồn 1 - URL hoặc Trích Dẫn\n   - [2] Tiêu Đề Nguồn 2 - URL hoặc Trích Dẫn\n   - [3] Tiêu Đề Nguồn 3 - URL hoặc Trích Dẫn\n   ```\n\n6. **Yêu Cầu Trích Dẫn**:\n   - Mọi điểm dữ liệu, thống kê, hoặc so sánh PHẢI có trích dẫn nội tuyến\n   - Sử dụng tài liệu tham khảo đánh số [1], [2], v.v., hoặc trích dẫn có tên [Tên Nguồn]\n   - Liên kết các trích dẫn với phần Tài Liệu Tham Khảo ở cuối\n   - Ví dụ: \"Các nghiên cứu cho thấy 65% nhà phát triển ưa thích TypeScript [1]\"\n   - Ví dụ: \"React hoạt động tốt hơn Vue 20% về tốc độ render [React Benchmarks 2024]\"\n\n### Bước 7: Commit Bản Nháp (nếu trong git repo)\n\n1. Kiểm tra xem có trong git repository không.\n\n2. Nếu có:\n   - Stage file bản nháp\n   - Tạo commit với thông điệp: `docs: Add draft v0.1 for blog post - [ten-chu-de]`\n   - Push đến remote\n\n3. Nếu không phải là git repo, bỏ qua và thông báo cho người dùng.\n\n### Bước 8: Trình Bày Bản Nháp Để Xem Xét\n\n1. Trình bày nội dung bản nháp cho người dùng.\n\n2. Yêu cầu phản hồi:\n   - Ấn tượng tổng thể?\n   - Các phần cần mở rộng hoặc giảm bớt?\n   - Cần điều chỉnh giọng điệu?\n   - Thiếu thông tin?\n   - Chỉnh sửa hoặc viết lại cụ thể?\n\n3. **Chờ phản hồi của người dùng.**\n\n### Bước 9: Lặp Lại Hoặc Hoàn Thành\n\n**Nếu người dùng yêu cầu thay đổi:**\n1. Ghi chú tất cả các chỉnh sửa được yêu cầu\n2. Quay lại Bước 6 với các điều chỉnh sau:\n   - Tăng số phiên bản (v0.2, v0.3, v.v.)\n   - Kết hợp tất cả phản hồi\n   - Lưu dưới dạng `draft-v[X.Y].md`\n   - Lặp lại Các bước 7-8\n\n**Nếu người dùng chấp thuận:**\n1. Xác nhận phiên bản bản nháp cuối cùng\n2. Tùy chọn đổi tên thành `final.md` nếu người dùng yêu cầu\n3. Tóm tắt quy trình tạo bài đăng blog:\n   - Tổng số phiên bản được tạo\n   - Các thay đổi chính giữa các phiên bản\n   - Số lượng từ cuối cùng\n   - Các file được tạo\n\n## Theo Dõi Phiên Bản\n\nTất cả bản nháp được bảo tồn với việc đánh số phiên bản tăng dần:\n- `draft-v0.1.md` - Bản nháp ban đầu\n- `draft-v0.2.md` - Sau vòng phản hồi đầu tiên\n- `draft-v0.3.md` - Sau vòng phản hồi thứ hai\n- v.v.\n\nĐiều này cho phép theo dõi sự phát triển của bài đăng blog và hoàn tác nếu cần.\n\n## Cấu Trúc File Đầu Ra\n\n```\nblog-posts/\n└── YYYY-MM-DD-ten-chu-de/\n    ├── resources/\n    │   ├── source-1-name.md\n    │   ├── source-2-name.md\n    │   └── ...\n    ├── OUTLINE.md\n    ├── draft-v0.1.md\n    ├── draft-v0.2.md (nếu có lặp lại)\n    └── draft-v0.3.md (nếu có nhiều lặp lại hơn)\n```\n\n## Mẹo Để Chất Lượng\n\n- **Mở bài**: Bắt đầu với một câu hỏi, sự thật đáng ngạc nhiên, hoặc kịch bản có thể liên quan\n- **Dòng Chảy**: Mỗi đoạn nên kết nối với đoạn tiếp theo\n- **Bằng Chứng**: Hỗ trợ các yêu cầu với dữ liệu từ nghiên cứu\n- **Trích Dẫn**: LUÔN LUÔN trích dẫn nguồn cho:\n  - Tất cả thống kê và điểm dữ liệu (ví dụ: \"Theo [Nguồn], 75% của...\")\n  - So sánh giữa các sản phẩm, dịch vụ, hoặc cách tiếp cận (ví dụ: \"X hoạt động nhanh hơn gấp 2 lần so với Y [Nguồn]\")\n  - Các yêu cầu thực tế về xu hướng thị trường, phát hiện nghiên cứu, hoặc điểm chuẩn\n  - Sử dụng trích dẫn nội tuyến với định dạng: [Tên Nguồn] hoặc [Tác Giả, Năm]\n- **Giọng**: Duy trì giọng điệu nhất quán throughout\n- **Độ Dài**: Tôn trọng số lượng từ mục tiêu\n- **Khả Đọc**: Sử dụng các đoạn ngắn, gạch đầu dòng nơi phù hợp\n- **CTA**: Kết thúc với một lời kêu gọi hành động rõ ràng hoặc câu hỏi đáng suy ngẫm\n\n## Ghi Chú\n\n- Luôn chờ chấp thuận của người dùng tại các điểm kiểm tra được phác thảo\n- Bảo tồn tất cả các phiên bản bản nháp để lịch sử\n- Sử dụng tìm kiếm web để có thông tin cập nhật khi URLs được cung cấp\n- Nếu tài nguyên không đủ, yêu cầu người dùng thêm hoặc đề xuất nghiên cứu bổ sung\n- Thích ứng giọng điệu dựa trên đối tượng mục tiêu (kỹ thuật, chung, kinh doanh, v.v.)\n","vi/03-skills/brand-voice/SKILL.md":"---\nname: brand-voice\ndescription: Đảm bảo tất cả các truyền thông phù hợp với hướng dẫn giọng điệu và phong cách thương hiệu. Sử dụng khi tạo bản sao marketing, truyền thông khách hàng, nội dung công khai, hoặc khi người dùng đề cập đến giọng điệu thương hiệu, ngữ điệu, hoặc phong cách viết.\nuser-invocable: false\n---\n\n# Brand Voice Skill\n\n## Tổng Quan\nSkill này đảm bảo tất cả các truyền thông duy trì giọng điệu, ngữ điệu, và thông điệp thương hiệu nhất quán.\n\n## Danh Tính Thương Hiệu\n\n### Sứ Mệnh\nGiúp các đội tự động hóa workflows phát triển của họ với AI\n\n### Giá Trị\n- **Sự Đơn Giản**: Làm cho những điều phức tạp trở nên đơn giản\n- **Độ Tin Cậy**: Thực thi vững chắc\n- **Sự Trao Quyền**: Cho phép sự sáng tạo của con người\n\n### Giọng Điệu\n- **Thân thiện nhưng chuyên nghiệp** - có thể tiếp cận mà không thân mật quá\n- **Rõ ràng và ngắn gọn** - tránh thuật ngữ, giải thích các khái niệm kỹ thuật một cách đơn giản\n- **Tự Tin** - chúng tôi biết chúng tôi đang làm gì\n- **Thấu Cảm** - hiểu nhu cầu và nỗi đau của người dùng\n\n## Hướng Dẫn Viết\n\n### Nên Làm ✅\n- Sử dụng \"bạn\" khi người đọc\n- Sử dụng chủ động: \"Claude tạo báo cáo\" không \"Báo cáo được tạo bởi Claude\"\n- Bắt đầu với giá trị\n- Sử dụng các ví dụ cụ thể\n- Giữ câu dưới 20 từ\n- Sử dụng danh sách để rõ ràng\n- Bao gồm các lời kêu gọi hành động\n\n### Không Nên Làm ❌\n- Đừng sử dụng thuật ngữ công ty\n- Đừng cư xử như trên hoặc đơn giản hóa quá mức\n- Đừng sử dụng \"chúng tôi tin\" hoặc \"chúng tôi nghĩ\"\n- Đừng sử dụng HOA TOÀN THỨ TRỪ khi nhấn mạnh\n- Đừng tạo các bức tường văn bản\n- Đừng giả định kiến thức kỹ thuật\n\n## Từ Vựng\n\n### ✅ Thuật Ngữ Ưu Tiên\n- Claude (not \"the Claude AI\")\n- Code generation (not \"auto-coding\")\n- Agent (not \"bot\")\n- Streamline (not \"revolutionize\")\n- Integrate (not \"synergize\")\n\n### ❌ Tránh Thuật Ngữ\n- \"Cutting-edge\" (bị lạm dụng)\n- \"Game-changer\" (mơ hồ)\n- \"Leverage\" (ngôn ngữ công ty)\n- \"Utilize\" (use \"use\")\n- \"Paradigm shift\" (không rõ)\n\n## Ví Dụ\n\n### ✅ Ví Dụ Tốt\n\"Claude tự động hóa quy trình review code của bạn. Thay vì kiểm tra thủ công từng PR, Claude review bảo mật, hiệu suất, và chất lượng—tiết kiệm cho đội của bạn hàng mỗi tuần.\"\n\nTại sao nó hoạt động: Giá trị rõ ràng, lợi ích cụ thể, hướng hành động\n\n### ❌ Ví Dụ Xấu\n\"Claude leverages cutting-edge AI to provide comprehensive software development solutions.\"\n\nTại sao nó không hoạt động: Mơ hồ, thuật ngữ công ty, không có giá trị cụ thể\n","vi/03-skills/claude-md/SKILL.md":"---\nname: claude-md\ndescription: Tạo hoặc cập nhật các file CLAUDE.md theo các thực hành tốt nhất để onboarding tác nhân AI tối ưu\n---\n\n## Đầu Vào Người Dùng\n\n```text\n$ARGUMENTS\n```\n\nBạn **BẮT BUỘC** phải xem xét đầu vào của người dùng trước khi tiếp tục (nếu không trống). Người dùng có thể chỉ định:\n- `create` - Tạo CLAUDE.md mới từ đầu\n- `update` - Cải thiện CLAUDE.md hiện có\n- `audit` - Phân tích và báo cáo về chất lượng CLAUDE.md hiện tại\n- Một đường dẫn cụ thể để tạo/cập nhật (ví dụ: `src/api/CLAUDE.md` cho hướng dẫn cụ thể thư mục)\n\n## Nguyên Tắc Cốt Lõi\n\n**LLMs là không trạng thái**: CLAUDE.md là file dự án chính được tải vào mọi cuộc hội thoại (cùng với auto memory và các rules không giới hạn phạm vi). Nó phục vụ như tài liệu onboarding chính cho các tác nhân AI vào codebase của bạn.\n\n### Các Quy Tắc Vàng\n\n1. **Less is More**: Các LLM biên giới có thể theo ~150-200 hướng dẫn. System prompt của Claude Code đã sử dụng ~50. Giữ CLAUDE.md của bạn tập trung và ngắn gọn.\n\n2. **Ứng Dụng Phổ Biến**: Chỉ bao gồm thông tin liên quan đến MỌI phiên. Hướng dẫn cụ thể theo tác vụ thuộc về các file riêng.\n\n3. **Đừng Sử Dụng Claude như Linter**: Hướng dẫn phong cách làm phình bối cảnh và làm giảm khả năng tuân theo hướng dẫn. Sử dụng các công cụ xác định (prettier, eslint, v.v.) thay thế.\n\n4. **Không Bao Giờ Tự Động Tạo**: CLAUDE.md là điểm đòn bẩy cao nhất của hệ thống AI. Tạo nó thủ công với sự xem xét cẩn thận.\n\n## Quy Trình Thực Thi\n\n### 1. Phân Tích Dự Án\n\nĐầu tiên, phân tích trạng thái dự án hiện tại:\n\n1. Kiểm tra các file CLAUDE.md hiện có:\n   - Cấp root: `./CLAUDE.md` hoặc `.claude/CLAUDE.md`\n   - Cụ thể thư mục: `**/CLAUDE.md`\n   - Cấu hình người dùng toàn cầu: `~/.claude/CLAUDE.md`\n\n2. Xác định cấu trúc dự án:\n   - Technology stack (ngôn ngữ, frameworks)\n   - Loại dự án (monorepo, ứng dụng đơn, library)\n   - Công cụ phát triển (quản lý package, hệ thống build, trình chạy test)\n\n3. Xem lại tài liệu hiện có:\n   - README.md\n   - CONTRIBUTING.md\n   - package.json, pyproject.toml, Cargo.toml, v.v.\n\n### 2. Chiến Lược Nội Dung (WHAT, WHY, HOW)\n\nCấu trúc CLAUDE.md xung quanh ba chiều:\n\n#### WHAT - Công Nghệ & Cấu Trúc\n- Tổng quan technology stack\n- Tổ chức dự án (đặc biệt quan trọng cho monorepos)\n- Các thư mục chính và mục đích của chúng\n\n#### WHY - Mục Đích & Bối Cảnh\n- Dự án làm gì\n- Tại sao các quyết định kiến trúc nhất định được đưa ra\n- Mỗi thành phần chính chịu trách nhiệm cho gì\n\n#### HOW - Workflow & Quy Ước\n- Workflow phát triển (bun vs node, pip vs uv, v.v.)\n- Thủ tục và lệnh testing\n- Phương pháp xác minh và build\n- Các \"gotchas\" quan trọng hoặc yêu cầu không rõ ràng\n\n### 3. Chiến Lược Progressive Disclosure\n\nĐối với các dự án lớn, khuyến nghị tạo thư mục `agent_docs/`:\n\n```\nagent_docs/\n  |- building_the_project.md\n  |- running_tests.md\n  |- code_conventions.md\n  |- architecture_decisions.md\n```\n\nTrong CLAUDE.md, tham khảo các file này với các hướng dẫn như:\n```markdown\nĐể có hướng dẫn build chi tiết, tham khảo `agent_docs/building_the_project.md`\n```\n\n**Quan Trọng**: Sử dụng các tham chiếu `file:line` thay vì các đoạn code để tránh bối cảnh lỗi thời.\n\n### 4. Ràng Buộc Chất Lượng\n\nKhi tạo hoặc cập nhật CLAUDE.md:\n\n1. **Độ Dài Mục Tiêu**: Dưới 200 dòng\n2. **Không Quy Tắc Phong Cách**: Loại bỏ bất kỳ hướng dẫn linting/formatting nào\n3. **Không Hướng Dẫn Cụ Theo Tác Vụ**: Di chuyển sang các file riêng\n4. **Không Đoạn Code**: Sử dụng tham chiếu file thay thế\n5. **Không Thông Tin Dư Thừa**: Đừng lặp lại những gì trong package.json hoặc README\n\n### 5. Các Phần Thiết Yếu\n\nMột CLAUDE.md được cấu trúc tốt nên bao gồm:\n\n```markdown\n# Tên Dự Án\n\nMô tả ngắn một dòng.\n\n## Tech Stack\n- Ngôn ngữ chính và phiên bản\n- Frameworks/thư viện chính\n- Database/lưu trữ (nếu có)\n\n## Cấu Trúc Dự Án\n[Chỉ cho monorepos hoặc cấu trúc phức tạp]\n- `apps/` - Điểm vào ứng dụng\n- `packages/` - Thư viện được chia sẻ\n\n## Lệnh Phát Triển\n- Install: `command`\n- Test: `command`\n- Build: `command`\n\n## Quy Ước Quan Trọng\n[Chỉ các quy ước không rõ ràng, tác động cao]\n- Quy ước 1 với giải thích ngắn\n- Quy ước 2 với giải thích ngắn\n\n## Vấn Đế Đã Biết / Gotchas\n[Những gì luôn làm các nhà phát triển vấp phải]\n- Vấn đề 1\n- Vấn đề 2\n```\n\n### 6. Các Anti-Patterns Cần Tránh\n\n**KHÔNG bao gồm:**\n- Hướng dẫn phong cách code (sử dụng linters)\n- Tài liệu về cách sử dụng Claude\n- Giải thích dài về các mẫu rõ ràng\n- Các ví dụ code copy-paste\n- Thực hành tốt chung (\"viết code sạch\")\n- Hướng dẫn cho các tác vụ cụ thể\n- Nội dung được tạo tự động\n- Danh sách TODO mở rộng\n\n### 7. Checklist Xác Minh\n\nTrước khi hoàn thành, xác minh:\n\n- [ ] Dưới 200 dòng\n- [ ] Mọi dòng áp dụng cho TẤT CẢ các phiên\n- [ ] Không quy tắc phong cách/formatting\n- [ ] Không đoạn code (sử dụng tham chiếu file)\n- [ ] Các lệnh được xác minh hoạt động\n- [ ] Progressive disclosure được sử dụng cho các dự án phức tạp\n- [ ] Các gotchas quan trọng được tài liệu hóa\n- [ ] Không dư thừa với README.md\n\n## Định Dạng Đầu Ra\n\n### Cho `create` hoặc mặc định:\n\n1. Phân tích dự án\n2. Soạn thảo CLAUDE.md theo cấu trúc ở trên\n3. Trình bày bản nháp để xem xét\n4. Ghi vào vị trí phù hợp sau khi được chấp thuận\n\n### Cho `update`:\n\n1. Đọc CLAUDE.md hiện có\n2. Kiểm tra theo các thực hành tốt nhất\n3. Xác định:\n   - Nội dung để loại bỏ (quy tắc phong cách, đoạn code, cụ thể tác vụ)\n   - Nội dung để cô đọng\n   - Thông tin thiết bị còn thiếu\n4. Trình bày các thay đổi để xem xét\n5. Áp dụng các thay đổi sau khi được chấp thuận\n\n### Cho `audit`:\n\n1. Đọc CLAUDE.md hiện có\n2. Tạo một báo cáo với:\n   - Số dòng hiện tại vs mục tiêu\n   - Phần trăm nội dung áp dụng phổ biến\n   - Danh sách các anti-patterns được tìm thấy\n   - Khuyến nghị cải thiện\n3. KHÔNG chỉnh sửa file, chỉ báo cáo\n\n## Xử Lý AGENTS.md\n\nNếu người dùng yêu cầu tạo/cập nhật AGENTS.md:\n\n**Từ v2.1.277, Claude Code đọc `AGENTS.md` trực tiếp như hướng dẫn dự án** — nhưng chỉ khi thư mục làm việc và mọi thư mục phía trên nó đều không có `CLAUDE.md`, `.claude/CLAUDE.md`, hay `CLAUDE.local.md`. `~/.claude/CLAUDE.md`, CLAUDE.md được quản lý, và `.claude/rules/` không tính vào kiểm tra đó và vẫn được tải song song. Hành vi này được điều khiển bởi **Project instructions** trong `/config`: `claude-md-or-agents-md` (mặc định), `claude-md-and-agents-md`, `claude-md`, hoặc `managed-only`. Ở nơi không hỗ trợ đọc trực tiếp — phiên bản trước v2.1.277 (trước v2.1.281 trên Bedrock/Vertex/Foundry, LLM gateway, hoặc khi telemetry bị tắt), hoặc phiên đầu tiên sau khi nâng cấp — hãy dùng cách dự phòng: import từ CLAUDE.md bằng `@AGENTS.md`, hoặc symlink `CLAUDE.md` tới nó.\n\nAGENTS.md là file bối cảnh dự án dùng chung giữa nhiều công cụ — cùng *loại* tài liệu với CLAUDE.md, không phải định dạng định nghĩa tác nhân. Nó tồn tại để nhiều coding agent có thể dùng chung một bộ quy ước dự án:\n- Các lệnh build, test, và lint\n- Quy ước code style và kiến trúc\n- Bố cục repository và vị trí của các thành phần\n\nSubagents được định nghĩa riêng, trong `.claude/agents/*.md` — không phải trong AGENTS.md.\n\nÁp dụng các nguyên tắc tương tự:\n- Giữ tập trung và ngắn gọn\n- Sử dụng progressive disclosure\n- Tham khảo tài liệu bên ngoài thay vì nhúng nội dung\n\n## Ghi Chú\n\n- Luôn xác minh các lệnh hoạt động trước khi bao gồm chúng\n- Khi nghi ngờ, hãy loại bỏ - less is more\n- Lời nhắc hệ thống cho Claude biết rằng CLAUDE.md \"có thể hoặc có thể không liên quan\" - càng nhiều tiếng ồn, càng bị bỏ qua\n- Monorepos hưởng lợi nhất từ cấu trúc WHAT/WHY/HOW rõ ràng\n- Các file CLAUDE.md cụ thể thư mục nên được tập trung hơn nữa\n\n---\n\n**Cập Nhật Lần Cuối**: Ngày 18 tháng 10 năm 2026\n**Phiên Bản Claude Code**: 2.1.302\n**Nguồn**:\n- https://code.claude.com/docs/en/memory\n","vi/03-skills/code-review-specialist/SKILL.md":"---\nname: code-review-specialist\ndescription: Review code toàn diện với phân tích bảo mật, hiệu suất, và chất lượng. Sử dụng khi người dùng yêu cầu review code, phân tích chất lượng code, đánh giá pull requests, hoặc đề cập đến review code, phân tích bảo mật, hoặc tối ưu hóa hiệu suất.\n---\n\n# Code Review Skill\n\nSkill này cung cấp các khả năng review code toàn diện tập trung vào:\n\n1. **Phân Tích Bảo Mật**\n   - Các vấn đề xác thực/uỷ quyền\n   - Rủi ro lộ dữ liệu\n   - Lỗ hổng tiêm nhiễm\n   - Điểm yếu mật mã\n   - Ghi log dữ liệu nhạy cảm\n\n2. **Review Hiệu Suất**\n   - Hiệu quả thuật toán (phân tích Big O)\n   - Tối ưu hóa bộ nhớ\n   - Tối ưu hóa truy vấn cơ sở dữ liệu\n   - Cơ hội caching\n   - Các vấn đề đồng thời\n\n3. **Chất Lượng Code**\n   - Nguyên tắc SOLID\n   - Mẫu thiết kế\n   - Quy ước đặt tên\n   - Tài liệu hóa\n   - Phủ vùng test\n\n4. **Khả Năng Duy Trì**\n   - Khả năng đọc code\n   - Kích thước hàm (nên < 50 dòng)\n   - Độ phức tạp vòng lục\n   - Quản lý dependency\n   - An toàn kiểu\n\n## Mẫu Review\n\nĐối với mỗi đoạn code được review, cung cấp:\n\n### Tóm Tắt\n- Đánh giá chất lượng tổng thể (1-5)\n- Số lượng phát hiện chính\n- Các khu vực ưu tiên được khuyến nghị\n\n### Vấn Đề Nguy Kịch (nếu có)\n- **Vấn đề**: Mô tả rõ ràng\n- **Vị Trí**: File và số dòng\n- **Tác Động**: Tại sao điều này quan trọng\n- **Mức Độ**: Nguy Kịch/Cao/Trung Bình\n- **Khắc Phục**: Ví dụ code\n\n### Các Phát Hiện Theo Danh Mục\n\n#### Bảo Mật (nếu tìm thấy vấn đề)\nLiệt kê các lỗ hổng bảo mật với ví dụ\n\n#### Hiệu Suất (nếu tìm thấy vấn đề)\nLiệt kê các vấn đề hiệu suất với phân tích độ phức tạp\n\n#### Chất Lượng (nếu tìm thấy vấn đề)\nLiệt kê các vấn đề chất lượng code với các đề xuất refactor\n\n#### Khả Năng Duy Trì (nếu tìm thấy vấn đề)\nLiệt kê các vấn đề duy trì với các cải tiến\n\n## Lịch Sử Phiên Bản\n\n- v1.0.0 (2024-12-10): Phiên bản phát hành ban đầu với phân tích bảo mật, hiệu suất, chất lượng, và khả năng duy trì\n","vi/03-skills/refactor/SKILL.md":"---\nname: refactor\ndescription: Refactor code có hệ thống dựa trên phương pháp luận của Martin Fowler. Sử dụng khi người dùng yêu cầu refactor code, cải thiện cấu trúc code, giảm nợ kỹ thuật, dọn code legacy, loại bỏ code smells, hoặc cải thiện khả năng duy trì code. Skill này hướng dẫn qua cách tiếp theo từng giai đoạn với nghiên cứu, lập kế hoạch, và triển khai tăng dần an toàn.\n---\n\n# Code Refactoring Skill\n\nMột cách tiếp có hệ thống để refactor code dựa trên *Refactoring: Improving the Design of Existing Code* (ấn bản 2) của Martin Fowler. Skill này nhấn mạnh các thay đổi tăng dần, an toàn được hỗ trợ bởi tests.\n\n> \"Refactoring là quá trình thay đổi một hệ thống phần mềm theo cách mà nó không làm thay đổi hành vi bên ngoài của code nhưng cải thiện cấu trúc nội bộ của nó.\" — Martin Fowler\n\n## Nguyên Tắc Cốt Lõi\n\n1. **Bảo Tồn Hành Vi**: Hành vi bên ngoài phải không thay đổi\n2. **Các Bước Nhỏ**: Thực hiện các thay đổi nhỏ, có thể test\n3. **Được Dẫn Bởi Test**: Tests là lưới an toàn\n4. **Liên Tục**: Refactoring là liên tục, không phải sự kiện một lần\n5. **Hợp Tác**: Cần sự chấp thuận của người dùng tại mỗi giai đoạn\n\n## Tổng Quan Workflow\n\n```\nGiai Đoạn 1: Nghiên Cứu & Phân Tích\n    ↓\nGiai Đoạn 2: Đánh Giá Phủ Vùng Test\n    ↓\nGiai Đoạn 3: Xác Định Code Smell\n    ↓\nGiai Đoạn 4: Tạo Kế Hoạch Refactoring\n    ↓\nGiai Đoạn 5: Triển Khai Tăng Dần\n    ↓\nGiai Đoạn 6: Review & Lặp Lại\n```\n\n---\n\n## Giai Đoạn 1: Nghiên Cứu & Phân Tích\n\n### Mục Tiêu\n- Hiểu cấu trúc và mục đích của codebase\n- Xác định phạm vi của refactoring\n- Thu thập bối cảnh về các yêu cầu kinh doanh\n\n### Câu Hỏi Đặt Cho Người Dùng\nTrước khi bắt đầu, làm rõ:\n\n1. **Phạm Vi**: Những file/module/hàm nào cần refactor?\n2. **Mục Tiêu**: Bạn đang cố gắng giải quyết vấn đề gì? (khả đọc, hiệu suất, khả năng duy trì)\n3. **Ràng Buộc**: Có những khu vực nào KHÔNG NÊN thay đổi không?\n4. **Áp Lực Thời Gian**: Điều này có chặn công việc khác không?\n5. **Trạng Thái Test**: Tests có tồn tại không? Chúng có pass không?\n\n### Hành Động\n- [ ] Đọc và hiểu code mục tiêu\n- [ ] Xác định dependencies và integrations\n- [ ] Tài liệu hóa kiến trúc hiện tại\n- [ ] Ghi chú bất kỳ markers nợ kỹ thuật hiện có (TODOs, FIXMEs)\n\n### Đầu Ra\nTrình bày phát hiện cho người dùng:\n- Tóm tắt cấu trúc code\n- Các khu vực vấn đề được xác định\n- Khuyến nghị ban đầu\n- **Yêu cầu chấp thuận để tiếp tục**\n\n---\n\n## Giai Đoạn 2: Đánh Giá Phủ Vùng Test\n\n### Tại Sao Tests Quan Trọng\n> \"Refactoring mà không có tests giống như lái xe mà không có thắt dây an toàn.\" — Martin Fowler\n\nTests là **bật dụng chính** của refactoring an toàn. Không có chúng, bạn có nguy cơ giới thiệu bugs.\n\n### Các Bước Đánh Giá\n\n1. **Kiểm tra các test hiện có**\n   ```bash\n   # Tìm các file test\n   find . -name \"*test*\" -o -name \"*spec*\" | head -20\n   ```\n\n2. **Chạy các test hiện có**\n   ```bash\n   # JavaScript/TypeScript\n   npm test\n\n   # Python\n   pytest -v\n\n   # Java\n   mvn test\n   ```\n\n3. **Kiểm tra phủ vùng (nếu có)**\n   ```bash\n   # JavaScript\n   npm run test:coverage\n\n   # Python\n   pytest --cov=.\n   ```\n\n### Điểm Quyết Định: Hỏi Người Dùng\n\n**Nếu tests tồn tại và pass:**\n- Tiếp tục đến Giai Đoạn 3\n\n**Nếu tests bị thiếu hoặc không hoàn chỉnh:**\nTrình bày các tùy chọn:\n1. Viết tests trước (khuyến nghị)\n2. Thêm tests tăng dần trong khi refactoring\n3. Tiếp tục mà không có tests (rủi ro - yêu cầu sự thừa nhận của người dùng)\n\n**Nếu tests đang fail:**\n- DỪNG LẠI. Sửa các test fail trước khi refactoring\n- Hỏi người dùng: Chúng ta nên sửa tests trước không?\n\n### Hướng Dẫn Viết Test (nếu cần)\n\nĐối với mỗi hàm được refactor, đảm bảo tests bao phủ:\n- Happy path (hoạt động bình thường)\n- Các trường hợp ngoại lệ (đầu vào trống, null, ranh giới)\n- Các kịch bản lỗi (đầu vào không hợp lệ, ngoại lệ)\n\nSử dụng chu trình \"red-green-refactor\":\n1. Viết test fail (red)\n2. Làm cho nó pass (green)\n3. Refactor\n\n---\n\n## Giai Đoạn 3: Xác Định Code Smell\n\n### Code Smells Là Gì?\nCác triệu chứng của các vấn đề sâu hơn trong code. Chúng không phải là bugs, nhưng là các chỉ báo rằng code có thể được cải thiện.\n\n### Các Code Smells Phổ Biến Để Kiểm Tra\n\nXem [references/code-smells.md](../../../03-skills/refactor/references/code-smells.md) để có danh sách đầy đủ.\n\n#### Tham Khảo Nhanh\n\n| Smell | Dấu Hiệu | Tác Động |\n|-------|-------|--------|\n| **Long Method** | Methods > 30-50 dòng | Khó hiểu, test, duy trì |\n| **Duplicated Code** | Cùng logic ở nhiều nơi | Cần sửa lỗi ở nhiều nơi |\n| **Large Class** | Class với quá nhiều trách nhiệm | Vi phạm Single Responsibility |\n| **Feature Envy** | Method sử dụng dữ liệu class khác nhiều | Đóng gói kém |\n| **Primitive Obsession** | Lạm dụng primitives thay vì objects | Thiếu các khái niệm domain |\n| **Long Parameter List** | Methods với 4+ parameters | Khó gọi đúng |\n| **Data Clumps** | Cùng dữ liệu xuất hiện cùng nhau | Thiếu abstraction |\n| **Switch Statements** | Switch/if-else chains phức tạp | Khó mở rộng |\n| **Speculative Generality** | Code \"trường hợp\" | Độ phức tạp không cần thiết |\n| **Dead Code** | Code không sử dụng | Nhầm lẫn, gánh nặng duy trì |\n\n### Các Bước Phân Tích\n\n1. **Phân Tích Tự Động** (nếu scripts có sẵn)\n   ```bash\n   python scripts/detect-smells.py <file>\n   ```\n\n2. **Review Thủ Công**\n   - Đi qua code một cách có hệ thống\n   - Ghi chú mỗi smell với vị trí và mức độ nghiêm trọng\n   - Phân loại theo tác động (Nguy Kịch/Cao/Trung Bình/Thấp)\n\n3. **Ưu Tiên**\n   Tập trung vào các smells mà:\n   - Chặn phát triển hiện tại\n   - Gây bugs hoặc nhầm lẫn\n   - Ảnh hưởng đến các đường dẫn code được thay đổi nhiều nhất\n\n### Đầu Ra: Báo Cáo Smell\n\nTrình bày cho người dùng:\n- Danh sách các smells được xác định với vị trí\n- Đánh giá mức độ nghiêm trọng cho mỗi smell\n- Thứ tự ưu tiên được khuyến nghị\n- **Yêu cầu chấp thuận về các ưu tiên**\n\n---\n\n## Giai Đoạn 4: Tạo Kế Hoạch Refactoring\n\n### Chọn Refactorings\n\nĐối với mỗi smell, chọn một refactoring phù hợp từ catalog.\n\nXem [references/refactoring-catalog.md](../../../03-skills/refactor/references/refactoring-catalog.md) để có danh sách đầy đủ.\n\n#### Smell-to-Refactoring Mapping\n\n| Code Smell | Refactoring Khuyến Nghị |\n|------------|---------------------------|\n| Long Method | Extract Method, Replace Temp with Query |\n| Duplicated Code | Extract Method, Pull Up Method, Form Template Method |\n| Large Class | Extract Class, Extract Subclass |\n| Feature Envy | Move Method, Move Field |\n| Primitive Obsession | Replace Primitive with Object, Replace Type Code with Class |\n| Long Parameter List | Introduce Parameter Object, Preserve Whole Object |\n| Data Clumps | Extract Class, Introduce Parameter Object |\n| Switch Statements | Replace Conditional with Polymorphism |\n| Speculative Generality | Collapse Hierarchy, Inline Class, Remove Dead Code |\n| Dead Code | Remove Dead Code |\n\n### Cấu Trúc Kế Hoạch\n\nSử dụng mẫu tại [templates/refactoring-plan.md](../../../03-skills/refactor/templates/refactoring-plan.md).\n\nĐối với mỗi refactoring:\n1. **Mục Tiêu**: Code nào sẽ thay đổi\n2. **Smell**: Vấn đề nào nó giải quyết\n3. **Refactoring**: Kỹ thuật nào để áp dụng\n4. **Các Bước**: Các micro-bước chi tiết\n5. **Rủi Ro**: Điều gì có thể sai\n6. **Hoàn Tác**: Cách hoàn tác nếu cần\n\n### Cách Tiếp Theo Giai Đoạn\n\n**QUAN TRỌNG**: Introduce refactoring tăng dần theo các giai đoạn.\n\n**Giai Đoạn A: Quick Wins** (Rủi ro thấp, giá trị cao)\n- Đổi tên biến để rõ hơn\n- Extract code trùng lặp rõ ràng\n- Loại bỏ dead code\n\n**Giai Đoạn B: Cải Tiến Cấu Trúc** (Rủi ro trung bình)\n- Extract methods từ các hàm dài\n- Introduce parameter objects\n- Move methods đến các lớp phù hợp\n\n**Giai Đoạn C: Thay Đổi Kiến Trúc** (Rủi ro cao hơn)\n- Thay thế conditionals với polymorphism\n- Extract classes\n- Introduce design patterns\n\n### Điểm Quyết Định: Trình Bày Kế Hoạch Cho Người Dùng\n\nTrước khi triển khai:\n- Hiển thị kế hoạch refactoring hoàn chỉnh\n- Giải thích mỗi giai đoạn và rủi ro của nó\n- Nhận sự chấp thuận rõ ràng cho mỗi giai đoạn\n- **Hỏi**: \"Tôi có nên tiếp tục với Giai Đoạn A không?\"\n\n---\n\n## Giai Đoạn 5: Triển Khai Tăng Dần\n\n### Quy Tắc Vàng\n> \"Thay Đổi → Test → Xanh? → Commit → Bước tiếp theo\"\n\n### Nhịp Triển Khai\n\nĐối với mỗi bước refactoring:\n\n1. **Kiểm tra trước**\n   - Tests đang pass (xanh)\n   - Code biên dịch\n\n2. **Thực hiện MỘT thay đổi nhỏ**\n   - Làm theo các cơ chế từ catalog\n   - Giữ thay đổi tối thiểu\n\n3. **Xác Minh**\n   - Chạy tests ngay lập tức\n   - Kiểm tra lỗi biên dịch\n\n4. **Nếu tests pass (xanh)**\n   - Commit với thông điệp mô tả\n   - Di chuyển đến bước tiếp theo\n\n5. **Nếu tests fail (đỏ)**\n   - DỪNG LẠI ngay lập tức\n   - Hoàn tác thay đổi\n   - Phân tích điều gì sai\n   - Hỏi người dùng nếu không rõ\n\n### Chiến Lược Commit\n\nMỗi commit nên là:\n- **Nguyên Tử**: Một thay đổi logic\n- **Có Thể Hoàn Tác**: Dễ dàng revert\n- **Mô Tả**: Thông điệp commit rõ ràng\n\nVí dụ thông điệp commit:\n```\nrefactor: Extract calculateTotal() from processOrder()\nrefactor: Rename 'x' to 'customerCount' for clarity\nrefactor: Remove unused validateOldFormat() method\n```\n\n### Báo Cáo Tiến Độ\n\nSau mỗi sub-giai đoạn, báo cáo cho người dùng:\n- Các thay đổi được thực hiện\n- Tests vẫn pass?\n- Bất kỳ vấn đề nào gặp phải\n- **Hỏi**: \"Tiếp tục với batch tiếp theo?\"\n\n---\n\n## Giai Đoạn 6: Review & Lặp Lại\n\n### Checklist Sau Refactoring\n\n- [ ] Tất cả tests pass\n- [ ] Không có cảnh báo/lỗi mới\n- [ ] Code biên dịch thành công\n- [ ] Hành vi không thay đổi (xác minh thủ công)\n- [ ] Tài liệu được cập nhật nếu cần\n- [ ] Lịch sử commit sạch\n\n### So Sánh Metrics\n\nChạy phân tích độ phức tạp trước và sau:\n```bash\npython scripts/analyze-complexity.py <file>\n```\n\nTrình bày cải tiến:\n- Thay đổi số dòng code\n- Thay đổi độ phức tạp vòng lục\n- Thay đổi chỉ số khả năng duy trì\n\n### Review Người Dùng\n\nTrình bày kết quả cuối cùng:\n- Tóm tắt tất cả thay đổi\n- So sánh code trước/sau\n- Cải tiến metrics\n- Nợ kỹ thuật còn lại\n- **Hỏi**: \"Bạn có hài lòng với những thay đổi này không?\"\n\n### Các Bước Tiếp Theo\n\nThảo luận với người dùng:\n- Có smells bổ sung để giải quyết không?\n- Lên lịch refactoring tiếp theo?\n- Áp dụng các thay đổi tương tự ở nơi khác?\n\n---\n\n## Hướng Dẫn Quan Trọng\n\n### Khi DỪNG LẠI và Hỏi\n\nLuôn dừng lại và tham khảo người dùng khi:\n- Không chắc về logic kinh doanh\n- Thay đổi có thể ảnh hưởng APIs bên ngoài\n- Phủ vùng test không đủ\n- Cần quyết định kiến trúc quan trọng\n- Mức độ rủi ro tăng\n- Bạn gặp độ phức tạp bất ngờ\n\n### Quy Tắc An Toàn\n\n1. **Không bao giờ refactor mà không có tests** (trừ khi người dùng thừa nhận rủi ro một cách rõ ràng)\n2. **Không bao giờ thực hiện các thay đổi lớn** - chia thành các bước nhỏ\n3. **Không bao giờ bỏ qua chạy test** sau mỗi thay đổi\n4. **Không bao giờ tiếp tục nếu tests fail** - sửa hoặc hoàn tác trước\n5. **Không bao giờ giả định** - khi nghi ngờ, hãy hỏi\n\n### Những Gì KHÔNG Nên Làm\n\n- Đừng kết hợp refactoring với việc thêm tính năng\n- Đừng refactor trong các tình huống khẩn cấp của production\n- Đừng refactor code mà bạn không hiểu\n- Đừng over-engineer - giữ nó đơn giản\n- Đừng refactor tất cả cùng một lúc\n\n---\n\n## Ví Dụ Bắt Đầu Nhanh\n\n### Kịch Bản: Long Method với Duplication\n\n**Trước:**\n```javascript\nfunction processOrder(order) {\n  // 150 dòng code với:\n  // - Logic xác thực trùng lặp\n  // - Tính toán nội tuyến\n  // - Trách nhiệm hỗn hợp\n}\n```\n\n**Các Bước Refactoring:**\n\n1. **Đảm bảo tests tồn tại** cho processOrder()\n2. **Extract** xác thực vào validateOrder()\n3. **Test** - nên pass\n4. **Extract** tính toán vào calculateOrderTotal()\n5. **Test** - nên pass\n6. **Extract** thông báo vào notifyCustomer()\n7. **Test** - nên pass\n8. **Review** - processOrder() giờ điều phối 3 hàm rõ ràng\n\n**Sau:**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const total = calculateOrderTotal(order);\n  notifyCustomer(order, total);\n  return { order, total };\n}\n```\n\n---\n\n## Tài Liệu Tham Khảo\n\n- [Catalog Code Smells](../../../03-skills/refactor/references/code-smells.md) - Danh sách đầy đủ code smells\n- [Catalog Refactoring](../../../03-skills/refactor/references/refactoring-catalog.md) - Các kỹ thuật refactoring\n- [Mẫu Kế Hoạch Refactoring](../../../03-skills/refactor/templates/refactoring-plan.md) - Mẫu lập kế hoạch\n\n## Scripts\n\n- `scripts/analyze-complexity.py` - Phân tích metrics độ phức tạp code\n- `scripts/detect-smells.py` - Phát hiện smell tự động\n\n## Lịch Sử Phiên Bản\n\n- v1.0.0 (2025-01-15): Phiên bản phát hành ban đầu với phương pháp luận Fowler, cách tiếp theo từng giai đoạn, các điểm tham khảo người dùng\n","vi/07-plugins/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2FREADME.md -->","vi/07-plugins/devops-automation/.claude-plugin/plugin.json":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fdevops-automation%2F.claude-plugin%2Fplugin.json -->","vi/07-plugins/devops-automation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fdevops-automation%2FREADME.md -->","vi/07-plugins/documentation/.claude-plugin/plugin.json":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fdocumentation%2F.claude-plugin%2Fplugin.json -->","vi/07-plugins/documentation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fdocumentation%2FREADME.md -->","vi/07-plugins/documentation/commands/generate-readme.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fdocumentation%2Fcommands%2Fgenerate-readme.md -->","vi/07-plugins/pr-review/.claude-plugin/plugin.json":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fpr-review%2F.claude-plugin%2Fplugin.json -->","vi/07-plugins/pr-review/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fpr-review%2FREADME.md -->","vi/CLAUDE.md":"# CLAUDE.md\n\nFile này cung cấp hướng dẫn cho Claude Code (claude.ai/code) khi làm việc với code trong repository này.\n\n## Tổng Quan Dự Án\n\nClaude How To là một repository tutorial về các tính năng của Claude Code. Đây là **documentation-as-code** — sản phẩm chính là các file markdown được tổ chức thành các module học tập đánh số (01-10), không phải một ứng dụng thực thi.\n\n**Kiến trúc**: Mỗi module (01-10) bao phủ một tính năng cụ thể của Claude Code với các template copy-paste, sơ đồ Mermaid, và ví dụ. Hệ thống build xác thực chất lượng documentation và tạo ebook EPUB.\n\n## Các Lệnh Thường Dùng\n\n### Kiểm Tra Chất Lượng Pre-commit\n\nTất cả documentation phải vượt qua năm kiểm tra chất lượng trước khi commit (các kiểm tra này chạy tự động qua pre-commit hooks):\n\n```bash\n# Cài đặt pre-commit hooks (chạy trên mỗi commit)\npre-commit install\n\n# Chạy tất cả các kiểm tra thủ công\npre-commit run --all-files\n```\n\nNăm kiểm tra là:\n1. **markdown-lint** — Cấu trúc và định dạng Markdown qua `markdownlint`\n2. **cross-references** — Liên kết nội bộ, anchors, cú pháp code fence (Python script)\n3. **mermaid-syntax** — Xác thực tất cả sơ đồ Mermaid parse đúng (Python script)\n4. **link-check** — Các URL bên ngoài có thể truy cập được (Python script)\n5. **markdown-rendering** — Markdown render không lỗi (Python script)\n\nViệc build EPUB **không phải** là một pre-commit hook — nó chỉ chạy trong CI (job `build-epub` trong `.github/workflows/test.yml`), vì đây là bản build toàn bộ sách, chạy chậm; hook mermaid-syntax đã render mọi sơ đồ bằng cùng bundle Pele.\n\n### Thiết Lập Môi Trường Phát Triển\n\n```bash\n# Cài đặt uv (Python package manager)\npip install uv\n\n# Tạo virtual environment và cài đặt Python dependencies\nuv venv\nsource .venv/bin/activate\nuv pip install -r scripts/requirements-dev.txt\n\n# Cài đặt Node.js tools (markdown linter)\nnpm install -g markdownlint-cli\n\n# Sơ đồ Mermaid được render bằng Pele: cần Node.js >= 20, không cần cài package toàn cục\nnode --version\n\n# Cài đặt pre-commit hooks\nuv pip install pre-commit\npre-commit install\n```\n\n### Testing\n\nCác script Python trong `scripts/` có unit tests:\n\n```bash\n# Chạy tất cả tests\npytest scripts/tests/ -v\n\n# Chạy với coverage\npytest scripts/tests/ -v --cov=scripts --cov-report=html\n\n# Chạy test cụ thể\npytest scripts/tests/test_build_epub.py -v\n```\n\n### Chất Lượng Code\n\n```bash\n# Lint và format Python code\nruff check scripts/\nruff format scripts/\n\n# Security scan\nbandit -c scripts/pyproject.toml -r scripts/ --exclude scripts/tests/\n\n# Type checking\nmypy scripts/ --ignore-missing-imports\n```\n\n### Build EPUB\n\n```bash\n# Tạo ebook (render Mermaid diagrams bằng Pele — cần Node.js >= 20; bundle cố định chỉ tải về một lần)\nuv run scripts/build_epub.py\n\n# Với các tùy chọn\nuv run scripts/build_epub.py --verbose --output custom-name.epub --lang vi\n```\n\n## Cấu Trúc Thư Mục\n\n```\n├── 01-slash-commands/      # Các lối tắt do người dùng gọi\n├── 02-memory/              # Ví dụ về bối cảnh liên tục\n├── 03-skills/              # Các khả năng có thể tái sử dụng\n├── 04-subagents/           # Các tác nhân AI chuyên dụng\n├── 05-mcp/                 # Ví dụ Model Context Protocol\n├── 06-hooks/              # Tự động hóa dựa trên sự kiện\n├── 07-plugins/             # Các tính năng được đóng gói\n├── 08-checkpoints/         # Các snapshot của phiên\n├── 09-advanced-features/   # Lập kế hoạch, suy nghĩ, background tasks\n├── 10-cli/                 # Tham chiếu CLI\n├── scripts/\n│   ├── build_epub.py           # EPUB generator (render Mermaid bằng Pele)\n│   ├── check_cross_references.py   # Xác thực liên kết nội bộ\n│   ├── check_links.py          # Kiểm tra các URL bên ngoài\n│   ├── check_mermaid.py        # Xác thực cú pháp Mermaid\n│   └── tests/                  # Unit tests cho scripts\n├── .pre-commit-config.yaml    # Định nghĩa các kiểm tra chất lượng\n└── README.md               # Hướng dẫn chính (cũng là index của module)\n```\n\n## Hướng Dẫn Nội Dung\n\n### Cấu Trúc Module\n\nMỗi thư mục đánh số tuân theo pattern:\n- **README.md** — Tổng quan về tính năng với các ví dụ\n- **Các file ví dụ** — Template copy-paste (`.md` cho commands, `.json` cho configs, `.sh` cho hooks)\n- Các file được tổ chức theo độ phức tạp của tính năng và dependencies\n\n### Sơ Đồ Mermaid\n- Tất cả sơ đồ phải parse thành công (được kiểm tra bởi pre-commit hook)\n- EPUB build render sơ đồ bằng Pele (cần Node.js >= 20; bundle cố định chỉ tải về trong lần chạy đầu tiên, sau đó chạy offline)\n- Sử dụng Mermaid cho flowcharts, sequence diagrams, và architecture visuals\n\n### Cross-References\n- Sử dụng relative paths cho internal links (ví dụ: `(01-slash-commands/README.md)`)\n- Code fences phải chỉ định ngôn ngữ (ví dụ: ` ```bash `, ` ```python `)\n- Anchor links sử dụng format `#heading-name`\n\n### Link Validation\n- Các URL bên ngoài phải có thể truy cập được (được kiểm tra bởi pre-commit hook)\n- Tránh link đến nội dung tạm thời\n- Sử dụng permalinks nếu có thể\n\n## Các Điểm Kiến Trúc Quan Trọng\n\n1. **Các thư mục đánh số thể hiện thứ tự học tập** — Prefix 01-10 thể hiện thứ tự được khuyến nghị để học các tính năng của Claude Code. Đánh số này có chủ đích; không tổ chức lại theo bảng chữ cái.\n\n2. **Scripts là các tiện ích, không phải sản phẩm** — Các script Python trong `scripts/` hỗ trợ chất lượng documentation và tạo EPUB. Nội dung thực tế nằm trong các thư mục module đánh số.\n\n3. **Pre-commit là người gác cổng** — Tất cả năm kiểm tra chất lượng phải pass trước khi PR được chấp nhận. CI pipeline chạy các kiểm tra tương tự như lần thứ hai.\n\n4. **Mermaid rendering cần Node.js >= 20** — EPUB build chạy bundle Pele cố định bằng Node.js để render diagrams (bundle chỉ tải về trong lần chạy đầu tiên, được kiểm tra sha256 và lưu cache). Các lỗi build ở đây thường là do chưa cài Node.js >= 20, tải bundle thất bại, hoặc cú pháp Mermaid không hợp lệ. Các hook mermaid của pre-commit chạy ở chế độ strict với Node.js 22 do pre-commit cung cấp, nên chúng sẽ báo lỗi thay vì bỏ qua. Bản thân EPUB build không chạy trong pre-commit — nó chỉ chạy trong CI.\n\n5. **Đây là tutorial, không phải thư viện** — Khi thêm nội dung, tập trung vào giải thích rõ ràng, ví dụ copy-paste, và sơ đồ trực quan. Giá trị nằm ở việc dạy các khái niệm, không cung cấp code có thể tái sử dụng.\n\n## Commit Conventions\n\nTuân theo format conventional commit:\n- `feat(slash-commands): Add API documentation generator`\n- `docs(memory): Improve personal preferences example`\n- `fix(README): Correct table of contents link`\n- `refactor(hooks): Simplify hook configuration examples`\n\nScope nên khớp với tên thư mục khi áp dụng.\n","zh/03-skills/blog-draft/SKILL.md":"---\nname: blog-draft\ndescription: 根据想法和资料撰写博客草稿。适用于用户想写博客、基于研究创建内容，或起草文章的场景。流程会引导你完成调研、头脑风暴、提纲编写和带版本控制的迭代撰写。\n---\n\n## 用户输入\n\n```text\n$ARGUMENTS\n```\n\n在继续之前，你**必须**先考虑用户输入。用户应提供：\n- **想法/主题**：博客文章的核心概念或主题\n- **资源**：用于研究的 URL、文件或参考资料（可选，但推荐）\n- **目标读者**：这篇博客是写给谁看的（可选）\n- **语气/风格**：正式、轻松、技术向等（可选）\n\n**重要**：如果用户是在请求更新一篇**已有博客文章**，请跳过步骤 0-8，直接从**步骤 9** 开始。先阅读现有草稿文件，再继续迭代流程。\n\n## 执行流程\n\n请按顺序执行以下步骤。**不要跳步，也不要在未获得用户批准的情况下继续执行标明需要确认的步骤。**\n\n### 步骤 0：创建项目文件夹\n\n1. 使用以下格式生成文件夹名称：`YYYY-MM-DD-short-topic-name`\n   - 使用今天的日期\n   - 根据主题生成一个简短、适合 URL 的 slug（小写、连字符连接，最多 5 个词）\n\n2. 创建文件夹结构：\n   ```text\n   blog-posts/\n   └── YYYY-MM-DD-short-topic-name/\n       └── resources/\n   ```\n\n3. 在继续前，先向用户确认文件夹已创建。\n\n### 步骤 1：研究与资源收集\n\n1. 在博客文章目录中创建 `resources/` 子文件夹\n\n2. 对于每个提供的资源：\n   - **URL**：抓取关键内容并保存到 `resources/` 下的 markdown 文件中\n   - **文件**：读取并在 `resources/` 中做摘要\n   - **主题**：使用网络搜索收集最新信息\n\n3. 为每个资源在 `resources/` 中创建摘要文件：\n   - `resources/source-1-[short-name].md`\n   - `resources/source-2-[short-name].md`\n   - 以此类推\n\n4. 每个摘要都应包含：\n   ```markdown\n   # 来源：[标题/URL]\n\n   ## 要点\n   - 要点 1\n   - 要点 2\n\n   ## 相关引文/数据\n   - 引文或统计 1\n   - 引文或统计 2\n\n   ## 与主题的关联\n   简要说明其相关性\n   ```\n\n5. 向用户展示研究摘要。\n\n### 步骤 2：头脑风暴与澄清\n\n1. 基于想法和已研究的资源，展示：\n   - 从研究中识别出的**主要主题**\n   - 博客文章的**可能切入角度**\n   - 应该覆盖的**关键点**\n   - 仍需进一步澄清的**信息缺口**\n\n2. 提出澄清问题：\n   - 你希望读者最终带走的核心结论是什么？\n   - 研究中有没有哪些点是你希望重点强调的？\n   - 目标长度是多少？（短：500-800 字，中：1000-1500 字，长：2000+ 字）\n   - 有没有哪些内容你希望排除？\n\n3. **在继续之前，等待用户回复。**\n\n### 步骤 3：提出提纲\n\n1. 创建一个结构化提纲，包括：\n\n   ```markdown\n   # 博客文章提纲：[标题]\n\n   ## 元信息\n   - **目标读者**：[谁]\n   - **语气**：[风格]\n   - **目标长度**：[字数]\n   - **核心结论**：[关键信息]\n\n   ## 建议结构\n\n   ### 开场/引子\n   - 开场钩子思路\n   - 背景铺垫\n   - 论点陈述\n\n   ### 第一部分：[标题]\n   - 关键点 A\n   - 关键点 B\n   - 来自 [来源] 的支撑证据\n\n   ### 第二部分：[标题]\n   - 关键点 A\n   - 关键点 B\n\n   [继续列出所有部分...]\n\n   ### 结论\n   - 关键点总结\n   - 行动号召或最终思考\n\n   ## 需要引用的来源\n   - 来源 1\n   - 来源 2\n   ```\n\n2. 向用户展示提纲，并**请求批准或修改意见**。\n\n### 步骤 4：保存已批准的提纲\n\n1. 用户批准提纲后，将其保存为博客文章文件夹中的 `OUTLINE.md`。\n\n2. 确认提纲已保存。\n\n### 步骤 5：提交提纲（如果在 git 仓库中）\n\n1. 检查当前目录是否为 git 仓库。\n\n2. 如果是：\n   - 暂存新文件：博客文章文件夹、resources 和 `OUTLINE.md`\n   - 使用如下提交信息创建 commit：`docs: Add outline for blog post - [topic-name]`\n   - 推送到远程仓库\n\n3. 如果不是 git 仓库，则跳过此步骤并告知用户。\n\n### 步骤 6：撰写草稿\n\n1. 基于已批准的提纲，撰写完整博客草稿。\n\n2. 严格按照 `OUTLINE.md` 的结构进行编写。\n\n3. 包含：\n   - 有吸引力的引言和开场钩子\n   - 清晰的章节标题\n   - 来自研究的支撑证据和示例\n   - 段落之间自然流畅的过渡\n   - 强有力的结尾和核心收获\n   - **引用**：所有比较、统计数据和事实性陈述都必须引用原始来源\n\n4. 将草稿保存为博客文章文件夹中的 `draft-v0.1.md`。\n\n5. 格式：\n   ```markdown\n   # [博客文章标题]\n\n   *[可选：副标题或标语]*\n\n   [包含行内引用的完整正文...]\n\n   ---\n\n   ## 参考资料\n   - [1] 来源 1 标题 - URL 或引用\n   - [2] 来源 2 标题 - URL 或引用\n   - [3] 来源 3 标题 - URL 或引用\n   ```\n\n6. **引用要求**：\n   - 每个数据点、统计信息或比较都必须带有行内引用\n   - 使用编号引用 [1]、[2] 等，或命名引用 [Source Name]\n   - 在文末的参考资料部分链接这些引用\n   - 示例：“研究表明，65% 的开发者更偏好 TypeScript [1]”\n   - 示例：“React 在渲染速度上比 Vue 快 20% [React Benchmarks 2024]”\n\n### 步骤 7：提交草稿（如果在 git 仓库中）\n\n1. 检查是否处于 git 仓库中。\n\n2. 如果是：\n   - 暂存草稿文件\n   - 使用如下提交信息创建 commit：`docs: Add draft v0.1 for blog post - [topic-name]`\n   - 推送到远程仓库\n\n3. 如果不是 git 仓库，则跳过并告知用户。\n\n### 步骤 8：向用户展示草稿以供审阅\n\n1. 向用户展示草稿内容。\n\n2. 询问反馈：\n   - 整体印象如何？\n   - 哪些部分需要扩展或压缩？\n   - 是否需要调整语气？\n   - 是否缺少关键信息？\n   - 有没有具体编辑或重写建议？\n\n3. **等待用户回复。**\n\n### 步骤 9：迭代或定稿\n\n**如果用户要求修改：**\n1. 记录所有修改请求\n2. 返回步骤 6，并做以下调整：\n   - 将版本号递增（v0.2、v0.3 等）\n   - 纳入所有反馈\n   - 保存为 `draft-v[X.Y].md`\n   - 重复步骤 7-8\n\n**如果用户批准：**\n1. 确认最终草稿版本\n2. 如用户要求，可重命名为 `final.md`\n3. 总结博客文章创建过程：\n   - 一共创建了多少个版本\n   - 各版本之间的关键变化\n   - 最终字数\n   - 创建了哪些文件\n\n## 版本跟踪\n\n所有草稿都会以递增版本号保留：\n- `draft-v0.1.md` - 初始草稿\n- `draft-v0.2.md` - 第一轮反馈后\n- `draft-v0.3.md` - 第二轮反馈后\n- 以此类推\n\n这可以跟踪博客文章的演变过程，并在需要时回退。\n\n## 输出文件结构\n\n```text\nblog-posts/\n└── YYYY-MM-DD-topic-name/\n    ├── resources/\n    │   ├── source-1-name.md\n    │   ├── source-2-name.md\n    │   └── ...\n    ├── OUTLINE.md\n    ├── draft-v0.1.md\n    ├── draft-v0.2.md（如果有迭代）\n    └── draft-v0.3.md（如果还有更多迭代）\n```\n\n## 质量建议\n\n- **钩子**：以问题、令人惊讶的事实或贴近读者的场景开头\n- **衔接**：每一段都要自然连接到下一段\n- **证据**：用研究数据支撑观点\n- **引用**：以下内容务必引用来源：\n  - 所有统计数据和数值（例如：“根据 [Source]，75% 的……”）\n  - 对产品、服务或方案的比较（例如：“X 的速度比 Y 快 2 倍 [Source]”）\n  - 关于市场趋势、研究发现或基准测试的事实性陈述\n  - 使用行内引用，格式为：[Source Name] 或 [Author, Year]\n- **语气**：全程保持一致\n- **长度**：尊重目标字数\n- **可读性**：使用短段落，并在适当位置使用项目符号\n- **CTA**：以明确的行动号召或发人深省的问题收尾\n\n## 备注\n\n- 始终在上述需要确认的节点等待用户批准\n- 保留所有草稿版本，方便追踪历史\n- 如果提供了 URL，使用网络搜索获取最新信息\n- 如果资源不足，询问用户补充，或建议进一步研究\n- 根据目标读者调整语气（技术、通用、商业等）\n","zh/03-skills/brand-voice/SKILL.md":"---\nname: brand-voice\ndescription: 确保所有沟通内容都符合品牌语气和风格指南。适用于撰写营销文案、客户沟通、对外内容，或用户提到品牌语气、tone、写作风格的场景。\nuser-invocable: false\n---\n\n# 品牌语气技能\n\n## 概览\n此技能确保所有沟通内容在品牌语气、风格和信息传达上保持一致。\n\n## 品牌定位\n\n### 使命\n帮助团队用 AI 自动化开发工作流\n\n### 价值观\n- **简洁**：把复杂的事情变简单\n- **可靠**：执行稳健，结果稳定\n- **赋能**：释放人的创造力\n\n### 语气风格\n- **友好但专业** - 平易近人，但不过于随意\n- **清晰简洁** - 避免行话，用通俗方式解释技术概念\n- **自信** - 体现我们知道自己在做什么\n- **有同理心** - 理解用户需求和痛点\n\n## 写作指南\n\n### 应该做的 ✅\n- 对读者使用“你”\n- 使用主动语态：“Claude 会生成报告”，而不是“报告由 Claude 生成”\n- 先讲价值主张\n- 使用具体示例\n- 句子保持在 20 个词以内\n- 使用列表增强清晰度\n- 包含行动号召\n\n### 不应该做的 ❌\n- 不要使用企业黑话\n- 不要居高临下，也不要过度简化\n- 不要使用“我们相信”或“我们认为”\n- 不要全大写，除非为了强调\n- 不要写成大段文字墙\n- 不要默认读者具备技术背景\n\n## 词汇\n\n### ✅ 推荐用词\n- Claude（不要写“the Claude AI”）\n- 代码生成（不要写“auto-coding”）\n- Agent（不要写“bot”）\n- 简化流程（不要写“革命性改变”）\n- 集成（不要写“synergize”）\n\n### ❌ 避免用词\n- “cutting-edge”（过度使用）\n- “game-changer”（过于空泛）\n- “leverage”（企业黑话）\n- “utilize”（直接用“use”）\n- “paradigm shift”（不够清晰）\n\n## 示例\n\n### ✅ 好示例\n“Claude 能自动化你的代码审查流程。它不再需要你手动检查每个 PR，而是会审查安全性、性能和质量，每周为团队节省数小时。”\n\n为什么好：价值明确、收益具体、行动导向强\n\n### ❌ 坏示例\n“Claude 利用前沿 AI 为软件开发提供全面解决方案。”\n\n为什么不好：太空泛、企业黑话太多、没有具体价值\n","zh/03-skills/claude-md/SKILL.md":"---\nname: claude-md\ndescription: 按最佳实践创建或更新 CLAUDE.md 文件，以便为 AI agent 提供最优的项目入门上下文\n---\n\n## 用户输入\n\n```text\n$ARGUMENTS\n```\n\n在继续之前，你**必须**先考虑用户输入（如果不为空）。用户可能会指定：\n- `create` - 从零创建新的 CLAUDE.md\n- `update` - 改进已有的 CLAUDE.md\n- `audit` - 分析并报告当前 CLAUDE.md 的质量\n- 一个具体路径，用于创建或更新（例如 `src/api/CLAUDE.md` 代表目录级说明）\n\n## 核心原则\n\n**LLM 是无状态的**：CLAUDE.md 是每次对话都会加载的主要项目文件（与自动记忆和未限定作用域的 rules 一起加载）。它是让 AI agent 了解代码库的主要入门文档。\n\n### 黄金法则\n\n1. **少即是多**：前沿 LLM 大约能遵循 150-200 条指令。Claude Code 的系统提示词本身已经占了大约 50 条，因此 CLAUDE.md 必须聚焦且简洁。\n\n2. **只放通用信息**：只包含每次会话都适用的内容。任务特定的说明应该放在单独文件里。\n\n3. **不要把 Claude 当成 lint 工具**：风格指南会膨胀上下文并降低指令遵循效果。应改用确定性工具（如 prettier、eslint 等）。\n\n4. **绝不自动生成**：CLAUDE.md 是 AI harness 中杠杆最高的位置。应该经过认真思考后手工编写。\n\n## 执行流程\n\n### 1. 项目分析\n\n首先分析当前项目状态：\n\n1. 检查是否存在已有的 CLAUDE.md 文件：\n   - 根目录：`./CLAUDE.md` 或 `.claude/CLAUDE.md`\n   - 目录级：`**/CLAUDE.md`\n   - 全局用户配置：`~/.claude/CLAUDE.md`\n\n2. 识别项目结构：\n   - 技术栈（语言、框架）\n   - 项目类型（monorepo、单体应用、库）\n   - 开发工具（包管理器、构建系统、测试运行器）\n\n3. 查看已有文档：\n   - README.md\n   - CONTRIBUTING.md\n   - package.json、pyproject.toml、Cargo.toml 等\n\n### 2. 内容策略（WHAT, WHY, HOW）\n\n围绕三个维度组织 CLAUDE.md：\n\n#### WHAT - 技术与结构\n- 技术栈概览\n- 项目组织方式（对 monorepo 尤其重要）\n- 关键目录及其用途\n\n#### WHY - 目的与背景\n- 项目是做什么的\n- 为什么做出这些架构决策\n- 每个主要组件负责什么\n\n#### HOW - 工作流与约定\n- 开发流程（bun vs node、pip vs uv 等）\n- 测试流程和命令\n- 验证与构建方法\n- 关键“坑点”或非显而易见的要求\n\n### 3. 渐进式披露策略\n\n对于较大的项目，建议创建 `agent_docs/` 文件夹：\n\n```text\nagent_docs/\n  |- building_the_project.md\n  |- running_tests.md\n  |- code_conventions.md\n  |- architecture_decisions.md\n```\n\n在 CLAUDE.md 中引用这些文件，并写明：\n```markdown\n关于详细的构建说明，请参考 `agent_docs/building_the_project.md`\n```\n\n**重要**：使用 `file:line` 引用，而不是代码片段，以避免上下文过时。\n\n### 4. 质量约束\n\n创建或更新 CLAUDE.md 时：\n\n1. **目标长度**：少于 200 行\n2. **不要写风格规则**：移除任何 lint/format 相关说明\n3. **不要写任务特定说明**：移到单独文件中\n4. **不要写代码片段**：改用文件引用\n5. **不要重复信息**：不要重复 package.json 或 README 中已有内容\n\n### 5. 必备章节\n\n一个结构良好的 CLAUDE.md 应包含：\n\n```markdown\n# 项目名称\n\n一句简短的项目描述。\n\n## 技术栈\n- 主语言和版本\n- 关键框架/库\n- 数据库/存储（如有）\n\n## 项目结构\n[仅适用于 monorepo 或复杂结构]\n- `apps/` - 应用入口\n- `packages/` - 共享库\n\n## 开发命令\n- 安装：`command`\n- 测试：`command`\n- 构建：`command`\n\n## 关键约定\n[只保留非显而易见、高影响的约定]\n- 约定 1，简要说明\n- 约定 2，简要说明\n\n## 已知问题 / 坑点\n[经常让开发者踩坑的内容]\n- 问题 1\n- 问题 2\n```\n\n### 6. 需要避免的反模式\n\n**不要包含：**\n- 代码风格指南（交给 lint 工具）\n- 如何使用 Claude 的说明\n- 对显而易见模式的冗长解释\n- 复制粘贴的代码示例\n- 泛泛而谈的最佳实践（例如“写干净的代码”）\n- 特定任务的说明\n- 自动生成内容\n- 大量 TODO 列表\n\n### 7. 验证清单\n\n在最终确定前，检查：\n\n- [ ] 少于 200 行\n- [ ] 每一行都适用于所有会话\n- [ ] 没有风格/格式规则\n- [ ] 没有代码片段（使用文件引用）\n- [ ] 命令已经验证可用\n- [ ] 对复杂项目使用了渐进式披露\n- [ ] 已记录关键坑点\n- [ ] 没有与 README.md 重复\n\n## 输出格式\n\n### 对于 `create` 或默认模式：\n\n1. 分析项目\n2. 按上述结构起草 CLAUDE.md\n3. 向用户展示草稿以供审阅\n4. 在获得批准后写入相应位置\n\n### 对于 `update`：\n\n1. 读取现有 CLAUDE.md\n2. 按最佳实践进行审计\n3. 识别：\n   - 需要删除的内容（风格规则、代码片段、任务特定内容）\n   - 需要压缩的内容\n   - 缺失的重要信息\n4. 向用户展示修改建议\n5. 在获得批准后应用修改\n\n### 对于 `audit`：\n\n1. 读取现有 CLAUDE.md\n2. 生成报告，包括：\n   - 当前行数与目标的对比\n   - 可通用于所有会话内容的百分比\n   - 发现的反模式列表\n   - 改进建议\n3. 不要修改文件，只做报告\n\n## AGENTS.md 处理\n\n如果用户请求创建或更新 AGENTS.md：\n\n**从 v2.1.277 起，Claude Code 会直接把 `AGENTS.md` 作为项目指令读取。** 但前提是工作目录以及它上面的每一级目录都没有 `CLAUDE.md`、`.claude/CLAUDE.md` 或 `CLAUDE.local.md`。`~/.claude/CLAUDE.md`、受管理的 CLAUDE.md 和 `.claude/rules/` 不计入这项检查，它们仍会一并加载。该行为由 `/config` 中的 **Project instructions** 控制：`claude-md-or-agents-md`（默认）、`claude-md-and-agents-md`、`claude-md`、`managed-only`。在无法直接读取的环境中 — v2.1.277 之前的版本（在 Bedrock/Vertex/Foundry、LLM 网关或关闭遥测的情况下为 v2.1.281 之前），或升级后的第一个会话 — 退回到在 CLAUDE.md 中用 `@AGENTS.md` 导入，或者把 `CLAUDE.md` 软链接到它。\n\nAGENTS.md 是一个跨工具的项目上下文文件 — 和 CLAUDE.md 属于同一*类*文档，而不是 agent 定义格式。它的存在是为了让多个编码 agent 共用同一套项目约定：\n- 构建、测试和 lint 命令\n- 代码风格与架构约定\n- 仓库结构以及各部分所在位置\n\nSubagents 是单独定义的，放在 `.claude/agents/*.md` 里 — 不在 AGENTS.md 中。\n\n同样适用以下原则：\n- 保持聚焦和简洁\n- 使用渐进式披露\n- 用外部文档引用代替内联内容\n\n## 备注\n\n- 在写入前始终验证命令是否可用\n- 不确定时就不要写，少即是多\n- 系统提醒会告诉 Claude，CLAUDE.md “可能相关，也可能不相关” - 噪音越多，越容易被忽略\n- monorepo 最需要清晰的 WHAT/WHY/HOW 结构\n- 目录级 CLAUDE.md 应该更聚焦\n\n---\n\n**最后更新**: 2026 年 10 月 18 日\n**Claude Code 版本**: 2.1.302\n**来源**:\n- https://code.claude.com/docs/en/memory\n","zh/03-skills/code-review-specialist/SKILL.md":"---\nname: code-review-specialist\ndescription: 提供全面的代码审查能力，覆盖安全、性能和代码质量分析。适用于用户请求代码审查、代码质量评估、Pull Request 审查，或提到安全分析和性能优化时。\n---\n\n# 代码审查 Skill\n\n这个 skill 提供全面的代码审查能力，重点关注：\n\n1. **安全分析**\n   - 身份验证 / 授权问题\n   - 数据泄露风险\n   - 注入漏洞\n   - 密码学弱点\n   - 敏感数据日志记录\n\n2. **性能审查**\n   - 算法效率（Big O 分析）\n   - 内存优化\n   - 数据库查询优化\n   - 缓存机会\n   - 并发问题\n\n3. **代码质量**\n   - SOLID 原则\n   - 设计模式\n   - 命名规范\n   - 文档\n   - 测试覆盖率\n\n4. **可维护性**\n   - 代码可读性\n   - 函数长度（建议少于 50 行）\n   - 圈复杂度\n   - 依赖管理\n   - 类型安全\n\n## 审查模板\n\n对每一段被审查的代码，请提供：\n\n### 摘要\n- 整体质量评分（1-5）\n- 关键发现数量\n- 建议优先关注的区域\n\n### 关键问题（如有）\n- **问题**：清晰描述\n- **位置**：文件和行号\n- **影响**：为什么这很重要\n- **严重性**：Critical / High / Medium\n- **修复**：代码示例\n\n### 按类别列出发现\n\n#### 安全性（如有问题）\n列出安全漏洞及示例\n\n#### 性能（如有问题）\n列出性能问题，并说明复杂度\n\n#### 质量（如有问题）\n列出代码质量问题，并给出重构建议\n\n#### 可维护性（如有问题）\n列出可维护性问题，并给出改进建议\n\n## 版本历史\n\n- v1.0.0 (2024-12-10)：首次发布，包含安全、性能、质量和可维护性分析\n","zh/03-skills/doc-generator/SKILL.md":"---\nname: doc-generator\ndescription: 从源代码生成全面且准确的 API 文档。适用于创建或更新 API 文档、生成 OpenAPI 规范，或在用户提到 API 文档、端点或说明时使用。\n---\n\n# API 文档生成 Skill\n\n## 可生成内容\n\n- OpenAPI / Swagger 规范\n- API 端点文档\n- SDK 使用示例\n- 集成指南\n- 错误码参考\n- 认证指南\n\n## 文档结构\n\n### 每个端点的写法\n\n````markdown\n## GET /api/v1/users/:id\n\n### 描述\n简要说明这个端点做什么\n\n### 参数\n\n| 名称 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| id | string | 是 | 用户 ID |\n\n### 响应\n\n**200 成功**\n```json\n{\n  \"id\": \"usr_123\",\n  \"name\": \"John Doe\",\n  \"email\": \"john@example.com\",\n  \"created_at\": \"2025-01-15T10:30:00Z\"\n}\n```\n\n**404 未找到**\n```json\n{\n  \"error\": \"USER_NOT_FOUND\",\n  \"message\": \"User does not exist\"\n}\n```\n\n### 示例\n\n**cURL**\n```bash\ncurl -X GET \"https://api.example.com/api/v1/users/usr_123\" \\\n  -H \"Authorization: Bearer YOUR_TOKEN\"\n```\n\n**JavaScript**\n```javascript\nconst user = await fetch('/api/v1/users/usr_123', {\n  headers: { 'Authorization': 'Bearer token' }\n}).then(r => r.json());\n```\n\n**Python**\n```python\nresponse = requests.get(\n    'https://api.example.com/api/v1/users/usr_123',\n    headers={'Authorization': 'Bearer token'}\n)\nuser = response.json()\n```\n````\n","zh/03-skills/refactor/SKILL.md":"---\nname: refactor\ndescription: 基于 Martin Fowler 方法论的系统化代码重构 skill。适用于用户请求重构代码、改进代码结构、减少技术债、清理旧代码、消除 code smell 或提升可维护性时。这个 skill 采用分阶段、带研究与计划的安全增量实施方式。\n---\n\n# 代码重构 Skill\n\n这是一个基于 Martin Fowler《Refactoring: Improving the Design of Existing Code》（第 2 版）的系统化代码重构方法。这个 skill 强调安全、渐进的修改，并由测试提供保障。\n\n> “重构是在不改变软件外部行为的前提下，改进其内部结构的过程。” — Martin Fowler\n\n## 核心原则\n\n1. **保持行为不变**：外部行为必须保持一致\n2. **小步前进**：每次只做很小、可测试的改动\n3. **测试驱动**：测试是安全网\n4. **持续进行**：重构是长期过程，不是一次性任务\n5. **协作确认**：每个阶段都需要用户确认\n\n## 工作流程总览\n\n```\n阶段 1：研究与分析\n    ↓\n阶段 2：测试覆盖评估\n    ↓\n阶段 3：识别代码异味\n    ↓\n阶段 4：创建重构计划\n    ↓\n阶段 5：增量实施\n    ↓\n阶段 6：评审与迭代\n```\n\n---\n\n## 阶段 1：研究与分析\n\n### 目标\n- 理解代码库结构和用途\n- 确定重构范围\n- 收集业务需求背景\n\n### 先向用户确认的问题\n开始前先确认：\n\n1. **范围**：哪些文件 / 模块 / 函数需要重构？\n2. **目标**：你想解决什么问题？（可读性、性能、可维护性）\n3. **约束**：有哪些区域不能改？\n4. **时间压力**：这是否阻塞了其他工作？\n5. **测试状态**：是否已有测试？是否通过？\n\n### 行动\n- [ ] 阅读并理解目标代码\n- [ ] 识别依赖和集成点\n- [ ] 记录当前架构\n- [ ] 标记已有技术债迹象（TODO、FIXME）\n\n### 输出\n向用户汇报：\n- 代码结构总结\n- 识别出的问题区域\n- 初步建议\n- **请求继续执行的批准**\n\n---\n\n## 阶段 2：测试覆盖评估\n\n### 为什么测试重要\n> “没有测试的重构，就像没有安全带就开车。” — Martin Fowler\n\n测试是安全重构的**关键前提**。没有测试，很容易引入 bug。\n\n### 评估步骤\n\n1. **检查现有测试**\n   ```bash\n   # 查找测试文件\n   find . -name \"*test*\" -o -name \"*spec*\" | head -20\n   ```\n\n2. **运行现有测试**\n   ```bash\n   # JavaScript / TypeScript\n   npm test\n\n   # Python\n   pytest -v\n\n   # Java\n   mvn test\n   ```\n\n3. **检查覆盖率（如果可用）**\n   ```bash\n   # JavaScript\n   npm run test:coverage\n\n   # Python\n   pytest --cov=.\n   ```\n\n### 决策点：询问用户\n\n**如果测试存在且通过：**\n- 进入阶段 3\n\n**如果测试缺失或不完整：**\n给出选项：\n1. 先写测试（推荐）\n2. 在重构过程中逐步补测试\n3. 不写测试直接继续（有风险，需要用户确认）\n\n**如果测试失败：**\n- 停止。先修复失败测试再重构\n- 问用户：是否先修测试？\n\n### 测试编写建议（如需要）\n\n对每个要重构的函数，测试应覆盖：\n- 正常路径\n- 边界情况（空输入、null、边界值）\n- 错误场景（非法输入、异常）\n\n使用“红-绿-重构”循环：\n1. 写失败测试（红）\n2. 让它通过（绿）\n3. 再重构\n\n---\n\n## 阶段 3：识别代码异味\n\n### 什么是代码异味？\n代码深层问题的表面症状。它们不一定是 bug，但说明代码设计可能有问题。\n\n### 常见异味清单\n\n完整目录见 [references/code-smells.md](references/code-smells.md)。\n\n#### 快速参考\n\n| 异味 | 迹象 | 影响 |\n|-------|------|------|\n| **长函数** | 函数超过 30-50 行 | 难以理解、测试和维护 |\n| **重复代码** | 多处出现相同逻辑 | 修复需要改多处 |\n| **大类** | 类承担了太多职责 | 违反单一职责原则 |\n| **Feature Envy** | 一个方法更多依赖别的类的数据 | 封装性差 |\n| **基础类型沉迷** | 过度使用基础类型而不是对象 | 缺少领域概念 |\n| **长参数列表** | 方法参数超过 4 个 | 调用困难 |\n| **数据泥团** | 一组数据总是一起出现 | 缺少抽象 |\n| **switch 语句** | 复杂的 switch / if-else 链 | 难以扩展 |\n| **臆想泛化** | “以防未来需要”提前设计 | 不必要的复杂度 |\n| **死代码** | 未使用的代码 | 造成困惑和维护负担 |\n\n### 分析步骤\n\n1. **自动分析**（如果有脚本）\n   ```bash\n   python scripts/detect-smells.py <file>\n   ```\n\n2. **人工审查**\n   - 系统地走读代码\n   - 记录每个异味的位置和严重性\n   - 按影响分类（Critical / High / Medium / Low）\n\n3. **优先级排序**\n   优先关注会：\n   - 阻塞当前开发的异味\n   - 导致 bug 或混淆的异味\n   - 影响最常变更代码路径的异味\n\n### 输出：异味报告\n\n向用户呈现：\n- 识别出的异味及位置\n- 每项的严重性评估\n- 建议的优先级顺序\n- **请求用户确认优先级**\n\n---\n\n## 阶段 4：创建重构计划\n\n### 选择重构方式\n\n针对每个异味，从目录中选择合适的重构手法。\n\n完整列表见 [references/refactoring-catalog.md](references/refactoring-catalog.md)。\n\n#### 异味到重构的映射\n\n| 代码异味 | 推荐重构 |\n|----------|----------|\n| 长函数 | Extract Method、Replace Temp with Query |\n| 重复代码 | Extract Method、Pull Up Method、Form Template Method |\n| 大类 | Extract Class、Extract Subclass |\n| Feature Envy | Move Method、Move Field |\n| 基础类型沉迷 | Replace Primitive with Object、Replace Type Code with Class |\n| 长参数列表 | Introduce Parameter Object、Preserve Whole Object |\n| 数据泥团 | Extract Class、Introduce Parameter Object |\n| switch 语句 | Replace Conditional with Polymorphism |\n| 臆想泛化 | Collapse Hierarchy、Inline Class、Remove Dead Code |\n| 死代码 | Remove Dead Code |\n\n### 计划结构\n\n使用 [templates/refactoring-plan.md](templates/refactoring-plan.md) 里的模板。\n\n每项重构都要写明：\n1. **Target**：将修改哪些代码\n2. **Smell**：解决什么问题\n3. **Refactoring**：采用哪种手法\n4. **Steps**：详细微步骤\n5. **Risks**：可能出什么问题\n6. **Rollback**：如何回退\n\n### 分阶段方法\n\n**关键**：重构必须分阶段推进。\n\n**阶段 A：快速收益**（低风险，高价值）\n- 重命名变量以提升清晰度\n- 提取明显重复的代码\n- 删除死代码\n\n**阶段 B：结构改进**（中风险）\n- 从长函数中提取方法\n- 引入参数对象\n- 把方法移动到更合适的类\n\n**阶段 C：架构改动**（高风险）\n- 用多态替代条件分支\n- 提取类\n- 引入设计模式\n\n### 决策点：把计划展示给用户\n\n在开始实施前：\n- 展示完整重构计划\n- 解释每个阶段及其风险\n- 获得每个阶段的明确批准\n- **询问**：“是否继续执行阶段 A？”\n\n---\n\n## 阶段 5：增量实施\n\n### 黄金法则\n> “修改 → 测试 → 通过？→ 提交 → 下一步”\n\n### 实施节奏\n\n对每一步重构：\n\n1. **预检查**\n   - 测试通过（绿色）\n   - 代码能编译\n\n2. **只做一个小改动**\n   - 按目录中的具体操作进行\n   - 保持改动最小化\n\n3. **验证**\n   - 立刻运行测试\n   - 检查编译错误\n\n4. **如果测试通过（绿色）**\n   - 用描述清晰的提交信息提交\n   - 继续下一步\n\n5. **如果测试失败（红色）**\n   - 立刻停止\n   - 撤销改动\n   - 分析原因\n   - 如有疑问，询问用户\n\n### 提交策略\n\n每次提交都应当：\n- **原子性**：只包含一个逻辑改动\n- **可回滚**：容易撤销\n- **描述清楚**：提交信息明确\n\n示例提交信息：\n```\nrefactor: 从 processOrder() 中提取 calculateTotal()\nrefactor: 将 'x' 重命名为 'customerCount' 以提升清晰度\nrefactor: 删除未使用的 validateOldFormat() 方法\n```\n\n### 进度汇报\n\n每个子阶段完成后，向用户汇报：\n- 做了哪些改动\n- 测试是否仍通过\n- 遇到了什么问题\n- **询问**：“继续下一批吗？”\n\n---\n\n## 阶段 6：评审与迭代\n\n### 重构后检查清单\n\n- [ ] 所有测试通过\n- [ ] 没有新的警告 / 错误\n- [ ] 代码编译成功\n- [ ] 行为没有变化（手动验证）\n- [ ] 必要时已更新文档\n- [ ] 提交历史干净\n\n### 指标对比\n\n重构前后运行复杂度分析：\n```bash\npython scripts/analyze-complexity.py <file>\n```\n\n展示改进：\n- 代码行数变化\n- 圈复杂度变化\n- 可维护性指标变化\n\n### 用户评审\n\n向用户展示最终结果：\n- 所有变更摘要\n- 重构前后代码对比\n- 指标改善情况\n- 剩余技术债\n- **询问**：“你对这些改动满意吗？”\n\n### 下一步\n\n和用户讨论：\n- 还要处理哪些异味？\n- 是否安排下一次重构？\n- 是否把类似修改应用到其他地方？\n\n---\n\n## 重要指南\n\n### 何时暂停并询问\n\n遇到以下情况时，务必暂停并和用户确认：\n- 不确定业务逻辑\n- 改动可能影响外部 API\n- 测试覆盖不足\n- 需要做重大的架构决策\n- 风险上升\n- 遇到意外复杂性\n\n### 安全规则\n\n1. **没有测试不要重构**（除非用户明确确认风险）\n2. **不要做大改动**，拆成小步\n3. **每次改动后都不要跳过测试**\n4. **测试失败就不要继续**，先修复或回滚\n5. **不要臆测**，不确定就问\n\n### 不要做什么\n\n- 不要把重构和新功能混在一起\n- 不要在生产事故期间做重构\n- 不要重构你看不懂的代码\n- 不要过度设计，保持简单\n- 不要一次性重构所有内容\n\n---\n\n## 快速上手示例\n\n### 场景：长函数 + 重复逻辑\n\n**重构前：**\n```javascript\nfunction processOrder(order) {\n  // 150 行代码，包含：\n  // - 重复验证逻辑\n  // - 内联计算\n  // - 多种职责混杂\n}\n```\n\n**重构步骤：**\n\n1. **确认测试存在**，覆盖 `processOrder()`\n2. **提取** 验证逻辑为 `validateOrder()`\n3. **测试** - 应该通过\n4. **提取** 计算逻辑为 `calculateOrderTotal()`\n5. **测试** - 应该通过\n6. **提取** 通知逻辑为 `notifyCustomer()`\n7. **测试** - 应该通过\n8. **评审** - `processOrder()` 现在只负责串联 3 个清晰函数\n\n**重构后：**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const total = calculateOrderTotal(order);\n  notifyCustomer(order, total);\n  return { order, total };\n}\n```\n\n---\n\n## 参考资料\n\n- [代码异味目录](references/code-smells.md) - 代码异味完整清单\n- [重构目录](references/refactoring-catalog.md) - 重构手法\n- [重构计划模板](templates/refactoring-plan.md) - 计划模板\n\n## 脚本\n\n- `scripts/analyze-complexity.py` - 分析代码复杂度指标\n- `scripts/detect-smells.py` - 自动检测 code smell\n\n## 版本历史\n\n- v1.0.0 (2025-01-15)：首次发布，包含 Fowler 方法论、分阶段流程和用户确认点\n","zh/03-skills/refactor/references/code-smells.md":"# 代码异味目录\n\n这是基于 Martin Fowler《Refactoring》（第 2 版）的代码异味参考目录。代码异味是更深层问题的表面症状，它们说明代码设计可能出了问题。\n\n> “代码异味通常是系统中更深层问题的表面信号。” — Martin Fowler\n\n---\n\n## 过度膨胀类异味\n\n表示对象或函数已经大到不再好用。\n\n### 长函数\n\n**迹象：**\n- 函数超过 30-50 行\n- 需要滚动才能看完整个函数\n- 嵌套层级很多\n- 需要注释来解释局部逻辑\n\n**为什么不好：**\n- 难理解\n- 难单独测试\n- 改动容易波及其他逻辑\n- 重复逻辑容易藏在里面\n\n**可用重构：**\n- Extract Method\n- Replace Temp with Query\n- Introduce Parameter Object\n- Replace Method with Method Object\n- Decompose Conditional\n\n**示例（重构前）：**\n```javascript\nfunction processOrder(order) {\n  // Validate order (20 lines)\n  if (!order.items) throw new Error('No items');\n  if (order.items.length === 0) throw new Error('Empty order');\n  // ... more validation\n\n  // Calculate totals (30 lines)\n  let subtotal = 0;\n  for (const item of order.items) {\n    subtotal += item.price * item.quantity;\n  }\n  // ... tax, shipping, discounts\n\n  // Send notifications (20 lines)\n  // ... email logic\n}\n```\n\n**示例（重构后）：**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const totals = calculateOrderTotals(order);\n  sendOrderNotifications(order, totals);\n  return { order, totals };\n}\n```\n\n---\n\n### 大类\n\n**迹象：**\n- 实例变量很多（>7-10）\n- 方法很多（>15-20）\n- 类名含糊（Manager、Handler、Processor）\n- 方法没有用到全部字段\n\n**为什么不好：**\n- 违反单一职责原则\n- 难测试\n- 改动会波及无关功能\n- 难以复用局部能力\n\n**可用重构：**\n- Extract Class\n- Extract Subclass\n- Extract Interface\n\n**检测参考：**\n```text\n代码行数 > 300\n方法数量 > 15\n字段数量 > 10\n```\n\n---\n\n### 基础类型沉迷\n\n**迹象：**\n- 用基础类型表达领域概念（用 string 表示邮箱、用 int 表示金额）\n- 使用基础类型数组，而不是对象\n- 用字符串常量表示类型码\n- 大量 magic number / magic string\n\n**为什么不好：**\n- 类型层面没有验证\n- 逻辑散落在整个代码库里\n- 容易传错值\n- 缺少领域对象\n\n**可用重构：**\n- Replace Primitive with Object\n- Replace Type Code with Class\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**示例（重构前）：**\n```javascript\nconst user = {\n  email: 'john@example.com',     // 只是字符串\n  phone: '1234567890',           // 只是字符串\n  status: 'active',              // 魔法字符串\n  balance: 10050                 // 以分为单位的整数\n};\n```\n\n**示例（重构后）：**\n```javascript\nconst user = {\n  email: new Email('john@example.com'),\n  phone: new PhoneNumber('1234567890'),\n  status: UserStatus.ACTIVE,\n  balance: Money.cents(10050)\n};\n```\n\n---\n\n### 长参数列表\n\n**迹象：**\n- 方法参数超过 4 个\n- 一些参数总是一起出现\n- 布尔参数改变方法行为\n- 经常传 null / undefined\n\n**为什么不好：**\n- 难正确调用\n- 参数顺序容易搞混\n- 暗示方法做了太多事\n- 难以增加新参数\n\n**可用重构：**\n- Introduce Parameter Object\n- Preserve Whole Object\n- Replace Parameter with Method Call\n- Remove Flag Argument\n\n**示例（重构前）：**\n```javascript\nfunction createUser(firstName, lastName, email, phone,\n                    street, city, state, zip,\n                    isAdmin, isActive, createdBy) {\n  // ...\n}\n```\n\n**示例（重构后）：**\n```javascript\nfunction createUser(personalInfo, address, options) {\n  // personalInfo: { firstName, lastName, email, phone }\n  // address: { street, city, state, zip }\n  // options: { isAdmin, isActive, createdBy }\n}\n```\n\n---\n\n### 数据泥团\n\n**迹象：**\n- 同样的 3 个以上字段反复一起出现\n- 参数总是成对或成组传递\n- 类中的字段子集总是一起使用\n\n**为什么不好：**\n- 逻辑重复\n- 缺少抽象\n- 难扩展\n- 暗示隐藏的类应该存在\n\n**可用重构：**\n- Extract Class\n- Introduce Parameter Object\n- Preserve Whole Object\n\n**示例：**\n```javascript\n// 数据泥团：坐标 (x, y, z)\nfunction movePoint(x, y, z, dx, dy, dz) { }\nfunction scalePoint(x, y, z, factor) { }\nfunction distanceBetween(x1, y1, z1, x2, y2, z2) { }\n\n// 提取 Point3D 类\nclass Point3D {\n  constructor(x, y, z) { }\n  move(delta) { }\n  scale(factor) { }\n  distanceTo(other) { }\n}\n```\n\n---\n\n## 面向对象滥用类异味\n\n表示 OOP 原则没有被正确使用。\n\n### switch 语句\n\n**迹象：**\n- 长 switch/case 或 if/else 链\n- 多处出现相同 switch\n- 按类型码分支\n- 新增 case 时需要改很多地方\n\n**为什么不好：**\n- 违反开放 / 封闭原则\n- 改动会扩散到所有 switch 位置\n- 难扩展\n- 往往说明缺少多态\n\n**可用重构：**\n- Replace Conditional with Polymorphism\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**示例（重构前）：**\n```javascript\nfunction calculatePay(employee) {\n  switch (employee.type) {\n    case 'hourly':\n      return employee.hours * employee.rate;\n    case 'salaried':\n      return employee.salary / 12;\n    case 'commissioned':\n      return employee.sales * employee.commission;\n  }\n}\n```\n\n**示例（重构后）：**\n```javascript\nclass HourlyEmployee {\n  calculatePay() {\n    return this.hours * this.rate;\n  }\n}\n\nclass SalariedEmployee {\n  calculatePay() {\n    return this.salary / 12;\n  }\n}\n```\n\n---\n\n### 临时字段\n\n**迹象：**\n- 实例变量只在部分方法中使用\n- 字段只在某些条件下设置\n- 某些情况初始化过程很复杂\n\n**为什么不好：**\n- 容易混淆：字段存在但可能为 null\n- 对象状态难理解\n- 说明条件逻辑被隐藏了\n\n**可用重构：**\n- Extract Class\n- Introduce Null Object\n- Replace Temp Field with Local\n\n---\n\n### 拒绝遗赠\n\n**迹象：**\n- 子类没有用到继承来的方法 / 数据\n- 子类重写方法只是为了不做事\n- 继承被当成代码复用，而不是真正的 IS-A\n\n**为什么不好：**\n- 抽象不对\n- 违反里氏替换原则\n- 继承层次误导人\n\n**可用重构：**\n- Push Down Method / Field\n- Replace Subclass with Delegate\n- Replace Inheritance with Delegation\n\n---\n\n### 不同接口的相似类\n\n**迹象：**\n- 两个类做的事情差不多\n- 同一个概念却用了不同方法名\n- 理论上可以互换使用\n\n**为什么不好：**\n- 重复实现\n- 没有公共接口\n- 难切换\n\n**可用重构：**\n- Rename Method\n- Move Method\n- Extract Superclass\n- Extract Interface\n\n---\n\n## 变更阻碍类异味\n\n这类异味会让改动变得困难，一次改动需要波及很多地方。\n\n### 发散式变化\n\n**迹象：**\n- 一个类因为很多不同原因而被修改\n- 不同区域的变更都会触发同一个类的编辑\n- 类变成了“上帝类”\n\n**为什么不好：**\n- 违反单一职责原则\n- 变更频率高\n- 容易产生合并冲突\n\n**可用重构：**\n- Extract Class\n- Extract Superclass\n- Extract Subclass\n\n**示例：**\n一个 `User` 类同时因为这些原因变化：\n- 身份验证变化\n- 个人资料变化\n- 计费变化\n- 通知变化\n\n→ 可以拆成：`AuthService`、`ProfileService`、`BillingService`、`NotificationService`\n\n---\n\n### 散弹式修改\n\n**迹象：**\n- 一个改动需要编辑很多类\n- 一个小功能要触碰 10+ 个文件\n- 改动分散，难以一次找全\n\n**为什么不好：**\n- 很容易漏改\n- 耦合高\n- 容易出错\n\n**可用重构：**\n- Move Method\n- Move Field\n- Inline Class\n\n**检测参考：**\n如果新增一个字段需要改 5 个以上文件，就要警惕。\n\n---\n\n### 平行继承体系\n\n**迹象：**\n- 在一个继承体系中创建子类，另一个体系也得跟着创建\n- 类前缀相似（如 `DatabaseOrder`、`DatabaseProduct`）\n\n**为什么不好：**\n- 维护成本翻倍\n- 两个层次之间耦合\n- 容易漏掉一边\n\n**可用重构：**\n- Move Method\n- Move Field\n- 消除其中一个层次\n\n---\n\n## 可舍弃类异味\n\n表示有些东西已经不必要了，应该移除。\n\n### 注释过多\n\n**迹象：**\n- 注释在解释代码“做了什么”\n- 注释掉的代码\n- 长期存在的 TODO / FIXME\n- 注释里带道歉语气\n\n**为什么不好：**\n- 注释会过时\n- 代码本身应该能自解释\n- 死代码会造成混乱\n\n**可用重构：**\n- Extract Method（让方法名解释意图）\n- Rename（通过命名提升清晰度）\n- 删除注释掉的代码\n- Introduce Assertion\n\n**好与坏的注释：**\n```javascript\n// BAD: 解释做了什么\n// 遍历用户并检查是否活跃\nfor (const user of users) {\n  if (user.status === 'active') { }\n}\n\n// GOOD: 解释为什么\n// 只保留活跃用户，未活跃用户由清理任务处理\nconst activeUsers = users.filter(u => u.isActive);\n```\n\n---\n\n### 重复代码\n\n**迹象：**\n- 多处出现相同代码\n- 只有少量差异的相似代码\n- 复制粘贴模式\n\n**为什么不好：**\n- 修复要改多处\n- 容易不一致\n- 代码库臃肿\n\n**可用重构：**\n- Extract Method\n- Extract Class\n- Pull Up Method（在继承层次中）\n- Form Template Method\n\n**检测规则：**\n任何重复 3 次以上的代码都应该考虑提取。\n\n---\n\n### 惰性类\n\n**迹象：**\n- 类做的事情不足以支撑它的存在\n- 只是一个没有增值的包装器\n- 过度设计的产物\n\n**为什么不好：**\n- 增加维护开销\n- 多了一层没必要的间接\n- 有复杂度但没收益\n\n**可用重构：**\n- Inline Class\n- Collapse Hierarchy\n\n---\n\n### 死代码\n\n**迹象：**\n- 无法到达的代码\n- 未使用的变量 / 方法 / 类\n- 注释掉的代码\n- 位于不可能条件分支后的代码\n\n**为什么不好：**\n- 造成困惑\n- 增加维护负担\n- 降低理解速度\n\n**可用重构：**\n- Remove Dead Code\n- Safe Delete\n\n**检测：**\n```bash\n# 查找未使用的导出\n# 查找未引用的函数\n# IDE 的“unused”警告\n```\n\n---\n\n### 臆想泛化\n\n**迹象：**\n- 只有一个子类的抽象类\n- 为“未来可能需要”而加的未使用参数\n- 只是转发的函数\n- 为一个用例设计的“框架”\n\n**为什么不好：**\n- 复杂度没有收益\n- 违背 YAGNI\n- 更难理解\n\n**可用重构：**\n- Collapse Hierarchy\n- Inline Class\n- Remove Parameter\n- Rename Method\n\n---\n\n## 耦合类异味\n\n表示类之间耦合过强。\n\n### Feature Envy\n\n**迹象：**\n- 一个方法使用别的类的数据比自己更多\n- 对另一个对象调用很多 getter\n- 数据和行为分离\n\n**为什么不好：**\n- 行为放错地方了\n- 封装性差\n- 难维护\n\n**可用重构：**\n- Move Method\n- Move Field\n- Extract Method（然后移动）\n\n**示例（重构前）：**\n```javascript\nclass Order {\n  getDiscountedPrice(customer) {\n    // 这里大量使用 customer 数据\n    if (customer.loyaltyYears > 5) {\n      return this.price * customer.discountRate;\n    }\n    return this.price;\n  }\n}\n```\n\n**示例（重构后）：**\n```javascript\nclass Customer {\n  getDiscountedPriceFor(price) {\n    if (this.loyaltyYears > 5) {\n      return price * this.discountRate;\n    }\n    return price;\n  }\n}\n```\n\n---\n\n### 不恰当的亲密\n\n**迹象：**\n- 类之间互相访问私有细节\n- 双向引用很多\n- 子类知道父类太多细节\n\n**为什么不好：**\n- 耦合高\n- 改一边会连带另一边\n- 难单独修改\n\n**可用重构：**\n- Move Method\n- Move Field\n- Change Bidirectional to Unidirectional\n- Extract Class\n- Hide Delegate\n\n---\n\n### 消息链\n\n**迹象：**\n- 方法调用链很长：`a.getB().getC().getD().getValue()`\n- 客户端依赖导航结构\n- “火车残骸”式代码\n\n**为什么不好：**\n- 很脆弱，任何一层变动都会坏\n- 违反迪米特法则\n- 绑定到对象结构\n\n**可用重构：**\n- Hide Delegate\n- Extract Method\n- Move Method\n\n**示例：**\n```javascript\n// 差：消息链\nconst managerName = employee.getDepartment().getManager().getName();\n\n// 更好：隐藏委派\nconst managerName = employee.getManagerName();\n```\n\n---\n\n### 中间人\n\n**迹象：**\n- 类只是把调用转发给另一个类\n- 一半以上的方法都是委派\n- 没有额外价值\n\n**为什么不好：**\n- 多了一层没必要的间接\n- 维护成本更高\n- 架构令人困惑\n\n**可用重构：**\n- Remove Middle Man\n- Inline Method\n\n---\n\n## 严重性指南\n\n| 严重性 | 说明 | 处理方式 |\n|--------|------|---------|\n| **Critical** | 阻塞开发，导致 bug | 立刻修复 |\n| **High** | 明显增加维护负担 | 本迭代修复 |\n| **Medium** | 有问题但还能接受 | 近期计划修复 |\n| **Low** | 小问题 | 视情况顺手修 |\n\n---\n\n## 快速检测清单\n\n扫描代码时使用这个清单：\n\n- [ ] 有没有超过 30 行的函数？\n- [ ] 有没有超过 300 行的类？\n- [ ] 有没有参数超过 4 个的函数？\n- [ ] 有没有重复代码块？\n- [ ] 有没有按类型码分支的 switch/case？\n- [ ] 有没有未使用的代码？\n- [ ] 有没有大量使用其他类数据的方法？\n- [ ] 有没有很长的方法调用链？\n- [ ] 有没有解释“是什么”而不是“为什么”的注释？\n- [ ] 有没有应该封装成对象的基础类型？\n\n---\n\n## 延伸阅读\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Kerievsky, J. (2004). *Refactoring to Patterns*\n- Feathers, M. (2004). *Working Effectively with Legacy Code*\n","zh/03-skills/refactor/references/refactoring-catalog.md":"# 重构目录\n\n这是 Martin Fowler《Refactoring》（第 2 版）中的一份精选重构目录。每个重构都包含动机、操作步骤和示例。\n\n> “重构由它的操作步骤来定义，也就是你执行这个变化时遵循的精确过程。” — Martin Fowler\n\n---\n\n## 如何使用这个目录\n\n1. **识别异味**：先用代码异味目录定位问题\n2. **找到对应重构**：在这里查找匹配的手法\n3. **按步骤执行**：一步一步来\n4. **每步都测试**：确保行为不变\n\n**黄金法则**：如果某一步超过 10 分钟，就把它拆得更小。\n\n---\n\n## 最常见的重构\n\n### Extract Method\n\n**何时使用**：长函数、重复代码、需要为概念命名\n\n**动机**：把一段代码抽成一个名字能说明意图的方法。\n\n**步骤**：\n1. 创建一个新方法，名字应描述“做什么”而不是“怎么做”\n2. 把代码片段复制到新方法里\n3. 检查片段里用了哪些局部变量\n4. 把局部变量作为参数传入，或在方法内声明\n5. 正确处理返回值\n6. 用新方法调用替换原始片段\n7. 测试\n\n**前：**\n```javascript\nfunction printOwing(invoice) {\n  let outstanding = 0;\n\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n\n  // Calculate outstanding\n  for (const order of invoice.orders) {\n    outstanding += order.amount;\n  }\n\n  // Print details\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n**后：**\n```javascript\nfunction printOwing(invoice) {\n  printBanner();\n  const outstanding = calculateOutstanding(invoice);\n  printDetails(invoice, outstanding);\n}\n\nfunction printBanner() {\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n}\n\nfunction calculateOutstanding(invoice) {\n  return invoice.orders.reduce((sum, order) => sum + order.amount, 0);\n}\n\nfunction printDetails(invoice, outstanding) {\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n---\n\n### Inline Method\n\n**何时使用**：方法体和名字一样清楚，或者只是多余转发\n\n**动机**：当方法没有额外价值时，去掉不必要的间接层。\n\n**步骤**：\n1. 确认这个方法不是多态方法\n2. 找到所有调用点\n3. 用方法体替换每个调用\n4. 每替换一次就测试一次\n5. 删除方法定义\n\n**前：**\n```javascript\nfunction getRating(driver) {\n  return moreThanFiveLateDeliveries(driver) ? 2 : 1;\n}\n\nfunction moreThanFiveLateDeliveries(driver) {\n  return driver.numberOfLateDeliveries > 5;\n}\n```\n\n**后：**\n```javascript\nfunction getRating(driver) {\n  return driver.numberOfLateDeliveries > 5 ? 2 : 1;\n}\n```\n\n---\n\n### Extract Variable\n\n**何时使用**：复杂表达式难以理解\n\n**动机**：给复杂表达式的一部分起名字。\n\n**步骤**：\n1. 确保表达式没有副作用\n2. 声明一个不可变变量\n3. 将表达式结果赋给变量\n4. 用变量替换原表达式\n5. 测试\n\n**前：**\n```javascript\nreturn order.quantity * order.itemPrice -\n  Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +\n  Math.min(order.quantity * order.itemPrice * 0.1, 100);\n```\n\n**后：**\n```javascript\nconst basePrice = order.quantity * order.itemPrice;\nconst quantityDiscount = Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;\nconst shipping = Math.min(basePrice * 0.1, 100);\nreturn basePrice - quantityDiscount + shipping;\n```\n\n---\n\n### Inline Variable\n\n**何时使用**：变量名没有比表达式更清楚\n\n**动机**：移除没必要的间接层。\n\n**步骤**：\n1. 检查右侧表达式没有副作用\n2. 如果变量不是不可变的，先改成不可变并测试\n3. 找到第一次引用并替换成表达式\n4. 测试\n5. 对所有引用重复\n6. 删除变量声明和赋值\n7. 测试\n\n---\n\n### Rename Variable\n\n**何时使用**：名字没有清楚表达用途\n\n**动机**：好名字是清晰代码的基础。\n\n**步骤**：\n1. 如果变量使用范围很广，先考虑封装\n2. 找到所有引用\n3. 逐个修改引用\n4. 测试\n\n**提示**：\n- 使用能体现意图的名字\n- 避免缩写\n- 使用领域术语\n\n```javascript\n// Bad\nconst d = 30;\nconst x = users.filter(u => u.a);\n\n// Good\nconst daysSinceLastLogin = 30;\nconst activeUsers = users.filter(user => user.isActive);\n```\n\n---\n\n### Change Function Declaration\n\n**何时使用**：函数名不能清楚说明用途，参数也需要变化\n\n**动机**：好函数名能让代码自解释。\n\n**步骤（简单情况）**：\n1. 删除不需要的参数\n2. 修改函数名\n3. 添加需要的参数\n4. 测试\n\n**步骤（迁移式，适用于复杂改动）**：\n1. 如果要删除参数，确保它没有被使用\n2. 创建一个新函数，声明符合新设计\n3. 让旧函数调用新函数\n4. 测试\n5. 让调用方逐步改用新函数\n6. 每改一个调用点就测试\n7. 删除旧函数\n\n**前：**\n```javascript\nfunction circum(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n**后：**\n```javascript\nfunction circumference(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n---\n\n### Encapsulate Variable\n\n**何时使用**：多个地方直接访问某个数据\n\n**动机**：为数据访问提供明确入口。\n\n**步骤**：\n1. 创建 getter 和 setter\n2. 找到所有引用\n3. 用 getter 替换读取\n4. 用 setter 替换写入\n5. 每次改动后测试\n6. 降低变量可见性\n\n**前：**\n```javascript\nlet defaultOwner = { firstName: \"Martin\", lastName: \"Fowler\" };\n\n// Used in many places\nspaceship.owner = defaultOwner;\n```\n\n**后：**\n```javascript\nlet defaultOwnerData = { firstName: \"Martin\", lastName: \"Fowler\" };\n\nfunction defaultOwner() { return defaultOwnerData; }\nfunction setDefaultOwner(arg) { defaultOwnerData = arg; }\n\nspaceship.owner = defaultOwner();\n```\n\n---\n\n### Introduce Parameter Object\n\n**何时使用**：一组参数经常一起出现\n\n**动机**：把自然属于一起的数据打包起来。\n\n**步骤**：\n1. 为这组参数创建一个新类 / 结构\n2. 测试\n3. 用 Change Function Declaration 引入新对象\n4. 测试\n5. 逐个移除参数，改用对象字段\n6. 每次移除后测试\n\n**前：**\n```javascript\nfunction amountInvoiced(startDate, endDate) { ... }\nfunction amountReceived(startDate, endDate) { ... }\nfunction amountOverdue(startDate, endDate) { ... }\n```\n\n**后：**\n```javascript\nclass DateRange {\n  constructor(start, end) {\n    this.start = start;\n    this.end = end;\n  }\n}\n\nfunction amountInvoiced(dateRange) { ... }\nfunction amountReceived(dateRange) { ... }\nfunction amountOverdue(dateRange) { ... }\n```\n\n---\n\n### Combine Functions into Class\n\n**何时使用**：多个函数操作同一份数据\n\n**动机**：把函数和它操作的数据放到一起。\n\n**步骤**：\n1. 对公共数据先做 Encapsulate Record\n2. 把每个函数移动到类里\n3. 每移动一次就测试\n4. 用类字段替代数据参数\n\n**前：**\n```javascript\nfunction base(reading) { ... }\nfunction taxableCharge(reading) { ... }\nfunction calculateBaseCharge(reading) { ... }\n```\n\n**后：**\n```javascript\nclass Reading {\n  constructor(data) { this._data = data; }\n\n  get base() { ... }\n  get taxableCharge() { ... }\n  get calculateBaseCharge() { ... }\n}\n```\n\n---\n\n### Split Phase\n\n**何时使用**：代码在处理两件不同的事\n\n**动机**：把代码拆成边界清晰的两个阶段。\n\n**步骤**：\n1. 为第二阶段创建新函数\n2. 测试\n3. 在两个阶段之间引入中间数据结构\n4. 测试\n5. 把第一阶段提取成独立函数\n6. 测试\n\n**前：**\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  const shippingPerCase = (basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = quantity * shippingPerCase;\n  return basePrice - discount + shippingCost;\n}\n```\n\n**后：**\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const priceData = calculatePricingData(product, quantity);\n  return applyShipping(priceData, shippingMethod);\n}\n\nfunction calculatePricingData(product, quantity) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  return { basePrice, quantity, discount };\n}\n\nfunction applyShipping(priceData, shippingMethod) {\n  const shippingPerCase = (priceData.basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = priceData.quantity * shippingPerCase;\n  return priceData.basePrice - priceData.discount + shippingCost;\n}\n```\n\n---\n\n## 移动特性\n\n### Move Method\n\n**何时使用**：方法更依赖另一个类的数据而不是自己类的数据\n\n**动机**：把函数放到它最依赖的数据所在的类里。\n\n**步骤**：\n1. 检查方法使用到的所有程序元素\n2. 确认方法不是多态的\n3. 把方法复制到目标类\n4. 调整上下文\n5. 让原方法委托给目标方法\n6. 测试\n7. 视情况删除原方法\n\n---\n\n### Move Field\n\n**何时使用**：字段更多被另一个类使用\n\n**动机**：让数据和使用它的函数靠在一起。\n\n**步骤**：\n1. 如果还没有，先封装字段\n2. 测试\n3. 在目标类中创建字段\n4. 把引用改成使用目标字段\n5. 测试\n6. 删除原字段\n\n---\n\n### Move Statements into Function\n\n**何时使用**：相同代码总是跟着函数调用一起出现\n\n**动机**：把重复语句移入函数，去掉重复。\n\n**步骤**：\n1. 如果还没有，先把重复代码提取成函数\n2. 把语句移入函数\n3. 测试\n4. 如果调用方不再需要独立语句，就删除它们\n\n---\n\n### Move Statements to Callers\n\n**何时使用**：不同调用方需要不同的行为\n\n**动机**：当行为需要差异化时，把它从函数里移出去。\n\n**步骤**：\n1. 先对要移动的代码做 Extract Method\n2. 再对原函数做 Inline Method\n3. 删除被内联后的调用\n4. 把提取出的代码移到各个调用方\n5. 测试\n\n---\n\n## 数据组织\n\n### Replace Primitive with Object\n\n**何时使用**：数据项需要的不只是简单值\n\n**动机**：把数据和行为封装在一起。\n\n**步骤**：\n1. 先做 Encapsulate Variable\n2. 创建一个简单值对象\n3. 修改 setter，让它创建新实例\n4. 修改 getter，让它返回值\n5. 测试\n6. 给新类增加更丰富的行为\n\n**前：**\n```javascript\nclass Order {\n  constructor(data) {\n    this.priority = data.priority; // string: \"high\", \"rush\", etc.\n  }\n}\n\n// Usage\nif (order.priority === \"high\" || order.priority === \"rush\") { ... }\n```\n\n**后：**\n```javascript\nclass Priority {\n  constructor(value) {\n    if (!Priority.legalValues().includes(value))\n      throw new Error(`Invalid priority: ${value}`);\n    this._value = value;\n  }\n\n  static legalValues() { return ['low', 'normal', 'high', 'rush']; }\n  get value() { return this._value; }\n\n  higherThan(other) {\n    return Priority.legalValues().indexOf(this._value) >\n           Priority.legalValues().indexOf(other._value);\n  }\n}\n\n// Usage\nif (order.priority.higherThan(new Priority(\"normal\"))) { ... }\n```\n\n---\n\n### Replace Temp with Query\n\n**何时使用**：临时变量保存的是一个表达式结果\n\n**动机**：把表达式提取成函数，让代码更清晰。\n\n**步骤**：\n1. 确保变量只被赋值一次\n2. 把赋值右侧提取成一个方法\n3. 用方法调用替换临时变量引用\n4. 测试\n5. 删除临时变量声明和赋值\n\n**前：**\n```javascript\nconst basePrice = this._quantity * this._itemPrice;\nif (basePrice > 1000) {\n  return basePrice * 0.95;\n} else {\n  return basePrice * 0.98;\n}\n```\n\n**后：**\n```javascript\nget basePrice() {\n  return this._quantity * this._itemPrice;\n}\n\n// In the method\nif (this.basePrice > 1000) {\n  return this.basePrice * 0.95;\n} else {\n  return this.basePrice * 0.98;\n}\n```\n\n---\n\n## 简化条件逻辑\n\n### Decompose Conditional\n\n**何时使用**：复杂条件语句\n\n**动机**：把条件和分支动作分别提取出来，让意图更清楚。\n\n**步骤**：\n1. 对条件做 Extract Method\n2. 对 then 分支做 Extract Method\n3. 对 else 分支也做 Extract Method（如果有）\n\n**前：**\n```javascript\nif (!aDate.isBefore(plan.summerStart) && !aDate.isAfter(plan.summerEnd)) {\n  charge = quantity * plan.summerRate;\n} else {\n  charge = quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n**后：**\n```javascript\nif (isSummer(aDate, plan)) {\n  charge = summerCharge(quantity, plan);\n} else {\n  charge = regularCharge(quantity, plan);\n}\n\nfunction isSummer(date, plan) {\n  return !date.isBefore(plan.summerStart) && !date.isAfter(plan.summerEnd);\n}\n\nfunction summerCharge(quantity, plan) {\n  return quantity * plan.summerRate;\n}\n\nfunction regularCharge(quantity, plan) {\n  return quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n---\n\n### Consolidate Conditional Expression\n\n**何时使用**：多个条件最后都返回同一个结果\n\n**动机**：让人一眼看出这些条件其实是一道检查。\n\n**步骤**：\n1. 确认条件没有副作用\n2. 用 and / or 合并条件\n3. 视情况对合并后的条件做 Extract Method\n\n**前：**\n```javascript\nif (employee.seniority < 2) return 0;\nif (employee.monthsDisabled > 12) return 0;\nif (employee.isPartTime) return 0;\n```\n\n**后：**\n```javascript\nif (isNotEligibleForDisability(employee)) return 0;\n\nfunction isNotEligibleForDisability(employee) {\n  return employee.seniority < 2 ||\n         employee.monthsDisabled > 12 ||\n         employee.isPartTime;\n}\n```\n\n---\n\n### Replace Nested Conditional with Guard Clauses\n\n**何时使用**：深层嵌套条件让流程难以追踪\n\n**动机**：用 guard clause 提前返回，让正常流程更清楚。\n\n**步骤**：\n1. 找出特殊情况\n2. 用提前返回的 guard clause 替换它们\n3. 每改一步就测试\n\n**前：**\n```javascript\nfunction payAmount(employee) {\n  let result;\n  if (employee.isSeparated) {\n    result = { amount: 0, reasonCode: \"SEP\" };\n  } else {\n    if (employee.isRetired) {\n      result = { amount: 0, reasonCode: \"RET\" };\n    } else {\n      result = calculateNormalPay(employee);\n    }\n  }\n  return result;\n}\n```\n\n**后：**\n```javascript\nfunction payAmount(employee) {\n  if (employee.isSeparated) return { amount: 0, reasonCode: \"SEP\" };\n  if (employee.isRetired) return { amount: 0, reasonCode: \"RET\" };\n  return calculateNormalPay(employee);\n}\n```\n\n---\n\n### Replace Conditional with Polymorphism\n\n**何时使用**：按类型分支的 switch / 条件逻辑\n\n**动机**：让对象自己处理自己的行为。\n\n**步骤**：\n1. 创建类层次（如果还没有）\n2. 用 Factory Function 创建对象\n3. 把条件逻辑移到超类方法里\n4. 给每种情况创建子类方法\n5. 删除原条件\n\n**前：**\n```javascript\nfunction plumages(birds) {\n  return birds.map(b => plumage(b));\n}\n\nfunction plumage(bird) {\n  switch (bird.type) {\n    case 'EuropeanSwallow':\n      return \"average\";\n    case 'AfricanSwallow':\n      return (bird.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n    case 'NorwegianBlueParrot':\n      return (bird.voltage > 100) ? \"scorched\" : \"beautiful\";\n    default:\n      return \"unknown\";\n  }\n}\n```\n\n**后：**\n```javascript\nclass Bird {\n  get plumage() { return \"unknown\"; }\n}\n\nclass EuropeanSwallow extends Bird {\n  get plumage() { return \"average\"; }\n}\n\nclass AfricanSwallow extends Bird {\n  get plumage() {\n    return (this.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n  }\n}\n\nclass NorwegianBlueParrot extends Bird {\n  get plumage() {\n    return (this.voltage > 100) ? \"scorched\" : \"beautiful\";\n  }\n}\n\nfunction createBird(data) {\n  switch (data.type) {\n    case 'EuropeanSwallow': return new EuropeanSwallow(data);\n    case 'AfricanSwallow': return new AfricanSwallow(data);\n    case 'NorwegianBlueParrot': return new NorwegianBlueParrot(data);\n    default: return new Bird(data);\n  }\n}\n```\n\n---\n\n### Introduce Special Case (Null Object)\n\n**何时使用**：重复出现 null 检查\n\n**动机**：返回一个特殊对象来处理特殊情况。\n\n**步骤**：\n1. 创建一个具备预期接口的特殊情况类\n2. 增加 isSpecialCase 检查\n3. 引入工厂方法\n4. 用特殊对象替换 null 检查\n5. 测试\n\n**前：**\n```javascript\nconst customer = site.customer;\n// ... many places checking\nif (customer === \"unknown\") {\n  customerName = \"occupant\";\n} else {\n  customerName = customer.name;\n}\n```\n\n**后：**\n```javascript\nclass UnknownCustomer {\n  get name() { return \"occupant\"; }\n  get billingPlan() { return registry.defaultPlan; }\n}\n\n// Factory method\nfunction customer(site) {\n  return site.customer === \"unknown\"\n    ? new UnknownCustomer()\n    : site.customer;\n}\n\n// Usage - no null checks needed\nconst customerName = customer.name;\n```\n\n---\n\n## 重构 API\n\n### Separate Query from Modifier\n\n**何时使用**：函数既返回值又有副作用\n\n**动机**：明确哪些操作会产生副作用。\n\n**步骤**：\n1. 创建新的查询函数\n2. 复制原函数的返回逻辑\n3. 修改原函数，让它只负责副作用\n4. 替换依赖返回值的调用点\n5. 测试\n\n**前：**\n```javascript\nfunction alertForMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") {\n      setOffAlarms();\n      return \"Don\";\n    }\n    if (p === \"John\") {\n      setOffAlarms();\n      return \"John\";\n    }\n  }\n  return \"\";\n}\n```\n\n**后：**\n```javascript\nfunction findMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") return \"Don\";\n    if (p === \"John\") return \"John\";\n  }\n  return \"\";\n}\n\nfunction alertForMiscreant(people) {\n  if (findMiscreant(people) !== \"\") setOffAlarms();\n}\n```\n\n---\n\n### Parameterize Function\n\n**何时使用**：有多个做类似事情但数值不同的函数\n\n**动机**：通过参数化减少重复。\n\n**步骤**：\n1. 选择一个函数\n2. 为变化的字面值增加参数\n3. 修改函数体使用该参数\n4. 测试\n5. 让调用方改用参数化版本\n6. 删除不再使用的旧函数\n\n**前：**\n```javascript\nfunction tenPercentRaise(person) {\n  person.salary = person.salary * 1.10;\n}\n\nfunction fivePercentRaise(person) {\n  person.salary = person.salary * 1.05;\n}\n```\n\n**后：**\n```javascript\nfunction raise(person, factor) {\n  person.salary = person.salary * (1 + factor);\n}\n\n// Usage\nraise(person, 0.10);\nraise(person, 0.05);\n```\n\n---\n\n### Remove Flag Argument\n\n**何时使用**：布尔参数改变函数行为\n\n**动机**：通过拆分成明确函数，让行为更清楚。\n\n**步骤**：\n1. 针对不同旗标值创建显式函数\n2. 替换每个调用点\n3. 每次改动后测试\n4. 删除原函数\n\n**前：**\n```javascript\nfunction bookConcert(customer, isPremium) {\n  if (isPremium) {\n    // premium booking logic\n  } else {\n    // regular booking logic\n  }\n}\n\nbookConcert(customer, true);\nbookConcert(customer, false);\n```\n\n**后：**\n```javascript\nfunction bookPremiumConcert(customer) {\n  // premium booking logic\n}\n\nfunction bookRegularConcert(customer) {\n  // regular booking logic\n}\n\nbookPremiumConcert(customer);\nbookRegularConcert(customer);\n```\n\n---\n\n## 继承相关\n\n### Pull Up Method\n\n**何时使用**：多个子类里有相同方法\n\n**动机**：去掉类层次中的重复。\n\n**步骤**：\n1. 检查方法是否完全相同\n2. 确认签名一致\n3. 在超类中新建方法\n4. 从一个子类复制实现\n5. 删除一个子类中的方法并测试\n6. 删除其他子类中的方法并测试\n\n---\n\n### Push Down Method\n\n**何时使用**：某个行为只适用于部分子类\n\n**动机**：把方法放到真正使用它的地方。\n\n**步骤**：\n1. 把方法复制到需要它的子类\n2. 从超类删除方法\n3. 测试\n4. 删除不需要该方法的子类副本\n5. 测试\n\n---\n\n### Replace Subclass with Delegate\n\n**何时使用**：继承用得不对，需要更灵活\n\n**动机**：在合适的地方更偏向组合而不是继承。\n\n**步骤**：\n1. 创建一个空的委托类\n2. 在宿主类中加一个持有委托的字段\n3. 在宿主类构造委托\n4. 把功能迁移到委托类\n5. 每次迁移后测试\n6. 用委托替代继承\n\n---\n\n## Extract Class\n\n**何时使用**：大类里有多个职责\n\n**动机**：拆分类以维持单一职责。\n\n**步骤**：\n1. 决定如何拆分职责\n2. 创建新类\n3. 把字段从原类移到新类\n4. 测试\n5. 把方法从原类移到新类\n6. 每次移动后测试\n7. 重新检查并命名两个类\n8. 决定如何暴露新类\n\n**前：**\n```javascript\nclass Person {\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get officeAreaCode() { return this._officeAreaCode; }\n  set officeAreaCode(arg) { this._officeAreaCode = arg; }\n  get officeNumber() { return this._officeNumber; }\n  set officeNumber(arg) { this._officeNumber = arg; }\n\n  get telephoneNumber() {\n    return `(${this._officeAreaCode}) ${this._officeNumber}`;\n  }\n}\n```\n\n**后：**\n```javascript\nclass Person {\n  constructor() {\n    this._telephoneNumber = new TelephoneNumber();\n  }\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get telephoneNumber() { return this._telephoneNumber.toString(); }\n  get officeAreaCode() { return this._telephoneNumber.areaCode; }\n  set officeAreaCode(arg) { this._telephoneNumber.areaCode = arg; }\n}\n\nclass TelephoneNumber {\n  get areaCode() { return this._areaCode; }\n  set areaCode(arg) { this._areaCode = arg; }\n  get number() { return this._number; }\n  set number(arg) { this._number = arg; }\n  toString() { return `(${this._areaCode}) ${this._number}`; }\n}\n```\n\n---\n\n## 快速参考：异味到重构\n\n| 代码异味 | 主要重构 | 备选方案 |\n|----------|---------|---------|\n| 长函数 | Extract Method | Replace Temp with Query |\n| 重复代码 | Extract Method | Pull Up Method |\n| 大类 | Extract Class | Extract Subclass |\n| 长参数列表 | Introduce Parameter Object | Preserve Whole Object |\n| Feature Envy | Move Method | Extract Method + Move |\n| 数据泥团 | Extract Class | Introduce Parameter Object |\n| 基础类型沉迷 | Replace Primitive with Object | Replace Type Code |\n| switch 语句 | Replace Conditional with Polymorphism | Replace Type Code |\n| 临时字段 | Extract Class | Introduce Null Object |\n| 消息链 | Hide Delegate | Extract Method |\n| 中间人 | Remove Middle Man | Inline Method |\n| 发散式变化 | Extract Class | Split Phase |\n| 散弹式修改 | Move Method | Inline Class |\n| 死代码 | Remove Dead Code | - |\n| 臆想泛化 | Collapse Hierarchy | Inline Class |\n\n---\n\n## 延伸阅读\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (第 2 版)\n- 在线目录：https://refactoring.com/catalog/\n","zh/07-plugins/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=zh%2F07-plugins%2FREADME.md -->","zh/07-plugins/devops-automation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=zh%2F07-plugins%2Fdevops-automation%2FREADME.md -->","zh/07-plugins/documentation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=zh%2F07-plugins%2Fdocumentation%2FREADME.md -->","zh/07-plugins/documentation/commands/generate-readme.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=zh%2F07-plugins%2Fdocumentation%2Fcommands%2Fgenerate-readme.md -->","zh/07-plugins/pr-review/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=zh%2F07-plugins%2Fpr-review%2FREADME.md -->"},"files":{".claude/skills/lesson-quiz/README.md":"# Lesson Quiz\n\n> Interactive quiz that tests your understanding of a specific Claude Code lesson with 10 questions, per-question feedback, and targeted review guidance.\n\n## Highlights\n\n- 10 questions per lesson mixing conceptual understanding and practical application\n- Covers all 10 lessons (01-Slash Commands through 10-CLI)\n- Three timing modes: pre-test, progress check, or mastery verification\n- Per-question feedback with correct answers and explanations\n- Targeted review recommendations pointing to specific lesson sections\n- 100-question bank across all lessons in `references/question-bank.md`\n\n## When to Use\n\n| Say this... | Skill will... |\n|---|---|\n| \"quiz me on hooks\" | Run a 10-question quiz on Lesson 06: Hooks |\n| \"lesson quiz 03\" | Test your knowledge of Lesson 03: Skills |\n| \"do I understand MCP\" | Assess your understanding of Lesson 05: MCP |\n| \"practice quiz\" | Let you pick a lesson, then quiz you |\n\n## How It Works\n\n```mermaid\ngraph TD\n    A[\"Select lesson\"] --> B[\"Choose timing: pre/during/after\"]\n    B --> C[\"Answer 10 questions in 5 rounds\"]\n    C --> D[\"Score and review feedback\"]\n    style A fill:#4CAF50,color:#fff\n    style D fill:#2196F3,color:#fff\n```\n\n## Usage\n\n```\n/lesson-quiz [lesson-name-or-number]\n```\n\nExamples:\n```\n/lesson-quiz hooks\n/lesson-quiz 03\n/lesson-quiz advanced-features\n/lesson-quiz           # (prompts for lesson selection)\n```\n\n## Output\n\n### Score Report\n- Total score out of 10 with grade (Mastered / Proficient / Developing / Beginning)\n- Breakdown by question category (conceptual vs. practical)\n\n### Per-Question Feedback\nFor each incorrect answer:\n- What you answered vs. the correct answer\n- Explanation of why the correct answer is right\n- Specific section of the lesson to review\n\n### Timing-Aware Guidance\n- **Pre-test**: Establishes baseline, highlights areas to focus on while studying\n- **During**: Identifies what you've grasped and what to revisit\n- **After**: Confirms mastery or pinpoints remaining gaps\n\n## Resources\n\n| Path | Description |\n|---|---|\n| `references/question-bank.md` | 100 pre-written questions (10 per lesson) with answers, explanations, and review pointers |\n",".claude/skills/lesson-quiz/SKILL.md":"---\nname: lesson-quiz\ndescription: \"Test a learner on a single Claude Code tutorial lesson (01-10) with 10 questions, scoring answers and flagging weak spots. Use before, during, or after a lesson. Don't use for whole-tutorial assessment or explaining a topic instead of testing it.\"\neffort: high\nmetadata:\n  version: 1.6.2\n  author: Luong NGUYEN\n---\n\n# Lesson Quiz\n\nInteractive quiz that tests understanding of a specific Claude Code lesson with 10 questions, provides per-question feedback, and identifies areas to review.\n\n## Prerequisites\n\nThis skill requires:\n\n- The tutorial repo checked out, so the lesson directories `01-slash-commands/` … `10-cli/` and each `README.md` are readable.\n- `references/question-bank.md` present in this skill (the source of all questions).\n\nBefore starting, confirm the target lesson's `README.md` exists. If it is missing, do not fabricate questions — warn the user and ask them to check the repository structure (see Error Handling).\n\n**Guardrails:**\n\n- **Never invent questions or answers.** Ask only questions drawn from `references/question-bank.md` for the selected lesson; if the bank lacks entries for a lesson, say so rather than making them up.\n- **Score accurately.** Track which shuffled position holds the correct answer for every question and validate each response against it — never guess a score.\n- **Confirm timing before scoring.** The pre/during/after choice changes how results are framed; do not skip it.\n\n## Instructions\n\n### Step 1: Determine the Lesson\n\nIf the user provided a lesson as an argument (e.g., `/lesson-quiz hooks` or `/lesson-quiz 03`), map it to the lesson directory:\n\n**Lesson mapping:**\n- `01`, `slash-commands`, `commands` → 01-slash-commands\n- `02`, `memory` → 02-memory\n- `03`, `skills` → 03-skills\n- `04`, `subagents`, `agents` → 04-subagents\n- `05`, `mcp` → 05-mcp\n- `06`, `hooks` → 06-hooks\n- `07`, `plugins` → 07-plugins\n- `08`, `checkpoints`, `checkpoint` → 08-checkpoints\n- `09`, `advanced`, `advanced-features` → 09-advanced-features\n- `10`, `cli` → 10-cli\n\nIf no argument was provided, present a selection prompt using AskUserQuestion:\n\n**Question 1** (header: \"Lesson\"):\n\"Which lesson do you want to quiz on?\"\nOptions:\n1. \"Slash Commands (01)\" — Custom commands, skills, frontmatter, arguments\n2. \"Memory (02)\" — CLAUDE.md, memory hierarchy, rules, auto memory\n3. \"Skills (03)\" — Progressive disclosure, auto-invocation, SKILL.md\n4. \"Subagents (04)\" — Task delegation, agent config, isolation\n\n**Question 2** (header: \"Lesson\"):\n\"Which lesson do you want to quiz on? (continued)\"\nOptions:\n1. \"MCP (05)\" — External integration, transport, servers, tool search\n2. \"Hooks (06)\" — Event automation, PreToolUse, exit codes, JSON I/O\n3. \"Plugins (07)\" — Bundled solutions, marketplace, plugin.json\n4. \"More lessons...\" — Checkpoints, Advanced Features, CLI\n\nIf \"More lessons...\" is selected, present:\n\n**Question 3** (header: \"Lesson\"):\n\"Select your lesson:\"\nOptions:\n1. \"Checkpoints (08)\" — Rewind, restore, safe experimentation\n2. \"Advanced Features (09)\" — Planning, permissions, print mode, thinking\n3. \"CLI Reference (10)\" — Flags, output formats, scripting, piping\n\n### Step 2: Read the Lesson Content\n\nRead the lesson README.md file to refresh context:\n- Read file: `<lesson-directory>/README.md`\n\nThen use the question bank from `references/question-bank.md` for that lesson (10 pre-written questions with answers and explanations). To stay within the context budget, read only the one selected lesson's README — not all ten.\n\n### Step 3: Present the Quiz\n\nAsk the user about quiz timing context:\n\nUse AskUserQuestion (header: \"Timing\"):\n\"When are you taking this quiz relative to the lesson?\"\nOptions:\n1. \"Before (pre-test)\" — I haven't read the lesson yet, testing my prior knowledge\n2. \"During (progress check)\" — I'm partway through the lesson\n3. \"After (mastery check)\" — I've completed the lesson and want to verify understanding\n\nThis context affects how the results are framed (see Step 5).\n\n### Step 4: Present Questions in Rounds\n\nPresent 10 questions from the question bank in rounds of 2 questions each (5 rounds total). Each question uses AskUserQuestion with the question text and 3-4 answer options.\n\n**IMPORTANT**: Use AskUserQuestion with max 4 options per question, 2 questions per round.\n\nFor each round, present 2 questions. After the user answers each round, immediately show per-question feedback: whether each answer was correct or incorrect, and if incorrect, show the correct answer and a brief explanation. Then proceed to the next round. After all 5 rounds, proceed to final scoring.\n\n**Question format per round:**\n\nEach question from the question bank has:\n- `question`: The question text\n- `options`: 3-4 answer choices (one correct, labeled in the bank)\n- `correct`: The correct answer label\n- `explanation`: Why the answer is correct\n- `category`: \"conceptual\" or \"practical\"\n\n**CRITICAL — Shuffle answer options**: For each question, you MUST randomize the order of the answer options before presenting them via AskUserQuestion. Do NOT present them in the order they appear in the question bank (A, B, C, D), and do NOT place the correct answer first. Use a different random permutation for each question. Track which shuffled position contains the correct answer so you can score accurately.\n\nExample: If the question bank lists options A (correct), B, C, D — you might present them as: C, A, D, B. The correct answer is now in position 2.\n\nPresent each question using AskUserQuestion. Record the user's answer for each.\n\n### Step 5: Score and Present Results\n\nAfter all rounds, calculate the score and present results.\n\n**Scoring:**\n- Each correct answer = 1 point\n- Total possible = 10 points\n\n**Grade scale:**\n- 9-10: Mastered — Excellent understanding\n- 7-8: Proficient — Good grasp, minor gaps\n- 5-6: Developing — Fundamentals understood, needs review\n- 3-4: Beginning — Significant gaps, review recommended\n- 0-2: Not yet — Start from the beginning of this lesson\n\n**Output format:** Follow the report template in `references/results-template.md`. It defines the score line, the per-question results table, the \"Incorrect Answers — Review These\" block, the timing-specific message (pre-test / during / after), and the \"Recommended Next Steps\" section. Fill its bracketed placeholders with this run's data.\n\n### Step 6: Offer Follow-up\n\nAfter presenting results, use AskUserQuestion:\n\n\"What would you like to do next?\"\nOptions:\n1. \"Retake this quiz\" — Try the same lesson quiz again\n2. \"Quiz another lesson\" — Switch to a different lesson\n3. \"Explain a topic I missed\" — Get a detailed explanation of an incorrect answer\n4. \"Done\" — End the quiz session\n\nIf **Retake**: Go back to Step 4 (skip timing question, use same timing).\nIf **Quiz another lesson**: Go back to Step 1.\nIf **Explain a topic**: Ask which question number, then read the relevant section from the lesson README.md and explain it with examples.\n\n## Acceptance Criteria\n\nA completed quiz run must satisfy all of these — verify each before presenting final results:\n\n- Exactly one lesson (01-10) was resolved before any question was asked.\n- The timing context (before / during / after) was captured via AskUserQuestion.\n- 10 questions from `references/question-bank.md` for that lesson were presented, in 5 rounds of 2, with answer options shuffled per question.\n- Every answer was scored against the tracked correct-position, producing an integer score in the range 0-10.\n- **Expected output**: a `## Lesson Quiz Results` report containing the score line (`Score: N/10` with a grade label), the per-question results table, an \"Incorrect Answers — Review These\" block for each miss, and a timing-specific message.\n- The follow-up prompt (retake / another lesson / explain / done) was offered.\n\nExample: for a 7/10 \"after\" run on Hooks, the report asserts `Score: 7/10 — Proficient`, lists all 10 rows in the results table, and expands the 3 incorrect questions with correct answer, explanation, and a review pointer.\n\n## Edge Cases & Error Handling\n\n### Invalid lesson argument\nIf the argument doesn't match any lesson, show the valid lesson list and ask the user to pick one.\n\n### User wants to quit mid-quiz\nIf the user indicates they want to stop during any round, present partial results for the questions answered so far (score out of the number attempted, not out of 10).\n\n### Lesson README not found\nIf the README.md file doesn't exist at the expected path, inform the user and suggest checking the repository structure. Do not proceed with fabricated content.\n\n### Question bank missing entries for a lesson\nIf `references/question-bank.md` has no questions for the resolved lesson, tell the user and stop — never invent questions to fill the gap.\n\n## Validation\n\n### Triggering test suite\n\n**Should trigger:**\n- \"quiz me on hooks\"\n- \"lesson quiz\"\n- \"test my knowledge of lesson 3\"\n- \"practice quiz for MCP\"\n- \"do I understand skills\"\n- \"quiz me on slash commands\"\n- \"lesson-quiz 06\"\n- \"test me on checkpoints\"\n- \"how well do I know the CLI\"\n- \"quiz me before I start the memory lesson\"\n\n**Should NOT trigger:**\n- \"assess my overall level\" (use /self-assessment)\n- \"explain hooks to me\"\n- \"create a hook\"\n- \"what is MCP\"\n- \"review my code\"\n",".claude/skills/lesson-quiz/references/question-bank.md":"# Lesson Quiz — Question Bank\n\n10 questions per lesson. Each question has: category, question text, options (3-4), correct answer, explanation, and review section.\n\n---\n\n## Lesson 01: Slash Commands\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the four types of slash commands in Claude Code?\n- **Options**: A) Built-in, skills, plugin commands, MCP prompts | B) Built-in, custom, hook commands, API prompts | C) System, user, plugin, terminal commands | D) Core, extension, macro, script commands\n- **Correct**: A\n- **Explanation**: Claude Code has built-in commands (like /help, /compact), skills (SKILL.md files), plugin commands (namespaced plugin-name:command), and MCP prompts (/mcp__server__prompt).\n- **Review**: Overview section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you pass all user-provided arguments to a skill?\n- **Options**: A) Use `${args}` | B) Use `$ARGUMENTS` | C) Use `$@` | D) Use `$INPUT`\n- **Correct**: B\n- **Explanation**: `$ARGUMENTS` captures all text after the command name. For positional args, use `$0`, `$1`, etc.\n- **Review**: Arguments\n\n### Q3\n- **Category**: conceptual\n- **Question**: When both a skill (.claude/skills/name/SKILL.md) and a legacy command (.claude/commands/name.md) exist with the same name, which takes priority?\n- **Options**: A) The legacy command | B) The skill | C) Whichever was created first | D) Claude asks the user to choose\n- **Correct**: B\n- **Explanation**: Skills take precedence over legacy commands with the same name. The skill system supersedes the older command system.\n- **Review**: Skill vs Command Conflict section\n\n### Q4\n- **Category**: practical\n- **Question**: How do you inject live shell output into a skill's prompt?\n- **Options**: A) Use `$(command)` syntax | B) Use `!`command`` (backtick with !) syntax | C) Use `@shell:command` syntax | D) Use `{command}` syntax\n- **Correct**: B\n- **Explanation**: The `!`command`` syntax runs a shell command and injects its output into the skill prompt before Claude sees it.\n- **Review**: Dynamic Context with Shell Commands\n\n### Q5\n- **Category**: conceptual\n- **Question**: What does `disable-model-invocation: true` do in a skill's frontmatter?\n- **Options**: A) Prevents the skill from running entirely | B) Allows only the user to invoke it (Claude cannot auto-invoke) | C) Hides it from the /help menu | D) Disables the skill's AI processing\n- **Correct**: B\n- **Explanation**: `disable-model-invocation: true` means only the user can trigger the command via `/command-name`. Claude will never auto-invoke it, useful for skills with side effects like deployments.\n- **Review**: Frontmatter Reference section\n\n### Q6\n- **Category**: practical\n- **Question**: You want to create a skill that only Claude can invoke automatically (hidden from the user's / menu). Which frontmatter field do you set?\n- **Options**: A) `disable-model-invocation: true` | B) `user-invocable: false` | C) `hidden: true` | D) `auto-only: true`\n- **Correct**: B\n- **Explanation**: `user-invocable: false` hides the skill from the user's slash menu but allows Claude to invoke it automatically based on context.\n- **Review**: Frontmatter Reference section\n\n### Q7\n- **Category**: practical\n- **Question**: What is the correct directory structure for a new custom skill called \"deploy\"?\n- **Options**: A) `.claude/commands/deploy.md` | B) `.claude/skills/deploy/SKILL.md` | C) `.claude/skills/deploy.md` | D) `.claude/deploy/SKILL.md`\n- **Correct**: B\n- **Explanation**: Skills live in a directory under `.claude/skills/` with a `SKILL.md` file inside. The directory name matches the command name.\n- **Review**: Creating a Custom Command as a Skill section\n\n### Q8\n- **Category**: conceptual\n- **Question**: How do plugin commands avoid name conflicts with user commands?\n- **Options**: A) They use a `plugin-name:command-name` namespace | B) They have a special .plugin extension | C) They are prefixed with `p/` | D) They override user commands automatically\n- **Correct**: A\n- **Explanation**: Plugin commands use a namespace like `pr-review:check-security` to avoid conflicts with standalone user commands.\n- **Review**: Plugin commands section\n\n### Q9\n- **Category**: practical\n- **Question**: You want a skill to use certain tools without asking for permission each time. Which frontmatter field do you add?\n- **Options**: A) `tools: [Read, Grep]` | B) `allowed-tools: [Read, Grep]` | C) `permissions: [Read, Grep]` | D) `restrict-tools: [Read, Grep]`\n- **Correct**: B\n- **Explanation**: `allowed-tools` pre-approves the listed tools during the turn that invokes the skill, so Claude can use them without a permission prompt; the grant clears when you send your next message. It does not restrict which tools are available — to remove tools while a skill is active, use `disallowed-tools`.\n- **Review**: Frontmatter Reference\n\n### Q10\n- **Category**: conceptual\n- **Question**: What is the `@file` syntax used for in a skill?\n- **Options**: A) Importing another skill | B) Referencing a file to include its content in the prompt | C) Creating a symlink | D) Setting file permissions\n- **Correct**: B\n- **Explanation**: The `@path/to/file` syntax in a skill includes the referenced file's content into the prompt, allowing skills to pull in templates or context files.\n- **Review**: File references section\n\n---\n\n## Lesson 02: Memory\n\n### Q1\n- **Category**: conceptual\n- **Question**: How do CLAUDE.md memory files relate to each other, and what has the highest authority?\n- **Options**: A) Higher tiers override lower tiers entirely | B) They are concatenated into context; Managed Policy loads first and cannot be excluded | C) The most recently modified file wins | D) Project Memory has the highest priority\n- **Correct**: B\n- **Explanation**: CLAUDE.md files are concatenated into context rather than overriding each other — load order sets position in context, not precedence. Managed Policy (admin-managed) loads first and cannot be excluded by individual settings. Auto memory is a separate mechanism.\n- **Review**: Memory hierarchy section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you quickly add a new rule to memory during a conversation?\n- **Options**: A) Use the `/memory` slash command or ask conversationally | B) Prefix your message with `#` (e.g., `# always use TypeScript`) | C) Type `/rule \"rule text\"` | D) Use `@add-memory \"rule text\"`\n- **Correct**: A\n- **Explanation**: Use `/memory` to open your CLAUDE.md and auto memory files in your editor, or ask Claude conversationally. Asking Claude to \"remember\" something (e.g., \"remember that we always use TypeScript strict mode\") saves it to auto memory; to put it in CLAUDE.md instead, say \"add this to CLAUDE.md\". The `#` prefix was discontinued and no longer works.\n- **Review**: Quick memory updates section in README\n\n### Q3\n- **Category**: conceptual\n- **Question**: What is the maximum depth for `@path/to/file` imports in CLAUDE.md?\n- **Options**: A) 3 levels deep | B) 4 levels deep | C) 10 levels deep | D) Unlimited\n- **Correct**: B\n- **Explanation**: The `@path` import syntax supports recursive imports up to a maximum depth of 4 hops to prevent infinite loops.\n- **Review**: The /memory Command section (Import features)\n\n### Q4\n- **Category**: practical\n- **Question**: How do you scope a rule file to only apply to files in `src/api/`?\n- **Options**: A) Put the rule in `src/api/CLAUDE.md` | B) Add `paths: src/api/**` YAML frontmatter to a `.claude/rules/*.md` file | C) Name the file `.claude/rules/api.md` | D) Use `@scope: src/api` in the rule file\n- **Correct**: B\n- **Explanation**: Files in `.claude/rules/` support a `paths:` frontmatter field with glob patterns to scope rules to specific directories.\n- **Review**: Path-specific rules section\n\n### Q5\n- **Category**: conceptual\n- **Question**: How many lines of Auto Memory's MEMORY.md are loaded at session start?\n- **Options**: A) All lines | B) First 100 lines | C) First 200 lines | D) First 500 lines\n- **Correct**: C\n- **Explanation**: The first 200 lines of MEMORY.md — or the first 25 KB, whichever comes first — are auto-loaded into context at session start. Topic files referenced from MEMORY.md are loaded on demand.\n- **Review**: Auto Memory section\n\n### Q6\n- **Category**: practical\n- **Question**: You want personal project preferences that are NOT committed to git. Which file should you use?\n- **Options**: A) `~/.claude/CLAUDE.md` | B) `CLAUDE.local.md` | C) `.claude/rules/personal.md` | D) `.claude/memory/personal.md`\n- **Correct**: B\n- **Explanation**: `CLAUDE.local.md` in the project root is for personal project-specific preferences. It should be git-ignored.\n- **Review**: Memory Locations Table\n\n### Q7\n- **Category**: conceptual\n- **Question**: What does the `/init` command do?\n- **Options**: A) Initializes a new Claude Code project from scratch | B) Generates a template CLAUDE.md based on your project structure | C) Resets all memory to defaults | D) Creates a new session\n- **Correct**: B\n- **Explanation**: `/init` analyzes your project and generates a template CLAUDE.md with suggested rules and standards. Re-running it on an existing CLAUDE.md suggests improvements.\n- **Review**: /init command section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you disable Auto Memory completely?\n- **Options**: A) Delete the ~/.claude/projects directory | B) Set `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1` | C) Add `auto-memory: false` to CLAUDE.md | D) Use `/memory disable auto`\n- **Correct**: B\n- **Explanation**: Setting `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1` disables auto memory. Value `0` forces it on. Unset = default on.\n- **Review**: Turning Auto Memory On or Off\n\n### Q9\n- **Category**: conceptual\n- **Question**: Can a lower-priority memory tier override rules from a higher-priority tier?\n- **Options**: A) Yes, the most recent rule always wins | B) No — CLAUDE.md files are concatenated into context, not overridden; load order sets position, not precedence | C) Yes, if the lower tier uses the `!important` flag | D) It depends on the rule type\n- **Correct**: B\n- **Explanation**: CLAUDE.md files (user, project, local, rules) are concatenated into context rather than overriding each other — later files appear later in context, not \"instead of\" earlier ones. Only Managed Policy is special: it loads first and cannot be excluded by individual settings. Auto memory is a separate mechanism, not part of the concatenation order.\n- **Review**: Memory hierarchy section\n\n### Q10\n- **Category**: practical\n- **Question**: You work across two repositories and want Claude to load CLAUDE.md from both. What flag do you use?\n- **Options**: A) `claude --multi-repo /path/to/other` | B) `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 claude --add-dir /path/to/other` | C) `claude --add-dir /path/to/other` on its own | D) `claude --include /path/to/other`\n- **Correct**: B\n- **Explanation**: `--add-dir` on its own only grants file access to the extra directory — its CLAUDE.md is not loaded by default. Setting `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1` makes Claude Code also load CLAUDE.md from directories added with `--add-dir`.\n- **Review**: Additional directories section\n\n---\n\n## Lesson 03: Skills\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the 3 levels of progressive disclosure in the skill system?\n- **Options**: A) Metadata, instructions, resources | B) Name, body, attachments | C) Header, content, scripts | D) Summary, details, data\n- **Correct**: A\n- **Explanation**: Level 1: Metadata (~100 tokens, always loaded), Level 2: SKILL.md body (<5k tokens, loaded on trigger), Level 3: Bundled resources (scripts/references/assets, loaded on demand).\n- **Review**: How Skills Work: Progressive Disclosure\n\n### Q2\n- **Category**: practical\n- **Question**: What is the most important factor for a skill to be auto-invoked by Claude?\n- **Options**: A) The skill's file name | B) The `description` field in frontmatter with when-to-use keywords | C) The skill's directory location | D) The `auto-invoke: true` frontmatter field\n- **Correct**: B\n- **Explanation**: Claude decides whether to auto-invoke a skill based on its `description` (plus optional `when_to_use`). It must include specific trigger phrases and scenarios.\n- **Review**: Controlling Skill Invocation section\n\n### Q3\n- **Category**: conceptual\n- **Question**: What is the maximum recommended length for a SKILL.md file?\n- **Options**: A) 100 lines | B) 250 lines | C) 500 lines | D) 1000 lines\n- **Correct**: C\n- **Explanation**: SKILL.md should be kept under 500 lines. Larger reference material belongs in `references/` subdirectory files.\n- **Review**: Keep SKILL.md Under 500 Lines section\n\n### Q4\n- **Category**: practical\n- **Question**: How do you make a skill run in an isolated subagent with its own context?\n- **Options**: A) Set `isolation: true` in frontmatter | B) Set `context: fork` with an `agent` field in frontmatter | C) Set `subagent: true` in frontmatter | D) Put the skill in `.claude/agents/`\n- **Correct**: B\n- **Explanation**: `context: fork` runs the skill in a separate context, and the `agent` field specifies which agent type (e.g., `Explore`, `Plan`, custom agent) to use.\n- **Review**: Running skills in subagents section\n\n### Q5\n- **Category**: conceptual\n- **Question**: What is the approximate context budget allocated to skill metadata (Level 1)?\n- **Options**: A) 0.5% of context window | B) 1% of context window | C) 5% of context window | D) 10% of context window\n- **Correct**: B\n- **Explanation**: Skill metadata occupies about 1% of the context window (fallback: 8,000 characters). This is configurable with `SLASH_COMMAND_TOOL_CHAR_BUDGET` or the `skillListingBudgetFraction` setting.\n- **Review**: the \"Description budget\" paragraph under Automatic Discovery\n\n### Q6\n- **Category**: practical\n- **Question**: A skill needs to reference a large API specification. Where should you put it?\n- **Options**: A) Inline in SKILL.md | B) In a `references/api-spec.md` file inside the skill directory | C) In the project's CLAUDE.md | D) In a separate `.claude/rules/` file\n- **Correct**: B\n- **Explanation**: Large reference material belongs in the `references/` subdirectory. Claude loads Level 3 resources on demand, keeping SKILL.md lean.\n- **Review**: Supporting files structure section\n\n### Q7\n- **Category**: conceptual\n- **Question**: What is the difference between Reference Content and Task Content in a skill?\n- **Options**: A) Reference is read-only, Task is read-write | B) Reference adds knowledge to context, Task provides step-by-step instructions | C) Reference is for documentation, Task is for code | D) There is no difference\n- **Correct**: B\n- **Explanation**: Reference Content adds domain knowledge to Claude's context (e.g., brand guidelines). Task Content provides actionable step-by-step instructions for a workflow.\n- **Review**: Skill content types section\n\n### Q8\n- **Category**: practical\n- **Question**: What characters are allowed in the `name` field of a skill's frontmatter for a skill you plan to share via claude.ai or the Skills API (Agent Skills spec)?\n- **Options**: A) Any characters | B) Lowercase letters, numbers, and hyphens only (max 64 chars) | C) Letters and underscores | D) Alphanumeric only\n- **Correct**: B\n- **Explanation**: The name must be kebab-case (lowercase, hyphens), max 64 characters. `name` is itself optional — if omitted it defaults to the skill's directory name — but when supplied it must follow these rules. In Claude Code, the `anthropic-skills` name and namespace are reserved for skills synced from claude.ai, so a skill with that name doesn't load; the broader ban on \"anthropic\" or \"claude\" applies to claude.ai skill uploads and the Skills API. Claude Code itself (v2.1.299) refuses only names that contain hidden, direction-changing or blank-like characters, `<` or `>`, or that are over 256 characters.\n- **Review**: SKILL.md format section\n\n### Q9\n- **Category**: conceptual\n- **Question**: In what order does Claude search for skills?\n- **Options**: A) User > Project > Enterprise | B) Enterprise > Personal > Project (plugin uses namespace) | C) Project > User > Enterprise | D) Alphabetical order\n- **Correct**: B\n- **Explanation**: Priority order is: Enterprise > Personal > Project. Plugin skills use a namespace (plugin-name:skill) so they don't conflict.\n- **Review**: Skill Types & Locations\n\n### Q10\n- **Category**: practical\n- **Question**: How do you prevent Claude from automatically invoking a skill while still allowing users to use it manually?\n- **Options**: A) Set `user-invocable: false` | B) Set `disable-model-invocation: true` | C) Remove the description field | D) Set `auto-invoke: false`\n- **Correct**: B\n- **Explanation**: `disable-model-invocation: true` prevents Claude from auto-invoking but keeps the skill available in the user's `/` menu for manual use.\n- **Review**: Controlling Skill Invocation\n\n---\n\n## Lesson 04: Subagents\n\n### Q1\n- **Category**: conceptual\n- **Question**: What is the main advantage of subagents over inline conversation?\n- **Options**: A) They are faster | B) They operate in a separate, clean context window preventing context pollution | C) They can use more tools | D) They have better error handling\n- **Correct**: B\n- **Explanation**: Subagents get a fresh context window, receiving only what the main agent passes. This prevents the main conversation from being polluted with task-specific details.\n- **Review**: Overview section\n\n### Q2\n- **Category**: practical\n- **Question**: What is the priority order for agent definitions?\n- **Options**: A) Project > User > CLI | B) CLI > Project > User | C) User > Project > CLI | D) They all have equal priority\n- **Correct**: B\n- **Explanation**: Full order is managed settings > `--agents` flag > project (`.claude/agents/`) > user (`~/.claude/agents/`) > plugin. Of the options listed, CLI > Project > User is the correct relative ordering.\n- **Review**: File locations section\n\n### Q3\n- **Category**: conceptual\n- **Question**: Which built-in subagent is optimized for read-only codebase exploration?\n- **Options**: A) general-purpose | B) Plan | C) Explore | D) Bash\n- **Correct**: C\n- **Explanation**: The Explore subagent is the read-only codebase search agent. Since v2.1.198 it inherits the session model, capped at Opus on the Claude API — `model: haiku` is opt-in, not the default. It supports three thoroughness levels: quick, medium, very thorough.\n- **Review**: Built-in subagents section\n\n### Q4\n- **Category**: practical\n- **Question**: How do you restrict which subagents a coordinator agent can spawn?\n- **Options**: A) Use `allowed-agents:` field | B) Use `Agent(agent_name)` syntax in the `tools` field | C) Set `spawn-limit: 2` | D) Use `restrict-agents: [name1, name2]`\n- **Correct**: B\n- **Explanation**: For an agent running as the main thread with `claude --agent`, `tools: Agent(worker, researcher)` creates an allowlist — it can only spawn subagents named \"worker\" or \"researcher\". `Task(...)` still works as an alias (the Task tool was renamed Agent in v2.1.63).\n- **Review**: Restrict spawnable subagents section\n\n### Q5\n- **Category**: conceptual\n- **Question**: What does `isolation: worktree` do for a subagent?\n- **Options**: A) Runs the agent in a Docker container | B) Gives the agent its own git worktree so changes don't affect the main tree | C) Prevents the agent from reading any files | D) Runs the agent in a sandbox\n- **Correct**: B\n- **Explanation**: Worktree isolation creates a separate git worktree. If the agent makes no changes, it auto-cleans up. If changes are made, the worktree path and branch are returned.\n- **Review**: Worktree isolation section\n\n### Q6\n- **Category**: practical\n- **Question**: How do you force a subagent to always run in the background (never inline)?\n- **Options**: A) Set `background: true` in the agent config | B) Use `async: true` in the agent config | C) Press Ctrl+D after starting it | D) Use `--background` CLI flag\n- **Correct**: A\n- **Explanation**: `background: true` in the agent configuration makes the subagent always run as a background task and prevents it from running inline. Subagents Claude spawns from the main conversation already run in the background by default (v2.1.198; always, in the desktop app and VS Code, since v2.1.302), but a subagent's own nested Agent calls run in the foreground by default in `claude -p`, the Agent SDK, the desktop app and VS Code. Users can also press Ctrl+B to send a running foreground task to the background.\n- **Review**: Background subagents section\n\n### Q7\n- **Category**: conceptual\n- **Question**: What does the `memory` field with scope `project` do for a subagent?\n- **Options**: A) Gives read access to the project CLAUDE.md | B) Creates a persistent memory directory scoped to the current project | C) Shares the main agent's conversation history | D) Loads the project's git history\n- **Correct**: B\n- **Explanation**: The `memory` field creates a persistent directory for the subagent. Scope `project` means the memory is tied to the current project. The first 200 lines or 25KB of the agent's MEMORY.md, whichever comes first, auto-load.\n- **Review**: Persistent memory section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you include a phrase in a subagent's description to encourage Claude to automatically delegate tasks to it?\n- **Options**: A) Add \"priority: high\" | B) Include \"use PROACTIVELY\" or \"MUST BE USED\" in the description | C) Set `auto-delegate: true` | D) Add \"trigger: always\"\n- **Correct**: B\n- **Explanation**: Including phrases like \"use PROACTIVELY\" or \"MUST BE USED\" in the description strongly encourages Claude to automatically delegate matching tasks.\n- **Review**: Automatic delegation section\n\n### Q9\n- **Category**: conceptual\n- **Question**: What are the valid `permissionMode` values for a subagent?\n- **Options**: A) read, write, admin | B) manual, acceptEdits, bypassPermissions, plan, dontAsk, auto | C) safe, normal, dangerous | D) restricted, standard, elevated\n- **Correct**: B\n- **Explanation**: Subagents support six permission modes: manual (runs reads without asking and prompts for everything else — shown as Manual; its config value is `default`, and manual is accepted as an alias since v2.1.200), acceptEdits (auto-accepts file edits), bypassPermissions (skips all), plan (read-only), dontAsk (auto-denies unless pre-approved), auto (background classifier decides).\n- **Review**: Configuration fields section\n\n### Q10\n- **Category**: practical\n- **Question**: How do you resume a subagent that returned an agentId from a previous run?\n- **Options**: A) Use `/resume agent-id` | B) Ask Claude to resume it — Claude messages the subagent with the SendMessage tool, using its agent ID or name | C) Use `claude -r agent-id` | D) Subagents cannot be resumed\n- **Correct**: B\n- **Explanation**: Each invocation starts a new instance. To continue earlier work, ask Claude to resume the subagent: Claude uses the SendMessage tool with the agent's ID or name, and the subagent resumes with its full conversation history. The built-in Explore and Plan agents are one-shot and can't be resumed.\n- **Review**: Resumable agents section\n\n---\n\n## Lesson 05: MCP\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the four MCP transport protocols, and which is recommended?\n- **Options**: A) HTTP (recommended), Stdio, SSE (deprecated), WebSocket (`ws`) | B) REST (recommended), GraphQL, gRPC, Thrift | C) TCP, UDP, HTTP | D) Stdio (recommended), HTTP, SSE\n- **Correct**: A\n- **Explanation**: HTTP is recommended for remote servers. Stdio is for local processes (most common currently). SSE is deprecated but still supported. WebSocket (`type: \"ws\"`) holds a persistent bidirectional connection for servers that push events unprompted; it is added with `claude mcp add-json` or `.mcp.json`, not with `--transport`, and supports header-only auth.\n- **Review**: MCP Installation Methods section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you add a GitHub MCP server via CLI?\n- **Options**: A) `claude mcp install github` | B) `claude mcp add --transport http github https://api.githubcopilot.com/mcp/` | C) `claude plugin add github-mcp` | D) `claude connect github`\n- **Correct**: B\n- **Explanation**: Use `claude mcp add` with the `--transport` flag, a name, and the server URL. GitHub's remote server also needs an auth header: `claude mcp add --transport http github https://api.githubcopilot.com/mcp/ --header \"Authorization: Bearer YOUR_GITHUB_PAT\"`.\n- **Review**: MCP configuration management section\n\n### Q3\n- **Category**: conceptual\n- **Question**: With `ENABLE_TOOL_SEARCH=auto`, what happens when MCP tool definitions reach 10% of the context window?\n- **Options**: A) They are truncated | B) Tool search kicks in: MCP tools are deferred and discovered on demand | C) Claude shows an error | D) Extra tools are disabled\n- **Correct**: B\n- **Explanation**: By default (`ENABLE_TOOL_SEARCH` unset) tool search is already on and all MCP tools are deferred. `auto` is threshold mode: tools load upfront until their definitions reach 10% of the context window, then all are deferred (`auto:N` sets a custom percentage). Tool search needs a model that supports `tool_reference` blocks: Opus 4, Sonnet 4, Haiku 4.5 and later.\n- **Review**: MCP Tool Search section\n\n### Q4\n- **Category**: practical\n- **Question**: How do you use environment variable fallbacks in MCP config?\n- **Options**: A) `${VAR || \"default\"}` | B) `${VAR:-default}` | C) `${VAR:default}` | D) `${VAR ? \"default\"}`\n- **Correct**: B\n- **Explanation**: `${VAR:-default}` provides a fallback value if the environment variable is not set. If `VAR` is unset and has no default, the server still loads with the literal `${VAR}` text, and `claude mcp list` and `/mcp` warn about the missing variable.\n- **Review**: Environment variable expansion section\n\n### Q5\n- **Category**: conceptual\n- **Question**: What is the difference between MCP and Memory for data access?\n- **Options**: A) MCP is faster, Memory is slower | B) MCP is for live/changing external data, Memory is for persistent/static preferences | C) MCP is for code, Memory is for text | D) They are interchangeable\n- **Correct**: B\n- **Explanation**: MCP connects to live, changing external data sources (APIs, databases). Memory stores persistent, static project context and preferences.\n- **Review**: MCP vs Memory section\n\n### Q6\n- **Category**: practical\n- **Question**: What happens when a team member first encounters a project-scoped `.mcp.json`?\n- **Options**: A) It loads automatically | B) They get an approval prompt to trust the project's MCP servers | C) It's ignored unless they opt in via settings | D) Claude asks the admin to approve\n- **Correct**: B\n- **Explanation**: Project-scoped `.mcp.json` triggers a security approval prompt on each team member's first use. This is intentional — it prevents untrusted MCP servers.\n- **Review**: MCP Scopes section\n\n### Q7\n- **Category**: conceptual\n- **Question**: What does `claude mcp serve` do?\n- **Options**: A) Starts an MCP server dashboard | B) Makes Claude Code itself act as an MCP server for other applications | C) Serves MCP documentation | D) Tests MCP server connections\n- **Correct**: B\n- **Explanation**: `claude mcp serve` turns Claude Code into an MCP server, enabling multi-agent orchestration where one Claude instance can be controlled by another.\n- **Review**: Claude as MCP Server section\n\n### Q8\n- **Category**: practical\n- **Question**: What is the default maximum output size for MCP tools?\n- **Options**: A) 5,000 tokens | B) 10,000 tokens | C) 25,000 tokens | D) 50,000 tokens\n- **Correct**: C\n- **Explanation**: Default max is 25,000 tokens (`MAX_MCP_OUTPUT_TOKENS`). A warning appears at 10k tokens. Text results over 50,000 characters are saved to a file.\n- **Review**: MCP Output Limits section\n\n### Q9\n- **Category**: conceptual\n- **Question**: When both `allowedMcpServers` and `deniedMcpServers` match a server in managed config, which wins?\n- **Options**: A) Allowed wins | B) Denied wins | C) The last one configured wins | D) Both are applied independently\n- **Correct**: B\n- **Explanation**: In managed MCP configuration, deny rules always take precedence over allow rules.\n- **Review**: Managed MCP Configuration section\n\n### Q10\n- **Category**: practical\n- **Question**: How do you reference an MCP resource in a conversation?\n- **Options**: A) Use `/mcp resource-name` | B) Use `@server-name:protocol://resource/path` mention syntax | C) Use `mcp.get(\"resource\")` | D) Resources are auto-loaded\n- **Correct**: B\n- **Explanation**: MCP resources are accessed via `@server-name:protocol://resource/path` mention syntax in conversation.\n- **Review**: MCP Resources section\n\n---\n\n## Lesson 06: Hooks\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the five types of hooks in Claude Code?\n- **Options**: A) Pre, Post, Error, Filter, and Transform hooks | B) Command, HTTP, MCP Tool, Prompt, and Agent hooks | C) Before, After, Around, Through, and Beside hooks | D) Input, Output, Filter, Transform, and Validate hooks\n- **Correct**: B\n- **Explanation**: Command hooks run shell scripts, HTTP hooks call webhook endpoints, MCP Tool hooks invoke an MCP tool, Prompt hooks use single-turn LLM evaluation, and Agent hooks use subagent-based verification. Agent hooks are experimental and may change.\n- **Review**: Hook types section\n\n### Q2\n- **Category**: practical\n- **Question**: A hook script exits with code 2. What happens?\n- **Options**: A) Non-blocking warning shown | B) Blocking error — stderr is shown as an error to Claude, tool use is prevented | C) Hook is retried | D) Session ends\n- **Correct**: B\n- **Explanation**: Exit code 0 = success/continue, exit code 2 = blocking error (stderr shown as error), any other non-zero = non-blocking error (a `<hook name> hook error` notice with the first line of stderr appears in the transcript, and the action goes ahead). Since v2.1.295, setting `\"onFailure\": \"block\"` on a command or HTTP hook makes such failures block like exit 2.\n- **Review**: Exit codes section\n\n### Q3\n- **Category**: conceptual\n- **Question**: What JSON fields does a PreToolUse hook receive on stdin?\n- **Options**: A) `tool_name` and `tool_output` | B) `session_id`, `tool_name`, `tool_input`, `hook_event_name`, `cwd`, and more | C) Only `tool_name` | D) The full conversation history\n- **Correct**: B\n- **Explanation**: Hooks receive a JSON object on stdin with: session_id, transcript_path, hook_event_name, tool_name, tool_input, tool_use_id, cwd, and permission_mode.\n- **Review**: JSON Input (via stdin)\n\n### Q4\n- **Category**: practical\n- **Question**: How can a PreToolUse hook modify the tool's input parameters before execution?\n- **Options**: A) Return modified JSON on stderr | B) Return JSON with `updatedInput` field on stdout (exit code 0) | C) Write to a temp file | D) Hooks cannot modify inputs\n- **Correct**: B\n- **Explanation**: A PreToolUse hook can output JSON with `\"updatedInput\": {...}` on stdout (with exit 0) to modify the tool's parameters before Claude uses them. `updatedInput` goes under `hookSpecificOutput` and replaces the whole input object; since v2.1.300 it is validated like Claude's own input, so unknown keys are dropped and input the tool rejects denies the call.\n- **Review**: PreToolUse section\n\n### Q5\n- **Category**: conceptual\n- **Question**: Which hook event supports `CLAUDE_ENV_FILE` for persisting environment variables into the session?\n- **Options**: A) PreToolUse | B) UserPromptSubmit | C) SessionStart | D) All events\n- **Correct**: C\n- **Explanation**: `CLAUDE_ENV_FILE` is available to SessionStart, Setup, CwdChanged, and FileChanged hooks, which use it to persist environment variables into the session. Of the options listed, SessionStart is the one that supports it — PreToolUse and UserPromptSubmit do not, and it is not available to all events.\n- **Review**: SessionStart section\n\n### Q6\n- **Category**: practical\n- **Question**: You want a hook that only runs once when a skill is first loaded, not on every tool call. What field do you add?\n- **Options**: A) `run-once: true` | B) `once: true` on a hook in the skill's frontmatter | C) `single: true` | D) `max-runs: 1`\n- **Correct**: B\n- **Explanation**: Hooks declared in a skill's frontmatter support `once: true` — Claude Code removes the hook after its first successful run (a run that fails, blocks, or times out leaves it in place). `once` is honored only in skill frontmatter.\n- **Review**: Component-scoped hooks section\n\n### Q7\n- **Category**: conceptual\n- **Question**: A Stop hook is defined in a subagent's frontmatter. What does it automatically convert to?\n- **Options**: A) A PostToolUse hook | B) A SubagentStop hook | C) A SessionEnd hook | D) It stays as a Stop hook\n- **Correct**: B\n- **Explanation**: When a Stop hook is placed in a subagent's frontmatter, it auto-converts to SubagentStop so it runs when that specific subagent finishes.\n- **Review**: Component-scoped hooks section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you match a hook to all MCP tools from a specific server?\n- **Options**: A) `matcher: \"mcp_github\"` | B) `matcher: \"mcp__github__.*\"` (regex pattern) | C) `matcher: \"mcp:github:*\"` | D) `matcher: \"github-mcp\"`\n- **Correct**: B\n- **Explanation**: Use regex patterns for matchers. MCP tools follow the `mcp__server__tool` naming convention, so `mcp__github__.*` matches all GitHub MCP tools.\n- **Review**: Matcher patterns section\n\n### Q9\n- **Category**: conceptual\n- **Question**: How many hook events does Claude Code support in total?\n- **Options**: A) 16 | B) 25 | C) 33 | D) 40\n- **Correct**: C\n- **Explanation**: Claude Code supports 33 hook events. They fall into four groups: session lifecycle (`SessionStart`, `Setup`, `SessionEnd`), prompt and message handling (`UserPromptSubmit`, `UserPromptExpansion`, `MessageDisplay`), tool use and permissions (`PreToolUse`, `PostToolUse`, `PermissionRequest`, …), and agent, task, and environment coordination (`SubagentStart`, `TaskCreated`, `CwdChanged`, `WorktreeCreate`, `PreModelSwitch`, `PostModelSwitch`, …).\n- **Review**: Hook events table\n\n### Q10\n- **Category**: practical\n- **Question**: You want to debug why a hook isn't firing. What's the best approach?\n- **Options**: A) Add print statements to the hook script | B) Use the `--debug` flag and `Ctrl+O` to open the transcript viewer | C) Check the system log | D) Hooks don't have debugging tools\n- **Correct**: B\n- **Explanation**: `claude --debug` (or `--debug-file <path>`, or `/debug` mid-session) logs hook runs to the debug log, including which hooks fire, their inputs, and outputs; `Ctrl+O` opens the transcript view to see hook outcomes.\n- **Review**: Debugging section\n\n---\n\n## Lesson 07: Plugins\n\n### Q1\n- **Category**: conceptual\n- **Question**: What is the core manifest file for a plugin and where does it live?\n- **Options**: A) `plugin.yaml` in the root directory | B) `.claude-plugin/plugin.json` | C) `package.json` with a \"claude\" key | D) `.claude/plugin.md`\n- **Correct**: B\n- **Explanation**: The plugin manifest lives at `.claude-plugin/plugin.json`. The manifest is optional; when present, `name` (kebab-case identifier) is its only required key; `description`, `version`, `author`, `homepage`, `repository` and `license` are optional metadata.\n- **Review**: Plugin definition structure section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you load a plugin from a local directory so you can try it in a session before publishing?\n- **Options**: A) Use `/plugin test ./my-plugin` | B) Use `claude --plugin-dir ./my-plugin` | C) Use `claude plugin validate ./my-plugin` | D) Copy it to ~/.claude/plugins/\n- **Correct**: B\n- **Explanation**: The `--plugin-dir` flag loads a plugin from a local directory for testing. It's repeatable for loading multiple plugins. `claude plugin validate ./my-plugin` checks the manifest and components but doesn't load the plugin into a session.\n- **Review**: Testing section\n\n### Q3\n- **Category**: conceptual\n- **Question**: What environment variable is available inside plugin hooks and MCP configs to reference the plugin's installation directory?\n- **Options**: A) `$PLUGIN_HOME` | B) `${CLAUDE_PLUGIN_ROOT}` | C) `$PLUGIN_DIR` | D) `${CLAUDE_PLUGIN_PATH}`\n- **Correct**: B\n- **Explanation**: `${CLAUDE_PLUGIN_ROOT}` resolves to the plugin's installed directory, enabling portable path references in hooks and MCP configs.\n- **Review**: Plugin-Provided MCP Servers section in Lesson 05 (MCP)\n\n### Q4\n- **Category**: practical\n- **Question**: A plugin has a command called \"check-security\" in the \"pr-review\" plugin. How does a user invoke it?\n- **Options**: A) `/check-security` | B) `/pr-review:check-security` | C) `/plugin pr-review check-security` | D) `/pr-review/check-security`\n- **Correct**: B\n- **Explanation**: Plugin commands use a `plugin-name:command-name` namespace to avoid conflicts with user commands and other plugins.\n- **Review**: Plugin Commands section in Lesson 01 (Slash Commands)\n\n### Q5\n- **Category**: conceptual\n- **Question**: Which components can a plugin bundle?\n- **Options**: A) Only commands and settings | B) Skills, agents, commands, hooks, MCP servers, LSP config, settings, templates, scripts | C) Only commands, hooks, and MCP servers | D) Only skills and agents\n- **Correct**: B\n- **Explanation**: Plugins can bundle: skills/, agents/, commands/, hooks/hooks.json, .mcp.json, .lsp.json, settings.json, templates/, scripts/, docs/, tests/. Note that `commands/` is legacy — official guidance is to use `skills/` for new plugins, though existing `commands/` directories keep working.\n- **Review**: Plugin Structure Example section\n\n### Q6\n- **Category**: practical\n- **Question**: How do you install a plugin from GitHub?\n- **Options**: A) `claude plugin add github:username/repo` | B) `/plugin marketplace add username/repo`, then `/plugin install plugin-name@marketplace-name` | C) `npm install @claude/username-repo` | D) `git clone` then `claude plugin register`\n- **Correct**: B\n- **Explanation**: Add the GitHub repo as a marketplace with `/plugin marketplace add username/repo`, then install with `/plugin install plugin-name@marketplace-name`. You can also do both in one step: `/plugin install plugin-name --marketplace username/repo` inside a session (v2.1.275+), or `claude plugin install plugin-name --marketplace username/repo` from your shell (v2.1.292+). There is no `github:` install form.\n- **Review**: Installation methods section\n\n### Q7\n- **Category**: conceptual\n- **Question**: What does the `settings.json` `agent` key do in a plugin?\n- **Options**: A) Specifies authentication credentials | B) Sets the main thread agent for the plugin | C) Lists available subagents | D) Configures agent permissions\n- **Correct**: B\n- **Explanation**: The `agent` key in a plugin's settings.json specifies which agent definition to use as the main thread agent when the plugin is active.\n- **Review**: Plugin Settings section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you manage plugin lifecycle (enable/disable/update)?\n- **Options**: A) Edit a config file manually | B) Use `/plugin enable`, `/plugin disable`, `claude plugin update <name>` | C) Use `claude plugin-manager` | D) Reinstall the plugin\n- **Correct**: B\n- **Explanation**: `/plugin enable` and `/plugin disable` are real slash commands. For updating an installed plugin, `claude plugin update <name>` is the form documented in the plugins reference, and the one Claude Code points you to when an update is available.\n- **Review**: Plugin CLI Commands section\n\n### Q9\n- **Category**: conceptual\n- **Question**: What is the main advantage of a plugin over standalone skills/hooks/MCP?\n- **Options**: A) Plugins are faster | B) Single-command install, versioned, marketplace distribution, bundles everything together | C) Plugins have more permissions | D) Plugins work offline\n- **Correct**: B\n- **Explanation**: Plugins package multiple components into one installable unit with versioning, marketplace distribution, and automatic updates — vs. manual setup of standalone components.\n- **Review**: Standalone vs Plugin Approach\n\n### Q10\n- **Category**: practical\n- **Question**: Where do plugin hooks configuration live within the plugin directory?\n- **Options**: A) `.claude-plugin/hooks.json` | B) `hooks/hooks.json` | C) `plugin.json` hooks section | D) `.claude/settings.json`\n- **Correct**: B\n- **Explanation**: Plugin hooks are configured in `hooks/hooks.json` within the plugin directory structure.\n- **Review**: Plugin Structure Example\n\n---\n\n## Lesson 08: Checkpoints\n\n### Q1\n- **Category**: conceptual\n- **Question**: What four things do checkpoints capture?\n- **Options**: A) Git commits, branches, tags, stashes | B) Messages, file modifications, tool usage history, session context | C) Code, tests, logs, configs | D) Inputs, outputs, errors, timing\n- **Correct**: B\n- **Explanation**: Checkpoints capture conversation messages, file modifications made by Claude's tools, tool usage history, and session context.\n- **Review**: Overview section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you access the checkpoint browser?\n- **Options**: A) Use `/restore` command | B) Press `Esc + Esc` (double-escape) or use `/rewind` | C) Use `/history` command | D) Press `Ctrl+Z`\n- **Correct**: B\n- **Explanation**: Double-escape (Esc+Esc) or the `/rewind` command opens the checkpoint browser to select a restore point.\n- **Review**: Accessing checkpoints section\n\n### Q3\n- **Category**: conceptual\n- **Question**: How many rewind options are available, and what are they?\n- **Options**: A) 3: Undo, Redo, Reset | B) 6: Restore code+conversation, Restore conversation, Restore code, Summarize from here, Summarize up to here, Never mind | C) 2: Full restore, Partial restore | D) 4: Code, Messages, Both, Cancel\n- **Correct**: B\n- **Explanation**: The 6 options are: Restore code and conversation (full rollback), Restore conversation only, Restore code only, Summarize from here (compress forward), Summarize up to here (compress backward), Never mind (cancel). The two summary options give bidirectional context compaction.\n- **Review**: Rewind options section\n\n### Q4\n- **Category**: practical\n- **Question**: You used `rm -rf temp/` via Bash in Claude Code, then want to rewind. Will the checkpoint restore those files?\n- **Options**: A) Yes, checkpoints capture everything | B) No, Bash filesystem operations (rm, mv, cp) are not tracked by checkpoints | C) Only if you used the Edit tool instead | D) Only if autoCheckpoint was enabled\n- **Correct**: B\n- **Explanation**: Checkpoints track file changes made by Claude's own Write/Edit tools in the main thread. Bash commands (rm, mv, cp), subagent edits (except a foreground `context: fork` skill), edits made outside Claude Code, and symlinked/hardlinked paths are all outside checkpoint tracking.\n- **Review**: Limitations section\n\n### Q5\n- **Category**: conceptual\n- **Question**: How long are checkpoints retained?\n- **Options**: A) Until session ends | B) 7 days | C) 30 days | D) Indefinitely\n- **Correct**: C\n- **Explanation**: Checkpoints are saved with the session, so `/rewind` works after you resume it; snapshots are deleted about 30 days after the session last saved one (`cleanupPeriodDays`); only the 100 most recent checkpoints keep file snapshots. The window is governed by `cleanupPeriodDays`.\n- **Review**: Checkpoint Retention section\n\n### Q6\n- **Category**: practical\n- **Question**: What does \"Summarize from here\" do when rewinding?\n- **Options**: A) Deletes the conversation from that point | B) Compresses the conversation into an AI-generated summary while preserving the original in the transcript | C) Creates a bullet-point list of changes | D) Exports the conversation to a file\n- **Correct**: B\n- **Explanation**: Summarize compresses the conversation into a shorter AI-generated summary. The original full text is preserved in the transcript file.\n- **Review**: Rewind Options section\n\n### Q7\n- **Category**: conceptual\n- **Question**: When are checkpoints created automatically?\n- **Options**: A) Every 5 minutes | B) On every user prompt | C) Only when you manually save | D) After every tool use\n- **Correct**: B\n- **Explanation**: Automatic checkpoints are created with every user prompt, capturing the state before Claude processes the request.\n- **Review**: Automatic checkpoints section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you disable automatic checkpoint creation?\n- **Options**: A) Use `--no-checkpoints` flag | B) Set `fileCheckpointingEnabled: false` in settings | C) Delete the checkpoints directory | D) Checkpoints cannot be disabled\n- **Correct**: B\n- **Explanation**: Set `fileCheckpointingEnabled: false` in your configuration to disable automatic checkpoint creation (default is true; requires v2.1.119+). Env equivalent: `CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING`.\n- **Review**: Configuration section\n\n### Q9\n- **Category**: conceptual\n- **Question**: Are checkpoints a replacement for git commits?\n- **Options**: A) Yes, they're more powerful | B) No, they are complementary — checkpoints are session-scoped and expire, git is permanent and shareable | C) Yes, for small projects | D) Only in solo development\n- **Correct**: B\n- **Explanation**: Checkpoints are temporary (30-day retention), session-scoped, and cannot be shared. Git commits are permanent, auditable, and shareable. Use both together.\n- **Review**: Integration with git section\n\n### Q10\n- **Category**: practical\n- **Question**: You want to compare two different approaches. What's the recommended checkpoint workflow?\n- **Options**: A) Create two separate sessions | B) Checkpoint before approach A, try it, rewind to checkpoint, try approach B, compare results | C) Use git branches instead | D) There's no good way to compare approaches\n- **Correct**: B\n- **Explanation**: The branching strategy: checkpoint at clean state, try approach A, note results, rewind to the same checkpoint, try approach B. Compare both outcomes.\n- **Review**: Workflow patterns section\n\n---\n\n## Lesson 09: Advanced Features\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the six permission modes in Claude Code?\n- **Options**: A) read, write, execute, admin, root, sudo | B) manual, acceptEdits, plan, auto, dontAsk, bypassPermissions | C) safe, normal, elevated, admin, unrestricted, god | D) view, edit, run, deploy, full, bypass\n- **Correct**: B\n- **Explanation**: The six modes are: manual (runs reads without asking and prompts for everything else — shown as Manual; its config value is `default`, and manual is accepted as an alias since v2.1.200), acceptEdits (auto-accepts file edits), plan (read-only analysis), auto (background classifier decides), dontAsk (auto-denies unless pre-approved), bypassPermissions (skips all checks).\n- **Review**: Permission Modes section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you activate planning mode?\n- **Options**: A) Only via `/plan` command | B) Via `/plan`, `Shift+Tab`/`Alt+M`, `--permission-mode plan` flag, or default config | C) Via `--planning` flag only | D) Planning is always on\n- **Correct**: B\n- **Explanation**: Planning mode can be activated multiple ways: /plan command, Shift+Tab/Alt+M keyboard shortcut, --permission-mode plan CLI flag, or as a default in config.\n- **Review**: Planning Mode section\n\n### Q3\n- **Category**: conceptual\n- **Question**: What does the `opusplan` model alias do?\n- **Options**: A) Uses only Opus for everything | B) Uses Opus for planning phase and Sonnet for implementation | C) Uses a special planning-optimized model | D) Enables plan mode automatically\n- **Correct**: B\n- **Explanation**: `opusplan` is a model alias that uses Opus for the planning phase (higher quality analysis) and Sonnet for the execution phase (faster implementation).\n- **Review**: Planning Mode section\n\n### Q4\n- **Category**: practical\n- **Question**: On a model where thinking can be turned off (for example Sonnet 5), how do you toggle extended thinking on or off during a session?\n- **Options**: A) Type `/effort max` | B) Press `Option+T` (macOS) or `Alt+T` | C) Include \"ultrathink\" in prompt | D) It's always enabled and cannot be toggled\n- **Correct**: B\n- **Explanation**: Option+T (macOS) or Alt+T toggles extended thinking on/off for the session. (`Ctrl+O` toggles verbose mode to show/hide the reasoning text.) On Opus 5.5 (the default model since v2.1.280), Sonnet 5.5 (what the `sonnet` alias resolves to on the Anthropic API since v2.1.284), Haiku 5.5 (what the `haiku` alias resolves to on the Anthropic API since v2.1.293), and the Fable models, thinking can't be turned off: the toggle, `alwaysThinkingEnabled` and `MAX_THINKING_TOKENS=0` have no effect there. For one-off deep reasoning, include \"ultrathink\" in your prompt; for session-level control, use the `/effort` command.\n- **Review**: Extended Thinking section\n\n### Q5\n- **Category**: conceptual\n- **Question**: Does the \"ultrathink\" keyword trigger deep reasoning?\n- **Options**: A) Yes, it triggers deep reasoning for one response without changing session settings | B) No, it's treated as regular prompt text | C) Yes, but only on Opus 4.6 | D) Yes, and it permanently changes the effort level\n- **Correct**: A\n- **Explanation**: Including \"ultrathink\" in your prompt adds an in-context instruction for the model to reason more on that turn. It does not change the effort level sent to the API—use `/effort max` for session-level deep reasoning.\n- **Review**: Extended Thinking section\n\n### Q6\n- **Category**: practical\n- **Question**: How do you run Claude in a CI/CD pipeline with structured JSON output and a turn limit?\n- **Options**: A) `claude --ci --json --limit 3` | B) `claude -p --output-format json --max-t\n\n<!-- [TRUNCATED AT 50KB] -->",".claude/skills/lesson-quiz/references/results-template.md":"# Results Report Template\n\nThe output format for Step 5 (\"Score and Present Results\"). Fill the bracketed placeholders; keep the headings and table columns as shown.\n\n```markdown\n## Lesson Quiz Results: [Lesson Name]\n\n**Score: N/10** — [Grade label]\n**Quiz timing**: [Before / During / After] the lesson\n**Question breakdown**: N conceptual correct, N practical correct\n\n### Per-Question Results\n\n| # | Category | Question (short) | Your Answer | Result |\n|---|----------|-----------------|-------------|--------|\n| 1 | Conceptual | [abbreviated question] | [their answer] | [Correct / Incorrect] |\n| 2 | Practical | ... | ... | ... |\n| ... | ... | ... | ... | ... |\n\n### Incorrect Answers — Review These\n\n[For each incorrect answer, show:]\n\n**Q[N]: [Full question text]**\n- Your answer: [what they chose]\n- Correct answer: [correct option]\n- Explanation: [why it's correct]\n- Review: [specific section of the lesson README to re-read]\n\n### [Timing-specific message]\n\n[If pre-test]:\n**Pre-test score: N/10.** This gives you a baseline! Focus your study on the topics you missed. After completing the lesson, retake the quiz to measure your improvement.\n\n[If during]:\n**Progress check: N/10.** [If 7 or above: Great progress — keep going! If 5-6: Review the incorrect topics before continuing. If 0-4: Consider re-reading from the beginning.]\n\n[If after]:\n**Mastery check: N/10.** [If 9-10: You've mastered this lesson! Move on to the next. If 7-8: Almost there — review the missed topics and retake. If <7: Spend more time with the lesson, especially the sections marked above.]\n\n### Recommended Next Steps\n\n[Based on score and timing:]\n- [If mastered]: Proceed to the next lesson in the roadmap: [next lesson link]\n- [If proficient]: Review these specific sections, then retake: [list sections]\n- [If developing or below]: Re-read the full lesson: [lesson link]. Focus on: [list weak categories]\n- [Offer]: \"Would you like to retake this quiz, try a different lesson, or get help with a specific topic?\"\n```\n\n---\n\n**Last Updated**: September 2, 2026\n**Claude Code Version**: 2.1.257\n**Sources**:\n- https://code.claude.com/docs/en/overview\n",".claude/skills/self-assessment/README.md":"# Self-Assessment & Learning Path Advisor\n\n> Comprehensive Claude Code proficiency assessment that evaluates 10 feature areas, identifies skill gaps, and generates a personalized learning path to level up.\n\n## Highlights\n\n- Two assessment modes: Quick (8 questions, 2 min) and Deep (5 rounds, 5 min)\n- Evaluates 10 feature areas: Slash Commands, Memory, Skills, Hooks, MCP, Subagents, Checkpoints, Advanced Features, Plugins, CLI\n- Per-topic scoring with mastery levels (None / Basic / Proficient)\n- Gap analysis with dependency-aware prioritization\n- Personalized learning path with specific exercises and success criteria\n- Follow-up actions: start learning, deep dive, practice project, or retake\n\n## When to Use\n\n| Say this... | Skill will... |\n|---|---|\n| \"assess my level\" | Run the assessment quiz and determine your level |\n| \"where should I start\" | Evaluate your experience and suggest a starting point |\n| \"check my skills\" | Produce a detailed skill profile across all 10 areas |\n| \"what should I learn next\" | Identify gaps and build a prioritized learning path |\n\n## How It Works\n\n```mermaid\ngraph TD\n    A[\"Choose assessment mode\"] --> B[\"Answer quiz questions\"]\n    B --> C[\"Score per-topic proficiency\"]\n    C --> D[\"Generate personalized learning path\"]\n    D --> E[\"Start learning or deep dive\"]\n    style A fill:#4CAF50,color:#fff\n    style E fill:#2196F3,color:#fff\n```\n\n## Assessment Modes\n\n### Quick Assessment (~2 min)\n- 8 yes/no experience questions across 2 rounds\n- Determines overall level: Beginner / Intermediate / Advanced\n- Lists specific gaps with tutorial links\n- Best for: first-time users, quick check-ins\n\n### Deep Assessment (~5 min)\n- 5 rounds of questions covering 10 feature areas (2 topics per round)\n- Per-topic scoring (0-2 points each, 20 points maximum — Checkpoints contributes 0-1, Advanced Features 0-3)\n- Mastery table with strength areas, priority gaps, and review items\n- Dependency-aware learning path with phases and time estimates\n- Recommended practice projects combining gap topics\n- Best for: experienced users wanting to level up, periodic skill reviews\n\n## Usage\n\n```text\n/self-assessment\n```\n\n## Output\n\n### Skill Profile Table\nShows per-topic score, mastery level, and status (Learn / Review / Mastered).\n\n### Personalized Learning Path\n- Organized into phases based on dependency order\n- Each topic includes: tutorial link, focus areas, key exercise, success criterion\n- Time estimate adjusted for topics already mastered\n- Practice projects combining multiple gap areas\n\n### Follow-up Actions\nAfter results, choose to:\n- Start the first gap tutorial with guided exercises\n- Deep dive into a specific gap area\n- Set up a practice project covering your gaps\n- Retake in a different assessment mode\n",".claude/skills/self-assessment/SKILL.md":"---\nname: self-assessment\nversion: 2.5.5\ndescription: Comprehensive Claude Code self-assessment and learning path advisor. Runs a multi-category quiz covering 10 feature areas, produces a detailed skill profile with per-topic scores, identifies specific gaps, and generates a personalized learning path with prioritized next steps. Use when asked to \"assess my level\", \"take the quiz\", \"find my level\", \"where should I start\", \"what should I learn next\", \"check my skills\", \"skill check\", or \"level up\".\n---\n\n# Self-Assessment & Learning Path Advisor\n\nComprehensive interactive assessment that evaluates Claude Code proficiency across 10 feature areas, identifies specific skill gaps, and generates a personalized learning path to level up.\n\n## Instructions\n\n### Step 1: Welcome & Choose Assessment Mode\n\nPresent the user with a choice of assessment depth:\n\nUse AskUserQuestion with these options:\n- **Quick Assessment** — \"2 multi-select questions (8 items), ~2 minutes. Determines your overall level (Beginner/Intermediate/Advanced) and gives a learning path.\"\n- **Deep Assessment** — \"5 categories with detailed questions, ~5 minutes. Gives per-topic skill scores, identifies specific gaps, and builds a prioritized learning path.\"\n\nIf user chooses **Quick Assessment**, go to Step 2A.\nIf user chooses **Deep Assessment**, go to Step 2B.\n\n---\n\n### Step 2A: Quick Assessment\n\nPresent TWO multi-select questions (AskUserQuestion supports max 4 options each):\n\n**Question 1** (header: \"Basics\"):\n\"Part 1/2: Which of these Claude Code skills do you already have?\"\nOptions:\n1. \"Start Claude Code and chat\" — I can run `claude` and interact with it\n2. \"Created/edited CLAUDE.md\" — I have set up project or user memory\n3. \"Used 3+ slash commands\" — e.g., /help, /compact, /model, /clear\n4. \"Created custom command/skill\" — Written a SKILL.md or custom command file\n\n**Question 2** (header: \"Advanced\"):\n\"Part 2/2: Which of these advanced skills do you have?\"\nOptions:\n1. \"Configured an MCP server\" — e.g., GitHub, database, or other external data source\n2. \"Set up hooks\" — Configured hooks in a settings file (e.g. ~/.claude/settings.json or .claude/settings.json)\n3. \"Created/used subagents\" — Used .claude/agents/ for task delegation\n4. \"Used print mode (claude -p)\" — Used `claude -p` for non-interactive or CI/CD use\n\n**Scoring:**\n- 0-2 total = Level 1: Beginner\n- 3-5 total = Level 2: Intermediate\n- 6-8 total = Level 3: Advanced\n\nGo to Step 3 with the level result, listing which specific items were NOT checked as gaps.\n\n---\n\n### Step 2B: Deep Assessment\n\nPresent 5 rounds of questions, one AskUserQuestion call per round. Each round covers 2 related feature areas. Use multi-select for all rounds.\n\n**IMPORTANT**: AskUserQuestion supports max 4 options per question. Each round has exactly 1 question with 4 options covering 2 topics (2 options per topic).\n\n---\n\n**Round 1 — Slash Commands & Memory** (header: \"Commands\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Created a custom slash command or skill\" — Written a SKILL.md file with frontmatter, or created .claude/commands/ files\n2. \"Used dynamic context in commands\" — Used `$ARGUMENTS`, `$0`/`$1`, backtick `!command` syntax, or `@file` references in skill/command files\n3. \"Set up project + personal memory\" — Created both a project CLAUDE.md and personal ~/.claude/CLAUDE.md (or CLAUDE.local.md)\n4. \"Used memory hierarchy features\" — Understand how the 7 memory locations are concatenated into context (loaded root-down, CLAUDE.local.md appended after CLAUDE.md at each level, subdirectory files loaded on demand), used .claude/rules/ directory, path-specific rules, or @import syntax\n\n**Scoring for Round 1:**\n- Options 1-2 map to **Slash Commands** (0-2 points)\n- Options 3-4 map to **Memory** (0-2 points)\n\n---\n\n**Round 2 — Skills & Hooks** (header: \"Automation\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Installed and used an auto-invoked skill\" — A skill that triggers automatically based on its description, without manual /command invocation\n2. \"Controlled skill invocation behavior\" — Used `disable-model-invocation`, `user-invocable`, or `context: fork` with agent field in SKILL.md frontmatter\n3. \"Set up a PreToolUse or PostToolUse hook\" — Configured a hook that runs before/after tool execution (e.g., command validator, auto-formatter)\n4. \"Used advanced hook features\" — Configured prompt-type hooks, skill-frontmatter hooks, HTTP hooks, or hooks with custom JSON output (updatedInput, systemMessage)\n\n**Scoring for Round 2:**\n- Options 1-2 map to **Skills** (0-2 points)\n- Options 3-4 map to **Hooks** (0-2 points)\n\n---\n\n**Round 3 — MCP & Subagents** (header: \"Integration\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Connected an MCP server and used its tools\" — e.g., GitHub MCP for PRs/issues, database MCP for queries, or any external data source\n2. \"Used advanced MCP features\" — Project-scope .mcp.json, OAuth authentication, MCP resources with @mentions, Tool Search, or `claude mcp serve`\n3. \"Created or configured custom subagents\" — Defined agents in .claude/agents/ with custom tools, model, or permissions\n4. \"Used advanced subagent features\" — Worktree isolation, persistent agent memory, background tasks with Ctrl+B, agent allowlists with `Agent(agent_type)` for an agent run as the main thread with `claude --agent` (the `Task(...)` form is a back-compat alias), or agent teams\n\n**Scoring for Round 3:**\n- Options 1-2 map to **MCP** (0-2 points)\n- Options 3-4 map to **Subagents** (0-2 points)\n\n---\n\n**Round 4 — Checkpoints & Advanced Features** (header: \"Power User\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Used checkpoints for safe experimentation\" — Rewound to a checkpoint with Esc+Esc or /rewind, restored code and/or conversation, or used either Summarize option (summarize from here / summarize up to here)\n2. \"Used planning mode or extended thinking\" — Activated planning via /plan, Shift+Tab, or --permission-mode plan; toggled extended thinking with Alt+T/Option+T on a model that allows it, or set reasoning depth with `/effort`\n3. \"Configured permission modes\" — Used any of the six modes — manual (config value `default`; shown as Manual since v2.1.200), acceptEdits, plan, auto, dontAsk, or bypassPermissions — via CLI flags, keyboard shortcuts, or settings (just starting in the built-in auto default doesn't count)\n4. \"Used remote/desktop/web features\" — Used `claude --remote-control`, `claude --cloud`, `/teleport`, `/desktop`, or worktrees with `claude -w`\n\n**Scoring for Round 4:**\n- Option 1 maps to **Checkpoints** (0-1 point)\n- Options 2-4 map to **Advanced Features** (0-3 points)\n\n---\n\n**Round 5 — Plugins & CLI** (header: \"Mastery\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Installed or created a plugin\" — Used a bundled plugin from marketplace, or created a .claude-plugin/ directory with plugin.json manifest\n2. \"Used plugin advanced features\" — Plugin skills (`skills/` — the preferred form; namespaced `commands/` is legacy but still works), plugin hooks, plugin MCP servers, LSP configuration, or --plugin-dir flag for testing\n3. \"Used print mode in scripts or CI/CD\" — Used `claude -p` with --output-format json, --max-turns, piped input, or integrated into GitHub Actions / CI pipelines\n4. \"Used advanced CLI features\" — Session resumption (-c/-r), --agents flag, --json-schema for structured output, --fallback-model, --from-pr, or batch processing loops\n\n**Scoring for Round 5:**\n- Options 1-2 map to **Plugins** (0-2 points)\n- Options 3-4 map to **CLI** (0-2 points)\n\n---\n\n### Step 3: Calculate & Present Results\n\n#### 3A: For Quick Assessment\n\nCount total selections and determine level. Then present:\n\n```markdown\n## Claude Code Skill Assessment Results\n\n### Your Level: [Level 1: Beginner / Level 2: Intermediate / Level 3: Advanced]\n\nYou checked **N/8** items.\n\n[One-line motivational summary based on level]\n\n### Your Skill Profile\n\n| Area | Status |\n|------|--------|\n| Basic CLI & Conversations | [Checked/Gap] |\n| CLAUDE.md & Memory | [Checked/Gap] |\n| Slash Commands (built-in) | [Checked/Gap] |\n| Custom Commands & Skills | [Checked/Gap] |\n| MCP Servers | [Checked/Gap] |\n| Hooks | [Checked/Gap] |\n| Subagents | [Checked/Gap] |\n| Print Mode & CI/CD | [Checked/Gap] |\n\n### Identified Gaps\n\n[For each unchecked item, provide a 1-line description of what to learn and a link to the tutorial]\n\n### Your Personalized Learning Path\n\n[Output the level-specific learning path — see Step 4]\n```\n\n#### 3B: For Deep Assessment\n\nCalculate per-topic scores from the 5 rounds. Each topic gets 0-2 points, except Advanced Features (0-3) and Checkpoints (0-1). Then present:\n\n```markdown\n## Claude Code Skill Assessment Results\n\n### Overall Level: [Level 1 / Level 2 / Level 3]\n\n**Total Score: N/20 points**\n\n[One-line motivational summary]\n\n### Your Skill Profile\n\n| Feature Area | Score | Mastery | Status |\n|-------------|-------|---------|--------|\n| Slash Commands | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Memory | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Skills | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Hooks | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| MCP | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Subagents | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Checkpoints | N/1 | [None/Proficient] | [Learn/Mastered] |\n| Advanced Features | N/3 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Plugins | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| CLI | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n\n**Mastery key:** 0 = None, 1 = Basic, 2 = Proficient\n\n### Strength Areas\n[List topics with score 2/2 — these are mastered]\n\n### Priority Gaps (Learn Next)\n[List topics with score 0 — these need attention first, ordered by dependency]\n\n### Review Areas\n[List topics with score 1/2 — basics known but advanced features not yet used]\n\n### Your Personalized Learning Path\n\n[Output gap-specific learning path — see Step 4]\n```\n\n**Overall level calculation for Deep Assessment:**\n- 0-6 total points = Level 1: Beginner\n- 7-13 total points = Level 2: Intermediate\n- 14-20 total points = Level 3: Advanced\n\n---\n\n### Step 4: Generate Personalized Learning Path\n\nBased on the assessment results, generate a learning path that is specific to the user's gaps. Do NOT just repeat the generic level path — adapt it.\n\n#### Rules for Path Generation\n\n1. **Skip mastered topics**: If a topic scored 2/2, do not include it in the path.\n2. **Prioritize by dependency order**: Slash Commands before Skills, Memory before Subagents, etc. The dependency order is:\n   - Slash Commands (no deps) -> Skills (depends on Slash Commands)\n   - Memory (no deps) -> Subagents (depends on Memory)\n   - CLI Basics (no deps) -> CLI Mastery (depends on all)\n   - Checkpoints (no deps)\n   - Hooks (depends on Slash Commands)\n   - MCP (no deps) -> Plugins (depends on MCP, Skills, Hooks)\n   - Advanced Features (depends on all previous)\n3. **For score 1/2 topics**: Recommend the \"deep dive\" — link to the specific advanced section they're missing.\n4. **Estimate time**: Sum only the topics they need to learn/review.\n5. **Group into phases**: Organize remaining topics into logical phases of 2-3 topics each.\n\n#### Path Output Format\n\n```markdown\n### Your Personalized Learning Path\n\n**Estimated time**: ~N hours (adjusted for your current skills)\n\n#### Phase 1: [Phase Name] (~N hours)\n[Only if they have gaps in these areas]\n\n**[Topic Name]** — [Learn from scratch / Deep dive into advanced features]\n- Tutorial: [link to tutorial directory]\n- Focus on: [specific sections/concepts they need]\n- Key exercise: [one concrete exercise to do]\n- You'll know it's done when: [specific success criterion]\n\n**[Topic Name]** — ...\n\n---\n\n#### Phase 2: [Phase Name] (~N hours)\n...\n\n---\n\n### Recommended Practice Projects\n\nBased on your gaps, try these real-world exercises to solidify your learning:\n\n1. **[Project name]**: [1-line description combining 2-3 gap topics]\n2. **[Project name]**: [1-line description]\n3. **[Project name]**: [1-line description]\n```\n\n#### Topic-Specific Recommendations\n\nUse these specific recommendations when a topic is a gap:\n\n**Slash Commands (score 0)**:\n- Tutorial: [01-slash-commands/](../../../01-slash-commands/)\n- Focus on: Built-in commands reference, creating your first SKILL.md, `$ARGUMENTS` syntax\n- Key exercise: Create a `/optimize` command and test it\n- Done when: You can create a custom skill with arguments and dynamic context\n\n**Slash Commands (score 1 — review)**:\n- Focus on: Dynamic context with the ``!`command` `` syntax, `@file` references, `disable-model-invocation` vs `user-invocable` control\n- Done when: You can create a skill that injects live command output and controls its own invocation behavior\n\n**Memory (score 0)**:\n- Tutorial: [02-memory/](../../../02-memory/)\n- Focus on: CLAUDE.md creation, `/init` and `/memory` commands, and the difference from auto memory (asking Claude to remember something saves it to auto memory; to put it in CLAUDE.md, say \"add this to CLAUDE.md\" or edit via `/memory` — the old `#` shortcut was removed)\n- Key exercise: Create a project CLAUDE.md with your coding standards\n- Done when: Claude remembers your preferences across sessions\n\n**Memory (score 1 — review)**:\n- Focus on: the 7 memory locations and how they are concatenated into context (loaded root-down, not overridden), .claude/rules/ directory with path-specific rules, `@import` syntax (max depth 4), Auto Memory MEMORY.md (Claude loads its first 200 lines or 25 KB, whichever comes first — a load cap, not a file-size limit)\n- Done when: You have modular rules for different directories and understand how every memory file is concatenated into context\n\n**Skills (score 0)**:\n- Tutorial: [03-skills/](../../../03-skills/)\n- Focus on: SKILL.md format, auto-invocation via description field, progressive disclosure (3 loading levels)\n- Key exercise: Install `03-skills/code-review-specialist` and verify it auto-triggers\n- Done when: A skill automatically activates based on conversation context\n\n**Skills (score 1 — review)**:\n- Focus on: `context: fork` with `agent` field for subagent execution, `disable-model-invocation` vs `user-invocable`, the skill-listing budget (1% of the context window, fallback 8,000 characters; each entry's `description` + `when_to_use` capped at 1,536 characters by default via `skillListingMaxDescChars`), bundled resources (scripts/, references/, assets/)\n- Done when: You can create a skill that runs in a subagent with forked context\n\n**Hooks (score 0)**:\n- Tutorial: [06-hooks/](../../../06-hooks/)\n- Focus on: Configuration structure (matcher + hooks array), PreToolUse/PostToolUse events, exit codes (0=success, 2=block), JSON input/output format\n- Key exercise: Create a PreToolUse hook that validates Bash commands\n- Done when: A hook blocks dangerous commands before execution\n\n**Hooks (score 1 — review)**:\n- Focus on: All 33 hook events (including PostToolUseFailure, StopFailure, TaskCreated, CwdChanged, FileChanged, PostCompact, Elicitation, ElicitationResult, Setup, UserPromptExpansion, MessageDisplay, PreModelSwitch, PostModelSwitch — the last two added in v2.1.251), 5 hook types (command, http, mcp_tool, prompt, agent — agent hooks are experimental and may change), hooks in SKILL.md frontmatter (they persist for the session after invocation; subagent-frontmatter hooks end with the subagent), HTTP hooks with allowedEnvVars, `onFailure: \"block\"` to block the action when a command or HTTP hook fails (v2.1.295+), `CLAUDE_ENV_FILE` for SessionStart, Setup, CwdChanged and FileChanged\n- Done when: You can create a prompt-based Stop hook and a hook in a skill's frontmatter (and you know it stays registered for the rest of the session)\n\n**MCP (score 0)**:\n- Tutorial: [05-mcp/](../../../05-mcp/)\n- Focus on: `claude mcp add` command, transport types (`http` recommended, `stdio`, `ws` for push-style servers, and the deprecated `sse` — note `--transport` does not accept `ws`, so add WebSocket servers with `claude mcp add-json`), GitHub MCP setup, environment variable expansion\n- Key exercise: Add GitHub MCP server and query PRs\n- Done when: You can query live data from an external service via MCP\n\n**MCP (score 1 — review)**:\n- Focus on: Project-scope .mcp.json (each user approves it on first use; workspace trust applies), OAuth 2.0 auth, MCP resources with `@server:resource` mentions, Tool Search (ENABLE_TOOL_SEARCH), `claude mcp serve`, output limits (10,000 tokens warning; 25,000 tokens default max via `MAX_MCP_OUTPUT_TOKENS`; 50,000 characters disk-persistence threshold)\n- Done when: You have a project .mcp.json and understand how tool search defers MCP tools by default and what `ENABLE_TOOL_SEARCH=auto`/`false` change\n\n**Subagents (score 0)**:\n- Tutorial: [04-subagents/](../../../04-subagents/)\n- Focus on: Agent file format (.claude/agents/*.md), built-in agents (Explore, Plan, general-purpose, claude, statusline-setup, claude-code-guide), tools/model/permissionMode config, spawn limits (depth default 3 since v2.1.219, concurrency default 20, and the 200-per-session spawn cap removed in v2.1.224)\n- Key exercise: Create a code-reviewer subagent and test delegation\n- Done when: Claude delegates code review to your custom agent\n\n**Subagents (score 1 — review)**:\n- Focus on: Worktree isolation (`isolation: worktree`), persistent agent memory (`memory` field with scopes), background agents (Ctrl+B to background; Ctrl+X Ctrl+K twice to stop them all), agent allowlists with `Agent(agent_type)` for a main-thread agent started with `claude --agent` (`Task(...)` remains a back-compat alias; in a subagent's own `tools` the type list is ignored), agent teams (`--teammate-mode`)\n- Done when: You have a subagent with persistent memory running in worktree isolation\n\n**Checkpoints (score 0)**:\n- Tutorial: [08-checkpoints/](../../../08-checkpoints/)\n- Focus on: Esc+Esc and /rewind access, 6 rewind options (restore code and conversation, restore conversation, restore code, summarize from here, summarize up to here, never mind), limitations — bash filesystem ops, subagent edits (except a foreground `context: fork` skill), edits made outside Claude Code are untracked, and symlinked/hard-linked paths are skipped on restore\n- Key exercise: Make experimental changes, then rewind to restore\n- Done when: You can confidently experiment knowing you can rewind\n\n**Advanced Features (score 0)**:\n- Tutorial: [09-advanced-features/](../../../09-advanced-features/)\n- Focus on: Planning mode (/plan or Shift+Tab), permission modes (6 types: manual — config value `default`, shown as Manual since v2.1.200 — acceptEdits, plan, auto, dontAsk, bypassPermissions), extended thinking (Alt+T/Option+T toggle — no effect on Opus 5.5 (the default model), Sonnet 5.5, Haiku 5.5, or the Fable models, where thinking stays on)\n- Key exercise: Use planning mode to design a feature, then implement it\n- Done when: You can switch between planning and implementation modes fluently\n\n**Advanced Features (score 1 — review)**:\n- Focus on: Remote control (`claude --remote-control`, alias `--rc`), web sessions (`claude --cloud`; `--remote` is a deprecated alias), desktop handoff (`/desktop`), worktrees (`claude -w`), task lists (Ctrl+T), managed settings for enterprise\n- Done when: You can hand off sessions between CLI, web, and desktop\n\n**Plugins (score 0)**:\n- Tutorial: [07-plugins/](../../../07-plugins/)\n- Focus on: Plugin structure (.claude-plugin/plugin.json), what plugins bundle (skills, agents, MCP, hooks, settings — plus the legacy `commands/` directory, which still works but `skills/` is preferred for new plugins), installation from marketplace (`/plugin install`, or `claude plugin install <plugin> --marketplace <source>` from the shell)\n- Key exercise: Install a plugin and explore its components\n- Done when: You understand when to use a plugin vs standalone components\n\n**Plugins (score 1 — review)**:\n- Focus on: Creating plugin.json manifest, plugin hooks (hooks/hooks.json), LSP configuration (.lsp.json), `${CLAUDE_PLUGIN_ROOT}` variable, --plugin-dir for testing, marketplace publishing, mods (hooks modules shipped in a plugin that add panes, commands, and tool-call rules — v2.1.287+)\n- Done when: You can create and test a plugin for your team\n\n**CLI (score 0)**:\n- Tutorial: [10-cli/](../../../10-cli/)\n- Focus on: Interactive vs print mode, `claude -p` with piping, `--output-format json`, session management (-c/-r)\n- Key exercise: Pipe a file to `claude -p` and get JSON output\n- Done when: You can use Claude non-interactively in a script\n\n**CLI (score 1 — review)**:\n- Focus on: --agents flag with JSON config, --json-schema for structured output, --fallback-model, --from-pr, --strict-mcp-config, batch processing with for loops, `claude mcp serve`\n- Done when: You have a CI/CD script that uses Claude with structured JSON output\n\n---\n\n### Step 5: Offer Follow-up Actions\n\nAfter presenting results, ask the user what they'd like to do next:\n\nUse AskUserQuestion with these options:\n- **Start learning** — \"Help me begin the first topic in my learning path right now\"\n- **Deep dive on a gap** — \"Explain one of my gap areas in detail so I can learn it here\"\n- **Practice project** — \"Set up a practice project that covers my gap areas\"\n- **Retake assessment** — \"I want to retake the quiz (maybe the other mode)\"\n\nIf **Start learning**: Read the README.md of the first gap tutorial and walk the user through the first exercise.\nIf **Deep dive on a gap**: Ask which gap topic, then read the relevant tutorial README.md and explain the key concepts with examples.\nIf **Practice project**: Design a small project that combines 2-3 of their gap topics with concrete steps.\nIf **Retake assessment**: Go back to Step 1.\n\n## Error Handling\n\n### User selects no items in a round\nTreat as 0 points for that round's topics. Continue to next round.\n\n### User selects no items in any round\nAssign Level 1: Beginner. Encourage starting from the beginning. Output the full Level 1 path.\n\n### User wants to retake\nRe-run from Step 1 with a fresh assessment.\n\n### User disagrees with their level\nAcknowledge their preference. Ask which level they identify with. Present the path for their chosen level with a prerequisites check for topics they may have missed.\n\n### User asks about a specific topic\nIf the user says something like \"tell me about hooks\" or \"I want to learn MCP\" during the assessment, note it. After presenting results, highlight that topic in their learning path regardless of score.\n\n## Validation\n\n### Triggering test suite\n\n**Should trigger:**\n- \"assess my level\"\n- \"take the quiz\"\n- \"find my level\"\n- \"where should I start\"\n- \"what level am I\"\n- \"learning path quiz\"\n- \"self-assessment\"\n- \"what should I learn next\"\n- \"check my skills\"\n- \"skill check\"\n- \"level up\"\n- \"how good am I at Claude Code\"\n- \"evaluate my Claude Code knowledge\"\n\n**Should NOT trigger:**\n- \"review my code\"\n- \"create a skill\"\n- \"help me with MCP\"\n- \"explain slash commands\"\n- \"what is a checkpoint\"\n",".claude/skills/self-assessment/references/deep-assessment-rounds.md":"# Deep Assessment — Round Questions\n\nThe 5 rounds for Deep Assessment. Present one AskUserQuestion call per round (multi-select, max 4 options). Each round covers 2 feature areas with 2 options each. The scoring map for each round is duplicated in SKILL.md Step 2B so results can be computed without re-reading this file.\n\n---\n\n**Round 1 — Slash Commands & Memory** (header: \"Commands\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Created a custom slash command or skill\" — Written a SKILL.md file with frontmatter, or created .claude/commands/ files\n2. \"Used dynamic context in commands\" — Used `$ARGUMENTS`, `$0`/`$1`, backtick `!command` syntax, or `@file` references in skill/command files\n3. \"Set up project + personal memory\" — Created both a project CLAUDE.md and personal ~/.claude/CLAUDE.md (or CLAUDE.local.md)\n4. \"Used memory hierarchy features\" — Understand how the 7 memory locations are concatenated into context (loaded root-down, CLAUDE.local.md appended after CLAUDE.md at each level, subdirectory files loaded on demand), used .claude/rules/ directory, path-specific rules, or @import syntax\n\n**Scoring:** Options 1-2 → **Slash Commands** (0-2); Options 3-4 → **Memory** (0-2)\n\n---\n\n**Round 2 — Skills & Hooks** (header: \"Automation\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Installed and used an auto-invoked skill\" — A skill that triggers automatically based on its description, without manual /command invocation\n2. \"Controlled skill invocation behavior\" — Used `disable-model-invocation`, `user-invocable`, or `context: fork` with agent field in SKILL.md frontmatter\n3. \"Set up a PreToolUse or PostToolUse hook\" — Configured a hook that runs before/after tool execution (e.g., command validator, auto-formatter)\n4. \"Used advanced hook features\" — Configured prompt-type hooks, skill-frontmatter hooks, HTTP hooks, or hooks with custom JSON output (updatedInput, systemMessage)\n\n**Scoring:** Options 1-2 → **Skills** (0-2); Options 3-4 → **Hooks** (0-2)\n\n---\n\n**Round 3 — MCP & Subagents** (header: \"Integration\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Connected an MCP server and used its tools\" — e.g., GitHub MCP for PRs/issues, database MCP for queries, or any external data source\n2. \"Used advanced MCP features\" — Project-scope .mcp.json, OAuth authentication, MCP resources with @mentions, Tool Search, or `claude mcp serve`\n3. \"Created or configured custom subagents\" — Defined agents in .claude/agents/ with custom tools, model, or permissions\n4. \"Used advanced subagent features\" — Worktree isolation, persistent agent memory, background tasks with Ctrl+B, agent allowlists with `Agent(agent_type)` for an agent run as the main thread with `claude --agent` (the `Task(...)` form is a back-compat alias), or agent teams\n\n**Scoring:** Options 1-2 → **MCP** (0-2); Options 3-4 → **Subagents** (0-2)\n\n---\n\n**Round 4 — Checkpoints & Advanced Features** (header: \"Power User\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Used checkpoints for safe experimentation\" — Rewound to a checkpoint with Esc+Esc or /rewind, restored code and/or conversation, or used either Summarize option (summarize from here / summarize up to here)\n2. \"Used planning mode or extended thinking\" — Activated planning via /plan, Shift+Tab, or --permission-mode plan; toggled extended thinking with Alt+T/Option+T on a model that allows it, or set reasoning depth with `/effort`\n3. \"Configured permission modes\" — Used any of the six modes — manual (config value `default`; shown as Manual since v2.1.200), acceptEdits, plan, auto, dontAsk, or bypassPermissions — via CLI flags, keyboard shortcuts, or settings (just starting in the built-in auto default doesn't count)\n4. \"Used remote/desktop/web features\" — Used `claude --remote-control`, `claude --cloud`, `/teleport`, `/desktop`, or worktrees with `claude -w`\n\n**Scoring:** Option 1 → **Checkpoints** (0-1); Options 2-4 → **Advanced Features** (0-3)\n\n---\n\n**Round 5 — Plugins & CLI** (header: \"Mastery\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Installed or created a plugin\" — Used a bundled plugin from marketplace, or created a .claude-plugin/ directory with plugin.json manifest\n2. \"Used plugin advanced features\" — Plugin skills (`skills/` — the preferred form; namespaced `commands/` is legacy but still works), plugin hooks, plugin MCP servers, LSP configuration, or --plugin-dir flag for testing\n3. \"Used print mode in scripts or CI/CD\" — Used `claude -p` with --output-format json, --max-turns, piped input, or integrated into GitHub Actions / CI pipelines\n4. \"Used advanced CLI features\" — Session resumption (-c/-r), --agents flag, --json-schema for structured output, --fallback-model, --from-pr, or batch processing loops\n\n**Scoring:** Options 1-2 → **Plugins** (0-2); Options 3-4 → **CLI** (0-2)\n\n---\n\n**Last Updated**: October 18, 2026\n**Claude Code Version**: 2.1.302\n**Sources**:\n- https://code.claude.com/docs/en/memory\n- https://code.claude.com/docs/en/sub-agents\n- https://code.claude.com/docs/en/permission-modes\n- https://code.claude.com/docs/en/checkpointing\n- https://code.claude.com/docs/en/plugins-reference\n- https://code.claude.com/docs/en/permission-modes#which-mode-a-session-starts-in\n- https://code.claude.com/docs/en/hooks#hooks-in-skills-and-agents\n- https://code.claude.com/docs/en/model-config#extended-thinking\n",".claude/skills/self-assessment/references/output-templates.md":"# Output Templates\n\nBlank markdown templates for the assessment results and learning path. The Step 3A/3B result templates and the Step 4 path-format template are duplicated verbatim in SKILL.md so results can be produced without re-reading this file.\n\n## Quick Assessment results (Step 3A)\n\n```markdown\n## Claude Code Skill Assessment Results\n\n### Your Level: [Level 1: Beginner / Level 2: Intermediate / Level 3: Advanced]\n\nYou checked **N/8** items.\n\n[One-line motivational summary based on level]\n\n### Your Skill Profile\n\n| Area | Status |\n|------|--------|\n| Basic CLI & Conversations | [Checked/Gap] |\n| CLAUDE.md & Memory | [Checked/Gap] |\n| Slash Commands (built-in) | [Checked/Gap] |\n| Custom Commands & Skills | [Checked/Gap] |\n| MCP Servers | [Checked/Gap] |\n| Hooks | [Checked/Gap] |\n| Subagents | [Checked/Gap] |\n| Print Mode & CI/CD | [Checked/Gap] |\n\n### Identified Gaps\n\n[For each unchecked item, provide a 1-line description of what to learn and a link to the tutorial]\n\n### Your Personalized Learning Path\n\n[Output the level-specific learning path — see Step 4]\n```\n\n## Deep Assessment results (Step 3B)\n\n```markdown\n## Claude Code Skill Assessment Results\n\n### Overall Level: [Level 1 / Level 2 / Level 3]\n\n**Total Score: N/20 points**\n\n[One-line motivational summary]\n\n### Your Skill Profile\n\n| Feature Area | Score | Mastery | Status |\n|-------------|-------|---------|--------|\n| Slash Commands | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Memory | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Skills | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Hooks | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| MCP | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Subagents | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Checkpoints | N/1 | [None/Proficient] | [Learn/Mastered] |\n| Advanced Features | N/3 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Plugins | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| CLI | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n\n**Mastery key:** 0 = None, 1 = Basic, 2 = Proficient\n\n### Strength Areas\n[List topics with score 2/2 — these are mastered]\n\n### Priority Gaps (Learn Next)\n[List topics with score 0 — these need attention first, ordered by dependency]\n\n### Review Areas\n[List topics with score 1/2 — basics known but advanced features not yet used]\n\n### Your Personalized Learning Path\n\n[Output gap-specific learning path — see Step 4]\n```\n\n## Learning Path (Step 4)\n\n```markdown\n### Your Personalized Learning Path\n\n**Estimated time**: ~N hours (adjusted for your current skills)\n\n#### Phase 1: [Phase Name] (~N hours)\n[Only if they have gaps in these areas]\n\n**[Topic Name]** — [Learn from scratch / Deep dive into advanced features]\n- Tutorial: [link to tutorial directory]\n- Focus on: [specific sections/concepts they need]\n- Key exercise: [one concrete exercise to do]\n- You'll know it's done when: [specific success criterion]\n\n**[Topic Name]** — ...\n\n---\n\n#### Phase 2: [Phase Name] (~N hours)\n...\n\n---\n\n### Recommended Practice Projects\n\nBased on your gaps, try these real-world exercises to solidify your learning:\n\n1. **[Project name]**: [1-line description combining 2-3 gap topics]\n2. **[Project name]**: [1-line description]\n3. **[Project name]**: [1-line description]\n```\n\n---\n\n**Last Updated**: September 2, 2026\n**Claude Code Version**: 2.1.257\n**Sources**:\n- https://code.claude.com/docs/en/overview\n",".claude/skills/self-assessment/references/topic-recommendations.md":"# Topic-Specific Recommendations\n\nUse these specific recommendations when a topic is a gap. Paths are relative to this reference file (`.claude/skills/self-assessment/references/`).\n\n**Slash Commands (score 0)**:\n- Tutorial: [01-slash-commands/](../../../../01-slash-commands/)\n- Focus on: Built-in commands reference, creating your first SKILL.md, `$ARGUMENTS` syntax\n- Key exercise: Create a `/optimize` command and test it\n- Done when: You can create a custom skill with arguments and dynamic context\n\n**Slash Commands (score 1 — review)**:\n- Focus on: Dynamic context with the ``!`command` `` syntax, `@file` references, `disable-model-invocation` vs `user-invocable` control\n- Done when: You can create a skill that injects live command output and controls its own invocation behavior\n\n**Memory (score 0)**:\n- Tutorial: [02-memory/](../../../../02-memory/)\n- Focus on: CLAUDE.md creation, `/init` and `/memory` commands, and the difference from auto memory (asking Claude to remember something saves it to auto memory; to put it in CLAUDE.md, say \"add this to CLAUDE.md\" or edit via `/memory` — the old `#` shortcut was removed)\n- Key exercise: Create a project CLAUDE.md with your coding standards\n- Done when: Claude remembers your preferences across sessions\n\n**Memory (score 1 — review)**:\n- Focus on: the 7 memory locations and how they are concatenated into context (loaded root-down, not overridden), .claude/rules/ directory with path-specific rules, `@import` syntax (max depth 4), Auto Memory MEMORY.md (Claude loads its first 200 lines or 25 KB, whichever comes first — a load cap, not a file-size limit)\n- Done when: You have modular rules for different directories and understand how every memory file is concatenated into context\n\n**Skills (score 0)**:\n- Tutorial: [03-skills/](../../../../03-skills/)\n- Focus on: SKILL.md format, auto-invocation via description field, progressive disclosure (3 loading levels)\n- Key exercise: Install `03-skills/code-review-specialist` and verify it auto-triggers\n- Done when: A skill automatically activates based on conversation context\n\n**Skills (score 1 — review)**:\n- Focus on: `context: fork` with `agent` field for subagent execution, `disable-model-invocation` vs `user-invocable`, the skill-listing budget (1% of the context window, fallback 8,000 characters; each entry's `description` + `when_to_use` capped at 1,536 characters by default via `skillListingMaxDescChars`), bundled resources (scripts/, references/, assets/)\n- Done when: You can create a skill that runs in a subagent with forked context\n\n**Hooks (score 0)**:\n- Tutorial: [06-hooks/](../../../../06-hooks/)\n- Focus on: Configuration structure (matcher + hooks array), PreToolUse/PostToolUse events, exit codes (0=success, 2=block), JSON input/output format\n- Key exercise: Create a PreToolUse hook that validates Bash commands\n- Done when: A hook blocks dangerous commands before execution\n\n**Hooks (score 1 — review)**:\n- Focus on: All 33 hook events (including PostToolUseFailure, StopFailure, TaskCreated, CwdChanged, FileChanged, PostCompact, Elicitation, ElicitationResult, Setup, UserPromptExpansion, MessageDisplay, PreModelSwitch, PostModelSwitch — the last two added in v2.1.251), 5 hook types (command, http, mcp_tool, prompt, agent — agent hooks are experimental and may change), hooks in SKILL.md frontmatter (they persist for the session after invocation; subagent-frontmatter hooks end with the subagent), HTTP hooks with allowedEnvVars, `onFailure: \"block\"` to block the action when a command or HTTP hook fails (v2.1.295+), `CLAUDE_ENV_FILE` for SessionStart, Setup, CwdChanged and FileChanged\n- Done when: You can create a prompt-based Stop hook and a hook in a skill's frontmatter (and you know it stays registered for the rest of the session)\n\n**MCP (score 0)**:\n- Tutorial: [05-mcp/](../../../../05-mcp/)\n- Focus on: `claude mcp add` command, transport types (`http` recommended, `stdio`, `ws` for push-style servers, and the deprecated `sse` — note `--transport` does not accept `ws`, so add WebSocket servers with `claude mcp add-json`), GitHub MCP setup, environment variable expansion\n- Key exercise: Add GitHub MCP server and query PRs\n- Done when: You can query live data from an external service via MCP\n\n**MCP (score 1 — review)**:\n- Focus on: Project-scope .mcp.json (each user approves it on first use; workspace trust applies), OAuth 2.0 auth, MCP resources with `@server:resource` mentions, Tool Search (ENABLE_TOOL_SEARCH), `claude mcp serve`, output limits (10,000 tokens warning; 25,000 tokens default max via `MAX_MCP_OUTPUT_TOKENS`; 50,000 characters disk-persistence threshold)\n- Done when: You have a project .mcp.json and understand how tool search defers MCP tools by default and what `ENABLE_TOOL_SEARCH=auto`/`false` change\n\n**Subagents (score 0)**:\n- Tutorial: [04-subagents/](../../../../04-subagents/)\n- Focus on: Agent file format (.claude/agents/*.md), built-in agents (Explore, Plan, general-purpose, claude, statusline-setup, claude-code-guide), tools/model/permissionMode config, spawn limits (depth default 3 since v2.1.219, concurrency default 20, and the 200-per-session spawn cap removed in v2.1.224)\n- Key exercise: Create a code-reviewer subagent and test delegation\n- Done when: Claude delegates code review to your custom agent\n\n**Subagents (score 1 — review)**:\n- Focus on: Worktree isolation (`isolation: worktree`), persistent agent memory (`memory` field with scopes), background agents (Ctrl+B to background; Ctrl+X Ctrl+K twice to stop them all), agent allowlists with `Agent(agent_type)` for a main-thread agent started with `claude --agent` (`Task(...)` remains a back-compat alias; in a subagent's own `tools` the type list is ignored), agent teams (`--teammate-mode`)\n- Done when: You have a subagent with persistent memory running in worktree isolation\n\n**Checkpoints (score 0)**:\n- Tutorial: [08-checkpoints/](../../../../08-checkpoints/)\n- Focus on: Esc+Esc and /rewind access, 6 rewind options (restore code and conversation, restore conversation, restore code, summarize from here, summarize up to here, never mind), limitations — bash filesystem ops, subagent edits (except a foreground `context: fork` skill), edits made outside Claude Code are untracked, and symlinked/hard-linked paths are skipped on restore\n- Key exercise: Make experimental changes, then rewind to restore\n- Done when: You can confidently experiment knowing you can rewind\n\n**Advanced Features (score 0)**:\n- Tutorial: [09-advanced-features/](../../../../09-advanced-features/)\n- Focus on: Planning mode (/plan or Shift+Tab), permission modes (6 types: manual — config value `default`, shown as Manual since v2.1.200 — acceptEdits, plan, auto, dontAsk, bypassPermissions), extended thinking (Alt+T/Option+T toggle — no effect on Opus 5.5 (the default model), Sonnet 5.5, Haiku 5.5, or the Fable models, where thinking stays on)\n- Key exercise: Use planning mode to design a feature, then implement it\n- Done when: You can switch between planning and implementation modes fluently\n\n**Advanced Features (score 1 — review)**:\n- Focus on: Remote control (`claude --remote-control`, alias `--rc`), web sessions (`claude --cloud`; `--remote` is a deprecated alias), desktop handoff (`/desktop`), worktrees (`claude -w`), task lists (Ctrl+T), managed settings for enterprise\n- Done when: You can hand off sessions between CLI, web, and desktop\n\n**Plugins (score 0)**:\n- Tutorial: [07-plugins/](../../../../07-plugins/)\n- Focus on: Plugin structure (.claude-plugin/plugin.json), what plugins bundle (skills, agents, MCP, hooks, settings — plus the legacy `commands/` directory, which still works but `skills/` is preferred for new plugins), installation from marketplace (`/plugin install`, or `claude plugin install <plugin> --marketplace <source>` from the shell)\n- Key exercise: Install a plugin and explore its components\n- Done when: You understand when to use a plugin vs standalone components\n\n**Plugins (score 1 — review)**:\n- Focus on: Creating plugin.json manifest, plugin hooks (hooks/hooks.json), LSP configuration (.lsp.json), `${CLAUDE_PLUGIN_ROOT}` variable, --plugin-dir for testing, marketplace publishing, mods (hooks modules shipped in a plugin that add panes, commands, and tool-call rules — v2.1.287+)\n- Done when: You can create and test a plugin for your team\n\n**CLI (score 0)**:\n- Tutorial: [10-cli/](../../../../10-cli/)\n- Focus on: Interactive vs print mode, `claude -p` with piping, `--output-format json`, session management (-c/-r)\n- Key exercise: Pipe a file to `claude -p` and get JSON output\n- Done when: You can use Claude non-interactively in a script\n\n**CLI (score 1 — review)**:\n- Focus on: --agents flag with JSON config, --json-schema for structured output, --fallback-model, --from-pr, --strict-mcp-config, batch processing with for loops, `claude mcp serve`\n- Done when: You have a CI/CD script that uses Claude with structured JSON output\n\n---\n\n**Last Updated**: October 18, 2026\n**Claude Code Version**: 2.1.302\n**Sources**:\n- https://code.claude.com/docs/en/hooks\n- https://code.claude.com/docs/en/memory\n- https://code.claude.com/docs/en/skills\n- https://code.claude.com/docs/en/mcp\n- https://code.claude.com/docs/en/sub-agents\n- https://code.claude.com/docs/en/checkpointing\n- https://code.claude.com/docs/en/permission-modes\n- https://code.claude.com/docs/en/plugins-reference\n- https://code.claude.com/docs/en/interactive-mode\n- https://code.claude.com/docs/en/model-config#extended-thinking\n- https://code.claude.com/docs/en/settings-reference\n- https://code.claude.com/docs/en/model-config\n- https://code.claude.com/docs/en/plugins/mods/overview\n- https://code.claude.com/docs/en/plugins/cli-reference\n- https://code.claude.com/docs/en/mcp#configure-tool-search\n- https://code.claude.com/docs/en/mcp#project-server-approvals-and-workspace-trust\n","03-skills/blog-draft/SKILL.md":"---\nname: blog-draft\ndescription: Draft a blog post from ideas and resources. Use when users want to write a blog post, create content from research, or draft articles. Guides through research, brainstorming, outlining, and iterative drafting with version control.\n---\n\n## User Input\n\n```text\n$ARGUMENTS\n```\n\nYou **MUST** consider the user input before proceeding. User should provide:\n- **Idea/Topic**: The main concept or theme for the blog post\n- **Resources**: URLs, files, or references to research (optional but recommended)\n- **Target audience**: Who the blog post is for (optional)\n- **Tone/Style**: Formal, casual, technical, etc. (optional)\n\n**IMPORTANT**: If the user is requesting updates to an **existing blog post**, skip steps 0-8 and start directly at **Step 9**. Read the existing draft file(s) first, then proceed with the iteration process.\n\n## Execution Flow\n\nFollow these steps sequentially. **Do not skip steps or proceed without user approval where indicated.**\n\n### Step 0: Create Project Folder\n\n1. Generate a folder name using format: `YYYY-MM-DD-short-topic-name`\n   - Use today's date\n   - Create a short, URL-friendly slug from the topic (lowercase, hyphens, max 5 words)\n\n2. Create the folder structure:\n   ```\n   blog-posts/\n   └── YYYY-MM-DD-short-topic-name/\n       └── resources/\n   ```\n\n3. Confirm folder creation with user before proceeding.\n\n### Step 1: Research & Resource Collection\n\n1. Create `resources/` subfolder in the blog post directory\n\n2. For each provided resource:\n   - **URLs**: Fetch and save key information to `resources/` as markdown files\n   - **Files**: Read and summarize in `resources/`\n   - **Topics**: Use web search to gather up-to-date information\n\n3. For each resource, create a summary file in `resources/`:\n   - `resources/source-1-[short-name].md`\n   - `resources/source-2-[short-name].md`\n   - etc.\n\n4. Each summary should include:\n   ```markdown\n   # Source: [Title/URL]\n\n   ## Key Points\n   - Point 1\n   - Point 2\n\n   ## Relevant Quotes/Data\n   - Quote or statistic 1\n   - Quote or statistic 2\n\n   ## How This Relates to Topic\n   Brief explanation of relevance\n   ```\n\n5. Present research summary to user.\n\n### Step 2: Brainstorm & Clarify\n\n1. Based on the idea and researched resources, present:\n   - **Main themes** identified from research\n   - **Potential angles** for the blog post\n   - **Key points** that should be covered\n   - **Gaps** in information that need clarification\n\n2. Ask clarifying questions:\n   - What is the main takeaway you want readers to have?\n   - Are there specific points from the research you want to emphasize?\n   - What's the target length? (short: 500-800 words, medium: 1000-1500, long: 2000+)\n   - Any points you want to exclude?\n\n3. **Wait for user responses before proceeding.**\n\n### Step 3: Propose Outline\n\n1. Create a structured outline including:\n\n   ```markdown\n   # Blog Post Outline: [Title]\n\n   ## Meta Information\n   - **Target Audience**: [who]\n   - **Tone**: [style]\n   - **Target Length**: [word count]\n   - **Main Takeaway**: [key message]\n\n   ## Proposed Structure\n\n   ### Hook/Introduction\n   - Opening hook idea\n   - Context setting\n   - Thesis statement\n\n   ### Section 1: [Title]\n   - Key point A\n   - Key point B\n   - Supporting evidence from [source]\n\n   ### Section 2: [Title]\n   - Key point A\n   - Key point B\n\n   [Continue for all sections...]\n\n   ### Conclusion\n   - Summary of key points\n   - Call to action or final thought\n\n   ## Sources to Cite\n   - Source 1\n   - Source 2\n   ```\n\n2. Present outline to user and **ask for approval or modifications**.\n\n### Step 4: Save Approved Outline\n\n1. Once user approves the outline, save it to `OUTLINE.md` in the blog post folder.\n\n2. Confirm the outline has been saved.\n\n### Step 5: Commit Outline (if in git repo)\n\n1. Check if current directory is a git repository.\n\n2. If yes:\n   - Stage the new files: blog post folder, resources, and OUTLINE.md\n   - Create commit with message: `docs: Add outline for blog post - [topic-name]`\n   - Push to remote\n\n3. If not a git repo, skip this step and inform user.\n\n### Step 6: Write Draft\n\n1. Based on the approved outline, write the full blog post draft.\n\n2. Follow the structure from OUTLINE.md exactly.\n\n3. Include:\n   - Engaging introduction with hook\n   - Clear section headers\n   - Supporting evidence and examples from research\n   - Smooth transitions between sections\n   - Strong conclusion with takeaway\n   - **Citations**: All comparisons, statistics, data points, and factual claims MUST cite the original source\n\n4. Save the draft as `draft-v0.1.md` in the blog post folder.\n\n5. Format:\n   ```markdown\n   # [Blog Post Title]\n\n   *[Optional: subtitle or tagline]*\n\n   [Full content with inline citations...]\n\n   ---\n\n   ## References\n   - [1] Source 1 Title - URL or Citation\n   - [2] Source 2 Title - URL or Citation\n   - [3] Source 3 Title - URL or Citation\n   ```\n\n6. **Citation Requirements**:\n   - Every data point, statistic, or comparison MUST have an inline citation\n   - Use numbered references [1], [2], etc., or named citations [Source Name]\n   - Link citations to the References section at the end\n   - Example: \"Studies show that 65% of developers prefer TypeScript [1]\"\n   - Example: \"React outperforms Vue in rendering speed by 20% [React Benchmarks 2024]\"\n\n### Step 7: Commit Draft (if in git repo)\n\n1. Check if in git repository.\n\n2. If yes:\n   - Stage the draft file\n   - Create commit with message: `docs: Add draft v0.1 for blog post - [topic-name]`\n   - Push to remote\n\n3. If not a git repo, skip and inform user.\n\n### Step 8: Present Draft for Review\n\n1. Present the draft content to user.\n\n2. Ask for feedback:\n   - Overall impression?\n   - Sections that need expansion or reduction?\n   - Tone adjustments needed?\n   - Missing information?\n   - Specific edits or rewrites?\n\n3. **Wait for user response.**\n\n### Step 9: Iterate or Finalize\n\n**If user requests changes:**\n1. Note all requested modifications\n2. Return to Step 6 with the following adjustments:\n   - Increment version number (v0.2, v0.3, etc.)\n   - Incorporate all feedback\n   - Save as `draft-v[X.Y].md`\n   - Repeat Steps 7-8\n\n**If user approves:**\n1. Confirm the final draft version\n2. Optionally rename to `final.md` if user requests\n3. Summarize the blog post creation process:\n   - Total versions created\n   - Key changes between versions\n   - Final word count\n   - Files created\n\n## Version Tracking\n\nAll drafts are preserved with incremental versioning:\n- `draft-v0.1.md` - Initial draft\n- `draft-v0.2.md` - After first round of feedback\n- `draft-v0.3.md` - After second round of feedback\n- etc.\n\nThis allows tracking the evolution of the blog post and reverting if needed.\n\n## Output Files Structure\n\n```\nblog-posts/\n└── YYYY-MM-DD-topic-name/\n    ├── resources/\n    │   ├── source-1-name.md\n    │   ├── source-2-name.md\n    │   └── ...\n    ├── OUTLINE.md\n    ├── draft-v0.1.md\n    ├── draft-v0.2.md (if iterations)\n    └── draft-v0.3.md (if more iterations)\n```\n\n## Tips for Quality\n\n- **Hook**: Start with a question, surprising fact, or relatable scenario\n- **Flow**: Each paragraph should connect to the next\n- **Evidence**: Support claims with data from research\n- **Citations**: ALWAYS cite sources for:\n  - All statistics and data points (e.g., \"According to [Source], 75% of...\")\n  - Comparisons between products, services, or approaches (e.g., \"X performs 2x faster than Y [Source]\")\n  - Factual claims about market trends, research findings, or benchmarks\n  - Use inline citations with format: [Source Name] or [Author, Year]\n- **Voice**: Maintain consistent tone throughout\n- **Length**: Respect the target word count\n- **Readability**: Use short paragraphs, bullet points where appropriate\n- **CTA**: End with a clear call-to-action or thought-provoking question\n\n## Notes\n\n- Always wait for user approval at outlined checkpoints\n- Preserve all draft versions for history\n- Use web search for up-to-date information when URLs are provided\n- If resources are insufficient, ask user for more or suggest additional research\n- Adapt tone based on target audience (technical, general, business, etc.)\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","03-skills/brand-voice/SKILL.md":"---\nname: brand-voice\ndescription: Ensure all communication matches brand voice and tone guidelines. Use when creating marketing copy, customer communications, public-facing content, or when users mention brand voice, tone, or writing style.\nuser-invocable: false\n---\n\n# Brand Voice Skill\n\n## Overview\nThis skill ensures all communications maintain consistent brand voice, tone, and messaging.\n\n## Brand Identity\n\n### Mission\nHelp teams automate their development workflows with AI\n\n### Values\n- **Simplicity**: Make complex things simple\n- **Reliability**: Rock-solid execution\n- **Empowerment**: Enable human creativity\n\n### Tone of Voice\n- **Friendly but professional** - approachable without being casual\n- **Clear and concise** - avoid jargon, explain technical concepts simply\n- **Confident** - we know what we're doing\n- **Empathetic** - understand user needs and pain points\n\n## Writing Guidelines\n\n### Do's ✅\n- Use \"you\" when addressing readers\n- Use active voice: \"Claude generates reports\" not \"Reports are generated by Claude\"\n- Start with value proposition\n- Use concrete examples\n- Keep sentences under 20 words\n- Use lists for clarity\n- Include calls-to-action\n\n### Don'ts ❌\n- Don't use corporate jargon\n- Don't patronize or oversimplify\n- Don't use \"we believe\" or \"we think\"\n- Don't use ALL CAPS except for emphasis\n- Don't create walls of text\n- Don't assume technical knowledge\n\n## Vocabulary\n\n### ✅ Preferred Terms\n- Claude (not \"the Claude AI\")\n- Code generation (not \"auto-coding\")\n- Agent (not \"bot\")\n- Streamline (not \"revolutionize\")\n- Integrate (not \"synergize\")\n\n### ❌ Avoid Terms\n- \"Cutting-edge\" (overused)\n- \"Game-changer\" (vague)\n- \"Leverage\" (corporate-speak)\n- \"Utilize\" (use \"use\")\n- \"Paradigm shift\" (unclear)\n\n## Examples\n\n### ✅ Good Example\n\"Claude automates your code review process. Instead of manually checking each PR, Claude reviews security, performance, and quality—saving your team hours every week.\"\n\nWhy it works: Clear value, specific benefits, action-oriented\n\n### ❌ Bad Example\n\"Claude leverages cutting-edge AI to provide comprehensive software development solutions.\"\n\nWhy it doesn't work: Vague, corporate jargon, no specific value\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","03-skills/claude-md/SKILL.md":"---\nname: claude-md\ndescription: Create or update CLAUDE.md files following best practices for optimal AI agent onboarding\n---\n\n## User Input\n\n```text\n$ARGUMENTS\n```\n\nYou **MUST** consider the user input before proceeding (if not empty). User may specify:\n- `create` - Create new CLAUDE.md from scratch\n- `update` - Improve existing CLAUDE.md\n- `audit` - Analyze and report on current CLAUDE.md quality\n- A specific path to create/update (e.g., `src/api/CLAUDE.md` for directory-specific instructions)\n\n## Core Principles\n\n**LLMs are stateless**: CLAUDE.md is the main project file loaded into every conversation (alongside auto memory and unscoped rules). It serves as the primary onboarding document for AI agents into your codebase.\n\n### The Golden Rules\n\n1. **Less is More**: Frontier LLMs can follow ~150-200 instructions. Claude Code's system prompt already uses ~50. Keep your CLAUDE.md focused and concise.\n\n2. **Universal Applicability**: Only include information relevant to EVERY session. Task-specific instructions belong in separate files.\n\n3. **Don't Use Claude as a Linter**: Style guidelines bloat context and degrade instruction-following. Use deterministic tools (prettier, eslint, etc.) instead.\n\n4. **Never Auto-Generate**: CLAUDE.md is the highest leverage point of the AI harness. Craft it manually with careful consideration.\n\n## Execution Flow\n\n### 1. Project Analysis\n\nFirst, analyze the current project state:\n\n1. Check for existing CLAUDE.md files:\n   - Root level: `./CLAUDE.md` or `.claude/CLAUDE.md`\n   - Directory-specific: `**/CLAUDE.md`\n   - Global user config: `~/.claude/CLAUDE.md`\n\n2. Identify the project structure:\n   - Technology stack (languages, frameworks)\n   - Project type (monorepo, single app, library)\n   - Development tools (package manager, build system, test runner)\n\n3. Review existing documentation:\n   - README.md\n   - CONTRIBUTING.md\n   - package.json, pyproject.toml, Cargo.toml, etc.\n\n### 2. Content Strategy (WHAT, WHY, HOW)\n\nStructure CLAUDE.md around three dimensions:\n\n#### WHAT - Technology & Structure\n- Technology stack overview\n- Project organization (especially important for monorepos)\n- Key directories and their purposes\n\n#### WHY - Purpose & Context\n- What the project does\n- Why certain architectural decisions were made\n- What each major component is responsible for\n\n#### HOW - Workflow & Conventions\n- Development workflow (bun vs node, pip vs uv, etc.)\n- Testing procedures and commands\n- Verification and build methods\n- Critical \"gotchas\" or non-obvious requirements\n\n### 3. Progressive Disclosure Strategy\n\nFor larger projects, recommend creating an `agent_docs/` folder:\n\n```\nagent_docs/\n  |- building_the_project.md\n  |- running_tests.md\n  |- code_conventions.md\n  |- architecture_decisions.md\n```\n\nIn CLAUDE.md, reference these files with instructions like:\n```markdown\nFor detailed build instructions, refer to `agent_docs/building_the_project.md`\n```\n\n**Important**: Use `file:line` references instead of code snippets to avoid outdated context.\n\n### 4. Quality Constraints\n\nWhen creating or updating CLAUDE.md:\n\n1. **Target Length**: Keep it under 200 lines; shorter is better\n2. **No Style Rules**: Remove any linting/formatting instructions\n3. **No Task-Specific Instructions**: Move to separate files\n4. **No Code Snippets**: Use file references instead\n5. **No Redundant Information**: Don't repeat what's in package.json or README\n\n### 5. Essential Sections\n\nA well-structured CLAUDE.md should include:\n\n```markdown\n# Project Name\n\nBrief one-line description.\n\n## Tech Stack\n- Primary language and version\n- Key frameworks/libraries\n- Database/storage (if any)\n\n## Project Structure\n[Only for monorepos or complex structures]\n- `apps/` - Application entry points\n- `packages/` - Shared libraries\n\n## Development Commands\n- Install: `command`\n- Test: `command`\n- Build: `command`\n\n## Critical Conventions\n[Only non-obvious, high-impact conventions]\n- Convention 1 with brief explanation\n- Convention 2 with brief explanation\n\n## Known Issues / Gotchas\n[Things that consistently trip up developers]\n- Issue 1\n- Issue 2\n```\n\n### 6. Anti-Patterns to Avoid\n\n**DO NOT include:**\n- Code style guidelines (use linters)\n- Documentation on how to use Claude\n- Long explanations of obvious patterns\n- Copy-pasted code examples\n- Generic best practices (\"write clean code\")\n- Instructions for specific tasks\n- Auto-generated content\n- Extensive TODO lists\n\n### 7. Validation Checklist\n\nBefore finalizing, verify:\n\n- [ ] Kept under 200 lines; shorter is better\n- [ ] Every line applies to ALL sessions\n- [ ] No style/formatting rules\n- [ ] No code snippets (use file references)\n- [ ] Commands are verified to work\n- [ ] Progressive disclosure used for complex projects\n- [ ] Critical gotchas are documented\n- [ ] No redundancy with README.md\n\n## Output Format\n\n### For `create` or default:\n\n1. Analyze the project\n2. Draft a CLAUDE.md following the structure above\n3. Present the draft for review\n4. Write to the appropriate location after approval\n\n### For `update`:\n\n1. Read existing CLAUDE.md\n2. Audit against best practices\n3. Identify:\n   - Content to remove (style rules, code snippets, task-specific)\n   - Content to condense\n   - Missing essential information\n4. Present changes for review\n5. Apply changes after approval\n\n### For `audit`:\n\n1. Read existing CLAUDE.md\n2. Generate a report with:\n   - Current line count vs target\n   - Percentage of universally-applicable content\n   - List of anti-patterns found\n   - Recommendations for improvement\n3. Do NOT modify the file, only report\n\n## AGENTS.md Handling\n\nIf the user requests AGENTS.md creation/update:\n\n**Since v2.1.277, Claude Code reads `AGENTS.md` directly as project instructions** — but only when the working directory and every directory above it contain no `CLAUDE.md`, `.claude/CLAUDE.md`, or `CLAUDE.local.md`. `~/.claude/CLAUDE.md`, managed CLAUDE.md, and `.claude/rules/` do not count for that check and keep loading alongside. Which files are read is controlled by **Project instructions** in `/config`: `claude-md-or-agents-md` (default), `claude-md-and-agents-md`, `claude-md`, or `managed-only`. Where direct reading is unavailable — versions before v2.1.277 (before v2.1.281 on Bedrock/Vertex/Foundry, LLM gateways, or with telemetry disabled), or the first session after upgrading — fall back to importing it from CLAUDE.md with `@AGENTS.md`, or symlinking `CLAUDE.md` to it.\n\nAGENTS.md is a cross-tool project-context file — the same *category* of document as CLAUDE.md, not an agent-definition format. It exists so several coding agents can share one set of project conventions:\n- Build, test, and lint commands\n- Code style and architectural conventions\n- Repository layout and where things live\n\nSubagents are defined separately, in `.claude/agents/*.md` — not in AGENTS.md.\n\nApply similar principles:\n- Keep focused and concise\n- Use progressive disclosure\n- Reference external docs instead of embedding content\n\n## Notes\n\n- Always verify commands work before including them\n- When in doubt, leave it out - less is more\n- The system reminder tells Claude that CLAUDE.md \"may or may not be relevant\" - the more noise, the more it gets ignored\n- Monorepos benefit most from clear WHAT/WHY/HOW structure\n- Directory-specific CLAUDE.md files should be even more focused\n\n---\n\n**Last Updated**: October 18, 2026\n**Claude Code Version**: 2.1.302\n**Sources**:\n- https://code.claude.com/docs/en/skills\n- https://code.claude.com/docs/en/memory#agents-md\n- https://code.claude.com/docs/en/memory#when-agents-md-support-is-unavailable\n- https://code.claude.com/docs/en/memory\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","03-skills/code-review-specialist/SKILL.md":"---\nname: code-review-specialist\ndescription: Comprehensive code review with security, performance, and quality analysis. Use when users ask to review code, analyze code quality, evaluate pull requests, or mention code review, security analysis, or performance optimization.\n---\n\n# Code Review Skill\n\nThis skill provides comprehensive code review capabilities focusing on:\n\n1. **Security Analysis**\n   - Authentication/authorization issues\n   - Data exposure risks\n   - Injection vulnerabilities\n   - Cryptographic weaknesses\n   - Sensitive data logging\n\n2. **Performance Review**\n   - Algorithm efficiency (Big O analysis)\n   - Memory optimization\n   - Database query optimization\n   - Caching opportunities\n   - Concurrency issues\n\n3. **Code Quality**\n   - SOLID principles\n   - Design patterns\n   - Naming conventions\n   - Documentation\n   - Test coverage\n\n4. **Maintainability**\n   - Code readability\n   - Function size (should be < 50 lines)\n   - Cyclomatic complexity\n   - Dependency management\n   - Type safety\n\n## Reference Files\n\nThis skill includes supporting files that you should read when performing reviews:\n\n- **`templates/review-checklist.md`** — Structured checklist covering security, performance, quality, and testing. Read this file and use it as a guide to ensure no category is missed during review.\n- **`templates/finding-template.md`** — Standard template for documenting individual findings with severity, location, code examples, and impact analysis. Read this file and use its format when reporting issues.\n- **`scripts/analyze-metrics.py`** — Python script that calculates code metrics (function count, class count, average line length, complexity score). Run this on the file under review to gather quantitative data.\n- **`scripts/compare-complexity.py`** — Python script that compares cyclomatic and cognitive complexity between two versions of a file. Run this with the before and after versions when reviewing refactoring changes.\n\n## Review Template\n\nFor each piece of code reviewed, provide:\n\n### Summary\n- Overall quality assessment (1-5)\n- Key findings count\n- Recommended priority areas\n\n### Critical Issues (if any)\n- **Issue**: Clear description\n- **Location**: File and line number\n- **Impact**: Why this matters\n- **Severity**: Critical/High/Medium\n- **Fix**: Code example\n\n### Findings by Category\n\n#### Security (if issues found)\nList security vulnerabilities with examples\n\n#### Performance (if issues found)\nList performance problems with complexity analysis\n\n#### Quality (if issues found)\nList code quality issues with refactoring suggestions\n\n#### Maintainability (if issues found)\nList maintainability problems with improvements\n\n## Version History\n\n- v1.0.0 (2024-12-10): Initial release with security, performance, quality, and maintainability analysis\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","03-skills/doc-generator/SKILL.md":"---\nname: doc-generator\ndescription: Generate comprehensive, accurate API documentation from source code. Use when creating or updating API documentation, generating OpenAPI specs, or when users mention API docs, endpoints, or documentation.\n---\n\n# API Documentation Generator Skill\n\n## Generates\n\n- OpenAPI/Swagger specifications\n- API endpoint documentation\n- SDK usage examples\n- Integration guides\n- Error code references\n- Authentication guides\n\n## Documentation Structure\n\n### For Each Endpoint\n\n````markdown\n## GET /api/v1/users/:id\n\n### Description\nBrief explanation of what this endpoint does\n\n### Parameters\n\n| Name | Type | Required | Description |\n|------|------|----------|-------------|\n| id | string | Yes | User ID |\n\n### Response\n\n**200 Success**\n```json\n{\n  \"id\": \"usr_123\",\n  \"name\": \"John Doe\",\n  \"email\": \"john@example.com\",\n  \"created_at\": \"2025-01-15T10:30:00Z\"\n}\n```\n\n**404 Not Found**\n```json\n{\n  \"error\": \"USER_NOT_FOUND\",\n  \"message\": \"User does not exist\"\n}\n```\n\n### Examples\n\n**cURL**\n```bash\ncurl -X GET \"https://api.example.com/api/v1/users/usr_123\" \\\n  -H \"Authorization: Bearer YOUR_TOKEN\"\n```\n\n**JavaScript**\n```javascript\nconst user = await fetch('/api/v1/users/usr_123', {\n  headers: { 'Authorization': 'Bearer token' }\n}).then(r => r.json());\n```\n\n**Python**\n```python\nresponse = requests.get(\n    'https://api.example.com/api/v1/users/usr_123',\n    headers={'Authorization': 'Bearer token'}\n)\nuser = response.json()\n```\n````\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","03-skills/refactor/SKILL.md":"---\nname: refactor\ndescription: Systematic code refactoring based on Martin Fowler's methodology. Use when users ask to refactor code, improve code structure, reduce technical debt, clean up legacy code, eliminate code smells, or improve code maintainability. This skill guides through a phased approach with research, planning, and safe incremental implementation.\n---\n\n# Code Refactoring Skill\n\nA systematic approach to refactoring code based on Martin Fowler's *Refactoring: Improving the Design of Existing Code* (2nd Edition). This skill emphasizes safe, incremental changes backed by tests.\n\n> \"Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure.\" — Martin Fowler\n\n## Core Principles\n\n1. **Behavior Preservation**: External behavior must remain unchanged\n2. **Small Steps**: Make tiny, testable changes\n3. **Test-Driven**: Tests are the safety net\n4. **Continuous**: Refactoring is ongoing, not a one-time event\n5. **Collaborative**: User approval required at each phase\n\n## Workflow Overview\n\n```\nPhase 1: Research & Analysis\n    ↓\nPhase 2: Test Coverage Assessment\n    ↓\nPhase 3: Code Smell Identification\n    ↓\nPhase 4: Refactoring Plan Creation\n    ↓\nPhase 5: Incremental Implementation\n    ↓\nPhase 6: Review & Iteration\n```\n\n---\n\n## Phase 1: Research & Analysis\n\n### Objectives\n- Understand the codebase structure and purpose\n- Identify the scope of refactoring\n- Gather context about business requirements\n\n### Questions to Ask User\nBefore starting, clarify:\n\n1. **Scope**: Which files/modules/functions need refactoring?\n2. **Goals**: What problems are you trying to solve? (readability, performance, maintainability)\n3. **Constraints**: Are there any areas that should NOT be changed?\n4. **Timeline pressure**: Is this blocking other work?\n5. **Test status**: Do tests exist? Are they passing?\n\n### Actions\n- [ ] Read and understand the target code\n- [ ] Identify dependencies and integrations\n- [ ] Document current architecture\n- [ ] Note any existing technical debt markers (TODOs, FIXMEs)\n\n### Output\nPresent findings to user:\n- Code structure summary\n- Identified problem areas\n- Initial recommendations\n- **Request approval to proceed**\n\n---\n\n## Phase 2: Test Coverage Assessment\n\n### Why Tests Matter\n> \"Refactoring without tests is like driving without a seatbelt.\" — Martin Fowler\n\nTests are the **key enabler** of safe refactoring. Without them, you risk introducing bugs.\n\n### Assessment Steps\n\n1. **Check for existing tests**\n   ```bash\n   # Look for test files\n   find . -name \"*test*\" -o -name \"*spec*\" | head -20\n   ```\n\n2. **Run existing tests**\n   ```bash\n   # JavaScript/TypeScript\n   npm test\n\n   # Python\n   pytest -v\n\n   # Java\n   mvn test\n   ```\n\n3. **Check coverage (if available)**\n   ```bash\n   # JavaScript\n   npm run test:coverage\n\n   # Python\n   pytest --cov=.\n   ```\n\n### Decision Point: Ask User\n\n**If tests exist and pass:**\n- Proceed to Phase 3\n\n**If tests are missing or incomplete:**\nPresent options:\n1. Write tests first (recommended)\n2. Add tests incrementally during refactoring\n3. Proceed without tests (risky - requires user acknowledgment)\n\n**If tests are failing:**\n- STOP. Fix failing tests before refactoring\n- Ask user: Should we fix tests first?\n\n### Test Writing Guidelines (if needed)\n\nFor each function being refactored, ensure tests cover:\n- Happy path (normal operation)\n- Edge cases (empty inputs, null, boundaries)\n- Error scenarios (invalid inputs, exceptions)\n\nUse the \"red-green-refactor\" cycle:\n1. Write failing test (red)\n2. Make it pass (green)\n3. Refactor\n\n---\n\n## Phase 3: Code Smell Identification\n\n### What Are Code Smells?\nSymptoms of deeper problems in code. They're not bugs, but indicators that the code could be improved.\n\n### Common Code Smells to Check\n\nSee [references/code-smells.md](references/code-smells.md) for the complete catalog.\n\n#### Quick Reference\n\n| Smell | Signs | Impact |\n|-------|-------|--------|\n| **Long Method** | Methods > 30-50 lines | Hard to understand, test, maintain |\n| **Duplicated Code** | Same logic in multiple places | Bug fixes needed in multiple places |\n| **Large Class** | Class with too many responsibilities | Violates Single Responsibility |\n| **Feature Envy** | Method uses another class's data more | Poor encapsulation |\n| **Primitive Obsession** | Overuse of primitives instead of objects | Missing domain concepts |\n| **Long Parameter List** | Methods with 4+ parameters | Hard to call correctly |\n| **Data Clumps** | Same data items appearing together | Missing abstraction |\n| **Switch Statements** | Complex switch/if-else chains | Hard to extend |\n| **Speculative Generality** | Code \"just in case\" | Unnecessary complexity |\n| **Dead Code** | Unused code | Confusion, maintenance burden |\n\n### Analysis Steps\n\n1. **Automated Analysis** (if scripts available)\n   ```bash\n   python scripts/detect-smells.py <file>\n   ```\n\n2. **Manual Review**\n   - Walk through code systematically\n   - Note each smell with location and severity\n   - Categorize by impact (Critical/High/Medium/Low)\n\n3. **Prioritization**\n   Focus on smells that:\n   - Block current development\n   - Cause bugs or confusion\n   - Affect most-changed code paths\n\n### Output: Smell Report\n\nPresent to user:\n- List of identified smells with locations\n- Severity assessment for each\n- Recommended priority order\n- **Request approval on priorities**\n\n---\n\n## Phase 4: Refactoring Plan Creation\n\n### Selecting Refactorings\n\nFor each smell, select an appropriate refactoring from the catalog.\n\nSee [references/refactoring-catalog.md](references/refactoring-catalog.md) for the complete list.\n\n#### Smell-to-Refactoring Mapping\n\n| Code Smell | Recommended Refactoring(s) |\n|------------|---------------------------|\n| Long Method | Extract Method, Replace Temp with Query |\n| Duplicated Code | Extract Method, Pull Up Method, Form Template Method |\n| Large Class | Extract Class, Extract Subclass |\n| Feature Envy | Move Method, Move Field |\n| Primitive Obsession | Replace Primitive with Object, Replace Type Code with Class |\n| Long Parameter List | Introduce Parameter Object, Preserve Whole Object |\n| Data Clumps | Extract Class, Introduce Parameter Object |\n| Switch Statements | Replace Conditional with Polymorphism |\n| Speculative Generality | Collapse Hierarchy, Inline Class, Remove Dead Code |\n| Dead Code | Remove Dead Code |\n\n### Plan Structure\n\nUse the template at [templates/refactoring-plan.md](templates/refactoring-plan.md).\n\nFor each refactoring:\n1. **Target**: What code will change\n2. **Smell**: What problem it addresses\n3. **Refactoring**: Which technique to apply\n4. **Steps**: Detailed micro-steps\n5. **Risks**: What could go wrong\n6. **Rollback**: How to undo if needed\n\n### Phased Approach\n\n**CRITICAL**: Introduce refactoring gradually in phases.\n\n**Phase A: Quick Wins** (Low risk, high value)\n- Rename variables for clarity\n- Extract obvious duplicate code\n- Remove dead code\n\n**Phase B: Structural Improvements** (Medium risk)\n- Extract methods from long functions\n- Introduce parameter objects\n- Move methods to appropriate classes\n\n**Phase C: Architectural Changes** (Higher risk)\n- Replace conditionals with polymorphism\n- Extract classes\n- Introduce design patterns\n\n### Decision Point: Present Plan to User\n\nBefore implementation:\n- Show complete refactoring plan\n- Explain each phase and its risks\n- Get explicit approval for each phase\n- **Ask**: \"Should I proceed with Phase A?\"\n\n---\n\n## Phase 5: Incremental Implementation\n\n### The Golden Rule\n> \"Change → Test → Green? → Commit → Next step\"\n\n### Implementation Rhythm\n\nFor each refactoring step:\n\n1. **Pre-check**\n   - Tests are passing (green)\n   - Code compiles\n\n2. **Make ONE small change**\n   - Follow the mechanics from the catalog\n   - Keep changes minimal\n\n3. **Verify**\n   - Run tests immediately\n   - Check for compilation errors\n\n4. **If tests pass (green)**\n   - Commit with descriptive message\n   - Move to next step\n\n5. **If tests fail (red)**\n   - STOP immediately\n   - Undo the change\n   - Analyze what went wrong\n   - Ask user if unclear\n\n### Commit Strategy\n\nEach commit should be:\n- **Atomic**: One logical change\n- **Reversible**: Easy to revert\n- **Descriptive**: Clear commit message\n\nExample commit messages:\n```\nrefactor: Extract calculateTotal() from processOrder()\nrefactor: Rename 'x' to 'customerCount' for clarity\nrefactor: Remove unused validateOldFormat() method\n```\n\n### Progress Reporting\n\nAfter each sub-phase, report to user:\n- Changes made\n- Tests still passing?\n- Any issues encountered\n- **Ask**: \"Continue with next batch?\"\n\n---\n\n## Phase 6: Review & Iteration\n\n### Post-Refactoring Checklist\n\n- [ ] All tests passing\n- [ ] No new warnings/errors\n- [ ] Code compiles successfully\n- [ ] Behavior unchanged (manual verification)\n- [ ] Documentation updated if needed\n- [ ] Commit history is clean\n\n### Metrics Comparison\n\nRun complexity analysis before and after:\n```bash\npython scripts/analyze-complexity.py <file>\n```\n\nPresent improvements:\n- Lines of code change\n- Cyclomatic complexity change\n- Maintainability index change\n\n### User Review\n\nPresent final results:\n- Summary of all changes\n- Before/after code comparison\n- Metrics improvements\n- Remaining technical debt\n- **Ask**: \"Are you satisfied with these changes?\"\n\n### Next Steps\n\nDiscuss with user:\n- Additional smells to address?\n- Schedule follow-up refactoring?\n- Apply similar changes elsewhere?\n\n---\n\n## Important Guidelines\n\n### When to STOP and Ask\n\nAlways pause and consult user when:\n- Unsure about business logic\n- Change might affect external APIs\n- Test coverage is inadequate\n- Significant architectural decision needed\n- Risk level increases\n- You encounter unexpected complexity\n\n### Safety Rules\n\n1. **Never refactor without tests** (unless user explicitly acknowledges risk)\n2. **Never make big changes** - break into tiny steps\n3. **Never skip the test run** after each change\n4. **Never continue if tests fail** - fix or rollback first\n5. **Never assume** - when in doubt, ask\n\n### What NOT to Do\n\n- Don't combine refactoring with feature additions\n- Don't refactor during production emergencies\n- Don't refactor code you don't understand\n- Don't over-engineer - keep it simple\n- Don't refactor everything at once\n\n---\n\n## Quick Start Example\n\n### Scenario: Long Method with Duplication\n\n**Before:**\n```javascript\nfunction processOrder(order) {\n  // 150 lines of code with:\n  // - Duplicated validation logic\n  // - Inline calculations\n  // - Mixed responsibilities\n}\n```\n\n**Refactoring Steps:**\n\n1. **Ensure tests exist** for processOrder()\n2. **Extract** validation into validateOrder()\n3. **Test** - should pass\n4. **Extract** calculation into calculateOrderTotal()\n5. **Test** - should pass\n6. **Extract** notification into notifyCustomer()\n7. **Test** - should pass\n8. **Review** - processOrder() now orchestrates 3 clear functions\n\n**After:**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const total = calculateOrderTotal(order);\n  notifyCustomer(order, total);\n  return { order, total };\n}\n```\n\n---\n\n## References\n\n- [Code Smells Catalog](references/code-smells.md) - Complete list of code smells\n- [Refactoring Catalog](references/refactoring-catalog.md) - Refactoring techniques\n- [Refactoring Plan Template](templates/refactoring-plan.md) - Planning template\n\n## Scripts\n\n- `scripts/analyze-complexity.py` - Analyze code complexity metrics\n- `scripts/detect-smells.py` - Automated smell detection\n\n## Version History\n\n- v1.0.0 (2025-01-15): Initial release with Fowler methodology, phased approach, user consultation points\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","03-skills/refactor/references/code-smells.md":"# Code Smells Catalog\n\nA comprehensive reference of code smells based on Martin Fowler's *Refactoring* (2nd Edition). Code smells are symptoms of deeper problems—they indicate that something might be wrong with your code's design.\n\n> \"A code smell is a surface indication that usually corresponds to a deeper problem in the system.\" — Martin Fowler\n\n---\n\n## Bloaters\n\nCode smells representing something that has grown too large to be handled effectively.\n\n### Long Method\n\n**Signs:**\n- Method exceeds 30-50 lines\n- Need to scroll to see the whole method\n- Multiple levels of nesting\n- Comments explaining what sections do\n\n**Why it's bad:**\n- Hard to understand\n- Difficult to test in isolation\n- Changes have unintended consequences\n- Duplicate logic hides inside\n\n**Refactorings:**\n- Extract Method\n- Replace Temp with Query\n- Introduce Parameter Object\n- Replace Method with Method Object\n- Decompose Conditional\n\n**Example (Before):**\n```javascript\nfunction processOrder(order) {\n  // Validate order (20 lines)\n  if (!order.items) throw new Error('No items');\n  if (order.items.length === 0) throw new Error('Empty order');\n  // ... more validation\n\n  // Calculate totals (30 lines)\n  let subtotal = 0;\n  for (const item of order.items) {\n    subtotal += item.price * item.quantity;\n  }\n  // ... tax, shipping, discounts\n\n  // Send notifications (20 lines)\n  // ... email logic\n}\n```\n\n**Example (After):**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const totals = calculateOrderTotals(order);\n  sendOrderNotifications(order, totals);\n  return { order, totals };\n}\n```\n\n---\n\n### Large Class\n\n**Signs:**\n- Class has many instance variables (>7-10)\n- Class has many methods (>15-20)\n- Class name is vague (Manager, Handler, Processor)\n- Methods don't use all instance variables\n\n**Why it's bad:**\n- Violates Single Responsibility Principle\n- Hard to test\n- Changes ripple through unrelated features\n- Difficult to reuse parts\n\n**Refactorings:**\n- Extract Class\n- Extract Subclass\n- Extract Interface\n\n**Detection:**\n```\nLines of code > 300\nNumber of methods > 15\nNumber of fields > 10\n```\n\n---\n\n### Primitive Obsession\n\n**Signs:**\n- Using primitives for domain concepts (string for email, int for money)\n- Arrays of primitives instead of objects\n- String constants for type codes\n- Magic numbers/strings\n\n**Why it's bad:**\n- No validation at type level\n- Logic scattered across codebase\n- Easy to pass wrong values\n- Missing domain concepts\n\n**Refactorings:**\n- Replace Primitive with Object\n- Replace Type Code with Class\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**Example (Before):**\n```javascript\nconst user = {\n  email: 'john@example.com',     // Just a string\n  phone: '1234567890',           // Just a string\n  status: 'active',              // Magic string\n  balance: 10050                 // Cents as integer\n};\n```\n\n**Example (After):**\n```javascript\nconst user = {\n  email: new Email('john@example.com'),\n  phone: new PhoneNumber('1234567890'),\n  status: UserStatus.ACTIVE,\n  balance: Money.cents(10050)\n};\n```\n\n---\n\n### Long Parameter List\n\n**Signs:**\n- Methods with 4+ parameters\n- Parameters that always appear together\n- Boolean flags changing method behavior\n- Null/undefined passed frequently\n\n**Why it's bad:**\n- Hard to call correctly\n- Parameter order confusion\n- Indicates method doing too much\n- Hard to add new parameters\n\n**Refactorings:**\n- Introduce Parameter Object\n- Preserve Whole Object\n- Replace Parameter with Method Call\n- Remove Flag Argument\n\n**Example (Before):**\n```javascript\nfunction createUser(firstName, lastName, email, phone,\n                    street, city, state, zip,\n                    isAdmin, isActive, createdBy) {\n  // ...\n}\n```\n\n**Example (After):**\n```javascript\nfunction createUser(personalInfo, address, options) {\n  // personalInfo: { firstName, lastName, email, phone }\n  // address: { street, city, state, zip }\n  // options: { isAdmin, isActive, createdBy }\n}\n```\n\n---\n\n### Data Clumps\n\n**Signs:**\n- Same 3+ fields appear together repeatedly\n- Parameters that always travel together\n- Classes with field subsets belonging together\n\n**Why it's bad:**\n- Duplicate handling logic\n- Missing abstraction\n- Harder to extend\n- Indicates hidden class\n\n**Refactorings:**\n- Extract Class\n- Introduce Parameter Object\n- Preserve Whole Object\n\n**Example:**\n```javascript\n// Data clump: (x, y, z) coordinates\nfunction movePoint(x, y, z, dx, dy, dz) { }\nfunction scalePoint(x, y, z, factor) { }\nfunction distanceBetween(x1, y1, z1, x2, y2, z2) { }\n\n// Extract Point3D class\nclass Point3D {\n  constructor(x, y, z) { }\n  move(delta) { }\n  scale(factor) { }\n  distanceTo(other) { }\n}\n```\n\n---\n\n## Object-Orientation Abusers\n\nSmells indicating incomplete or incorrect use of OOP principles.\n\n### Switch Statements\n\n**Signs:**\n- Long switch/case or if/else chains\n- Same switch in multiple places\n- Switch on type codes\n- Adding new cases requires changes everywhere\n\n**Why it's bad:**\n- Violates Open/Closed Principle\n- Changes ripple to all switch locations\n- Hard to extend\n- Often indicates missing polymorphism\n\n**Refactorings:**\n- Replace Conditional with Polymorphism\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**Example (Before):**\n```javascript\nfunction calculatePay(employee) {\n  switch (employee.type) {\n    case 'hourly':\n      return employee.hours * employee.rate;\n    case 'salaried':\n      return employee.salary / 12;\n    case 'commissioned':\n      return employee.sales * employee.commission;\n  }\n}\n```\n\n**Example (After):**\n```javascript\nclass HourlyEmployee {\n  calculatePay() {\n    return this.hours * this.rate;\n  }\n}\n\nclass SalariedEmployee {\n  calculatePay() {\n    return this.salary / 12;\n  }\n}\n```\n\n---\n\n### Temporary Field\n\n**Signs:**\n- Instance variables only used in some methods\n- Fields set conditionally\n- Complex initialization for certain cases\n\n**Why it's bad:**\n- Confusing—field exists but might be null\n- Hard to understand object state\n- Indicates conditional logic hiding\n\n**Refactorings:**\n- Extract Class\n- Introduce Null Object\n- Replace Temp Field with Local\n\n---\n\n### Refused Bequest\n\n**Signs:**\n- Subclass doesn't use inherited methods/data\n- Subclass overrides to do nothing\n- Inheritance used for code reuse, not IS-A relationship\n\n**Why it's bad:**\n- Wrong abstraction\n- Violates Liskov Substitution Principle\n- Misleading hierarchy\n\n**Refactorings:**\n- Push Down Method/Field\n- Replace Subclass with Delegate\n- Replace Inheritance with Delegation\n\n---\n\n### Alternative Classes with Different Interfaces\n\n**Signs:**\n- Two classes that do similar things\n- Different method names for same concept\n- Could be used interchangeably\n\n**Why it's bad:**\n- Duplicate implementations\n- No common interface\n- Hard to switch between\n\n**Refactorings:**\n- Rename Method\n- Move Method\n- Extract Superclass\n- Extract Interface\n\n---\n\n## Change Preventers\n\nSmells that make changes difficult—changing one thing requires changing many others.\n\n### Divergent Change\n\n**Signs:**\n- One class changed for multiple different reasons\n- Changes in different areas trigger same class edits\n- Class is a \"God class\"\n\n**Why it's bad:**\n- Violates Single Responsibility\n- High change frequency\n- Merge conflicts\n\n**Refactorings:**\n- Extract Class\n- Extract Superclass\n- Extract Subclass\n\n**Example:**\nA `User` class changes for:\n- Authentication changes\n- Profile changes\n- Billing changes\n- Notification changes\n\n→ Extract: `AuthService`, `ProfileService`, `BillingService`, `NotificationService`\n\n---\n\n### Shotgun Surgery\n\n**Signs:**\n- One change requires edits in many classes\n- Small feature needs touching 10+ files\n- Changes are scattered, hard to find all\n\n**Why it's bad:**\n- Easy to miss a spot\n- High coupling\n- Changes are error-prone\n\n**Refactorings:**\n- Move Method\n- Move Field\n- Inline Class\n\n**Detection:**\nLook for: adding one field requires changes in >5 files.\n\n---\n\n### Parallel Inheritance Hierarchies\n\n**Signs:**\n- Creating subclass in one hierarchy requires subclass in another\n- Class prefixes match (e.g., `DatabaseOrder`, `DatabaseProduct`)\n\n**Why it's bad:**\n- Double the maintenance\n- Coupling between hierarchies\n- Easy to forget one side\n\n**Refactorings:**\n- Move Method\n- Move Field\n- Eliminate one hierarchy\n\n---\n\n## Dispensables\n\nSomething unnecessary that should be removed.\n\n### Comments (Excessive)\n\n**Signs:**\n- Comments explaining what code does\n- Commented-out code\n- TODO/FIXME that linger forever\n- Apologies in comments\n\n**Why it's bad:**\n- Comments lie (get out of sync)\n- Code should be self-documenting\n- Dead code causes confusion\n\n**Refactorings:**\n- Extract Method (name explains what)\n- Rename (clarity without comments)\n- Remove commented code\n- Introduce Assertion\n\n**Good vs Bad Comments:**\n```javascript\n// BAD: Explaining what\n// Loop through users and check if active\nfor (const user of users) {\n  if (user.status === 'active') { }\n}\n\n// GOOD: Explaining why\n// Active users only - inactive are handled by cleanup job\nconst activeUsers = users.filter(u => u.isActive);\n```\n\n---\n\n### Duplicate Code\n\n**Signs:**\n- Same code in multiple places\n- Similar code with small variations\n- Copy-paste patterns\n\n**Why it's bad:**\n- Bug fixes needed in multiple places\n- Inconsistency risk\n- Bloated codebase\n\n**Refactorings:**\n- Extract Method\n- Extract Class\n- Pull Up Method (in hierarchies)\n- Form Template Method\n\n**Detection Rule:**\nAny code duplicated 3+ times should be extracted.\n\n---\n\n### Lazy Class\n\n**Signs:**\n- Class doesn't do enough to justify existence\n- Wrapper with no added value\n- Result of over-engineering\n\n**Why it's bad:**\n- Maintenance overhead\n- Unnecessary indirection\n- Complexity without benefit\n\n**Refactorings:**\n- Inline Class\n- Collapse Hierarchy\n\n---\n\n### Dead Code\n\n**Signs:**\n- Unreachable code\n- Unused variables/methods/classes\n- Commented-out code\n- Code behind impossible conditions\n\n**Why it's bad:**\n- Confusion\n- Maintenance burden\n- Slows down understanding\n\n**Refactorings:**\n- Remove Dead Code\n- Safe Delete\n\n**Detection:**\n```bash\n# Look for unused exports\n# Look for unreferenced functions\n# IDE \"unused\" warnings\n```\n\n---\n\n### Speculative Generality\n\n**Signs:**\n- Abstract classes with one subclass\n- Unused parameters \"for future use\"\n- Methods that only delegate\n- \"Framework\" for one use case\n\n**Why it's bad:**\n- Complexity without benefit\n- YAGNI (You Ain't Gonna Need It)\n- Harder to understand\n\n**Refactorings:**\n- Collapse Hierarchy\n- Inline Class\n- Remove Parameter\n- Rename Method\n\n---\n\n## Couplers\n\nSmells that represent excessive coupling between classes.\n\n### Feature Envy\n\n**Signs:**\n- Method uses more data from another class than its own\n- Many getter calls to another object\n- Data and behavior are separated\n\n**Why it's bad:**\n- Wrong location for behavior\n- Poor encapsulation\n- Hard to maintain\n\n**Refactorings:**\n- Move Method\n- Move Field\n- Extract Method (then move)\n\n**Example (Before):**\n```javascript\nclass Order {\n  getDiscountedPrice(customer) {\n    // Uses customer data heavily\n    if (customer.loyaltyYears > 5) {\n      return this.price * customer.discountRate;\n    }\n    return this.price;\n  }\n}\n```\n\n**Example (After):**\n```javascript\nclass Customer {\n  getDiscountedPriceFor(price) {\n    if (this.loyaltyYears > 5) {\n      return price * this.discountRate;\n    }\n    return price;\n  }\n}\n```\n\n---\n\n### Inappropriate Intimacy\n\n**Signs:**\n- Classes access each other's private parts\n- Bidirectional references\n- Subclasses know too much about parents\n\n**Why it's bad:**\n- High coupling\n- Changes cascade\n- Hard to modify one without other\n\n**Refactorings:**\n- Move Method\n- Move Field\n- Change Bidirectional to Unidirectional\n- Extract Class\n- Hide Delegate\n\n---\n\n### Message Chains\n\n**Signs:**\n- Long chains of method calls: `a.getB().getC().getD().getValue()`\n- Client depends on navigation structure\n- \"Train wreck\" code\n\n**Why it's bad:**\n- Fragile—any change breaks chain\n- Violates Law of Demeter\n- Coupling to structure\n\n**Refactorings:**\n- Hide Delegate\n- Extract Method\n- Move Method\n\n**Example:**\n```javascript\n// Bad: Message chain\nconst managerName = employee.getDepartment().getManager().getName();\n\n// Better: Hide delegation\nconst managerName = employee.getManagerName();\n```\n\n---\n\n### Middle Man\n\n**Signs:**\n- Class that only delegates to another\n- Half the methods are delegations\n- No added value\n\n**Why it's bad:**\n- Unnecessary indirection\n- Maintenance overhead\n- Confusing architecture\n\n**Refactorings:**\n- Remove Middle Man\n- Inline Method\n\n---\n\n## Smell Severity Guide\n\n| Severity | Description | Action |\n|----------|-------------|--------|\n| **Critical** | Blocks development, causes bugs | Fix immediately |\n| **High** | Significant maintenance burden | Fix in current sprint |\n| **Medium** | Noticeable but manageable | Plan for near future |\n| **Low** | Minor inconvenience | Fix opportunistically |\n\n---\n\n## Quick Detection Checklist\n\nUse this checklist when scanning code:\n\n- [ ] Any method > 30 lines?\n- [ ] Any class > 300 lines?\n- [ ] Any method with > 4 parameters?\n- [ ] Any duplicated code blocks?\n- [ ] Any switch/case on type codes?\n- [ ] Any unused code?\n- [ ] Any methods using another class's data heavily?\n- [ ] Any long chains of method calls?\n- [ ] Any comments explaining \"what\" not \"why\"?\n- [ ] Any primitives that should be objects?\n\n---\n\n## Further Reading\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Kerievsky, J. (2004). *Refactoring to Patterns*\n- Feathers, M. (2004). *Working Effectively with Legacy Code*\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","03-skills/refactor/references/refactoring-catalog.md":"# Refactoring Catalog\n\nA curated catalog of refactoring techniques from Martin Fowler's *Refactoring* (2nd Edition). Each refactoring includes motivation, step-by-step mechanics, and examples.\n\n> \"A refactoring is defined by its mechanics—the precise sequence of steps that you follow to carry out the change.\" — Martin Fowler\n\n---\n\n## How to Use This Catalog\n\n1. **Identify the smell** using the code smells reference\n2. **Find the matching refactoring** in this catalog\n3. **Follow the mechanics** step by step\n4. **Test after each step** to ensure behavior is preserved\n\n**Golden Rule**: If any step takes more than 10 minutes, break it into smaller steps.\n\n---\n\n## Most Common Refactorings\n\n### Extract Method\n\n**When to use**: Long method, duplicate code, need to name a concept\n\n**Motivation**: Turn a code fragment into a method whose name explains the purpose.\n\n**Mechanics**:\n1. Create a new method named for what it does (not how)\n2. Copy the code fragment into the new method\n3. Scan for local variables used in the fragment\n4. Pass local variables as parameters (or declare in method)\n5. Handle return values appropriately\n6. Replace the original fragment with a call to the new method\n7. Test\n\n**Before**:\n```javascript\nfunction printOwing(invoice) {\n  let outstanding = 0;\n\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n\n  // Calculate outstanding\n  for (const order of invoice.orders) {\n    outstanding += order.amount;\n  }\n\n  // Print details\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n**After**:\n```javascript\nfunction printOwing(invoice) {\n  printBanner();\n  const outstanding = calculateOutstanding(invoice);\n  printDetails(invoice, outstanding);\n}\n\nfunction printBanner() {\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n}\n\nfunction calculateOutstanding(invoice) {\n  return invoice.orders.reduce((sum, order) => sum + order.amount, 0);\n}\n\nfunction printDetails(invoice, outstanding) {\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n---\n\n### Inline Method\n\n**When to use**: Method body is as clear as its name, excessive delegation\n\n**Motivation**: Remove needless indirection when the method doesn't add value.\n\n**Mechanics**:\n1. Check that the method isn't polymorphic\n2. Find all calls to the method\n3. Replace each call with the method body\n4. Test after each replacement\n5. Remove the method definition\n\n**Before**:\n```javascript\nfunction getRating(driver) {\n  return moreThanFiveLateDeliveries(driver) ? 2 : 1;\n}\n\nfunction moreThanFiveLateDeliveries(driver) {\n  return driver.numberOfLateDeliveries > 5;\n}\n```\n\n**After**:\n```javascript\nfunction getRating(driver) {\n  return driver.numberOfLateDeliveries > 5 ? 2 : 1;\n}\n```\n\n---\n\n### Extract Variable\n\n**When to use**: Complex expression that is hard to understand\n\n**Motivation**: Give a name to a piece of a complex expression.\n\n**Mechanics**:\n1. Ensure the expression has no side effects\n2. Declare an immutable variable\n3. Set it to the result of the expression (or part)\n4. Replace the original expression with the variable\n5. Test\n\n**Before**:\n```javascript\nreturn order.quantity * order.itemPrice -\n  Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +\n  Math.min(order.quantity * order.itemPrice * 0.1, 100);\n```\n\n**After**:\n```javascript\nconst basePrice = order.quantity * order.itemPrice;\nconst quantityDiscount = Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;\nconst shipping = Math.min(basePrice * 0.1, 100);\nreturn basePrice - quantityDiscount + shipping;\n```\n\n---\n\n### Inline Variable\n\n**When to use**: Variable name doesn't communicate more than the expression\n\n**Motivation**: Remove unnecessary indirection.\n\n**Mechanics**:\n1. Check that the right-hand side has no side effects\n2. If variable isn't immutable, make it so and test\n3. Find the first reference and replace with the expression\n4. Test\n5. Repeat for all references\n6. Remove the declaration and assignment\n7. Test\n\n---\n\n### Rename Variable\n\n**When to use**: Name doesn't clearly communicate purpose\n\n**Motivation**: Good names are crucial for clean code.\n\n**Mechanics**:\n1. If variable is widely used, consider encapsulating\n2. Find all references\n3. Change each reference\n4. Test\n\n**Tips**:\n- Use intention-revealing names\n- Avoid abbreviations\n- Use domain terminology\n\n```javascript\n// Bad\nconst d = 30;\nconst x = users.filter(u => u.a);\n\n// Good\nconst daysSinceLastLogin = 30;\nconst activeUsers = users.filter(user => user.isActive);\n```\n\n---\n\n### Change Function Declaration\n\n**When to use**: Function name doesn't explain purpose, parameters need change\n\n**Motivation**: Good function names make code self-documenting.\n\n**Mechanics (Simple)**:\n1. Remove parameters not needed\n2. Change the name\n3. Add parameters needed\n4. Test\n\n**Mechanics (Migration - for complex changes)**:\n1. If removing parameter, make sure it's not used\n2. Create new function with desired declaration\n3. Have old function call new function\n4. Test\n5. Change callers to use new function\n6. Test after each\n7. Remove old function\n\n**Before**:\n```javascript\nfunction circum(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n**After**:\n```javascript\nfunction circumference(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n---\n\n### Encapsulate Variable\n\n**When to use**: Direct access to data from multiple places\n\n**Motivation**: Provide a clear access point for data manipulation.\n\n**Mechanics**:\n1. Create getter and setter functions\n2. Find all references\n3. Replace reads with getter\n4. Replace writes with setter\n5. Test after each change\n6. Restrict visibility of the variable\n\n**Before**:\n```javascript\nlet defaultOwner = { firstName: \"Martin\", lastName: \"Fowler\" };\n\n// Used in many places\nspaceship.owner = defaultOwner;\n```\n\n**After**:\n```javascript\nlet defaultOwnerData = { firstName: \"Martin\", lastName: \"Fowler\" };\n\nfunction defaultOwner() { return defaultOwnerData; }\nfunction setDefaultOwner(arg) { defaultOwnerData = arg; }\n\nspaceship.owner = defaultOwner();\n```\n\n---\n\n### Introduce Parameter Object\n\n**When to use**: Several parameters that frequently go together\n\n**Motivation**: Group data that naturally belongs together.\n\n**Mechanics**:\n1. Create a new class/structure for the grouped parameters\n2. Test\n3. Use Change Function Declaration to add the new object\n4. Test\n5. For each parameter in the group, remove it from the function and use the new object\n6. Test after each\n\n**Before**:\n```javascript\nfunction amountInvoiced(startDate, endDate) { ... }\nfunction amountReceived(startDate, endDate) { ... }\nfunction amountOverdue(startDate, endDate) { ... }\n```\n\n**After**:\n```javascript\nclass DateRange {\n  constructor(start, end) {\n    this.start = start;\n    this.end = end;\n  }\n}\n\nfunction amountInvoiced(dateRange) { ... }\nfunction amountReceived(dateRange) { ... }\nfunction amountOverdue(dateRange) { ... }\n```\n\n---\n\n### Combine Functions into Class\n\n**When to use**: Several functions operate on the same data\n\n**Motivation**: Group functions with the data they operate on.\n\n**Mechanics**:\n1. Apply Encapsulate Record to the common data\n2. Move each function into the class\n3. Test after each move\n4. Replace data arguments with uses of class fields\n\n**Before**:\n```javascript\nfunction base(reading) { ... }\nfunction taxableCharge(reading) { ... }\nfunction calculateBaseCharge(reading) { ... }\n```\n\n**After**:\n```javascript\nclass Reading {\n  constructor(data) { this._data = data; }\n\n  get base() { ... }\n  get taxableCharge() { ... }\n  get calculateBaseCharge() { ... }\n}\n```\n\n---\n\n### Split Phase\n\n**When to use**: Code deals with two different things\n\n**Motivation**: Separate code into distinct phases with clear boundaries.\n\n**Mechanics**:\n1. Create a second function for the second phase\n2. Test\n3. Introduce an intermediate data structure between phases\n4. Test\n5. Extract first phase into its own function\n6. Test\n\n**Before**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  const shippingPerCase = (basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = quantity * shippingPerCase;\n  return basePrice - discount + shippingCost;\n}\n```\n\n**After**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const priceData = calculatePricingData(product, quantity);\n  return applyShipping(priceData, shippingMethod);\n}\n\nfunction calculatePricingData(product, quantity) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  return { basePrice, quantity, discount };\n}\n\nfunction applyShipping(priceData, shippingMethod) {\n  const shippingPerCase = (priceData.basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = priceData.quantity * shippingPerCase;\n  return priceData.basePrice - priceData.discount + shippingCost;\n}\n```\n\n---\n\n## Moving Features\n\n### Move Method\n\n**When to use**: Method uses more features of another class than its own\n\n**Motivation**: Put functions with the data they use most.\n\n**Mechanics**:\n1. Examine all program elements used by method in its class\n2. Check if method is polymorphic\n3. Copy method to target class\n4. Adjust for new context\n5. Make original method delegate to target\n6. Test\n7. Consider removing original method\n\n---\n\n### Move Field\n\n**When to use**: Field is used more by another class\n\n**Motivation**: Keep data with the functions that use it.\n\n**Mechanics**:\n1. Encapsulate the field if not already\n2. Test\n3. Create field in target\n4. Update references to use target field\n5. Test\n6. Remove original field\n\n---\n\n### Move Statements into Function\n\n**When to use**: Same code always appears with a function call\n\n**Motivation**: Remove duplication by moving repeated code into the function.\n\n**Mechanics**:\n1. Extract the repeated code into a function if not already\n2. Move statements into that function\n3. Test\n4. If callers no longer need standalone statements, remove them\n\n---\n\n### Move Statements to Callers\n\n**When to use**: Common behavior varies between callers\n\n**Motivation**: When behavior needs to differ, move it out of the function.\n\n**Mechanics**:\n1. Use Extract Method on the code to move\n2. Use Inline Method on the original function\n3. Remove the now-inlined call\n4. Move extracted code to each caller\n5. Test\n\n---\n\n## Organizing Data\n\n### Replace Primitive with Object\n\n**When to use**: Data item needs more behavior than simple value\n\n**Motivation**: Encapsulate data with its behavior.\n\n**Mechanics**:\n1. Apply Encapsulate Variable\n2. Create a simple value class\n3. Change the setter to create a new instance\n4. Change the getter to return the value\n5. Test\n6. Add richer behavior to the new class\n\n**Before**:\n```javascript\nclass Order {\n  constructor(data) {\n    this.priority = data.priority; // string: \"high\", \"rush\", etc.\n  }\n}\n\n// Usage\nif (order.priority === \"high\" || order.priority === \"rush\") { ... }\n```\n\n**After**:\n```javascript\nclass Priority {\n  constructor(value) {\n    if (!Priority.legalValues().includes(value))\n      throw new Error(`Invalid priority: ${value}`);\n    this._value = value;\n  }\n\n  static legalValues() { return ['low', 'normal', 'high', 'rush']; }\n  get value() { return this._value; }\n\n  higherThan(other) {\n    return Priority.legalValues().indexOf(this._value) >\n           Priority.legalValues().indexOf(other._value);\n  }\n}\n\n// Usage\nif (order.priority.higherThan(new Priority(\"normal\"))) { ... }\n```\n\n---\n\n### Replace Temp with Query\n\n**When to use**: Temporary variable holds result of an expression\n\n**Motivation**: Make the code clearer by extracting the expression into a function.\n\n**Mechanics**:\n1. Check that the variable is assigned only once\n2. Extract the assignment's right-hand side into a method\n3. Replace references to the temp with the method call\n4. Test\n5. Remove the temp declaration and assignment\n\n**Before**:\n```javascript\nconst basePrice = this._quantity * this._itemPrice;\nif (basePrice > 1000) {\n  return basePrice * 0.95;\n} else {\n  return basePrice * 0.98;\n}\n```\n\n**After**:\n```javascript\nget basePrice() {\n  return this._quantity * this._itemPrice;\n}\n\n// In the method\nif (this.basePrice > 1000) {\n  return this.basePrice * 0.95;\n} else {\n  return this.basePrice * 0.98;\n}\n```\n\n---\n\n## Simplifying Conditional Logic\n\n### Decompose Conditional\n\n**When to use**: Complex conditional (if-then-else) statement\n\n**Motivation**: Make the intention clear by extracting conditions and actions.\n\n**Mechanics**:\n1. Apply Extract Method on the condition\n2. Apply Extract Method on the then-branch\n3. Apply Extract Method on the else-branch (if present)\n\n**Before**:\n```javascript\nif (!aDate.isBefore(plan.summerStart) && !aDate.isAfter(plan.summerEnd)) {\n  charge = quantity * plan.summerRate;\n} else {\n  charge = quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n**After**:\n```javascript\nif (isSummer(aDate, plan)) {\n  charge = summerCharge(quantity, plan);\n} else {\n  charge = regularCharge(quantity, plan);\n}\n\nfunction isSummer(date, plan) {\n  return !date.isBefore(plan.summerStart) && !date.isAfter(plan.summerEnd);\n}\n\nfunction summerCharge(quantity, plan) {\n  return quantity * plan.summerRate;\n}\n\nfunction regularCharge(quantity, plan) {\n  return quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n---\n\n### Consolidate Conditional Expression\n\n**When to use**: Multiple conditions with the same result\n\n**Motivation**: Make it clear that conditions are a single check.\n\n**Mechanics**:\n1. Verify no side effects in conditions\n2. Combine conditions using `and` or `or`\n3. Consider Extract Method on the combined condition\n\n**Before**:\n```javascript\nif (employee.seniority < 2) return 0;\nif (employee.monthsDisabled > 12) return 0;\nif (employee.isPartTime) return 0;\n```\n\n**After**:\n```javascript\nif (isNotEligibleForDisability(employee)) return 0;\n\nfunction isNotEligibleForDisability(employee) {\n  return employee.seniority < 2 ||\n         employee.monthsDisabled > 12 ||\n         employee.isPartTime;\n}\n```\n\n---\n\n### Replace Nested Conditional with Guard Clauses\n\n**When to use**: Deeply nested conditionals making flow hard to follow\n\n**Motivation**: Use guard clauses for special cases, keeping normal flow clear.\n\n**Mechanics**:\n1. Find the special case conditions\n2. Replace them with guard clauses that return early\n3. Test after each change\n\n**Before**:\n```javascript\nfunction payAmount(employee) {\n  let result;\n  if (employee.isSeparated) {\n    result = { amount: 0, reasonCode: \"SEP\" };\n  } else {\n    if (employee.isRetired) {\n      result = { amount: 0, reasonCode: \"RET\" };\n    } else {\n      result = calculateNormalPay(employee);\n    }\n  }\n  return result;\n}\n```\n\n**After**:\n```javascript\nfunction payAmount(employee) {\n  if (employee.isSeparated) return { amount: 0, reasonCode: \"SEP\" };\n  if (employee.isRetired) return { amount: 0, reasonCode: \"RET\" };\n  return calculateNormalPay(employee);\n}\n```\n\n---\n\n### Replace Conditional with Polymorphism\n\n**When to use**: Switch/case based on type, conditional logic varying by type\n\n**Motivation**: Let objects handle their own behavior.\n\n**Mechanics**:\n1. Create class hierarchy (if not exists)\n2. Use Factory Function for object creation\n3. Move conditional logic into superclass method\n4. Create subclass method for each case\n5. Remove original conditional\n\n**Before**:\n```javascript\nfunction plumages(birds) {\n  return birds.map(b => plumage(b));\n}\n\nfunction plumage(bird) {\n  switch (bird.type) {\n    case 'EuropeanSwallow':\n      return \"average\";\n    case 'AfricanSwallow':\n      return (bird.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n    case 'NorwegianBlueParrot':\n      return (bird.voltage > 100) ? \"scorched\" : \"beautiful\";\n    default:\n      return \"unknown\";\n  }\n}\n```\n\n**After**:\n```javascript\nclass Bird {\n  get plumage() { return \"unknown\"; }\n}\n\nclass EuropeanSwallow extends Bird {\n  get plumage() { return \"average\"; }\n}\n\nclass AfricanSwallow extends Bird {\n  get plumage() {\n    return (this.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n  }\n}\n\nclass NorwegianBlueParrot extends Bird {\n  get plumage() {\n    return (this.voltage > 100) ? \"scorched\" : \"beautiful\";\n  }\n}\n\nfunction createBird(data) {\n  switch (data.type) {\n    case 'EuropeanSwallow': return new EuropeanSwallow(data);\n    case 'AfricanSwallow': return new AfricanSwallow(data);\n    case 'NorwegianBlueParrot': return new NorwegianBlueParrot(data);\n    default: return new Bird(data);\n  }\n}\n```\n\n---\n\n### Introduce Special Case (Null Object)\n\n**When to use**: Repeated null checks for special cases\n\n**Motivation**: Return a special object that handles the special case.\n\n**Mechanics**:\n1. Create special case class with expected interface\n2. Add isSpecialCase check\n3. Introduce factory method\n4. Replace null checks with special case object usage\n5. Test\n\n**Before**:\n```javascript\nconst customer = site.customer;\n// ... many places checking\nif (customer === \"unknown\") {\n  customerName = \"occupant\";\n} else {\n  customerName = customer.name;\n}\n```\n\n**After**:\n```javascript\nclass UnknownCustomer {\n  get name() { return \"occupant\"; }\n  get billingPlan() { return registry.defaultPlan; }\n}\n\n// Factory method\nfunction customer(site) {\n  return site.customer === \"unknown\"\n    ? new UnknownCustomer()\n    : site.customer;\n}\n\n// Usage - no null checks needed\nconst customerName = customer.name;\n```\n\n---\n\n## Refactoring APIs\n\n### Separate Query from Modifier\n\n**When to use**: Function both returns a value and has side effects\n\n**Motivation**: Make it clear which operations have side effects.\n\n**Mechanics**:\n1. Create a new query function\n2. Copy original function's return logic\n3. Modify original to return void\n4. Replace calls that use return value\n5. Test\n\n**Before**:\n```javascript\nfunction alertForMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") {\n      setOffAlarms();\n      return \"Don\";\n    }\n    if (p === \"John\") {\n      setOffAlarms();\n      return \"John\";\n    }\n  }\n  return \"\";\n}\n```\n\n**After**:\n```javascript\nfunction findMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") return \"Don\";\n    if (p === \"John\") return \"John\";\n  }\n  return \"\";\n}\n\nfunction alertForMiscreant(people) {\n  if (findMiscreant(people) !== \"\") setOffAlarms();\n}\n```\n\n---\n\n### Parameterize Function\n\n**When to use**: Several functions doing similar things with different values\n\n**Motivation**: Remove duplication by adding a parameter.\n\n**Mechanics**:\n1. Select one function\n2. Add parameter for the varying literal\n3. Change body to use the parameter\n4. Test\n5. Change callers to use the parameterized version\n6. Remove now-unused functions\n\n**Before**:\n```javascript\nfunction tenPercentRaise(person) {\n  person.salary = person.salary * 1.10;\n}\n\nfunction fivePercentRaise(person) {\n  person.salary = person.salary * 1.05;\n}\n```\n\n**After**:\n```javascript\nfunction raise(person, factor) {\n  person.salary = person.salary * (1 + factor);\n}\n\n// Usage\nraise(person, 0.10);\nraise(person, 0.05);\n```\n\n---\n\n### Remove Flag Argument\n\n**When to use**: Boolean parameter that changes function behavior\n\n**Motivation**: Make the behavior explicit through separate functions.\n\n**Mechanics**:\n1. Create explicit function for each flag value\n2. Replace each call with appropriate new function\n3. Test after each change\n4. Remove original function\n\n**Before**:\n```javascript\nfunction bookConcert(customer, isPremium) {\n  if (isPremium) {\n    // premium booking logic\n  } else {\n    // regular booking logic\n  }\n}\n\nbookConcert(customer, true);\nbookConcert(customer, false);\n```\n\n**After**:\n```javascript\nfunction bookPremiumConcert(customer) {\n  // premium booking logic\n}\n\nfunction bookRegularConcert(customer) {\n  // regular booking logic\n}\n\nbookPremiumConcert(customer);\nbookRegularConcert(customer);\n```\n\n---\n\n## Dealing with Inheritance\n\n### Pull Up Method\n\n**When to use**: Same method in multiple subclasses\n\n**Motivation**: Remove duplication in class hierarchy.\n\n**Mechanics**:\n1. Inspect methods to ensure they are identical\n2. Check signatures are the same\n3. Create new method in superclass\n4. Copy body from one subclass\n5. Delete one subclass method, test\n6. Delete other subclass methods, test each\n\n---\n\n### Push Down Method\n\n**When to use**: Behavior relevant only to a subset of subclasses\n\n**Motivation**: Put method where it's used.\n\n**Mechanics**:\n1. Copy method to each subclass that needs it\n2. Remove method from superclass\n3. Test\n4. Remove from subclasses that don't need it\n5. Test\n\n---\n\n### Replace Subclass with Delegate\n\n**When to use**: Inheritance is being used incorrectly, need more flexibility\n\n**Motivation**: Prefer composition over inheritance when appropriate.\n\n**Mechanics**:\n1. Create empty class for delegate\n2. Add field to host class holding delegate\n3. Create constructor for delegate, called from host\n4. Move features to delegate\n5. Test after each move\n6. Replace inheritance with delegation\n\n---\n\n## Extract Class\n\n**When to use**: Large class with multiple responsibilities\n\n**Motivation**: Split class to maintain single responsibility.\n\n**Mechanics**:\n1. Decide how to split responsibilities\n2. Create new class\n3. Move field from original to new class\n4. Test\n5. Move methods from original to new class\n6. Test after each move\n7. Review and rename both classes\n8. Decide how to expose new class\n\n**Before**:\n```javascript\nclass Person {\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get officeAreaCode() { return this._officeAreaCode; }\n  set officeAreaCode(arg) { this._officeAreaCode = arg; }\n  get officeNumber() { return this._officeNumber; }\n  set officeNumber(arg) { this._officeNumber = arg; }\n\n  get telephoneNumber() {\n    return `(${this._officeAreaCode}) ${this._officeNumber}`;\n  }\n}\n```\n\n**After**:\n```javascript\nclass Person {\n  constructor() {\n    this._telephoneNumber = new TelephoneNumber();\n  }\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get telephoneNumber() { return this._telephoneNumber.toString(); }\n  get officeAreaCode() { return this._telephoneNumber.areaCode; }\n  set officeAreaCode(arg) { this._telephoneNumber.areaCode = arg; }\n}\n\nclass TelephoneNumber {\n  get areaCode() { return this._areaCode; }\n  set areaCode(arg) { this._areaCode = arg; }\n  get number() { return this._number; }\n  set number(arg) { this._number = arg; }\n  toString() { return `(${this._areaCode}) ${this._number}`; }\n}\n```\n\n---\n\n## Quick Reference: Smell to Refactoring\n\n| Code Smell | Primary Refactoring | Alternative |\n|------------|-------------------|-------------|\n| Long Method | Extract Method | Replace Temp with Query |\n| Duplicate Code | Extract Method | Pull Up Method |\n| Large Class | Extract Class | Extract Subclass |\n| Long Parameter List | Introduce Parameter Object | Preserve Whole Object |\n| Feature Envy | Move Method | Extract Method + Move |\n| Data Clumps | Extract Class | Introduce Parameter Object |\n| Primitive Obsession | Replace Primitive with Object | Replace Type Code |\n| Switch Statements | Replace Conditional with Polymorphism | Replace Type Code |\n| Temporary Field | Extract Class | Introduce Null Object |\n| Message Chains | Hide Delegate | Extract Method |\n| Middle Man | Remove Middle Man | Inline Method |\n| Divergent Change | Extract Class | Split Phase |\n| Shotgun Surgery | Move Method | Inline Class |\n| Dead Code | Remove Dead Code | - |\n| Speculative Generality | Collapse Hierarchy | Inline Class |\n\n---\n\n## Further Reading\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Online catalog: https://refactoring.com/catalog/\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","07-plugins/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2FREADME.md -->","07-plugins/devops-automation/.claude-plugin/plugin.json":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fdevops-automation%2F.claude-plugin%2Fplugin.json -->","07-plugins/devops-automation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fdevops-automation%2FREADME.md -->","07-plugins/documentation/.claude-plugin/plugin.json":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fdocumentation%2F.claude-plugin%2Fplugin.json -->","07-plugins/documentation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fdocumentation%2FREADME.md -->","07-plugins/documentation/commands/generate-readme.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fdocumentation%2Fcommands%2Fgenerate-readme.md -->","07-plugins/pr-review/.claude-plugin/plugin.json":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fpr-review%2F.claude-plugin%2Fplugin.json -->","07-plugins/pr-review/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fpr-review%2FREADME.md -->","CLAUDE.md":"# CLAUDE.md\n\nTutorial repo. Output is markdown in numbered modules `01-` through `10-`, not an app. Scripts in `scripts/` exist only to validate docs and build the EPUB.\n\nSee also `.claude/CLAUDE.md` for stack/commands and `STYLE_GUIDE.md` for lesson structure.\n\n## Critical commands\n\n```bash\n# Quality gate (also runs on commit via pre-commit hooks)\npre-commit run --all-files\n\n# Tests\npytest scripts/tests/ -v\n\n# EPUB build (renders Mermaid with Pele — needs Node.js >= 20; the pinned bundle downloads once, then works offline)\nuv run scripts/build_epub.py\n\n# Python tooling\nruff check scripts/ && ruff format scripts/\nmypy scripts/ --ignore-missing-imports\nbandit -c scripts/pyproject.toml -r scripts/ --exclude scripts/tests/\n```\n\nPre-commit runs 5 doc checks on `.md` changes: markdown-lint, cross-references, mermaid-syntax, link-check, markdown-rendering. All must pass. The EPUB build is **not** a pre-commit hook — it runs in CI only (`build-epub` job in `.github/workflows/test.yml`), because it is a slow full-book build; the mermaid-syntax hook already renders every diagram with the same Pele bundle.\n\n## Architecture map\n\n- `01-` … `10-` — tutorial modules. **Numbered prefix = learning order**, not alphabetical. Do not reorganize.\n- Each module: `README.md` + copy-paste templates (`.md`, `.json`, `.sh`).\n- `scripts/` — utilities (EPUB builder, link/mermaid/cross-ref validators). Not the product.\n- `02-memory/*.md` — CLAUDE.md templates users copy into their own projects. Don't confuse with this file.\n- `openspec/` — spec-driven change proposals.\n\n## Hard rules\n\n- **YOU MUST NOT commit or push without explicit user request.**\n- **YOU MUST NOT add `Co-Authored-By: Claude`** to any commit message.\n- Always activate `.venv` before running Python scripts (check `venv/`, `.venv/`, `env/`).\n- Internal links use **relative paths** (e.g. `01-slash-commands/README.md`); anchors use `#heading-name`.\n- Code fences **must** declare a language (`bash`, `python`, `json`, …) — the cross-reference check fails otherwise.\n- External URLs must be reachable and stable. No ephemeral links.\n- Mermaid diagrams must render with Pele. The pre-commit mermaid hooks get Node.js 22 from pre-commit and run strict, so they fail instead of skipping; the first run needs network to download Node.js and the pinned Pele bundle (offline: `SKIP=mermaid,vietnamese-mermaid,japanese-mermaid`). Run by hand, `scripts/check_mermaid.py` only warns without Node.js >= 20, and fails under `--strict` or in CI. A broken EPUB build is usually invalid Mermaid, a missing Node.js >= 20, or a failed bundle download.\n- Commit format: `type(scope): subject` where `scope` matches the module folder (e.g. `feat(slash-commands):`, `docs(memory):`, `fix(README):`).\n- Do not reorganize the `01-`–`10-` numbering. The order is the curriculum.\n\n## Workflow preferences\n\n- For lesson edits, follow `STYLE_GUIDE.md` for structure/naming/diagrams.\n- Small fixes → minimal diff. Don't rewrite a section to fix a typo.\n- When adding a module page: README + templates first, then update root `README.md` index and `LEARNING-ROADMAP.md` if order/timing changes.\n- Tutorial > library: prioritize clear explanations and copy-paste examples over reusable abstractions.\n- If a quality check fails, fix the underlying issue. Don't bypass with `--no-verify`.\n\n## Token Efficiency\n- Never re-read files you just wrote or edited. You know the contents.\n- Never re-run commands to \"verify\" unless the outcome was uncertain.\n- Don't echo back large blocks of code or file contents unless asked.\n- Batch related edits into single operations. Don't make 5 edits when 1 handles it.\n- Skip confirmations like \"I'll continue...\" Just do it.\n- If a task needs 1 tool call, don't use 3. Plan before acting.\n- Do not summarize what you just did unless the result is ambiguous or you need additional input.\n","ja/03-skills/blog-draft/SKILL.md":"<!-- i18n-source: 03-skills/blog-draft/SKILL.md -->\n<!-- i18n-source-sha: f396788 -->\n<!-- i18n-date: 2026-04-27 -->\n\n---\nname: blog-draft\ndescription: アイデアとリソースからブログ記事の下書きを作成する。ブログ記事の執筆、リサーチからのコンテンツ作成、記事の下書き作成時に使用する。リサーチ、ブレインストーミング、アウトライン作成、バージョン管理付きの反復的な下書き作成を案内する。\n---\n\n## ユーザー入力\n\n```text\n$ARGUMENTS\n```\n\n進める前にユーザー入力を**必ず**考慮する。ユーザーは以下を提供すべきである。\n- **Idea/Topic**: ブログ記事の主要なコンセプトやテーマ\n- **Resources**: URL、ファイル、リサーチ用の参考情報（任意だが推奨）\n- **Target audience**: ブログ記事の対象読者（任意）\n- **Tone/Style**: フォーマル、カジュアル、技術的、など（任意）\n\n**重要**: ユーザーが**既存のブログ記事**の更新を要求している場合、ステップ 0-8 をスキップして直接**ステップ 9**から開始する。まず既存の下書きファイルを読み、その後で反復プロセスを進める。\n\n## 実行フロー\n\n以下のステップを順次実行する。**ステップをスキップしたり、指示された箇所でユーザー承認なしに進めたりしてはならない。**\n\n### Step 0: プロジェクトフォルダの作成\n\n1. 次の形式でフォルダ名を生成する: `YYYY-MM-DD-short-topic-name`\n   - 今日の日付を使用\n   - トピックから短く URL フレンドリーなスラッグを作成（小文字、ハイフン、最大 5 単語）\n\n2. フォルダ構造を作成:\n   ```\n   blog-posts/\n   └── YYYY-MM-DD-short-topic-name/\n       └── resources/\n   ```\n\n3. 進める前にフォルダ作成をユーザーに確認する。\n\n### Step 1: リサーチとリソース収集\n\n1. ブログ記事ディレクトリ内に `resources/` サブフォルダを作成\n\n2. 提供された各リソースに対して:\n   - **URLs**: 取得して主要情報を `resources/` にマークダウンファイルとして保存\n   - **Files**: 読み込んで `resources/` に要約\n   - **Topics**: ウェブ検索を使用して最新情報を収集\n\n3. 各リソースについて、`resources/` に要約ファイルを作成:\n   - `resources/source-1-[short-name].md`\n   - `resources/source-2-[short-name].md`\n   - など\n\n4. 各要約には以下を含める:\n   ```markdown\n   # Source: [Title/URL]\n\n   ## Key Points\n   - Point 1\n   - Point 2\n\n   ## Relevant Quotes/Data\n   - Quote or statistic 1\n   - Quote or statistic 2\n\n   ## How This Relates to Topic\n   関連性の簡潔な説明\n   ```\n\n5. リサーチの要約をユーザーに提示する。\n\n### Step 2: ブレインストーミングと明確化\n\n1. アイデアとリサーチしたリソースに基づき、以下を提示:\n   - リサーチから特定された**主要テーマ**\n   - ブログ記事の**取りうる切り口**\n   - カバーすべき**重要ポイント**\n   - 明確化が必要な情報の**ギャップ**\n\n2. 明確化のための質問:\n   - 読者に持って帰ってほしい主要なテイクアウェイは何か？\n   - リサーチの中で特に強調したい点はあるか？\n   - 目標の長さは？（short: 500-800 words、medium: 1000-1500、long: 2000+）\n   - 除外したい点はあるか？\n\n3. **進める前にユーザー応答を待つ。**\n\n### Step 3: アウトライン提案\n\n1. 以下を含む構造化されたアウトラインを作成:\n\n   ```markdown\n   # Blog Post Outline: [Title]\n\n   ## Meta Information\n   - **Target Audience**: [who]\n   - **Tone**: [style]\n   - **Target Length**: [word count]\n   - **Main Takeaway**: [key message]\n\n   ## Proposed Structure\n\n   ### Hook/Introduction\n   - Opening hook idea\n   - Context setting\n   - Thesis statement\n\n   ### Section 1: [Title]\n   - Key point A\n   - Key point B\n   - Supporting evidence from [source]\n\n   ### Section 2: [Title]\n   - Key point A\n   - Key point B\n\n   [全セクションについて続ける...]\n\n   ### Conclusion\n   - Summary of key points\n   - Call to action or final thought\n\n   ## Sources to Cite\n   - Source 1\n   - Source 2\n   ```\n\n2. アウトラインをユーザーに提示し、**承認または修正を求める**。\n\n### Step 4: 承認されたアウトラインの保存\n\n1. ユーザーがアウトラインを承認したら、ブログ記事フォルダ内の `OUTLINE.md` に保存する。\n\n2. アウトラインが保存されたことを確認する。\n\n### Step 5: アウトラインのコミット（git リポジトリの場合）\n\n1. カレントディレクトリが git リポジトリかどうか確認する。\n\n2. はいの場合:\n   - 新しいファイル（ブログ記事フォルダ、resources、OUTLINE.md）をステージング\n   - 次のメッセージでコミットを作成: `docs: Add outline for blog post - [topic-name]`\n   - リモートへプッシュ\n\n3. git リポジトリでない場合は、このステップをスキップしユーザーに伝える。\n\n### Step 6: 下書き作成\n\n1. 承認されたアウトラインに基づき、ブログ記事の下書き全文を作成する。\n\n2. OUTLINE.md の構造に厳密に従う。\n\n3. 含めるもの:\n   - フック付きの魅力的な導入\n   - 明確なセクション見出し\n   - リサーチからの裏付けとなる証拠と例\n   - セクション間の滑らかな遷移\n   - テイクアウェイのある力強い結論\n   - **Citations**: すべての比較、統計、データポイント、事実主張は元のソースを必ず引用すること\n\n4. 下書きをブログ記事フォルダ内に `draft-v0.1.md` として保存する。\n\n5. フォーマット:\n   ```markdown\n   # [Blog Post Title]\n\n   *[Optional: subtitle or tagline]*\n\n   [インライン引用付きの本文...]\n\n   ---\n\n   ## References\n   - [1] Source 1 Title - URL or Citation\n   - [2] Source 2 Title - URL or Citation\n   - [3] Source 3 Title - URL or Citation\n   ```\n\n6. **引用要件**:\n   - すべてのデータポイント、統計、比較にはインライン引用を必ず付ける\n   - [1]、[2] などの番号引用、または [Source Name] のような名前付き引用を使用\n   - 引用を末尾の References セクションへリンクする\n   - 例: \"Studies show that 65% of developers prefer TypeScript [1]\"\n   - 例: \"React outperforms Vue in rendering speed by 20% [React Benchmarks 2024]\"\n\n### Step 7: 下書きのコミット（git リポジトリの場合）\n\n1. git リポジトリかどうか確認する。\n\n2. はいの場合:\n   - 下書きファイルをステージング\n   - 次のメッセージでコミットを作成: `docs: Add draft v0.1 for blog post - [topic-name]`\n   - リモートへプッシュ\n\n3. git リポジトリでない場合は、スキップしてユーザーに伝える。\n\n### Step 8: レビュー用に下書きを提示\n\n1. 下書きの内容をユーザーに提示する。\n\n2. フィードバックを求める:\n   - 全体の印象は？\n   - 拡張または削減が必要なセクションは？\n   - トーン調整は必要か？\n   - 不足している情報は？\n   - 具体的な編集や書き直しは？\n\n3. **ユーザー応答を待つ。**\n\n### Step 9: 反復または最終化\n\n**ユーザーが変更を要求した場合:**\n1. すべての要望を記録する\n2. 以下の調整を加えてステップ 6 へ戻る:\n   - バージョン番号を増加（v0.2、v0.3 など）\n   - すべてのフィードバックを反映\n   - `draft-v[X.Y].md` として保存\n   - ステップ 7-8 を繰り返す\n\n**ユーザーが承認した場合:**\n1. 最終下書きのバージョンを確認\n2. ユーザーが要求すれば任意で `final.md` にリネーム\n3. ブログ記事作成プロセスを要約:\n   - 作成したバージョンの総数\n   - バージョン間の主要な変更\n   - 最終ワード数\n   - 作成したファイル\n\n## バージョン追跡\n\nすべての下書きは段階的なバージョン番号付きで保持する:\n- `draft-v0.1.md` - 初回下書き\n- `draft-v0.2.md` - 1 回目のフィードバック反映後\n- `draft-v0.3.md` - 2 回目のフィードバック反映後\n- など\n\nこれによりブログ記事の進化を追跡し、必要に応じて差し戻すことができる。\n\n## 出力ファイル構造\n\n```\nblog-posts/\n└── YYYY-MM-DD-topic-name/\n    ├── resources/\n    │   ├── source-1-name.md\n    │   ├── source-2-name.md\n    │   └── ...\n    ├── OUTLINE.md\n    ├── draft-v0.1.md\n    ├── draft-v0.2.md (反復した場合)\n    └── draft-v0.3.md (さらに反復した場合)\n```\n\n## 品質のためのヒント\n\n- **Hook**: 質問、意外な事実、共感できるシナリオで始める\n- **Flow**: 各段落は次の段落と接続させる\n- **Evidence**: リサーチデータで主張を裏付ける\n- **Citations**: 以下については必ずソースを引用する:\n  - すべての統計とデータポイント（例: \"According to [Source], 75% of...\"）\n  - 製品、サービス、アプローチ間の比較（例: \"X performs 2x faster than Y [Source]\"）\n  - 市場トレンド、リサーチ結果、ベンチマークについての事実主張\n  - 形式: [Source Name] または [Author, Year] のインライン引用を使用\n- **Voice**: 全体を通じて一貫したトーンを保つ\n- **Length**: 目標ワード数を尊重\n- **Readability**: 短い段落、適切な箇所での箇条書きを使用\n- **CTA**: 明確な CTA または考えさせる問いで終える\n\n## 注意事項\n\n- 指定されたチェックポイントでは必ずユーザー承認を待つ\n- 履歴のためすべての下書きバージョンを保持する\n- URL が提供された場合は最新情報のためウェブ検索を使用する\n- リソースが不十分な場合はユーザーに追加を求めるか、追加リサーチを提案する\n- 対象読者（技術系、一般、ビジネスなど）に応じてトーンを適応させる\n","ja/03-skills/brand-voice/SKILL.md":"<!-- i18n-source: 03-skills/brand-voice/SKILL.md -->\n<!-- i18n-source-sha: a6380d8 -->\n<!-- i18n-date: 2026-04-27 -->\n\n---\nname: brand-voice\ndescription: すべてのコミュニケーションがブランドボイスとトーンのガイドラインに沿うことを保証する。マーケティングコピー、顧客向け連絡、公開コンテンツの作成時、またはブランドボイス、トーン、文体について言及がある場合に使用する。\nuser-invocable: false\n---\n\n# ブランドボイス・スキル\n\n## 概要\nこのスキルは、すべてのコミュニケーションにおいて一貫したブランドボイス、トーン、メッセージングを維持する。\n\n## ブランドアイデンティティ\n\n### ミッション\nチームが AI で開発ワークフローを自動化することを支援する\n\n### バリュー\n- **シンプリシティ**: 複雑なものをシンプルにする\n- **信頼性**: 揺るぎない実行\n- **エンパワーメント**: 人間の創造性を引き出す\n\n### トーン・オブ・ボイス\n- **フレンドリーかつプロフェッショナル** - カジュアルにならず、親しみやすい\n- **明快で簡潔** - 専門用語を避け、技術的な概念をわかりやすく説明する\n- **自信を持って** - 自分たちが何をしているかを理解している\n- **共感的** - ユーザーのニーズと痛みを理解する\n\n## 執筆ガイドライン\n\n### やるべきこと ✅\n- 読者を指す際には「you」を使用\n- 能動態を使用: 「Claude generates reports」とし、「Reports are generated by Claude」としない\n- 価値提案から始める\n- 具体例を用いる\n- 1 文を 20 語未満に保つ\n- 明確化のためリストを使用\n- CTA（行動喚起）を含める\n\n### 避けるべきこと ❌\n- 企業ジャーゴンを使わない\n- 見下したり過度に単純化したりしない\n- 「we believe」や「we think」を使わない\n- 強調以外で全大文字を使わない\n- 文章の壁を作らない\n- 技術的な前提知識を仮定しない\n\n## ボキャブラリー\n\n### ✅ 推奨用語\n- Claude（「the Claude AI」ではなく）\n- Code generation（「auto-coding」ではなく）\n- Agent（「bot」ではなく）\n- Streamline（「revolutionize」ではなく）\n- Integrate（「synergize」ではなく）\n\n### ❌ 避ける用語\n- 「Cutting-edge」（使い古されている）\n- 「Game-changer」（曖昧）\n- 「Leverage」（企業用語的）\n- 「Utilize」（「use」を使う）\n- 「Paradigm shift」（不明瞭）\n\n## 例\n\n### ✅ 良い例\n\"Claude automates your code review process. Instead of manually checking each PR, Claude reviews security, performance, and quality—saving your team hours every week.\"\n\nなぜ機能するか: 明確な価値、具体的なメリット、行動志向\n\n### ❌ 悪い例\n\"Claude leverages cutting-edge AI to provide comprehensive software development solutions.\"\n\nなぜ機能しないか: 曖昧、企業ジャーゴン、具体的な価値がない\n","ja/03-skills/claude-md/SKILL.md":"<!-- i18n-source: 03-skills/claude-md/SKILL.md -->\n<!-- i18n-source-sha: f78c094 -->\n<!-- i18n-date: 2026-04-27 -->\n---\nname: claude-md\ndescription: Create or update CLAUDE.md files following best practices for optimal AI agent onboarding\n---\n\n## ユーザー入力\n\n```text\n$ARGUMENTS\n```\n\nユーザー入力が空でない場合、進める前に **必ず** 内容を考慮すること。ユーザーは以下を指定する場合がある:\n- `create` - 新しい CLAUDE.md をゼロから作成\n- `update` - 既存 CLAUDE.md を改善\n- `audit` - 現在の CLAUDE.md の品質を分析しレポート\n- 作成・更新する具体的なパス（例: ディレクトリ固有命令向けの `src/api/CLAUDE.md`）\n\n## 基本原則\n\n**LLM はステートレス**: CLAUDE.md は、すべての会話に読み込まれる主要なプロジェクトファイルである（自動メモリやスコープなしのルールと並んで読み込まれる）。コードベースに対する AI エージェントの主要なオンボーディングドキュメントとして機能する。\n\n### ゴールデンルール\n\n1. **少ないほど良い**: フロンティア LLM は約 150〜200 個の命令に従える。Claude Code のシステムプロンプトはすでに約 50 個を使用している。CLAUDE.md は焦点を絞り簡潔に保つこと。\n\n2. **普遍的な適用性**: あらゆるセッションに関係する情報のみを含める。タスク固有の命令は別ファイルに置く。\n\n3. **Claude をリンターとして使わない**: スタイルガイドラインはコンテキストを膨張させ命令の遵守を低下させる。代わりに決定論的なツール（prettier, eslint など）を使う。\n\n4. **絶対に自動生成しない**: CLAUDE.md は AI ハーネスにおける最も影響力の高いポイントである。慎重に手作業で作り上げること。\n\n## 実行フロー\n\n### 1. プロジェクト分析\n\nまず現在のプロジェクト状態を分析する:\n\n1. 既存の CLAUDE.md ファイルを確認:\n   - ルートレベル: `./CLAUDE.md` または `.claude/CLAUDE.md`\n   - ディレクトリ固有: `**/CLAUDE.md`\n   - グローバルユーザー設定: `~/.claude/CLAUDE.md`\n\n2. プロジェクト構造を特定:\n   - 技術スタック（言語、フレームワーク）\n   - プロジェクト種別（モノレポ、単一アプリ、ライブラリ）\n   - 開発ツール（パッケージマネージャー、ビルドシステム、テストランナー）\n\n3. 既存ドキュメントをレビュー:\n   - README.md\n   - CONTRIBUTING.md\n   - package.json, pyproject.toml, Cargo.toml など\n\n### 2. コンテンツ戦略（WHAT, WHY, HOW）\n\nCLAUDE.md を 3 つの観点で構成する:\n\n#### WHAT - 技術と構造\n- 技術スタックの概要\n- プロジェクトの編成（モノレポでは特に重要）\n- 主要ディレクトリとその目的\n\n#### WHY - 目的と背景\n- プロジェクトが何をするか\n- なぜ特定の設計判断が下されたのか\n- 各主要コンポーネントが何を担当するか\n\n#### HOW - ワークフローと規約\n- 開発ワークフロー（bun と node、pip と uv など）\n- テスト手順とコマンド\n- 検証およびビルド手段\n- 重要な「ハマりどころ」や明示されない要件\n\n### 3. プログレッシブディスクロージャ戦略\n\n大規模プロジェクトでは `agent_docs/` フォルダの作成を推奨する:\n\n```\nagent_docs/\n  |- building_the_project.md\n  |- running_tests.md\n  |- code_conventions.md\n  |- architecture_decisions.md\n```\n\nCLAUDE.md からは以下のような命令でこれらのファイルを参照する:\n```markdown\nFor detailed build instructions, refer to `agent_docs/building_the_project.md`\n```\n\n**重要**: 古くなるコンテキストを避けるため、コードスニペットではなく `file:line` 参照を用いる。\n\n### 4. 品質制約\n\nCLAUDE.md を作成・更新する際:\n\n1. **目標の長さ**: 200 行未満\n2. **スタイルルールなし**: lint やフォーマットの命令は除く\n3. **タスク固有命令なし**: 別ファイルへ移す\n4. **コードスニペットなし**: ファイル参照を用いる\n5. **冗長情報なし**: package.json や README にあるものを繰り返さない\n\n### 5. 必須セクション\n\n良く構成された CLAUDE.md には以下を含めるべきである:\n\n```markdown\n# Project Name\n\nBrief one-line description.\n\n## Tech Stack\n- Primary language and version\n- Key frameworks/libraries\n- Database/storage (if any)\n\n## Project Structure\n[Only for monorepos or complex structures]\n- `apps/` - Application entry points\n- `packages/` - Shared libraries\n\n## Development Commands\n- Install: `command`\n- Test: `command`\n- Build: `command`\n\n## Critical Conventions\n[Only non-obvious, high-impact conventions]\n- Convention 1 with brief explanation\n- Convention 2 with brief explanation\n\n## Known Issues / Gotchas\n[Things that consistently trip up developers]\n- Issue 1\n- Issue 2\n```\n\n### 6. 避けるべきアンチパターン\n\n**含めてはいけないもの:**\n- コードスタイルガイドライン（リンターを使う）\n- Claude の使い方に関するドキュメント\n- 自明なパターンへの長い説明\n- コピー＆ペーストされたコード例\n- 一般的なベストプラクティス（\"write clean code\"）\n- 特定タスク向けの命令\n- 自動生成された内容\n- 大量の TODO リスト\n\n### 7. 検証チェックリスト\n\n最終化前に確認:\n\n- [ ] 200 行未満\n- [ ] すべての行があらゆるセッションに適用される\n- [ ] スタイルやフォーマットのルールがない\n- [ ] コードスニペットがない（ファイル参照を使う）\n- [ ] コマンドが動作することを検証済み\n- [ ] 複雑なプロジェクトでプログレッシブディスクロージャを利用\n- [ ] 重要なハマりどころがドキュメント化されている\n- [ ] README.md と内容が重複していない\n\n## 出力形式\n\n### `create` または既定の場合:\n\n1. プロジェクトを分析する\n2. 上記の構造に従って CLAUDE.md の草案を作る\n3. 草案をレビュー用に提示する\n4. 承認後、適切な場所へ書き込む\n\n### `update` の場合:\n\n1. 既存 CLAUDE.md を読む\n2. ベストプラクティスに照らして監査する\n3. 以下を特定する:\n   - 削除する内容（スタイルルール、コードスニペット、タスク固有）\n   - 凝縮する内容\n   - 不足している必須情報\n4. 変更内容をレビュー用に提示する\n5. 承認後、変更を適用する\n\n### `audit` の場合:\n\n1. 既存 CLAUDE.md を読む\n2. 以下を含むレポートを生成する:\n   - 現在の行数と目標値\n   - 普遍的に適用可能なコンテンツの割合\n   - 検出されたアンチパターンの一覧\n   - 改善のための推奨\n3. ファイルを変更しない、レポートのみを行う\n\n## AGENTS.md の取り扱い\n\nユーザーが AGENTS.md の作成・更新を求めた場合:\n\n**v2.1.277 以降、Claude Code は `AGENTS.md` をプロジェクト指示として直接読み込む。** ただし、作業ディレクトリとその上位すべてのディレクトリに `CLAUDE.md`、`.claude/CLAUDE.md`、`CLAUDE.local.md` のいずれも存在しない場合に限る。`~/.claude/CLAUDE.md`、管理 CLAUDE.md、`.claude/rules/` はこの判定の対象外であり、引き続き併せて読み込まれる。この挙動は `/config` の **Project instructions** で制御する: `claude-md-or-agents-md`（デフォルト）、`claude-md-and-agents-md`、`claude-md`、`managed-only`。直接読み込みが利用できない環境 — v2.1.277 より前のバージョン（Bedrock/Vertex/Foundry、LLM ゲートウェイ、テレメトリ無効の場合は v2.1.281 より前）、またはアップグレード後の最初のセッション — では、CLAUDE.md から `@AGENTS.md` でインポートするか、`CLAUDE.md` をこのファイルへのシンボリックリンクにするフォールバックを使う。\n\nAGENTS.md はツール横断のプロジェクトコンテキストファイルであり、CLAUDE.md と同じ *種類* のドキュメントである。エージェント定義フォーマットではない。複数のコーディングエージェントが 1 つのプロジェクト規約を共有できるようにするために存在する:\n- ビルド、テスト、リントのコマンド\n- コードスタイルとアーキテクチャ上の規約\n- リポジトリの構成と各要素の所在\n\nサブエージェントは AGENTS.md ではなく、`.claude/agents/*.md` で別途定義する。\n\n同様の原則を適用する:\n- 焦点を絞り簡潔に保つ\n- プログレッシブディスクロージャを用いる\n- 内容を埋め込むのではなく外部ドキュメントを参照する\n\n## 注意事項\n\n- コマンドを含める前に必ず動作確認する\n- 迷ったら省略する。少ないほど良い\n- システムリマインダーは Claude に対して CLAUDE.md は「関係があるかどうかわからない」と告げている。ノイズが多いほど無視されやすい\n- モノレポは明確な WHAT/WHY/HOW 構造の恩恵が最も大きい\n- ディレクトリ固有の CLAUDE.md ファイルはさらに焦点を絞るべきである\n\n---\n\n**最終更新**: 2026 年 10 月 18 日\n**Claude Code バージョン**: 2.1.302\n**Sources**:\n- https://code.claude.com/docs/en/memory\n","ja/03-skills/code-review-specialist/SKILL.md":"<!-- i18n-source: 03-skills/code-review-specialist/SKILL.md -->\n<!-- i18n-source-sha: e978c49 -->\n<!-- i18n-date: 2026-04-27 -->\n\n---\nname: code-review-specialist\ndescription: セキュリティ、パフォーマンス、品質分析を含む包括的なコードレビュー。コードレビュー、コード品質分析、プルリクエスト評価の依頼があった場合、またはコードレビュー、セキュリティ分析、パフォーマンス最適化について言及がある場合に使用する。\n---\n\n# コードレビュー・スキル\n\nこのスキルは、以下に焦点を当てた包括的なコードレビュー機能を提供する。\n\n1. **セキュリティ分析**\n   - 認証・認可の問題\n   - データ漏洩リスク\n   - インジェクション脆弱性\n   - 暗号の弱点\n   - 機密データのロギング\n\n2. **パフォーマンス・レビュー**\n   - アルゴリズム効率（Big O 分析）\n   - メモリ最適化\n   - データベースクエリ最適化\n   - キャッシュ機会\n   - 並行性の問題\n\n3. **コード品質**\n   - SOLID 原則\n   - デザインパターン\n   - 命名規則\n   - ドキュメント\n   - テストカバレッジ\n\n4. **保守性**\n   - コードの可読性\n   - 関数サイズ（50 行未満が望ましい）\n   - 循環的複雑度\n   - 依存関係管理\n   - 型安全性\n\n## レビュー・テンプレート\n\nレビューしたコードごとに、以下を提供する。\n\n### サマリー\n- 全体品質評価（1-5）\n- 主要な指摘件数\n- 推奨される優先領域\n\n### クリティカルな問題（あれば）\n- **Issue**: 明確な説明\n- **Location**: ファイルと行番号\n- **Impact**: なぜ重要か\n- **Severity**: Critical/High/Medium\n- **Fix**: コード例\n\n### カテゴリ別の指摘事項\n\n#### セキュリティ（問題が見つかった場合）\nセキュリティ脆弱性を例示しながら列挙\n\n#### パフォーマンス（問題が見つかった場合）\n複雑度分析を含めパフォーマンス問題を列挙\n\n#### 品質（問題が見つかった場合）\nリファクタリング提案を含めコード品質の問題を列挙\n\n#### 保守性（問題が見つかった場合）\n改善案を含め保守性の問題を列挙\n\n## バージョン履歴\n\n- v1.0.0 (2024-12-10): セキュリティ、パフォーマンス、品質、保守性分析を含む初回リリース\n","ja/03-skills/doc-generator/SKILL.md":"<!-- i18n-source: 03-skills/doc-generator/SKILL.md -->\n<!-- i18n-source-sha: a6380d8 -->\n<!-- i18n-date: 2026-04-27 -->\n\n---\nname: doc-generator\ndescription: ソースコードから包括的かつ正確な API ドキュメントを生成する。API ドキュメントの作成・更新、OpenAPI 仕様の生成時、または API ドキュメント、エンドポイント、ドキュメントについて言及がある場合に使用する。\n---\n\n# API ドキュメント生成スキル\n\n## 生成するもの\n\n- OpenAPI/Swagger 仕様\n- API エンドポイントのドキュメント\n- SDK 利用例\n- 統合ガイド\n- エラーコード・リファレンス\n- 認証ガイド\n\n## ドキュメント構造\n\n### 各エンドポイントごと\n\n````markdown\n## GET /api/v1/users/:id\n\n### Description\nこのエンドポイントの動作を簡潔に説明\n\n### Parameters\n\n| Name | Type | Required | Description |\n|------|------|----------|-------------|\n| id | string | Yes | User ID |\n\n### Response\n\n**200 Success**\n```json\n{\n  \"id\": \"usr_123\",\n  \"name\": \"John Doe\",\n  \"email\": \"john@example.com\",\n  \"created_at\": \"2025-01-15T10:30:00Z\"\n}\n```\n\n**404 Not Found**\n```json\n{\n  \"error\": \"USER_NOT_FOUND\",\n  \"message\": \"User does not exist\"\n}\n```\n\n### Examples\n\n**cURL**\n```bash\ncurl -X GET \"https://api.example.com/api/v1/users/usr_123\" \\\n  -H \"Authorization: Bearer YOUR_TOKEN\"\n```\n\n**JavaScript**\n```javascript\nconst user = await fetch('/api/v1/users/usr_123', {\n  headers: { 'Authorization': 'Bearer token' }\n}).then(r => r.json());\n```\n\n**Python**\n```python\nresponse = requests.get(\n    'https://api.example.com/api/v1/users/usr_123',\n    headers={'Authorization': 'Bearer token'}\n)\nuser = response.json()\n```\n````\n","ja/03-skills/refactor/SKILL.md":"<!-- i18n-source: 03-skills/refactor/SKILL.md -->\n<!-- i18n-source-sha: 245272f -->\n<!-- i18n-date: 2026-04-27 -->\n---\nname: refactor\ndescription: Martin Fowler の方法論に基づく体系的なコードリファクタリング。ユーザーがコードのリファクタリング、コード構造の改善、技術的負債の削減、レガシーコードのクリーンアップ、コードスメルの解消、コード保守性の向上を求めた際に使用する。本スキルは、リサーチ・計画・安全な段階的実装からなる段階的アプローチを案内する。\n---\n\n# コードリファクタリングスキル\n\nMartin Fowler 著『Refactoring: Improving the Design of Existing Code』(第 2 版) に基づくコードリファクタリングへの体系的アプローチ。本スキルは、テストに支えられた安全で段階的な変更を重視する。\n\n> \"Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure.\" — Martin Fowler\n\n## 中核となる原則\n\n1. **振る舞いの保全**: 外部から見える振る舞いは変えてはならない\n2. **小さなステップ**: テスト可能な微小な変更を積み重ねる\n3. **テスト駆動**: テストはセーフティネットである\n4. **継続的**: リファクタリングは一度きりの作業ではなく継続的に行う\n5. **協調的**: 各フェーズでユーザーの承認が必要\n\n## ワークフロー概要\n\n```\nPhase 1: Research & Analysis\n    ↓\nPhase 2: Test Coverage Assessment\n    ↓\nPhase 3: Code Smell Identification\n    ↓\nPhase 4: Refactoring Plan Creation\n    ↓\nPhase 5: Incremental Implementation\n    ↓\nPhase 6: Review & Iteration\n```\n\n---\n\n## フェーズ 1: リサーチと分析\n\n### 目的\n- コードベースの構造と目的を把握する\n- リファクタリングの範囲を特定する\n- ビジネス要件に関するコンテキストを収集する\n\n### ユーザーへの確認事項\n開始前に次の点を明確化する。\n\n1. **範囲**: どのファイル/モジュール/関数をリファクタリングするのか?\n2. **目標**: 何を解決したいのか?(可読性、性能、保守性)\n3. **制約**: 変更してはいけない領域はあるか?\n4. **時間的圧力**: 他作業のブロッカーになっているか?\n5. **テスト状況**: テストは存在するか?パスしているか?\n\n### アクション\n- [ ] 対象コードを読み、理解する\n- [ ] 依存関係と統合箇所を洗い出す\n- [ ] 現行アーキテクチャを文書化する\n- [ ] 既存の技術的負債マーカー(TODO、FIXME)を控える\n\n### 出力\nユーザーへの提示内容:\n- コード構造のサマリー\n- 検出された問題箇所\n- 初期推奨事項\n- **着手の承認を依頼する**\n\n---\n\n## フェーズ 2: テストカバレッジの評価\n\n### なぜテストが重要か\n> \"Refactoring without tests is like driving without a seatbelt.\" — Martin Fowler\n\nテストは安全なリファクタリングを可能にする**鍵となる要素**である。テストがなければ、バグを混入させるリスクがある。\n\n### 評価ステップ\n\n1. **既存テストの確認**\n   ```bash\n   # テストファイルを探す\n   find . -name \"*test*\" -o -name \"*spec*\" | head -20\n   ```\n\n2. **既存テストの実行**\n   ```bash\n   # JavaScript/TypeScript\n   npm test\n\n   # Python\n   pytest -v\n\n   # Java\n   mvn test\n   ```\n\n3. **カバレッジの確認(可能な場合)**\n   ```bash\n   # JavaScript\n   npm run test:coverage\n\n   # Python\n   pytest --cov=.\n   ```\n\n### 判断ポイント: ユーザーへの確認\n\n**テストが存在し、かつパスしている場合:**\n- フェーズ 3 へ進む\n\n**テストが不足、または不完全な場合:**\n次の選択肢を提示する。\n1. 先にテストを書く(推奨)\n2. リファクタリング中に段階的にテストを追加する\n3. テストなしで進める(リスクあり、ユーザーの明示的同意が必要)\n\n**テストが失敗している場合:**\n- STOP。リファクタリング前に失敗テストを修正する\n- ユーザーに確認: 先にテストを直すべきか?\n\n### テスト作成のガイドライン(必要時)\n\nリファクタリング対象の各関数について、以下をテストでカバーする。\n- ハッピーパス(通常動作)\n- エッジケース(空入力、null、境界値)\n- エラーシナリオ(無効入力、例外)\n\n「red-green-refactor」サイクルを用いる。\n1. 失敗するテストを書く(red)\n2. パスさせる(green)\n3. リファクタリングする\n\n---\n\n## フェーズ 3: コードスメルの特定\n\n### コードスメルとは?\nコードに潜むより深い問題の症状である。バグそのものではないが、コード改善の余地を示す指標となる。\n\n### よくチェックすべきコードスメル\n\n完全なカタログは [references/code-smells.md](references/code-smells.md) を参照。\n\n#### クイックリファレンス\n\n| スメル | 兆候 | 影響 |\n|-------|-------|--------|\n| **Long Method（長すぎる関数）** | メソッドが 30〜50 行を超える | 理解、テスト、保守が困難 |\n| **Duplicated Code（重複したコード）** | 同じロジックが複数箇所に存在 | バグ修正を複数箇所で行う必要がある |\n| **Large Class（巨大なクラス）** | 責務が多すぎるクラス | 単一責任原則に違反 |\n| **Feature Envy（機能の横恋慕）** | 他クラスのデータを多く使用するメソッド | カプセル化が不十分 |\n| **Primitive Obsession（プリミティブ型への執着）** | オブジェクト化すべき所をプリミティブで多用 | ドメイン概念が欠落 |\n| **Long Parameter List（長すぎるパラメータリスト）** | パラメータが 4 個以上 | 正しく呼び出すのが困難 |\n| **Data Clumps（データの群れ）** | 同じデータ項目が常に一緒に現れる | 抽象化が欠落 |\n| **Switch Statements（スイッチ文)** | 複雑な switch / if-else の連鎖 | 拡張が困難 |\n| **Speculative Generality（投機的一般化）** | 「念のため」のコード | 不要な複雑さ |\n| **Dead Code（デッドコード）** | 使われていないコード | 混乱と保守負担 |\n\n### 分析ステップ\n\n1. **自動分析**(スクリプトが利用可能な場合)\n   ```bash\n   python scripts/detect-smells.py <file>\n   ```\n\n2. **手動レビュー**\n   - コードを体系的に読み進める\n   - 各スメルを場所と深刻度とともに記録する\n   - 影響度別に分類する(Critical / High / Medium / Low)\n\n3. **優先順位付け**\n   次のようなスメルに注力する。\n   - 現在の開発をブロックしているもの\n   - バグや混乱を引き起こしているもの\n   - 変更頻度が高いコードパスに影響するもの\n\n### 出力: スメルレポート\n\nユーザーへの提示内容:\n- 検出されたスメルの一覧と場所\n- 各スメルの深刻度評価\n- 推奨される優先順位\n- **優先順位の承認を依頼する**\n\n---\n\n## フェーズ 4: リファクタリング計画の作成\n\n### リファクタリング技法の選定\n\n各スメルに対して、カタログから適切なリファクタリング技法を選ぶ。\n\n完全な一覧は [references/refactoring-catalog.md](references/refactoring-catalog.md) を参照。\n\n#### スメル別の推奨リファクタリング\n\n| コードスメル | 推奨リファクタリング |\n|------------|---------------------------|\n| Long Method（長すぎる関数） | メソッドの抽出、Replace Temp with Query |\n| Duplicated Code（重複したコード） | メソッドの抽出、Pull Up Method、Form Template Method |\n| Large Class（巨大なクラス） | クラスの抽出、Extract Subclass |\n| Feature Envy（機能の横恋慕） | Move Method、Move Field |\n| Primitive Obsession（プリミティブ型への執着） | Replace Primitive with Object、Replace Type Code with Class |\n| Long Parameter List（長すぎるパラメータリスト） | パラメータオブジェクトの導入、Preserve Whole Object |\n| Data Clumps（データの群れ） | クラスの抽出、パラメータオブジェクトの導入 |\n| Switch Statements（スイッチ文） | ポリモーフィズムによる条件記述の置き換え |\n| Speculative Generality（投機的一般化） | Collapse Hierarchy、Inline Class、デッドコードの削除 |\n| Dead Code（デッドコード） | デッドコードの削除 |\n\n### 計画の構成\n\n[templates/refactoring-plan.md](templates/refactoring-plan.md) のテンプレートを使用する。\n\n各リファクタリングごとに次の項目を埋める。\n1. **対象**: 何を変更するか\n2. **スメル**: どの問題に対処するか\n3. **リファクタリング**: どの技法を適用するか\n4. **手順**: 細かいマイクロステップ\n5. **リスク**: 何が失敗しうるか\n6. **ロールバック**: 取り消す方法\n\n### 段階的アプローチ\n\n**重要**: リファクタリングはフェーズに分けて段階的に導入する。\n\n**フェーズ A: クイックウィン**(低リスク、高価値)\n- 明確化のための変数名変更\n- 明らかな重複コードの抽出\n- デッドコードの削除\n\n**フェーズ B: 構造改善**(中リスク)\n- 長すぎる関数からのメソッド抽出\n- パラメータオブジェクトの導入\n- メソッドを適切なクラスへ移動\n\n**フェーズ C: アーキテクチャ変更**(高リスク)\n- 条件分岐をポリモーフィズムで置換\n- クラスの抽出\n- デザインパターンの導入\n\n### 判断ポイント: ユーザーへの計画提示\n\n実装前に:\n- 完全なリファクタリング計画を提示する\n- 各フェーズの内容とリスクを説明する\n- 各フェーズについて明示的な承認を得る\n- **質問**: 「フェーズ A を進めてもよいか?」\n\n---\n\n## フェーズ 5: 段階的な実装\n\n### ゴールデンルール\n> \"Change → Test → Green? → Commit → Next step\"\n\n### 実装のリズム\n\n各リファクタリングステップで:\n\n1. **事前チェック**\n   - テストがパスしている(green)\n   - コードがコンパイルできる\n\n2. **小さな変更を 1 つだけ行う**\n   - カタログのメカニクスに従う\n   - 変更は最小限に保つ\n\n3. **検証**\n   - 直ちにテストを実行\n   - コンパイルエラーがないか確認\n\n4. **テストがパス(green)した場合**\n   - 説明的なコミットメッセージでコミット\n   - 次のステップへ進む\n\n5. **テストが失敗(red)した場合**\n   - 直ちに STOP\n   - 変更を取り消す\n   - 何が起きたかを分析する\n   - 不明な場合はユーザーに確認する\n\n### コミット戦略\n\n各コミットは次の性質を満たすこと。\n- **アトミック**: 論理的に 1 つの変更\n- **可逆**: 容易に revert できる\n- **説明的**: 明確なコミットメッセージ\n\nコミットメッセージ例:\n```\nrefactor: Extract calculateTotal() from processOrder()\nrefactor: Rename 'x' to 'customerCount' for clarity\nrefactor: Remove unused validateOldFormat() method\n```\n\n### 進捗報告\n\nサブフェーズごとに、ユーザーへ次を報告する。\n- 行った変更\n- テストはまだパスしているか\n- 発生した問題\n- **質問**: 「次のバッチへ進めてもよいか?」\n\n---\n\n## フェーズ 6: レビューと反復\n\n### リファクタリング後チェックリスト\n\n- [ ] 全テストがパスする\n- [ ] 新たな警告/エラーが出ていない\n- [ ] コードが正常にコンパイルできる\n- [ ] 振る舞いが変わっていない(手動検証)\n- [ ] 必要に応じてドキュメントが更新されている\n- [ ] コミット履歴が整理されている\n\n### メトリクス比較\n\nリファクタリング前後で複雑度解析を実施する。\n```bash\npython scripts/analyze-complexity.py <file>\n```\n\n改善点を提示する。\n- コード行数の変化\n- 循環的複雑度の変化\n- 保守性指数の変化\n\n### ユーザーレビュー\n\n最終結果を提示する。\n- 全変更のサマリー\n- Before / After のコード比較\n- メトリクスの改善\n- 残る技術的負債\n- **質問**: 「この変更内容で問題ないか?」\n\n### 次のステップ\n\nユーザーと議論する。\n- 追加で対処すべきスメルはあるか?\n- フォローアップのリファクタリングを計画するか?\n- 同様の変更を他箇所にも適用するか?\n\n---\n\n## 重要なガイドライン\n\n### STOP してユーザーに相談すべきタイミング\n\n次の場合、必ず一旦止まりユーザーに相談する。\n- ビジネスロジックに不確実性がある\n- 外部 API に影響しうる変更\n- テストカバレッジが不十分\n- 重大なアーキテクチャ判断が必要\n- リスクレベルが上昇する\n- 想定外の複雑さに遭遇した\n\n### 安全のためのルール\n\n1. **テストなしでリファクタリングしない**(ユーザーが明示的にリスクを受容しない限り)\n2. **大きな変更を一度にしない** - 微小なステップに分割する\n3. **各変更後のテスト実行を省略しない**\n4. **テスト失敗時は続行しない** - 修正かロールバックを先に行う\n5. **思い込みで進めない** - 疑問があれば確認する\n\n### やってはいけないこと\n\n- リファクタリングと機能追加を同時に行わない\n- 本番障害対応中にリファクタリングしない\n- 理解していないコードをリファクタリングしない\n- 過剰設計をしない - シンプルに保つ\n- 全てを一度にリファクタリングしない\n\n---\n\n## クイックスタート例\n\n### シナリオ: 重複を含む長い関数\n\n**Before:**\n```javascript\nfunction processOrder(order) {\n  // 150 行のコードに以下が混在:\n  // - 重複したバリデーションロジック\n  // - インラインの計算処理\n  // - 複数の責務\n}\n```\n\n**リファクタリング手順:**\n\n1. processOrder() に対する**テストの存在を確認**\n2. バリデーションを validateOrder() に**抽出**\n3. **テスト** - パスすること\n4. 計算を calculateOrderTotal() に**抽出**\n5. **テスト** - パスすること\n6. 通知を notifyCustomer() に**抽出**\n7. **テスト** - パスすること\n8. **レビュー** - processOrder() は明確な 3 関数の調整役となる\n\n**After:**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const total = calculateOrderTotal(order);\n  notifyCustomer(order, total);\n  return { order, total };\n}\n```\n\n---\n\n## 参考文献\n\n- [Code Smells Catalog](references/code-smells.md) - コードスメルの完全な一覧\n- [Refactoring Catalog](references/refactoring-catalog.md) - リファクタリング技法\n- [Refactoring Plan Template](templates/refactoring-plan.md) - 計画用テンプレート\n\n## スクリプト\n\n- `scripts/analyze-complexity.py` - コード複雑度メトリクスの分析\n- `scripts/detect-smells.py` - スメルの自動検出\n\n## バージョン履歴\n\n- v1.0.0 (2025-01-15): Fowler の方法論、段階的アプローチ、ユーザー相談ポイントを備えた初版リリース\n","ja/03-skills/refactor/references/code-smells.md":"<!-- i18n-source: 03-skills/refactor/references/code-smells.md -->\n<!-- i18n-source-sha: 245272f -->\n<!-- i18n-date: 2026-04-27 -->\n# コードスメルカタログ\n\nMartin Fowler 著『Refactoring』(第 2 版) に基づく、コードスメルの包括的なリファレンスである。コードスメルはより深い問題の症状であり、コード設計に何か問題がある可能性を示す指標となる。\n\n> \"A code smell is a surface indication that usually corresponds to a deeper problem in the system.\" — Martin Fowler\n\n---\n\n## Bloaters（肥満児）\n\n効果的に扱うには大きくなりすぎたものを表すコードスメル群である。\n\n### Long Method（長すぎる関数）\n\n**兆候:**\n- メソッドが 30〜50 行を超える\n- メソッド全体を見るのにスクロールが必要\n- ネストが多重になっている\n- セクションごとに何をしているかを説明するコメントがある\n\n**なぜ悪いか:**\n- 理解しづらい\n- 単独でテストするのが難しい\n- 変更が予期しない影響を及ぼす\n- 内部に重複ロジックが隠れる\n\n**リファクタリング:**\n- メソッドの抽出\n- Replace Temp with Query\n- パラメータオブジェクトの導入\n- Replace Method with Method Object\n- 条件記述の分解\n\n**例（Before）:**\n```javascript\nfunction processOrder(order) {\n  // 注文の検証 (20 行)\n  if (!order.items) throw new Error('No items');\n  if (order.items.length === 0) throw new Error('Empty order');\n  // ... さらに検証\n\n  // 合計金額の計算 (30 行)\n  let subtotal = 0;\n  for (const item of order.items) {\n    subtotal += item.price * item.quantity;\n  }\n  // ... 税、送料、割引\n\n  // 通知の送信 (20 行)\n  // ... メール送信ロジック\n}\n```\n\n**例（After）:**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const totals = calculateOrderTotals(order);\n  sendOrderNotifications(order, totals);\n  return { order, totals };\n}\n```\n\n---\n\n### Large Class（巨大なクラス）\n\n**兆候:**\n- クラスのインスタンス変数が多い(7〜10 個超)\n- クラスのメソッドが多い(15〜20 個超)\n- クラス名が漠然としている(Manager、Handler、Processor)\n- 全インスタンス変数を使わないメソッドがある\n\n**なぜ悪いか:**\n- 単一責任原則に違反する\n- テストが困難\n- 変更が無関係な機能にも波及する\n- 部分的な再利用が難しい\n\n**リファクタリング:**\n- クラスの抽出\n- Extract Subclass\n- Extract Interface\n\n**検出基準:**\n```\nコード行数 > 300\nメソッド数 > 15\nフィールド数 > 10\n```\n\n---\n\n### Primitive Obsession（プリミティブ型への執着）\n\n**兆候:**\n- ドメイン概念にプリミティブを使う(メールに string、金額に int)\n- オブジェクトでなくプリミティブの配列を使う\n- タイプコードに文字列定数を使う\n- マジックナンバーやマジックストリング\n\n**なぜ悪いか:**\n- 型レベルでの検証ができない\n- ロジックがコードベース全体に散らばる\n- 誤った値を渡しやすい\n- ドメイン概念が欠落する\n\n**リファクタリング:**\n- Replace Primitive with Object\n- Replace Type Code with Class\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**例（Before）:**\n```javascript\nconst user = {\n  email: 'john@example.com',     // 単なる文字列\n  phone: '1234567890',           // 単なる文字列\n  status: 'active',              // マジックストリング\n  balance: 10050                 // セント単位の整数\n};\n```\n\n**例（After）:**\n```javascript\nconst user = {\n  email: new Email('john@example.com'),\n  phone: new PhoneNumber('1234567890'),\n  status: UserStatus.ACTIVE,\n  balance: Money.cents(10050)\n};\n```\n\n---\n\n### Long Parameter List（長すぎるパラメータリスト）\n\n**兆候:**\n- パラメータが 4 個以上のメソッド\n- 常に一緒に現れるパラメータ\n- メソッドの振る舞いを切り替える真偽値フラグ\n- null/undefined が頻繁に渡される\n\n**なぜ悪いか:**\n- 正しく呼び出すのが難しい\n- 引数順序の混乱を招く\n- メソッドが多くを抱え込んでいるサイン\n- パラメータの追加が難しい\n\n**リファクタリング:**\n- パラメータオブジェクトの導入\n- Preserve Whole Object\n- Replace Parameter with Method Call\n- Remove Flag Argument\n\n**例（Before）:**\n```javascript\nfunction createUser(firstName, lastName, email, phone,\n                    street, city, state, zip,\n                    isAdmin, isActive, createdBy) {\n  // ...\n}\n```\n\n**例（After）:**\n```javascript\nfunction createUser(personalInfo, address, options) {\n  // personalInfo: { firstName, lastName, email, phone }\n  // address: { street, city, state, zip }\n  // options: { isAdmin, isActive, createdBy }\n}\n```\n\n---\n\n### Data Clumps（データの群れ）\n\n**兆候:**\n- 同じ 3 個以上のフィールドが繰り返し一緒に現れる\n- 常に一緒に渡されるパラメータ群\n- 一塊として属するべきフィールド集合を持つクラス\n\n**なぜ悪いか:**\n- 取り扱いロジックが重複する\n- 抽象化が欠けている\n- 拡張しづらい\n- 隠れたクラスの存在を示す\n\n**リファクタリング:**\n- クラスの抽出\n- パラメータオブジェクトの導入\n- Preserve Whole Object\n\n**例:**\n```javascript\n// データの群れ: (x, y, z) 座標\nfunction movePoint(x, y, z, dx, dy, dz) { }\nfunction scalePoint(x, y, z, factor) { }\nfunction distanceBetween(x1, y1, z1, x2, y2, z2) { }\n\n// Point3D クラスを抽出\nclass Point3D {\n  constructor(x, y, z) { }\n  move(delta) { }\n  scale(factor) { }\n  distanceTo(other) { }\n}\n```\n\n---\n\n## Object-Orientation Abusers（オブジェクト指向の濫用者）\n\nオブジェクト指向の原則を不完全または誤って使っていることを示すスメル群である。\n\n### Switch Statements（スイッチ文）\n\n**兆候:**\n- 長い switch/case や if/else の連鎖\n- 同じ switch が複数箇所に存在\n- タイプコードに対する switch\n- 新ケース追加で各所を変更する必要がある\n\n**なぜ悪いか:**\n- 開放閉鎖原則に違反する\n- 全ての switch 箇所に変更が波及する\n- 拡張が困難\n- ポリモーフィズム不在のサインであることが多い\n\n**リファクタリング:**\n- ポリモーフィズムによる条件記述の置き換え\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**例（Before）:**\n```javascript\nfunction calculatePay(employee) {\n  switch (employee.type) {\n    case 'hourly':\n      return employee.hours * employee.rate;\n    case 'salaried':\n      return employee.salary / 12;\n    case 'commissioned':\n      return employee.sales * employee.commission;\n  }\n}\n```\n\n**例（After）:**\n```javascript\nclass HourlyEmployee {\n  calculatePay() {\n    return this.hours * this.rate;\n  }\n}\n\nclass SalariedEmployee {\n  calculatePay() {\n    return this.salary / 12;\n  }\n}\n```\n\n---\n\n### Temporary Field（一時的フィールド）\n\n**兆候:**\n- 一部のメソッドでのみ使用されるインスタンス変数\n- 条件付きで設定されるフィールド\n- 特定ケースのために複雑な初期化を要する\n\n**なぜ悪いか:**\n- 紛らわしい - フィールドが存在するが null の場合がある\n- オブジェクトの状態が理解しづらい\n- 隠れた条件分岐ロジックを示す\n\n**リファクタリング:**\n- クラスの抽出\n- Introduce Null Object\n- Replace Temp Field with Local\n\n---\n\n### Refused Bequest（相続拒否）\n\n**兆候:**\n- サブクラスが継承したメソッド/データを使わない\n- サブクラスがオーバーライドして何もしない\n- IS-A 関係ではなくコード再利用目的の継承\n\n**なぜ悪いか:**\n- 抽象化が誤っている\n- リスコフの置換原則に違反する\n- 階層が誤解を招く\n\n**リファクタリング:**\n- Push Down Method/Field\n- Replace Subclass with Delegate\n- Replace Inheritance with Delegation\n\n---\n\n### Alternative Classes with Different Interfaces（異なるインターフェイスの代替クラス）\n\n**兆候:**\n- 似たことをする 2 つのクラス\n- 同じ概念に異なるメソッド名を使っている\n- 互いに置換可能だが共通インターフェイスがない\n\n**なぜ悪いか:**\n- 実装が重複する\n- 共通インターフェイスがない\n- 切り替えが難しい\n\n**リファクタリング:**\n- Rename Method\n- Move Method\n- Extract Superclass\n- Extract Interface\n\n---\n\n## Change Preventers（変更の妨げ）\n\n変更を困難にするスメル群 - ある変更のために他の多くを変える必要が生じる。\n\n### Divergent Change（変更の発散）\n\n**兆候:**\n- 1 つのクラスが異なる複数の理由で変更される\n- 異なる領域の変更が同じクラスへの編集を引き起こす\n- そのクラスは「神クラス」化している\n\n**なぜ悪いか:**\n- 単一責任原則に違反する\n- 変更頻度が高くなる\n- マージコンフリクトを招く\n\n**リファクタリング:**\n- クラスの抽出\n- Extract Superclass\n- Extract Subclass\n\n**例:**\n`User` クラスが次の理由で変更される:\n- 認証の変更\n- プロフィールの変更\n- 課金の変更\n- 通知の変更\n\n→ 抽出: `AuthService`、`ProfileService`、`BillingService`、`NotificationService`\n\n---\n\n### Shotgun Surgery（散弾銃手術）\n\n**兆候:**\n- 1 つの変更で多くのクラスへの編集が必要\n- 小さな機能でも 10 ファイル以上に手を入れる\n- 変更箇所が散在し、すべてを見つけにくい\n\n**なぜ悪いか:**\n- 修正漏れが起きやすい\n- 結合度が高い\n- 変更がエラーを誘発しやすい\n\n**リファクタリング:**\n- Move Method\n- Move Field\n- Inline Class\n\n**検出基準:**\n1 フィールドの追加で 5 ファイル以上の変更が必要かを確認する。\n\n---\n\n### Parallel Inheritance Hierarchies（並行継承階層）\n\n**兆候:**\n- 一方の階層にサブクラスを作ると、もう一方にも作る必要がある\n- クラス名のプレフィックスが揃っている(例: `DatabaseOrder`、`DatabaseProduct`)\n\n**なぜ悪いか:**\n- 保守コストが倍になる\n- 階層間の結合度が高い\n- 片側を忘れやすい\n\n**リファクタリング:**\n- Move Method\n- Move Field\n- 一方の階層を削除する\n\n---\n\n## Dispensables（不要物）\n\n不要であり削除すべきものを表すスメル群である。\n\n### Comments（過剰なコメント）\n\n**兆候:**\n- コードが何をしているかを説明するコメント\n- コメントアウトされたコード\n- 永遠に残る TODO/FIXME\n- 言い訳のコメント\n\n**なぜ悪いか:**\n- コメントは嘘をつく(コードと乖離する)\n- コードは自己文書化されているべき\n- 死んだコードは混乱を生む\n\n**リファクタリング:**\n- メソッドの抽出(名前で「何」を表す)\n- Rename(コメントなしで明確化)\n- コメントアウトされたコードの削除\n- Introduce Assertion\n\n**良いコメントと悪いコメント:**\n```javascript\n// 悪い: 「何」を説明している\n// users をループしてアクティブかどうか確認\nfor (const user of users) {\n  if (user.status === 'active') { }\n}\n\n// 良い: 「なぜ」を説明している\n// アクティブなユーザーのみ。非アクティブはクリーンアップジョブで処理される\nconst activeUsers = users.filter(u => u.isActive);\n```\n\n---\n\n### Duplicate Code（重複したコード）\n\n**兆候:**\n- 同じコードが複数箇所にある\n- わずかな違いだけの似たコード\n- コピペのパターン\n\n**なぜ悪いか:**\n- バグ修正を複数箇所で行う必要がある\n- 不整合のリスク\n- コードベースが肥大化する\n\n**リファクタリング:**\n- メソッドの抽出\n- クラスの抽出\n- Pull Up Method(階層内)\n- Form Template Method\n\n**検出ルール:**\n3 回以上重複するコードは抽出すべきである。\n\n---\n\n### Lazy Class（怠け者のクラス）\n\n**兆候:**\n- クラスが存在を正当化できるほど働いていない\n- 付加価値のないラッパー\n- 過剰設計の結果\n\n**なぜ悪いか:**\n- 保守オーバーヘッド\n- 不要な間接参照\n- メリットなき複雑さ\n\n**リファクタリング:**\n- Inline Class\n- Collapse Hierarchy\n\n---\n\n### Dead Code（デッドコード）\n\n**兆候:**\n- 到達不能なコード\n- 使われていない変数/メソッド/クラス\n- コメントアウトされたコード\n- 起こり得ない条件下にあるコード\n\n**なぜ悪いか:**\n- 混乱を招く\n- 保守の負担\n- 理解の速度を落とす\n\n**リファクタリング:**\n- デッドコードの削除\n- Safe Delete\n\n**検出基準:**\n```bash\n# 未使用のエクスポートを探す\n# 参照されない関数を探す\n# IDE の「未使用」警告を確認\n```\n\n---\n\n### Speculative Generality（投機的一般化）\n\n**兆候:**\n- サブクラスが 1 つしかない抽象クラス\n- 「将来のため」の未使用パラメータ\n- 委譲のみのメソッド\n- 1 用途しかない「フレームワーク」\n\n**なぜ悪いか:**\n- メリットなき複雑さ\n- YAGNI(You Ain't Gonna Need It)\n- 理解しづらい\n\n**リファクタリング:**\n- Collapse Hierarchy\n- Inline Class\n- Remove Parameter\n- Rename Method\n\n---\n\n## Couplers（結合の問題）\n\nクラス間の過剰な結合を表すスメル群である。\n\n### Feature Envy（機能の横恋慕）\n\n**兆候:**\n- メソッドが自クラスより他クラスのデータを多く使う\n- 他オブジェクトへの getter 呼び出しが多い\n- データと振る舞いが分離している\n\n**なぜ悪いか:**\n- 振る舞いの置き場所が誤っている\n- カプセル化が不十分\n- 保守が難しい\n\n**リファクタリング:**\n- Move Method\n- Move Field\n- メソッドの抽出(その後 move)\n\n**例（Before）:**\n```javascript\nclass Order {\n  getDiscountedPrice(customer) {\n    // customer のデータを多く使っている\n    if (customer.loyaltyYears > 5) {\n      return this.price * customer.discountRate;\n    }\n    return this.price;\n  }\n}\n```\n\n**例（After）:**\n```javascript\nclass Customer {\n  getDiscountedPriceFor(price) {\n    if (this.loyaltyYears > 5) {\n      return price * this.discountRate;\n    }\n    return price;\n  }\n}\n```\n\n---\n\n### Inappropriate Intimacy（不適切な親密さ）\n\n**兆候:**\n- クラスが互いのプライベート部分にアクセスする\n- 双方向の参照\n- サブクラスが親について詳しすぎる\n\n**なぜ悪いか:**\n- 結合度が高い\n- 変更が連鎖する\n- 一方を変えると他方も変える必要がある\n\n**リファクタリング:**\n- Move Method\n- Move Field\n- Change Bidirectional to Unidirectional\n- クラスの抽出\n- Hide Delegate\n\n---\n\n### Message Chains（メッセージの連鎖）\n\n**兆候:**\n- メソッド呼び出しの長い連鎖: `a.getB().getC().getD().getValue()`\n- クライアントがナビゲーション構造に依存している\n- 「列車事故」コード\n\n**なぜ悪いか:**\n- 脆弱 - 連鎖中のいずれかが変わると壊れる\n- デメテルの法則に違反する\n- 構造への結合\n\n**リファクタリング:**\n- Hide Delegate\n- メソッドの抽出\n- Move Method\n\n**例:**\n```javascript\n// 悪い: メッセージの連鎖\nconst managerName = employee.getDepartment().getManager().getName();\n\n// 良い: 委譲を隠す\nconst managerName = employee.getManagerName();\n```\n\n---\n\n### Middle Man（仲介人）\n\n**兆候:**\n- 他クラスへ委譲するだけのクラス\n- メソッドの半数が委譲\n- 付加価値がない\n\n**なぜ悪いか:**\n- 不要な間接参照\n- 保守オーバーヘッド\n- アーキテクチャが分かりにくい\n\n**リファクタリング:**\n- Remove Middle Man\n- メソッドのインライン化\n\n---\n\n## スメル深刻度ガイド\n\n| 深刻度 | 説明 | 対応 |\n|----------|-------------|--------|\n| **Critical** | 開発をブロックし、バグの原因となる | 直ちに修正 |\n| **High** | 保守負担が大きい | 当該スプリント中に修正 |\n| **Medium** | 目に付くが許容範囲 | 近い将来に計画 |\n| **Low** | 軽微な不便 | 機会があれば修正 |\n\n---\n\n## 簡易検出チェックリスト\n\nコードをスキャンする際に使うチェックリストである。\n\n- [ ] 30 行を超えるメソッドはあるか?\n- [ ] 300 行を超えるクラスはあるか?\n- [ ] 4 個を超えるパラメータを持つメソッドはあるか?\n- [ ] 重複したコードブロックはあるか?\n- [ ] タイプコードに対する switch/case はあるか?\n- [ ] 使われていないコードはあるか?\n- [ ] 他クラスのデータを多く使っているメソッドはあるか?\n- [ ] メソッド呼び出しの長い連鎖はあるか?\n- [ ] 「なぜ」ではなく「何」を説明しているコメントはあるか?\n- [ ] オブジェクト化すべきプリミティブはあるか?\n\n---\n\n## 参考文献\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Kerievsky, J. (2004). *Refactoring to Patterns*\n- Feathers, M. (2004). *Working Effectively with Legacy Code*\n","ja/03-skills/refactor/references/refactoring-catalog.md":"<!-- i18n-source: 03-skills/refactor/references/refactoring-catalog.md -->\n<!-- i18n-source-sha: 245272f -->\n<!-- i18n-date: 2026-04-27 -->\n\n# リファクタリングカタログ\n\nMartin Fowler 著『Refactoring』(第 2 版) から厳選したリファクタリング技法のカタログである。各リファクタリングには動機、手順、例を掲載している。\n\n> 「リファクタリングは、その手順、すなわち変更を実施するための正確なステップ列によって定義される。」 — Martin Fowler\n\n---\n\n## このカタログの使い方\n\n1. コードスメルのリファレンスを使って **コードスメルを特定する**\n2. このカタログから **対応するリファクタリングを探す**\n3. **手順に沿って一段ずつ進める**\n4. **各ステップごとにテスト** を実行し、振る舞いが保たれていることを確認する\n\n**鉄則**: ある手順に 10 分以上かかるのであれば、もっと小さなステップに分割すること。\n\n---\n\n## 最も頻出するリファクタリング\n\n### メソッドの抽出 (Extract Method)\n\n**使う場面**: 長いメソッド、重複コード、概念に名前を付けたいとき\n\n**動機**: コード片を、目的を表す名前を持つメソッドに切り出す。\n\n**手順**:\n1. やっていること(どうやってではなく)にちなんだ名前で新しいメソッドを作成する\n2. コード片を新しいメソッドへコピーする\n3. コード片で使われているローカル変数を洗い出す\n4. ローカル変数をパラメータとして渡す(あるいはメソッド内で宣言する)\n5. 戻り値を適切に処理する\n6. 元のコード片を新しいメソッドの呼び出しに置き換える\n7. テストする\n\n**Before**:\n```javascript\nfunction printOwing(invoice) {\n  let outstanding = 0;\n\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n\n  // 未払額の計算\n  for (const order of invoice.orders) {\n    outstanding += order.amount;\n  }\n\n  // 詳細の出力\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n**After**:\n```javascript\nfunction printOwing(invoice) {\n  printBanner();\n  const outstanding = calculateOutstanding(invoice);\n  printDetails(invoice, outstanding);\n}\n\nfunction printBanner() {\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n}\n\nfunction calculateOutstanding(invoice) {\n  return invoice.orders.reduce((sum, order) => sum + order.amount, 0);\n}\n\nfunction printDetails(invoice, outstanding) {\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n---\n\n### メソッドのインライン化 (Inline Method)\n\n**使う場面**: メソッド本体が名前と同じくらい明快な場合、過度な委譲が見られる場合\n\n**動機**: メソッドが価値を加えていない場合、不要な間接参照を取り除く。\n\n**手順**:\n1. メソッドがポリモーフィックでないことを確認する\n2. メソッドの呼び出し箇所をすべて見つける\n3. 各呼び出しをメソッド本体で置き換える\n4. 置き換えるたびにテストする\n5. メソッド定義を削除する\n\n**Before**:\n```javascript\nfunction getRating(driver) {\n  return moreThanFiveLateDeliveries(driver) ? 2 : 1;\n}\n\nfunction moreThanFiveLateDeliveries(driver) {\n  return driver.numberOfLateDeliveries > 5;\n}\n```\n\n**After**:\n```javascript\nfunction getRating(driver) {\n  return driver.numberOfLateDeliveries > 5 ? 2 : 1;\n}\n```\n\n---\n\n### 変数の抽出 (Extract Variable)\n\n**使う場面**: 複雑で理解しづらい式があるとき\n\n**動機**: 複雑な式の一部に名前を付ける。\n\n**手順**:\n1. 式に副作用がないことを確認する\n2. イミュータブルな変数を宣言する\n3. 式(または式の一部)の結果をその変数に代入する\n4. 元の式を変数で置き換える\n5. テストする\n\n**Before**:\n```javascript\nreturn order.quantity * order.itemPrice -\n  Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +\n  Math.min(order.quantity * order.itemPrice * 0.1, 100);\n```\n\n**After**:\n```javascript\nconst basePrice = order.quantity * order.itemPrice;\nconst quantityDiscount = Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;\nconst shipping = Math.min(basePrice * 0.1, 100);\nreturn basePrice - quantityDiscount + shipping;\n```\n\n---\n\n### 変数のインライン化 (Inline Variable)\n\n**使う場面**: 変数名が式以上の情報を伝えていないとき\n\n**動機**: 不要な間接参照を取り除く。\n\n**手順**:\n1. 右辺に副作用がないことを確認する\n2. 変数がイミュータブルでなければイミュータブルにし、テストする\n3. 最初の参照箇所を見つけて式で置き換える\n4. テストする\n5. すべての参照箇所について繰り返す\n6. 宣言と代入を削除する\n7. テストする\n\n---\n\n### 変数名の変更 (Rename Variable)\n\n**使う場面**: 名前が目的を明確に伝えていないとき\n\n**動機**: クリーンなコードには良い名前が不可欠である。\n\n**手順**:\n1. 変数が広く使われている場合は、カプセル化を検討する\n2. すべての参照箇所を見つける\n3. 各参照箇所を変更する\n4. テストする\n\n**Tips**:\n- 意図を明らかにする名前を使う\n- 略語を避ける\n- ドメイン用語を用いる\n\n```javascript\n// 悪い例\nconst d = 30;\nconst x = users.filter(u => u.a);\n\n// 良い例\nconst daysSinceLastLogin = 30;\nconst activeUsers = users.filter(user => user.isActive);\n```\n\n---\n\n### 関数宣言の変更 (Change Function Declaration)\n\n**使う場面**: 関数名が目的を表していない、パラメータの変更が必要な場合\n\n**動機**: 良い関数名はコードを自己説明的にする。\n\n**手順 (シンプル版)**:\n1. 不要なパラメータを削除する\n2. 名前を変更する\n3. 必要なパラメータを追加する\n4. テストする\n\n**手順 (マイグレーション版 — 複雑な変更向け)**:\n1. パラメータを削除する場合、それが使われていないことを確認する\n2. 望ましい宣言の新しい関数を作成する\n3. 古い関数から新しい関数を呼び出すようにする\n4. テストする\n5. 呼び出し側を新しい関数を使うように変更する\n6. 各変更後にテストする\n7. 古い関数を削除する\n\n**Before**:\n```javascript\nfunction circum(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n**After**:\n```javascript\nfunction circumference(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n---\n\n### 変数のカプセル化 (Encapsulate Variable)\n\n**使う場面**: データに複数箇所から直接アクセスしているとき\n\n**動機**: データ操作のための明確なアクセスポイントを提供する。\n\n**手順**:\n1. getter と setter 関数を作成する\n2. すべての参照箇所を見つける\n3. 読み取りを getter で置き換える\n4. 書き込みを setter で置き換える\n5. 各変更後にテストする\n6. 変数の可視性を制限する\n\n**Before**:\n```javascript\nlet defaultOwner = { firstName: \"Martin\", lastName: \"Fowler\" };\n\n// 多くの場所で利用される\nspaceship.owner = defaultOwner;\n```\n\n**After**:\n```javascript\nlet defaultOwnerData = { firstName: \"Martin\", lastName: \"Fowler\" };\n\nfunction defaultOwner() { return defaultOwnerData; }\nfunction setDefaultOwner(arg) { defaultOwnerData = arg; }\n\nspaceship.owner = defaultOwner();\n```\n\n---\n\n### パラメータオブジェクトの導入 (Introduce Parameter Object)\n\n**使う場面**: いくつかのパラメータがしばしばまとまって登場する場合\n\n**動機**: 自然にまとまるべきデータをグループ化する。\n\n**手順**:\n1. グループ化したパラメータ用の新しいクラス/構造体を作成する\n2. テストする\n3. 「関数宣言の変更」で新しいオブジェクトを追加する\n4. テストする\n5. グループ内の各パラメータについて、関数から取り除き新しいオブジェクトを使うようにする\n6. 各変更後にテストする\n\n**Before**:\n```javascript\nfunction amountInvoiced(startDate, endDate) { ... }\nfunction amountReceived(startDate, endDate) { ... }\nfunction amountOverdue(startDate, endDate) { ... }\n```\n\n**After**:\n```javascript\nclass DateRange {\n  constructor(start, end) {\n    this.start = start;\n    this.end = end;\n  }\n}\n\nfunction amountInvoiced(dateRange) { ... }\nfunction amountReceived(dateRange) { ... }\nfunction amountOverdue(dateRange) { ... }\n```\n\n---\n\n### 関数群のクラス化 (Combine Functions into Class)\n\n**使う場面**: 複数の関数が同じデータを操作している場合\n\n**動機**: 関数を、それらが操作するデータと共にまとめる。\n\n**手順**:\n1. 共通データに「レコードのカプセル化 (Encapsulate Record)」を適用する\n2. 各関数をクラス内に移動する\n3. 移動するたびにテストする\n4. データ引数をクラスのフィールド利用に置き換える\n\n**Before**:\n```javascript\nfunction base(reading) { ... }\nfunction taxableCharge(reading) { ... }\nfunction calculateBaseCharge(reading) { ... }\n```\n\n**After**:\n```javascript\nclass Reading {\n  constructor(data) { this._data = data; }\n\n  get base() { ... }\n  get taxableCharge() { ... }\n  get calculateBaseCharge() { ... }\n}\n```\n\n---\n\n### 段階の分割 (Split Phase)\n\n**使う場面**: コードが 2 つの異なる事柄を扱っている場合\n\n**動機**: コードを明確な境界を持つ別々のフェーズに分離する。\n\n**手順**:\n1. 第 2 フェーズ用の関数を作成する\n2. テストする\n3. フェーズ間の中間データ構造を導入する\n4. テストする\n5. 第 1 フェーズを独立した関数として抽出する\n6. テストする\n\n**Before**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  const shippingPerCase = (basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = quantity * shippingPerCase;\n  return basePrice - discount + shippingCost;\n}\n```\n\n**After**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const priceData = calculatePricingData(product, quantity);\n  return applyShipping(priceData, shippingMethod);\n}\n\nfunction calculatePricingData(product, quantity) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  return { basePrice, quantity, discount };\n}\n\nfunction applyShipping(priceData, shippingMethod) {\n  const shippingPerCase = (priceData.basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = priceData.quantity * shippingPerCase;\n  return priceData.basePrice - priceData.discount + shippingCost;\n}\n```\n\n---\n\n## 機能の移動\n\n### メソッドの移動 (Move Method)\n\n**使う場面**: メソッドが自分のクラスより他のクラスの機能を多く使っている場合\n\n**動機**: 関数を、最もよく利用するデータの近くに置く。\n\n**手順**:\n1. 自クラス内でメソッドが利用しているプログラム要素をすべて調べる\n2. メソッドがポリモーフィックかどうか確認する\n3. 移動先クラスにメソッドをコピーする\n4. 新しいコンテキストに合わせて調整する\n5. 元のメソッドが移動先に委譲するようにする\n6. テストする\n7. 元のメソッドの削除を検討する\n\n---\n\n### フィールドの移動 (Move Field)\n\n**使う場面**: フィールドが他のクラスでより多く使われている場合\n\n**動機**: データを、それを使う関数と共に保持する。\n\n**手順**:\n1. まだの場合はフィールドをカプセル化する\n2. テストする\n3. 移動先にフィールドを作成する\n4. 参照箇所を移動先のフィールドを使うように更新する\n5. テストする\n6. 元のフィールドを削除する\n\n---\n\n### 関数への文の移動 (Move Statements into Function)\n\n**使う場面**: 同じコードが必ずある関数呼び出しと一緒に現れる場合\n\n**動機**: 繰り返しコードを関数内に移動して重複を取り除く。\n\n**手順**:\n1. まだの場合は繰り返しコードを関数として抽出する\n2. その関数の中に文を移動する\n3. テストする\n4. 呼び出し側で単独の文が不要になったら削除する\n\n---\n\n### 呼び出し側への文の移動 (Move Statements to Callers)\n\n**使う場面**: 共通の振る舞いが呼び出し側ごとに異なる場合\n\n**動機**: 振る舞いを変える必要があるなら、関数の外に移す。\n\n**手順**:\n1. 移動するコードに「メソッドの抽出」を適用する\n2. 元の関数に「メソッドのインライン化」を適用する\n3. インライン化された呼び出しを削除する\n4. 抽出したコードを各呼び出し側に移動する\n5. テストする\n\n---\n\n## データの再編成\n\n### プリミティブをオブジェクトで置き換える (Replace Primitive with Object)\n\n**使う場面**: データ項目に単純な値以上の振る舞いが必要な場合\n\n**動機**: データを振る舞いと共にカプセル化する。\n\n**手順**:\n1. 「変数のカプセル化」を適用する\n2. シンプルな値クラスを作成する\n3. setter を新しいインスタンス生成に変更する\n4. getter を値の返却に変更する\n5. テストする\n6. 新しいクラスにより豊かな振る舞いを追加する\n\n**Before**:\n```javascript\nclass Order {\n  constructor(data) {\n    this.priority = data.priority; // 文字列: \"high\"、\"rush\" など\n  }\n}\n\n// 利用箇所\nif (order.priority === \"high\" || order.priority === \"rush\") { ... }\n```\n\n**After**:\n```javascript\nclass Priority {\n  constructor(value) {\n    if (!Priority.legalValues().includes(value))\n      throw new Error(`Invalid priority: ${value}`);\n    this._value = value;\n  }\n\n  static legalValues() { return ['low', 'normal', 'high', 'rush']; }\n  get value() { return this._value; }\n\n  higherThan(other) {\n    return Priority.legalValues().indexOf(this._value) >\n           Priority.legalValues().indexOf(other._value);\n  }\n}\n\n// 利用箇所\nif (order.priority.higherThan(new Priority(\"normal\"))) { ... }\n```\n\n---\n\n### 一時変数を問い合わせで置き換える (Replace Temp with Query)\n\n**使う場面**: 一時変数が式の結果を保持している場合\n\n**動機**: 式を関数として切り出すことでコードを明快にする。\n\n**手順**:\n1. 変数が一度だけ代入されていることを確認する\n2. 代入の右辺をメソッドとして抽出する\n3. 一時変数の参照箇所をメソッド呼び出しで置き換える\n4. テストする\n5. 一時変数の宣言と代入を削除する\n\n**Before**:\n```javascript\nconst basePrice = this._quantity * this._itemPrice;\nif (basePrice > 1000) {\n  return basePrice * 0.95;\n} else {\n  return basePrice * 0.98;\n}\n```\n\n**After**:\n```javascript\nget basePrice() {\n  return this._quantity * this._itemPrice;\n}\n\n// メソッド内\nif (this.basePrice > 1000) {\n  return this.basePrice * 0.95;\n} else {\n  return this.basePrice * 0.98;\n}\n```\n\n---\n\n## 条件記述の単純化\n\n### 条件記述の分解 (Decompose Conditional)\n\n**使う場面**: 複雑な条件分岐 (if-then-else) があるとき\n\n**動機**: 条件と動作を抽出して意図を明確にする。\n\n**手順**:\n1. 条件部分に「メソッドの抽出」を適用する\n2. then 節に「メソッドの抽出」を適用する\n3. else 節 (もしあれば) に「メソッドの抽出」を適用する\n\n**Before**:\n```javascript\nif (!aDate.isBefore(plan.summerStart) && !aDate.isAfter(plan.summerEnd)) {\n  charge = quantity * plan.summerRate;\n} else {\n  charge = quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n**After**:\n```javascript\nif (isSummer(aDate, plan)) {\n  charge = summerCharge(quantity, plan);\n} else {\n  charge = regularCharge(quantity, plan);\n}\n\nfunction isSummer(date, plan) {\n  return !date.isBefore(plan.summerStart) && !date.isAfter(plan.summerEnd);\n}\n\nfunction summerCharge(quantity, plan) {\n  return quantity * plan.summerRate;\n}\n\nfunction regularCharge(quantity, plan) {\n  return quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n---\n\n### 条件式の統合 (Consolidate Conditional Expression)\n\n**使う場面**: 同じ結果を返す条件が複数あるとき\n\n**動機**: それらの条件が単一のチェックであることを明らかにする。\n\n**手順**:\n1. 条件に副作用がないことを確認する\n2. 条件を `and` または `or` で結合する\n3. 結合した条件に「メソッドの抽出」を検討する\n\n**Before**:\n```javascript\nif (employee.seniority < 2) return 0;\nif (employee.monthsDisabled > 12) return 0;\nif (employee.isPartTime) return 0;\n```\n\n**After**:\n```javascript\nif (isNotEligibleForDisability(employee)) return 0;\n\nfunction isNotEligibleForDisability(employee) {\n  return employee.seniority < 2 ||\n         employee.monthsDisabled > 12 ||\n         employee.isPartTime;\n}\n```\n\n---\n\n### ガード節による入れ子の条件記述の置き換え (Replace Nested Conditional with Guard Clauses)\n\n**使う場面**: 入れ子の条件分岐が深く、流れを追いにくいとき\n\n**動機**: 特殊ケースにガード節を使い、通常フローを明確に保つ。\n\n**手順**:\n1. 特殊ケースの条件を見つける\n2. それらを早期 return するガード節で置き換える\n3. 各変更後にテストする\n\n**Before**:\n```javascript\nfunction payAmount(employee) {\n  let result;\n  if (employee.isSeparated) {\n    result = { amount: 0, reasonCode: \"SEP\" };\n  } else {\n    if (employee.isRetired) {\n      result = { amount: 0, reasonCode: \"RET\" };\n    } else {\n      result = calculateNormalPay(employee);\n    }\n  }\n  return result;\n}\n```\n\n**After**:\n```javascript\nfunction payAmount(employee) {\n  if (employee.isSeparated) return { amount: 0, reasonCode: \"SEP\" };\n  if (employee.isRetired) return { amount: 0, reasonCode: \"RET\" };\n  return calculateNormalPay(employee);\n}\n```\n\n---\n\n### ポリモーフィズムによる条件記述の置き換え (Replace Conditional with Polymorphism)\n\n**使う場面**: 型に基づく switch/case、型ごとに変化する条件ロジック\n\n**動機**: オブジェクト自身に振る舞いを担わせる。\n\n**手順**:\n1. クラス階層を作成する (なければ)\n2. オブジェクト生成にファクトリ関数を使う\n3. 条件ロジックをスーパークラスのメソッドに移す\n4. ケースごとにサブクラスのメソッドを作成する\n5. 元の条件記述を削除する\n\n**Before**:\n```javascript\nfunction plumages(birds) {\n  return birds.map(b => plumage(b));\n}\n\nfunction plumage(bird) {\n  switch (bird.type) {\n    case 'EuropeanSwallow':\n      return \"average\";\n    case 'AfricanSwallow':\n      return (bird.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n    case 'NorwegianBlueParrot':\n      return (bird.voltage > 100) ? \"scorched\" : \"beautiful\";\n    default:\n      return \"unknown\";\n  }\n}\n```\n\n**After**:\n```javascript\nclass Bird {\n  get plumage() { return \"unknown\"; }\n}\n\nclass EuropeanSwallow extends Bird {\n  get plumage() { return \"average\"; }\n}\n\nclass AfricanSwallow extends Bird {\n  get plumage() {\n    return (this.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n  }\n}\n\nclass NorwegianBlueParrot extends Bird {\n  get plumage() {\n    return (this.voltage > 100) ? \"scorched\" : \"beautiful\";\n  }\n}\n\nfunction createBird(data) {\n  switch (data.type) {\n    case 'EuropeanSwallow': return new EuropeanSwallow(data);\n    case 'AfricanSwallow': return new AfricanSwallow(data);\n    case 'NorwegianBlueParrot': return new NorwegianBlueParrot(data);\n    default: return new Bird(data);\n  }\n}\n```\n\n---\n\n### 特殊ケースの導入 (Introduce Special Case / Null Object)\n\n**使う場面**: 特殊ケースに対する null チェックが繰り返される場合\n\n**動機**: 特殊ケースを処理する特殊オブジェクトを返す。\n\n**手順**:\n1. 期待されるインターフェースを持つ特殊ケースクラスを作成する\n2. isSpecialCase チェックを追加する\n3. ファクトリメソッドを導入する\n4. null チェックを特殊ケースオブジェクトの利用で置き換える\n5. テストする\n\n**Before**:\n```javascript\nconst customer = site.customer;\n// ... 多数の箇所でチェック\nif (customer === \"unknown\") {\n  customerName = \"occupant\";\n} else {\n  customerName = customer.name;\n}\n```\n\n**After**:\n```javascript\nclass UnknownCustomer {\n  get name() { return \"occupant\"; }\n  get billingPlan() { return registry.defaultPlan; }\n}\n\n// ファクトリメソッド\nfunction customer(site) {\n  return site.customer === \"unknown\"\n    ? new UnknownCustomer()\n    : site.customer;\n}\n\n// 利用箇所 — null チェック不要\nconst customerName = customer.name;\n```\n\n---\n\n## API のリファクタリング\n\n### 問い合わせと変更の分離 (Separate Query from Modifier)\n\n**使う場面**: 関数が値を返すと同時に副作用も持つ場合\n\n**動機**: どの操作に副作用があるのかを明確にする。\n\n**手順**:\n1. 新しい問い合わせ関数を作成する\n2. 元の関数の戻り値ロジックをコピーする\n3. 元の関数を void を返すように変更する\n4. 戻り値を使っていた呼び出しを置き換える\n5. テストする\n\n**Before**:\n```javascript\nfunction alertForMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") {\n      setOffAlarms();\n      return \"Don\";\n    }\n    if (p === \"John\") {\n      setOffAlarms();\n      return \"John\";\n    }\n  }\n  return \"\";\n}\n```\n\n**After**:\n```javascript\nfunction findMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") return \"Don\";\n    if (p === \"John\") return \"John\";\n  }\n  return \"\";\n}\n\nfunction alertForMiscreant(people) {\n  if (findMiscreant(people) !== \"\") setOffAlarms();\n}\n```\n\n---\n\n### 関数のパラメータ化 (Parameterize Function)\n\n**使う場面**: 似たような処理を異なる値で行う関数が複数あるとき\n\n**動機**: パラメータを追加することで重複を取り除く。\n\n**手順**:\n1. 一つの関数を選ぶ\n2. 変動するリテラル用のパラメータを追加する\n3. 本体をそのパラメータを使うように変更する\n4. テストする\n5. 呼び出し側をパラメータ化された版を使うように変更する\n6. 不要になった関数を削除する\n\n**Before**:\n```javascript\nfunction tenPercentRaise(person) {\n  person.salary = person.salary * 1.10;\n}\n\nfunction fivePercentRaise(person) {\n  person.salary = person.salary * 1.05;\n}\n```\n\n**After**:\n```javascript\nfunction raise(person, factor) {\n  person.salary = person.salary * (1 + factor);\n}\n\n// 利用箇所\nraise(person, 0.10);\nraise(person, 0.05);\n```\n\n---\n\n### フラグ引数の削除 (Remove Flag Argument)\n\n**使う場面**: 関数の振る舞いを切り替えるブール型パラメータがある場合\n\n**動機**: 別々の関数を通して振る舞いを明示的にする。\n\n**手順**:\n1. フラグの値ごとに明示的な関数を作成する\n2. 各呼び出しを適切な新しい関数で置き換える\n3. 各変更後にテストする\n4. 元の関数を削除する\n\n**Before**:\n```javascript\nfunction bookConcert(customer, isPremium) {\n  if (isPremium) {\n    // プレミアム予約のロジック\n  } else {\n    // 通常予約のロジック\n  }\n}\n\nbookConcert(customer, true);\nbookConcert(customer, false);\n```\n\n**After**:\n```javascript\nfunction bookPremiumConcert(customer) {\n  // プレミアム予約のロジック\n}\n\nfunction bookRegularConcert(customer) {\n  // 通常予約のロジック\n}\n\nbookPremiumConcert(customer);\nbookRegularConcert(customer);\n```\n\n---\n\n## 継承の取り扱い\n\n### メソッドの引き上げ (Pull Up Method)\n\n**使う場面**: 同じメソッドが複数のサブクラスにあるとき\n\n**動機**: クラス階層内の重複を取り除く。\n\n**手順**:\n1. メソッド同士が同一であることを確認する\n2. シグネチャが同じであることを確認する\n3. スーパークラスに新しいメソッドを作成する\n4. 一つのサブクラスから本体をコピーする\n5. 一つのサブクラスからメソッドを削除し、テストする\n6. 他のサブクラスのメソッドも順次削除し、その都度テストする\n\n---\n\n### メソッドの押し下げ (Push Down Method)\n\n**使う場面**: サブクラスの一部のみに関係する振る舞いがあるとき\n\n**動機**: メソッドを使われる場所に置く。\n\n**手順**:\n1. メソッドを必要とする各サブクラスにコピーする\n2. スーパークラスからメソッドを削除する\n3. テストする\n4. 必要としないサブクラスからは削除する\n5. テストする\n\n---\n\n### サブクラスを委譲で置き換える (Replace Subclass with Delegate)\n\n**使う場面**: 継承が誤って使われている、もしくはより柔軟性が必要な場合\n\n**動機**: 適切な場面では継承よりコンポジションを優先する。\n\n**手順**:\n1. 委譲先用の空クラスを作成する\n2. 委譲先を保持するフィールドをホストクラスに追加する\n3. ホストから呼ばれる委譲先のコンストラクタを作成する\n4. 機能を委譲先へ移動する\n5. 移動するたびにテストする\n6. 継承を委譲で置き換える\n\n---\n\n## クラスの抽出 (Extract Class)\n\n**使う場面**: 複数の責務を持つ大きなクラスがあるとき\n\n**動機**: クラスを分割して単一責務を保つ。\n\n**手順**:\n1. 責務をどう分けるか決める\n2. 新しいクラスを作成する\n3. フィールドを元のクラスから新しいクラスへ移動する\n4. テストする\n5. メソッドを元のクラスから新しいクラスへ移動する\n6. 移動するたびにテストする\n7. 両クラスを見直して必要なら名前を変更する\n8. 新しいクラスをどう公開するかを決める\n\n**Before**:\n```javascript\nclass Person {\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get officeAreaCode() { return this._officeAreaCode; }\n  set officeAreaCode(arg) { this._officeAreaCode = arg; }\n  get officeNumber() { return this._officeNumber; }\n  set officeNumber(arg) { this._officeNumber = arg; }\n\n  get telephoneNumber() {\n    return `(${this._officeAreaCode}) ${this._officeNumber}`;\n  }\n}\n```\n\n**After**:\n```javascript\nclass Person {\n  constructor() {\n    this._telephoneNumber = new TelephoneNumber();\n  }\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get telephoneNumber() { return this._telephoneNumber.toString(); }\n  get officeAreaCode() { return this._telephoneNumber.areaCode; }\n  set officeAreaCode(arg) { this._telephoneNumber.areaCode = arg; }\n}\n\nclass TelephoneNumber {\n  get areaCode() { return this._areaCode; }\n  set areaCode(arg) { this._areaCode = arg; }\n  get number() { return this._number; }\n  set number(arg) { this._number = arg; }\n  toString() { return `(${this._areaCode}) ${this._number}`; }\n}\n```\n\n---\n\n## クイックリファレンス: スメルからリファクタリングへ\n\n| コードスメル | 主なリファクタリング | 代替 |\n|------------|-------------------|-------------|\n| 長すぎるメソッド (Long Method) | メソッドの抽出 | 一時変数を問い合わせで置き換える |\n| 重複コード (Duplicate Code) | メソッドの抽出 | メソッドの引き上げ |\n| 大きすぎるクラス (Large Class) | クラスの抽出 | サブクラスの抽出 |\n| 長すぎるパラメータリスト (Long Parameter List) | パラメータオブジェクトの導入 | オブジェクトそのものの受け渡し |\n| 機能の横恋慕 (Feature Envy) | メソッドの移動 | メソッドの抽出 + 移動 |\n| データのかたまり (Data Clumps) | クラスの抽出 | パラメータオブジェクトの導入 |\n| プリミティブ依存症 (Primitive Obsession) | プリミティブをオブジェクトで置き換える | タイプコードの置き換え |\n| switch 文 (Switch Statements) | ポリモーフィズムによる条件記述の置き換え | タイプコードの置き換え |\n| 一時的属性 (Temporary Field) | クラスの抽出 | Null オブジェクトの導入 |\n| メッセージの連鎖 (Message Chains) | 委譲の隠蔽 | メソッドの抽出 |\n| 仲介人 (Middle Man) | 中間者の除去 | メソッドのインライン化 |\n| 変更の分散 (Divergent Change) | クラスの抽出 | 段階の分割 |\n| 散弾銃手術 (Shotgun Surgery) | メソッドの移動 | クラスのインライン化 |\n| 死せるコード (Dead Code) | 死せるコードの除去 | - |\n| 投機的一般性 (Speculative Generality) | 階層の平坦化 | クラスのインライン化 |\n\n---\n\n## 参考文献\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- オンラインカタログ: https://refactoring.com/catalog/\n","ja/07-plugins/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=ja%2F07-plugins%2FREADME.md -->","ja/07-plugins/devops-automation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=ja%2F07-plugins%2Fdevops-automation%2FREADME.md -->","ja/07-plugins/documentation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=ja%2F07-plugins%2Fdocumentation%2FREADME.md -->","ja/07-plugins/documentation/commands/generate-readme.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=ja%2F07-plugins%2Fdocumentation%2Fcommands%2Fgenerate-readme.md -->","ja/07-plugins/pr-review/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=ja%2F07-plugins%2Fpr-review%2FREADME.md -->","ja/CLAUDE.md":"<!-- i18n-source: CLAUDE.md -->\n<!-- i18n-source-sha: a70777e -->\n<!-- i18n-date: 2026-04-27 -->\n\n# CLAUDE.md\n\nこのファイルは、本リポジトリ内のコードを扱う際の Claude Code（claude.ai/code）向けガイドである。\n\n## プロジェクト概要\n\nClaude How To は Claude Code 機能のチュートリアルリポジトリである。これは **ドキュメント・アズ・コード** であり、主な成果物は実行可能アプリケーションではなく、番号付きの学習モジュールに整理された Markdown ファイルである。\n\n**アーキテクチャ：** 各モジュール（01〜10）は Claude Code の特定の機能を、コピー＆ペースト可能なテンプレート、Mermaid 図、サンプルとともに解説する。ビルドシステムはドキュメントの品質を検証し、EPUB 電子書籍を生成する。\n\n## よく使うコマンド\n\n### pre-commit 品質チェック\n\nすべてのドキュメントは、コミット前に 5 つの品質チェックを通過しなければならない（pre-commit フックで自動実行される）：\n\n```bash\n# pre-commit フックをインストール（毎コミットで実行）\npre-commit install\n\n# 全チェックを手動で実行\npre-commit run --all-files\n```\n\n5 つのチェックは以下のとおり：\n1. **markdown-lint** — `markdownlint` による Markdown 構造とフォーマット\n2. **cross-references** — 内部リンク、アンカー、コードフェンスの構文（Python スクリプト）\n3. **mermaid-syntax** — すべての Mermaid 図が正しくパースされるかを検証（Python スクリプト）\n4. **link-check** — 外部 URL が到達可能か（Python スクリプト）\n5. **markdown-rendering** — Markdown が壊れずにレンダリングされるか（Python スクリプト）\n\nEPUB ビルドは pre-commit フック **ではない** — CI のみで実行される（`.github/workflows/test.yml` の `build-epub` ジョブ）。本全体をビルドするため時間がかかるからである。mermaid-syntax フックが同じ Pele バンドルですべての図をすでにレンダリングしている。\n\n### 開発環境のセットアップ\n\n```bash\n# uv（Python パッケージマネージャ）をインストール\npip install uv\n\n# 仮想環境を作成して Python 依存関係をインストール\nuv venv\nsource .venv/bin/activate\nuv pip install -r scripts/requirements-dev.txt\n\n# Node.js ツール（Markdown リンタ）をインストール\nnpm install -g markdownlint-cli\n\n# Mermaid 図は Pele でレンダリングする（Node.js >= 20 が必要。グローバルインストールは不要）\nnode --version\n\n# pre-commit フックをインストール\nuv pip install pre-commit\npre-commit install\n```\n\n### テスト\n\n`scripts/` 内の Python スクリプトはユニットテストを持つ：\n\n```bash\n# 全テストを実行\npytest scripts/tests/ -v\n\n# カバレッジ付きで実行\npytest scripts/tests/ -v --cov=scripts --cov-report=html\n\n# 特定のテストを実行\npytest scripts/tests/test_build_epub.py -v\n```\n\n### コード品質\n\n```bash\n# Python コードをリント・整形\nruff check scripts/\nruff format scripts/\n\n# セキュリティスキャン\nbandit -c scripts/pyproject.toml -r scripts/ --exclude scripts/tests/\n\n# 型チェック\nmypy scripts/ --ignore-missing-imports\n```\n\n### EPUB ビルド\n\n```bash\n# 電子書籍を生成（Mermaid 図は Pele でレンダリング／Node.js >= 20 が必要。固定バンドルは初回のみダウンロード）\nuv run scripts/build_epub.py\n\n# オプション付き\nuv run scripts/build_epub.py --verbose --output custom-name.epub --lang ja\n```\n\n## ディレクトリ構造\n\n```\n├── 01-slash-commands/      # ユーザーが起動するショートカット\n├── 02-memory/              # 永続コンテキストの例\n├── 03-skills/              # 再利用可能な能力\n├── 04-subagents/           # 専門 AI アシスタント\n├── 05-mcp/                 # Model Context Protocol の例\n├── 06-hooks/               # イベント駆動の自動化\n├── 07-plugins/             # バンドル機能\n├── 08-checkpoints/         # セッションのスナップショット\n├── 09-advanced-features/   # プランニング、シンキング、バックグラウンド\n├── 10-cli/                 # CLI リファレンス\n├── scripts/\n│   ├── build_epub.py           # EPUB ジェネレータ（Mermaid を Pele でレンダリング）\n│   ├── check_cross_references.py   # 内部リンクを検証\n│   ├── check_links.py          # 外部 URL を検証\n│   ├── check_mermaid.py        # Mermaid 構文を検証\n│   └── tests/                  # スクリプトのユニットテスト\n├── .pre-commit-config.yaml    # 品質チェック定義\n└── README.md               # メインガイド（モジュール索引も兼ねる）\n```\n\n## コンテンツ作成ガイド\n\n### モジュール構造\n番号付きフォルダはいずれも以下のパターンに従う：\n- **README.md** — 機能の概要と例\n- **サンプルファイル** — コピー＆ペースト可能なテンプレート（コマンドは `.md`、設定は `.json`、フックは `.sh`）\n- ファイルは機能の複雑さと依存関係に従って整理されている\n\n### Mermaid 図\n- すべての図は正常にパースできること（pre-commit フックで検査）\n- EPUB ビルドは Pele で図をレンダリングする（Node.js >= 20 が必要。固定バンドルは初回のみダウンロードされ、以降はオフラインで動作する）\n- フローチャート、シーケンス図、アーキテクチャ可視化に Mermaid を使用する\n\n### 相互参照\n- 内部リンクは相対パスを使う（例：`(01-slash-commands/README.md)`）\n- コードフェンスは言語指定が必須（例：` ```bash `、` ```python `）\n- アンカーリンクは `#heading-name` 形式\n\n### リンク検証\n- 外部 URL は到達可能であること（pre-commit フックで検査）\n- 一時的なコンテンツへのリンクは避ける\n- 可能な限りパーマリンクを使用する\n\n## 主要なアーキテクチャ上のポイント\n\n1. **番号付きフォルダは学習順序を示す** — 01〜10 のプレフィックスは Claude Code 機能の推奨学習順序を表す。この番号付けは意図的なものなので、アルファベット順に並べ替えてはならない。\n\n2. **スクリプトはユーティリティであり製品ではない** — `scripts/` の Python スクリプトはドキュメント品質と EPUB 生成を支援するものである。実際のコンテンツは番号付きモジュールフォルダにある。\n\n3. **pre-commit がゲートキーパー** — PR が承認される前に 5 つの品質チェックがすべて通過しなければならない。CI パイプラインは同じチェックを 2 回目のパスとして実行する。\n\n4. **Mermaid のレンダリングには Node.js >= 20 が必要** — EPUB ビルドは固定バージョンの Pele バンドルを Node.js で実行して図をレンダリングする（バンドルは初回のみダウンロードされ、sha256 で検証してキャッシュされる）。ここでビルドが失敗する場合は、Node.js >= 20 が未インストールか、バンドルのダウンロード失敗か、Mermaid 構文エラーが典型的な原因である。pre-commit の mermaid フックは pre-commit が用意する Node.js 22 で厳格モードで実行され、スキップせずに失敗する。EPUB ビルド自体は pre-commit では実行されず、CI のみで実行される。\n\n5. **これはチュートリアルでありライブラリではない** — コンテンツを追加する際は、明快な解説、コピー＆ペースト可能な例、視覚的な図を重視する。価値は概念を教えることにあり、再利用可能なコードを提供することではない。\n\n## コミット規約\n\nConventional Commits 形式に従う：\n- `feat(slash-commands): Add API documentation generator`\n- `docs(memory): Improve personal preferences example`\n- `fix(README): Correct table of contents link`\n- `refactor(hooks): Simplify hook configuration examples`\n\nスコープは該当するフォルダ名に合わせる。\n","uk/03-skills/blog-draft/SKILL.md":"---\nname: blog-draft\ndescription: Створення чернетки блог-посту з ідей та ресурсів. Використовуйте, коли користувачі хочуть написати блог-пост, створити контент з дослідження або підготувати статтю. Проводить через дослідження, мозковий штурм, складання плану та ітеративне написання з контролем версій.\n---\n\n## Введення користувача\n\n```text\n$ARGUMENTS\n```\n\nВи **ПОВИННІ** врахувати введення користувача перед продовженням. Користувач має надати:\n- **Ідея/Тема**: Основна концепція або тематика блог-посту\n- **Ресурси**: URL, файли або посилання на дослідження (необовʼязково, але рекомендовано)\n- **Цільова аудиторія**: Для кого блог-пост (необовʼязково)\n- **Тон/Стиль**: Формальний, невимушений, технічний тощо (необовʼязково)\n\n**ВАЖЛИВО**: Якщо користувач запитує оновлення **існуючого блог-посту**, пропустіть кроки 0-8 і починайте безпосередньо з **Кроку 9**. Спочатку прочитайте існуючий файл(и) чернетки, потім продовжуйте з процесом ітерації.\n\n## Потік виконання\n\nВиконуйте ці кроки послідовно. **Не пропускайте кроки та не продовжуйте без затвердження користувача, де це зазначено.**\n\n### Крок 0: Створення папки проєкту\n\n1. Згенерувати назву папки у форматі: `YYYY-MM-DD-short-topic-name`\n   - Використати сьогоднішню дату\n   - Створити короткий, URL-дружній slug з теми (малі літери, дефіси, макс. 5 слів)\n\n2. Створити структуру папок:\n   ```\n   blog-posts/\n   └── YYYY-MM-DD-short-topic-name/\n       └── resources/\n   ```\n\n3. Підтвердити створення папки з користувачем перед продовженням.\n\n### Крок 1: Дослідження та збір ресурсів\n\n1. Створити підпапку `resources/` у каталозі блог-посту\n\n2. Для кожного наданого ресурсу:\n   - **URL-адреси**: Отримати та зберегти ключову інформацію до `resources/` як markdown-файли\n   - **Файли**: Прочитати та підсумувати в `resources/`\n   - **Теми**: Використати веб-пошук для збору актуальної інформації\n\n3. Для кожного ресурсу створити файл резюме в `resources/`:\n   - `resources/source-1-[short-name].md`\n   - `resources/source-2-[short-name].md`\n   - тощо\n\n4. Кожне резюме має включати:\n   ```markdown\n   # Джерело: [Назва/URL]\n\n   ## Ключові тези\n   - Теза 1\n   - Теза 2\n\n   ## Релевантні цитати/дані\n   - Цитата або статистика 1\n   - Цитата або статистика 2\n\n   ## Як це стосується теми\n   Короткий опис релевантності\n   ```\n\n5. Представити резюме дослідження користувачу.\n\n### Крок 2: Мозковий штурм та уточнення\n\n1. На основі ідеї та досліджених ресурсів представити:\n   - **Основні теми**, виявлені з дослідження\n   - **Потенційні ракурси** для блог-посту\n   - **Ключові тези**, які слід розкрити\n   - **Прогалини** в інформації, що потребують уточнення\n\n2. Поставити уточнюючі запитання:\n   - Який головний висновок ви хочете донести до читачів?\n   - Чи є конкретні тези з дослідження, які хочете виділити?\n   - Яка цільова довжина? (коротка: 500-800 слів, середня: 1000-1500, довга: 2000+)\n   - Щось хочете виключити?\n\n3. **Чекати відповідей користувача перед продовженням.**\n\n### Крок 3: Запропонувати план\n\n1. Створити структурований план, що включає:\n\n   ```markdown\n   # План блог-посту: [Назва]\n\n   ## Метаінформація\n   - **Цільова аудиторія**: [хто]\n   - **Тон**: [стиль]\n   - **Цільова довжина**: [кількість слів]\n   - **Головний висновок**: [ключове повідомлення]\n\n   ## Запропонована структура\n\n   ### Зачіпка/Вступ\n   - Ідея вступної зачіпки\n   - Встановлення контексту\n   - Теза\n\n   ### Розділ 1: [Назва]\n   - Ключова теза A\n   - Ключова теза B\n   - Підтверджуючі докази з [джерела]\n\n   ### Розділ 2: [Назва]\n   - Ключова теза A\n   - Ключова теза B\n\n   [Продовжити для всіх розділів...]\n\n   ### Висновок\n   - Резюме ключових тез\n   - Заклик до дії або завершальна думка\n\n   ## Джерела для цитування\n   - Джерело 1\n   - Джерело 2\n   ```\n\n2. Представити план користувачу та **запитати затвердження або модифікації**.\n\n### Крок 4: Зберегти затверджений план\n\n1. Після затвердження плану користувачем зберегти його як `OUTLINE.md` у папці блог-посту.\n\n2. Підтвердити збереження плану.\n\n### Крок 5: Закомітити план (якщо в git-репо)\n\n1. Перевірити, чи поточний каталог є git-репозиторієм.\n\n2. Якщо так:\n   - Додати нові файли до індексу: папку блог-посту, ресурси та OUTLINE.md\n   - Створити коміт з повідомленням: `docs: Add outline for blog post - [topic-name]`\n   - Відправити на віддалений сервер\n\n3. Якщо не git-репо, пропустити цей крок та повідомити користувача.\n\n### Крок 6: Написати чернетку\n\n1. На основі затвердженого плану написати повну чернетку блог-посту.\n\n2. Точно дотримуватися структури з OUTLINE.md.\n\n3. Включити:\n   - Захопливий вступ із зачіпкою\n   - Чіткі заголовки розділів\n   - Підтверджуючі докази та приклади з дослідження\n   - Плавні переходи між розділами\n   - Сильний висновок з головною тезою\n   - **Цитування**: Усі порівняння, статистика, дані та фактичні твердження ПОВИННІ цитувати оригінальне джерело\n\n4. Зберегти чернетку як `draft-v0.1.md` у папці блог-посту.\n\n5. Формат:\n   ```markdown\n   # [Назва блог-посту]\n\n   *[Необовʼязково: підзаголовок або слоган]*\n\n   [Повний вміст з інлайн-цитатами...]\n\n   ---\n\n   ## Список джерел\n   - [1] Назва джерела 1 - URL або цитата\n   - [2] Назва джерела 2 - URL або цитата\n   - [3] Назва джерела 3 - URL або цитата\n   ```\n\n6. **Вимоги до цитування**:\n   - Кожна точка даних, статистика або порівняння ПОВИННІ мати інлайн-цитату\n   - Використовуйте нумеровані посилання [1], [2] тощо, або іменовані цитати [Назва джерела]\n   - Звʼязуйте цитати з розділом Список джерел наприкінці\n   - Приклад: «Дослідження показують, що 65% розробників віддають перевагу TypeScript [1]»\n   - Приклад: «React перевершує Vue за швидкістю рендерингу на 20% [React Benchmarks 2024]»\n\n### Крок 7: Закомітити чернетку (якщо в git-репо)\n\n1. Перевірити, чи в git-репозиторії.\n\n2. Якщо так:\n   - Додати файл чернетки до індексу\n   - Створити коміт з повідомленням: `docs: Add draft v0.1 for blog post - [topic-name]`\n   - Відправити на віддалений сервер\n\n3. Якщо не git-репо, пропустити та повідомити користувача.\n\n### Крок 8: Представити чернетку для перегляду\n\n1. Представити вміст чернетки користувачу.\n\n2. Запитати зворотний звʼязок:\n   - Загальне враження?\n   - Розділи, що потребують розширення або скорочення?\n   - Потрібні корекції тону?\n   - Відсутня інформація?\n   - Конкретні правки або переписування?\n\n3. **Чекати відповіді користувача.**\n\n### Крок 9: Ітерація або фіналізація\n\n**Якщо користувач запитує зміни:**\n1. Зафіксувати всі запитані модифікації\n2. Повернутися до Кроку 6 з такими змінами:\n   - Збільшити номер версії (v0.2, v0.3 тощо)\n   - Врахувати всі зауваження\n   - Зберегти як `draft-v[X.Y].md`\n   - Повторити Кроки 7-8\n\n**Якщо користувач затверджує:**\n1. Підтвердити фінальну версію чернетки\n2. За бажанням перейменувати на `final.md`\n3. Підсумувати процес створення блог-посту:\n   - Загальна кількість створених версій\n   - Ключові зміни між версіями\n   - Фінальна кількість слів\n   - Створені файли\n\n## Відстеження версій\n\nУсі чернетки зберігаються з інкрементальним версіонуванням:\n- `draft-v0.1.md` — початкова чернетка\n- `draft-v0.2.md` — після першого раунду зауважень\n- `draft-v0.3.md` — після другого раунду зауважень\n- тощо\n\nЦе дозволяє відстежувати еволюцію блог-посту та повертатися до попередніх версій за потреби.\n\n## Структура вихідних файлів\n\n```\nblog-posts/\n└── YYYY-MM-DD-topic-name/\n    ├── resources/\n    │   ├── source-1-name.md\n    │   ├── source-2-name.md\n    │   └── ...\n    ├── OUTLINE.md\n    ├── draft-v0.1.md\n    ├── draft-v0.2.md (якщо ітерації)\n    └── draft-v0.3.md (якщо більше ітерацій)\n```\n\n## Поради щодо якості\n\n- **Зачіпка**: Починайте з питання, дивовижного факту або знайомого сценарію\n- **Потік**: Кожен абзац має зʼєднуватися з наступним\n- **Докази**: Підтверджуйте твердження даними з дослідження\n- **Цитування**: ЗАВЖДИ цитуйте джерела для:\n  - Усіх статистик та даних (напр., «За даними [Джерело], 75%...»)\n  - Порівнянь між продуктами, сервісами або підходами (напр., «X працює у 2 рази швидше за Y [Джерело]»)\n  - Фактичних тверджень про ринкові тенденції, результати досліджень або бенчмарки\n  - Використовуйте інлайн-цитати у форматі: [Назва джерела] або [Автор, Рік]\n- **Голос**: Підтримуйте послідовний тон протягом усього тексту\n- **Довжина**: Дотримуйтесь цільової кількості слів\n- **Читабельність**: Використовуйте короткі абзаци, маркери де доречно\n- **CTA**: Завершуйте чітким закликом до дії або питанням, що провокує думки\n\n## Примітки\n\n- Завжди чекайте затвердження користувача у зазначених контрольних точках\n- Зберігайте всі версії чернеток для історії\n- Використовуйте веб-пошук для актуальної інформації, коли надані URL\n- Якщо ресурсів недостатньо, попросіть користувача надати більше або запропонуйте додаткове дослідження\n- Адаптуйте тон відповідно до цільової аудиторії (технічна, загальна, бізнес тощо)\n","uk/03-skills/brand-voice/SKILL.md":"---\nname: brand-voice\ndescription: Забезпечення відповідності всіх комунікацій голосу та тону бренду. Використовуйте при створенні маркетингових текстів, клієнтських комунікацій, публічного контенту, або коли користувачі згадують голос бренду, тон чи стиль написання.\nuser-invocable: false\n---\n\n# Навичка голосу бренду\n\n## Огляд\nЦя навичка забезпечує послідовність голосу бренду, тону та повідомлень у всіх комунікаціях.\n\n## Ідентичність бренду\n\n### Місія\nДопомогти командам автоматизувати робочі процеси розробки за допомогою AI\n\n### Цінності\n- **Простота**: Робити складне простим\n- **Надійність**: Непохитне виконання\n- **Розширення можливостей**: Дати простір людській креативності\n\n### Тон голосу\n- **Дружній, але професійний** — доступний, але не панібратський\n- **Зрозумілий і лаконічний** — уникати жаргону, пояснювати технічні концепції просто\n- **Впевнений** — ми знаємо, що робимо\n- **Емпатичний** — розуміємо потреби та болі користувачів\n\n## Рекомендації щодо написання\n\n### Рекомендовано ✅\n- Використовуйте «ви» при зверненні до читачів\n- Використовуйте активний стан: «Claude генерує звіти», а не «Звіти генеруються Claude»\n- Починайте з ціннісної пропозиції\n- Використовуйте конкретні приклади\n- Тримайте речення до 20 слів\n- Використовуйте списки для ясності\n- Включайте заклики до дії\n\n### Не рекомендовано ❌\n- Не використовуйте корпоративний жаргон\n- Не будьте поблажливими та не надмірно спрощуйте\n- Не використовуйте «ми вважаємо» або «ми думаємо»\n- Не використовуйте ВСІ ВЕЛИКІ ЛІТЕРИ, крім виділення\n- Не створюйте стіни тексту\n- Не припускайте наявність технічних знань\n\n## Словник\n\n### ✅ Бажані терміни\n- Claude (не «AI Claude»)\n- Генерація коду (не «автокодування»)\n- Агент (не «бот»)\n- Оптимізувати (не «революціонізувати»)\n- Інтегрувати (не «синергізувати»)\n\n### ❌ Уникати\n- «Передовий» (заїжджено)\n- «Проривний» (розмито)\n- «Левериджити» (корпоративний жаргон)\n- «Утилізувати» (використовуйте «використовувати»)\n- «Зміна парадигми» (незрозуміло)\n\n## Приклади\n\n### ✅ Вдалий приклад\n«Claude автоматизує ваш процес код-рев'ю. Замість ручної перевірки кожного PR, Claude перевіряє безпеку, продуктивність та якість — заощаджуючи вашій команді години щотижня.»\n\nЧому працює: Зрозуміла цінність, конкретні переваги, орієнтація на дію\n\n### ❌ Невдалий приклад\n«Claude левериджить передовий AI для надання комплексних рішень розробки програмного забезпечення.»\n\nЧому не працює: Розмито, корпоративний жаргон, немає конкретної цінності\n","uk/03-skills/claude-md/SKILL.md":"---\nname: claude-md\ndescription: Створення або оновлення файлів CLAUDE.md відповідно до найкращих практик для оптимального онбордингу AI-агента\n---\n\n## Введення користувача\n\n```text\n$ARGUMENTS\n```\n\nВи **ПОВИННІ** врахувати введення користувача перед продовженням (якщо не порожнє). Користувач може вказати:\n- `create` — створити новий CLAUDE.md з нуля\n- `update` — покращити існуючий CLAUDE.md\n- `audit` — проаналізувати та звітувати про якість поточного CLAUDE.md\n- Конкретний шлях для створення/оновлення (напр., `src/api/CLAUDE.md` для інструкцій, специфічних для каталогу)\n\n## Основні принципи\n\n**LLM не мають стану**: CLAUDE.md — головний файл проєкту, що завантажується в кожну розмову (разом з автоматичною пам'яттю та правилами без обмеження області). Він слугує головним документом онбордингу AI-агентів у вашу кодову базу.\n\n### Золоті правила\n\n1. **Менше — краще**: Найсучасніші LLM можуть дотримуватись ~150-200 інструкцій. Системний промпт Claude Code вже використовує ~50. Тримайте CLAUDE.md зосередженим та лаконічним.\n\n2. **Універсальна застосовність**: Включайте лише інформацію, релевантну для КОЖНОЇ сесії. Інструкції для конкретних завдань належать до окремих файлів.\n\n3. **Не використовуйте Claude як лінтер**: Рекомендації зі стилю роздувають контекст та погіршують дотримання інструкцій. Використовуйте натомість детерміністичні інструменти (prettier, eslint тощо).\n\n4. **Ніколи не генеруйте автоматично**: CLAUDE.md — найвпливовіша точка AI-системи. Створюйте його вручну з ретельним обмірковуванням.\n\n## Потік виконання\n\n### 1. Аналіз проєкту\n\nСпочатку проаналізуйте поточний стан проєкту:\n\n1. Перевірити наявні файли CLAUDE.md:\n   - Кореневий рівень: `./CLAUDE.md` або `.claude/CLAUDE.md`\n   - Специфічні для каталогу: `**/CLAUDE.md`\n   - Глобальний конфіг користувача: `~/.claude/CLAUDE.md`\n\n2. Визначити структуру проєкту:\n   - Технологічний стек (мови, фреймворки)\n   - Тип проєкту (монорепо, окремий додаток, бібліотека)\n   - Інструменти розробки (пакетний менеджер, система збірки, тест-раннер)\n\n3. Переглянути існуючу документацію:\n   - README.md\n   - CONTRIBUTING.md\n   - package.json, pyproject.toml, Cargo.toml тощо\n\n### 2. Стратегія контенту (ЩО, ЧОМУ, ЯК)\n\nСтруктуруйте CLAUDE.md навколо трьох вимірів:\n\n#### ЩО — Технологія та структура\n- Огляд технологічного стеку\n- Організація проєкту (особливо важливо для монорепо)\n- Ключові каталоги та їхнє призначення\n\n#### ЧОМУ — Призначення та контекст\n- Що робить проєкт\n- Чому були прийняті певні архітектурні рішення\n- За що відповідає кожен основний компонент\n\n#### ЯК — Робочий процес та конвенції\n- Робочий процес розробки (bun vs node, pip vs uv тощо)\n- Процедури та команди тестування\n- Методи верифікації та збірки\n- Критичні «підводні камені» або неочевидні вимоги\n\n### 3. Стратегія поступового розкриття\n\nДля великих проєктів рекомендуйте створити папку `agent_docs/`:\n\n```\nagent_docs/\n  |- building_the_project.md\n  |- running_tests.md\n  |- code_conventions.md\n  |- architecture_decisions.md\n```\n\nУ CLAUDE.md посилайтесь на ці файли інструкціями:\n```markdown\nFor detailed build instructions, refer to `agent_docs/building_the_project.md`\n```\n\n**Важливо**: Використовуйте посилання `файл:рядок` замість фрагментів коду, щоб уникнути застарілого контексту.\n\n### 4. Обмеження якості\n\nПри створенні або оновленні CLAUDE.md:\n\n1. **Цільова довжина**: Менше 200 рядків\n2. **Без правил стилю**: Видалити будь-які інструкції лінтингу/форматування\n3. **Без інструкцій для конкретних завдань**: Перемістити до окремих файлів\n4. **Без фрагментів коду**: Використовувати посилання на файли замість цього\n5. **Без надлишкової інформації**: Не повторювати те, що є в package.json або README\n\n### 5. Обовʼязкові секції\n\nДобре структурований CLAUDE.md має включати:\n\n```markdown\n# Назва проєкту\n\nКороткий однорядковий опис.\n\n## Технологічний стек\n- Основна мова та версія\n- Ключові фреймворки/бібліотеки\n- База даних/сховище (якщо є)\n\n## Структура проєкту\n[Лише для монорепо або складних структур]\n- `apps/` - Точки входу додатків\n- `packages/` - Спільні бібліотеки\n\n## Команди розробки\n- Встановлення: `команда`\n- Тестування: `команда`\n- Збірка: `команда`\n\n## Критичні конвенції\n[Лише неочевидні, високовпливові конвенції]\n- Конвенція 1 з коротким поясненням\n- Конвенція 2 з коротким поясненням\n\n## Відомі проблеми / Підводні камені\n[Речі, що постійно створюють труднощі розробникам]\n- Проблема 1\n- Проблема 2\n```\n\n### 6. Антипатерни, яких слід уникати\n\n**НЕ включайте:**\n- Рекомендації зі стилю коду (використовуйте лінтери)\n- Документацію щодо використання Claude\n- Довгі пояснення очевидних патернів\n- Скопійовані приклади коду\n- Загальні найкращі практики («пишіть чистий код»)\n- Інструкції для конкретних завдань\n- Автозгенерований контент\n- Розлогі списки TODO\n\n### 7. Контрольний список валідації\n\nПеред фіналізацією перевірте:\n\n- [ ] Менше 200 рядків\n- [ ] Кожен рядок застосовний до ВСІХ сесій\n- [ ] Без правил стилю/форматування\n- [ ] Без фрагментів коду (використані посилання на файли)\n- [ ] Команди перевірені на працездатність\n- [ ] Поступове розкриття використано для складних проєктів\n- [ ] Критичні підводні камені задокументовані\n- [ ] Немає надлишковості з README.md\n\n## Формат виводу\n\n### Для `create` або за замовчуванням:\n\n1. Проаналізувати проєкт\n2. Створити чернетку CLAUDE.md за структурою вище\n3. Представити чернетку для перегляду\n4. Записати у відповідне місце після затвердження\n\n### Для `update`:\n\n1. Прочитати існуючий CLAUDE.md\n2. Аудит за найкращими практиками\n3. Визначити:\n   - Контент для видалення (правила стилю, фрагменти коду, специфічне для завдань)\n   - Контент для скорочення\n   - Відсутню важливу інформацію\n4. Представити зміни для перегляду\n5. Застосувати зміни після затвердження\n\n### Для `audit`:\n\n1. Прочитати існуючий CLAUDE.md\n2. Згенерувати звіт з:\n   - Поточна кількість рядків vs ціль\n   - Відсоток універсально застосовного контенту\n   - Список знайдених антипатернів\n   - Рекомендації для покращення\n3. НЕ модифікувати файл, лише звітувати\n\n## Обробка AGENTS.md\n\nЯкщо користувач запитує створення/оновлення AGENTS.md:\n\n**Починаючи з v2.1.277, Claude Code читає `AGENTS.md` напряму як інструкції проєкту** — але лише тоді, коли ні в робочому каталозі, ні в жодному каталозі вище немає `CLAUDE.md`, `.claude/CLAUDE.md` чи `CLAUDE.local.md`. `~/.claude/CLAUDE.md`, керований CLAUDE.md і `.claude/rules/` не враховуються в цій перевірці та завантажуються паралельно. Поведінку визначає **Project instructions** у `/config`: `claude-md-or-agents-md` (за замовчуванням), `claude-md-and-agents-md`, `claude-md` або `managed-only`. Там, де пряме читання недоступне — версії до v2.1.277 (до v2.1.281 на Bedrock/Vertex/Foundry, за LLM-шлюзами або з вимкненою телеметрією) або перша сесія після оновлення — використовуйте запасний варіант: імпортуйте файл з CLAUDE.md через `@AGENTS.md` або зробіть `CLAUDE.md` символічним посиланням на нього.\n\nAGENTS.md — це міжінструментальний файл контексту проєкту, тобто документ тієї ж *категорії*, що й CLAUDE.md, а не формат визначення агентів. Він існує для того, щоб кілька кодових агентів могли користуватися спільним набором конвенцій проєкту:\n- Команди збірки, тестування та лінтингу\n- Стиль коду та архітектурні конвенції\n- Структура репозиторію та розташування компонентів\n\nСубагенти визначаються окремо — у `.claude/agents/*.md`, а не в AGENTS.md.\n\nЗастосовуйте аналогічні принципи:\n- Тримайте зосередженим та лаконічним\n- Використовуйте поступове розкриття\n- Посилайтесь на зовнішні документи замість вбудовування контенту\n\n## Примітки\n\n- Завжди перевіряйте працездатність команд перед їх включенням\n- Якщо сумніваєтесь — не включайте; менше — краще\n- Системне нагадування повідомляє Claude, що CLAUDE.md «може бути або не бути релевантним» — чим більше шуму, тим більше він ігнорується\n- Монорепо найбільше виграють від чіткої структури ЩО/ЧОМУ/ЯК\n- Файли CLAUDE.md для конкретних каталогів мають бути ще більш зосередженими\n\n---\n\n**Останнє оновлення**: 18 жовтня 2026\n**Версія Claude Code**: 2.1.302\n**Джерела**:\n- https://code.claude.com/docs/en/memory\n","uk/03-skills/code-review-specialist/SKILL.md":"---\nname: code-review-specialist\ndescription: Комплексне код-рев'ю з аналізом безпеки, продуктивності та якості. Використовуйте, коли користувачі просять переглянути код, проаналізувати якість коду, оцінити pull request, або згадують код-рев'ю, аналіз безпеки чи оптимізацію продуктивності.\n---\n\n# Навичка код-рев'ю\n\nЦя навичка забезпечує комплексні можливості код-рев'ю з фокусом на:\n\n1. **Аналіз безпеки**\n   - Проблеми автентифікації/авторизації\n   - Ризики розкриття даних\n   - Вразливості інʼєкцій\n   - Криптографічні слабкості\n   - Логування чутливих даних\n\n2. **Аналіз продуктивності**\n   - Ефективність алгоритмів (аналіз Big O)\n   - Оптимізація памʼяті\n   - Оптимізація запитів до БД\n   - Можливості кешування\n   - Проблеми конкурентності\n\n3. **Якість коду**\n   - Принципи SOLID\n   - Патерни проєктування\n   - Конвенції іменування\n   - Документація\n   - Покриття тестами\n\n4. **Супровідність**\n   - Читабельність коду\n   - Розмір функцій (має бути < 50 рядків)\n   - Цикломатична складність\n   - Управління залежностями\n   - Безпека типів\n\n## Шаблон рев'ю\n\nДля кожного фрагмента перевіреного коду надати:\n\n### Резюме\n- Загальна оцінка якості (1-5)\n- Кількість виявлених проблем\n- Рекомендовані пріоритетні зони\n\n### Критичні проблеми (якщо є)\n- **Проблема**: Чіткий опис\n- **Розташування**: Файл і номер рядка\n- **Вплив**: Чому це важливо\n- **Серйозність**: Критична/Висока/Середня\n- **Виправлення**: Приклад коду\n\n### Знахідки за категоріями\n\n#### Безпека (якщо знайдено проблеми)\nПерелік вразливостей безпеки з прикладами\n\n#### Продуктивність (якщо знайдено проблеми)\nПерелік проблем продуктивності з аналізом складності\n\n#### Якість (якщо знайдено проблеми)\nПерелік проблем якості коду з пропозиціями рефакторингу\n\n#### Супровідність (якщо знайдено проблеми)\nПерелік проблем супровідності з покращеннями\n\n## Історія версій\n\n- v1.0.0 (2024-12-10): Початковий випуск з аналізом безпеки, продуктивності, якості та супровідності\n","uk/03-skills/doc-generator/SKILL.md":"---\nname: doc-generator\ndescription: Генерація вичерпної, точної документації API з вихідного коду. Використовуйте при створенні або оновленні документації API, генерації специфікацій OpenAPI, або коли користувачі згадують документацію API, ендпоінти чи документацію.\n---\n\n# Навичка генерації документації API\n\n## Генерує\n\n- Специфікації OpenAPI/Swagger\n- Документацію ендпоінтів API\n- Приклади використання SDK\n- Посібники з інтеграції\n- Довідники кодів помилок\n- Посібники з автентифікації\n\n## Структура документації\n\n### Для кожного ендпоінту\n\n````markdown\n## GET /api/v1/users/:id\n\n### Опис\nКороткий опис призначення цього ендпоінту\n\n### Параметри\n\n| Назва | Тип | Обовʼязковий | Опис |\n|-------|-----|-------------|------|\n| id | string | Так | ID користувача |\n\n### Відповідь\n\n**200 Успіх**\n```json\n{\n  \"id\": \"usr_123\",\n  \"name\": \"John Doe\",\n  \"email\": \"john@example.com\",\n  \"created_at\": \"2025-01-15T10:30:00Z\"\n}\n```\n\n**404 Не знайдено**\n```json\n{\n  \"error\": \"USER_NOT_FOUND\",\n  \"message\": \"Користувач не існує\"\n}\n```\n\n### Приклади\n\n**cURL**\n```bash\ncurl -X GET \"https://api.example.com/api/v1/users/usr_123\" \\\n  -H \"Authorization: Bearer YOUR_TOKEN\"\n```\n\n**JavaScript**\n```javascript\nconst user = await fetch('/api/v1/users/usr_123', {\n  headers: { 'Authorization': 'Bearer token' }\n}).then(r => r.json());\n```\n\n**Python**\n```python\nresponse = requests.get(\n    'https://api.example.com/api/v1/users/usr_123',\n    headers={'Authorization': 'Bearer token'}\n)\nuser = response.json()\n```\n````\n","uk/03-skills/refactor/SKILL.md":"---\nname: refactor\ndescription: Систематичний рефакторинг коду на основі методології Мартіна Фаулера. Використовуйте, коли користувачі просять рефакторити код, покращити структуру коду, зменшити технічний борг, очистити застарілий код, усунути запахи коду (code smells) або покращити супровідність коду. Ця навичка проводить через поетапний підхід з дослідженням, плануванням та безпечною інкрементальною реалізацією.\n---\n\n# Навичка рефакторингу коду\n\nСистематичний підхід до рефакторингу коду на основі книги Мартіна Фаулера *Refactoring: Improving the Design of Existing Code* (2-ге видання). Ця навичка наголошує на безпечних, інкрементальних змінах, підкріплених тестами.\n\n> «Рефакторинг — це процес зміни програмної системи таким чином, що не змінює зовнішню поведінку коду, але покращує його внутрішню структуру.» — Мартін Фаулер\n\n## Основні принципи\n\n1. **Збереження поведінки**: Зовнішня поведінка повинна залишатися незмінною\n2. **Малі кроки**: Робити крихітні, тестовані зміни\n3. **Тест-орієнтованість**: Тести — це страхувальна сітка\n4. **Безперервність**: Рефакторинг — постійний процес, а не одноразова подія\n5. **Співпраця**: Затвердження користувача потрібне на кожній фазі\n\n## Огляд робочого процесу\n\n```\nФаза 1: Дослідження та аналіз\n    ↓\nФаза 2: Оцінка покриття тестами\n    ↓\nФаза 3: Виявлення запахів коду\n    ↓\nФаза 4: Створення плану рефакторингу\n    ↓\nФаза 5: Інкрементальна реалізація\n    ↓\nФаза 6: Перегляд та ітерація\n```\n\n---\n\n## Фаза 1: Дослідження та аналіз\n\n### Цілі\n- Зрозуміти структуру та призначення кодової бази\n- Визначити обсяг рефакторингу\n- Зібрати контекст про бізнес-вимоги\n\n### Запитання до користувача\nПеред початком уточніть:\n\n1. **Обсяг**: Які файли/модулі/функції потребують рефакторингу?\n2. **Цілі**: Які проблеми ви намагаєтесь вирішити? (читабельність, продуктивність, супровідність)\n3. **Обмеження**: Чи є зони, які НЕ слід змінювати?\n4. **Тиск термінів**: Чи блокує це іншу роботу?\n5. **Стан тестів**: Чи існують тести? Чи проходять вони?\n\n### Дії\n- [ ] Прочитати та зрозуміти цільовий код\n- [ ] Виявити залежності та інтеграції\n- [ ] Задокументувати поточну архітектуру\n- [ ] Зафіксувати існуючі маркери технічного боргу (TODOs, FIXMEs)\n\n### Вивід\nПредставити знахідки користувачу:\n- Резюме структури коду\n- Виявлені проблемні зони\n- Початкові рекомендації\n- **Запросити затвердження для продовження**\n\n---\n\n## Фаза 2: Оцінка покриття тестами\n\n### Чому тести важливі\n> «Рефакторинг без тестів — як їзда без пасків безпеки.» — Мартін Фаулер\n\nТести — **ключовий засіб** безпечного рефакторингу. Без них ви ризикуєте внести помилки.\n\n### Кроки оцінки\n\n1. **Перевірити наявні тести**\n   ```bash\n   # Пошук файлів тестів\n   find . -name \"*test*\" -o -name \"*spec*\" | head -20\n   ```\n\n2. **Запустити існуючі тести**\n   ```bash\n   # JavaScript/TypeScript\n   npm test\n\n   # Python\n   pytest -v\n\n   # Java\n   mvn test\n   ```\n\n3. **Перевірити покриття (якщо доступно)**\n   ```bash\n   # JavaScript\n   npm run test:coverage\n\n   # Python\n   pytest --cov=.\n   ```\n\n### Точка рішення: Запитати користувача\n\n**Якщо тести існують та проходять:**\n- Перейти до Фази 3\n\n**Якщо тести відсутні або неповні:**\nПредставити варіанти:\n1. Спочатку написати тести (рекомендовано)\n2. Додавати тести інкрементально під час рефакторингу\n3. Продовжити без тестів (ризиковано — потребує підтвердження користувача)\n\n**Якщо тести не проходять:**\n- ЗУПИНИТИСЯ. Виправити тести перед рефакторингом\n- Запитати користувача: Чи слід спочатку виправити тести?\n\n### Рекомендації щодо написання тестів (якщо потрібно)\n\nДля кожної функції, що рефакториться, забезпечити тести для:\n- Успішний шлях (нормальна робота)\n- Граничні випадки (порожні введення, null, межі)\n- Сценарії помилок (невалідні введення, виключення)\n\nВикористовуйте цикл «red-green-refactor»:\n1. Написати тест, що не проходить (red)\n2. Зробити так, щоб пройшов (green)\n3. Рефакторити\n\n---\n\n## Фаза 3: Виявлення запахів коду\n\n### Що таке запахи коду?\nСимптоми глибших проблем у коді. Це не помилки, а індикатори того, що код можна покращити.\n\n### Типові запахи коду для перевірки\n\nДив. [references/code-smells.md](references/code-smells.md) для повного каталогу.\n\n#### Короткий довідник\n\n| Запах | Ознаки | Вплив |\n|-------|--------|-------|\n| **Довгий метод** | Методи > 30-50 рядків | Важко зрозуміти, тестувати, супроводжувати |\n| **Дубльований код** | Та сама логіка в кількох місцях | Виправлення помилок потрібне в кількох місцях |\n| **Великий клас** | Клас з занадто багатьма відповідальностями | Порушує принцип єдиної відповідальності |\n| **Заздрість до функцій** | Метод використовує дані іншого класу більше | Погана інкапсуляція |\n| **Одержимість примітивами** | Надмірне використання примітивів замість обʼєктів | Відсутні доменні концепції |\n| **Довгий список параметрів** | Методи з 4+ параметрами | Складно викликати правильно |\n| **Групи даних** | Ті самі елементи даних зʼявляються разом | Відсутня абстракція |\n| **Оператори Switch** | Складні ланцюжки switch/if-else | Важко розширювати |\n| **Спекулятивна загальність** | Код «на всякий випадок» | Зайва складність |\n| **Мертвий код** | Невикористаний код | Плутанина, тягар супровідності |\n\n### Кроки аналізу\n\n1. **Автоматичний аналіз** (якщо скрипти доступні)\n   ```bash\n   python scripts/detect-smells.py <file>\n   ```\n\n2. **Ручний перегляд**\n   - Систематично пройти код\n   - Зафіксувати кожен запах з розташуванням та серйозністю\n   - Категоризувати за впливом (Критичний/Високий/Середній/Низький)\n\n3. **Пріоритезація**\n   Зосередитися на запахах, які:\n   - Блокують поточну розробку\n   - Спричиняють помилки або плутанину\n   - Впливають на найчастіше змінювані шляхи коду\n\n### Вивід: Звіт про запахи\n\nПредставити користувачу:\n- Список виявлених запахів з розташуванням\n- Оцінку серйозності для кожного\n- Рекомендований порядок пріоритету\n- **Запросити затвердження пріоритетів**\n\n---\n\n## Фаза 4: Створення плану рефакторингу\n\n### Вибір рефакторингів\n\nДля кожного запаху обрати відповідний рефакторинг з каталогу.\n\nДив. [references/refactoring-catalog.md](references/refactoring-catalog.md) для повного списку.\n\n#### Відповідність запахів рефакторингам\n\n| Запах коду | Рекомендований рефакторинг |\n|------------|---------------------------|\n| Long Method | Extract Method, Replace Temp with Query |\n| Duplicated Code | Extract Method, Pull Up Method, Form Template Method |\n| Large Class | Extract Class, Extract Subclass |\n| Feature Envy | Move Method, Move Field |\n| Primitive Obsession | Replace Primitive with Object, Replace Type Code with Class |\n| Long Parameter List | Introduce Parameter Object, Preserve Whole Object |\n| Data Clumps | Extract Class, Introduce Parameter Object |\n| Switch Statements | Replace Conditional with Polymorphism |\n| Speculative Generality | Collapse Hierarchy, Inline Class, Remove Dead Code |\n| Dead Code | Remove Dead Code |\n\n### Структура плану\n\nВикористовуйте шаблон [templates/refactoring-plan.md](templates/refactoring-plan.md).\n\nДля кожного рефакторингу:\n1. **Ціль**: Який код зміниться\n2. **Запах**: Яку проблему вирішує\n3. **Рефакторинг**: Яку техніку застосувати\n4. **Кроки**: Детальні мікрокроки\n5. **Ризики**: Що може піти не так\n6. **Відкат**: Як скасувати за потреби\n\n### Поетапний підхід\n\n**КРИТИЧНО**: Впроваджуйте рефакторинг поступово, фазами.\n\n**Фаза A: Швидкі перемоги** (Низький ризик, висока цінність)\n- Перейменування змінних для ясності\n- Витяг очевидного дубльованого коду\n- Видалення мертвого коду\n\n**Фаза B: Структурні покращення** (Середній ризик)\n- Витяг методів з довгих функцій\n- Введення обʼєктів параметрів\n- Переміщення методів до відповідних класів\n\n**Фаза C: Архітектурні зміни** (Вищий ризик)\n- Заміна умовних конструкцій поліморфізмом\n- Витяг класів\n- Введення патернів проєктування\n\n### Точка рішення: Представити план користувачу\n\nПеред реалізацією:\n- Показати повний план рефакторингу\n- Пояснити кожну фазу та її ризики\n- Отримати явне затвердження для кожної фази\n- **Запитати**: «Чи продовжити з Фазою A?»\n\n---\n\n## Фаза 5: Інкрементальна реалізація\n\n### Золоте правило\n> «Зміна → Тест → Зелений? → Коміт → Наступний крок»\n\n### Ритм реалізації\n\nДля кожного кроку рефакторингу:\n\n1. **Попередня перевірка**\n   - Тести проходять (зелені)\n   - Код компілюється\n\n2. **Зробити ОДНУ малу зміну**\n   - Дотримуватися механіки з каталогу\n   - Тримати зміни мінімальними\n\n3. **Верифікація**\n   - Негайно запустити тести\n   - Перевірити на помилки компіляції\n\n4. **Якщо тести проходять (зелені)**\n   - Закомітити з описовим повідомленням\n   - Перейти до наступного кроку\n\n5. **Якщо тести не проходять (червоні)**\n   - ЗУПИНИТИСЯ негайно\n   - Скасувати зміну\n   - Проаналізувати, що пішло не так\n   - Запитати користувача, якщо незрозуміло\n\n### Стратегія комітів\n\nКожен коміт має бути:\n- **Атомарний**: Одна логічна зміна\n- **Оборотний**: Легко відкатити\n- **Описовий**: Зрозуміле повідомлення коміту\n\nПриклади повідомлень комітів:\n```\nrefactor: Extract calculateTotal() from processOrder()\nrefactor: Rename 'x' to 'customerCount' for clarity\nrefactor: Remove unused validateOldFormat() method\n```\n\n### Звіт про прогрес\n\nПісля кожної підфази звітувати користувачу:\n- Внесені зміни\n- Тести досі проходять?\n- Виявлені проблеми\n- **Запитати**: «Продовжити з наступною порцією?»\n\n---\n\n## Фаза 6: Перегляд та ітерація\n\n### Контрольний список після рефакторингу\n\n- [ ] Усі тести проходять\n- [ ] Немає нових попереджень/помилок\n- [ ] Код успішно компілюється\n- [ ] Поведінка не змінилася (ручна верифікація)\n- [ ] Документація оновлена за потреби\n- [ ] Історія комітів чиста\n\n### Порівняння метрик\n\nЗапустити аналіз складності до і після:\n```bash\npython scripts/analyze-complexity.py <file>\n```\n\nПредставити покращення:\n- Зміна кількості рядків коду\n- Зміна цикломатичної складності\n- Зміна індексу супровідності\n\n### Перегляд користувачем\n\nПредставити фінальні результати:\n- Резюме всіх змін\n- Порівняння коду до/після\n- Покращення метрик\n- Залишковий технічний борг\n- **Запитати**: «Чи задоволені ви цими змінами?»\n\n### Наступні кроки\n\nОбговорити з користувачем:\n- Додаткові запахи для усунення?\n- Запланувати подальший рефакторинг?\n- Застосувати аналогічні зміни в інших місцях?\n\n---\n\n## Важливі рекомендації\n\n### Коли ЗУПИНИТИСЯ та запитати\n\nЗавжди паузу та консультацію з користувачем, коли:\n- Невпевненість щодо бізнес-логіки\n- Зміна може вплинути на зовнішні API\n- Покриття тестами недостатнє\n- Потрібне значне архітектурне рішення\n- Рівень ризику зростає\n- Зустрічаєте неочікувану складність\n\n### Правила безпеки\n\n1. **Ніколи не рефакторити без тестів** (якщо користувач явно не підтвердив ризик)\n2. **Ніколи не робити великих змін** — розбивати на крихітні кроки\n3. **Ніколи не пропускати запуск тестів** після кожної зміни\n4. **Ніколи не продовжувати, якщо тести не проходять** — виправити або відкатити\n5. **Ніколи не припускати** — якщо сумніваєтесь, запитайте\n\n### Чого НЕ робити\n\n- Не поєднуйте рефакторинг з додаванням функцій\n- Не рефакторте під час аварій на продакшні\n- Не рефакторте код, який не розумієте\n- Не переускладнюйте — тримайте просто\n- Не рефакторте все одразу\n\n---\n\n## Приклад швидкого старту\n\n### Сценарій: Довгий метод з дублюванням\n\n**До:**\n```javascript\nfunction processOrder(order) {\n  // 150 рядків коду з:\n  // - Дубльованою логікою валідації\n  // - Інлайн-обчисленнями\n  // - Змішаними відповідальностями\n}\n```\n\n**Кроки рефакторингу:**\n\n1. **Переконатися, що тести існують** для processOrder()\n2. **Витягти** валідацію у validateOrder()\n3. **Тест** — має пройти\n4. **Витягти** обчислення у calculateOrderTotal()\n5. **Тест** — має пройти\n6. **Витягти** сповіщення у notifyCustomer()\n7. **Тест** — має пройти\n8. **Перегляд** — processOrder() тепер оркеструє 3 чіткі функції\n\n**Після:**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const total = calculateOrderTotal(order);\n  notifyCustomer(order, total);\n  return { order, total };\n}\n```\n\n---\n\n## Довідники\n\n- [Каталог запахів коду](references/code-smells.md) — повний список запахів коду\n- [Каталог рефакторингів](references/refactoring-catalog.md) — техніки рефакторингу\n- [Шаблон плану рефакторингу](templates/refactoring-plan.md) — шаблон планування\n\n## Скрипти\n\n- `scripts/analyze-complexity.py` — аналіз метрик складності коду\n- `scripts/detect-smells.py` — автоматичне виявлення запахів\n\n## Історія версій\n\n- v1.0.0 (2025-01-15): Початковий випуск з методологією Фаулера, поетапним підходом, точками консультації з користувачем\n","uk/03-skills/refactor/references/code-smells.md":"# Каталог запахів коду\n\nКомплексний довідник запахів коду на основі книги Мартіна Фаулера *Refactoring* (2-ге видання). Запахи коду — це симптоми глибших проблем; вони вказують на те, що щось може бути не так з дизайном вашого коду.\n\n> «Запах коду — це поверхнева ознака, яка зазвичай відповідає глибшій проблемі в системі.» — Мартін Фаулер\n\n---\n\n## Роздуті елементи (Bloaters)\n\nЗапахи коду, що представляють щось, що розрослося занадто великим для ефективної роботи.\n\n### Long Method (Довгий метод)\n\n**Ознаки:**\n- Метод перевищує 30-50 рядків\n- Потрібно прокручувати, щоб побачити весь метод\n- Кілька рівнів вкладеності\n- Коментарі пояснюють, що роблять секції\n\n**Чому це погано:**\n- Важко зрозуміти\n- Складно тестувати ізольовано\n- Зміни мають непередбачувані наслідки\n- Дубльована логіка ховається всередині\n\n**Рефакторинги:**\n- Extract Method\n- Replace Temp with Query\n- Introduce Parameter Object\n- Replace Method with Method Object\n- Decompose Conditional\n\n**Приклад (до):**\n```javascript\nfunction processOrder(order) {\n  // Валідація замовлення (20 рядків)\n  if (!order.items) throw new Error('No items');\n  if (order.items.length === 0) throw new Error('Empty order');\n  // ... ще валідація\n\n  // Обчислення підсумків (30 рядків)\n  let subtotal = 0;\n  for (const item of order.items) {\n    subtotal += item.price * item.quantity;\n  }\n  // ... податок, доставка, знижки\n\n  // Надсилання сповіщень (20 рядків)\n  // ... логіка email\n}\n```\n\n**Приклад (після):**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const totals = calculateOrderTotals(order);\n  sendOrderNotifications(order, totals);\n  return { order, totals };\n}\n```\n\n---\n\n### Large Class (Великий клас)\n\n**Ознаки:**\n- Клас має багато полів екземпляра (>7-10)\n- Клас має багато методів (>15-20)\n- Назва класу розмита (Manager, Handler, Processor)\n- Методи не використовують усі поля екземпляра\n\n**Чому це погано:**\n- Порушує принцип єдиної відповідальності\n- Важко тестувати\n- Зміни поширюються на неповʼязані функції\n- Складно повторно використовувати частини\n\n**Рефакторинги:**\n- Extract Class\n- Extract Subclass\n- Extract Interface\n\n**Виявлення:**\n```\nРядків коду > 300\nКількість методів > 15\nКількість полів > 10\n```\n\n---\n\n### Primitive Obsession (Одержимість примітивами)\n\n**Ознаки:**\n- Використання примітивів для доменних концепцій (string для email, int для грошей)\n- Масиви примітивів замість обʼєктів\n- Рядкові константи для кодів типів\n- Магічні числа/рядки\n\n**Чому це погано:**\n- Немає валідації на рівні типу\n- Логіка розкидана по кодовій базі\n- Легко передати неправильні значення\n- Відсутні доменні концепції\n\n**Рефакторинги:**\n- Replace Primitive with Object\n- Replace Type Code with Class\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**Приклад (до):**\n```javascript\nconst user = {\n  email: 'john@example.com',     // Просто рядок\n  phone: '1234567890',           // Просто рядок\n  status: 'active',              // Магічний рядок\n  balance: 10050                 // Копійки як ціле число\n};\n```\n\n**Приклад (після):**\n```javascript\nconst user = {\n  email: new Email('john@example.com'),\n  phone: new PhoneNumber('1234567890'),\n  status: UserStatus.ACTIVE,\n  balance: Money.cents(10050)\n};\n```\n\n---\n\n### Long Parameter List (Довгий список параметрів)\n\n**Ознаки:**\n- Методи з 4+ параметрами\n- Параметри, що завжди зʼявляються разом\n- Булеві прапорці, що змінюють поведінку методу\n- Часте передавання null/undefined\n\n**Чому це погано:**\n- Важко викликати правильно\n- Плутанина з порядком параметрів\n- Вказує, що метод робить занадто багато\n- Важко додавати нові параметри\n\n**Рефакторинги:**\n- Introduce Parameter Object\n- Preserve Whole Object\n- Replace Parameter with Method Call\n- Remove Flag Argument\n\n**Приклад (до):**\n```javascript\nfunction createUser(firstName, lastName, email, phone,\n                    street, city, state, zip,\n                    isAdmin, isActive, createdBy) {\n  // ...\n}\n```\n\n**Приклад (після):**\n```javascript\nfunction createUser(personalInfo, address, options) {\n  // personalInfo: { firstName, lastName, email, phone }\n  // address: { street, city, state, zip }\n  // options: { isAdmin, isActive, createdBy }\n}\n```\n\n---\n\n### Data Clumps (Групи даних)\n\n**Ознаки:**\n- Ті самі 3+ поля зʼявляються разом повторно\n- Параметри, що завжди подорожують разом\n- Класи з підмножинами полів, що належать один одному\n\n**Чому це погано:**\n- Дубльована логіка обробки\n- Відсутня абстракція\n- Важче розширювати\n- Вказує на прихований клас\n\n**Рефакторинги:**\n- Extract Class\n- Introduce Parameter Object\n- Preserve Whole Object\n\n**Приклад:**\n```javascript\n// Група даних: координати (x, y, z)\nfunction movePoint(x, y, z, dx, dy, dz) { }\nfunction scalePoint(x, y, z, factor) { }\nfunction distanceBetween(x1, y1, z1, x2, y2, z2) { }\n\n// Витяг класу Point3D\nclass Point3D {\n  constructor(x, y, z) { }\n  move(delta) { }\n  scale(factor) { }\n  distanceTo(other) { }\n}\n```\n\n---\n\n## Зловживання обʼєктною орієнтацією (OO Abusers)\n\nЗапахи, що вказують на неповне або некоректне використання принципів ООП.\n\n### Switch Statements (Оператори Switch)\n\n**Ознаки:**\n- Довгі ланцюжки switch/case або if/else\n- Той самий switch у кількох місцях\n- Switch за кодами типів\n- Додавання нових випадків вимагає змін всюди\n\n**Чому це погано:**\n- Порушує принцип відкритості/закритості\n- Зміни поширюються на всі місця з switch\n- Важко розширювати\n- Часто вказує на відсутній поліморфізм\n\n**Рефакторинги:**\n- Replace Conditional with Polymorphism\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**Приклад (до):**\n```javascript\nfunction calculatePay(employee) {\n  switch (employee.type) {\n    case 'hourly':\n      return employee.hours * employee.rate;\n    case 'salaried':\n      return employee.salary / 12;\n    case 'commissioned':\n      return employee.sales * employee.commission;\n  }\n}\n```\n\n**Приклад (після):**\n```javascript\nclass HourlyEmployee {\n  calculatePay() {\n    return this.hours * this.rate;\n  }\n}\n\nclass SalariedEmployee {\n  calculatePay() {\n    return this.salary / 12;\n  }\n}\n```\n\n---\n\n### Temporary Field (Тимчасове поле)\n\n**Ознаки:**\n- Поля екземпляра, що використовуються лише в деяких методах\n- Поля, що встановлюються умовно\n- Складна ініціалізація для певних випадків\n\n**Чому це погано:**\n- Плутанина — поле існує, але може бути null\n- Важко зрозуміти стан обʼєкта\n- Вказує на приховану умовну логіку\n\n**Рефакторинги:**\n- Extract Class\n- Introduce Null Object\n- Replace Temp Field with Local\n\n---\n\n### Refused Bequest (Відхилена спадщина)\n\n**Ознаки:**\n- Підклас не використовує успадковані методи/дані\n- Підклас перевизначає, щоб нічого не робити\n- Успадкування використовується для повторного використання коду, а не для відношення IS-A\n\n**Чому це погано:**\n- Неправильна абстракція\n- Порушує принцип підстановки Лісков\n- Оманлива ієрархія\n\n**Рефакторинги:**\n- Push Down Method/Field\n- Replace Subclass with Delegate\n- Replace Inheritance with Delegation\n\n---\n\n### Alternative Classes with Different Interfaces (Альтернативні класи з різними інтерфейсами)\n\n**Ознаки:**\n- Два класи, що роблять схожі речі\n- Різні назви методів для тієї самої концепції\n- Можуть використовуватися взаємозамінно\n\n**Чому це погано:**\n- Дубльовані реалізації\n- Немає спільного інтерфейсу\n- Важко перемикатися між ними\n\n**Рефакторинги:**\n- Rename Method\n- Move Method\n- Extract Superclass\n- Extract Interface\n\n---\n\n## Перешкоди для змін (Change Preventers)\n\nЗапахи, що ускладнюють зміни — зміна однієї речі вимагає зміни багатьох інших.\n\n### Divergent Change (Дивергентна зміна)\n\n**Ознаки:**\n- Один клас змінюється з кількох різних причин\n- Зміни в різних областях запускають редагування того самого класу\n- Клас є «God-класом»\n\n**Чому це погано:**\n- Порушує принцип єдиної відповідальності\n- Висока частота змін\n- Конфлікти злиття\n\n**Рефакторинги:**\n- Extract Class\n- Extract Superclass\n- Extract Subclass\n\n**Приклад:**\nКлас `User` змінюється через:\n- Зміни автентифікації\n- Зміни профілю\n- Зміни білінгу\n- Зміни сповіщень\n\n→ Витягти: `AuthService`, `ProfileService`, `BillingService`, `NotificationService`\n\n---\n\n### Shotgun Surgery (Хірургія дробовиком)\n\n**Ознаки:**\n- Одна зміна вимагає редагування в багатьох класах\n- Мала функція потребує правок у 10+ файлах\n- Зміни розкидані, важко знайти всі\n\n**Чому це погано:**\n- Легко пропустити місце\n- Високий звʼязок (coupling)\n- Зміни схильні до помилок\n\n**Рефакторинги:**\n- Move Method\n- Move Field\n- Inline Class\n\n**Виявлення:**\nШукайте: додавання одного поля вимагає змін у >5 файлах.\n\n---\n\n### Parallel Inheritance Hierarchies (Паралельні ієрархії успадкування)\n\n**Ознаки:**\n- Створення підкласу в одній ієрархії вимагає підкласу в іншій\n- Префікси класів збігаються (напр., `DatabaseOrder`, `DatabaseProduct`)\n\n**Чому це погано:**\n- Подвійне обслуговування\n- Звʼязок між ієрархіями\n- Легко забути одну сторону\n\n**Рефакторинги:**\n- Move Method\n- Move Field\n- Усунути одну ієрархію\n\n---\n\n## Непотрібне (Dispensables)\n\nЩось непотрібне, що слід видалити.\n\n### Comments (Надмірні коментарі)\n\n**Ознаки:**\n- Коментарі, що пояснюють, що робить код\n- Закоментований код\n- TODO/FIXME, що залишаються назавжди\n- Вибачення в коментарях\n\n**Чому це погано:**\n- Коментарі брешуть (розсинхронізуються)\n- Код має бути самодокументованим\n- Мертвий код створює плутанину\n\n**Рефакторинги:**\n- Extract Method (назва пояснює що)\n- Rename (ясність без коментарів)\n- Видалити закоментований код\n- Introduce Assertion\n\n**Хороші vs погані коментарі:**\n```javascript\n// ПОГАНО: Пояснює що\n// Цикл по користувачах і перевірка чи активні\nfor (const user of users) {\n  if (user.status === 'active') { }\n}\n\n// ДОБРЕ: Пояснює чому\n// Лише активні — неактивні обробляються задачею очищення\nconst activeUsers = users.filter(u => u.isActive);\n```\n\n---\n\n### Duplicate Code (Дубльований код)\n\n**Ознаки:**\n- Той самий код у кількох місцях\n- Схожий код з малими варіаціями\n- Патерни копі-пасту\n\n**Чому це погано:**\n- Виправлення помилок потрібне в кількох місцях\n- Ризик неконсистентності\n- Роздута кодова база\n\n**Рефакторинги:**\n- Extract Method\n- Extract Class\n- Pull Up Method (в ієрархіях)\n- Form Template Method\n\n**Правило виявлення:**\nБудь-який код, дубльований 3+ разів, слід витягти.\n\n---\n\n### Lazy Class (Ледачий клас)\n\n**Ознаки:**\n- Клас не робить достатньо для виправдання свого існування\n- Обгортка без доданої цінності\n- Результат надмірної інженерії\n\n**Чому це погано:**\n- Накладні витрати обслуговування\n- Непотрібна непрямість\n- Складність без користі\n\n**Рефакторинги:**\n- Inline Class\n- Collapse Hierarchy\n\n---\n\n### Dead Code (Мертвий код)\n\n**Ознаки:**\n- Недосяжний код\n- Невикористані змінні/методи/класи\n- Закоментований код\n- Код за неможливими умовами\n\n**Чому це погано:**\n- Плутанина\n- Тягар обслуговування\n- Уповільнює розуміння\n\n**Рефакторинги:**\n- Remove Dead Code\n- Safe Delete\n\n**Виявлення:**\n```bash\n# Шукати невикористані експорти\n# Шукати невикористані функції\n# Попередження IDE \"unused\"\n```\n\n---\n\n### Speculative Generality (Спекулятивна загальність)\n\n**Ознаки:**\n- Абстрактні класи з одним підкласом\n- Невикористані параметри «на майбутнє»\n- Методи, що лише делегують\n- «Фреймворк» для одного випадку\n\n**Чому це погано:**\n- Складність без користі\n- YAGNI (You Ain't Gonna Need It — Вам це не знадобиться)\n- Важче зрозуміти\n\n**Рефакторинги:**\n- Collapse Hierarchy\n- Inline Class\n- Remove Parameter\n- Rename Method\n\n---\n\n## Звʼязувачі (Couplers)\n\nЗапахи, що представляють надмірний звʼязок між класами.\n\n### Feature Envy (Заздрість до функцій)\n\n**Ознаки:**\n- Метод використовує більше даних іншого класу, ніж свого\n- Багато викликів геттерів іншого обʼєкта\n- Дані та поведінка розділені\n\n**Чому це погано:**\n- Неправильне розташування поведінки\n- Погана інкапсуляція\n- Важко супроводжувати\n\n**Рефакторинги:**\n- Move Method\n- Move Field\n- Extract Method (потім перемістити)\n\n**Приклад (до):**\n```javascript\nclass Order {\n  getDiscountedPrice(customer) {\n    // Інтенсивно використовує дані customer\n    if (customer.loyaltyYears > 5) {\n      return this.price * customer.discountRate;\n    }\n    return this.price;\n  }\n}\n```\n\n**Приклад (після):**\n```javascript\nclass Customer {\n  getDiscountedPriceFor(price) {\n    if (this.loyaltyYears > 5) {\n      return price * this.discountRate;\n    }\n    return price;\n  }\n}\n```\n\n---\n\n### Inappropriate Intimacy (Недоречна інтимність)\n\n**Ознаки:**\n- Класи отримують доступ до приватних частин один одного\n- Двосторонні посилання\n- Підкласи знають занадто багато про батьків\n\n**Чому це погано:**\n- Високий звʼязок\n- Зміни каскадуються\n- Важко модифікувати один без іншого\n\n**Рефакторинги:**\n- Move Method\n- Move Field\n- Change Bidirectional to Unidirectional\n- Extract Class\n- Hide Delegate\n\n---\n\n### Message Chains (Ланцюжки повідомлень)\n\n**Ознаки:**\n- Довгі ланцюжки викликів: `a.getB().getC().getD().getValue()`\n- Клієнт залежить від структури навігації\n- Код типу «потяг-катастрофа» (train wreck)\n\n**Чому це погано:**\n- Крихкий — будь-яка зміна ламає ланцюжок\n- Порушує Закон Деметри\n- Звʼязок зі структурою\n\n**Рефакторинги:**\n- Hide Delegate\n- Extract Method\n- Move Method\n\n**Приклад:**\n```javascript\n// Погано: Ланцюжок повідомлень\nconst managerName = employee.getDepartment().getManager().getName();\n\n// Краще: Приховати делегування\nconst managerName = employee.getManagerName();\n```\n\n---\n\n### Middle Man (Посередник)\n\n**Ознаки:**\n- Клас, що лише делегує іншому\n- Половина методів — делегування\n- Немає доданої цінності\n\n**Чому це погано:**\n- Непотрібна непрямість\n- Накладні витрати обслуговування\n- Заплутана архітектура\n\n**Рефакторинги:**\n- Remove Middle Man\n- Inline Method\n\n---\n\n## Посібник серйозності запахів\n\n| Серйозність | Опис | Дія |\n|-------------|------|-----|\n| **Критичний** | Блокує розробку, спричиняє помилки | Виправити негайно |\n| **Високий** | Значний тягар обслуговування | Виправити в поточному спринті |\n| **Середній** | Помітний, але керований | Запланувати на найближче майбутнє |\n| **Низький** | Незначна незручність | Виправляти при нагоді |\n\n---\n\n## Контрольний список швидкого виявлення\n\nВикористовуйте цей список при скануванні коду:\n\n- [ ] Є методи > 30 рядків?\n- [ ] Є класи > 300 рядків?\n- [ ] Є методи з > 4 параметрами?\n- [ ] Є дубльовані блоки коду?\n- [ ] Є switch/case за кодами типів?\n- [ ] Є невикористаний код?\n- [ ] Є методи, що інтенсивно використовують дані іншого класу?\n- [ ] Є довгі ланцюжки викликів?\n- [ ] Є коментарі, що пояснюють «що», а не «чому»?\n- [ ] Є примітиви, що мають бути обʼєктами?\n\n---\n\n## Додаткове читання\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Kerievsky, J. (2004). *Refactoring to Patterns*\n- Feathers, M. (2004). *Working Effectively with Legacy Code*\n","uk/03-skills/refactor/references/refactoring-catalog.md":"# Каталог рефакторингів\n\nКурований каталог технік рефакторингу з книги Мартіна Фаулера *Refactoring* (2-ге видання). Кожен рефакторинг включає мотивацію, покрокову механіку та приклади.\n\n> «Рефакторинг визначається своєю механікою — точною послідовністю кроків, яких ви дотримуєтесь для здійснення зміни.» — Мартін Фаулер\n\n---\n\n## Як використовувати цей каталог\n\n1. **Виявити запах** за допомогою довідника запахів коду\n2. **Знайти відповідний рефакторинг** у цьому каталозі\n3. **Дотримуватися механіки** крок за кроком\n4. **Тестувати після кожного кроку** для збереження поведінки\n\n**Золоте правило**: Якщо будь-який крок займає більше 10 хвилин, розбийте його на менші кроки.\n\n---\n\n## Найпоширеніші рефакторинги\n\n### Extract Method\n\n**Коли використовувати**: Довгий метод, дубльований код, потрібно назвати концепцію\n\n**Мотивація**: Перетворити фрагмент коду на метод, назва якого пояснює призначення.\n\n**Механіка**:\n1. Створити новий метод, названий за тим, що він робить (не як)\n2. Скопіювати фрагмент коду в новий метод\n3. Просканувати локальні змінні, використані у фрагменті\n4. Передати локальні змінні як параметри (або оголосити в методі)\n5. Обробити повернені значення належним чином\n6. Замінити оригінальний фрагмент викликом нового методу\n7. Тестувати\n\n**До**:\n```javascript\nfunction printOwing(invoice) {\n  let outstanding = 0;\n\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n\n  // Обчислення заборгованості\n  for (const order of invoice.orders) {\n    outstanding += order.amount;\n  }\n\n  // Друк деталей\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n**Після**:\n```javascript\nfunction printOwing(invoice) {\n  printBanner();\n  const outstanding = calculateOutstanding(invoice);\n  printDetails(invoice, outstanding);\n}\n\nfunction printBanner() {\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n}\n\nfunction calculateOutstanding(invoice) {\n  return invoice.orders.reduce((sum, order) => sum + order.amount, 0);\n}\n\nfunction printDetails(invoice, outstanding) {\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n---\n\n### Inline Method\n\n**Коли використовувати**: Тіло методу таке ж зрозуміле, як його назва; надмірне делегування\n\n**Мотивація**: Видалити непотрібну непрямість, коли метод не додає цінності.\n\n**Механіка**:\n1. Перевірити, що метод не є поліморфним\n2. Знайти всі виклики методу\n3. Замінити кожен виклик тілом методу\n4. Тестувати після кожної заміни\n5. Видалити визначення методу\n\n**До**:\n```javascript\nfunction getRating(driver) {\n  return moreThanFiveLateDeliveries(driver) ? 2 : 1;\n}\n\nfunction moreThanFiveLateDeliveries(driver) {\n  return driver.numberOfLateDeliveries > 5;\n}\n```\n\n**Після**:\n```javascript\nfunction getRating(driver) {\n  return driver.numberOfLateDeliveries > 5 ? 2 : 1;\n}\n```\n\n---\n\n### Extract Variable\n\n**Коли використовувати**: Складний вираз, важкий для розуміння\n\n**Мотивація**: Дати назву частині складного виразу.\n\n**Механіка**:\n1. Переконатися, що вираз не має побічних ефектів\n2. Оголосити незмінну змінну\n3. Встановити її як результат виразу (або частини)\n4. Замінити оригінальний вираз змінною\n5. Тестувати\n\n**До**:\n```javascript\nreturn order.quantity * order.itemPrice -\n  Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +\n  Math.min(order.quantity * order.itemPrice * 0.1, 100);\n```\n\n**Після**:\n```javascript\nconst basePrice = order.quantity * order.itemPrice;\nconst quantityDiscount = Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;\nconst shipping = Math.min(basePrice * 0.1, 100);\nreturn basePrice - quantityDiscount + shipping;\n```\n\n---\n\n### Inline Variable\n\n**Коли використовувати**: Назва змінної не передає більше, ніж вираз\n\n**Мотивація**: Видалити непотрібну непрямість.\n\n**Механіка**:\n1. Перевірити, що права частина не має побічних ефектів\n2. Якщо змінна не незмінна, зробити її такою і тестувати\n3. Знайти перше посилання та замінити виразом\n4. Тестувати\n5. Повторити для всіх посилань\n6. Видалити оголошення та присвоєння\n7. Тестувати\n\n---\n\n### Rename Variable\n\n**Коли використовувати**: Назва не чітко передає призначення\n\n**Мотивація**: Хороші назви критичні для чистого коду.\n\n**Механіка**:\n1. Якщо змінна широко використовується, розглянути інкапсуляцію\n2. Знайти всі посилання\n3. Змінити кожне посилання\n4. Тестувати\n\n**Поради**:\n- Використовуйте назви, що розкривають намір\n- Уникайте абревіатур\n- Використовуйте доменну термінологію\n\n```javascript\n// Погано\nconst d = 30;\nconst x = users.filter(u => u.a);\n\n// Добре\nconst daysSinceLastLogin = 30;\nconst activeUsers = users.filter(user => user.isActive);\n```\n\n---\n\n### Change Function Declaration\n\n**Коли використовувати**: Назва функції не пояснює призначення, параметри потребують зміни\n\n**Мотивація**: Хороші назви функцій роблять код самодокументованим.\n\n**Механіка (проста)**:\n1. Видалити непотрібні параметри\n2. Змінити назву\n3. Додати потрібні параметри\n4. Тестувати\n\n**Механіка (міграція — для складних змін)**:\n1. Якщо видаляєте параметр, переконайтеся, що він не використовується\n2. Створити нову функцію з бажаним оголошенням\n3. Зробити так, щоб стара функція викликала нову\n4. Тестувати\n5. Змінити виклики на нову функцію\n6. Тестувати після кожного\n7. Видалити стару функцію\n\n**До**:\n```javascript\nfunction circum(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n**Після**:\n```javascript\nfunction circumference(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n---\n\n### Encapsulate Variable\n\n**Коли використовувати**: Прямий доступ до даних з кількох місць\n\n**Мотивація**: Забезпечити чітку точку доступу для маніпуляції даними.\n\n**Механіка**:\n1. Створити функції getter та setter\n2. Знайти всі посилання\n3. Замінити читання на getter\n4. Замінити записи на setter\n5. Тестувати після кожної зміни\n6. Обмежити видимість змінної\n\n**До**:\n```javascript\nlet defaultOwner = { firstName: \"Martin\", lastName: \"Fowler\" };\n\n// Використовується в багатьох місцях\nspaceship.owner = defaultOwner;\n```\n\n**Після**:\n```javascript\nlet defaultOwnerData = { firstName: \"Martin\", lastName: \"Fowler\" };\n\nfunction defaultOwner() { return defaultOwnerData; }\nfunction setDefaultOwner(arg) { defaultOwnerData = arg; }\n\nspaceship.owner = defaultOwner();\n```\n\n---\n\n### Introduce Parameter Object\n\n**Коли використовувати**: Кілька параметрів, що часто зʼявляються разом\n\n**Мотивація**: Згрупувати дані, що природно належать разом.\n\n**Механіка**:\n1. Створити новий клас/структуру для згрупованих параметрів\n2. Тестувати\n3. Використати Change Function Declaration для додавання нового обʼєкта\n4. Тестувати\n5. Для кожного параметра в групі видалити його з функції та використати новий обʼєкт\n6. Тестувати після кожного\n\n**До**:\n```javascript\nfunction amountInvoiced(startDate, endDate) { ... }\nfunction amountReceived(startDate, endDate) { ... }\nfunction amountOverdue(startDate, endDate) { ... }\n```\n\n**Після**:\n```javascript\nclass DateRange {\n  constructor(start, end) {\n    this.start = start;\n    this.end = end;\n  }\n}\n\nfunction amountInvoiced(dateRange) { ... }\nfunction amountReceived(dateRange) { ... }\nfunction amountOverdue(dateRange) { ... }\n```\n\n---\n\n### Combine Functions into Class\n\n**Коли використовувати**: Кілька функцій оперують тими самими даними\n\n**Мотивація**: Згрупувати функції з даними, над якими вони працюють.\n\n**Механіка**:\n1. Застосувати Encapsulate Record до спільних даних\n2. Перемістити кожну функцію в клас\n3. Тестувати після кожного переміщення\n4. Замінити аргументи даних використанням полів класу\n\n**До**:\n```javascript\nfunction base(reading) { ... }\nfunction taxableCharge(reading) { ... }\nfunction calculateBaseCharge(reading) { ... }\n```\n\n**Після**:\n```javascript\nclass Reading {\n  constructor(data) { this._data = data; }\n\n  get base() { ... }\n  get taxableCharge() { ... }\n  get calculateBaseCharge() { ... }\n}\n```\n\n---\n\n### Split Phase\n\n**Коли використовувати**: Код працює з двома різними речами\n\n**Мотивація**: Розділити код на окремі фази з чіткими межами.\n\n**Механіка**:\n1. Створити другу функцію для другої фази\n2. Тестувати\n3. Ввести проміжну структуру даних між фазами\n4. Тестувати\n5. Витягти першу фазу в окрему функцію\n6. Тестувати\n\n**До**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  const shippingPerCase = (basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = quantity * shippingPerCase;\n  return basePrice - discount + shippingCost;\n}\n```\n\n**Після**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const priceData = calculatePricingData(product, quantity);\n  return applyShipping(priceData, shippingMethod);\n}\n\nfunction calculatePricingData(product, quantity) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  return { basePrice, quantity, discount };\n}\n\nfunction applyShipping(priceData, shippingMethod) {\n  const shippingPerCase = (priceData.basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = priceData.quantity * shippingPerCase;\n  return priceData.basePrice - priceData.discount + shippingCost;\n}\n```\n\n---\n\n## Переміщення функцій (Moving Features)\n\n### Move Method\n\n**Коли використовувати**: Метод використовує більше можливостей іншого класу, ніж свого\n\n**Мотивація**: Розміщувати функції разом з даними, які вони використовують найбільше.\n\n**Механіка**:\n1. Дослідити всі елементи програми, використані методом у своєму класі\n2. Перевірити, чи метод є поліморфним\n3. Скопіювати метод у цільовий клас\n4. Адаптувати до нового контексту\n5. Зробити оригінальний метод делегуючим до цільового\n6. Тестувати\n7. Розглянути видалення оригінального методу\n\n---\n\n### Move Field\n\n**Коли використовувати**: Поле використовується більше іншим класом\n\n**Мотивація**: Тримати дані разом з функціями, що їх використовують.\n\n**Механіка**:\n1. Інкапсулювати поле, якщо ще не зроблено\n2. Тестувати\n3. Створити поле в цільовому класі\n4. Оновити посилання на використання цільового поля\n5. Тестувати\n6. Видалити оригінальне поле\n\n---\n\n### Move Statements into Function\n\n**Коли використовувати**: Той самий код завжди зʼявляється разом з викликом функції\n\n**Мотивація**: Видалити дублювання, перемістивши повторюваний код у функцію.\n\n**Механіка**:\n1. Витягти повторюваний код у функцію, якщо ще не зроблено\n2. Перемістити оператори в цю функцію\n3. Тестувати\n4. Якщо виклики більше не потребують окремих операторів, видалити їх\n\n---\n\n### Move Statements to Callers\n\n**Коли використовувати**: Загальна поведінка різниться між викликачами\n\n**Мотивація**: Коли поведінка має відрізнятися, перемістити її з функції.\n\n**Механіка**:\n1. Використати Extract Method на коді для переміщення\n2. Використати Inline Method на оригінальній функції\n3. Видалити тепер вбудований виклик\n4. Перемістити витягнутий код до кожного виклику\n5. Тестувати\n\n---\n\n## Організація даних (Organizing Data)\n\n### Replace Primitive with Object\n\n**Коли використовувати**: Елемент даних потребує більше поведінки, ніж просте значення\n\n**Мотивація**: Інкапсулювати дані разом з їхньою поведінкою.\n\n**Механіка**:\n1. Застосувати Encapsulate Variable\n2. Створити простий клас значення\n3. Змінити setter для створення нового екземпляра\n4. Змінити getter для повернення значення\n5. Тестувати\n6. Додати багатшу поведінку до нового класу\n\n**До**:\n```javascript\nclass Order {\n  constructor(data) {\n    this.priority = data.priority; // рядок: \"high\", \"rush\" тощо\n  }\n}\n\n// Використання\nif (order.priority === \"high\" || order.priority === \"rush\") { ... }\n```\n\n**Після**:\n```javascript\nclass Priority {\n  constructor(value) {\n    if (!Priority.legalValues().includes(value))\n      throw new Error(`Invalid priority: ${value}`);\n    this._value = value;\n  }\n\n  static legalValues() { return ['low', 'normal', 'high', 'rush']; }\n  get value() { return this._value; }\n\n  higherThan(other) {\n    return Priority.legalValues().indexOf(this._value) >\n           Priority.legalValues().indexOf(other._value);\n  }\n}\n\n// Використання\nif (order.priority.higherThan(new Priority(\"normal\"))) { ... }\n```\n\n---\n\n### Replace Temp with Query\n\n**Коли використовувати**: Тимчасова змінна зберігає результат виразу\n\n**Мотивація**: Зробити код зрозумілішим, витягнувши вираз у функцію.\n\n**Механіка**:\n1. Перевірити, що змінна присвоюється лише один раз\n2. Витягти праву частину присвоєння в метод\n3. Замінити посилання на тимчасову змінну викликом методу\n4. Тестувати\n5. Видалити оголошення та присвоєння тимчасової змінної\n\n**До**:\n```javascript\nconst basePrice = this._quantity * this._itemPrice;\nif (basePrice > 1000) {\n  return basePrice * 0.95;\n} else {\n  return basePrice * 0.98;\n}\n```\n\n**Після**:\n```javascript\nget basePrice() {\n  return this._quantity * this._itemPrice;\n}\n\n// В методі\nif (this.basePrice > 1000) {\n  return this.basePrice * 0.95;\n} else {\n  return this.basePrice * 0.98;\n}\n```\n\n---\n\n## Спрощення умовної логіки (Simplifying Conditional Logic)\n\n### Decompose Conditional\n\n**Коли використовувати**: Складний умовний оператор (if-then-else)\n\n**Мотивація**: Зробити намір зрозумілим, витягнувши умови та дії.\n\n**Механіка**:\n1. Застосувати Extract Method на умові\n2. Застосувати Extract Method на then-гілці\n3. Застосувати Extract Method на else-гілці (якщо є)\n\n**До**:\n```javascript\nif (!aDate.isBefore(plan.summerStart) && !aDate.isAfter(plan.summerEnd)) {\n  charge = quantity * plan.summerRate;\n} else {\n  charge = quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n**Після**:\n```javascript\nif (isSummer(aDate, plan)) {\n  charge = summerCharge(quantity, plan);\n} else {\n  charge = regularCharge(quantity, plan);\n}\n\nfunction isSummer(date, plan) {\n  return !date.isBefore(plan.summerStart) && !date.isAfter(plan.summerEnd);\n}\n\nfunction summerCharge(quantity, plan) {\n  return quantity * plan.summerRate;\n}\n\nfunction regularCharge(quantity, plan) {\n  return quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n---\n\n### Consolidate Conditional Expression\n\n**Коли використовувати**: Кілька умов з однаковим результатом\n\n**Мотивація**: Зробити зрозумілим, що умови є однією перевіркою.\n\n**Механіка**:\n1. Перевірити відсутність побічних ефектів в умовах\n2. Обʼєднати умови за допомогою `and` або `or`\n3. Розглянути Extract Method на обʼєднаній умові\n\n**До**:\n```javascript\nif (employee.seniority < 2) return 0;\nif (employee.monthsDisabled > 12) return 0;\nif (employee.isPartTime) return 0;\n```\n\n**Після**:\n```javascript\nif (isNotEligibleForDisability(employee)) return 0;\n\nfunction isNotEligibleForDisability(employee) {\n  return employee.seniority < 2 ||\n         employee.monthsDisabled > 12 ||\n         employee.isPartTime;\n}\n```\n\n---\n\n### Replace Nested Conditional with Guard Clauses\n\n**Коли використовувати**: Глибоко вкладені умови ускладнюють відстеження потоку\n\n**Мотивація**: Використовувати захисні вирази (guard clauses) для спеціальних випадків, зберігаючи нормальний потік зрозумілим.\n\n**Механіка**:\n1. Знайти умови спеціальних випадків\n2. Замінити їх захисними виразами з раннім поверненням\n3. Тестувати після кожної зміни\n\n**До**:\n```javascript\nfunction payAmount(employee) {\n  let result;\n  if (employee.isSeparated) {\n    result = { amount: 0, reasonCode: \"SEP\" };\n  } else {\n    if (employee.isRetired) {\n      result = { amount: 0, reasonCode: \"RET\" };\n    } else {\n      result = calculateNormalPay(employee);\n    }\n  }\n  return result;\n}\n```\n\n**Після**:\n```javascript\nfunction payAmount(employee) {\n  if (employee.isSeparated) return { amount: 0, reasonCode: \"SEP\" };\n  if (employee.isRetired) return { amount: 0, reasonCode: \"RET\" };\n  return calculateNormalPay(employee);\n}\n```\n\n---\n\n### Replace Conditional with Polymorphism\n\n**Коли використовувати**: Switch/case за типом, умовна логіка що варіюється за типом\n\n**Мотивація**: Дозволити обʼєктам обробляти свою поведінку самостійно.\n\n**Механіка**:\n1. Створити ієрархію класів (якщо не існує)\n2. Використати фабричну функцію для створення обʼєктів\n3. Перемістити умовну логіку в метод суперкласу\n4. Створити метод підкласу для кожного випадку\n5. Видалити оригінальну умову\n\n**До**:\n```javascript\nfunction plumage(bird) {\n  switch (bird.type) {\n    case 'EuropeanSwallow':\n      return \"average\";\n    case 'AfricanSwallow':\n      return (bird.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n    case 'NorwegianBlueParrot':\n      return (bird.voltage > 100) ? \"scorched\" : \"beautiful\";\n    default:\n      return \"unknown\";\n  }\n}\n```\n\n**Після**:\n```javascript\nclass Bird {\n  get plumage() { return \"unknown\"; }\n}\n\nclass EuropeanSwallow extends Bird {\n  get plumage() { return \"average\"; }\n}\n\nclass AfricanSwallow extends Bird {\n  get plumage() {\n    return (this.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n  }\n}\n\nclass NorwegianBlueParrot extends Bird {\n  get plumage() {\n    return (this.voltage > 100) ? \"scorched\" : \"beautiful\";\n  }\n}\n\nfunction createBird(data) {\n  switch (data.type) {\n    case 'EuropeanSwallow': return new EuropeanSwallow(data);\n    case 'AfricanSwallow': return new AfricanSwallow(data);\n    case 'NorwegianBlueParrot': return new NorwegianBlueParrot(data);\n    default: return new Bird(data);\n  }\n}\n```\n\n---\n\n### Introduce Special Case (Null Object)\n\n**Коли використовувати**: Повторні перевірки на null для спеціальних випадків\n\n**Мотивація**: Повертати спеціальний обʼєкт, що обробляє спеціальний випадок.\n\n**Механіка**:\n1. Створити клас спеціального випадку з очікуваним інтерфейсом\n2. Додати перевірку isSpecialCase\n3. Ввести фабричний метод\n4. Замінити перевірки на null використанням обʼєкта спеціального випадку\n5. Тестувати\n\n**До**:\n```javascript\nconst customer = site.customer;\n// ... багато місць з перевіркою\nif (customer === \"unknown\") {\n  customerName = \"occupant\";\n} else {\n  customerName = customer.name;\n}\n```\n\n**Після**:\n```javascript\nclass UnknownCustomer {\n  get name() { return \"occupant\"; }\n  get billingPlan() { return registry.defaultPlan; }\n}\n\n// Фабричний метод\nfunction customer(site) {\n  return site.customer === \"unknown\"\n    ? new UnknownCustomer()\n    : site.customer;\n}\n\n// Використання — перевірки на null не потрібні\nconst customerName = customer.name;\n```\n\n---\n\n## Рефакторинг API (Refactoring APIs)\n\n### Separate Query from Modifier\n\n**Коли використовувати**: Функція і повертає значення, і має побічні ефекти\n\n**Мотивація**: Зробити зрозумілим, які операції мають побічні ефекти.\n\n**Механіка**:\n1. Створити нову функцію-запит\n2. Скопіювати логіку повернення оригінальної функції\n3. Змінити оригінал, щоб повертав void\n4. Замінити виклики, що використовують повернене значення\n5. Тестувати\n\n**До**:\n```javascript\nfunction alertForMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") {\n      setOffAlarms();\n      return \"Don\";\n    }\n    if (p === \"John\") {\n      setOffAlarms();\n      return \"John\";\n    }\n  }\n  return \"\";\n}\n```\n\n**Після**:\n```javascript\nfunction findMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") return \"Don\";\n    if (p === \"John\") return \"John\";\n  }\n  return \"\";\n}\n\nfunction alertForMiscreant(people) {\n  if (findMiscreant(people) !== \"\") setOffAlarms();\n}\n```\n\n---\n\n### Parameterize Function\n\n**Коли використовувати**: Кілька функцій роблять схожі речі з різними значеннями\n\n**Мотивація**: Видалити дублювання додаванням параметра.\n\n**Механіка**:\n1. Обрати одну функцію\n2. Додати параметр для варійованого літерала\n3. Змінити тіло для використання параметра\n4. Тестувати\n5. Змінити виклики на параметризовану версію\n6. Видалити тепер невикористані функції\n\n**До**:\n```javascript\nfunction tenPercentRaise(person) {\n  person.salary = person.salary * 1.10;\n}\n\nfunction fivePercentRaise(person) {\n  person.salary = person.salary * 1.05;\n}\n```\n\n**Після**:\n```javascript\nfunction raise(person, factor) {\n  person.salary = person.salary * (1 + factor);\n}\n\n// Використання\nraise(person, 0.10);\nraise(person, 0.05);\n```\n\n---\n\n### Remove Flag Argument\n\n**Коли використовувати**: Булевий параметр, що змінює поведінку функції\n\n**Мотивація**: Зробити поведінку явною через окремі функції.\n\n**Механіка**:\n1. Створити явну функцію для кожного значення прапорця\n2. Замінити кожен виклик відповідною новою функцією\n3. Тестувати після кожної зміни\n4. Видалити оригінальну функцію\n\n**До**:\n```javascript\nfunction bookConcert(customer, isPremium) {\n  if (isPremium) {\n    // логіка преміум-бронювання\n  } else {\n    // логіка звичайного бронювання\n  }\n}\n\nbookConcert(customer, true);\nbookConcert(customer, false);\n```\n\n**Після**:\n```javascript\nfunction bookPremiumConcert(customer) {\n  // логіка преміум-бронювання\n}\n\nfunction bookRegularConcert(customer) {\n  // логіка звичайного бронювання\n}\n\nbookPremiumConcert(customer);\nbookRegularConcert(customer);\n```\n\n---\n\n## Робота з успадкуванням (Dealing with Inheritance)\n\n### Pull Up Method\n\n**Коли використовувати**: Той самий метод у кількох підкласах\n\n**Мотивація**: Видалити дублювання в ієрархії класів.\n\n**Механіка**:\n1. Перевірити, що методи ідентичні\n2. Перевірити, що сигнатури однакові\n3. Створити новий метод у суперкласі\n4. Скопіювати тіло з одного підкласу\n5. Видалити один метод підкласу, тестувати\n6. Видалити інші методи підкласів, тестувати кожен\n\n---\n\n### Push Down Method\n\n**Коли використовувати**: Поведінка релевантна лише для підмножини підкласів\n\n**Мотивація**: Розмістити метод там, де він використовується.\n\n**Механіка**:\n1. Скопіювати метод у кожен підклас, що його потребує\n2. Видалити метод із суперкласу\n3. Тестувати\n4. Видалити з підкласів, що його не потребують\n5. Тестувати\n\n---\n\n### Replace Subclass with Delegate\n\n**Коли використовувати**: Успадкування використовується некоректно, потрібна більша гнучкість\n\n**Мотивація**: Віддавати перевагу композиції над успадкуванням, коли доречно.\n\n**Механіка**:\n1. Створити порожній клас для делегата\n2. Додати поле в клас-хост для утримання делегата\n3. Створити конструктор для делегата, що викликається з хоста\n4. Перемістити функціональність до делегата\n5. Тестувати після кожного переміщення\n6. Замінити успадкування делегуванням\n\n---\n\n## Extract Class\n\n**Коли використовувати**: Великий клас з кількома відповідальностями\n\n**Мотивація**: Розділити клас для збереження єдиної відповідальності.\n\n**Механіка**:\n1. Вирішити, як розділити відповідальності\n2. Створити новий клас\n3. Перемістити поле з оригіналу до нового класу\n4. Тестувати\n5. Перемістити методи з оригіналу до нового класу\n6. Тестувати після кожного переміщення\n7. Переглянути та перейменувати обидва класи\n8. Вирішити, як відкрити новий клас\n\n**До**:\n```javascript\nclass Person {\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get officeAreaCode() { return this._officeAreaCode; }\n  set officeAreaCode(arg) { this._officeAreaCode = arg; }\n  get officeNumber() { return this._officeNumber; }\n  set officeNumber(arg) { this._officeNumber = arg; }\n\n  get telephoneNumber() {\n    return `(${this._officeAreaCode}) ${this._officeNumber}`;\n  }\n}\n```\n\n**Після**:\n```javascript\nclass Person {\n  constructor() {\n    this._telephoneNumber = new TelephoneNumber();\n  }\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get telephoneNumber() { return this._telephoneNumber.toString(); }\n  get officeAreaCode() { return this._telephoneNumber.areaCode; }\n  set officeAreaCode(arg) { this._telephoneNumber.areaCode = arg; }\n}\n\nclass TelephoneNumber {\n  get areaCode() { return this._areaCode; }\n  set areaCode(arg) { this._areaCode = arg; }\n  get number() { return this._number; }\n  set number(arg) { this._number = arg; }\n  toString() { return `(${this._areaCode}) ${this._number}`; }\n}\n```\n\n---\n\n## Короткий довідник: Запах → Рефакторинг\n\n| Запах коду | Основний рефакторинг | Альтернатива |\n|------------|---------------------|--------------|\n| Long Method | Extract Method | Replace Temp with Query |\n| Duplicate Code | Extract Method | Pull Up Method |\n| Large Class | Extract Class | Extract Subclass |\n| Long Parameter List | Introduce Parameter Object | Preserve Whole Object |\n| Feature Envy | Move Method | Extract Method + Move |\n| Data Clumps | Extract Class | Introduce Parameter Object |\n| Primitive Obsession | Replace Primitive with Object | Replace Type Code |\n| Switch Statements | Replace Conditional with Polymorphism | Replace Type Code |\n| Temporary Field | Extract Class | Introduce Null Object |\n| Message Chains | Hide Delegate | Extract Method |\n| Middle Man | Remove Middle Man | Inline Method |\n| Divergent Change | Extract Class | Split Phase |\n| Shotgun Surgery | Move Method | Inline Class |\n| Dead Code | Remove Dead Code | - |\n| Speculative Generality | Collapse Hierarchy | Inline Class |\n\n---\n\n## Додаткове читання\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Онлайн-каталог: https://refactoring.com/catalog/\n","uk/07-plugins/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2FREADME.md -->","uk/07-plugins/devops-automation/.claude-plugin/plugin.json":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fdevops-automation%2F.claude-plugin%2Fplugin.json -->","uk/07-plugins/devops-automation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fdevops-automation%2FREADME.md -->","uk/07-plugins/documentation/.claude-plugin/plugin.json":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fdocumentation%2F.claude-plugin%2Fplugin.json -->","uk/07-plugins/documentation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fdocumentation%2FREADME.md -->","uk/07-plugins/documentation/commands/generate-readme.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fdocumentation%2Fcommands%2Fgenerate-readme.md -->","uk/07-plugins/pr-review/.claude-plugin/plugin.json":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fpr-review%2F.claude-plugin%2Fplugin.json -->","uk/07-plugins/pr-review/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fpr-review%2FREADME.md -->","uk/CLAUDE.md":"<!-- i18n-source: CLAUDE.md -->\n<!-- i18n-source-sha: 63a1416 -->\n<!-- i18n-date: 2026-04-10 -->\n\n# CLAUDE.md\n\nЦей файл надає настанови для Claude Code (claude.ai/code) при роботі з кодом у цьому репозиторії.\n\n## Огляд проєкту\n\nClaude How To — це навчальний репозиторій з функцій Claude Code. Це **документація-як-код** — основний продукт — markdown-файли, організовані в пронумеровані навчальні модулі, а не виконуваний додаток.\n\n**Архітектура**: Кожен модуль (01-10) охоплює конкретну функцію Claude Code з готовими шаблонами для копіювання, Mermaid-діаграмами та прикладами. Система збірки валідує якість документації та генерує EPUB-книгу.\n\n## Типові команди\n\n### Перевірки якості pre-commit\n\nУся документація повинна пройти п'ять перевірок якості перед комітами (запускаються автоматично через pre-commit хуки):\n\n```bash\n# Install pre-commit hooks (runs on every commit)\npre-commit install\n\n# Run all checks manually\npre-commit run --all-files\n```\n\nП'ять перевірок:\n1. **markdown-lint** — Структура та форматування Markdown через `markdownlint`\n2. **cross-references** — Внутрішні посилання, якорі, синтаксис блоків коду (Python-скрипт)\n3. **mermaid-syntax** — Валідація коректного парсингу всіх Mermaid-діаграм (Python-скрипт)\n4. **link-check** — Доступність зовнішніх URL (Python-скрипт)\n5. **markdown-rendering** — Markdown рендериться без помилок (Python-скрипт)\n\nЗбірка EPUB **не є** pre-commit хуком — вона виконується лише в CI (джоб `build-epub` у `.github/workflows/test.yml`), бо це повільна збірка всієї книги; хук mermaid-syntax уже рендерить кожну діаграму тим самим бандлом Pele.\n\n### Налаштування середовища розробки\n\n```bash\n# Install uv (Python package manager)\npip install uv\n\n# Create virtual environment and install Python dependencies\nuv venv\nsource .venv/bin/activate\nuv pip install -r scripts/requirements-dev.txt\n\n# Install Node.js tools (markdown linter)\nnpm install -g markdownlint-cli\n\n# Mermaid diagrams render with Pele: needs Node.js >= 20, no global package\nnode --version\n\n# Install pre-commit hooks\nuv pip install pre-commit\npre-commit install\n```\n\n### Тестування\n\nPython-скрипти в `scripts/` мають юніт-тести:\n\n```bash\n# Run all tests\npytest scripts/tests/ -v\n\n# Run with coverage\npytest scripts/tests/ -v --cov=scripts --cov-report=html\n\n# Run specific test\npytest scripts/tests/test_build_epub.py -v\n```\n\n### Якість коду\n\n```bash\n# Lint and format Python code\nruff check scripts/\nruff format scripts/\n\n# Security scan\nbandit -c scripts/pyproject.toml -r scripts/ --exclude scripts/tests/\n\n# Type checking\nmypy scripts/ --ignore-missing-imports\n```\n\n### Збірка EPUB\n\n```bash\n# Generate ebook (renders Mermaid diagrams with Pele — needs Node.js >= 20; the pinned bundle downloads once)\nuv run scripts/build_epub.py\n\n# With options\nuv run scripts/build_epub.py --verbose --output custom-name.epub\n```\n\n## Структура каталогів\n\n```\n├── 01-slash-commands/      # Ярлики, ініційовані користувачем\n├── 02-memory/              # Приклади постійного контексту\n├── 03-skills/              # Повторно використовувані можливості\n├── 04-subagents/           # Спеціалізовані AI-асистенти\n├── 05-mcp/                 # Приклади Model Context Protocol\n├── 06-hooks/               # Автоматизація на основі подій\n├── 07-plugins/             # Пакетні функції\n├── 08-checkpoints/         # Знімки сесій\n├── 09-advanced-features/   # Планування, мислення, фони\n├── 10-cli/                 # Довідник CLI\n├── scripts/\n│   ├── build_epub.py           # Генератор EPUB (рендерить Mermaid через Pele)\n│   ├── check_cross_references.py   # Валідація внутрішніх посилань\n│   ├── check_links.py          # Перевірка зовнішніх URL\n│   ├── check_mermaid.py        # Валідація синтаксису Mermaid\n│   └── tests/                  # Юніт-тести для скриптів\n├── .pre-commit-config.yaml    # Визначення перевірок якості\n└── README.md               # Основний довідник (також індекс модулів)\n```\n\n## Настанови щодо контенту\n\n### Структура модуля\nКожна пронумерована папка дотримується патерну:\n- **README.md** — Огляд функції з прикладами\n- **Файли прикладів** — Готові шаблони для копіювання (`.md` для команд, `.json` для конфігурацій, `.sh` для хуків)\n- Файли організовані за складністю функцій та залежностями\n\n### Mermaid-діаграми\n- Усі діаграми повинні успішно парситися (перевіряється pre-commit хуком)\n- Збірка EPUB рендерить діаграми через Pele (потрібен Node.js >= 20; закріплений бандл завантажується лише під час першого запуску, далі все працює офлайн)\n- Використовуйте Mermaid для блок-схем, діаграм послідовностей та архітектурних візуалізацій\n\n### Перехресні посилання\n- Використовуйте відносні шляхи для внутрішніх посилань (напр., `(01-slash-commands/README.md)`)\n- Блоки коду повинні вказувати мову (напр., ` ```bash `, ` ```python `)\n- Якірні посилання використовують формат `#heading-name`\n\n### Валідація посилань\n- Зовнішні URL повинні бути доступні (перевіряється pre-commit хуком)\n- Уникайте посилань на тимчасовий контент\n- Використовуйте пермалінки де можливо\n\n## Ключові архітектурні рішення\n\n1. **Пронумеровані папки вказують порядок навчання** — Префікс 01-10 відображає рекомендовану послідовність вивчення функцій Claude Code. Ця нумерація навмисна; не реорганізовуйте за алфавітом.\n\n2. **Скрипти — утиліти, а не продукт** — Python-скрипти в `scripts/` підтримують якість документації та генерацію EPUB. Фактичний контент — у пронумерованих папках модулів.\n\n3. **Pre-commit — привратник** — Усі перевірки якості повинні пройти перед прийняттям PR. CI-конвеєр запускає ці ж перевірки як другий прохід.\n\n4. **Рендеринг Mermaid потребує Node.js >= 20** — Збірка EPUB запускає закріплений бандл Pele через Node.js для рендерингу діаграм (бандл завантажується лише під час першого запуску, перевіряється за sha256 і кешується). Помилки збірки тут зазвичай пов'язані з відсутнім Node.js >= 20, невдалим завантаженням бандла або невалідним синтаксисом Mermaid. Хуки mermaid у pre-commit працюють у суворому режимі з Node.js 22, який надає сам pre-commit, тож вони падають, а не пропускають перевірку. Сама збірка EPUB не виконується у pre-commit — лише в CI.\n\n5. **Це туторіал, а не бібліотека** — При додаванні контенту зосереджуйтесь на чітких поясненнях, готових прикладах та візуальних діаграмах. Цінність — у навчанні концепцій, а не у наданні повторно використовуваного коду.\n\n## Конвенції комітів\n\nДотримуйтесь формату conventional commits:\n- `feat(slash-commands): Add API documentation generator`\n- `docs(memory): Improve personal preferences example`\n- `fix(README): Correct table of contents link`\n- `refactor(hooks): Simplify hook configuration examples`\n\nСкоуп повинен відповідати назві папки де можливо.\n","vi/03-skills/blog-draft/SKILL.md":"---\nname: blog-draft\ndescription: Soạn thảo bài đăng blog từ ý tưởng và tài nguyên. Sử dụng khi người dùng muốn viết bài blog, tạo nội dung từ nghiên cứu, hoặc soạn thảo bài viết. Hướng dẫn qua nghiên cứu, động não, lập dàn ý, và soạn thảo lặp lại với kiểm soát phiên bản.\n---\n\n## Đầu Vào Người Dùng\n\n```text\n$ARGUMENTS\n```\n\nBạn **BẮT BUỘC** phải xem xét đầu vào của người dùng trước khi tiếp tục. Người dùng nên cung cấp:\n- **Ý tưởng/Chủ đề**: Khái niệm hoặc chủ đề chính cho bài đăng blog\n- **Tài nguyên**: URLs, files, hoặc tài liệu tham khảo để nghiên cứu (tùy chọn nhưng được khuyến nghị)\n- **Đối tượng mục tiêu**: Bài đăng blog dành cho ai (tùy chọn)\n- **Giọng điệu/Phong cách**: Trang trọng, thân mật, kỹ thuật, v.v. (tùy chọn)\n\n**QUAN TRỌNG**: Nếu người dùng đang yêu cầu cập nhật cho một **bài đăng blog hiện có**, bỏ qua các bước 0-8 và bắt đầu trực tiếp tại **Bước 9**. Đọc các file draft hiện có trước, sau đó tiếp tục với quy trình lặp lại.\n\n## Quy Trình Thực Thi\n\nLàm theo các bước này tuần tự. **Đừng bỏ qua bước hoặc tiếp tục mà không có sự chấp thuận của người dùng nơi được chỉ ra.**\n\n### Bước 0: Tạo Thư Mục Dự Án\n\n1. Tạo tên thư mục sử dụng định dạng: `YYYY-MM-DD-ten-chu-de-ngan`\n   - Sử dụng ngày hôm nay\n   - Tạo một slug ngắn, thân thiện với URL từ chủ đề (chữ thường, gạch ngang, tối đa 5 từ)\n\n2. Tạo cấu trúc thư mục:\n   ```\n   blog-posts/\n   └── YYYY-MM-DD-ten-chu-de-ngan/\n       └── resources/\n   ```\n\n3. Xác nhận việc tạo thư mục với người dùng trước khi tiếp tục.\n\n### Bước 1: Nghiên Cứu & Thu Thập Tài Nguyên\n\n1. Tạo thư mục con `resources/` trong thư mục bài đăng blog\n\n2. Với mỗi tài nguyên được cung cấp:\n   - **URLs**: Lấy và lưu thông tin chính vào `resources/` dưới dạng files markdown\n   - **Files**: Đọc và tóm tắt trong `resources/`\n   - **Chủ đề**: Sử dụng tìm kiếm web để thu thập thông tin cập nhật\n\n3. Với mỗi tài nguyên, tạo một file tóm tắt trong `resources/`:\n   - `resources/source-1-[ten-ngan].md`\n   - `resources/source-2-[ten-ngan].md`\n   - v.v.\n\n4. Mỗi tóm tắt nên bao gồm:\n   ```markdown\n   # Nguồn: [Tiêu Đề/URL]\n\n   ## Các Điểm Chính\n   - Điểm 1\n   - Điểm 2\n\n   ## Trích Dẫn/Dữ Liệu Liên Quan\n   - Trích dẫn hoặc thống kê 1\n   - Trích dẫn hoặc thống kê 2\n\n   ## Cái Này Liên Quan Đến Chủ Đề Như Thế Nào\n   Giải thích ngắn về sự liên quan\n   ```\n\n5. Trình bày tóm tắt nghiên cứu cho người dùng.\n\n### Bước 2: Động Não & Làm Rõ\n\n1. Dựa trên ý tưởng và các tài nguyên đã nghiên cứu, trình bày:\n   - **Chủ đề chính** được xác định từ nghiên cứu\n   - **Góc độ tiềm năng** cho bài đăng blog\n   - **Các điểm chính** nên được bao phủ\n   - **Khoảng trống** trong thông tin cần làm rõ\n\n2. Đặt các câu hỏi làm rõ:\n   - Điều chính bạn muốn người đọc nhận được là gì?\n   - Có điểm cụ thể nào từ nghiên cứu bạn muốn nhấn mạnh không?\n   - Độ dài mục tiêu là bao nhiêu? (ngắn: 500-800 từ, trung bình: 1000-1500, dài: 2000+)\n   - Có điểm nào bạn muốn loại bỏ không?\n\n3. **Chờ phản hồi của người dùng trước khi tiếp tục.**\n\n### Bước 3: Đề Xuất Dàn Ý\n\n1. Tạo một dàn ý có cấu trúc bao gồm:\n\n   ```markdown\n   # Dàn Ý Bài Đăng Blog: [Tiêu Đề]\n\n   ## Thông Tin Meta\n   - **Đối Tượng Mục Tiêu**: [ai]\n   - **Giọng Điệu**: [phong cách]\n   - **Độ Dài Mục Tiêu**: [số lượng từ]\n   - **Điểm Chính Lấy Được**: [thông điệp chính]\n\n   ## Cấu Trúc Được Đề Xuất\n\n   ### Mở Bài/Giới Thiệu\n   - Ý tưởng mở bài hấp dẫn\n   - Thiết lập bối cảnh\n   - Tuyên bố luận điểm\n\n   ### Phần 1: [Tiêu Đề]\n   - Điểm chính A\n   - Điểm chính B\n   - Bằng chứng hỗ trợ từ [nguồn]\n\n   ### Phần 2: [Tiêu Đề]\n   - Điểm chính A\n   - Điểm chính B\n\n   [Tiếp tục cho tất cả các phần...]\n\n   ### Kết Luận\n   - Tóm tắt các điểm chính\n   - Kêu gọi hành động hoặc suy nghĩ cuối cùng\n\n   ## Nguồn Để Trích Dẫn\n   - Nguồn 1\n   - Nguồn 2\n   ```\n\n2. Trình bày dàn ý cho người dùng và **yêu cầu chấp thuận hoặc chỉnh sửa**.\n\n### Bước 4: Lưu Dàn Ý Được Chấp Thuận\n\n1. Khi người dùng chấp thuận dàn ý, lưu nó vào `OUTLINE.md` trong thư mục bài đăng blog.\n\n2. Xác nhận dàn ý đã được lưu.\n\n### Bước 5: Commit Dàn Ý (nếu trong git repo)\n\n1. Kiểm tra xem thư mục hiện tại có phải là một git repository không.\n\n2. Nếu có:\n   - Stage các file mới: thư mục bài đăng blog, resources, và OUTLINE.md\n   - Tạo commit với thông điệp: `docs: Add outline for blog post - [ten-chu-de]`\n   - Push đến remote\n\n3. Nếu không phải là git repo, bỏ qua bước này và thông báo cho người dùng.\n\n### Bước 6: Viết Bản Nháp\n\n1. Dựa trên dàn ý được chấp thuận, viết bản nháp bài đăng blog đầy đủ.\n\n2. Làm theo cấu trúc từ OUTLINE.md chính xác.\n\n3. Bao gồm:\n   - Giới thiệu hấp dẫn với mở bài\n   - Các tiêu đề phần rõ ràng\n   - Bằng chứng hỗ trợ và ví dụ từ nghiên cứu\n   - Chuyển tiếp mượt mà giữa các phần\n   - Kết luận mạnh mẽ với điểm chính\n   - **Trích dẫn**: Tất cả các so sánh, thống kê, dữ liệu, và yêu cầu thực tế PHẢI trích dẫn nguồn gốc\n\n4. Lưu bản nháp dưới dạng `draft-v0.1.md` trong thư mục bài đăng blog.\n\n5. Định dạng:\n   ```markdown\n   # [Tiêu Đề Bài Đăng Blog]\n\n   *[Tùy chọn: phụ đề hoặc câu khẩu hiệu]*\n\n   [Nội dung đầy đủ với các trích dẫn nội tuyến...]\n\n   ---\n\n   ## Tài Liệu Tham Khảo\n   - [1] Tiêu Đề Nguồn 1 - URL hoặc Trích Dẫn\n   - [2] Tiêu Đề Nguồn 2 - URL hoặc Trích Dẫn\n   - [3] Tiêu Đề Nguồn 3 - URL hoặc Trích Dẫn\n   ```\n\n6. **Yêu Cầu Trích Dẫn**:\n   - Mọi điểm dữ liệu, thống kê, hoặc so sánh PHẢI có trích dẫn nội tuyến\n   - Sử dụng tài liệu tham khảo đánh số [1], [2], v.v., hoặc trích dẫn có tên [Tên Nguồn]\n   - Liên kết các trích dẫn với phần Tài Liệu Tham Khảo ở cuối\n   - Ví dụ: \"Các nghiên cứu cho thấy 65% nhà phát triển ưa thích TypeScript [1]\"\n   - Ví dụ: \"React hoạt động tốt hơn Vue 20% về tốc độ render [React Benchmarks 2024]\"\n\n### Bước 7: Commit Bản Nháp (nếu trong git repo)\n\n1. Kiểm tra xem có trong git repository không.\n\n2. Nếu có:\n   - Stage file bản nháp\n   - Tạo commit với thông điệp: `docs: Add draft v0.1 for blog post - [ten-chu-de]`\n   - Push đến remote\n\n3. Nếu không phải là git repo, bỏ qua và thông báo cho người dùng.\n\n### Bước 8: Trình Bày Bản Nháp Để Xem Xét\n\n1. Trình bày nội dung bản nháp cho người dùng.\n\n2. Yêu cầu phản hồi:\n   - Ấn tượng tổng thể?\n   - Các phần cần mở rộng hoặc giảm bớt?\n   - Cần điều chỉnh giọng điệu?\n   - Thiếu thông tin?\n   - Chỉnh sửa hoặc viết lại cụ thể?\n\n3. **Chờ phản hồi của người dùng.**\n\n### Bước 9: Lặp Lại Hoặc Hoàn Thành\n\n**Nếu người dùng yêu cầu thay đổi:**\n1. Ghi chú tất cả các chỉnh sửa được yêu cầu\n2. Quay lại Bước 6 với các điều chỉnh sau:\n   - Tăng số phiên bản (v0.2, v0.3, v.v.)\n   - Kết hợp tất cả phản hồi\n   - Lưu dưới dạng `draft-v[X.Y].md`\n   - Lặp lại Các bước 7-8\n\n**Nếu người dùng chấp thuận:**\n1. Xác nhận phiên bản bản nháp cuối cùng\n2. Tùy chọn đổi tên thành `final.md` nếu người dùng yêu cầu\n3. Tóm tắt quy trình tạo bài đăng blog:\n   - Tổng số phiên bản được tạo\n   - Các thay đổi chính giữa các phiên bản\n   - Số lượng từ cuối cùng\n   - Các file được tạo\n\n## Theo Dõi Phiên Bản\n\nTất cả bản nháp được bảo tồn với việc đánh số phiên bản tăng dần:\n- `draft-v0.1.md` - Bản nháp ban đầu\n- `draft-v0.2.md` - Sau vòng phản hồi đầu tiên\n- `draft-v0.3.md` - Sau vòng phản hồi thứ hai\n- v.v.\n\nĐiều này cho phép theo dõi sự phát triển của bài đăng blog và hoàn tác nếu cần.\n\n## Cấu Trúc File Đầu Ra\n\n```\nblog-posts/\n└── YYYY-MM-DD-ten-chu-de/\n    ├── resources/\n    │   ├── source-1-name.md\n    │   ├── source-2-name.md\n    │   └── ...\n    ├── OUTLINE.md\n    ├── draft-v0.1.md\n    ├── draft-v0.2.md (nếu có lặp lại)\n    └── draft-v0.3.md (nếu có nhiều lặp lại hơn)\n```\n\n## Mẹo Để Chất Lượng\n\n- **Mở bài**: Bắt đầu với một câu hỏi, sự thật đáng ngạc nhiên, hoặc kịch bản có thể liên quan\n- **Dòng Chảy**: Mỗi đoạn nên kết nối với đoạn tiếp theo\n- **Bằng Chứng**: Hỗ trợ các yêu cầu với dữ liệu từ nghiên cứu\n- **Trích Dẫn**: LUÔN LUÔN trích dẫn nguồn cho:\n  - Tất cả thống kê và điểm dữ liệu (ví dụ: \"Theo [Nguồn], 75% của...\")\n  - So sánh giữa các sản phẩm, dịch vụ, hoặc cách tiếp cận (ví dụ: \"X hoạt động nhanh hơn gấp 2 lần so với Y [Nguồn]\")\n  - Các yêu cầu thực tế về xu hướng thị trường, phát hiện nghiên cứu, hoặc điểm chuẩn\n  - Sử dụng trích dẫn nội tuyến với định dạng: [Tên Nguồn] hoặc [Tác Giả, Năm]\n- **Giọng**: Duy trì giọng điệu nhất quán throughout\n- **Độ Dài**: Tôn trọng số lượng từ mục tiêu\n- **Khả Đọc**: Sử dụng các đoạn ngắn, gạch đầu dòng nơi phù hợp\n- **CTA**: Kết thúc với một lời kêu gọi hành động rõ ràng hoặc câu hỏi đáng suy ngẫm\n\n## Ghi Chú\n\n- Luôn chờ chấp thuận của người dùng tại các điểm kiểm tra được phác thảo\n- Bảo tồn tất cả các phiên bản bản nháp để lịch sử\n- Sử dụng tìm kiếm web để có thông tin cập nhật khi URLs được cung cấp\n- Nếu tài nguyên không đủ, yêu cầu người dùng thêm hoặc đề xuất nghiên cứu bổ sung\n- Thích ứng giọng điệu dựa trên đối tượng mục tiêu (kỹ thuật, chung, kinh doanh, v.v.)\n","vi/03-skills/brand-voice/SKILL.md":"---\nname: brand-voice\ndescription: Đảm bảo tất cả các truyền thông phù hợp với hướng dẫn giọng điệu và phong cách thương hiệu. Sử dụng khi tạo bản sao marketing, truyền thông khách hàng, nội dung công khai, hoặc khi người dùng đề cập đến giọng điệu thương hiệu, ngữ điệu, hoặc phong cách viết.\nuser-invocable: false\n---\n\n# Brand Voice Skill\n\n## Tổng Quan\nSkill này đảm bảo tất cả các truyền thông duy trì giọng điệu, ngữ điệu, và thông điệp thương hiệu nhất quán.\n\n## Danh Tính Thương Hiệu\n\n### Sứ Mệnh\nGiúp các đội tự động hóa workflows phát triển của họ với AI\n\n### Giá Trị\n- **Sự Đơn Giản**: Làm cho những điều phức tạp trở nên đơn giản\n- **Độ Tin Cậy**: Thực thi vững chắc\n- **Sự Trao Quyền**: Cho phép sự sáng tạo của con người\n\n### Giọng Điệu\n- **Thân thiện nhưng chuyên nghiệp** - có thể tiếp cận mà không thân mật quá\n- **Rõ ràng và ngắn gọn** - tránh thuật ngữ, giải thích các khái niệm kỹ thuật một cách đơn giản\n- **Tự Tin** - chúng tôi biết chúng tôi đang làm gì\n- **Thấu Cảm** - hiểu nhu cầu và nỗi đau của người dùng\n\n## Hướng Dẫn Viết\n\n### Nên Làm ✅\n- Sử dụng \"bạn\" khi người đọc\n- Sử dụng chủ động: \"Claude tạo báo cáo\" không \"Báo cáo được tạo bởi Claude\"\n- Bắt đầu với giá trị\n- Sử dụng các ví dụ cụ thể\n- Giữ câu dưới 20 từ\n- Sử dụng danh sách để rõ ràng\n- Bao gồm các lời kêu gọi hành động\n\n### Không Nên Làm ❌\n- Đừng sử dụng thuật ngữ công ty\n- Đừng cư xử như trên hoặc đơn giản hóa quá mức\n- Đừng sử dụng \"chúng tôi tin\" hoặc \"chúng tôi nghĩ\"\n- Đừng sử dụng HOA TOÀN THỨ TRỪ khi nhấn mạnh\n- Đừng tạo các bức tường văn bản\n- Đừng giả định kiến thức kỹ thuật\n\n## Từ Vựng\n\n### ✅ Thuật Ngữ Ưu Tiên\n- Claude (not \"the Claude AI\")\n- Code generation (not \"auto-coding\")\n- Agent (not \"bot\")\n- Streamline (not \"revolutionize\")\n- Integrate (not \"synergize\")\n\n### ❌ Tránh Thuật Ngữ\n- \"Cutting-edge\" (bị lạm dụng)\n- \"Game-changer\" (mơ hồ)\n- \"Leverage\" (ngôn ngữ công ty)\n- \"Utilize\" (use \"use\")\n- \"Paradigm shift\" (không rõ)\n\n## Ví Dụ\n\n### ✅ Ví Dụ Tốt\n\"Claude tự động hóa quy trình review code của bạn. Thay vì kiểm tra thủ công từng PR, Claude review bảo mật, hiệu suất, và chất lượng—tiết kiệm cho đội của bạn hàng mỗi tuần.\"\n\nTại sao nó hoạt động: Giá trị rõ ràng, lợi ích cụ thể, hướng hành động\n\n### ❌ Ví Dụ Xấu\n\"Claude leverages cutting-edge AI to provide comprehensive software development solutions.\"\n\nTại sao nó không hoạt động: Mơ hồ, thuật ngữ công ty, không có giá trị cụ thể\n","vi/03-skills/claude-md/SKILL.md":"---\nname: claude-md\ndescription: Tạo hoặc cập nhật các file CLAUDE.md theo các thực hành tốt nhất để onboarding tác nhân AI tối ưu\n---\n\n## Đầu Vào Người Dùng\n\n```text\n$ARGUMENTS\n```\n\nBạn **BẮT BUỘC** phải xem xét đầu vào của người dùng trước khi tiếp tục (nếu không trống). Người dùng có thể chỉ định:\n- `create` - Tạo CLAUDE.md mới từ đầu\n- `update` - Cải thiện CLAUDE.md hiện có\n- `audit` - Phân tích và báo cáo về chất lượng CLAUDE.md hiện tại\n- Một đường dẫn cụ thể để tạo/cập nhật (ví dụ: `src/api/CLAUDE.md` cho hướng dẫn cụ thể thư mục)\n\n## Nguyên Tắc Cốt Lõi\n\n**LLMs là không trạng thái**: CLAUDE.md là file dự án chính được tải vào mọi cuộc hội thoại (cùng với auto memory và các rules không giới hạn phạm vi). Nó phục vụ như tài liệu onboarding chính cho các tác nhân AI vào codebase của bạn.\n\n### Các Quy Tắc Vàng\n\n1. **Less is More**: Các LLM biên giới có thể theo ~150-200 hướng dẫn. System prompt của Claude Code đã sử dụng ~50. Giữ CLAUDE.md của bạn tập trung và ngắn gọn.\n\n2. **Ứng Dụng Phổ Biến**: Chỉ bao gồm thông tin liên quan đến MỌI phiên. Hướng dẫn cụ thể theo tác vụ thuộc về các file riêng.\n\n3. **Đừng Sử Dụng Claude như Linter**: Hướng dẫn phong cách làm phình bối cảnh và làm giảm khả năng tuân theo hướng dẫn. Sử dụng các công cụ xác định (prettier, eslint, v.v.) thay thế.\n\n4. **Không Bao Giờ Tự Động Tạo**: CLAUDE.md là điểm đòn bẩy cao nhất của hệ thống AI. Tạo nó thủ công với sự xem xét cẩn thận.\n\n## Quy Trình Thực Thi\n\n### 1. Phân Tích Dự Án\n\nĐầu tiên, phân tích trạng thái dự án hiện tại:\n\n1. Kiểm tra các file CLAUDE.md hiện có:\n   - Cấp root: `./CLAUDE.md` hoặc `.claude/CLAUDE.md`\n   - Cụ thể thư mục: `**/CLAUDE.md`\n   - Cấu hình người dùng toàn cầu: `~/.claude/CLAUDE.md`\n\n2. Xác định cấu trúc dự án:\n   - Technology stack (ngôn ngữ, frameworks)\n   - Loại dự án (monorepo, ứng dụng đơn, library)\n   - Công cụ phát triển (quản lý package, hệ thống build, trình chạy test)\n\n3. Xem lại tài liệu hiện có:\n   - README.md\n   - CONTRIBUTING.md\n   - package.json, pyproject.toml, Cargo.toml, v.v.\n\n### 2. Chiến Lược Nội Dung (WHAT, WHY, HOW)\n\nCấu trúc CLAUDE.md xung quanh ba chiều:\n\n#### WHAT - Công Nghệ & Cấu Trúc\n- Tổng quan technology stack\n- Tổ chức dự án (đặc biệt quan trọng cho monorepos)\n- Các thư mục chính và mục đích của chúng\n\n#### WHY - Mục Đích & Bối Cảnh\n- Dự án làm gì\n- Tại sao các quyết định kiến trúc nhất định được đưa ra\n- Mỗi thành phần chính chịu trách nhiệm cho gì\n\n#### HOW - Workflow & Quy Ước\n- Workflow phát triển (bun vs node, pip vs uv, v.v.)\n- Thủ tục và lệnh testing\n- Phương pháp xác minh và build\n- Các \"gotchas\" quan trọng hoặc yêu cầu không rõ ràng\n\n### 3. Chiến Lược Progressive Disclosure\n\nĐối với các dự án lớn, khuyến nghị tạo thư mục `agent_docs/`:\n\n```\nagent_docs/\n  |- building_the_project.md\n  |- running_tests.md\n  |- code_conventions.md\n  |- architecture_decisions.md\n```\n\nTrong CLAUDE.md, tham khảo các file này với các hướng dẫn như:\n```markdown\nĐể có hướng dẫn build chi tiết, tham khảo `agent_docs/building_the_project.md`\n```\n\n**Quan Trọng**: Sử dụng các tham chiếu `file:line` thay vì các đoạn code để tránh bối cảnh lỗi thời.\n\n### 4. Ràng Buộc Chất Lượng\n\nKhi tạo hoặc cập nhật CLAUDE.md:\n\n1. **Độ Dài Mục Tiêu**: Dưới 200 dòng\n2. **Không Quy Tắc Phong Cách**: Loại bỏ bất kỳ hướng dẫn linting/formatting nào\n3. **Không Hướng Dẫn Cụ Theo Tác Vụ**: Di chuyển sang các file riêng\n4. **Không Đoạn Code**: Sử dụng tham chiếu file thay thế\n5. **Không Thông Tin Dư Thừa**: Đừng lặp lại những gì trong package.json hoặc README\n\n### 5. Các Phần Thiết Yếu\n\nMột CLAUDE.md được cấu trúc tốt nên bao gồm:\n\n```markdown\n# Tên Dự Án\n\nMô tả ngắn một dòng.\n\n## Tech Stack\n- Ngôn ngữ chính và phiên bản\n- Frameworks/thư viện chính\n- Database/lưu trữ (nếu có)\n\n## Cấu Trúc Dự Án\n[Chỉ cho monorepos hoặc cấu trúc phức tạp]\n- `apps/` - Điểm vào ứng dụng\n- `packages/` - Thư viện được chia sẻ\n\n## Lệnh Phát Triển\n- Install: `command`\n- Test: `command`\n- Build: `command`\n\n## Quy Ước Quan Trọng\n[Chỉ các quy ước không rõ ràng, tác động cao]\n- Quy ước 1 với giải thích ngắn\n- Quy ước 2 với giải thích ngắn\n\n## Vấn Đế Đã Biết / Gotchas\n[Những gì luôn làm các nhà phát triển vấp phải]\n- Vấn đề 1\n- Vấn đề 2\n```\n\n### 6. Các Anti-Patterns Cần Tránh\n\n**KHÔNG bao gồm:**\n- Hướng dẫn phong cách code (sử dụng linters)\n- Tài liệu về cách sử dụng Claude\n- Giải thích dài về các mẫu rõ ràng\n- Các ví dụ code copy-paste\n- Thực hành tốt chung (\"viết code sạch\")\n- Hướng dẫn cho các tác vụ cụ thể\n- Nội dung được tạo tự động\n- Danh sách TODO mở rộng\n\n### 7. Checklist Xác Minh\n\nTrước khi hoàn thành, xác minh:\n\n- [ ] Dưới 200 dòng\n- [ ] Mọi dòng áp dụng cho TẤT CẢ các phiên\n- [ ] Không quy tắc phong cách/formatting\n- [ ] Không đoạn code (sử dụng tham chiếu file)\n- [ ] Các lệnh được xác minh hoạt động\n- [ ] Progressive disclosure được sử dụng cho các dự án phức tạp\n- [ ] Các gotchas quan trọng được tài liệu hóa\n- [ ] Không dư thừa với README.md\n\n## Định Dạng Đầu Ra\n\n### Cho `create` hoặc mặc định:\n\n1. Phân tích dự án\n2. Soạn thảo CLAUDE.md theo cấu trúc ở trên\n3. Trình bày bản nháp để xem xét\n4. Ghi vào vị trí phù hợp sau khi được chấp thuận\n\n### Cho `update`:\n\n1. Đọc CLAUDE.md hiện có\n2. Kiểm tra theo các thực hành tốt nhất\n3. Xác định:\n   - Nội dung để loại bỏ (quy tắc phong cách, đoạn code, cụ thể tác vụ)\n   - Nội dung để cô đọng\n   - Thông tin thiết bị còn thiếu\n4. Trình bày các thay đổi để xem xét\n5. Áp dụng các thay đổi sau khi được chấp thuận\n\n### Cho `audit`:\n\n1. Đọc CLAUDE.md hiện có\n2. Tạo một báo cáo với:\n   - Số dòng hiện tại vs mục tiêu\n   - Phần trăm nội dung áp dụng phổ biến\n   - Danh sách các anti-patterns được tìm thấy\n   - Khuyến nghị cải thiện\n3. KHÔNG chỉnh sửa file, chỉ báo cáo\n\n## Xử Lý AGENTS.md\n\nNếu người dùng yêu cầu tạo/cập nhật AGENTS.md:\n\n**Từ v2.1.277, Claude Code đọc `AGENTS.md` trực tiếp như hướng dẫn dự án** — nhưng chỉ khi thư mục làm việc và mọi thư mục phía trên nó đều không có `CLAUDE.md`, `.claude/CLAUDE.md`, hay `CLAUDE.local.md`. `~/.claude/CLAUDE.md`, CLAUDE.md được quản lý, và `.claude/rules/` không tính vào kiểm tra đó và vẫn được tải song song. Hành vi này được điều khiển bởi **Project instructions** trong `/config`: `claude-md-or-agents-md` (mặc định), `claude-md-and-agents-md`, `claude-md`, hoặc `managed-only`. Ở nơi không hỗ trợ đọc trực tiếp — phiên bản trước v2.1.277 (trước v2.1.281 trên Bedrock/Vertex/Foundry, LLM gateway, hoặc khi telemetry bị tắt), hoặc phiên đầu tiên sau khi nâng cấp — hãy dùng cách dự phòng: import từ CLAUDE.md bằng `@AGENTS.md`, hoặc symlink `CLAUDE.md` tới nó.\n\nAGENTS.md là file bối cảnh dự án dùng chung giữa nhiều công cụ — cùng *loại* tài liệu với CLAUDE.md, không phải định dạng định nghĩa tác nhân. Nó tồn tại để nhiều coding agent có thể dùng chung một bộ quy ước dự án:\n- Các lệnh build, test, và lint\n- Quy ước code style và kiến trúc\n- Bố cục repository và vị trí của các thành phần\n\nSubagents được định nghĩa riêng, trong `.claude/agents/*.md` — không phải trong AGENTS.md.\n\nÁp dụng các nguyên tắc tương tự:\n- Giữ tập trung và ngắn gọn\n- Sử dụng progressive disclosure\n- Tham khảo tài liệu bên ngoài thay vì nhúng nội dung\n\n## Ghi Chú\n\n- Luôn xác minh các lệnh hoạt động trước khi bao gồm chúng\n- Khi nghi ngờ, hãy loại bỏ - less is more\n- Lời nhắc hệ thống cho Claude biết rằng CLAUDE.md \"có thể hoặc có thể không liên quan\" - càng nhiều tiếng ồn, càng bị bỏ qua\n- Monorepos hưởng lợi nhất từ cấu trúc WHAT/WHY/HOW rõ ràng\n- Các file CLAUDE.md cụ thể thư mục nên được tập trung hơn nữa\n\n---\n\n**Cập Nhật Lần Cuối**: Ngày 18 tháng 10 năm 2026\n**Phiên Bản Claude Code**: 2.1.302\n**Nguồn**:\n- https://code.claude.com/docs/en/memory\n","vi/03-skills/code-review-specialist/SKILL.md":"---\nname: code-review-specialist\ndescription: Review code toàn diện với phân tích bảo mật, hiệu suất, và chất lượng. Sử dụng khi người dùng yêu cầu review code, phân tích chất lượng code, đánh giá pull requests, hoặc đề cập đến review code, phân tích bảo mật, hoặc tối ưu hóa hiệu suất.\n---\n\n# Code Review Skill\n\nSkill này cung cấp các khả năng review code toàn diện tập trung vào:\n\n1. **Phân Tích Bảo Mật**\n   - Các vấn đề xác thực/uỷ quyền\n   - Rủi ro lộ dữ liệu\n   - Lỗ hổng tiêm nhiễm\n   - Điểm yếu mật mã\n   - Ghi log dữ liệu nhạy cảm\n\n2. **Review Hiệu Suất**\n   - Hiệu quả thuật toán (phân tích Big O)\n   - Tối ưu hóa bộ nhớ\n   - Tối ưu hóa truy vấn cơ sở dữ liệu\n   - Cơ hội caching\n   - Các vấn đề đồng thời\n\n3. **Chất Lượng Code**\n   - Nguyên tắc SOLID\n   - Mẫu thiết kế\n   - Quy ước đặt tên\n   - Tài liệu hóa\n   - Phủ vùng test\n\n4. **Khả Năng Duy Trì**\n   - Khả năng đọc code\n   - Kích thước hàm (nên < 50 dòng)\n   - Độ phức tạp vòng lục\n   - Quản lý dependency\n   - An toàn kiểu\n\n## Mẫu Review\n\nĐối với mỗi đoạn code được review, cung cấp:\n\n### Tóm Tắt\n- Đánh giá chất lượng tổng thể (1-5)\n- Số lượng phát hiện chính\n- Các khu vực ưu tiên được khuyến nghị\n\n### Vấn Đề Nguy Kịch (nếu có)\n- **Vấn đề**: Mô tả rõ ràng\n- **Vị Trí**: File và số dòng\n- **Tác Động**: Tại sao điều này quan trọng\n- **Mức Độ**: Nguy Kịch/Cao/Trung Bình\n- **Khắc Phục**: Ví dụ code\n\n### Các Phát Hiện Theo Danh Mục\n\n#### Bảo Mật (nếu tìm thấy vấn đề)\nLiệt kê các lỗ hổng bảo mật với ví dụ\n\n#### Hiệu Suất (nếu tìm thấy vấn đề)\nLiệt kê các vấn đề hiệu suất với phân tích độ phức tạp\n\n#### Chất Lượng (nếu tìm thấy vấn đề)\nLiệt kê các vấn đề chất lượng code với các đề xuất refactor\n\n#### Khả Năng Duy Trì (nếu tìm thấy vấn đề)\nLiệt kê các vấn đề duy trì với các cải tiến\n\n## Lịch Sử Phiên Bản\n\n- v1.0.0 (2024-12-10): Phiên bản phát hành ban đầu với phân tích bảo mật, hiệu suất, chất lượng, và khả năng duy trì\n","vi/03-skills/refactor/SKILL.md":"---\nname: refactor\ndescription: Refactor code có hệ thống dựa trên phương pháp luận của Martin Fowler. Sử dụng khi người dùng yêu cầu refactor code, cải thiện cấu trúc code, giảm nợ kỹ thuật, dọn code legacy, loại bỏ code smells, hoặc cải thiện khả năng duy trì code. Skill này hướng dẫn qua cách tiếp theo từng giai đoạn với nghiên cứu, lập kế hoạch, và triển khai tăng dần an toàn.\n---\n\n# Code Refactoring Skill\n\nMột cách tiếp có hệ thống để refactor code dựa trên *Refactoring: Improving the Design of Existing Code* (ấn bản 2) của Martin Fowler. Skill này nhấn mạnh các thay đổi tăng dần, an toàn được hỗ trợ bởi tests.\n\n> \"Refactoring là quá trình thay đổi một hệ thống phần mềm theo cách mà nó không làm thay đổi hành vi bên ngoài của code nhưng cải thiện cấu trúc nội bộ của nó.\" — Martin Fowler\n\n## Nguyên Tắc Cốt Lõi\n\n1. **Bảo Tồn Hành Vi**: Hành vi bên ngoài phải không thay đổi\n2. **Các Bước Nhỏ**: Thực hiện các thay đổi nhỏ, có thể test\n3. **Được Dẫn Bởi Test**: Tests là lưới an toàn\n4. **Liên Tục**: Refactoring là liên tục, không phải sự kiện một lần\n5. **Hợp Tác**: Cần sự chấp thuận của người dùng tại mỗi giai đoạn\n\n## Tổng Quan Workflow\n\n```\nGiai Đoạn 1: Nghiên Cứu & Phân Tích\n    ↓\nGiai Đoạn 2: Đánh Giá Phủ Vùng Test\n    ↓\nGiai Đoạn 3: Xác Định Code Smell\n    ↓\nGiai Đoạn 4: Tạo Kế Hoạch Refactoring\n    ↓\nGiai Đoạn 5: Triển Khai Tăng Dần\n    ↓\nGiai Đoạn 6: Review & Lặp Lại\n```\n\n---\n\n## Giai Đoạn 1: Nghiên Cứu & Phân Tích\n\n### Mục Tiêu\n- Hiểu cấu trúc và mục đích của codebase\n- Xác định phạm vi của refactoring\n- Thu thập bối cảnh về các yêu cầu kinh doanh\n\n### Câu Hỏi Đặt Cho Người Dùng\nTrước khi bắt đầu, làm rõ:\n\n1. **Phạm Vi**: Những file/module/hàm nào cần refactor?\n2. **Mục Tiêu**: Bạn đang cố gắng giải quyết vấn đề gì? (khả đọc, hiệu suất, khả năng duy trì)\n3. **Ràng Buộc**: Có những khu vực nào KHÔNG NÊN thay đổi không?\n4. **Áp Lực Thời Gian**: Điều này có chặn công việc khác không?\n5. **Trạng Thái Test**: Tests có tồn tại không? Chúng có pass không?\n\n### Hành Động\n- [ ] Đọc và hiểu code mục tiêu\n- [ ] Xác định dependencies và integrations\n- [ ] Tài liệu hóa kiến trúc hiện tại\n- [ ] Ghi chú bất kỳ markers nợ kỹ thuật hiện có (TODOs, FIXMEs)\n\n### Đầu Ra\nTrình bày phát hiện cho người dùng:\n- Tóm tắt cấu trúc code\n- Các khu vực vấn đề được xác định\n- Khuyến nghị ban đầu\n- **Yêu cầu chấp thuận để tiếp tục**\n\n---\n\n## Giai Đoạn 2: Đánh Giá Phủ Vùng Test\n\n### Tại Sao Tests Quan Trọng\n> \"Refactoring mà không có tests giống như lái xe mà không có thắt dây an toàn.\" — Martin Fowler\n\nTests là **bật dụng chính** của refactoring an toàn. Không có chúng, bạn có nguy cơ giới thiệu bugs.\n\n### Các Bước Đánh Giá\n\n1. **Kiểm tra các test hiện có**\n   ```bash\n   # Tìm các file test\n   find . -name \"*test*\" -o -name \"*spec*\" | head -20\n   ```\n\n2. **Chạy các test hiện có**\n   ```bash\n   # JavaScript/TypeScript\n   npm test\n\n   # Python\n   pytest -v\n\n   # Java\n   mvn test\n   ```\n\n3. **Kiểm tra phủ vùng (nếu có)**\n   ```bash\n   # JavaScript\n   npm run test:coverage\n\n   # Python\n   pytest --cov=.\n   ```\n\n### Điểm Quyết Định: Hỏi Người Dùng\n\n**Nếu tests tồn tại và pass:**\n- Tiếp tục đến Giai Đoạn 3\n\n**Nếu tests bị thiếu hoặc không hoàn chỉnh:**\nTrình bày các tùy chọn:\n1. Viết tests trước (khuyến nghị)\n2. Thêm tests tăng dần trong khi refactoring\n3. Tiếp tục mà không có tests (rủi ro - yêu cầu sự thừa nhận của người dùng)\n\n**Nếu tests đang fail:**\n- DỪNG LẠI. Sửa các test fail trước khi refactoring\n- Hỏi người dùng: Chúng ta nên sửa tests trước không?\n\n### Hướng Dẫn Viết Test (nếu cần)\n\nĐối với mỗi hàm được refactor, đảm bảo tests bao phủ:\n- Happy path (hoạt động bình thường)\n- Các trường hợp ngoại lệ (đầu vào trống, null, ranh giới)\n- Các kịch bản lỗi (đầu vào không hợp lệ, ngoại lệ)\n\nSử dụng chu trình \"red-green-refactor\":\n1. Viết test fail (red)\n2. Làm cho nó pass (green)\n3. Refactor\n\n---\n\n## Giai Đoạn 3: Xác Định Code Smell\n\n### Code Smells Là Gì?\nCác triệu chứng của các vấn đề sâu hơn trong code. Chúng không phải là bugs, nhưng là các chỉ báo rằng code có thể được cải thiện.\n\n### Các Code Smells Phổ Biến Để Kiểm Tra\n\nXem [references/code-smells.md](../../../03-skills/refactor/references/code-smells.md) để có danh sách đầy đủ.\n\n#### Tham Khảo Nhanh\n\n| Smell | Dấu Hiệu | Tác Động |\n|-------|-------|--------|\n| **Long Method** | Methods > 30-50 dòng | Khó hiểu, test, duy trì |\n| **Duplicated Code** | Cùng logic ở nhiều nơi | Cần sửa lỗi ở nhiều nơi |\n| **Large Class** | Class với quá nhiều trách nhiệm | Vi phạm Single Responsibility |\n| **Feature Envy** | Method sử dụng dữ liệu class khác nhiều | Đóng gói kém |\n| **Primitive Obsession** | Lạm dụng primitives thay vì objects | Thiếu các khái niệm domain |\n| **Long Parameter List** | Methods với 4+ parameters | Khó gọi đúng |\n| **Data Clumps** | Cùng dữ liệu xuất hiện cùng nhau | Thiếu abstraction |\n| **Switch Statements** | Switch/if-else chains phức tạp | Khó mở rộng |\n| **Speculative Generality** | Code \"trường hợp\" | Độ phức tạp không cần thiết |\n| **Dead Code** | Code không sử dụng | Nhầm lẫn, gánh nặng duy trì |\n\n### Các Bước Phân Tích\n\n1. **Phân Tích Tự Động** (nếu scripts có sẵn)\n   ```bash\n   python scripts/detect-smells.py <file>\n   ```\n\n2. **Review Thủ Công**\n   - Đi qua code một cách có hệ thống\n   - Ghi chú mỗi smell với vị trí và mức độ nghiêm trọng\n   - Phân loại theo tác động (Nguy Kịch/Cao/Trung Bình/Thấp)\n\n3. **Ưu Tiên**\n   Tập trung vào các smells mà:\n   - Chặn phát triển hiện tại\n   - Gây bugs hoặc nhầm lẫn\n   - Ảnh hưởng đến các đường dẫn code được thay đổi nhiều nhất\n\n### Đầu Ra: Báo Cáo Smell\n\nTrình bày cho người dùng:\n- Danh sách các smells được xác định với vị trí\n- Đánh giá mức độ nghiêm trọng cho mỗi smell\n- Thứ tự ưu tiên được khuyến nghị\n- **Yêu cầu chấp thuận về các ưu tiên**\n\n---\n\n## Giai Đoạn 4: Tạo Kế Hoạch Refactoring\n\n### Chọn Refactorings\n\nĐối với mỗi smell, chọn một refactoring phù hợp từ catalog.\n\nXem [references/refactoring-catalog.md](../../../03-skills/refactor/references/refactoring-catalog.md) để có danh sách đầy đủ.\n\n#### Smell-to-Refactoring Mapping\n\n| Code Smell | Refactoring Khuyến Nghị |\n|------------|---------------------------|\n| Long Method | Extract Method, Replace Temp with Query |\n| Duplicated Code | Extract Method, Pull Up Method, Form Template Method |\n| Large Class | Extract Class, Extract Subclass |\n| Feature Envy | Move Method, Move Field |\n| Primitive Obsession | Replace Primitive with Object, Replace Type Code with Class |\n| Long Parameter List | Introduce Parameter Object, Preserve Whole Object |\n| Data Clumps | Extract Class, Introduce Parameter Object |\n| Switch Statements | Replace Conditional with Polymorphism |\n| Speculative Generality | Collapse Hierarchy, Inline Class, Remove Dead Code |\n| Dead Code | Remove Dead Code |\n\n### Cấu Trúc Kế Hoạch\n\nSử dụng mẫu tại [templates/refactoring-plan.md](../../../03-skills/refactor/templates/refactoring-plan.md).\n\nĐối với mỗi refactoring:\n1. **Mục Tiêu**: Code nào sẽ thay đổi\n2. **Smell**: Vấn đề nào nó giải quyết\n3. **Refactoring**: Kỹ thuật nào để áp dụng\n4. **Các Bước**: Các micro-bước chi tiết\n5. **Rủi Ro**: Điều gì có thể sai\n6. **Hoàn Tác**: Cách hoàn tác nếu cần\n\n### Cách Tiếp Theo Giai Đoạn\n\n**QUAN TRỌNG**: Introduce refactoring tăng dần theo các giai đoạn.\n\n**Giai Đoạn A: Quick Wins** (Rủi ro thấp, giá trị cao)\n- Đổi tên biến để rõ hơn\n- Extract code trùng lặp rõ ràng\n- Loại bỏ dead code\n\n**Giai Đoạn B: Cải Tiến Cấu Trúc** (Rủi ro trung bình)\n- Extract methods từ các hàm dài\n- Introduce parameter objects\n- Move methods đến các lớp phù hợp\n\n**Giai Đoạn C: Thay Đổi Kiến Trúc** (Rủi ro cao hơn)\n- Thay thế conditionals với polymorphism\n- Extract classes\n- Introduce design patterns\n\n### Điểm Quyết Định: Trình Bày Kế Hoạch Cho Người Dùng\n\nTrước khi triển khai:\n- Hiển thị kế hoạch refactoring hoàn chỉnh\n- Giải thích mỗi giai đoạn và rủi ro của nó\n- Nhận sự chấp thuận rõ ràng cho mỗi giai đoạn\n- **Hỏi**: \"Tôi có nên tiếp tục với Giai Đoạn A không?\"\n\n---\n\n## Giai Đoạn 5: Triển Khai Tăng Dần\n\n### Quy Tắc Vàng\n> \"Thay Đổi → Test → Xanh? → Commit → Bước tiếp theo\"\n\n### Nhịp Triển Khai\n\nĐối với mỗi bước refactoring:\n\n1. **Kiểm tra trước**\n   - Tests đang pass (xanh)\n   - Code biên dịch\n\n2. **Thực hiện MỘT thay đổi nhỏ**\n   - Làm theo các cơ chế từ catalog\n   - Giữ thay đổi tối thiểu\n\n3. **Xác Minh**\n   - Chạy tests ngay lập tức\n   - Kiểm tra lỗi biên dịch\n\n4. **Nếu tests pass (xanh)**\n   - Commit với thông điệp mô tả\n   - Di chuyển đến bước tiếp theo\n\n5. **Nếu tests fail (đỏ)**\n   - DỪNG LẠI ngay lập tức\n   - Hoàn tác thay đổi\n   - Phân tích điều gì sai\n   - Hỏi người dùng nếu không rõ\n\n### Chiến Lược Commit\n\nMỗi commit nên là:\n- **Nguyên Tử**: Một thay đổi logic\n- **Có Thể Hoàn Tác**: Dễ dàng revert\n- **Mô Tả**: Thông điệp commit rõ ràng\n\nVí dụ thông điệp commit:\n```\nrefactor: Extract calculateTotal() from processOrder()\nrefactor: Rename 'x' to 'customerCount' for clarity\nrefactor: Remove unused validateOldFormat() method\n```\n\n### Báo Cáo Tiến Độ\n\nSau mỗi sub-giai đoạn, báo cáo cho người dùng:\n- Các thay đổi được thực hiện\n- Tests vẫn pass?\n- Bất kỳ vấn đề nào gặp phải\n- **Hỏi**: \"Tiếp tục với batch tiếp theo?\"\n\n---\n\n## Giai Đoạn 6: Review & Lặp Lại\n\n### Checklist Sau Refactoring\n\n- [ ] Tất cả tests pass\n- [ ] Không có cảnh báo/lỗi mới\n- [ ] Code biên dịch thành công\n- [ ] Hành vi không thay đổi (xác minh thủ công)\n- [ ] Tài liệu được cập nhật nếu cần\n- [ ] Lịch sử commit sạch\n\n### So Sánh Metrics\n\nChạy phân tích độ phức tạp trước và sau:\n```bash\npython scripts/analyze-complexity.py <file>\n```\n\nTrình bày cải tiến:\n- Thay đổi số dòng code\n- Thay đổi độ phức tạp vòng lục\n- Thay đổi chỉ số khả năng duy trì\n\n### Review Người Dùng\n\nTrình bày kết quả cuối cùng:\n- Tóm tắt tất cả thay đổi\n- So sánh code trước/sau\n- Cải tiến metrics\n- Nợ kỹ thuật còn lại\n- **Hỏi**: \"Bạn có hài lòng với những thay đổi này không?\"\n\n### Các Bước Tiếp Theo\n\nThảo luận với người dùng:\n- Có smells bổ sung để giải quyết không?\n- Lên lịch refactoring tiếp theo?\n- Áp dụng các thay đổi tương tự ở nơi khác?\n\n---\n\n## Hướng Dẫn Quan Trọng\n\n### Khi DỪNG LẠI và Hỏi\n\nLuôn dừng lại và tham khảo người dùng khi:\n- Không chắc về logic kinh doanh\n- Thay đổi có thể ảnh hưởng APIs bên ngoài\n- Phủ vùng test không đủ\n- Cần quyết định kiến trúc quan trọng\n- Mức độ rủi ro tăng\n- Bạn gặp độ phức tạp bất ngờ\n\n### Quy Tắc An Toàn\n\n1. **Không bao giờ refactor mà không có tests** (trừ khi người dùng thừa nhận rủi ro một cách rõ ràng)\n2. **Không bao giờ thực hiện các thay đổi lớn** - chia thành các bước nhỏ\n3. **Không bao giờ bỏ qua chạy test** sau mỗi thay đổi\n4. **Không bao giờ tiếp tục nếu tests fail** - sửa hoặc hoàn tác trước\n5. **Không bao giờ giả định** - khi nghi ngờ, hãy hỏi\n\n### Những Gì KHÔNG Nên Làm\n\n- Đừng kết hợp refactoring với việc thêm tính năng\n- Đừng refactor trong các tình huống khẩn cấp của production\n- Đừng refactor code mà bạn không hiểu\n- Đừng over-engineer - giữ nó đơn giản\n- Đừng refactor tất cả cùng một lúc\n\n---\n\n## Ví Dụ Bắt Đầu Nhanh\n\n### Kịch Bản: Long Method với Duplication\n\n**Trước:**\n```javascript\nfunction processOrder(order) {\n  // 150 dòng code với:\n  // - Logic xác thực trùng lặp\n  // - Tính toán nội tuyến\n  // - Trách nhiệm hỗn hợp\n}\n```\n\n**Các Bước Refactoring:**\n\n1. **Đảm bảo tests tồn tại** cho processOrder()\n2. **Extract** xác thực vào validateOrder()\n3. **Test** - nên pass\n4. **Extract** tính toán vào calculateOrderTotal()\n5. **Test** - nên pass\n6. **Extract** thông báo vào notifyCustomer()\n7. **Test** - nên pass\n8. **Review** - processOrder() giờ điều phối 3 hàm rõ ràng\n\n**Sau:**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const total = calculateOrderTotal(order);\n  notifyCustomer(order, total);\n  return { order, total };\n}\n```\n\n---\n\n## Tài Liệu Tham Khảo\n\n- [Catalog Code Smells](../../../03-skills/refactor/references/code-smells.md) - Danh sách đầy đủ code smells\n- [Catalog Refactoring](../../../03-skills/refactor/references/refactoring-catalog.md) - Các kỹ thuật refactoring\n- [Mẫu Kế Hoạch Refactoring](../../../03-skills/refactor/templates/refactoring-plan.md) - Mẫu lập kế hoạch\n\n## Scripts\n\n- `scripts/analyze-complexity.py` - Phân tích metrics độ phức tạp code\n- `scripts/detect-smells.py` - Phát hiện smell tự động\n\n## Lịch Sử Phiên Bản\n\n- v1.0.0 (2025-01-15): Phiên bản phát hành ban đầu với phương pháp luận Fowler, cách tiếp theo từng giai đoạn, các điểm tham khảo người dùng\n","vi/07-plugins/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2FREADME.md -->","vi/07-plugins/devops-automation/.claude-plugin/plugin.json":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fdevops-automation%2F.claude-plugin%2Fplugin.json -->","vi/07-plugins/devops-automation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fdevops-automation%2FREADME.md -->","vi/07-plugins/documentation/.claude-plugin/plugin.json":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fdocumentation%2F.claude-plugin%2Fplugin.json -->","vi/07-plugins/documentation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fdocumentation%2FREADME.md -->","vi/07-plugins/documentation/commands/generate-readme.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fdocumentation%2Fcommands%2Fgenerate-readme.md -->","vi/07-plugins/pr-review/.claude-plugin/plugin.json":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fpr-review%2F.claude-plugin%2Fplugin.json -->","vi/07-plugins/pr-review/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fpr-review%2FREADME.md -->","vi/CLAUDE.md":"# CLAUDE.md\n\nFile này cung cấp hướng dẫn cho Claude Code (claude.ai/code) khi làm việc với code trong repository này.\n\n## Tổng Quan Dự Án\n\nClaude How To là một repository tutorial về các tính năng của Claude Code. Đây là **documentation-as-code** — sản phẩm chính là các file markdown được tổ chức thành các module học tập đánh số (01-10), không phải một ứng dụng thực thi.\n\n**Kiến trúc**: Mỗi module (01-10) bao phủ một tính năng cụ thể của Claude Code với các template copy-paste, sơ đồ Mermaid, và ví dụ. Hệ thống build xác thực chất lượng documentation và tạo ebook EPUB.\n\n## Các Lệnh Thường Dùng\n\n### Kiểm Tra Chất Lượng Pre-commit\n\nTất cả documentation phải vượt qua năm kiểm tra chất lượng trước khi commit (các kiểm tra này chạy tự động qua pre-commit hooks):\n\n```bash\n# Cài đặt pre-commit hooks (chạy trên mỗi commit)\npre-commit install\n\n# Chạy tất cả các kiểm tra thủ công\npre-commit run --all-files\n```\n\nNăm kiểm tra là:\n1. **markdown-lint** — Cấu trúc và định dạng Markdown qua `markdownlint`\n2. **cross-references** — Liên kết nội bộ, anchors, cú pháp code fence (Python script)\n3. **mermaid-syntax** — Xác thực tất cả sơ đồ Mermaid parse đúng (Python script)\n4. **link-check** — Các URL bên ngoài có thể truy cập được (Python script)\n5. **markdown-rendering** — Markdown render không lỗi (Python script)\n\nViệc build EPUB **không phải** là một pre-commit hook — nó chỉ chạy trong CI (job `build-epub` trong `.github/workflows/test.yml`), vì đây là bản build toàn bộ sách, chạy chậm; hook mermaid-syntax đã render mọi sơ đồ bằng cùng bundle Pele.\n\n### Thiết Lập Môi Trường Phát Triển\n\n```bash\n# Cài đặt uv (Python package manager)\npip install uv\n\n# Tạo virtual environment và cài đặt Python dependencies\nuv venv\nsource .venv/bin/activate\nuv pip install -r scripts/requirements-dev.txt\n\n# Cài đặt Node.js tools (markdown linter)\nnpm install -g markdownlint-cli\n\n# Sơ đồ Mermaid được render bằng Pele: cần Node.js >= 20, không cần cài package toàn cục\nnode --version\n\n# Cài đặt pre-commit hooks\nuv pip install pre-commit\npre-commit install\n```\n\n### Testing\n\nCác script Python trong `scripts/` có unit tests:\n\n```bash\n# Chạy tất cả tests\npytest scripts/tests/ -v\n\n# Chạy với coverage\npytest scripts/tests/ -v --cov=scripts --cov-report=html\n\n# Chạy test cụ thể\npytest scripts/tests/test_build_epub.py -v\n```\n\n### Chất Lượng Code\n\n```bash\n# Lint và format Python code\nruff check scripts/\nruff format scripts/\n\n# Security scan\nbandit -c scripts/pyproject.toml -r scripts/ --exclude scripts/tests/\n\n# Type checking\nmypy scripts/ --ignore-missing-imports\n```\n\n### Build EPUB\n\n```bash\n# Tạo ebook (render Mermaid diagrams bằng Pele — cần Node.js >= 20; bundle cố định chỉ tải về một lần)\nuv run scripts/build_epub.py\n\n# Với các tùy chọn\nuv run scripts/build_epub.py --verbose --output custom-name.epub --lang vi\n```\n\n## Cấu Trúc Thư Mục\n\n```\n├── 01-slash-commands/      # Các lối tắt do người dùng gọi\n├── 02-memory/              # Ví dụ về bối cảnh liên tục\n├── 03-skills/              # Các khả năng có thể tái sử dụng\n├── 04-subagents/           # Các tác nhân AI chuyên dụng\n├── 05-mcp/                 # Ví dụ Model Context Protocol\n├── 06-hooks/              # Tự động hóa dựa trên sự kiện\n├── 07-plugins/             # Các tính năng được đóng gói\n├── 08-checkpoints/         # Các snapshot của phiên\n├── 09-advanced-features/   # Lập kế hoạch, suy nghĩ, background tasks\n├── 10-cli/                 # Tham chiếu CLI\n├── scripts/\n│   ├── build_epub.py           # EPUB generator (render Mermaid bằng Pele)\n│   ├── check_cross_references.py   # Xác thực liên kết nội bộ\n│   ├── check_links.py          # Kiểm tra các URL bên ngoài\n│   ├── check_mermaid.py        # Xác thực cú pháp Mermaid\n│   └── tests/                  # Unit tests cho scripts\n├── .pre-commit-config.yaml    # Định nghĩa các kiểm tra chất lượng\n└── README.md               # Hướng dẫn chính (cũng là index của module)\n```\n\n## Hướng Dẫn Nội Dung\n\n### Cấu Trúc Module\n\nMỗi thư mục đánh số tuân theo pattern:\n- **README.md** — Tổng quan về tính năng với các ví dụ\n- **Các file ví dụ** — Template copy-paste (`.md` cho commands, `.json` cho configs, `.sh` cho hooks)\n- Các file được tổ chức theo độ phức tạp của tính năng và dependencies\n\n### Sơ Đồ Mermaid\n- Tất cả sơ đồ phải parse thành công (được kiểm tra bởi pre-commit hook)\n- EPUB build render sơ đồ bằng Pele (cần Node.js >= 20; bundle cố định chỉ tải về trong lần chạy đầu tiên, sau đó chạy offline)\n- Sử dụng Mermaid cho flowcharts, sequence diagrams, và architecture visuals\n\n### Cross-References\n- Sử dụng relative paths cho internal links (ví dụ: `(01-slash-commands/README.md)`)\n- Code fences phải chỉ định ngôn ngữ (ví dụ: ` ```bash `, ` ```python `)\n- Anchor links sử dụng format `#heading-name`\n\n### Link Validation\n- Các URL bên ngoài phải có thể truy cập được (được kiểm tra bởi pre-commit hook)\n- Tránh link đến nội dung tạm thời\n- Sử dụng permalinks nếu có thể\n\n## Các Điểm Kiến Trúc Quan Trọng\n\n1. **Các thư mục đánh số thể hiện thứ tự học tập** — Prefix 01-10 thể hiện thứ tự được khuyến nghị để học các tính năng của Claude Code. Đánh số này có chủ đích; không tổ chức lại theo bảng chữ cái.\n\n2. **Scripts là các tiện ích, không phải sản phẩm** — Các script Python trong `scripts/` hỗ trợ chất lượng documentation và tạo EPUB. Nội dung thực tế nằm trong các thư mục module đánh số.\n\n3. **Pre-commit là người gác cổng** — Tất cả năm kiểm tra chất lượng phải pass trước khi PR được chấp nhận. CI pipeline chạy các kiểm tra tương tự như lần thứ hai.\n\n4. **Mermaid rendering cần Node.js >= 20** — EPUB build chạy bundle Pele cố định bằng Node.js để render diagrams (bundle chỉ tải về trong lần chạy đầu tiên, được kiểm tra sha256 và lưu cache). Các lỗi build ở đây thường là do chưa cài Node.js >= 20, tải bundle thất bại, hoặc cú pháp Mermaid không hợp lệ. Các hook mermaid của pre-commit chạy ở chế độ strict với Node.js 22 do pre-commit cung cấp, nên chúng sẽ báo lỗi thay vì bỏ qua. Bản thân EPUB build không chạy trong pre-commit — nó chỉ chạy trong CI.\n\n5. **Đây là tutorial, không phải thư viện** — Khi thêm nội dung, tập trung vào giải thích rõ ràng, ví dụ copy-paste, và sơ đồ trực quan. Giá trị nằm ở việc dạy các khái niệm, không cung cấp code có thể tái sử dụng.\n\n## Commit Conventions\n\nTuân theo format conventional commit:\n- `feat(slash-commands): Add API documentation generator`\n- `docs(memory): Improve personal preferences example`\n- `fix(README): Correct table of contents link`\n- `refactor(hooks): Simplify hook configuration examples`\n\nScope nên khớp với tên thư mục khi áp dụng.\n","zh/03-skills/blog-draft/SKILL.md":"---\nname: blog-draft\ndescription: 根据想法和资料撰写博客草稿。适用于用户想写博客、基于研究创建内容，或起草文章的场景。流程会引导你完成调研、头脑风暴、提纲编写和带版本控制的迭代撰写。\n---\n\n## 用户输入\n\n```text\n$ARGUMENTS\n```\n\n在继续之前，你**必须**先考虑用户输入。用户应提供：\n- **想法/主题**：博客文章的核心概念或主题\n- **资源**：用于研究的 URL、文件或参考资料（可选，但推荐）\n- **目标读者**：这篇博客是写给谁看的（可选）\n- **语气/风格**：正式、轻松、技术向等（可选）\n\n**重要**：如果用户是在请求更新一篇**已有博客文章**，请跳过步骤 0-8，直接从**步骤 9** 开始。先阅读现有草稿文件，再继续迭代流程。\n\n## 执行流程\n\n请按顺序执行以下步骤。**不要跳步，也不要在未获得用户批准的情况下继续执行标明需要确认的步骤。**\n\n### 步骤 0：创建项目文件夹\n\n1. 使用以下格式生成文件夹名称：`YYYY-MM-DD-short-topic-name`\n   - 使用今天的日期\n   - 根据主题生成一个简短、适合 URL 的 slug（小写、连字符连接，最多 5 个词）\n\n2. 创建文件夹结构：\n   ```text\n   blog-posts/\n   └── YYYY-MM-DD-short-topic-name/\n       └── resources/\n   ```\n\n3. 在继续前，先向用户确认文件夹已创建。\n\n### 步骤 1：研究与资源收集\n\n1. 在博客文章目录中创建 `resources/` 子文件夹\n\n2. 对于每个提供的资源：\n   - **URL**：抓取关键内容并保存到 `resources/` 下的 markdown 文件中\n   - **文件**：读取并在 `resources/` 中做摘要\n   - **主题**：使用网络搜索收集最新信息\n\n3. 为每个资源在 `resources/` 中创建摘要文件：\n   - `resources/source-1-[short-name].md`\n   - `resources/source-2-[short-name].md`\n   - 以此类推\n\n4. 每个摘要都应包含：\n   ```markdown\n   # 来源：[标题/URL]\n\n   ## 要点\n   - 要点 1\n   - 要点 2\n\n   ## 相关引文/数据\n   - 引文或统计 1\n   - 引文或统计 2\n\n   ## 与主题的关联\n   简要说明其相关性\n   ```\n\n5. 向用户展示研究摘要。\n\n### 步骤 2：头脑风暴与澄清\n\n1. 基于想法和已研究的资源，展示：\n   - 从研究中识别出的**主要主题**\n   - 博客文章的**可能切入角度**\n   - 应该覆盖的**关键点**\n   - 仍需进一步澄清的**信息缺口**\n\n2. 提出澄清问题：\n   - 你希望读者最终带走的核心结论是什么？\n   - 研究中有没有哪些点是你希望重点强调的？\n   - 目标长度是多少？（短：500-800 字，中：1000-1500 字，长：2000+ 字）\n   - 有没有哪些内容你希望排除？\n\n3. **在继续之前，等待用户回复。**\n\n### 步骤 3：提出提纲\n\n1. 创建一个结构化提纲，包括：\n\n   ```markdown\n   # 博客文章提纲：[标题]\n\n   ## 元信息\n   - **目标读者**：[谁]\n   - **语气**：[风格]\n   - **目标长度**：[字数]\n   - **核心结论**：[关键信息]\n\n   ## 建议结构\n\n   ### 开场/引子\n   - 开场钩子思路\n   - 背景铺垫\n   - 论点陈述\n\n   ### 第一部分：[标题]\n   - 关键点 A\n   - 关键点 B\n   - 来自 [来源] 的支撑证据\n\n   ### 第二部分：[标题]\n   - 关键点 A\n   - 关键点 B\n\n   [继续列出所有部分...]\n\n   ### 结论\n   - 关键点总结\n   - 行动号召或最终思考\n\n   ## 需要引用的来源\n   - 来源 1\n   - 来源 2\n   ```\n\n2. 向用户展示提纲，并**请求批准或修改意见**。\n\n### 步骤 4：保存已批准的提纲\n\n1. 用户批准提纲后，将其保存为博客文章文件夹中的 `OUTLINE.md`。\n\n2. 确认提纲已保存。\n\n### 步骤 5：提交提纲（如果在 git 仓库中）\n\n1. 检查当前目录是否为 git 仓库。\n\n2. 如果是：\n   - 暂存新文件：博客文章文件夹、resources 和 `OUTLINE.md`\n   - 使用如下提交信息创建 commit：`docs: Add outline for blog post - [topic-name]`\n   - 推送到远程仓库\n\n3. 如果不是 git 仓库，则跳过此步骤并告知用户。\n\n### 步骤 6：撰写草稿\n\n1. 基于已批准的提纲，撰写完整博客草稿。\n\n2. 严格按照 `OUTLINE.md` 的结构进行编写。\n\n3. 包含：\n   - 有吸引力的引言和开场钩子\n   - 清晰的章节标题\n   - 来自研究的支撑证据和示例\n   - 段落之间自然流畅的过渡\n   - 强有力的结尾和核心收获\n   - **引用**：所有比较、统计数据和事实性陈述都必须引用原始来源\n\n4. 将草稿保存为博客文章文件夹中的 `draft-v0.1.md`。\n\n5. 格式：\n   ```markdown\n   # [博客文章标题]\n\n   *[可选：副标题或标语]*\n\n   [包含行内引用的完整正文...]\n\n   ---\n\n   ## 参考资料\n   - [1] 来源 1 标题 - URL 或引用\n   - [2] 来源 2 标题 - URL 或引用\n   - [3] 来源 3 标题 - URL 或引用\n   ```\n\n6. **引用要求**：\n   - 每个数据点、统计信息或比较都必须带有行内引用\n   - 使用编号引用 [1]、[2] 等，或命名引用 [Source Name]\n   - 在文末的参考资料部分链接这些引用\n   - 示例：“研究表明，65% 的开发者更偏好 TypeScript [1]”\n   - 示例：“React 在渲染速度上比 Vue 快 20% [React Benchmarks 2024]”\n\n### 步骤 7：提交草稿（如果在 git 仓库中）\n\n1. 检查是否处于 git 仓库中。\n\n2. 如果是：\n   - 暂存草稿文件\n   - 使用如下提交信息创建 commit：`docs: Add draft v0.1 for blog post - [topic-name]`\n   - 推送到远程仓库\n\n3. 如果不是 git 仓库，则跳过并告知用户。\n\n### 步骤 8：向用户展示草稿以供审阅\n\n1. 向用户展示草稿内容。\n\n2. 询问反馈：\n   - 整体印象如何？\n   - 哪些部分需要扩展或压缩？\n   - 是否需要调整语气？\n   - 是否缺少关键信息？\n   - 有没有具体编辑或重写建议？\n\n3. **等待用户回复。**\n\n### 步骤 9：迭代或定稿\n\n**如果用户要求修改：**\n1. 记录所有修改请求\n2. 返回步骤 6，并做以下调整：\n   - 将版本号递增（v0.2、v0.3 等）\n   - 纳入所有反馈\n   - 保存为 `draft-v[X.Y].md`\n   - 重复步骤 7-8\n\n**如果用户批准：**\n1. 确认最终草稿版本\n2. 如用户要求，可重命名为 `final.md`\n3. 总结博客文章创建过程：\n   - 一共创建了多少个版本\n   - 各版本之间的关键变化\n   - 最终字数\n   - 创建了哪些文件\n\n## 版本跟踪\n\n所有草稿都会以递增版本号保留：\n- `draft-v0.1.md` - 初始草稿\n- `draft-v0.2.md` - 第一轮反馈后\n- `draft-v0.3.md` - 第二轮反馈后\n- 以此类推\n\n这可以跟踪博客文章的演变过程，并在需要时回退。\n\n## 输出文件结构\n\n```text\nblog-posts/\n└── YYYY-MM-DD-topic-name/\n    ├── resources/\n    │   ├── source-1-name.md\n    │   ├── source-2-name.md\n    │   └── ...\n    ├── OUTLINE.md\n    ├── draft-v0.1.md\n    ├── draft-v0.2.md（如果有迭代）\n    └── draft-v0.3.md（如果还有更多迭代）\n```\n\n## 质量建议\n\n- **钩子**：以问题、令人惊讶的事实或贴近读者的场景开头\n- **衔接**：每一段都要自然连接到下一段\n- **证据**：用研究数据支撑观点\n- **引用**：以下内容务必引用来源：\n  - 所有统计数据和数值（例如：“根据 [Source]，75% 的……”）\n  - 对产品、服务或方案的比较（例如：“X 的速度比 Y 快 2 倍 [Source]”）\n  - 关于市场趋势、研究发现或基准测试的事实性陈述\n  - 使用行内引用，格式为：[Source Name] 或 [Author, Year]\n- **语气**：全程保持一致\n- **长度**：尊重目标字数\n- **可读性**：使用短段落，并在适当位置使用项目符号\n- **CTA**：以明确的行动号召或发人深省的问题收尾\n\n## 备注\n\n- 始终在上述需要确认的节点等待用户批准\n- 保留所有草稿版本，方便追踪历史\n- 如果提供了 URL，使用网络搜索获取最新信息\n- 如果资源不足，询问用户补充，或建议进一步研究\n- 根据目标读者调整语气（技术、通用、商业等）\n","zh/03-skills/brand-voice/SKILL.md":"---\nname: brand-voice\ndescription: 确保所有沟通内容都符合品牌语气和风格指南。适用于撰写营销文案、客户沟通、对外内容，或用户提到品牌语气、tone、写作风格的场景。\nuser-invocable: false\n---\n\n# 品牌语气技能\n\n## 概览\n此技能确保所有沟通内容在品牌语气、风格和信息传达上保持一致。\n\n## 品牌定位\n\n### 使命\n帮助团队用 AI 自动化开发工作流\n\n### 价值观\n- **简洁**：把复杂的事情变简单\n- **可靠**：执行稳健，结果稳定\n- **赋能**：释放人的创造力\n\n### 语气风格\n- **友好但专业** - 平易近人，但不过于随意\n- **清晰简洁** - 避免行话，用通俗方式解释技术概念\n- **自信** - 体现我们知道自己在做什么\n- **有同理心** - 理解用户需求和痛点\n\n## 写作指南\n\n### 应该做的 ✅\n- 对读者使用“你”\n- 使用主动语态：“Claude 会生成报告”，而不是“报告由 Claude 生成”\n- 先讲价值主张\n- 使用具体示例\n- 句子保持在 20 个词以内\n- 使用列表增强清晰度\n- 包含行动号召\n\n### 不应该做的 ❌\n- 不要使用企业黑话\n- 不要居高临下，也不要过度简化\n- 不要使用“我们相信”或“我们认为”\n- 不要全大写，除非为了强调\n- 不要写成大段文字墙\n- 不要默认读者具备技术背景\n\n## 词汇\n\n### ✅ 推荐用词\n- Claude（不要写“the Claude AI”）\n- 代码生成（不要写“auto-coding”）\n- Agent（不要写“bot”）\n- 简化流程（不要写“革命性改变”）\n- 集成（不要写“synergize”）\n\n### ❌ 避免用词\n- “cutting-edge”（过度使用）\n- “game-changer”（过于空泛）\n- “leverage”（企业黑话）\n- “utilize”（直接用“use”）\n- “paradigm shift”（不够清晰）\n\n## 示例\n\n### ✅ 好示例\n“Claude 能自动化你的代码审查流程。它不再需要你手动检查每个 PR，而是会审查安全性、性能和质量，每周为团队节省数小时。”\n\n为什么好：价值明确、收益具体、行动导向强\n\n### ❌ 坏示例\n“Claude 利用前沿 AI 为软件开发提供全面解决方案。”\n\n为什么不好：太空泛、企业黑话太多、没有具体价值\n","zh/03-skills/claude-md/SKILL.md":"---\nname: claude-md\ndescription: 按最佳实践创建或更新 CLAUDE.md 文件，以便为 AI agent 提供最优的项目入门上下文\n---\n\n## 用户输入\n\n```text\n$ARGUMENTS\n```\n\n在继续之前，你**必须**先考虑用户输入（如果不为空）。用户可能会指定：\n- `create` - 从零创建新的 CLAUDE.md\n- `update` - 改进已有的 CLAUDE.md\n- `audit` - 分析并报告当前 CLAUDE.md 的质量\n- 一个具体路径，用于创建或更新（例如 `src/api/CLAUDE.md` 代表目录级说明）\n\n## 核心原则\n\n**LLM 是无状态的**：CLAUDE.md 是每次对话都会加载的主要项目文件（与自动记忆和未限定作用域的 rules 一起加载）。它是让 AI agent 了解代码库的主要入门文档。\n\n### 黄金法则\n\n1. **少即是多**：前沿 LLM 大约能遵循 150-200 条指令。Claude Code 的系统提示词本身已经占了大约 50 条，因此 CLAUDE.md 必须聚焦且简洁。\n\n2. **只放通用信息**：只包含每次会话都适用的内容。任务特定的说明应该放在单独文件里。\n\n3. **不要把 Claude 当成 lint 工具**：风格指南会膨胀上下文并降低指令遵循效果。应改用确定性工具（如 prettier、eslint 等）。\n\n4. **绝不自动生成**：CLAUDE.md 是 AI harness 中杠杆最高的位置。应该经过认真思考后手工编写。\n\n## 执行流程\n\n### 1. 项目分析\n\n首先分析当前项目状态：\n\n1. 检查是否存在已有的 CLAUDE.md 文件：\n   - 根目录：`./CLAUDE.md` 或 `.claude/CLAUDE.md`\n   - 目录级：`**/CLAUDE.md`\n   - 全局用户配置：`~/.claude/CLAUDE.md`\n\n2. 识别项目结构：\n   - 技术栈（语言、框架）\n   - 项目类型（monorepo、单体应用、库）\n   - 开发工具（包管理器、构建系统、测试运行器）\n\n3. 查看已有文档：\n   - README.md\n   - CONTRIBUTING.md\n   - package.json、pyproject.toml、Cargo.toml 等\n\n### 2. 内容策略（WHAT, WHY, HOW）\n\n围绕三个维度组织 CLAUDE.md：\n\n#### WHAT - 技术与结构\n- 技术栈概览\n- 项目组织方式（对 monorepo 尤其重要）\n- 关键目录及其用途\n\n#### WHY - 目的与背景\n- 项目是做什么的\n- 为什么做出这些架构决策\n- 每个主要组件负责什么\n\n#### HOW - 工作流与约定\n- 开发流程（bun vs node、pip vs uv 等）\n- 测试流程和命令\n- 验证与构建方法\n- 关键“坑点”或非显而易见的要求\n\n### 3. 渐进式披露策略\n\n对于较大的项目，建议创建 `agent_docs/` 文件夹：\n\n```text\nagent_docs/\n  |- building_the_project.md\n  |- running_tests.md\n  |- code_conventions.md\n  |- architecture_decisions.md\n```\n\n在 CLAUDE.md 中引用这些文件，并写明：\n```markdown\n关于详细的构建说明，请参考 `agent_docs/building_the_project.md`\n```\n\n**重要**：使用 `file:line` 引用，而不是代码片段，以避免上下文过时。\n\n### 4. 质量约束\n\n创建或更新 CLAUDE.md 时：\n\n1. **目标长度**：少于 200 行\n2. **不要写风格规则**：移除任何 lint/format 相关说明\n3. **不要写任务特定说明**：移到单独文件中\n4. **不要写代码片段**：改用文件引用\n5. **不要重复信息**：不要重复 package.json 或 README 中已有内容\n\n### 5. 必备章节\n\n一个结构良好的 CLAUDE.md 应包含：\n\n```markdown\n# 项目名称\n\n一句简短的项目描述。\n\n## 技术栈\n- 主语言和版本\n- 关键框架/库\n- 数据库/存储（如有）\n\n## 项目结构\n[仅适用于 monorepo 或复杂结构]\n- `apps/` - 应用入口\n- `packages/` - 共享库\n\n## 开发命令\n- 安装：`command`\n- 测试：`command`\n- 构建：`command`\n\n## 关键约定\n[只保留非显而易见、高影响的约定]\n- 约定 1，简要说明\n- 约定 2，简要说明\n\n## 已知问题 / 坑点\n[经常让开发者踩坑的内容]\n- 问题 1\n- 问题 2\n```\n\n### 6. 需要避免的反模式\n\n**不要包含：**\n- 代码风格指南（交给 lint 工具）\n- 如何使用 Claude 的说明\n- 对显而易见模式的冗长解释\n- 复制粘贴的代码示例\n- 泛泛而谈的最佳实践（例如“写干净的代码”）\n- 特定任务的说明\n- 自动生成内容\n- 大量 TODO 列表\n\n### 7. 验证清单\n\n在最终确定前，检查：\n\n- [ ] 少于 200 行\n- [ ] 每一行都适用于所有会话\n- [ ] 没有风格/格式规则\n- [ ] 没有代码片段（使用文件引用）\n- [ ] 命令已经验证可用\n- [ ] 对复杂项目使用了渐进式披露\n- [ ] 已记录关键坑点\n- [ ] 没有与 README.md 重复\n\n## 输出格式\n\n### 对于 `create` 或默认模式：\n\n1. 分析项目\n2. 按上述结构起草 CLAUDE.md\n3. 向用户展示草稿以供审阅\n4. 在获得批准后写入相应位置\n\n### 对于 `update`：\n\n1. 读取现有 CLAUDE.md\n2. 按最佳实践进行审计\n3. 识别：\n   - 需要删除的内容（风格规则、代码片段、任务特定内容）\n   - 需要压缩的内容\n   - 缺失的重要信息\n4. 向用户展示修改建议\n5. 在获得批准后应用修改\n\n### 对于 `audit`：\n\n1. 读取现有 CLAUDE.md\n2. 生成报告，包括：\n   - 当前行数与目标的对比\n   - 可通用于所有会话内容的百分比\n   - 发现的反模式列表\n   - 改进建议\n3. 不要修改文件，只做报告\n\n## AGENTS.md 处理\n\n如果用户请求创建或更新 AGENTS.md：\n\n**从 v2.1.277 起，Claude Code 会直接把 `AGENTS.md` 作为项目指令读取。** 但前提是工作目录以及它上面的每一级目录都没有 `CLAUDE.md`、`.claude/CLAUDE.md` 或 `CLAUDE.local.md`。`~/.claude/CLAUDE.md`、受管理的 CLAUDE.md 和 `.claude/rules/` 不计入这项检查，它们仍会一并加载。该行为由 `/config` 中的 **Project instructions** 控制：`claude-md-or-agents-md`（默认）、`claude-md-and-agents-md`、`claude-md`、`managed-only`。在无法直接读取的环境中 — v2.1.277 之前的版本（在 Bedrock/Vertex/Foundry、LLM 网关或关闭遥测的情况下为 v2.1.281 之前），或升级后的第一个会话 — 退回到在 CLAUDE.md 中用 `@AGENTS.md` 导入，或者把 `CLAUDE.md` 软链接到它。\n\nAGENTS.md 是一个跨工具的项目上下文文件 — 和 CLAUDE.md 属于同一*类*文档，而不是 agent 定义格式。它的存在是为了让多个编码 agent 共用同一套项目约定：\n- 构建、测试和 lint 命令\n- 代码风格与架构约定\n- 仓库结构以及各部分所在位置\n\nSubagents 是单独定义的，放在 `.claude/agents/*.md` 里 — 不在 AGENTS.md 中。\n\n同样适用以下原则：\n- 保持聚焦和简洁\n- 使用渐进式披露\n- 用外部文档引用代替内联内容\n\n## 备注\n\n- 在写入前始终验证命令是否可用\n- 不确定时就不要写，少即是多\n- 系统提醒会告诉 Claude，CLAUDE.md “可能相关，也可能不相关” - 噪音越多，越容易被忽略\n- monorepo 最需要清晰的 WHAT/WHY/HOW 结构\n- 目录级 CLAUDE.md 应该更聚焦\n\n---\n\n**最后更新**: 2026 年 10 月 18 日\n**Claude Code 版本**: 2.1.302\n**来源**:\n- https://code.claude.com/docs/en/memory\n","zh/03-skills/code-review-specialist/SKILL.md":"---\nname: code-review-specialist\ndescription: 提供全面的代码审查能力，覆盖安全、性能和代码质量分析。适用于用户请求代码审查、代码质量评估、Pull Request 审查，或提到安全分析和性能优化时。\n---\n\n# 代码审查 Skill\n\n这个 skill 提供全面的代码审查能力，重点关注：\n\n1. **安全分析**\n   - 身份验证 / 授权问题\n   - 数据泄露风险\n   - 注入漏洞\n   - 密码学弱点\n   - 敏感数据日志记录\n\n2. **性能审查**\n   - 算法效率（Big O 分析）\n   - 内存优化\n   - 数据库查询优化\n   - 缓存机会\n   - 并发问题\n\n3. **代码质量**\n   - SOLID 原则\n   - 设计模式\n   - 命名规范\n   - 文档\n   - 测试覆盖率\n\n4. **可维护性**\n   - 代码可读性\n   - 函数长度（建议少于 50 行）\n   - 圈复杂度\n   - 依赖管理\n   - 类型安全\n\n## 审查模板\n\n对每一段被审查的代码，请提供：\n\n### 摘要\n- 整体质量评分（1-5）\n- 关键发现数量\n- 建议优先关注的区域\n\n### 关键问题（如有）\n- **问题**：清晰描述\n- **位置**：文件和行号\n- **影响**：为什么这很重要\n- **严重性**：Critical / High / Medium\n- **修复**：代码示例\n\n### 按类别列出发现\n\n#### 安全性（如有问题）\n列出安全漏洞及示例\n\n#### 性能（如有问题）\n列出性能问题，并说明复杂度\n\n#### 质量（如有问题）\n列出代码质量问题，并给出重构建议\n\n#### 可维护性（如有问题）\n列出可维护性问题，并给出改进建议\n\n## 版本历史\n\n- v1.0.0 (2024-12-10)：首次发布，包含安全、性能、质量和可维护性分析\n","zh/03-skills/doc-generator/SKILL.md":"---\nname: doc-generator\ndescription: 从源代码生成全面且准确的 API 文档。适用于创建或更新 API 文档、生成 OpenAPI 规范，或在用户提到 API 文档、端点或说明时使用。\n---\n\n# API 文档生成 Skill\n\n## 可生成内容\n\n- OpenAPI / Swagger 规范\n- API 端点文档\n- SDK 使用示例\n- 集成指南\n- 错误码参考\n- 认证指南\n\n## 文档结构\n\n### 每个端点的写法\n\n````markdown\n## GET /api/v1/users/:id\n\n### 描述\n简要说明这个端点做什么\n\n### 参数\n\n| 名称 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| id | string | 是 | 用户 ID |\n\n### 响应\n\n**200 成功**\n```json\n{\n  \"id\": \"usr_123\",\n  \"name\": \"John Doe\",\n  \"email\": \"john@example.com\",\n  \"created_at\": \"2025-01-15T10:30:00Z\"\n}\n```\n\n**404 未找到**\n```json\n{\n  \"error\": \"USER_NOT_FOUND\",\n  \"message\": \"User does not exist\"\n}\n```\n\n### 示例\n\n**cURL**\n```bash\ncurl -X GET \"https://api.example.com/api/v1/users/usr_123\" \\\n  -H \"Authorization: Bearer YOUR_TOKEN\"\n```\n\n**JavaScript**\n```javascript\nconst user = await fetch('/api/v1/users/usr_123', {\n  headers: { 'Authorization': 'Bearer token' }\n}).then(r => r.json());\n```\n\n**Python**\n```python\nresponse = requests.get(\n    'https://api.example.com/api/v1/users/usr_123',\n    headers={'Authorization': 'Bearer token'}\n)\nuser = response.json()\n```\n````\n","zh/03-skills/refactor/SKILL.md":"---\nname: refactor\ndescription: 基于 Martin Fowler 方法论的系统化代码重构 skill。适用于用户请求重构代码、改进代码结构、减少技术债、清理旧代码、消除 code smell 或提升可维护性时。这个 skill 采用分阶段、带研究与计划的安全增量实施方式。\n---\n\n# 代码重构 Skill\n\n这是一个基于 Martin Fowler《Refactoring: Improving the Design of Existing Code》（第 2 版）的系统化代码重构方法。这个 skill 强调安全、渐进的修改，并由测试提供保障。\n\n> “重构是在不改变软件外部行为的前提下，改进其内部结构的过程。” — Martin Fowler\n\n## 核心原则\n\n1. **保持行为不变**：外部行为必须保持一致\n2. **小步前进**：每次只做很小、可测试的改动\n3. **测试驱动**：测试是安全网\n4. **持续进行**：重构是长期过程，不是一次性任务\n5. **协作确认**：每个阶段都需要用户确认\n\n## 工作流程总览\n\n```\n阶段 1：研究与分析\n    ↓\n阶段 2：测试覆盖评估\n    ↓\n阶段 3：识别代码异味\n    ↓\n阶段 4：创建重构计划\n    ↓\n阶段 5：增量实施\n    ↓\n阶段 6：评审与迭代\n```\n\n---\n\n## 阶段 1：研究与分析\n\n### 目标\n- 理解代码库结构和用途\n- 确定重构范围\n- 收集业务需求背景\n\n### 先向用户确认的问题\n开始前先确认：\n\n1. **范围**：哪些文件 / 模块 / 函数需要重构？\n2. **目标**：你想解决什么问题？（可读性、性能、可维护性）\n3. **约束**：有哪些区域不能改？\n4. **时间压力**：这是否阻塞了其他工作？\n5. **测试状态**：是否已有测试？是否通过？\n\n### 行动\n- [ ] 阅读并理解目标代码\n- [ ] 识别依赖和集成点\n- [ ] 记录当前架构\n- [ ] 标记已有技术债迹象（TODO、FIXME）\n\n### 输出\n向用户汇报：\n- 代码结构总结\n- 识别出的问题区域\n- 初步建议\n- **请求继续执行的批准**\n\n---\n\n## 阶段 2：测试覆盖评估\n\n### 为什么测试重要\n> “没有测试的重构，就像没有安全带就开车。” — Martin Fowler\n\n测试是安全重构的**关键前提**。没有测试，很容易引入 bug。\n\n### 评估步骤\n\n1. **检查现有测试**\n   ```bash\n   # 查找测试文件\n   find . -name \"*test*\" -o -name \"*spec*\" | head -20\n   ```\n\n2. **运行现有测试**\n   ```bash\n   # JavaScript / TypeScript\n   npm test\n\n   # Python\n   pytest -v\n\n   # Java\n   mvn test\n   ```\n\n3. **检查覆盖率（如果可用）**\n   ```bash\n   # JavaScript\n   npm run test:coverage\n\n   # Python\n   pytest --cov=.\n   ```\n\n### 决策点：询问用户\n\n**如果测试存在且通过：**\n- 进入阶段 3\n\n**如果测试缺失或不完整：**\n给出选项：\n1. 先写测试（推荐）\n2. 在重构过程中逐步补测试\n3. 不写测试直接继续（有风险，需要用户确认）\n\n**如果测试失败：**\n- 停止。先修复失败测试再重构\n- 问用户：是否先修测试？\n\n### 测试编写建议（如需要）\n\n对每个要重构的函数，测试应覆盖：\n- 正常路径\n- 边界情况（空输入、null、边界值）\n- 错误场景（非法输入、异常）\n\n使用“红-绿-重构”循环：\n1. 写失败测试（红）\n2. 让它通过（绿）\n3. 再重构\n\n---\n\n## 阶段 3：识别代码异味\n\n### 什么是代码异味？\n代码深层问题的表面症状。它们不一定是 bug，但说明代码设计可能有问题。\n\n### 常见异味清单\n\n完整目录见 [references/code-smells.md](references/code-smells.md)。\n\n#### 快速参考\n\n| 异味 | 迹象 | 影响 |\n|-------|------|------|\n| **长函数** | 函数超过 30-50 行 | 难以理解、测试和维护 |\n| **重复代码** | 多处出现相同逻辑 | 修复需要改多处 |\n| **大类** | 类承担了太多职责 | 违反单一职责原则 |\n| **Feature Envy** | 一个方法更多依赖别的类的数据 | 封装性差 |\n| **基础类型沉迷** | 过度使用基础类型而不是对象 | 缺少领域概念 |\n| **长参数列表** | 方法参数超过 4 个 | 调用困难 |\n| **数据泥团** | 一组数据总是一起出现 | 缺少抽象 |\n| **switch 语句** | 复杂的 switch / if-else 链 | 难以扩展 |\n| **臆想泛化** | “以防未来需要”提前设计 | 不必要的复杂度 |\n| **死代码** | 未使用的代码 | 造成困惑和维护负担 |\n\n### 分析步骤\n\n1. **自动分析**（如果有脚本）\n   ```bash\n   python scripts/detect-smells.py <file>\n   ```\n\n2. **人工审查**\n   - 系统地走读代码\n   - 记录每个异味的位置和严重性\n   - 按影响分类（Critical / High / Medium / Low）\n\n3. **优先级排序**\n   优先关注会：\n   - 阻塞当前开发的异味\n   - 导致 bug 或混淆的异味\n   - 影响最常变更代码路径的异味\n\n### 输出：异味报告\n\n向用户呈现：\n- 识别出的异味及位置\n- 每项的严重性评估\n- 建议的优先级顺序\n- **请求用户确认优先级**\n\n---\n\n## 阶段 4：创建重构计划\n\n### 选择重构方式\n\n针对每个异味，从目录中选择合适的重构手法。\n\n完整列表见 [references/refactoring-catalog.md](references/refactoring-catalog.md)。\n\n#### 异味到重构的映射\n\n| 代码异味 | 推荐重构 |\n|----------|----------|\n| 长函数 | Extract Method、Replace Temp with Query |\n| 重复代码 | Extract Method、Pull Up Method、Form Template Method |\n| 大类 | Extract Class、Extract Subclass |\n| Feature Envy | Move Method、Move Field |\n| 基础类型沉迷 | Replace Primitive with Object、Replace Type Code with Class |\n| 长参数列表 | Introduce Parameter Object、Preserve Whole Object |\n| 数据泥团 | Extract Class、Introduce Parameter Object |\n| switch 语句 | Replace Conditional with Polymorphism |\n| 臆想泛化 | Collapse Hierarchy、Inline Class、Remove Dead Code |\n| 死代码 | Remove Dead Code |\n\n### 计划结构\n\n使用 [templates/refactoring-plan.md](templates/refactoring-plan.md) 里的模板。\n\n每项重构都要写明：\n1. **Target**：将修改哪些代码\n2. **Smell**：解决什么问题\n3. **Refactoring**：采用哪种手法\n4. **Steps**：详细微步骤\n5. **Risks**：可能出什么问题\n6. **Rollback**：如何回退\n\n### 分阶段方法\n\n**关键**：重构必须分阶段推进。\n\n**阶段 A：快速收益**（低风险，高价值）\n- 重命名变量以提升清晰度\n- 提取明显重复的代码\n- 删除死代码\n\n**阶段 B：结构改进**（中风险）\n- 从长函数中提取方法\n- 引入参数对象\n- 把方法移动到更合适的类\n\n**阶段 C：架构改动**（高风险）\n- 用多态替代条件分支\n- 提取类\n- 引入设计模式\n\n### 决策点：把计划展示给用户\n\n在开始实施前：\n- 展示完整重构计划\n- 解释每个阶段及其风险\n- 获得每个阶段的明确批准\n- **询问**：“是否继续执行阶段 A？”\n\n---\n\n## 阶段 5：增量实施\n\n### 黄金法则\n> “修改 → 测试 → 通过？→ 提交 → 下一步”\n\n### 实施节奏\n\n对每一步重构：\n\n1. **预检查**\n   - 测试通过（绿色）\n   - 代码能编译\n\n2. **只做一个小改动**\n   - 按目录中的具体操作进行\n   - 保持改动最小化\n\n3. **验证**\n   - 立刻运行测试\n   - 检查编译错误\n\n4. **如果测试通过（绿色）**\n   - 用描述清晰的提交信息提交\n   - 继续下一步\n\n5. **如果测试失败（红色）**\n   - 立刻停止\n   - 撤销改动\n   - 分析原因\n   - 如有疑问，询问用户\n\n### 提交策略\n\n每次提交都应当：\n- **原子性**：只包含一个逻辑改动\n- **可回滚**：容易撤销\n- **描述清楚**：提交信息明确\n\n示例提交信息：\n```\nrefactor: 从 processOrder() 中提取 calculateTotal()\nrefactor: 将 'x' 重命名为 'customerCount' 以提升清晰度\nrefactor: 删除未使用的 validateOldFormat() 方法\n```\n\n### 进度汇报\n\n每个子阶段完成后，向用户汇报：\n- 做了哪些改动\n- 测试是否仍通过\n- 遇到了什么问题\n- **询问**：“继续下一批吗？”\n\n---\n\n## 阶段 6：评审与迭代\n\n### 重构后检查清单\n\n- [ ] 所有测试通过\n- [ ] 没有新的警告 / 错误\n- [ ] 代码编译成功\n- [ ] 行为没有变化（手动验证）\n- [ ] 必要时已更新文档\n- [ ] 提交历史干净\n\n### 指标对比\n\n重构前后运行复杂度分析：\n```bash\npython scripts/analyze-complexity.py <file>\n```\n\n展示改进：\n- 代码行数变化\n- 圈复杂度变化\n- 可维护性指标变化\n\n### 用户评审\n\n向用户展示最终结果：\n- 所有变更摘要\n- 重构前后代码对比\n- 指标改善情况\n- 剩余技术债\n- **询问**：“你对这些改动满意吗？”\n\n### 下一步\n\n和用户讨论：\n- 还要处理哪些异味？\n- 是否安排下一次重构？\n- 是否把类似修改应用到其他地方？\n\n---\n\n## 重要指南\n\n### 何时暂停并询问\n\n遇到以下情况时，务必暂停并和用户确认：\n- 不确定业务逻辑\n- 改动可能影响外部 API\n- 测试覆盖不足\n- 需要做重大的架构决策\n- 风险上升\n- 遇到意外复杂性\n\n### 安全规则\n\n1. **没有测试不要重构**（除非用户明确确认风险）\n2. **不要做大改动**，拆成小步\n3. **每次改动后都不要跳过测试**\n4. **测试失败就不要继续**，先修复或回滚\n5. **不要臆测**，不确定就问\n\n### 不要做什么\n\n- 不要把重构和新功能混在一起\n- 不要在生产事故期间做重构\n- 不要重构你看不懂的代码\n- 不要过度设计，保持简单\n- 不要一次性重构所有内容\n\n---\n\n## 快速上手示例\n\n### 场景：长函数 + 重复逻辑\n\n**重构前：**\n```javascript\nfunction processOrder(order) {\n  // 150 行代码，包含：\n  // - 重复验证逻辑\n  // - 内联计算\n  // - 多种职责混杂\n}\n```\n\n**重构步骤：**\n\n1. **确认测试存在**，覆盖 `processOrder()`\n2. **提取** 验证逻辑为 `validateOrder()`\n3. **测试** - 应该通过\n4. **提取** 计算逻辑为 `calculateOrderTotal()`\n5. **测试** - 应该通过\n6. **提取** 通知逻辑为 `notifyCustomer()`\n7. **测试** - 应该通过\n8. **评审** - `processOrder()` 现在只负责串联 3 个清晰函数\n\n**重构后：**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const total = calculateOrderTotal(order);\n  notifyCustomer(order, total);\n  return { order, total };\n}\n```\n\n---\n\n## 参考资料\n\n- [代码异味目录](references/code-smells.md) - 代码异味完整清单\n- [重构目录](references/refactoring-catalog.md) - 重构手法\n- [重构计划模板](templates/refactoring-plan.md) - 计划模板\n\n## 脚本\n\n- `scripts/analyze-complexity.py` - 分析代码复杂度指标\n- `scripts/detect-smells.py` - 自动检测 code smell\n\n## 版本历史\n\n- v1.0.0 (2025-01-15)：首次发布，包含 Fowler 方法论、分阶段流程和用户确认点\n","zh/03-skills/refactor/references/code-smells.md":"# 代码异味目录\n\n这是基于 Martin Fowler《Refactoring》（第 2 版）的代码异味参考目录。代码异味是更深层问题的表面症状，它们说明代码设计可能出了问题。\n\n> “代码异味通常是系统中更深层问题的表面信号。” — Martin Fowler\n\n---\n\n## 过度膨胀类异味\n\n表示对象或函数已经大到不再好用。\n\n### 长函数\n\n**迹象：**\n- 函数超过 30-50 行\n- 需要滚动才能看完整个函数\n- 嵌套层级很多\n- 需要注释来解释局部逻辑\n\n**为什么不好：**\n- 难理解\n- 难单独测试\n- 改动容易波及其他逻辑\n- 重复逻辑容易藏在里面\n\n**可用重构：**\n- Extract Method\n- Replace Temp with Query\n- Introduce Parameter Object\n- Replace Method with Method Object\n- Decompose Conditional\n\n**示例（重构前）：**\n```javascript\nfunction processOrder(order) {\n  // Validate order (20 lines)\n  if (!order.items) throw new Error('No items');\n  if (order.items.length === 0) throw new Error('Empty order');\n  // ... more validation\n\n  // Calculate totals (30 lines)\n  let subtotal = 0;\n  for (const item of order.items) {\n    subtotal += item.price * item.quantity;\n  }\n  // ... tax, shipping, discounts\n\n  // Send notifications (20 lines)\n  // ... email logic\n}\n```\n\n**示例（重构后）：**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const totals = calculateOrderTotals(order);\n  sendOrderNotifications(order, totals);\n  return { order, totals };\n}\n```\n\n---\n\n### 大类\n\n**迹象：**\n- 实例变量很多（>7-10）\n- 方法很多（>15-20）\n- 类名含糊（Manager、Handler、Processor）\n- 方法没有用到全部字段\n\n**为什么不好：**\n- 违反单一职责原则\n- 难测试\n- 改动会波及无关功能\n- 难以复用局部能力\n\n**可用重构：**\n- Extract Class\n- Extract Subclass\n- Extract Interface\n\n**检测参考：**\n```text\n代码行数 > 300\n方法数量 > 15\n字段数量 > 10\n```\n\n---\n\n### 基础类型沉迷\n\n**迹象：**\n- 用基础类型表达领域概念（用 string 表示邮箱、用 int 表示金额）\n- 使用基础类型数组，而不是对象\n- 用字符串常量表示类型码\n- 大量 magic number / magic string\n\n**为什么不好：**\n- 类型层面没有验证\n- 逻辑散落在整个代码库里\n- 容易传错值\n- 缺少领域对象\n\n**可用重构：**\n- Replace Primitive with Object\n- Replace Type Code with Class\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**示例（重构前）：**\n```javascript\nconst user = {\n  email: 'john@example.com',     // 只是字符串\n  phone: '1234567890',           // 只是字符串\n  status: 'active',              // 魔法字符串\n  balance: 10050                 // 以分为单位的整数\n};\n```\n\n**示例（重构后）：**\n```javascript\nconst user = {\n  email: new Email('john@example.com'),\n  phone: new PhoneNumber('1234567890'),\n  status: UserStatus.ACTIVE,\n  balance: Money.cents(10050)\n};\n```\n\n---\n\n### 长参数列表\n\n**迹象：**\n- 方法参数超过 4 个\n- 一些参数总是一起出现\n- 布尔参数改变方法行为\n- 经常传 null / undefined\n\n**为什么不好：**\n- 难正确调用\n- 参数顺序容易搞混\n- 暗示方法做了太多事\n- 难以增加新参数\n\n**可用重构：**\n- Introduce Parameter Object\n- Preserve Whole Object\n- Replace Parameter with Method Call\n- Remove Flag Argument\n\n**示例（重构前）：**\n```javascript\nfunction createUser(firstName, lastName, email, phone,\n                    street, city, state, zip,\n                    isAdmin, isActive, createdBy) {\n  // ...\n}\n```\n\n**示例（重构后）：**\n```javascript\nfunction createUser(personalInfo, address, options) {\n  // personalInfo: { firstName, lastName, email, phone }\n  // address: { street, city, state, zip }\n  // options: { isAdmin, isActive, createdBy }\n}\n```\n\n---\n\n### 数据泥团\n\n**迹象：**\n- 同样的 3 个以上字段反复一起出现\n- 参数总是成对或成组传递\n- 类中的字段子集总是一起使用\n\n**为什么不好：**\n- 逻辑重复\n- 缺少抽象\n- 难扩展\n- 暗示隐藏的类应该存在\n\n**可用重构：**\n- Extract Class\n- Introduce Parameter Object\n- Preserve Whole Object\n\n**示例：**\n```javascript\n// 数据泥团：坐标 (x, y, z)\nfunction movePoint(x, y, z, dx, dy, dz) { }\nfunction scalePoint(x, y, z, factor) { }\nfunction distanceBetween(x1, y1, z1, x2, y2, z2) { }\n\n// 提取 Point3D 类\nclass Point3D {\n  constructor(x, y, z) { }\n  move(delta) { }\n  scale(factor) { }\n  distanceTo(other) { }\n}\n```\n\n---\n\n## 面向对象滥用类异味\n\n表示 OOP 原则没有被正确使用。\n\n### switch 语句\n\n**迹象：**\n- 长 switch/case 或 if/else 链\n- 多处出现相同 switch\n- 按类型码分支\n- 新增 case 时需要改很多地方\n\n**为什么不好：**\n- 违反开放 / 封闭原则\n- 改动会扩散到所有 switch 位置\n- 难扩展\n- 往往说明缺少多态\n\n**可用重构：**\n- Replace Conditional with Polymorphism\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**示例（重构前）：**\n```javascript\nfunction calculatePay(employee) {\n  switch (employee.type) {\n    case 'hourly':\n      return employee.hours * employee.rate;\n    case 'salaried':\n      return employee.salary / 12;\n    case 'commissioned':\n      return employee.sales * employee.commission;\n  }\n}\n```\n\n**示例（重构后）：**\n```javascript\nclass HourlyEmployee {\n  calculatePay() {\n    return this.hours * this.rate;\n  }\n}\n\nclass SalariedEmployee {\n  calculatePay() {\n    return this.salary / 12;\n  }\n}\n```\n\n---\n\n### 临时字段\n\n**迹象：**\n- 实例变量只在部分方法中使用\n- 字段只在某些条件下设置\n- 某些情况初始化过程很复杂\n\n**为什么不好：**\n- 容易混淆：字段存在但可能为 null\n- 对象状态难理解\n- 说明条件逻辑被隐藏了\n\n**可用重构：**\n- Extract Class\n- Introduce Null Object\n- Replace Temp Field with Local\n\n---\n\n### 拒绝遗赠\n\n**迹象：**\n- 子类没有用到继承来的方法 / 数据\n- 子类重写方法只是为了不做事\n- 继承被当成代码复用，而不是真正的 IS-A\n\n**为什么不好：**\n- 抽象不对\n- 违反里氏替换原则\n- 继承层次误导人\n\n**可用重构：**\n- Push Down Method / Field\n- Replace Subclass with Delegate\n- Replace Inheritance with Delegation\n\n---\n\n### 不同接口的相似类\n\n**迹象：**\n- 两个类做的事情差不多\n- 同一个概念却用了不同方法名\n- 理论上可以互换使用\n\n**为什么不好：**\n- 重复实现\n- 没有公共接口\n- 难切换\n\n**可用重构：**\n- Rename Method\n- Move Method\n- Extract Superclass\n- Extract Interface\n\n---\n\n## 变更阻碍类异味\n\n这类异味会让改动变得困难，一次改动需要波及很多地方。\n\n### 发散式变化\n\n**迹象：**\n- 一个类因为很多不同原因而被修改\n- 不同区域的变更都会触发同一个类的编辑\n- 类变成了“上帝类”\n\n**为什么不好：**\n- 违反单一职责原则\n- 变更频率高\n- 容易产生合并冲突\n\n**可用重构：**\n- Extract Class\n- Extract Superclass\n- Extract Subclass\n\n**示例：**\n一个 `User` 类同时因为这些原因变化：\n- 身份验证变化\n- 个人资料变化\n- 计费变化\n- 通知变化\n\n→ 可以拆成：`AuthService`、`ProfileService`、`BillingService`、`NotificationService`\n\n---\n\n### 散弹式修改\n\n**迹象：**\n- 一个改动需要编辑很多类\n- 一个小功能要触碰 10+ 个文件\n- 改动分散，难以一次找全\n\n**为什么不好：**\n- 很容易漏改\n- 耦合高\n- 容易出错\n\n**可用重构：**\n- Move Method\n- Move Field\n- Inline Class\n\n**检测参考：**\n如果新增一个字段需要改 5 个以上文件，就要警惕。\n\n---\n\n### 平行继承体系\n\n**迹象：**\n- 在一个继承体系中创建子类，另一个体系也得跟着创建\n- 类前缀相似（如 `DatabaseOrder`、`DatabaseProduct`）\n\n**为什么不好：**\n- 维护成本翻倍\n- 两个层次之间耦合\n- 容易漏掉一边\n\n**可用重构：**\n- Move Method\n- Move Field\n- 消除其中一个层次\n\n---\n\n## 可舍弃类异味\n\n表示有些东西已经不必要了，应该移除。\n\n### 注释过多\n\n**迹象：**\n- 注释在解释代码“做了什么”\n- 注释掉的代码\n- 长期存在的 TODO / FIXME\n- 注释里带道歉语气\n\n**为什么不好：**\n- 注释会过时\n- 代码本身应该能自解释\n- 死代码会造成混乱\n\n**可用重构：**\n- Extract Method（让方法名解释意图）\n- Rename（通过命名提升清晰度）\n- 删除注释掉的代码\n- Introduce Assertion\n\n**好与坏的注释：**\n```javascript\n// BAD: 解释做了什么\n// 遍历用户并检查是否活跃\nfor (const user of users) {\n  if (user.status === 'active') { }\n}\n\n// GOOD: 解释为什么\n// 只保留活跃用户，未活跃用户由清理任务处理\nconst activeUsers = users.filter(u => u.isActive);\n```\n\n---\n\n### 重复代码\n\n**迹象：**\n- 多处出现相同代码\n- 只有少量差异的相似代码\n- 复制粘贴模式\n\n**为什么不好：**\n- 修复要改多处\n- 容易不一致\n- 代码库臃肿\n\n**可用重构：**\n- Extract Method\n- Extract Class\n- Pull Up Method（在继承层次中）\n- Form Template Method\n\n**检测规则：**\n任何重复 3 次以上的代码都应该考虑提取。\n\n---\n\n### 惰性类\n\n**迹象：**\n- 类做的事情不足以支撑它的存在\n- 只是一个没有增值的包装器\n- 过度设计的产物\n\n**为什么不好：**\n- 增加维护开销\n- 多了一层没必要的间接\n- 有复杂度但没收益\n\n**可用重构：**\n- Inline Class\n- Collapse Hierarchy\n\n---\n\n### 死代码\n\n**迹象：**\n- 无法到达的代码\n- 未使用的变量 / 方法 / 类\n- 注释掉的代码\n- 位于不可能条件分支后的代码\n\n**为什么不好：**\n- 造成困惑\n- 增加维护负担\n- 降低理解速度\n\n**可用重构：**\n- Remove Dead Code\n- Safe Delete\n\n**检测：**\n```bash\n# 查找未使用的导出\n# 查找未引用的函数\n# IDE 的“unused”警告\n```\n\n---\n\n### 臆想泛化\n\n**迹象：**\n- 只有一个子类的抽象类\n- 为“未来可能需要”而加的未使用参数\n- 只是转发的函数\n- 为一个用例设计的“框架”\n\n**为什么不好：**\n- 复杂度没有收益\n- 违背 YAGNI\n- 更难理解\n\n**可用重构：**\n- Collapse Hierarchy\n- Inline Class\n- Remove Parameter\n- Rename Method\n\n---\n\n## 耦合类异味\n\n表示类之间耦合过强。\n\n### Feature Envy\n\n**迹象：**\n- 一个方法使用别的类的数据比自己更多\n- 对另一个对象调用很多 getter\n- 数据和行为分离\n\n**为什么不好：**\n- 行为放错地方了\n- 封装性差\n- 难维护\n\n**可用重构：**\n- Move Method\n- Move Field\n- Extract Method（然后移动）\n\n**示例（重构前）：**\n```javascript\nclass Order {\n  getDiscountedPrice(customer) {\n    // 这里大量使用 customer 数据\n    if (customer.loyaltyYears > 5) {\n      return this.price * customer.discountRate;\n    }\n    return this.price;\n  }\n}\n```\n\n**示例（重构后）：**\n```javascript\nclass Customer {\n  getDiscountedPriceFor(price) {\n    if (this.loyaltyYears > 5) {\n      return price * this.discountRate;\n    }\n    return price;\n  }\n}\n```\n\n---\n\n### 不恰当的亲密\n\n**迹象：**\n- 类之间互相访问私有细节\n- 双向引用很多\n- 子类知道父类太多细节\n\n**为什么不好：**\n- 耦合高\n- 改一边会连带另一边\n- 难单独修改\n\n**可用重构：**\n- Move Method\n- Move Field\n- Change Bidirectional to Unidirectional\n- Extract Class\n- Hide Delegate\n\n---\n\n### 消息链\n\n**迹象：**\n- 方法调用链很长：`a.getB().getC().getD().getValue()`\n- 客户端依赖导航结构\n- “火车残骸”式代码\n\n**为什么不好：**\n- 很脆弱，任何一层变动都会坏\n- 违反迪米特法则\n- 绑定到对象结构\n\n**可用重构：**\n- Hide Delegate\n- Extract Method\n- Move Method\n\n**示例：**\n```javascript\n// 差：消息链\nconst managerName = employee.getDepartment().getManager().getName();\n\n// 更好：隐藏委派\nconst managerName = employee.getManagerName();\n```\n\n---\n\n### 中间人\n\n**迹象：**\n- 类只是把调用转发给另一个类\n- 一半以上的方法都是委派\n- 没有额外价值\n\n**为什么不好：**\n- 多了一层没必要的间接\n- 维护成本更高\n- 架构令人困惑\n\n**可用重构：**\n- Remove Middle Man\n- Inline Method\n\n---\n\n## 严重性指南\n\n| 严重性 | 说明 | 处理方式 |\n|--------|------|---------|\n| **Critical** | 阻塞开发，导致 bug | 立刻修复 |\n| **High** | 明显增加维护负担 | 本迭代修复 |\n| **Medium** | 有问题但还能接受 | 近期计划修复 |\n| **Low** | 小问题 | 视情况顺手修 |\n\n---\n\n## 快速检测清单\n\n扫描代码时使用这个清单：\n\n- [ ] 有没有超过 30 行的函数？\n- [ ] 有没有超过 300 行的类？\n- [ ] 有没有参数超过 4 个的函数？\n- [ ] 有没有重复代码块？\n- [ ] 有没有按类型码分支的 switch/case？\n- [ ] 有没有未使用的代码？\n- [ ] 有没有大量使用其他类数据的方法？\n- [ ] 有没有很长的方法调用链？\n- [ ] 有没有解释“是什么”而不是“为什么”的注释？\n- [ ] 有没有应该封装成对象的基础类型？\n\n---\n\n## 延伸阅读\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Kerievsky, J. (2004). *Refactoring to Patterns*\n- Feathers, M. (2004). *Working Effectively with Legacy Code*\n","zh/03-skills/refactor/references/refactoring-catalog.md":"# 重构目录\n\n这是 Martin Fowler《Refactoring》（第 2 版）中的一份精选重构目录。每个重构都包含动机、操作步骤和示例。\n\n> “重构由它的操作步骤来定义，也就是你执行这个变化时遵循的精确过程。” — Martin Fowler\n\n---\n\n## 如何使用这个目录\n\n1. **识别异味**：先用代码异味目录定位问题\n2. **找到对应重构**：在这里查找匹配的手法\n3. **按步骤执行**：一步一步来\n4. **每步都测试**：确保行为不变\n\n**黄金法则**：如果某一步超过 10 分钟，就把它拆得更小。\n\n---\n\n## 最常见的重构\n\n### Extract Method\n\n**何时使用**：长函数、重复代码、需要为概念命名\n\n**动机**：把一段代码抽成一个名字能说明意图的方法。\n\n**步骤**：\n1. 创建一个新方法，名字应描述“做什么”而不是“怎么做”\n2. 把代码片段复制到新方法里\n3. 检查片段里用了哪些局部变量\n4. 把局部变量作为参数传入，或在方法内声明\n5. 正确处理返回值\n6. 用新方法调用替换原始片段\n7. 测试\n\n**前：**\n```javascript\nfunction printOwing(invoice) {\n  let outstanding = 0;\n\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n\n  // Calculate outstanding\n  for (const order of invoice.orders) {\n    outstanding += order.amount;\n  }\n\n  // Print details\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n**后：**\n```javascript\nfunction printOwing(invoice) {\n  printBanner();\n  const outstanding = calculateOutstanding(invoice);\n  printDetails(invoice, outstanding);\n}\n\nfunction printBanner() {\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n}\n\nfunction calculateOutstanding(invoice) {\n  return invoice.orders.reduce((sum, order) => sum + order.amount, 0);\n}\n\nfunction printDetails(invoice, outstanding) {\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n---\n\n### Inline Method\n\n**何时使用**：方法体和名字一样清楚，或者只是多余转发\n\n**动机**：当方法没有额外价值时，去掉不必要的间接层。\n\n**步骤**：\n1. 确认这个方法不是多态方法\n2. 找到所有调用点\n3. 用方法体替换每个调用\n4. 每替换一次就测试一次\n5. 删除方法定义\n\n**前：**\n```javascript\nfunction getRating(driver) {\n  return moreThanFiveLateDeliveries(driver) ? 2 : 1;\n}\n\nfunction moreThanFiveLateDeliveries(driver) {\n  return driver.numberOfLateDeliveries > 5;\n}\n```\n\n**后：**\n```javascript\nfunction getRating(driver) {\n  return driver.numberOfLateDeliveries > 5 ? 2 : 1;\n}\n```\n\n---\n\n### Extract Variable\n\n**何时使用**：复杂表达式难以理解\n\n**动机**：给复杂表达式的一部分起名字。\n\n**步骤**：\n1. 确保表达式没有副作用\n2. 声明一个不可变变量\n3. 将表达式结果赋给变量\n4. 用变量替换原表达式\n5. 测试\n\n**前：**\n```javascript\nreturn order.quantity * order.itemPrice -\n  Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +\n  Math.min(order.quantity * order.itemPrice * 0.1, 100);\n```\n\n**后：**\n```javascript\nconst basePrice = order.quantity * order.itemPrice;\nconst quantityDiscount = Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;\nconst shipping = Math.min(basePrice * 0.1, 100);\nreturn basePrice - quantityDiscount + shipping;\n```\n\n---\n\n### Inline Variable\n\n**何时使用**：变量名没有比表达式更清楚\n\n**动机**：移除没必要的间接层。\n\n**步骤**：\n1. 检查右侧表达式没有副作用\n2. 如果变量不是不可变的，先改成不可变并测试\n3. 找到第一次引用并替换成表达式\n4. 测试\n5. 对所有引用重复\n6. 删除变量声明和赋值\n7. 测试\n\n---\n\n### Rename Variable\n\n**何时使用**：名字没有清楚表达用途\n\n**动机**：好名字是清晰代码的基础。\n\n**步骤**：\n1. 如果变量使用范围很广，先考虑封装\n2. 找到所有引用\n3. 逐个修改引用\n4. 测试\n\n**提示**：\n- 使用能体现意图的名字\n- 避免缩写\n- 使用领域术语\n\n```javascript\n// Bad\nconst d = 30;\nconst x = users.filter(u => u.a);\n\n// Good\nconst daysSinceLastLogin = 30;\nconst activeUsers = users.filter(user => user.isActive);\n```\n\n---\n\n### Change Function Declaration\n\n**何时使用**：函数名不能清楚说明用途，参数也需要变化\n\n**动机**：好函数名能让代码自解释。\n\n**步骤（简单情况）**：\n1. 删除不需要的参数\n2. 修改函数名\n3. 添加需要的参数\n4. 测试\n\n**步骤（迁移式，适用于复杂改动）**：\n1. 如果要删除参数，确保它没有被使用\n2. 创建一个新函数，声明符合新设计\n3. 让旧函数调用新函数\n4. 测试\n5. 让调用方逐步改用新函数\n6. 每改一个调用点就测试\n7. 删除旧函数\n\n**前：**\n```javascript\nfunction circum(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n**后：**\n```javascript\nfunction circumference(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n---\n\n### Encapsulate Variable\n\n**何时使用**：多个地方直接访问某个数据\n\n**动机**：为数据访问提供明确入口。\n\n**步骤**：\n1. 创建 getter 和 setter\n2. 找到所有引用\n3. 用 getter 替换读取\n4. 用 setter 替换写入\n5. 每次改动后测试\n6. 降低变量可见性\n\n**前：**\n```javascript\nlet defaultOwner = { firstName: \"Martin\", lastName: \"Fowler\" };\n\n// Used in many places\nspaceship.owner = defaultOwner;\n```\n\n**后：**\n```javascript\nlet defaultOwnerData = { firstName: \"Martin\", lastName: \"Fowler\" };\n\nfunction defaultOwner() { return defaultOwnerData; }\nfunction setDefaultOwner(arg) { defaultOwnerData = arg; }\n\nspaceship.owner = defaultOwner();\n```\n\n---\n\n### Introduce Parameter Object\n\n**何时使用**：一组参数经常一起出现\n\n**动机**：把自然属于一起的数据打包起来。\n\n**步骤**：\n1. 为这组参数创建一个新类 / 结构\n2. 测试\n3. 用 Change Function Declaration 引入新对象\n4. 测试\n5. 逐个移除参数，改用对象字段\n6. 每次移除后测试\n\n**前：**\n```javascript\nfunction amountInvoiced(startDate, endDate) { ... }\nfunction amountReceived(startDate, endDate) { ... }\nfunction amountOverdue(startDate, endDate) { ... }\n```\n\n**后：**\n```javascript\nclass DateRange {\n  constructor(start, end) {\n    this.start = start;\n    this.end = end;\n  }\n}\n\nfunction amountInvoiced(dateRange) { ... }\nfunction amountReceived(dateRange) { ... }\nfunction amountOverdue(dateRange) { ... }\n```\n\n---\n\n### Combine Functions into Class\n\n**何时使用**：多个函数操作同一份数据\n\n**动机**：把函数和它操作的数据放到一起。\n\n**步骤**：\n1. 对公共数据先做 Encapsulate Record\n2. 把每个函数移动到类里\n3. 每移动一次就测试\n4. 用类字段替代数据参数\n\n**前：**\n```javascript\nfunction base(reading) { ... }\nfunction taxableCharge(reading) { ... }\nfunction calculateBaseCharge(reading) { ... }\n```\n\n**后：**\n```javascript\nclass Reading {\n  constructor(data) { this._data = data; }\n\n  get base() { ... }\n  get taxableCharge() { ... }\n  get calculateBaseCharge() { ... }\n}\n```\n\n---\n\n### Split Phase\n\n**何时使用**：代码在处理两件不同的事\n\n**动机**：把代码拆成边界清晰的两个阶段。\n\n**步骤**：\n1. 为第二阶段创建新函数\n2. 测试\n3. 在两个阶段之间引入中间数据结构\n4. 测试\n5. 把第一阶段提取成独立函数\n6. 测试\n\n**前：**\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  const shippingPerCase = (basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = quantity * shippingPerCase;\n  return basePrice - discount + shippingCost;\n}\n```\n\n**后：**\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const priceData = calculatePricingData(product, quantity);\n  return applyShipping(priceData, shippingMethod);\n}\n\nfunction calculatePricingData(product, quantity) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  return { basePrice, quantity, discount };\n}\n\nfunction applyShipping(priceData, shippingMethod) {\n  const shippingPerCase = (priceData.basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = priceData.quantity * shippingPerCase;\n  return priceData.basePrice - priceData.discount + shippingCost;\n}\n```\n\n---\n\n## 移动特性\n\n### Move Method\n\n**何时使用**：方法更依赖另一个类的数据而不是自己类的数据\n\n**动机**：把函数放到它最依赖的数据所在的类里。\n\n**步骤**：\n1. 检查方法使用到的所有程序元素\n2. 确认方法不是多态的\n3. 把方法复制到目标类\n4. 调整上下文\n5. 让原方法委托给目标方法\n6. 测试\n7. 视情况删除原方法\n\n---\n\n### Move Field\n\n**何时使用**：字段更多被另一个类使用\n\n**动机**：让数据和使用它的函数靠在一起。\n\n**步骤**：\n1. 如果还没有，先封装字段\n2. 测试\n3. 在目标类中创建字段\n4. 把引用改成使用目标字段\n5. 测试\n6. 删除原字段\n\n---\n\n### Move Statements into Function\n\n**何时使用**：相同代码总是跟着函数调用一起出现\n\n**动机**：把重复语句移入函数，去掉重复。\n\n**步骤**：\n1. 如果还没有，先把重复代码提取成函数\n2. 把语句移入函数\n3. 测试\n4. 如果调用方不再需要独立语句，就删除它们\n\n---\n\n### Move Statements to Callers\n\n**何时使用**：不同调用方需要不同的行为\n\n**动机**：当行为需要差异化时，把它从函数里移出去。\n\n**步骤**：\n1. 先对要移动的代码做 Extract Method\n2. 再对原函数做 Inline Method\n3. 删除被内联后的调用\n4. 把提取出的代码移到各个调用方\n5. 测试\n\n---\n\n## 数据组织\n\n### Replace Primitive with Object\n\n**何时使用**：数据项需要的不只是简单值\n\n**动机**：把数据和行为封装在一起。\n\n**步骤**：\n1. 先做 Encapsulate Variable\n2. 创建一个简单值对象\n3. 修改 setter，让它创建新实例\n4. 修改 getter，让它返回值\n5. 测试\n6. 给新类增加更丰富的行为\n\n**前：**\n```javascript\nclass Order {\n  constructor(data) {\n    this.priority = data.priority; // string: \"high\", \"rush\", etc.\n  }\n}\n\n// Usage\nif (order.priority === \"high\" || order.priority === \"rush\") { ... }\n```\n\n**后：**\n```javascript\nclass Priority {\n  constructor(value) {\n    if (!Priority.legalValues().includes(value))\n      throw new Error(`Invalid priority: ${value}`);\n    this._value = value;\n  }\n\n  static legalValues() { return ['low', 'normal', 'high', 'rush']; }\n  get value() { return this._value; }\n\n  higherThan(other) {\n    return Priority.legalValues().indexOf(this._value) >\n           Priority.legalValues().indexOf(other._value);\n  }\n}\n\n// Usage\nif (order.priority.higherThan(new Priority(\"normal\"))) { ... }\n```\n\n---\n\n### Replace Temp with Query\n\n**何时使用**：临时变量保存的是一个表达式结果\n\n**动机**：把表达式提取成函数，让代码更清晰。\n\n**步骤**：\n1. 确保变量只被赋值一次\n2. 把赋值右侧提取成一个方法\n3. 用方法调用替换临时变量引用\n4. 测试\n5. 删除临时变量声明和赋值\n\n**前：**\n```javascript\nconst basePrice = this._quantity * this._itemPrice;\nif (basePrice > 1000) {\n  return basePrice * 0.95;\n} else {\n  return basePrice * 0.98;\n}\n```\n\n**后：**\n```javascript\nget basePrice() {\n  return this._quantity * this._itemPrice;\n}\n\n// In the method\nif (this.basePrice > 1000) {\n  return this.basePrice * 0.95;\n} else {\n  return this.basePrice * 0.98;\n}\n```\n\n---\n\n## 简化条件逻辑\n\n### Decompose Conditional\n\n**何时使用**：复杂条件语句\n\n**动机**：把条件和分支动作分别提取出来，让意图更清楚。\n\n**步骤**：\n1. 对条件做 Extract Method\n2. 对 then 分支做 Extract Method\n3. 对 else 分支也做 Extract Method（如果有）\n\n**前：**\n```javascript\nif (!aDate.isBefore(plan.summerStart) && !aDate.isAfter(plan.summerEnd)) {\n  charge = quantity * plan.summerRate;\n} else {\n  charge = quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n**后：**\n```javascript\nif (isSummer(aDate, plan)) {\n  charge = summerCharge(quantity, plan);\n} else {\n  charge = regularCharge(quantity, plan);\n}\n\nfunction isSummer(date, plan) {\n  return !date.isBefore(plan.summerStart) && !date.isAfter(plan.summerEnd);\n}\n\nfunction summerCharge(quantity, plan) {\n  return quantity * plan.summerRate;\n}\n\nfunction regularCharge(quantity, plan) {\n  return quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n---\n\n### Consolidate Conditional Expression\n\n**何时使用**：多个条件最后都返回同一个结果\n\n**动机**：让人一眼看出这些条件其实是一道检查。\n\n**步骤**：\n1. 确认条件没有副作用\n2. 用 and / or 合并条件\n3. 视情况对合并后的条件做 Extract Method\n\n**前：**\n```javascript\nif (employee.seniority < 2) return 0;\nif (employee.monthsDisabled > 12) return 0;\nif (employee.isPartTime) return 0;\n```\n\n**后：**\n```javascript\nif (isNotEligibleForDisability(employee)) return 0;\n\nfunction isNotEligibleForDisability(employee) {\n  return employee.seniority < 2 ||\n         employee.monthsDisabled > 12 ||\n         employee.isPartTime;\n}\n```\n\n---\n\n### Replace Nested Conditional with Guard Clauses\n\n**何时使用**：深层嵌套条件让流程难以追踪\n\n**动机**：用 guard clause 提前返回，让正常流程更清楚。\n\n**步骤**：\n1. 找出特殊情况\n2. 用提前返回的 guard clause 替换它们\n3. 每改一步就测试\n\n**前：**\n```javascript\nfunction payAmount(employee) {\n  let result;\n  if (employee.isSeparated) {\n    result = { amount: 0, reasonCode: \"SEP\" };\n  } else {\n    if (employee.isRetired) {\n      result = { amount: 0, reasonCode: \"RET\" };\n    } else {\n      result = calculateNormalPay(employee);\n    }\n  }\n  return result;\n}\n```\n\n**后：**\n```javascript\nfunction payAmount(employee) {\n  if (employee.isSeparated) return { amount: 0, reasonCode: \"SEP\" };\n  if (employee.isRetired) return { amount: 0, reasonCode: \"RET\" };\n  return calculateNormalPay(employee);\n}\n```\n\n---\n\n### Replace Conditional with Polymorphism\n\n**何时使用**：按类型分支的 switch / 条件逻辑\n\n**动机**：让对象自己处理自己的行为。\n\n**步骤**：\n1. 创建类层次（如果还没有）\n2. 用 Factory Function 创建对象\n3. 把条件逻辑移到超类方法里\n4. 给每种情况创建子类方法\n5. 删除原条件\n\n**前：**\n```javascript\nfunction plumages(birds) {\n  return birds.map(b => plumage(b));\n}\n\nfunction plumage(bird) {\n  switch (bird.type) {\n    case 'EuropeanSwallow':\n      return \"average\";\n    case 'AfricanSwallow':\n      return (bird.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n    case 'NorwegianBlueParrot':\n      return (bird.voltage > 100) ? \"scorched\" : \"beautiful\";\n    default:\n      return \"unknown\";\n  }\n}\n```\n\n**后：**\n```javascript\nclass Bird {\n  get plumage() { return \"unknown\"; }\n}\n\nclass EuropeanSwallow extends Bird {\n  get plumage() { return \"average\"; }\n}\n\nclass AfricanSwallow extends Bird {\n  get plumage() {\n    return (this.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n  }\n}\n\nclass NorwegianBlueParrot extends Bird {\n  get plumage() {\n    return (this.voltage > 100) ? \"scorched\" : \"beautiful\";\n  }\n}\n\nfunction createBird(data) {\n  switch (data.type) {\n    case 'EuropeanSwallow': return new EuropeanSwallow(data);\n    case 'AfricanSwallow': return new AfricanSwallow(data);\n    case 'NorwegianBlueParrot': return new NorwegianBlueParrot(data);\n    default: return new Bird(data);\n  }\n}\n```\n\n---\n\n### Introduce Special Case (Null Object)\n\n**何时使用**：重复出现 null 检查\n\n**动机**：返回一个特殊对象来处理特殊情况。\n\n**步骤**：\n1. 创建一个具备预期接口的特殊情况类\n2. 增加 isSpecialCase 检查\n3. 引入工厂方法\n4. 用特殊对象替换 null 检查\n5. 测试\n\n**前：**\n```javascript\nconst customer = site.customer;\n// ... many places checking\nif (customer === \"unknown\") {\n  customerName = \"occupant\";\n} else {\n  customerName = customer.name;\n}\n```\n\n**后：**\n```javascript\nclass UnknownCustomer {\n  get name() { return \"occupant\"; }\n  get billingPlan() { return registry.defaultPlan; }\n}\n\n// Factory method\nfunction customer(site) {\n  return site.customer === \"unknown\"\n    ? new UnknownCustomer()\n    : site.customer;\n}\n\n// Usage - no null checks needed\nconst customerName = customer.name;\n```\n\n---\n\n## 重构 API\n\n### Separate Query from Modifier\n\n**何时使用**：函数既返回值又有副作用\n\n**动机**：明确哪些操作会产生副作用。\n\n**步骤**：\n1. 创建新的查询函数\n2. 复制原函数的返回逻辑\n3. 修改原函数，让它只负责副作用\n4. 替换依赖返回值的调用点\n5. 测试\n\n**前：**\n```javascript\nfunction alertForMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") {\n      setOffAlarms();\n      return \"Don\";\n    }\n    if (p === \"John\") {\n      setOffAlarms();\n      return \"John\";\n    }\n  }\n  return \"\";\n}\n```\n\n**后：**\n```javascript\nfunction findMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") return \"Don\";\n    if (p === \"John\") return \"John\";\n  }\n  return \"\";\n}\n\nfunction alertForMiscreant(people) {\n  if (findMiscreant(people) !== \"\") setOffAlarms();\n}\n```\n\n---\n\n### Parameterize Function\n\n**何时使用**：有多个做类似事情但数值不同的函数\n\n**动机**：通过参数化减少重复。\n\n**步骤**：\n1. 选择一个函数\n2. 为变化的字面值增加参数\n3. 修改函数体使用该参数\n4. 测试\n5. 让调用方改用参数化版本\n6. 删除不再使用的旧函数\n\n**前：**\n```javascript\nfunction tenPercentRaise(person) {\n  person.salary = person.salary * 1.10;\n}\n\nfunction fivePercentRaise(person) {\n  person.salary = person.salary * 1.05;\n}\n```\n\n**后：**\n```javascript\nfunction raise(person, factor) {\n  person.salary = person.salary * (1 + factor);\n}\n\n// Usage\nraise(person, 0.10);\nraise(person, 0.05);\n```\n\n---\n\n### Remove Flag Argument\n\n**何时使用**：布尔参数改变函数行为\n\n**动机**：通过拆分成明确函数，让行为更清楚。\n\n**步骤**：\n1. 针对不同旗标值创建显式函数\n2. 替换每个调用点\n3. 每次改动后测试\n4. 删除原函数\n\n**前：**\n```javascript\nfunction bookConcert(customer, isPremium) {\n  if (isPremium) {\n    // premium booking logic\n  } else {\n    // regular booking logic\n  }\n}\n\nbookConcert(customer, true);\nbookConcert(customer, false);\n```\n\n**后：**\n```javascript\nfunction bookPremiumConcert(customer) {\n  // premium booking logic\n}\n\nfunction bookRegularConcert(customer) {\n  // regular booking logic\n}\n\nbookPremiumConcert(customer);\nbookRegularConcert(customer);\n```\n\n---\n\n## 继承相关\n\n### Pull Up Method\n\n**何时使用**：多个子类里有相同方法\n\n**动机**：去掉类层次中的重复。\n\n**步骤**：\n1. 检查方法是否完全相同\n2. 确认签名一致\n3. 在超类中新建方法\n4. 从一个子类复制实现\n5. 删除一个子类中的方法并测试\n6. 删除其他子类中的方法并测试\n\n---\n\n### Push Down Method\n\n**何时使用**：某个行为只适用于部分子类\n\n**动机**：把方法放到真正使用它的地方。\n\n**步骤**：\n1. 把方法复制到需要它的子类\n2. 从超类删除方法\n3. 测试\n4. 删除不需要该方法的子类副本\n5. 测试\n\n---\n\n### Replace Subclass with Delegate\n\n**何时使用**：继承用得不对，需要更灵活\n\n**动机**：在合适的地方更偏向组合而不是继承。\n\n**步骤**：\n1. 创建一个空的委托类\n2. 在宿主类中加一个持有委托的字段\n3. 在宿主类构造委托\n4. 把功能迁移到委托类\n5. 每次迁移后测试\n6. 用委托替代继承\n\n---\n\n## Extract Class\n\n**何时使用**：大类里有多个职责\n\n**动机**：拆分类以维持单一职责。\n\n**步骤**：\n1. 决定如何拆分职责\n2. 创建新类\n3. 把字段从原类移到新类\n4. 测试\n5. 把方法从原类移到新类\n6. 每次移动后测试\n7. 重新检查并命名两个类\n8. 决定如何暴露新类\n\n**前：**\n```javascript\nclass Person {\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get officeAreaCode() { return this._officeAreaCode; }\n  set officeAreaCode(arg) { this._officeAreaCode = arg; }\n  get officeNumber() { return this._officeNumber; }\n  set officeNumber(arg) { this._officeNumber = arg; }\n\n  get telephoneNumber() {\n    return `(${this._officeAreaCode}) ${this._officeNumber}`;\n  }\n}\n```\n\n**后：**\n```javascript\nclass Person {\n  constructor() {\n    this._telephoneNumber = new TelephoneNumber();\n  }\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get telephoneNumber() { return this._telephoneNumber.toString(); }\n  get officeAreaCode() { return this._telephoneNumber.areaCode; }\n  set officeAreaCode(arg) { this._telephoneNumber.areaCode = arg; }\n}\n\nclass TelephoneNumber {\n  get areaCode() { return this._areaCode; }\n  set areaCode(arg) { this._areaCode = arg; }\n  get number() { return this._number; }\n  set number(arg) { this._number = arg; }\n  toString() { return `(${this._areaCode}) ${this._number}`; }\n}\n```\n\n---\n\n## 快速参考：异味到重构\n\n| 代码异味 | 主要重构 | 备选方案 |\n|----------|---------|---------|\n| 长函数 | Extract Method | Replace Temp with Query |\n| 重复代码 | Extract Method | Pull Up Method |\n| 大类 | Extract Class | Extract Subclass |\n| 长参数列表 | Introduce Parameter Object | Preserve Whole Object |\n| Feature Envy | Move Method | Extract Method + Move |\n| 数据泥团 | Extract Class | Introduce Parameter Object |\n| 基础类型沉迷 | Replace Primitive with Object | Replace Type Code |\n| switch 语句 | Replace Conditional with Polymorphism | Replace Type Code |\n| 临时字段 | Extract Class | Introduce Null Object |\n| 消息链 | Hide Delegate | Extract Method |\n| 中间人 | Remove Middle Man | Inline Method |\n| 发散式变化 | Extract Class | Split Phase |\n| 散弹式修改 | Move Method | Inline Class |\n| 死代码 | Remove Dead Code | - |\n| 臆想泛化 | Collapse Hierarchy | Inline Class |\n\n---\n\n## 延伸阅读\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (第 2 版)\n- 在线目录：https://refactoring.com/catalog/\n","zh/07-plugins/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=zh%2F07-plugins%2FREADME.md -->","zh/07-plugins/devops-automation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=zh%2F07-plugins%2Fdevops-automation%2FREADME.md -->","zh/07-plugins/documentation/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=zh%2F07-plugins%2Fdocumentation%2FREADME.md -->","zh/07-plugins/documentation/commands/generate-readme.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=zh%2F07-plugins%2Fdocumentation%2Fcommands%2Fgenerate-readme.md -->","zh/07-plugins/pr-review/README.md":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=zh%2F07-plugins%2Fpr-review%2FREADME.md -->"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# CLAUDE.md\n\nTutorial repo. Output is markdown in numbered modules `01-` through `10-`, not an app. Scripts in `scripts/` exist only to validate docs and build the EPUB.\n\nSee also `.claude/CLAUDE.md` for stack/commands and `STYLE_GUIDE.md` for lesson structure.\n\n## Critical commands\n\n```bash\n# Quality gate (also runs on commit via pre-commit hooks)\npre-commit run --all-files\n\n# Tests\npytest scripts/tests/ -v\n\n# EPUB build (renders Mermaid with Pele — needs Node.js >= 20; the pinned bundle downloads once, then works offline)\nuv run scripts/build_epub.py\n\n# Python tooling\nruff check scripts/ && ruff format scripts/\nmypy scripts/ --ignore-missing-imports\nbandit -c scripts/pyproject.toml -r scripts/ --exclude scripts/tests/\n```\n\nPre-commit runs 5 doc checks on `.md` changes: markdown-lint, cross-references, mermaid-syntax, link-check, markdown-rendering. All must pass. The EPUB build is **not** a pre-commit hook — it runs in CI only (`build-epub` job in `.github/workflows/test.yml`), because it is a slow full-book build; the mermaid-syntax hook already renders every diagram with the same Pele bundle.\n\n## Architecture map\n\n- `01-` … `10-` — tutorial modules. **Numbered prefix = learning order**, not alphabetical. Do not reorganize.\n- Each module: `README.md` + copy-paste templates (`.md`, `.json`, `.sh`).\n- `scripts/` — utilities (EPUB builder, link/mermaid/cross-ref validators). Not the product.\n- `02-memory/*.md` — CLAUDE.md templates users copy into their own projects. Don't confuse with this file.\n- `openspec/` — spec-driven change proposals.\n\n## Hard rules\n\n- **YOU MUST NOT commit or push without explicit user request.**\n- **YOU MUST NOT add `Co-Authored-By: Claude`** to any commit message.\n- Always activate `.venv` before running Python scripts (check `venv/`, `.venv/`, `env/`).\n- Internal links use **relative paths** (e.g. `01-slash-commands/README.md`); anchors use `#heading-name`.\n- Code fences **must** declare a language (`bash`, `python`, `json`, …) — the cross-reference check fails otherwise.\n- External URLs must be reachable and stable. No ephemeral links.\n- Mermaid diagrams must render with Pele. The pre-commit mermaid hooks get Node.js 22 from pre-commit and run strict, so they fail instead of skipping; the first run needs network to download Node.js and the pinned Pele bundle (offline: `SKIP=mermaid,vietnamese-mermaid,japanese-mermaid`). Run by hand, `scripts/check_mermaid.py` only warns without Node.js >= 20, and fails under `--strict` or in CI. A broken EPUB build is usually invalid Mermaid, a missing Node.js >= 20, or a failed bundle download.\n- Commit format: `type(scope): subject` where `scope` matches the module folder (e.g. `feat(slash-commands):`, `docs(memory):`, `fix(README):`).\n- Do not reorganize the `01-`–`10-` numbering. The order is the curriculum.\n\n## Workflow preferences\n\n- For lesson edits, follow `STYLE_GUIDE.md` for structure/naming/diagrams.\n- Small fixes → minimal diff. Don't rewrite a section to fix a typo.\n- When adding a module page: README + templates first, then update root `README.md` index and `LEARNING-ROADMAP.md` if order/timing changes.\n- Tutorial > library: prioritize clear explanations and copy-paste examples over reusable abstractions.\n- If a quality check fails, fix the underlying issue. Don't bypass with `--no-verify`.\n\n## Token Efficiency\n- Never re-read files you just wrote or edited. You know the contents.\n- Never re-run commands to \"verify\" unless the outcome was uncertain.\n- Don't echo back large blocks of code or file contents unless asked.\n- Batch related edits into single operations. Don't make 5 edits when 1 handles it.\n- Skip confirmations like \"I'll continue...\" Just do it.\n- If a task needs 1 tool call, don't use 3. Plan before acting.\n- Do not summarize what you just did unless the result is ambiguous or you need additional input.\n","isInternal":false,"tokens":982,"sizeBytes":3884},{"name":"CLAUDE.md","path":"ja/CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/ja/CLAUDE.md","title":"ja - Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"<!-- i18n-source: CLAUDE.md -->\n<!-- i18n-source-sha: a70777e -->\n<!-- i18n-date: 2026-04-27 -->\n\n# CLAUDE.md\n\nこのファイルは、本リポジトリ内のコードを扱う際の Claude Code（claude.ai/code）向けガイドである。\n\n## プロジェクト概要\n\nClaude How To は Claude Code 機能のチュートリアルリポジトリである。これは **ドキュメント・アズ・コード** であり、主な成果物は実行可能アプリケーションではなく、番号付きの学習モジュールに整理された Markdown ファイルである。\n\n**アーキテクチャ：** 各モジュール（01〜10）は Claude Code の特定の機能を、コピー＆ペースト可能なテンプレート、Mermaid 図、サンプルとともに解説する。ビルドシステムはドキュメントの品質を検証し、EPUB 電子書籍を生成する。\n\n## よく使うコマンド\n\n### pre-commit 品質チェック\n\nすべてのドキュメントは、コミット前に 5 つの品質チェックを通過しなければならない（pre-commit フックで自動実行される）：\n\n```bash\n# pre-commit フックをインストール（毎コミットで実行）\npre-commit install\n\n# 全チェックを手動で実行\npre-commit run --all-files\n```\n\n5 つのチェックは以下のとおり：\n1. **markdown-lint** — `markdownlint` による Markdown 構造とフォーマット\n2. **cross-references** — 内部リンク、アンカー、コードフェンスの構文（Python スクリプト）\n3. **mermaid-syntax** — すべての Mermaid 図が正しくパースされるかを検証（Python スクリプト）\n4. **link-check** — 外部 URL が到達可能か（Python スクリプト）\n5. **markdown-rendering** — Markdown が壊れずにレンダリングされるか（Python スクリプト）\n\nEPUB ビルドは pre-commit フック **ではない** — CI のみで実行される（`.github/workflows/test.yml` の `build-epub` ジョブ）。本全体をビルドするため時間がかかるからである。mermaid-syntax フックが同じ Pele バンドルですべての図をすでにレンダリングしている。\n\n### 開発環境のセットアップ\n\n```bash\n# uv（Python パッケージマネージャ）をインストール\npip install uv\n\n# 仮想環境を作成して Python 依存関係をインストール\nuv venv\nsource .venv/bin/activate\nuv pip install -r scripts/requirements-dev.txt\n\n# Node.js ツール（Markdown リンタ）をインストール\nnpm install -g markdownlint-cli\n\n# Mermaid 図は Pele でレンダリングする（Node.js >= 20 が必要。グローバルインストールは不要）\nnode --version\n\n# pre-commit フックをインストール\nuv pip install pre-commit\npre-commit install\n```\n\n### テスト\n\n`scripts/` 内の Python スクリプトはユニットテストを持つ：\n\n```bash\n# 全テストを実行\npytest scripts/tests/ -v\n\n# カバレッジ付きで実行\npytest scripts/tests/ -v --cov=scripts --cov-report=html\n\n# 特定のテストを実行\npytest scripts/tests/test_build_epub.py -v\n```\n\n### コード品質\n\n```bash\n# Python コードをリント・整形\nruff check scripts/\nruff format scripts/\n\n# セキュリティスキャン\nbandit -c scripts/pyproject.toml -r scripts/ --exclude scripts/tests/\n\n# 型チェック\nmypy scripts/ --ignore-missing-imports\n```\n\n### EPUB ビルド\n\n```bash\n# 電子書籍を生成（Mermaid 図は Pele でレンダリング／Node.js >= 20 が必要。固定バンドルは初回のみダウンロード）\nuv run scripts/build_epub.py\n\n# オプション付き\nuv run scripts/build_epub.py --verbose --output custom-name.epub --lang ja\n```\n\n## ディレクトリ構造\n\n```\n├── 01-slash-commands/      # ユーザーが起動するショートカット\n├── 02-memory/              # 永続コンテキストの例\n├── 03-skills/              # 再利用可能な能力\n├── 04-subagents/           # 専門 AI アシスタント\n├── 05-mcp/                 # Model Context Protocol の例\n├── 06-hooks/               # イベント駆動の自動化\n├── 07-plugins/             # バンドル機能\n├── 08-checkpoints/         # セッションのスナップショット\n├── 09-advanced-features/   # プランニング、シンキング、バックグラウンド\n├── 10-cli/                 # CLI リファレンス\n├── scripts/\n│   ├── build_epub.py           # EPUB ジェネレータ（Mermaid を Pele でレンダリング）\n│   ├── check_cross_references.py   # 内部リンクを検証\n│   ├── check_links.py          # 外部 URL を検証\n│   ├── check_mermaid.py        # Mermaid 構文を検証\n│   └── tests/                  # スクリプトのユニットテスト\n├── .pre-commit-config.yaml    # 品質チェック定義\n└── README.md               # メインガイド（モジュール索引も兼ねる）\n```\n\n## コンテンツ作成ガイド\n\n### モジュール構造\n番号付きフォルダはいずれも以下のパターンに従う：\n- **README.md** — 機能の概要と例\n- **サンプルファイル** — コピー＆ペースト可能なテンプレート（コマンドは `.md`、設定は `.json`、フックは `.sh`）\n- ファイルは機能の複雑さと依存関係に従って整理されている\n\n### Mermaid 図\n- すべての図は正常にパースできること（pre-commit フックで検査）\n- EPUB ビルドは Pele で図をレンダリングする（Node.js >= 20 が必要。固定バンドルは初回のみダウンロードされ、以降はオフラインで動作する）\n- フローチャート、シーケンス図、アーキテクチャ可視化に Mermaid を使用する\n\n### 相互参照\n- 内部リンクは相対パスを使う（例：`(01-slash-commands/README.md)`）\n- コードフェンスは言語指定が必須（例：` ```bash `、` ```python `）\n- アンカーリンクは `#heading-name` 形式\n\n### リンク検証\n- 外部 URL は到達可能であること（pre-commit フックで検査）\n- 一時的なコンテンツへのリンクは避ける\n- 可能な限りパーマリンクを使用する\n\n## 主要なアーキテクチャ上のポイント\n\n1. **番号付きフォルダは学習順序を示す** — 01〜10 のプレフィックスは Claude Code 機能の推奨学習順序を表す。この番号付けは意図的なものなので、アルファベット順に並べ替えてはならない。\n\n2. **スクリプトはユーティリティであり製品ではない** — `scripts/` の Python スクリプトはドキュメント品質と EPUB 生成を支援するものである。実際のコンテンツは番号付きモジュールフォルダにある。\n\n3. **pre-commit がゲートキーパー** — PR が承認される前に 5 つの品質チェックがすべて通過しなければならない。CI パイプラインは同じチェックを 2 回目のパスとして実行する。\n\n4. **Mermaid のレンダリングには Node.js >= 20 が必要** — EPUB ビルドは固定バージョンの Pele バンドルを Node.js で実行して図をレンダリングする（バンドルは初回のみダウンロードされ、sha256 で検証してキャッシュされる）。ここでビルドが失敗する場合は、Node.js >= 20 が未インストールか、バンドルのダウンロード失敗か、Mermaid 構文エラーが典型的な原因である。pre-commit の mermaid フックは pre-commit が用意する Node.js 22 で厳格モードで実行され、スキップせずに失敗する。EPUB ビルド自体は pre-commit では実行されず、CI のみで実行される。\n\n5. **これはチュートリアルでありライブラリではない** — コンテンツを追加する際は、明快な解説、コピー＆ペースト可能な例、視覚的な図を重視する。価値は概念を教えることにあり、再利用可能なコードを提供することではない。\n\n## コミット規約\n\nConventional Commits 形式に従う：\n- `feat(slash-commands): Add API documentation generator`\n- `docs(memory): Improve personal preferences example`\n- `fix(README): Correct table of contents link`\n- `refactor(hooks): Simplify hook configuration examples`\n\nスコープは該当するフォルダ名に合わせる。\n","isInternal":false,"tokens":2794,"sizeBytes":8512},{"name":"CLAUDE.md","path":"uk/CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/uk/CLAUDE.md","title":"uk - Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"<!-- i18n-source: CLAUDE.md -->\n<!-- i18n-source-sha: 63a1416 -->\n<!-- i18n-date: 2026-04-10 -->\n\n# CLAUDE.md\n\nЦей файл надає настанови для Claude Code (claude.ai/code) при роботі з кодом у цьому репозиторії.\n\n## Огляд проєкту\n\nClaude How To — це навчальний репозиторій з функцій Claude Code. Це **документація-як-код** — основний продукт — markdown-файли, організовані в пронумеровані навчальні модулі, а не виконуваний додаток.\n\n**Архітектура**: Кожен модуль (01-10) охоплює конкретну функцію Claude Code з готовими шаблонами для копіювання, Mermaid-діаграмами та прикладами. Система збірки валідує якість документації та генерує EPUB-книгу.\n\n## Типові команди\n\n### Перевірки якості pre-commit\n\nУся документація повинна пройти п'ять перевірок якості перед комітами (запускаються автоматично через pre-commit хуки):\n\n```bash\n# Install pre-commit hooks (runs on every commit)\npre-commit install\n\n# Run all checks manually\npre-commit run --all-files\n```\n\nП'ять перевірок:\n1. **markdown-lint** — Структура та форматування Markdown через `markdownlint`\n2. **cross-references** — Внутрішні посилання, якорі, синтаксис блоків коду (Python-скрипт)\n3. **mermaid-syntax** — Валідація коректного парсингу всіх Mermaid-діаграм (Python-скрипт)\n4. **link-check** — Доступність зовнішніх URL (Python-скрипт)\n5. **markdown-rendering** — Markdown рендериться без помилок (Python-скрипт)\n\nЗбірка EPUB **не є** pre-commit хуком — вона виконується лише в CI (джоб `build-epub` у `.github/workflows/test.yml`), бо це повільна збірка всієї книги; хук mermaid-syntax уже рендерить кожну діаграму тим самим бандлом Pele.\n\n### Налаштування середовища розробки\n\n```bash\n# Install uv (Python package manager)\npip install uv\n\n# Create virtual environment and install Python dependencies\nuv venv\nsource .venv/bin/activate\nuv pip install -r scripts/requirements-dev.txt\n\n# Install Node.js tools (markdown linter)\nnpm install -g markdownlint-cli\n\n# Mermaid diagrams render with Pele: needs Node.js >= 20, no global package\nnode --version\n\n# Install pre-commit hooks\nuv pip install pre-commit\npre-commit install\n```\n\n### Тестування\n\nPython-скрипти в `scripts/` мають юніт-тести:\n\n```bash\n# Run all tests\npytest scripts/tests/ -v\n\n# Run with coverage\npytest scripts/tests/ -v --cov=scripts --cov-report=html\n\n# Run specific test\npytest scripts/tests/test_build_epub.py -v\n```\n\n### Якість коду\n\n```bash\n# Lint and format Python code\nruff check scripts/\nruff format scripts/\n\n# Security scan\nbandit -c scripts/pyproject.toml -r scripts/ --exclude scripts/tests/\n\n# Type checking\nmypy scripts/ --ignore-missing-imports\n```\n\n### Збірка EPUB\n\n```bash\n# Generate ebook (renders Mermaid diagrams with Pele — needs Node.js >= 20; the pinned bundle downloads once)\nuv run scripts/build_epub.py\n\n# With options\nuv run scripts/build_epub.py --verbose --output custom-name.epub\n```\n\n## Структура каталогів\n\n```\n├── 01-slash-commands/      # Ярлики, ініційовані користувачем\n├── 02-memory/              # Приклади постійного контексту\n├── 03-skills/              # Повторно використовувані можливості\n├── 04-subagents/           # Спеціалізовані AI-асистенти\n├── 05-mcp/                 # Приклади Model Context Protocol\n├── 06-hooks/               # Автоматизація на основі подій\n├── 07-plugins/             # Пакетні функції\n├── 08-checkpoints/         # Знімки сесій\n├── 09-advanced-features/   # Планування, мислення, фони\n├── 10-cli/                 # Довідник CLI\n├── scripts/\n│   ├── build_epub.py           # Генератор EPUB (рендерить Mermaid через Pele)\n│   ├── check_cross_references.py   # Валідація внутрішніх посилань\n│   ├── check_links.py          # Перевірка зовнішніх URL\n│   ├── check_mermaid.py        # Валідація синтаксису Mermaid\n│   └── tests/                  # Юніт-тести для скриптів\n├── .pre-commit-config.yaml    # Визначення перевірок якості\n└── README.md               # Основний довідник (також індекс модулів)\n```\n\n## Настанови щодо контенту\n\n### Структура модуля\nКожна пронумерована папка дотримується патерну:\n- **README.md** — Огляд функції з прикладами\n- **Файли прикладів** — Готові шаблони для копіювання (`.md` для команд, `.json` для конфігурацій, `.sh` для хуків)\n- Файли організовані за складністю функцій та залежностями\n\n### Mermaid-діаграми\n- Усі діаграми повинні успішно парситися (перевіряється pre-commit хуком)\n- Збірка EPUB рендерить діаграми через Pele (потрібен Node.js >= 20; закріплений бандл завантажується лише під час першого запуску, далі все працює офлайн)\n- Використовуйте Mermaid для блок-схем, діаграм послідовностей та архітектурних візуалізацій\n\n### Перехресні посилання\n- Використовуйте відносні шляхи для внутрішніх посилань (напр., `(01-slash-commands/README.md)`)\n- Блоки коду повинні вказувати мову (напр., ` ```bash `, ` ```python `)\n- Якірні посилання використовують формат `#heading-name`\n\n### Валідація посилань\n- Зовнішні URL повинні бути доступні (перевіряється pre-commit хуком)\n- Уникайте посилань на тимчасовий контент\n- Використовуйте пермалінки де можливо\n\n## Ключові архітектурні рішення\n\n1. **Пронумеровані папки вказують порядок навчання** — Префікс 01-10 відображає рекомендовану послідовність вивчення функцій Claude Code. Ця нумерація навмисна; не реорганізовуйте за алфавітом.\n\n2. **Скрипти — утиліти, а не продукт** — Python-скрипти в `scripts/` підтримують якість документації та генерацію EPUB. Фактичний контент — у пронумерованих папках модулів.\n\n3. **Pre-commit — привратник** — Усі перевірки якості повинні пройти перед прийняттям PR. CI-конвеєр запускає ці ж перевірки як другий прохід.\n\n4. **Рендеринг Mermaid потребує Node.js >= 20** — Збірка EPUB запускає закріплений бандл Pele через Node.js для рендерингу діаграм (бандл завантажується лише під час першого запуску, перевіряється за sha256 і кешується). Помилки збірки тут зазвичай пов'язані з відсутнім Node.js >= 20, невдалим завантаженням бандла або невалідним синтаксисом Mermaid. Хуки mermaid у pre-commit працюють у суворому режимі з Node.js 22, який надає сам pre-commit, тож вони падають, а не пропускають перевірку. Сама збірка EPUB не виконується у pre-commit — лише в CI.\n\n5. **Це туторіал, а не бібліотека** — При додаванні контенту зосереджуйтесь на чітких поясненнях, готових прикладах та візуальних діаграмах. Цінність — у навчанні концепцій, а не у наданні повторно використовуваного коду.\n\n## Конвенції комітів\n\nДотримуйтесь формату conventional commits:\n- `feat(slash-commands): Add API documentation generator`\n- `docs(memory): Improve personal preferences example`\n- `fix(README): Correct table of contents link`\n- `refactor(hooks): Simplify hook configuration examples`\n\nСкоуп повинен відповідати назві папки де можливо.\n","isInternal":false,"tokens":2879,"sizeBytes":9753},{"name":"CLAUDE.md","path":"vi/CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/vi/CLAUDE.md","title":"vi - Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# CLAUDE.md\n\nFile này cung cấp hướng dẫn cho Claude Code (claude.ai/code) khi làm việc với code trong repository này.\n\n## Tổng Quan Dự Án\n\nClaude How To là một repository tutorial về các tính năng của Claude Code. Đây là **documentation-as-code** — sản phẩm chính là các file markdown được tổ chức thành các module học tập đánh số (01-10), không phải một ứng dụng thực thi.\n\n**Kiến trúc**: Mỗi module (01-10) bao phủ một tính năng cụ thể của Claude Code với các template copy-paste, sơ đồ Mermaid, và ví dụ. Hệ thống build xác thực chất lượng documentation và tạo ebook EPUB.\n\n## Các Lệnh Thường Dùng\n\n### Kiểm Tra Chất Lượng Pre-commit\n\nTất cả documentation phải vượt qua năm kiểm tra chất lượng trước khi commit (các kiểm tra này chạy tự động qua pre-commit hooks):\n\n```bash\n# Cài đặt pre-commit hooks (chạy trên mỗi commit)\npre-commit install\n\n# Chạy tất cả các kiểm tra thủ công\npre-commit run --all-files\n```\n\nNăm kiểm tra là:\n1. **markdown-lint** — Cấu trúc và định dạng Markdown qua `markdownlint`\n2. **cross-references** — Liên kết nội bộ, anchors, cú pháp code fence (Python script)\n3. **mermaid-syntax** — Xác thực tất cả sơ đồ Mermaid parse đúng (Python script)\n4. **link-check** — Các URL bên ngoài có thể truy cập được (Python script)\n5. **markdown-rendering** — Markdown render không lỗi (Python script)\n\nViệc build EPUB **không phải** là một pre-commit hook — nó chỉ chạy trong CI (job `build-epub` trong `.github/workflows/test.yml`), vì đây là bản build toàn bộ sách, chạy chậm; hook mermaid-syntax đã render mọi sơ đồ bằng cùng bundle Pele.\n\n### Thiết Lập Môi Trường Phát Triển\n\n```bash\n# Cài đặt uv (Python package manager)\npip install uv\n\n# Tạo virtual environment và cài đặt Python dependencies\nuv venv\nsource .venv/bin/activate\nuv pip install -r scripts/requirements-dev.txt\n\n# Cài đặt Node.js tools (markdown linter)\nnpm install -g markdownlint-cli\n\n# Sơ đồ Mermaid được render bằng Pele: cần Node.js >= 20, không cần cài package toàn cục\nnode --version\n\n# Cài đặt pre-commit hooks\nuv pip install pre-commit\npre-commit install\n```\n\n### Testing\n\nCác script Python trong `scripts/` có unit tests:\n\n```bash\n# Chạy tất cả tests\npytest scripts/tests/ -v\n\n# Chạy với coverage\npytest scripts/tests/ -v --cov=scripts --cov-report=html\n\n# Chạy test cụ thể\npytest scripts/tests/test_build_epub.py -v\n```\n\n### Chất Lượng Code\n\n```bash\n# Lint và format Python code\nruff check scripts/\nruff format scripts/\n\n# Security scan\nbandit -c scripts/pyproject.toml -r scripts/ --exclude scripts/tests/\n\n# Type checking\nmypy scripts/ --ignore-missing-imports\n```\n\n### Build EPUB\n\n```bash\n# Tạo ebook (render Mermaid diagrams bằng Pele — cần Node.js >= 20; bundle cố định chỉ tải về một lần)\nuv run scripts/build_epub.py\n\n# Với các tùy chọn\nuv run scripts/build_epub.py --verbose --output custom-name.epub --lang vi\n```\n\n## Cấu Trúc Thư Mục\n\n```\n├── 01-slash-commands/      # Các lối tắt do người dùng gọi\n├── 02-memory/              # Ví dụ về bối cảnh liên tục\n├── 03-skills/              # Các khả năng có thể tái sử dụng\n├── 04-subagents/           # Các tác nhân AI chuyên dụng\n├── 05-mcp/                 # Ví dụ Model Context Protocol\n├── 06-hooks/              # Tự động hóa dựa trên sự kiện\n├── 07-plugins/             # Các tính năng được đóng gói\n├── 08-checkpoints/         # Các snapshot của phiên\n├── 09-advanced-features/   # Lập kế hoạch, suy nghĩ, background tasks\n├── 10-cli/                 # Tham chiếu CLI\n├── scripts/\n│   ├── build_epub.py           # EPUB generator (render Mermaid bằng Pele)\n│   ├── check_cross_references.py   # Xác thực liên kết nội bộ\n│   ├── check_links.py          # Kiểm tra các URL bên ngoài\n│   ├── check_mermaid.py        # Xác thực cú pháp Mermaid\n│   └── tests/                  # Unit tests cho scripts\n├── .pre-commit-config.yaml    # Định nghĩa các kiểm tra chất lượng\n└── README.md               # Hướng dẫn chính (cũng là index của module)\n```\n\n## Hướng Dẫn Nội Dung\n\n### Cấu Trúc Module\n\nMỗi thư mục đánh số tuân theo pattern:\n- **README.md** — Tổng quan về tính năng với các ví dụ\n- **Các file ví dụ** — Template copy-paste (`.md` cho commands, `.json` cho configs, `.sh` cho hooks)\n- Các file được tổ chức theo độ phức tạp của tính năng và dependencies\n\n### Sơ Đồ Mermaid\n- Tất cả sơ đồ phải parse thành công (được kiểm tra bởi pre-commit hook)\n- EPUB build render sơ đồ bằng Pele (cần Node.js >= 20; bundle cố định chỉ tải về trong lần chạy đầu tiên, sau đó chạy offline)\n- Sử dụng Mermaid cho flowcharts, sequence diagrams, và architecture visuals\n\n### Cross-References\n- Sử dụng relative paths cho internal links (ví dụ: `(01-slash-commands/README.md)`)\n- Code fences phải chỉ định ngôn ngữ (ví dụ: ` ```bash `, ` ```python `)\n- Anchor links sử dụng format `#heading-name`\n\n### Link Validation\n- Các URL bên ngoài phải có thể truy cập được (được kiểm tra bởi pre-commit hook)\n- Tránh link đến nội dung tạm thời\n- Sử dụng permalinks nếu có thể\n\n## Các Điểm Kiến Trúc Quan Trọng\n\n1. **Các thư mục đánh số thể hiện thứ tự học tập** — Prefix 01-10 thể hiện thứ tự được khuyến nghị để học các tính năng của Claude Code. Đánh số này có chủ đích; không tổ chức lại theo bảng chữ cái.\n\n2. **Scripts là các tiện ích, không phải sản phẩm** — Các script Python trong `scripts/` hỗ trợ chất lượng documentation và tạo EPUB. Nội dung thực tế nằm trong các thư mục module đánh số.\n\n3. **Pre-commit là người gác cổng** — Tất cả năm kiểm tra chất lượng phải pass trước khi PR được chấp nhận. CI pipeline chạy các kiểm tra tương tự như lần thứ hai.\n\n4. **Mermaid rendering cần Node.js >= 20** — EPUB build chạy bundle Pele cố định bằng Node.js để render diagrams (bundle chỉ tải về trong lần chạy đầu tiên, được kiểm tra sha256 và lưu cache). Các lỗi build ở đây thường là do chưa cài Node.js >= 20, tải bundle thất bại, hoặc cú pháp Mermaid không hợp lệ. Các hook mermaid của pre-commit chạy ở chế độ strict với Node.js 22 do pre-commit cung cấp, nên chúng sẽ báo lỗi thay vì bỏ qua. Bản thân EPUB build không chạy trong pre-commit — nó chỉ chạy trong CI.\n\n5. **Đây là tutorial, không phải thư viện** — Khi thêm nội dung, tập trung vào giải thích rõ ràng, ví dụ copy-paste, và sơ đồ trực quan. Giá trị nằm ở việc dạy các khái niệm, không cung cấp code có thể tái sử dụng.\n\n## Commit Conventions\n\nTuân theo format conventional commit:\n- `feat(slash-commands): Add API documentation generator`\n- `docs(memory): Improve personal preferences example`\n- `fix(README): Correct table of contents link`\n- `refactor(hooks): Simplify hook configuration examples`\n\nScope nên khớp với tên thư mục khi áp dụng.\n","isInternal":false,"tokens":2333,"sizeBytes":7706},{"name":"README.md","path":".claude/skills/lesson-quiz/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/.claude/skills/lesson-quiz/README.md","title":"Lesson-quiz Skill","category":"anthropic-skill","format":"markdown","content":"# Lesson Quiz\n\n> Interactive quiz that tests your understanding of a specific Claude Code lesson with 10 questions, per-question feedback, and targeted review guidance.\n\n## Highlights\n\n- 10 questions per lesson mixing conceptual understanding and practical application\n- Covers all 10 lessons (01-Slash Commands through 10-CLI)\n- Three timing modes: pre-test, progress check, or mastery verification\n- Per-question feedback with correct answers and explanations\n- Targeted review recommendations pointing to specific lesson sections\n- 100-question bank across all lessons in `references/question-bank.md`\n\n## When to Use\n\n| Say this... | Skill will... |\n|---|---|\n| \"quiz me on hooks\" | Run a 10-question quiz on Lesson 06: Hooks |\n| \"lesson quiz 03\" | Test your knowledge of Lesson 03: Skills |\n| \"do I understand MCP\" | Assess your understanding of Lesson 05: MCP |\n| \"practice quiz\" | Let you pick a lesson, then quiz you |\n\n## How It Works\n\n```mermaid\ngraph TD\n    A[\"Select lesson\"] --> B[\"Choose timing: pre/during/after\"]\n    B --> C[\"Answer 10 questions in 5 rounds\"]\n    C --> D[\"Score and review feedback\"]\n    style A fill:#4CAF50,color:#fff\n    style D fill:#2196F3,color:#fff\n```\n\n## Usage\n\n```\n/lesson-quiz [lesson-name-or-number]\n```\n\nExamples:\n```\n/lesson-quiz hooks\n/lesson-quiz 03\n/lesson-quiz advanced-features\n/lesson-quiz           # (prompts for lesson selection)\n```\n\n## Output\n\n### Score Report\n- Total score out of 10 with grade (Mastered / Proficient / Developing / Beginning)\n- Breakdown by question category (conceptual vs. practical)\n\n### Per-Question Feedback\nFor each incorrect answer:\n- What you answered vs. the correct answer\n- Explanation of why the correct answer is right\n- Specific section of the lesson to review\n\n### Timing-Aware Guidance\n- **Pre-test**: Establishes baseline, highlights areas to focus on while studying\n- **During**: Identifies what you've grasped and what to revisit\n- **After**: Confirms mastery or pinpoints remaining gaps\n\n## Resources\n\n| Path | Description |\n|---|---|\n| `references/question-bank.md` | 100 pre-written questions (10 per lesson) with answers, explanations, and review pointers |\n","isInternal":false,"tokens":519,"sizeBytes":2158},{"name":"question-bank.md","path":".claude/skills/lesson-quiz/references/question-bank.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/.claude/skills/lesson-quiz/references/question-bank.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Lesson Quiz — Question Bank\n\n10 questions per lesson. Each question has: category, question text, options (3-4), correct answer, explanation, and review section.\n\n---\n\n## Lesson 01: Slash Commands\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the four types of slash commands in Claude Code?\n- **Options**: A) Built-in, skills, plugin commands, MCP prompts | B) Built-in, custom, hook commands, API prompts | C) System, user, plugin, terminal commands | D) Core, extension, macro, script commands\n- **Correct**: A\n- **Explanation**: Claude Code has built-in commands (like /help, /compact), skills (SKILL.md files), plugin commands (namespaced plugin-name:command), and MCP prompts (/mcp__server__prompt).\n- **Review**: Overview section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you pass all user-provided arguments to a skill?\n- **Options**: A) Use `${args}` | B) Use `$ARGUMENTS` | C) Use `$@` | D) Use `$INPUT`\n- **Correct**: B\n- **Explanation**: `$ARGUMENTS` captures all text after the command name. For positional args, use `$0`, `$1`, etc.\n- **Review**: Arguments\n\n### Q3\n- **Category**: conceptual\n- **Question**: When both a skill (.claude/skills/name/SKILL.md) and a legacy command (.claude/commands/name.md) exist with the same name, which takes priority?\n- **Options**: A) The legacy command | B) The skill | C) Whichever was created first | D) Claude asks the user to choose\n- **Correct**: B\n- **Explanation**: Skills take precedence over legacy commands with the same name. The skill system supersedes the older command system.\n- **Review**: Skill vs Command Conflict section\n\n### Q4\n- **Category**: practical\n- **Question**: How do you inject live shell output into a skill's prompt?\n- **Options**: A) Use `$(command)` syntax | B) Use `!`command`` (backtick with !) syntax | C) Use `@shell:command` syntax | D) Use `{command}` syntax\n- **Correct**: B\n- **Explanation**: The `!`command`` syntax runs a shell command and injects its output into the skill prompt before Claude sees it.\n- **Review**: Dynamic Context with Shell Commands\n\n### Q5\n- **Category**: conceptual\n- **Question**: What does `disable-model-invocation: true` do in a skill's frontmatter?\n- **Options**: A) Prevents the skill from running entirely | B) Allows only the user to invoke it (Claude cannot auto-invoke) | C) Hides it from the /help menu | D) Disables the skill's AI processing\n- **Correct**: B\n- **Explanation**: `disable-model-invocation: true` means only the user can trigger the command via `/command-name`. Claude will never auto-invoke it, useful for skills with side effects like deployments.\n- **Review**: Frontmatter Reference section\n\n### Q6\n- **Category**: practical\n- **Question**: You want to create a skill that only Claude can invoke automatically (hidden from the user's / menu). Which frontmatter field do you set?\n- **Options**: A) `disable-model-invocation: true` | B) `user-invocable: false` | C) `hidden: true` | D) `auto-only: true`\n- **Correct**: B\n- **Explanation**: `user-invocable: false` hides the skill from the user's slash menu but allows Claude to invoke it automatically based on context.\n- **Review**: Frontmatter Reference section\n\n### Q7\n- **Category**: practical\n- **Question**: What is the correct directory structure for a new custom skill called \"deploy\"?\n- **Options**: A) `.claude/commands/deploy.md` | B) `.claude/skills/deploy/SKILL.md` | C) `.claude/skills/deploy.md` | D) `.claude/deploy/SKILL.md`\n- **Correct**: B\n- **Explanation**: Skills live in a directory under `.claude/skills/` with a `SKILL.md` file inside. The directory name matches the command name.\n- **Review**: Creating a Custom Command as a Skill section\n\n### Q8\n- **Category**: conceptual\n- **Question**: How do plugin commands avoid name conflicts with user commands?\n- **Options**: A) They use a `plugin-name:command-name` namespace | B) They have a special .plugin extension | C) They are prefixed with `p/` | D) They override user commands automatically\n- **Correct**: A\n- **Explanation**: Plugin commands use a namespace like `pr-review:check-security` to avoid conflicts with standalone user commands.\n- **Review**: Plugin commands section\n\n### Q9\n- **Category**: practical\n- **Question**: You want a skill to use certain tools without asking for permission each time. Which frontmatter field do you add?\n- **Options**: A) `tools: [Read, Grep]` | B) `allowed-tools: [Read, Grep]` | C) `permissions: [Read, Grep]` | D) `restrict-tools: [Read, Grep]`\n- **Correct**: B\n- **Explanation**: `allowed-tools` pre-approves the listed tools during the turn that invokes the skill, so Claude can use them without a permission prompt; the grant clears when you send your next message. It does not restrict which tools are available — to remove tools while a skill is active, use `disallowed-tools`.\n- **Review**: Frontmatter Reference\n\n### Q10\n- **Category**: conceptual\n- **Question**: What is the `@file` syntax used for in a skill?\n- **Options**: A) Importing another skill | B) Referencing a file to include its content in the prompt | C) Creating a symlink | D) Setting file permissions\n- **Correct**: B\n- **Explanation**: The `@path/to/file` syntax in a skill includes the referenced file's content into the prompt, allowing skills to pull in templates or context files.\n- **Review**: File references section\n\n---\n\n## Lesson 02: Memory\n\n### Q1\n- **Category**: conceptual\n- **Question**: How do CLAUDE.md memory files relate to each other, and what has the highest authority?\n- **Options**: A) Higher tiers override lower tiers entirely | B) They are concatenated into context; Managed Policy loads first and cannot be excluded | C) The most recently modified file wins | D) Project Memory has the highest priority\n- **Correct**: B\n- **Explanation**: CLAUDE.md files are concatenated into context rather than overriding each other — load order sets position in context, not precedence. Managed Policy (admin-managed) loads first and cannot be excluded by individual settings. Auto memory is a separate mechanism.\n- **Review**: Memory hierarchy section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you quickly add a new rule to memory during a conversation?\n- **Options**: A) Use the `/memory` slash command or ask conversationally | B) Prefix your message with `#` (e.g., `# always use TypeScript`) | C) Type `/rule \"rule text\"` | D) Use `@add-memory \"rule text\"`\n- **Correct**: A\n- **Explanation**: Use `/memory` to open your CLAUDE.md and auto memory files in your editor, or ask Claude conversationally. Asking Claude to \"remember\" something (e.g., \"remember that we always use TypeScript strict mode\") saves it to auto memory; to put it in CLAUDE.md instead, say \"add this to CLAUDE.md\". The `#` prefix was discontinued and no longer works.\n- **Review**: Quick memory updates section in README\n\n### Q3\n- **Category**: conceptual\n- **Question**: What is the maximum depth for `@path/to/file` imports in CLAUDE.md?\n- **Options**: A) 3 levels deep | B) 4 levels deep | C) 10 levels deep | D) Unlimited\n- **Correct**: B\n- **Explanation**: The `@path` import syntax supports recursive imports up to a maximum depth of 4 hops to prevent infinite loops.\n- **Review**: The /memory Command section (Import features)\n\n### Q4\n- **Category**: practical\n- **Question**: How do you scope a rule file to only apply to files in `src/api/`?\n- **Options**: A) Put the rule in `src/api/CLAUDE.md` | B) Add `paths: src/api/**` YAML frontmatter to a `.claude/rules/*.md` file | C) Name the file `.claude/rules/api.md` | D) Use `@scope: src/api` in the rule file\n- **Correct**: B\n- **Explanation**: Files in `.claude/rules/` support a `paths:` frontmatter field with glob patterns to scope rules to specific directories.\n- **Review**: Path-specific rules section\n\n### Q5\n- **Category**: conceptual\n- **Question**: How many lines of Auto Memory's MEMORY.md are loaded at session start?\n- **Options**: A) All lines | B) First 100 lines | C) First 200 lines | D) First 500 lines\n- **Correct**: C\n- **Explanation**: The first 200 lines of MEMORY.md — or the first 25 KB, whichever comes first — are auto-loaded into context at session start. Topic files referenced from MEMORY.md are loaded on demand.\n- **Review**: Auto Memory section\n\n### Q6\n- **Category**: practical\n- **Question**: You want personal project preferences that are NOT committed to git. Which file should you use?\n- **Options**: A) `~/.claude/CLAUDE.md` | B) `CLAUDE.local.md` | C) `.claude/rules/personal.md` | D) `.claude/memory/personal.md`\n- **Correct**: B\n- **Explanation**: `CLAUDE.local.md` in the project root is for personal project-specific preferences. It should be git-ignored.\n- **Review**: Memory Locations Table\n\n### Q7\n- **Category**: conceptual\n- **Question**: What does the `/init` command do?\n- **Options**: A) Initializes a new Claude Code project from scratch | B) Generates a template CLAUDE.md based on your project structure | C) Resets all memory to defaults | D) Creates a new session\n- **Correct**: B\n- **Explanation**: `/init` analyzes your project and generates a template CLAUDE.md with suggested rules and standards. Re-running it on an existing CLAUDE.md suggests improvements.\n- **Review**: /init command section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you disable Auto Memory completely?\n- **Options**: A) Delete the ~/.claude/projects directory | B) Set `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1` | C) Add `auto-memory: false` to CLAUDE.md | D) Use `/memory disable auto`\n- **Correct**: B\n- **Explanation**: Setting `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1` disables auto memory. Value `0` forces it on. Unset = default on.\n- **Review**: Turning Auto Memory On or Off\n\n### Q9\n- **Category**: conceptual\n- **Question**: Can a lower-priority memory tier override rules from a higher-priority tier?\n- **Options**: A) Yes, the most recent rule always wins | B) No — CLAUDE.md files are concatenated into context, not overridden; load order sets position, not precedence | C) Yes, if the lower tier uses the `!important` flag | D) It depends on the rule type\n- **Correct**: B\n- **Explanation**: CLAUDE.md files (user, project, local, rules) are concatenated into context rather than overriding each other — later files appear later in context, not \"instead of\" earlier ones. Only Managed Policy is special: it loads first and cannot be excluded by individual settings. Auto memory is a separate mechanism, not part of the concatenation order.\n- **Review**: Memory hierarchy section\n\n### Q10\n- **Category**: practical\n- **Question**: You work across two repositories and want Claude to load CLAUDE.md from both. What flag do you use?\n- **Options**: A) `claude --multi-repo /path/to/other` | B) `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 claude --add-dir /path/to/other` | C) `claude --add-dir /path/to/other` on its own | D) `claude --include /path/to/other`\n- **Correct**: B\n- **Explanation**: `--add-dir` on its own only grants file access to the extra directory — its CLAUDE.md is not loaded by default. Setting `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1` makes Claude Code also load CLAUDE.md from directories added with `--add-dir`.\n- **Review**: Additional directories section\n\n---\n\n## Lesson 03: Skills\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the 3 levels of progressive disclosure in the skill system?\n- **Options**: A) Metadata, instructions, resources | B) Name, body, attachments | C) Header, content, scripts | D) Summary, details, data\n- **Correct**: A\n- **Explanation**: Level 1: Metadata (~100 tokens, always loaded), Level 2: SKILL.md body (<5k tokens, loaded on trigger), Level 3: Bundled resources (scripts/references/assets, loaded on demand).\n- **Review**: How Skills Work: Progressive Disclosure\n\n### Q2\n- **Category**: practical\n- **Question**: What is the most important factor for a skill to be auto-invoked by Claude?\n- **Options**: A) The skill's file name | B) The `description` field in frontmatter with when-to-use keywords | C) The skill's directory location | D) The `auto-invoke: true` frontmatter field\n- **Correct**: B\n- **Explanation**: Claude decides whether to auto-invoke a skill based on its `description` (plus optional `when_to_use`). It must include specific trigger phrases and scenarios.\n- **Review**: Controlling Skill Invocation section\n\n### Q3\n- **Category**: conceptual\n- **Question**: What is the maximum recommended length for a SKILL.md file?\n- **Options**: A) 100 lines | B) 250 lines | C) 500 lines | D) 1000 lines\n- **Correct**: C\n- **Explanation**: SKILL.md should be kept under 500 lines. Larger reference material belongs in `references/` subdirectory files.\n- **Review**: Keep SKILL.md Under 500 Lines section\n\n### Q4\n- **Category**: practical\n- **Question**: How do you make a skill run in an isolated subagent with its own context?\n- **Options**: A) Set `isolation: true` in frontmatter | B) Set `context: fork` with an `agent` field in frontmatter | C) Set `subagent: true` in frontmatter | D) Put the skill in `.claude/agents/`\n- **Correct**: B\n- **Explanation**: `context: fork` runs the skill in a separate context, and the `agent` field specifies which agent type (e.g., `Explore`, `Plan`, custom agent) to use.\n- **Review**: Running skills in subagents section\n\n### Q5\n- **Category**: conceptual\n- **Question**: What is the approximate context budget allocated to skill metadata (Level 1)?\n- **Options**: A) 0.5% of context window | B) 1% of context window | C) 5% of context window | D) 10% of context window\n- **Correct**: B\n- **Explanation**: Skill metadata occupies about 1% of the context window (fallback: 8,000 characters). This is configurable with `SLASH_COMMAND_TOOL_CHAR_BUDGET` or the `skillListingBudgetFraction` setting.\n- **Review**: the \"Description budget\" paragraph under Automatic Discovery\n\n### Q6\n- **Category**: practical\n- **Question**: A skill needs to reference a large API specification. Where should you put it?\n- **Options**: A) Inline in SKILL.md | B) In a `references/api-spec.md` file inside the skill directory | C) In the project's CLAUDE.md | D) In a separate `.claude/rules/` file\n- **Correct**: B\n- **Explanation**: Large reference material belongs in the `references/` subdirectory. Claude loads Level 3 resources on demand, keeping SKILL.md lean.\n- **Review**: Supporting files structure section\n\n### Q7\n- **Category**: conceptual\n- **Question**: What is the difference between Reference Content and Task Content in a skill?\n- **Options**: A) Reference is read-only, Task is read-write | B) Reference adds knowledge to context, Task provides step-by-step instructions | C) Reference is for documentation, Task is for code | D) There is no difference\n- **Correct**: B\n- **Explanation**: Reference Content adds domain knowledge to Claude's context (e.g., brand guidelines). Task Content provides actionable step-by-step instructions for a workflow.\n- **Review**: Skill content types section\n\n### Q8\n- **Category**: practical\n- **Question**: What characters are allowed in the `name` field of a skill's frontmatter for a skill you plan to share via claude.ai or the Skills API (Agent Skills spec)?\n- **Options**: A) Any characters | B) Lowercase letters, numbers, and hyphens only (max 64 chars) | C) Letters and underscores | D) Alphanumeric only\n- **Correct**: B\n- **Explanation**: The name must be kebab-case (lowercase, hyphens), max 64 characters. `name` is itself optional — if omitted it defaults to the skill's directory name — but when supplied it must follow these rules. In Claude Code, the `anthropic-skills` name and namespace are reserved for skills synced from claude.ai, so a skill with that name doesn't load; the broader ban on \"anthropic\" or \"claude\" applies to claude.ai skill uploads and the Skills API. Claude Code itself (v2.1.299) refuses only names that contain hidden, direction-changing or blank-like characters, `<` or `>`, or that are over 256 characters.\n- **Review**: SKILL.md format section\n\n### Q9\n- **Category**: conceptual\n- **Question**: In what order does Claude search for skills?\n- **Options**: A) User > Project > Enterprise | B) Enterprise > Personal > Project (plugin uses namespace) | C) Project > User > Enterprise | D) Alphabetical order\n- **Correct**: B\n- **Explanation**: Priority order is: Enterprise > Personal > Project. Plugin skills use a namespace (plugin-name:skill) so they don't conflict.\n- **Review**: Skill Types & Locations\n\n### Q10\n- **Category**: practical\n- **Question**: How do you prevent Claude from automatically invoking a skill while still allowing users to use it manually?\n- **Options**: A) Set `user-invocable: false` | B) Set `disable-model-invocation: true` | C) Remove the description field | D) Set `auto-invoke: false`\n- **Correct**: B\n- **Explanation**: `disable-model-invocation: true` prevents Claude from auto-invoking but keeps the skill available in the user's `/` menu for manual use.\n- **Review**: Controlling Skill Invocation\n\n---\n\n## Lesson 04: Subagents\n\n### Q1\n- **Category**: conceptual\n- **Question**: What is the main advantage of subagents over inline conversation?\n- **Options**: A) They are faster | B) They operate in a separate, clean context window preventing context pollution | C) They can use more tools | D) They have better error handling\n- **Correct**: B\n- **Explanation**: Subagents get a fresh context window, receiving only what the main agent passes. This prevents the main conversation from being polluted with task-specific details.\n- **Review**: Overview section\n\n### Q2\n- **Category**: practical\n- **Question**: What is the priority order for agent definitions?\n- **Options**: A) Project > User > CLI | B) CLI > Project > User | C) User > Project > CLI | D) They all have equal priority\n- **Correct**: B\n- **Explanation**: Full order is managed settings > `--agents` flag > project (`.claude/agents/`) > user (`~/.claude/agents/`) > plugin. Of the options listed, CLI > Project > User is the correct relative ordering.\n- **Review**: File locations section\n\n### Q3\n- **Category**: conceptual\n- **Question**: Which built-in subagent is optimized for read-only codebase exploration?\n- **Options**: A) general-purpose | B) Plan | C) Explore | D) Bash\n- **Correct**: C\n- **Explanation**: The Explore subagent is the read-only codebase search agent. Since v2.1.198 it inherits the session model, capped at Opus on the Claude API — `model: haiku` is opt-in, not the default. It supports three thoroughness levels: quick, medium, very thorough.\n- **Review**: Built-in subagents section\n\n### Q4\n- **Category**: practical\n- **Question**: How do you restrict which subagents a coordinator agent can spawn?\n- **Options**: A) Use `allowed-agents:` field | B) Use `Agent(agent_name)` syntax in the `tools` field | C) Set `spawn-limit: 2` | D) Use `restrict-agents: [name1, name2]`\n- **Correct**: B\n- **Explanation**: For an agent running as the main thread with `claude --agent`, `tools: Agent(worker, researcher)` creates an allowlist — it can only spawn subagents named \"worker\" or \"researcher\". `Task(...)` still works as an alias (the Task tool was renamed Agent in v2.1.63).\n- **Review**: Restrict spawnable subagents section\n\n### Q5\n- **Category**: conceptual\n- **Question**: What does `isolation: worktree` do for a subagent?\n- **Options**: A) Runs the agent in a Docker container | B) Gives the agent its own git worktree so changes don't affect the main tree | C) Prevents the agent from reading any files | D) Runs the agent in a sandbox\n- **Correct**: B\n- **Explanation**: Worktree isolation creates a separate git worktree. If the agent makes no changes, it auto-cleans up. If changes are made, the worktree path and branch are returned.\n- **Review**: Worktree isolation section\n\n### Q6\n- **Category**: practical\n- **Question**: How do you force a subagent to always run in the background (never inline)?\n- **Options**: A) Set `background: true` in the agent config | B) Use `async: true` in the agent config | C) Press Ctrl+D after starting it | D) Use `--background` CLI flag\n- **Correct**: A\n- **Explanation**: `background: true` in the agent configuration makes the subagent always run as a background task and prevents it from running inline. Subagents Claude spawns from the main conversation already run in the background by default (v2.1.198; always, in the desktop app and VS Code, since v2.1.302), but a subagent's own nested Agent calls run in the foreground by default in `claude -p`, the Agent SDK, the desktop app and VS Code. Users can also press Ctrl+B to send a running foreground task to the background.\n- **Review**: Background subagents section\n\n### Q7\n- **Category**: conceptual\n- **Question**: What does the `memory` field with scope `project` do for a subagent?\n- **Options**: A) Gives read access to the project CLAUDE.md | B) Creates a persistent memory directory scoped to the current project | C) Shares the main agent's conversation history | D) Loads the project's git history\n- **Correct**: B\n- **Explanation**: The `memory` field creates a persistent directory for the subagent. Scope `project` means the memory is tied to the current project. The first 200 lines or 25KB of the agent's MEMORY.md, whichever comes first, auto-load.\n- **Review**: Persistent memory section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you include a phrase in a subagent's description to encourage Claude to automatically delegate tasks to it?\n- **Options**: A) Add \"priority: high\" | B) Include \"use PROACTIVELY\" or \"MUST BE USED\" in the description | C) Set `auto-delegate: true` | D) Add \"trigger: always\"\n- **Correct**: B\n- **Explanation**: Including phrases like \"use PROACTIVELY\" or \"MUST BE USED\" in the description strongly encourages Claude to automatically delegate matching tasks.\n- **Review**: Automatic delegation section\n\n### Q9\n- **Category**: conceptual\n- **Question**: What are the valid `permissionMode` values for a subagent?\n- **Options**: A) read, write, admin | B) manual, acceptEdits, bypassPermissions, plan, dontAsk, auto | C) safe, normal, dangerous | D) restricted, standard, elevated\n- **Correct**: B\n- **Explanation**: Subagents support six permission modes: manual (runs reads without asking and prompts for everything else — shown as Manual; its config value is `default`, and manual is accepted as an alias since v2.1.200), acceptEdits (auto-accepts file edits), bypassPermissions (skips all), plan (read-only), dontAsk (auto-denies unless pre-approved), auto (background classifier decides).\n- **Review**: Configuration fields section\n\n### Q10\n- **Category**: practical\n- **Question**: How do you resume a subagent that returned an agentId from a previous run?\n- **Options**: A) Use `/resume agent-id` | B) Ask Claude to resume it — Claude messages the subagent with the SendMessage tool, using its agent ID or name | C) Use `claude -r agent-id` | D) Subagents cannot be resumed\n- **Correct**: B\n- **Explanation**: Each invocation starts a new instance. To continue earlier work, ask Claude to resume the subagent: Claude uses the SendMessage tool with the agent's ID or name, and the subagent resumes with its full conversation history. The built-in Explore and Plan agents are one-shot and can't be resumed.\n- **Review**: Resumable agents section\n\n---\n\n## Lesson 05: MCP\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the four MCP transport protocols, and which is recommended?\n- **Options**: A) HTTP (recommended), Stdio, SSE (deprecated), WebSocket (`ws`) | B) REST (recommended), GraphQL, gRPC, Thrift | C) TCP, UDP, HTTP | D) Stdio (recommended), HTTP, SSE\n- **Correct**: A\n- **Explanation**: HTTP is recommended for remote servers. Stdio is for local processes (most common currently). SSE is deprecated but still supported. WebSocket (`type: \"ws\"`) holds a persistent bidirectional connection for servers that push events unprompted; it is added with `claude mcp add-json` or `.mcp.json`, not with `--transport`, and supports header-only auth.\n- **Review**: MCP Installation Methods section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you add a GitHub MCP server via CLI?\n- **Options**: A) `claude mcp install github` | B) `claude mcp add --transport http github https://api.githubcopilot.com/mcp/` | C) `claude plugin add github-mcp` | D) `claude connect github`\n- **Correct**: B\n- **Explanation**: Use `claude mcp add` with the `--transport` flag, a name, and the server URL. GitHub's remote server also needs an auth header: `claude mcp add --transport http github https://api.githubcopilot.com/mcp/ --header \"Authorization: Bearer YOUR_GITHUB_PAT\"`.\n- **Review**: MCP configuration management section\n\n### Q3\n- **Category**: conceptual\n- **Question**: With `ENABLE_TOOL_SEARCH=auto`, what happens when MCP tool definitions reach 10% of the context window?\n- **Options**: A) They are truncated | B) Tool search kicks in: MCP tools are deferred and discovered on demand | C) Claude shows an error | D) Extra tools are disabled\n- **Correct**: B\n- **Explanation**: By default (`ENABLE_TOOL_SEARCH` unset) tool search is already on and all MCP tools are deferred. `auto` is threshold mode: tools load upfront until their definitions reach 10% of the context window, then all are deferred (`auto:N` sets a custom percentage). Tool search needs a model that supports `tool_reference` blocks: Opus 4, Sonnet 4, Haiku 4.5 and later.\n- **Review**: MCP Tool Search section\n\n### Q4\n- **Category**: practical\n- **Question**: How do you use environment variable fallbacks in MCP config?\n- **Options**: A) `${VAR || \"default\"}` | B) `${VAR:-default}` | C) `${VAR:default}` | D) `${VAR ? \"default\"}`\n- **Correct**: B\n- **Explanation**: `${VAR:-default}` provides a fallback value if the environment variable is not set. If `VAR` is unset and has no default, the server still loads with the literal `${VAR}` text, and `claude mcp list` and `/mcp` warn about the missing variable.\n- **Review**: Environment variable expansion section\n\n### Q5\n- **Category**: conceptual\n- **Question**: What is the difference between MCP and Memory for data access?\n- **Options**: A) MCP is faster, Memory is slower | B) MCP is for live/changing external data, Memory is for persistent/static preferences | C) MCP is for code, Memory is for text | D) They are interchangeable\n- **Correct**: B\n- **Explanation**: MCP connects to live, changing external data sources (APIs, databases). Memory stores persistent, static project context and preferences.\n- **Review**: MCP vs Memory section\n\n### Q6\n- **Category**: practical\n- **Question**: What happens when a team member first encounters a project-scoped `.mcp.json`?\n- **Options**: A) It loads automatically | B) They get an approval prompt to trust the project's MCP servers | C) It's ignored unless they opt in via settings | D) Claude asks the admin to approve\n- **Correct**: B\n- **Explanation**: Project-scoped `.mcp.json` triggers a security approval prompt on each team member's first use. This is intentional — it prevents untrusted MCP servers.\n- **Review**: MCP Scopes section\n\n### Q7\n- **Category**: conceptual\n- **Question**: What does `claude mcp serve` do?\n- **Options**: A) Starts an MCP server dashboard | B) Makes Claude Code itself act as an MCP server for other applications | C) Serves MCP documentation | D) Tests MCP server connections\n- **Correct**: B\n- **Explanation**: `claude mcp serve` turns Claude Code into an MCP server, enabling multi-agent orchestration where one Claude instance can be controlled by another.\n- **Review**: Claude as MCP Server section\n\n### Q8\n- **Category**: practical\n- **Question**: What is the default maximum output size for MCP tools?\n- **Options**: A) 5,000 tokens | B) 10,000 tokens | C) 25,000 tokens | D) 50,000 tokens\n- **Correct**: C\n- **Explanation**: Default max is 25,000 tokens (`MAX_MCP_OUTPUT_TOKENS`). A warning appears at 10k tokens. Text results over 50,000 characters are saved to a file.\n- **Review**: MCP Output Limits section\n\n### Q9\n- **Category**: conceptual\n- **Question**: When both `allowedMcpServers` and `deniedMcpServers` match a server in managed config, which wins?\n- **Options**: A) Allowed wins | B) Denied wins | C) The last one configured wins | D) Both are applied independently\n- **Correct**: B\n- **Explanation**: In managed MCP configuration, deny rules always take precedence over allow rules.\n- **Review**: Managed MCP Configuration section\n\n### Q10\n- **Category**: practical\n- **Question**: How do you reference an MCP resource in a conversation?\n- **Options**: A) Use `/mcp resource-name` | B) Use `@server-name:protocol://resource/path` mention syntax | C) Use `mcp.get(\"resource\")` | D) Resources are auto-loaded\n- **Correct**: B\n- **Explanation**: MCP resources are accessed via `@server-name:protocol://resource/path` mention syntax in conversation.\n- **Review**: MCP Resources section\n\n---\n\n## Lesson 06: Hooks\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the five types of hooks in Claude Code?\n- **Options**: A) Pre, Post, Error, Filter, and Transform hooks | B) Command, HTTP, MCP Tool, Prompt, and Agent hooks | C) Before, After, Around, Through, and Beside hooks | D) Input, Output, Filter, Transform, and Validate hooks\n- **Correct**: B\n- **Explanation**: Command hooks run shell scripts, HTTP hooks call webhook endpoints, MCP Tool hooks invoke an MCP tool, Prompt hooks use single-turn LLM evaluation, and Agent hooks use subagent-based verification. Agent hooks are experimental and may change.\n- **Review**: Hook types section\n\n### Q2\n- **Category**: practical\n- **Question**: A hook script exits with code 2. What happens?\n- **Options**: A) Non-blocking warning shown | B) Blocking error — stderr is shown as an error to Claude, tool use is prevented | C) Hook is retried | D) Session ends\n- **Correct**: B\n- **Explanation**: Exit code 0 = success/continue, exit code 2 = blocking error (stderr shown as error), any other non-zero = non-blocking error (a `<hook name> hook error` notice with the first line of stderr appears in the transcript, and the action goes ahead). Since v2.1.295, setting `\"onFailure\": \"block\"` on a command or HTTP hook makes such failures block like exit 2.\n- **Review**: Exit codes section\n\n### Q3\n- **Category**: conceptual\n- **Question**: What JSON fields does a PreToolUse hook receive on stdin?\n- **Options**: A) `tool_name` and `tool_output` | B) `session_id`, `tool_name`, `tool_input`, `hook_event_name`, `cwd`, and more | C) Only `tool_name` | D) The full conversation history\n- **Correct**: B\n- **Explanation**: Hooks receive a JSON object on stdin with: session_id, transcript_path, hook_event_name, tool_name, tool_input, tool_use_id, cwd, and permission_mode.\n- **Review**: JSON Input (via stdin)\n\n### Q4\n- **Category**: practical\n- **Question**: How can a PreToolUse hook modify the tool's input parameters before execution?\n- **Options**: A) Return modified JSON on stderr | B) Return JSON with `updatedInput` field on stdout (exit code 0) | C) Write to a temp file | D) Hooks cannot modify inputs\n- **Correct**: B\n- **Explanation**: A PreToolUse hook can output JSON with `\"updatedInput\": {...}` on stdout (with exit 0) to modify the tool's parameters before Claude uses them. `updatedInput` goes under `hookSpecificOutput` and replaces the whole input object; since v2.1.300 it is validated like Claude's own input, so unknown keys are dropped and input the tool rejects denies the call.\n- **Review**: PreToolUse section\n\n### Q5\n- **Category**: conceptual\n- **Question**: Which hook event supports `CLAUDE_ENV_FILE` for persisting environment variables into the session?\n- **Options**: A) PreToolUse | B) UserPromptSubmit | C) SessionStart | D) All events\n- **Correct**: C\n- **Explanation**: `CLAUDE_ENV_FILE` is available to SessionStart, Setup, CwdChanged, and FileChanged hooks, which use it to persist environment variables into the session. Of the options listed, SessionStart is the one that supports it — PreToolUse and UserPromptSubmit do not, and it is not available to all events.\n- **Review**: SessionStart section\n\n### Q6\n- **Category**: practical\n- **Question**: You want a hook that only runs once when a skill is first loaded, not on every tool call. What field do you add?\n- **Options**: A) `run-once: true` | B) `once: true` on a hook in the skill's frontmatter | C) `single: true` | D) `max-runs: 1`\n- **Correct**: B\n- **Explanation**: Hooks declared in a skill's frontmatter support `once: true` — Claude Code removes the hook after its first successful run (a run that fails, blocks, or times out leaves it in place). `once` is honored only in skill frontmatter.\n- **Review**: Component-scoped hooks section\n\n### Q7\n- **Category**: conceptual\n- **Question**: A Stop hook is defined in a subagent's frontmatter. What does it automatically convert to?\n- **Options**: A) A PostToolUse hook | B) A SubagentStop hook | C) A SessionEnd hook | D) It stays as a Stop hook\n- **Correct**: B\n- **Explanation**: When a Stop hook is placed in a subagent's frontmatter, it auto-converts to SubagentStop so it runs when that specific subagent finishes.\n- **Review**: Component-scoped hooks section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you match a hook to all MCP tools from a specific server?\n- **Options**: A) `matcher: \"mcp_github\"` | B) `matcher: \"mcp__github__.*\"` (regex pattern) | C) `matcher: \"mcp:github:*\"` | D) `matcher: \"github-mcp\"`\n- **Correct**: B\n- **Explanation**: Use regex patterns for matchers. MCP tools follow the `mcp__server__tool` naming convention, so `mcp__github__.*` matches all GitHub MCP tools.\n- **Review**: Matcher patterns section\n\n### Q9\n- **Category**: conceptual\n- **Question**: How many hook events does Claude Code support in total?\n- **Options**: A) 16 | B) 25 | C) 33 | D) 40\n- **Correct**: C\n- **Explanation**: Claude Code supports 33 hook events. They fall into four groups: session lifecycle (`SessionStart`, `Setup`, `SessionEnd`), prompt and message handling (`UserPromptSubmit`, `UserPromptExpansion`, `MessageDisplay`), tool use and permissions (`PreToolUse`, `PostToolUse`, `PermissionRequest`, …), and agent, task, and environment coordination (`SubagentStart`, `TaskCreated`, `CwdChanged`, `WorktreeCreate`, `PreModelSwitch`, `PostModelSwitch`, …).\n- **Review**: Hook events table\n\n### Q10\n- **Category**: practical\n- **Question**: You want to debug why a hook isn't firing. What's the best approach?\n- **Options**: A) Add print statements to the hook script | B) Use the `--debug` flag and `Ctrl+O` to open the transcript viewer | C) Check the system log | D) Hooks don't have debugging tools\n- **Correct**: B\n- **Explanation**: `claude --debug` (or `--debug-file <path>`, or `/debug` mid-session) logs hook runs to the debug log, including which hooks fire, their inputs, and outputs; `Ctrl+O` opens the transcript view to see hook outcomes.\n- **Review**: Debugging section\n\n---\n\n## Lesson 07: Plugins\n\n### Q1\n- **Category**: conceptual\n- **Question**: What is the core manifest file for a plugin and where does it live?\n- **Options**: A) `plugin.yaml` in the root directory | B) `.claude-plugin/plugin.json` | C) `package.json` with a \"claude\" key | D) `.claude/plugin.md`\n- **Correct**: B\n- **Explanation**: The plugin manifest lives at `.claude-plugin/plugin.json`. The manifest is optional; when present, `name` (kebab-case identifier) is its only required key; `description`, `version`, `author`, `homepage`, `repository` and `license` are optional metadata.\n- **Review**: Plugin definition structure section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you load a plugin from a local directory so you can try it in a session before publishing?\n- **Options**: A) Use `/plugin test ./my-plugin` | B) Use `claude --plugin-dir ./my-plugin` | C) Use `claude plugin validate ./my-plugin` | D) Copy it to ~/.claude/plugins/\n- **Correct**: B\n- **Explanation**: The `--plugin-dir` flag loads a plugin from a local directory for testing. It's repeatable for loading multiple plugins. `claude plugin validate ./my-plugin` checks the manifest and components but doesn't load the plugin into a session.\n- **Review**: Testing section\n\n### Q3\n- **Category**: conceptual\n- **Question**: What environment variable is available inside plugin hooks and MCP configs to reference the plugin's installation directory?\n- **Options**: A) `$PLUGIN_HOME` | B) `${CLAUDE_PLUGIN_ROOT}` | C) `$PLUGIN_DIR` | D) `${CLAUDE_PLUGIN_PATH}`\n- **Correct**: B\n- **Explanation**: `${CLAUDE_PLUGIN_ROOT}` resolves to the plugin's installed directory, enabling portable path references in hooks and MCP configs.\n- **Review**: Plugin-Provided MCP Servers section in Lesson 05 (MCP)\n\n### Q4\n- **Category**: practical\n- **Question**: A plugin has a command called \"check-security\" in the \"pr-review\" plugin. How does a user invoke it?\n- **Options**: A) `/check-security` | B) `/pr-review:check-security` | C) `/plugin pr-review check-security` | D) `/pr-review/check-security`\n- **Correct**: B\n- **Explanation**: Plugin commands use a `plugin-name:command-name` namespace to avoid conflicts with user commands and other plugins.\n- **Review**: Plugin Commands section in Lesson 01 (Slash Commands)\n\n### Q5\n- **Category**: conceptual\n- **Question**: Which components can a plugin bundle?\n- **Options**: A) Only commands and settings | B) Skills, agents, commands, hooks, MCP servers, LSP config, settings, templates, scripts | C) Only commands, hooks, and MCP servers | D) Only skills and agents\n- **Correct**: B\n- **Explanation**: Plugins can bundle: skills/, agents/, commands/, hooks/hooks.json, .mcp.json, .lsp.json, settings.json, templates/, scripts/, docs/, tests/. Note that `commands/` is legacy — official guidance is to use `skills/` for new plugins, though existing `commands/` directories keep working.\n- **Review**: Plugin Structure Example section\n\n### Q6\n- **Category**: practical\n- **Question**: How do you install a plugin from GitHub?\n- **Options**: A) `claude plugin add github:username/repo` | B) `/plugin marketplace add username/repo`, then `/plugin install plugin-name@marketplace-name` | C) `npm install @claude/username-repo` | D) `git clone` then `claude plugin register`\n- **Correct**: B\n- **Explanation**: Add the GitHub repo as a marketplace with `/plugin marketplace add username/repo`, then install with `/plugin install plugin-name@marketplace-name`. You can also do both in one step: `/plugin install plugin-name --marketplace username/repo` inside a session (v2.1.275+), or `claude plugin install plugin-name --marketplace username/repo` from your shell (v2.1.292+). There is no `github:` install form.\n- **Review**: Installation methods section\n\n### Q7\n- **Category**: conceptual\n- **Question**: What does the `settings.json` `agent` key do in a plugin?\n- **Options**: A) Specifies authentication credentials | B) Sets the main thread agent for the plugin | C) Lists available subagents | D) Configures agent permissions\n- **Correct**: B\n- **Explanation**: The `agent` key in a plugin's settings.json specifies which agent definition to use as the main thread agent when the plugin is active.\n- **Review**: Plugin Settings section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you manage plugin lifecycle (enable/disable/update)?\n- **Options**: A) Edit a config file manually | B) Use `/plugin enable`, `/plugin disable`, `claude plugin update <name>` | C) Use `claude plugin-manager` | D) Reinstall the plugin\n- **Correct**: B\n- **Explanation**: `/plugin enable` and `/plugin disable` are real slash commands. For updating an installed plugin, `claude plugin update <name>` is the form documented in the plugins reference, and the one Claude Code points you to when an update is available.\n- **Review**: Plugin CLI Commands section\n\n### Q9\n- **Category**: conceptual\n- **Question**: What is the main advantage of a plugin over standalone skills/hooks/MCP?\n- **Options**: A) Plugins are faster | B) Single-command install, versioned, marketplace distribution, bundles everything together | C) Plugins have more permissions | D) Plugins work offline\n- **Correct**: B\n- **Explanation**: Plugins package multiple components into one installable unit with versioning, marketplace distribution, and automatic updates — vs. manual setup of standalone components.\n- **Review**: Standalone vs Plugin Approach\n\n### Q10\n- **Category**: practical\n- **Question**: Where do plugin hooks configuration live within the plugin directory?\n- **Options**: A) `.claude-plugin/hooks.json` | B) `hooks/hooks.json` | C) `plugin.json` hooks section | D) `.claude/settings.json`\n- **Correct**: B\n- **Explanation**: Plugin hooks are configured in `hooks/hooks.json` within the plugin directory structure.\n- **Review**: Plugin Structure Example\n\n---\n\n## Lesson 08: Checkpoints\n\n### Q1\n- **Category**: conceptual\n- **Question**: What four things do checkpoints capture?\n- **Options**: A) Git commits, branches, tags, stashes | B) Messages, file modifications, tool usage history, session context | C) Code, tests, logs, configs | D) Inputs, outputs, errors, timing\n- **Correct**: B\n- **Explanation**: Checkpoints capture conversation messages, file modifications made by Claude's tools, tool usage history, and session context.\n- **Review**: Overview section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you access the checkpoint browser?\n- **Options**: A) Use `/restore` command | B) Press `Esc + Esc` (double-escape) or use `/rewind` | C) Use `/history` command | D) Press `Ctrl+Z`\n- **Correct**: B\n- **Explanation**: Double-escape (Esc+Esc) or the `/rewind` command opens the checkpoint browser to select a restore point.\n- **Review**: Accessing checkpoints section\n\n### Q3\n- **Category**: conceptual\n- **Question**: How many rewind options are available, and what are they?\n- **Options**: A) 3: Undo, Redo, Reset | B) 6: Restore code+conversation, Restore conversation, Restore code, Summarize from here, Summarize up to here, Never mind | C) 2: Full restore, Partial restore | D) 4: Code, Messages, Both, Cancel\n- **Correct**: B\n- **Explanation**: The 6 options are: Restore code and conversation (full rollback), Restore conversation only, Restore code only, Summarize from here (compress forward), Summarize up to here (compress backward), Never mind (cancel). The two summary options give bidirectional context compaction.\n- **Review**: Rewind options section\n\n### Q4\n- **Category**: practical\n- **Question**: You used `rm -rf temp/` via Bash in Claude Code, then want to rewind. Will the checkpoint restore those files?\n- **Options**: A) Yes, checkpoints capture everything | B) No, Bash filesystem operations (rm, mv, cp) are not tracked by checkpoints | C) Only if you used the Edit tool instead | D) Only if autoCheckpoint was enabled\n- **Correct**: B\n- **Explanation**: Checkpoints track file changes made by Claude's own Write/Edit tools in the main thread. Bash commands (rm, mv, cp), subagent edits (except a foreground `context: fork` skill), edits made outside Claude Code, and symlinked/hardlinked paths are all outside checkpoint tracking.\n- **Review**: Limitations section\n\n### Q5\n- **Category**: conceptual\n- **Question**: How long are checkpoints retained?\n- **Options**: A) Until session ends | B) 7 days | C) 30 days | D) Indefinitely\n- **Correct**: C\n- **Explanation**: Checkpoints are saved with the session, so `/rewind` works after you resume it; snapshots are deleted about 30 days after the session last saved one (`cleanupPeriodDays`); only the 100 most recent checkpoints keep file snapshots. The window is governed by `cleanupPeriodDays`.\n- **Review**: Checkpoint Retention section\n\n### Q6\n- **Category**: practical\n- **Question**: What does \"Summarize from here\" do when rewinding?\n- **Options**: A) Deletes the conversation from that point | B) Compresses the conversation into an AI-generated summary while preserving the original in the transcript | C) Creates a bullet-point list of changes | D) Exports the conversation to a file\n- **Correct**: B\n- **Explanation**: Summarize compresses the conversation into a shorter AI-generated summary. The original full text is preserved in the transcript file.\n- **Review**: Rewind Options section\n\n### Q7\n- **Category**: conceptual\n- **Question**: When are checkpoints created automatically?\n- **Options**: A) Every 5 minutes | B) On every user prompt | C) Only when you manually save | D) After every tool use\n- **Correct**: B\n- **Explanation**: Automatic checkpoints are created with every user prompt, capturing the state before Claude processes the request.\n- **Review**: Automatic checkpoints section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you disable automatic checkpoint creation?\n- **Options**: A) Use `--no-checkpoints` flag | B) Set `fileCheckpointingEnabled: false` in settings | C) Delete the checkpoints directory | D) Checkpoints cannot be disabled\n- **Correct**: B\n- **Explanation**: Set `fileCheckpointingEnabled: false` in your configuration to disable automatic checkpoint creation (default is true; requires v2.1.119+). Env equivalent: `CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING`.\n- **Review**: Configuration section\n\n### Q9\n- **Category**: conceptual\n- **Question**: Are checkpoints a replacement for git commits?\n- **Options**: A) Yes, they're more powerful | B) No, they are complementary — checkpoints are session-scoped and expire, git is permanent and shareable | C) Yes, for small projects | D) Only in solo development\n- **Correct**: B\n- **Explanation**: Checkpoints are temporary (30-day retention), session-scoped, and cannot be shared. Git commits are permanent, auditable, and shareable. Use both together.\n- **Review**: Integration with git section\n\n### Q10\n- **Category**: practical\n- **Question**: You want to compare two different approaches. What's the recommended checkpoint workflow?\n- **Options**: A) Create two separate sessions | B) Checkpoint before approach A, try it, rewind to checkpoint, try approach B, compare results | C) Use git branches instead | D) There's no good way to compare approaches\n- **Correct**: B\n- **Explanation**: The branching strategy: checkpoint at clean state, try approach A, note results, rewind to the same checkpoint, try approach B. Compare both outcomes.\n- **Review**: Workflow patterns section\n\n---\n\n## Lesson 09: Advanced Features\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the six permission modes in Claude Code?\n- **Options**: A) read, write, execute, admin, root, sudo | B) manual, acceptEdits, plan, auto, dontAsk, bypassPermissions | C) safe, normal, elevated, admin, unrestricted, god | D) view, edit, run, deploy, full, bypass\n- **Correct**: B\n- **Explanation**: The six modes are: manual (runs reads without asking and prompts for everything else — shown as Manual; its config value is `default`, and manual is accepted as an alias since v2.1.200), acceptEdits (auto-accepts file edits), plan (read-only analysis), auto (background classifier decides), dontAsk (auto-denies unless pre-approved), bypassPermissions (skips all checks).\n- **Review**: Permission Modes section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you activate planning mode?\n- **Options**: A) Only via `/plan` command | B) Via `/plan`, `Shift+Tab`/`Alt+M`, `--permission-mode plan` flag, or default config | C) Via `--planning` flag only | D) Planning is always on\n- **Correct**: B\n- **Explanation**: Planning mode can be activated multiple ways: /plan command, Shift+Tab/Alt+M keyboard shortcut, --permission-mode plan CLI flag, or as a default in config.\n- **Review**: Planning Mode section\n\n### Q3\n- **Category**: conceptual\n- **Question**: What does the `opusplan` model alias do?\n- **Options**: A) Uses only Opus for everything | B) Uses Opus for planning phase and Sonnet for implementation | C) Uses a special planning-optimized model | D) Enables plan mode automatically\n- **Correct**: B\n- **Explanation**: `opusplan` is a model alias that uses Opus for the planning phase (higher quality analysis) and Sonnet for the execution phase (faster implementation).\n- **Review**: Planning Mode section\n\n### Q4\n- **Category**: practical\n- **Question**: On a model where thinking can be turned off (for example Sonnet 5), how do you toggle extended thinking on or off during a session?\n- **Options**: A) Type `/effort max` | B) Press `Option+T` (macOS) or `Alt+T` | C) Include \"ultrathink\" in prompt | D) It's always enabled and cannot be toggled\n- **Correct**: B\n- **Explanation**: Option+T (macOS) or Alt+T toggles extended thinking on/off for the session. (`Ctrl+O` toggles verbose mode to show/hide the reasoning text.) On Opus 5.5 (the default model since v2.1.280), Sonnet 5.5 (what the `sonnet` alias resolves to on the Anthropic API since v2.1.284), Haiku 5.5 (what the `haiku` alias resolves to on the Anthropic API since v2.1.293), and the Fable models, thinking can't be turned off: the toggle, `alwaysThinkingEnabled` and `MAX_THINKING_TOKENS=0` have no effect there. For one-off deep reasoning, include \"ultrathink\" in your prompt; for session-level control, use the `/effort` command.\n- **Review**: Extended Thinking section\n\n### Q5\n- **Category**: conceptual\n- **Question**: Does the \"ultrathink\" keyword trigger deep reasoning?\n- **Options**: A) Yes, it triggers deep reasoning for one response without changing session settings | B) No, it's treated as regular prompt text | C) Yes, but only on Opus 4.6 | D) Yes, and it permanently changes the effort level\n- **Correct**: A\n- **Explanation**: Including \"ultrathink\" in your prompt adds an in-context instruction for the model to reason more on that turn. It does not change the effort level sent to the API—use `/effort max` for session-level deep reasoning.\n- **Review**: Extended Thinking section\n\n### Q6\n- **Category**: practical\n- **Question**: How do you run Claude in a CI/CD pipeline with structured JSON output and a turn limit?\n- **Options**: A) `claude --ci --json --limit 3` | B) `claude -p --output-format json --max-t\n\n<!-- [TRUNCATED AT 50KB] -->","isInternal":false,"tokens":12386,"sizeBytes":50080},{"name":"results-template.md","path":".claude/skills/lesson-quiz/references/results-template.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/.claude/skills/lesson-quiz/references/results-template.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Results Report Template\n\nThe output format for Step 5 (\"Score and Present Results\"). Fill the bracketed placeholders; keep the headings and table columns as shown.\n\n```markdown\n## Lesson Quiz Results: [Lesson Name]\n\n**Score: N/10** — [Grade label]\n**Quiz timing**: [Before / During / After] the lesson\n**Question breakdown**: N conceptual correct, N practical correct\n\n### Per-Question Results\n\n| # | Category | Question (short) | Your Answer | Result |\n|---|----------|-----------------|-------------|--------|\n| 1 | Conceptual | [abbreviated question] | [their answer] | [Correct / Incorrect] |\n| 2 | Practical | ... | ... | ... |\n| ... | ... | ... | ... | ... |\n\n### Incorrect Answers — Review These\n\n[For each incorrect answer, show:]\n\n**Q[N]: [Full question text]**\n- Your answer: [what they chose]\n- Correct answer: [correct option]\n- Explanation: [why it's correct]\n- Review: [specific section of the lesson README to re-read]\n\n### [Timing-specific message]\n\n[If pre-test]:\n**Pre-test score: N/10.** This gives you a baseline! Focus your study on the topics you missed. After completing the lesson, retake the quiz to measure your improvement.\n\n[If during]:\n**Progress check: N/10.** [If 7 or above: Great progress — keep going! If 5-6: Review the incorrect topics before continuing. If 0-4: Consider re-reading from the beginning.]\n\n[If after]:\n**Mastery check: N/10.** [If 9-10: You've mastered this lesson! Move on to the next. If 7-8: Almost there — review the missed topics and retake. If <7: Spend more time with the lesson, especially the sections marked above.]\n\n### Recommended Next Steps\n\n[Based on score and timing:]\n- [If mastered]: Proceed to the next lesson in the roadmap: [next lesson link]\n- [If proficient]: Review these specific sections, then retake: [list sections]\n- [If developing or below]: Re-read the full lesson: [lesson link]. Focus on: [list weak categories]\n- [Offer]: \"Would you like to retake this quiz, try a different lesson, or get help with a specific topic?\"\n```\n\n---\n\n**Last Updated**: September 2, 2026\n**Claude Code Version**: 2.1.257\n**Sources**:\n- https://code.claude.com/docs/en/overview\n","isInternal":false,"tokens":544,"sizeBytes":2148},{"name":"SKILL.md","path":".claude/skills/lesson-quiz/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/.claude/skills/lesson-quiz/SKILL.md","title":"lesson-quiz","category":"anthropic-skill","format":"markdown","content":"---\nname: lesson-quiz\ndescription: \"Test a learner on a single Claude Code tutorial lesson (01-10) with 10 questions, scoring answers and flagging weak spots. Use before, during, or after a lesson. Don't use for whole-tutorial assessment or explaining a topic instead of testing it.\"\neffort: high\nmetadata:\n  version: 1.6.2\n  author: Luong NGUYEN\n---\n\n# Lesson Quiz\n\nInteractive quiz that tests understanding of a specific Claude Code lesson with 10 questions, provides per-question feedback, and identifies areas to review.\n\n## Prerequisites\n\nThis skill requires:\n\n- The tutorial repo checked out, so the lesson directories `01-slash-commands/` … `10-cli/` and each `README.md` are readable.\n- `references/question-bank.md` present in this skill (the source of all questions).\n\nBefore starting, confirm the target lesson's `README.md` exists. If it is missing, do not fabricate questions — warn the user and ask them to check the repository structure (see Error Handling).\n\n**Guardrails:**\n\n- **Never invent questions or answers.** Ask only questions drawn from `references/question-bank.md` for the selected lesson; if the bank lacks entries for a lesson, say so rather than making them up.\n- **Score accurately.** Track which shuffled position holds the correct answer for every question and validate each response against it — never guess a score.\n- **Confirm timing before scoring.** The pre/during/after choice changes how results are framed; do not skip it.\n\n## Instructions\n\n### Step 1: Determine the Lesson\n\nIf the user provided a lesson as an argument (e.g., `/lesson-quiz hooks` or `/lesson-quiz 03`), map it to the lesson directory:\n\n**Lesson mapping:**\n- `01`, `slash-commands`, `commands` → 01-slash-commands\n- `02`, `memory` → 02-memory\n- `03`, `skills` → 03-skills\n- `04`, `subagents`, `agents` → 04-subagents\n- `05`, `mcp` → 05-mcp\n- `06`, `hooks` → 06-hooks\n- `07`, `plugins` → 07-plugins\n- `08`, `checkpoints`, `checkpoint` → 08-checkpoints\n- `09`, `advanced`, `advanced-features` → 09-advanced-features\n- `10`, `cli` → 10-cli\n\nIf no argument was provided, present a selection prompt using AskUserQuestion:\n\n**Question 1** (header: \"Lesson\"):\n\"Which lesson do you want to quiz on?\"\nOptions:\n1. \"Slash Commands (01)\" — Custom commands, skills, frontmatter, arguments\n2. \"Memory (02)\" — CLAUDE.md, memory hierarchy, rules, auto memory\n3. \"Skills (03)\" — Progressive disclosure, auto-invocation, SKILL.md\n4. \"Subagents (04)\" — Task delegation, agent config, isolation\n\n**Question 2** (header: \"Lesson\"):\n\"Which lesson do you want to quiz on? (continued)\"\nOptions:\n1. \"MCP (05)\" — External integration, transport, servers, tool search\n2. \"Hooks (06)\" — Event automation, PreToolUse, exit codes, JSON I/O\n3. \"Plugins (07)\" — Bundled solutions, marketplace, plugin.json\n4. \"More lessons...\" — Checkpoints, Advanced Features, CLI\n\nIf \"More lessons...\" is selected, present:\n\n**Question 3** (header: \"Lesson\"):\n\"Select your lesson:\"\nOptions:\n1. \"Checkpoints (08)\" — Rewind, restore, safe experimentation\n2. \"Advanced Features (09)\" — Planning, permissions, print mode, thinking\n3. \"CLI Reference (10)\" — Flags, output formats, scripting, piping\n\n### Step 2: Read the Lesson Content\n\nRead the lesson README.md file to refresh context:\n- Read file: `<lesson-directory>/README.md`\n\nThen use the question bank from `references/question-bank.md` for that lesson (10 pre-written questions with answers and explanations). To stay within the context budget, read only the one selected lesson's README — not all ten.\n\n### Step 3: Present the Quiz\n\nAsk the user about quiz timing context:\n\nUse AskUserQuestion (header: \"Timing\"):\n\"When are you taking this quiz relative to the lesson?\"\nOptions:\n1. \"Before (pre-test)\" — I haven't read the lesson yet, testing my prior knowledge\n2. \"During (progress check)\" — I'm partway through the lesson\n3. \"After (mastery check)\" — I've completed the lesson and want to verify understanding\n\nThis context affects how the results are framed (see Step 5).\n\n### Step 4: Present Questions in Rounds\n\nPresent 10 questions from the question bank in rounds of 2 questions each (5 rounds total). Each question uses AskUserQuestion with the question text and 3-4 answer options.\n\n**IMPORTANT**: Use AskUserQuestion with max 4 options per question, 2 questions per round.\n\nFor each round, present 2 questions. After the user answers each round, immediately show per-question feedback: whether each answer was correct or incorrect, and if incorrect, show the correct answer and a brief explanation. Then proceed to the next round. After all 5 rounds, proceed to final scoring.\n\n**Question format per round:**\n\nEach question from the question bank has:\n- `question`: The question text\n- `options`: 3-4 answer choices (one correct, labeled in the bank)\n- `correct`: The correct answer label\n- `explanation`: Why the answer is correct\n- `category`: \"conceptual\" or \"practical\"\n\n**CRITICAL — Shuffle answer options**: For each question, you MUST randomize the order of the answer options before presenting them via AskUserQuestion. Do NOT present them in the order they appear in the question bank (A, B, C, D), and do NOT place the correct answer first. Use a different random permutation for each question. Track which shuffled position contains the correct answer so you can score accurately.\n\nExample: If the question bank lists options A (correct), B, C, D — you might present them as: C, A, D, B. The correct answer is now in position 2.\n\nPresent each question using AskUserQuestion. Record the user's answer for each.\n\n### Step 5: Score and Present Results\n\nAfter all rounds, calculate the score and present results.\n\n**Scoring:**\n- Each correct answer = 1 point\n- Total possible = 10 points\n\n**Grade scale:**\n- 9-10: Mastered — Excellent understanding\n- 7-8: Proficient — Good grasp, minor gaps\n- 5-6: Developing — Fundamentals understood, needs review\n- 3-4: Beginning — Significant gaps, review recommended\n- 0-2: Not yet — Start from the beginning of this lesson\n\n**Output format:** Follow the report template in `references/results-template.md`. It defines the score line, the per-question results table, the \"Incorrect Answers — Review These\" block, the timing-specific message (pre-test / during / after), and the \"Recommended Next Steps\" section. Fill its bracketed placeholders with this run's data.\n\n### Step 6: Offer Follow-up\n\nAfter presenting results, use AskUserQuestion:\n\n\"What would you like to do next?\"\nOptions:\n1. \"Retake this quiz\" — Try the same lesson quiz again\n2. \"Quiz another lesson\" — Switch to a different lesson\n3. \"Explain a topic I missed\" — Get a detailed explanation of an incorrect answer\n4. \"Done\" — End the quiz session\n\nIf **Retake**: Go back to Step 4 (skip timing question, use same timing).\nIf **Quiz another lesson**: Go back to Step 1.\nIf **Explain a topic**: Ask which question number, then read the relevant section from the lesson README.md and explain it with examples.\n\n## Acceptance Criteria\n\nA completed quiz run must satisfy all of these — verify each before presenting final results:\n\n- Exactly one lesson (01-10) was resolved before any question was asked.\n- The timing context (before / during / after) was captured via AskUserQuestion.\n- 10 questions from `references/question-bank.md` for that lesson were presented, in 5 rounds of 2, with answer options shuffled per question.\n- Every answer was scored against the tracked correct-position, producing an integer score in the range 0-10.\n- **Expected output**: a `## Lesson Quiz Results` report containing the score line (`Score: N/10` with a grade label), the per-question results table, an \"Incorrect Answers — Review These\" block for each miss, and a timing-specific message.\n- The follow-up prompt (retake / another lesson / explain / done) was offered.\n\nExample: for a 7/10 \"after\" run on Hooks, the report asserts `Score: 7/10 — Proficient`, lists all 10 rows in the results table, and expands the 3 incorrect questions with correct answer, explanation, and a review pointer.\n\n## Edge Cases & Error Handling\n\n### Invalid lesson argument\nIf the argument doesn't match any lesson, show the valid lesson list and ask the user to pick one.\n\n### User wants to quit mid-quiz\nIf the user indicates they want to stop during any round, present partial results for the questions answered so far (score out of the number attempted, not out of 10).\n\n### Lesson README not found\nIf the README.md file doesn't exist at the expected path, inform the user and suggest checking the repository structure. Do not proceed with fabricated content.\n\n### Question bank missing entries for a lesson\nIf `references/question-bank.md` has no questions for the resolved lesson, tell the user and stop — never invent questions to fill the gap.\n\n## Validation\n\n### Triggering test suite\n\n**Should trigger:**\n- \"quiz me on hooks\"\n- \"lesson quiz\"\n- \"test my knowledge of lesson 3\"\n- \"practice quiz for MCP\"\n- \"do I understand skills\"\n- \"quiz me on slash commands\"\n- \"lesson-quiz 06\"\n- \"test me on checkpoints\"\n- \"how well do I know the CLI\"\n- \"quiz me before I start the memory lesson\"\n\n**Should NOT trigger:**\n- \"assess my overall level\" (use /self-assessment)\n- \"explain hooks to me\"\n- \"create a hook\"\n- \"what is MCP\"\n- \"review my code\"\n","frontmatter":{"name":"lesson-quiz","description":"Test a learner on a single Claude Code tutorial lesson (01-10) with 10 questions, scoring answers and flagging weak spots. Use before, during, or after a lesson. Don't use for whole-tutorial assessment or explaining a topic instead of testing it.","effort":"high","metadata":{"version":"1.6.2","author":"Luong NGUYEN"}},"isInternal":false,"tokens":2237,"sizeBytes":9336},{"name":"README.md","path":".claude/skills/self-assessment/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/.claude/skills/self-assessment/README.md","title":"Self-assessment Skill","category":"anthropic-skill","format":"markdown","content":"# Self-Assessment & Learning Path Advisor\n\n> Comprehensive Claude Code proficiency assessment that evaluates 10 feature areas, identifies skill gaps, and generates a personalized learning path to level up.\n\n## Highlights\n\n- Two assessment modes: Quick (8 questions, 2 min) and Deep (5 rounds, 5 min)\n- Evaluates 10 feature areas: Slash Commands, Memory, Skills, Hooks, MCP, Subagents, Checkpoints, Advanced Features, Plugins, CLI\n- Per-topic scoring with mastery levels (None / Basic / Proficient)\n- Gap analysis with dependency-aware prioritization\n- Personalized learning path with specific exercises and success criteria\n- Follow-up actions: start learning, deep dive, practice project, or retake\n\n## When to Use\n\n| Say this... | Skill will... |\n|---|---|\n| \"assess my level\" | Run the assessment quiz and determine your level |\n| \"where should I start\" | Evaluate your experience and suggest a starting point |\n| \"check my skills\" | Produce a detailed skill profile across all 10 areas |\n| \"what should I learn next\" | Identify gaps and build a prioritized learning path |\n\n## How It Works\n\n```mermaid\ngraph TD\n    A[\"Choose assessment mode\"] --> B[\"Answer quiz questions\"]\n    B --> C[\"Score per-topic proficiency\"]\n    C --> D[\"Generate personalized learning path\"]\n    D --> E[\"Start learning or deep dive\"]\n    style A fill:#4CAF50,color:#fff\n    style E fill:#2196F3,color:#fff\n```\n\n## Assessment Modes\n\n### Quick Assessment (~2 min)\n- 8 yes/no experience questions across 2 rounds\n- Determines overall level: Beginner / Intermediate / Advanced\n- Lists specific gaps with tutorial links\n- Best for: first-time users, quick check-ins\n\n### Deep Assessment (~5 min)\n- 5 rounds of questions covering 10 feature areas (2 topics per round)\n- Per-topic scoring (0-2 points each, 20 points maximum — Checkpoints contributes 0-1, Advanced Features 0-3)\n- Mastery table with strength areas, priority gaps, and review items\n- Dependency-aware learning path with phases and time estimates\n- Recommended practice projects combining gap topics\n- Best for: experienced users wanting to level up, periodic skill reviews\n\n## Usage\n\n```text\n/self-assessment\n```\n\n## Output\n\n### Skill Profile Table\nShows per-topic score, mastery level, and status (Learn / Review / Mastered).\n\n### Personalized Learning Path\n- Organized into phases based on dependency order\n- Each topic includes: tutorial link, focus areas, key exercise, success criterion\n- Time estimate adjusted for topics already mastered\n- Practice projects combining multiple gap areas\n\n### Follow-up Actions\nAfter results, choose to:\n- Start the first gap tutorial with guided exercises\n- Deep dive into a specific gap area\n- Set up a practice project covering your gaps\n- Retake in a different assessment mode\n","isInternal":false,"tokens":617,"sizeBytes":2762},{"name":"deep-assessment-rounds.md","path":".claude/skills/self-assessment/references/deep-assessment-rounds.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/.claude/skills/self-assessment/references/deep-assessment-rounds.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Deep Assessment — Round Questions\n\nThe 5 rounds for Deep Assessment. Present one AskUserQuestion call per round (multi-select, max 4 options). Each round covers 2 feature areas with 2 options each. The scoring map for each round is duplicated in SKILL.md Step 2B so results can be computed without re-reading this file.\n\n---\n\n**Round 1 — Slash Commands & Memory** (header: \"Commands\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Created a custom slash command or skill\" — Written a SKILL.md file with frontmatter, or created .claude/commands/ files\n2. \"Used dynamic context in commands\" — Used `$ARGUMENTS`, `$0`/`$1`, backtick `!command` syntax, or `@file` references in skill/command files\n3. \"Set up project + personal memory\" — Created both a project CLAUDE.md and personal ~/.claude/CLAUDE.md (or CLAUDE.local.md)\n4. \"Used memory hierarchy features\" — Understand how the 7 memory locations are concatenated into context (loaded root-down, CLAUDE.local.md appended after CLAUDE.md at each level, subdirectory files loaded on demand), used .claude/rules/ directory, path-specific rules, or @import syntax\n\n**Scoring:** Options 1-2 → **Slash Commands** (0-2); Options 3-4 → **Memory** (0-2)\n\n---\n\n**Round 2 — Skills & Hooks** (header: \"Automation\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Installed and used an auto-invoked skill\" — A skill that triggers automatically based on its description, without manual /command invocation\n2. \"Controlled skill invocation behavior\" — Used `disable-model-invocation`, `user-invocable`, or `context: fork` with agent field in SKILL.md frontmatter\n3. \"Set up a PreToolUse or PostToolUse hook\" — Configured a hook that runs before/after tool execution (e.g., command validator, auto-formatter)\n4. \"Used advanced hook features\" — Configured prompt-type hooks, skill-frontmatter hooks, HTTP hooks, or hooks with custom JSON output (updatedInput, systemMessage)\n\n**Scoring:** Options 1-2 → **Skills** (0-2); Options 3-4 → **Hooks** (0-2)\n\n---\n\n**Round 3 — MCP & Subagents** (header: \"Integration\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Connected an MCP server and used its tools\" — e.g., GitHub MCP for PRs/issues, database MCP for queries, or any external data source\n2. \"Used advanced MCP features\" — Project-scope .mcp.json, OAuth authentication, MCP resources with @mentions, Tool Search, or `claude mcp serve`\n3. \"Created or configured custom subagents\" — Defined agents in .claude/agents/ with custom tools, model, or permissions\n4. \"Used advanced subagent features\" — Worktree isolation, persistent agent memory, background tasks with Ctrl+B, agent allowlists with `Agent(agent_type)` for an agent run as the main thread with `claude --agent` (the `Task(...)` form is a back-compat alias), or agent teams\n\n**Scoring:** Options 1-2 → **MCP** (0-2); Options 3-4 → **Subagents** (0-2)\n\n---\n\n**Round 4 — Checkpoints & Advanced Features** (header: \"Power User\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Used checkpoints for safe experimentation\" — Rewound to a checkpoint with Esc+Esc or /rewind, restored code and/or conversation, or used either Summarize option (summarize from here / summarize up to here)\n2. \"Used planning mode or extended thinking\" — Activated planning via /plan, Shift+Tab, or --permission-mode plan; toggled extended thinking with Alt+T/Option+T on a model that allows it, or set reasoning depth with `/effort`\n3. \"Configured permission modes\" — Used any of the six modes — manual (config value `default`; shown as Manual since v2.1.200), acceptEdits, plan, auto, dontAsk, or bypassPermissions — via CLI flags, keyboard shortcuts, or settings (just starting in the built-in auto default doesn't count)\n4. \"Used remote/desktop/web features\" — Used `claude --remote-control`, `claude --cloud`, `/teleport`, `/desktop`, or worktrees with `claude -w`\n\n**Scoring:** Option 1 → **Checkpoints** (0-1); Options 2-4 → **Advanced Features** (0-3)\n\n---\n\n**Round 5 — Plugins & CLI** (header: \"Mastery\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Installed or created a plugin\" — Used a bundled plugin from marketplace, or created a .claude-plugin/ directory with plugin.json manifest\n2. \"Used plugin advanced features\" — Plugin skills (`skills/` — the preferred form; namespaced `commands/` is legacy but still works), plugin hooks, plugin MCP servers, LSP configuration, or --plugin-dir flag for testing\n3. \"Used print mode in scripts or CI/CD\" — Used `claude -p` with --output-format json, --max-turns, piped input, or integrated into GitHub Actions / CI pipelines\n4. \"Used advanced CLI features\" — Session resumption (-c/-r), --agents flag, --json-schema for structured output, --fallback-model, --from-pr, or batch processing loops\n\n**Scoring:** Options 1-2 → **Plugins** (0-2); Options 3-4 → **CLI** (0-2)\n\n---\n\n**Last Updated**: October 18, 2026\n**Claude Code Version**: 2.1.302\n**Sources**:\n- https://code.claude.com/docs/en/memory\n- https://code.claude.com/docs/en/sub-agents\n- https://code.claude.com/docs/en/permission-modes\n- https://code.claude.com/docs/en/checkpointing\n- https://code.claude.com/docs/en/plugins-reference\n- https://code.claude.com/docs/en/permission-modes#which-mode-a-session-starts-in\n- https://code.claude.com/docs/en/hooks#hooks-in-skills-and-agents\n- https://code.claude.com/docs/en/model-config#extended-thinking\n","isInternal":false,"tokens":1423,"sizeBytes":5517},{"name":"output-templates.md","path":".claude/skills/self-assessment/references/output-templates.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/.claude/skills/self-assessment/references/output-templates.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Output Templates\n\nBlank markdown templates for the assessment results and learning path. The Step 3A/3B result templates and the Step 4 path-format template are duplicated verbatim in SKILL.md so results can be produced without re-reading this file.\n\n## Quick Assessment results (Step 3A)\n\n```markdown\n## Claude Code Skill Assessment Results\n\n### Your Level: [Level 1: Beginner / Level 2: Intermediate / Level 3: Advanced]\n\nYou checked **N/8** items.\n\n[One-line motivational summary based on level]\n\n### Your Skill Profile\n\n| Area | Status |\n|------|--------|\n| Basic CLI & Conversations | [Checked/Gap] |\n| CLAUDE.md & Memory | [Checked/Gap] |\n| Slash Commands (built-in) | [Checked/Gap] |\n| Custom Commands & Skills | [Checked/Gap] |\n| MCP Servers | [Checked/Gap] |\n| Hooks | [Checked/Gap] |\n| Subagents | [Checked/Gap] |\n| Print Mode & CI/CD | [Checked/Gap] |\n\n### Identified Gaps\n\n[For each unchecked item, provide a 1-line description of what to learn and a link to the tutorial]\n\n### Your Personalized Learning Path\n\n[Output the level-specific learning path — see Step 4]\n```\n\n## Deep Assessment results (Step 3B)\n\n```markdown\n## Claude Code Skill Assessment Results\n\n### Overall Level: [Level 1 / Level 2 / Level 3]\n\n**Total Score: N/20 points**\n\n[One-line motivational summary]\n\n### Your Skill Profile\n\n| Feature Area | Score | Mastery | Status |\n|-------------|-------|---------|--------|\n| Slash Commands | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Memory | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Skills | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Hooks | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| MCP | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Subagents | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Checkpoints | N/1 | [None/Proficient] | [Learn/Mastered] |\n| Advanced Features | N/3 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Plugins | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| CLI | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n\n**Mastery key:** 0 = None, 1 = Basic, 2 = Proficient\n\n### Strength Areas\n[List topics with score 2/2 — these are mastered]\n\n### Priority Gaps (Learn Next)\n[List topics with score 0 — these need attention first, ordered by dependency]\n\n### Review Areas\n[List topics with score 1/2 — basics known but advanced features not yet used]\n\n### Your Personalized Learning Path\n\n[Output gap-specific learning path — see Step 4]\n```\n\n## Learning Path (Step 4)\n\n```markdown\n### Your Personalized Learning Path\n\n**Estimated time**: ~N hours (adjusted for your current skills)\n\n#### Phase 1: [Phase Name] (~N hours)\n[Only if they have gaps in these areas]\n\n**[Topic Name]** — [Learn from scratch / Deep dive into advanced features]\n- Tutorial: [link to tutorial directory]\n- Focus on: [specific sections/concepts they need]\n- Key exercise: [one concrete exercise to do]\n- You'll know it's done when: [specific success criterion]\n\n**[Topic Name]** — ...\n\n---\n\n#### Phase 2: [Phase Name] (~N hours)\n...\n\n---\n\n### Recommended Practice Projects\n\nBased on your gaps, try these real-world exercises to solidify your learning:\n\n1. **[Project name]**: [1-line description combining 2-3 gap topics]\n2. **[Project name]**: [1-line description]\n3. **[Project name]**: [1-line description]\n```\n\n---\n\n**Last Updated**: September 2, 2026\n**Claude Code Version**: 2.1.257\n**Sources**:\n- https://code.claude.com/docs/en/overview\n","isInternal":false,"tokens":949,"sizeBytes":3512},{"name":"topic-recommendations.md","path":".claude/skills/self-assessment/references/topic-recommendations.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/.claude/skills/self-assessment/references/topic-recommendations.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Topic-Specific Recommendations\n\nUse these specific recommendations when a topic is a gap. Paths are relative to this reference file (`.claude/skills/self-assessment/references/`).\n\n**Slash Commands (score 0)**:\n- Tutorial: [01-slash-commands/](../../../../01-slash-commands/)\n- Focus on: Built-in commands reference, creating your first SKILL.md, `$ARGUMENTS` syntax\n- Key exercise: Create a `/optimize` command and test it\n- Done when: You can create a custom skill with arguments and dynamic context\n\n**Slash Commands (score 1 — review)**:\n- Focus on: Dynamic context with the ``!`command` `` syntax, `@file` references, `disable-model-invocation` vs `user-invocable` control\n- Done when: You can create a skill that injects live command output and controls its own invocation behavior\n\n**Memory (score 0)**:\n- Tutorial: [02-memory/](../../../../02-memory/)\n- Focus on: CLAUDE.md creation, `/init` and `/memory` commands, and the difference from auto memory (asking Claude to remember something saves it to auto memory; to put it in CLAUDE.md, say \"add this to CLAUDE.md\" or edit via `/memory` — the old `#` shortcut was removed)\n- Key exercise: Create a project CLAUDE.md with your coding standards\n- Done when: Claude remembers your preferences across sessions\n\n**Memory (score 1 — review)**:\n- Focus on: the 7 memory locations and how they are concatenated into context (loaded root-down, not overridden), .claude/rules/ directory with path-specific rules, `@import` syntax (max depth 4), Auto Memory MEMORY.md (Claude loads its first 200 lines or 25 KB, whichever comes first — a load cap, not a file-size limit)\n- Done when: You have modular rules for different directories and understand how every memory file is concatenated into context\n\n**Skills (score 0)**:\n- Tutorial: [03-skills/](../../../../03-skills/)\n- Focus on: SKILL.md format, auto-invocation via description field, progressive disclosure (3 loading levels)\n- Key exercise: Install `03-skills/code-review-specialist` and verify it auto-triggers\n- Done when: A skill automatically activates based on conversation context\n\n**Skills (score 1 — review)**:\n- Focus on: `context: fork` with `agent` field for subagent execution, `disable-model-invocation` vs `user-invocable`, the skill-listing budget (1% of the context window, fallback 8,000 characters; each entry's `description` + `when_to_use` capped at 1,536 characters by default via `skillListingMaxDescChars`), bundled resources (scripts/, references/, assets/)\n- Done when: You can create a skill that runs in a subagent with forked context\n\n**Hooks (score 0)**:\n- Tutorial: [06-hooks/](../../../../06-hooks/)\n- Focus on: Configuration structure (matcher + hooks array), PreToolUse/PostToolUse events, exit codes (0=success, 2=block), JSON input/output format\n- Key exercise: Create a PreToolUse hook that validates Bash commands\n- Done when: A hook blocks dangerous commands before execution\n\n**Hooks (score 1 — review)**:\n- Focus on: All 33 hook events (including PostToolUseFailure, StopFailure, TaskCreated, CwdChanged, FileChanged, PostCompact, Elicitation, ElicitationResult, Setup, UserPromptExpansion, MessageDisplay, PreModelSwitch, PostModelSwitch — the last two added in v2.1.251), 5 hook types (command, http, mcp_tool, prompt, agent — agent hooks are experimental and may change), hooks in SKILL.md frontmatter (they persist for the session after invocation; subagent-frontmatter hooks end with the subagent), HTTP hooks with allowedEnvVars, `onFailure: \"block\"` to block the action when a command or HTTP hook fails (v2.1.295+), `CLAUDE_ENV_FILE` for SessionStart, Setup, CwdChanged and FileChanged\n- Done when: You can create a prompt-based Stop hook and a hook in a skill's frontmatter (and you know it stays registered for the rest of the session)\n\n**MCP (score 0)**:\n- Tutorial: [05-mcp/](../../../../05-mcp/)\n- Focus on: `claude mcp add` command, transport types (`http` recommended, `stdio`, `ws` for push-style servers, and the deprecated `sse` — note `--transport` does not accept `ws`, so add WebSocket servers with `claude mcp add-json`), GitHub MCP setup, environment variable expansion\n- Key exercise: Add GitHub MCP server and query PRs\n- Done when: You can query live data from an external service via MCP\n\n**MCP (score 1 — review)**:\n- Focus on: Project-scope .mcp.json (each user approves it on first use; workspace trust applies), OAuth 2.0 auth, MCP resources with `@server:resource` mentions, Tool Search (ENABLE_TOOL_SEARCH), `claude mcp serve`, output limits (10,000 tokens warning; 25,000 tokens default max via `MAX_MCP_OUTPUT_TOKENS`; 50,000 characters disk-persistence threshold)\n- Done when: You have a project .mcp.json and understand how tool search defers MCP tools by default and what `ENABLE_TOOL_SEARCH=auto`/`false` change\n\n**Subagents (score 0)**:\n- Tutorial: [04-subagents/](../../../../04-subagents/)\n- Focus on: Agent file format (.claude/agents/*.md), built-in agents (Explore, Plan, general-purpose, claude, statusline-setup, claude-code-guide), tools/model/permissionMode config, spawn limits (depth default 3 since v2.1.219, concurrency default 20, and the 200-per-session spawn cap removed in v2.1.224)\n- Key exercise: Create a code-reviewer subagent and test delegation\n- Done when: Claude delegates code review to your custom agent\n\n**Subagents (score 1 — review)**:\n- Focus on: Worktree isolation (`isolation: worktree`), persistent agent memory (`memory` field with scopes), background agents (Ctrl+B to background; Ctrl+X Ctrl+K twice to stop them all), agent allowlists with `Agent(agent_type)` for a main-thread agent started with `claude --agent` (`Task(...)` remains a back-compat alias; in a subagent's own `tools` the type list is ignored), agent teams (`--teammate-mode`)\n- Done when: You have a subagent with persistent memory running in worktree isolation\n\n**Checkpoints (score 0)**:\n- Tutorial: [08-checkpoints/](../../../../08-checkpoints/)\n- Focus on: Esc+Esc and /rewind access, 6 rewind options (restore code and conversation, restore conversation, restore code, summarize from here, summarize up to here, never mind), limitations — bash filesystem ops, subagent edits (except a foreground `context: fork` skill), edits made outside Claude Code are untracked, and symlinked/hard-linked paths are skipped on restore\n- Key exercise: Make experimental changes, then rewind to restore\n- Done when: You can confidently experiment knowing you can rewind\n\n**Advanced Features (score 0)**:\n- Tutorial: [09-advanced-features/](../../../../09-advanced-features/)\n- Focus on: Planning mode (/plan or Shift+Tab), permission modes (6 types: manual — config value `default`, shown as Manual since v2.1.200 — acceptEdits, plan, auto, dontAsk, bypassPermissions), extended thinking (Alt+T/Option+T toggle — no effect on Opus 5.5 (the default model), Sonnet 5.5, Haiku 5.5, or the Fable models, where thinking stays on)\n- Key exercise: Use planning mode to design a feature, then implement it\n- Done when: You can switch between planning and implementation modes fluently\n\n**Advanced Features (score 1 — review)**:\n- Focus on: Remote control (`claude --remote-control`, alias `--rc`), web sessions (`claude --cloud`; `--remote` is a deprecated alias), desktop handoff (`/desktop`), worktrees (`claude -w`), task lists (Ctrl+T), managed settings for enterprise\n- Done when: You can hand off sessions between CLI, web, and desktop\n\n**Plugins (score 0)**:\n- Tutorial: [07-plugins/](../../../../07-plugins/)\n- Focus on: Plugin structure (.claude-plugin/plugin.json), what plugins bundle (skills, agents, MCP, hooks, settings — plus the legacy `commands/` directory, which still works but `skills/` is preferred for new plugins), installation from marketplace (`/plugin install`, or `claude plugin install <plugin> --marketplace <source>` from the shell)\n- Key exercise: Install a plugin and explore its components\n- Done when: You understand when to use a plugin vs standalone components\n\n**Plugins (score 1 — review)**:\n- Focus on: Creating plugin.json manifest, plugin hooks (hooks/hooks.json), LSP configuration (.lsp.json), `${CLAUDE_PLUGIN_ROOT}` variable, --plugin-dir for testing, marketplace publishing, mods (hooks modules shipped in a plugin that add panes, commands, and tool-call rules — v2.1.287+)\n- Done when: You can create and test a plugin for your team\n\n**CLI (score 0)**:\n- Tutorial: [10-cli/](../../../../10-cli/)\n- Focus on: Interactive vs print mode, `claude -p` with piping, `--output-format json`, session management (-c/-r)\n- Key exercise: Pipe a file to `claude -p` and get JSON output\n- Done when: You can use Claude non-interactively in a script\n\n**CLI (score 1 — review)**:\n- Focus on: --agents flag with JSON config, --json-schema for structured output, --fallback-model, --from-pr, --strict-mcp-config, batch processing with for loops, `claude mcp serve`\n- Done when: You have a CI/CD script that uses Claude with structured JSON output\n\n---\n\n**Last Updated**: October 18, 2026\n**Claude Code Version**: 2.1.302\n**Sources**:\n- https://code.claude.com/docs/en/hooks\n- https://code.claude.com/docs/en/memory\n- https://code.claude.com/docs/en/skills\n- https://code.claude.com/docs/en/mcp\n- https://code.claude.com/docs/en/sub-agents\n- https://code.claude.com/docs/en/checkpointing\n- https://code.claude.com/docs/en/permission-modes\n- https://code.claude.com/docs/en/plugins-reference\n- https://code.claude.com/docs/en/interactive-mode\n- https://code.claude.com/docs/en/model-config#extended-thinking\n- https://code.claude.com/docs/en/settings-reference\n- https://code.claude.com/docs/en/model-config\n- https://code.claude.com/docs/en/plugins/mods/overview\n- https://code.claude.com/docs/en/plugins/cli-reference\n- https://code.claude.com/docs/en/mcp#configure-tool-search\n- https://code.claude.com/docs/en/mcp#project-server-approvals-and-workspace-trust\n","isInternal":false,"tokens":2475,"sizeBytes":9903},{"name":"SKILL.md","path":".claude/skills/self-assessment/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/.claude/skills/self-assessment/SKILL.md","title":"self-assessment","category":"anthropic-skill","format":"markdown","content":"---\nname: self-assessment\nversion: 2.5.5\ndescription: Comprehensive Claude Code self-assessment and learning path advisor. Runs a multi-category quiz covering 10 feature areas, produces a detailed skill profile with per-topic scores, identifies specific gaps, and generates a personalized learning path with prioritized next steps. Use when asked to \"assess my level\", \"take the quiz\", \"find my level\", \"where should I start\", \"what should I learn next\", \"check my skills\", \"skill check\", or \"level up\".\n---\n\n# Self-Assessment & Learning Path Advisor\n\nComprehensive interactive assessment that evaluates Claude Code proficiency across 10 feature areas, identifies specific skill gaps, and generates a personalized learning path to level up.\n\n## Instructions\n\n### Step 1: Welcome & Choose Assessment Mode\n\nPresent the user with a choice of assessment depth:\n\nUse AskUserQuestion with these options:\n- **Quick Assessment** — \"2 multi-select questions (8 items), ~2 minutes. Determines your overall level (Beginner/Intermediate/Advanced) and gives a learning path.\"\n- **Deep Assessment** — \"5 categories with detailed questions, ~5 minutes. Gives per-topic skill scores, identifies specific gaps, and builds a prioritized learning path.\"\n\nIf user chooses **Quick Assessment**, go to Step 2A.\nIf user chooses **Deep Assessment**, go to Step 2B.\n\n---\n\n### Step 2A: Quick Assessment\n\nPresent TWO multi-select questions (AskUserQuestion supports max 4 options each):\n\n**Question 1** (header: \"Basics\"):\n\"Part 1/2: Which of these Claude Code skills do you already have?\"\nOptions:\n1. \"Start Claude Code and chat\" — I can run `claude` and interact with it\n2. \"Created/edited CLAUDE.md\" — I have set up project or user memory\n3. \"Used 3+ slash commands\" — e.g., /help, /compact, /model, /clear\n4. \"Created custom command/skill\" — Written a SKILL.md or custom command file\n\n**Question 2** (header: \"Advanced\"):\n\"Part 2/2: Which of these advanced skills do you have?\"\nOptions:\n1. \"Configured an MCP server\" — e.g., GitHub, database, or other external data source\n2. \"Set up hooks\" — Configured hooks in a settings file (e.g. ~/.claude/settings.json or .claude/settings.json)\n3. \"Created/used subagents\" — Used .claude/agents/ for task delegation\n4. \"Used print mode (claude -p)\" — Used `claude -p` for non-interactive or CI/CD use\n\n**Scoring:**\n- 0-2 total = Level 1: Beginner\n- 3-5 total = Level 2: Intermediate\n- 6-8 total = Level 3: Advanced\n\nGo to Step 3 with the level result, listing which specific items were NOT checked as gaps.\n\n---\n\n### Step 2B: Deep Assessment\n\nPresent 5 rounds of questions, one AskUserQuestion call per round. Each round covers 2 related feature areas. Use multi-select for all rounds.\n\n**IMPORTANT**: AskUserQuestion supports max 4 options per question. Each round has exactly 1 question with 4 options covering 2 topics (2 options per topic).\n\n---\n\n**Round 1 — Slash Commands & Memory** (header: \"Commands\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Created a custom slash command or skill\" — Written a SKILL.md file with frontmatter, or created .claude/commands/ files\n2. \"Used dynamic context in commands\" — Used `$ARGUMENTS`, `$0`/`$1`, backtick `!command` syntax, or `@file` references in skill/command files\n3. \"Set up project + personal memory\" — Created both a project CLAUDE.md and personal ~/.claude/CLAUDE.md (or CLAUDE.local.md)\n4. \"Used memory hierarchy features\" — Understand how the 7 memory locations are concatenated into context (loaded root-down, CLAUDE.local.md appended after CLAUDE.md at each level, subdirectory files loaded on demand), used .claude/rules/ directory, path-specific rules, or @import syntax\n\n**Scoring for Round 1:**\n- Options 1-2 map to **Slash Commands** (0-2 points)\n- Options 3-4 map to **Memory** (0-2 points)\n\n---\n\n**Round 2 — Skills & Hooks** (header: \"Automation\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Installed and used an auto-invoked skill\" — A skill that triggers automatically based on its description, without manual /command invocation\n2. \"Controlled skill invocation behavior\" — Used `disable-model-invocation`, `user-invocable`, or `context: fork` with agent field in SKILL.md frontmatter\n3. \"Set up a PreToolUse or PostToolUse hook\" — Configured a hook that runs before/after tool execution (e.g., command validator, auto-formatter)\n4. \"Used advanced hook features\" — Configured prompt-type hooks, skill-frontmatter hooks, HTTP hooks, or hooks with custom JSON output (updatedInput, systemMessage)\n\n**Scoring for Round 2:**\n- Options 1-2 map to **Skills** (0-2 points)\n- Options 3-4 map to **Hooks** (0-2 points)\n\n---\n\n**Round 3 — MCP & Subagents** (header: \"Integration\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Connected an MCP server and used its tools\" — e.g., GitHub MCP for PRs/issues, database MCP for queries, or any external data source\n2. \"Used advanced MCP features\" — Project-scope .mcp.json, OAuth authentication, MCP resources with @mentions, Tool Search, or `claude mcp serve`\n3. \"Created or configured custom subagents\" — Defined agents in .claude/agents/ with custom tools, model, or permissions\n4. \"Used advanced subagent features\" — Worktree isolation, persistent agent memory, background tasks with Ctrl+B, agent allowlists with `Agent(agent_type)` for an agent run as the main thread with `claude --agent` (the `Task(...)` form is a back-compat alias), or agent teams\n\n**Scoring for Round 3:**\n- Options 1-2 map to **MCP** (0-2 points)\n- Options 3-4 map to **Subagents** (0-2 points)\n\n---\n\n**Round 4 — Checkpoints & Advanced Features** (header: \"Power User\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Used checkpoints for safe experimentation\" — Rewound to a checkpoint with Esc+Esc or /rewind, restored code and/or conversation, or used either Summarize option (summarize from here / summarize up to here)\n2. \"Used planning mode or extended thinking\" — Activated planning via /plan, Shift+Tab, or --permission-mode plan; toggled extended thinking with Alt+T/Option+T on a model that allows it, or set reasoning depth with `/effort`\n3. \"Configured permission modes\" — Used any of the six modes — manual (config value `default`; shown as Manual since v2.1.200), acceptEdits, plan, auto, dontAsk, or bypassPermissions — via CLI flags, keyboard shortcuts, or settings (just starting in the built-in auto default doesn't count)\n4. \"Used remote/desktop/web features\" — Used `claude --remote-control`, `claude --cloud`, `/teleport`, `/desktop`, or worktrees with `claude -w`\n\n**Scoring for Round 4:**\n- Option 1 maps to **Checkpoints** (0-1 point)\n- Options 2-4 map to **Advanced Features** (0-3 points)\n\n---\n\n**Round 5 — Plugins & CLI** (header: \"Mastery\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Installed or created a plugin\" — Used a bundled plugin from marketplace, or created a .claude-plugin/ directory with plugin.json manifest\n2. \"Used plugin advanced features\" — Plugin skills (`skills/` — the preferred form; namespaced `commands/` is legacy but still works), plugin hooks, plugin MCP servers, LSP configuration, or --plugin-dir flag for testing\n3. \"Used print mode in scripts or CI/CD\" — Used `claude -p` with --output-format json, --max-turns, piped input, or integrated into GitHub Actions / CI pipelines\n4. \"Used advanced CLI features\" — Session resumption (-c/-r), --agents flag, --json-schema for structured output, --fallback-model, --from-pr, or batch processing loops\n\n**Scoring for Round 5:**\n- Options 1-2 map to **Plugins** (0-2 points)\n- Options 3-4 map to **CLI** (0-2 points)\n\n---\n\n### Step 3: Calculate & Present Results\n\n#### 3A: For Quick Assessment\n\nCount total selections and determine level. Then present:\n\n```markdown\n## Claude Code Skill Assessment Results\n\n### Your Level: [Level 1: Beginner / Level 2: Intermediate / Level 3: Advanced]\n\nYou checked **N/8** items.\n\n[One-line motivational summary based on level]\n\n### Your Skill Profile\n\n| Area | Status |\n|------|--------|\n| Basic CLI & Conversations | [Checked/Gap] |\n| CLAUDE.md & Memory | [Checked/Gap] |\n| Slash Commands (built-in) | [Checked/Gap] |\n| Custom Commands & Skills | [Checked/Gap] |\n| MCP Servers | [Checked/Gap] |\n| Hooks | [Checked/Gap] |\n| Subagents | [Checked/Gap] |\n| Print Mode & CI/CD | [Checked/Gap] |\n\n### Identified Gaps\n\n[For each unchecked item, provide a 1-line description of what to learn and a link to the tutorial]\n\n### Your Personalized Learning Path\n\n[Output the level-specific learning path — see Step 4]\n```\n\n#### 3B: For Deep Assessment\n\nCalculate per-topic scores from the 5 rounds. Each topic gets 0-2 points, except Advanced Features (0-3) and Checkpoints (0-1). Then present:\n\n```markdown\n## Claude Code Skill Assessment Results\n\n### Overall Level: [Level 1 / Level 2 / Level 3]\n\n**Total Score: N/20 points**\n\n[One-line motivational summary]\n\n### Your Skill Profile\n\n| Feature Area | Score | Mastery | Status |\n|-------------|-------|---------|--------|\n| Slash Commands | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Memory | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Skills | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Hooks | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| MCP | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Subagents | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Checkpoints | N/1 | [None/Proficient] | [Learn/Mastered] |\n| Advanced Features | N/3 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Plugins | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| CLI | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n\n**Mastery key:** 0 = None, 1 = Basic, 2 = Proficient\n\n### Strength Areas\n[List topics with score 2/2 — these are mastered]\n\n### Priority Gaps (Learn Next)\n[List topics with score 0 — these need attention first, ordered by dependency]\n\n### Review Areas\n[List topics with score 1/2 — basics known but advanced features not yet used]\n\n### Your Personalized Learning Path\n\n[Output gap-specific learning path — see Step 4]\n```\n\n**Overall level calculation for Deep Assessment:**\n- 0-6 total points = Level 1: Beginner\n- 7-13 total points = Level 2: Intermediate\n- 14-20 total points = Level 3: Advanced\n\n---\n\n### Step 4: Generate Personalized Learning Path\n\nBased on the assessment results, generate a learning path that is specific to the user's gaps. Do NOT just repeat the generic level path — adapt it.\n\n#### Rules for Path Generation\n\n1. **Skip mastered topics**: If a topic scored 2/2, do not include it in the path.\n2. **Prioritize by dependency order**: Slash Commands before Skills, Memory before Subagents, etc. The dependency order is:\n   - Slash Commands (no deps) -> Skills (depends on Slash Commands)\n   - Memory (no deps) -> Subagents (depends on Memory)\n   - CLI Basics (no deps) -> CLI Mastery (depends on all)\n   - Checkpoints (no deps)\n   - Hooks (depends on Slash Commands)\n   - MCP (no deps) -> Plugins (depends on MCP, Skills, Hooks)\n   - Advanced Features (depends on all previous)\n3. **For score 1/2 topics**: Recommend the \"deep dive\" — link to the specific advanced section they're missing.\n4. **Estimate time**: Sum only the topics they need to learn/review.\n5. **Group into phases**: Organize remaining topics into logical phases of 2-3 topics each.\n\n#### Path Output Format\n\n```markdown\n### Your Personalized Learning Path\n\n**Estimated time**: ~N hours (adjusted for your current skills)\n\n#### Phase 1: [Phase Name] (~N hours)\n[Only if they have gaps in these areas]\n\n**[Topic Name]** — [Learn from scratch / Deep dive into advanced features]\n- Tutorial: [link to tutorial directory]\n- Focus on: [specific sections/concepts they need]\n- Key exercise: [one concrete exercise to do]\n- You'll know it's done when: [specific success criterion]\n\n**[Topic Name]** — ...\n\n---\n\n#### Phase 2: [Phase Name] (~N hours)\n...\n\n---\n\n### Recommended Practice Projects\n\nBased on your gaps, try these real-world exercises to solidify your learning:\n\n1. **[Project name]**: [1-line description combining 2-3 gap topics]\n2. **[Project name]**: [1-line description]\n3. **[Project name]**: [1-line description]\n```\n\n#### Topic-Specific Recommendations\n\nUse these specific recommendations when a topic is a gap:\n\n**Slash Commands (score 0)**:\n- Tutorial: [01-slash-commands/](../../../01-slash-commands/)\n- Focus on: Built-in commands reference, creating your first SKILL.md, `$ARGUMENTS` syntax\n- Key exercise: Create a `/optimize` command and test it\n- Done when: You can create a custom skill with arguments and dynamic context\n\n**Slash Commands (score 1 — review)**:\n- Focus on: Dynamic context with the ``!`command` `` syntax, `@file` references, `disable-model-invocation` vs `user-invocable` control\n- Done when: You can create a skill that injects live command output and controls its own invocation behavior\n\n**Memory (score 0)**:\n- Tutorial: [02-memory/](../../../02-memory/)\n- Focus on: CLAUDE.md creation, `/init` and `/memory` commands, and the difference from auto memory (asking Claude to remember something saves it to auto memory; to put it in CLAUDE.md, say \"add this to CLAUDE.md\" or edit via `/memory` — the old `#` shortcut was removed)\n- Key exercise: Create a project CLAUDE.md with your coding standards\n- Done when: Claude remembers your preferences across sessions\n\n**Memory (score 1 — review)**:\n- Focus on: the 7 memory locations and how they are concatenated into context (loaded root-down, not overridden), .claude/rules/ directory with path-specific rules, `@import` syntax (max depth 4), Auto Memory MEMORY.md (Claude loads its first 200 lines or 25 KB, whichever comes first — a load cap, not a file-size limit)\n- Done when: You have modular rules for different directories and understand how every memory file is concatenated into context\n\n**Skills (score 0)**:\n- Tutorial: [03-skills/](../../../03-skills/)\n- Focus on: SKILL.md format, auto-invocation via description field, progressive disclosure (3 loading levels)\n- Key exercise: Install `03-skills/code-review-specialist` and verify it auto-triggers\n- Done when: A skill automatically activates based on conversation context\n\n**Skills (score 1 — review)**:\n- Focus on: `context: fork` with `agent` field for subagent execution, `disable-model-invocation` vs `user-invocable`, the skill-listing budget (1% of the context window, fallback 8,000 characters; each entry's `description` + `when_to_use` capped at 1,536 characters by default via `skillListingMaxDescChars`), bundled resources (scripts/, references/, assets/)\n- Done when: You can create a skill that runs in a subagent with forked context\n\n**Hooks (score 0)**:\n- Tutorial: [06-hooks/](../../../06-hooks/)\n- Focus on: Configuration structure (matcher + hooks array), PreToolUse/PostToolUse events, exit codes (0=success, 2=block), JSON input/output format\n- Key exercise: Create a PreToolUse hook that validates Bash commands\n- Done when: A hook blocks dangerous commands before execution\n\n**Hooks (score 1 — review)**:\n- Focus on: All 33 hook events (including PostToolUseFailure, StopFailure, TaskCreated, CwdChanged, FileChanged, PostCompact, Elicitation, ElicitationResult, Setup, UserPromptExpansion, MessageDisplay, PreModelSwitch, PostModelSwitch — the last two added in v2.1.251), 5 hook types (command, http, mcp_tool, prompt, agent — agent hooks are experimental and may change), hooks in SKILL.md frontmatter (they persist for the session after invocation; subagent-frontmatter hooks end with the subagent), HTTP hooks with allowedEnvVars, `onFailure: \"block\"` to block the action when a command or HTTP hook fails (v2.1.295+), `CLAUDE_ENV_FILE` for SessionStart, Setup, CwdChanged and FileChanged\n- Done when: You can create a prompt-based Stop hook and a hook in a skill's frontmatter (and you know it stays registered for the rest of the session)\n\n**MCP (score 0)**:\n- Tutorial: [05-mcp/](../../../05-mcp/)\n- Focus on: `claude mcp add` command, transport types (`http` recommended, `stdio`, `ws` for push-style servers, and the deprecated `sse` — note `--transport` does not accept `ws`, so add WebSocket servers with `claude mcp add-json`), GitHub MCP setup, environment variable expansion\n- Key exercise: Add GitHub MCP server and query PRs\n- Done when: You can query live data from an external service via MCP\n\n**MCP (score 1 — review)**:\n- Focus on: Project-scope .mcp.json (each user approves it on first use; workspace trust applies), OAuth 2.0 auth, MCP resources with `@server:resource` mentions, Tool Search (ENABLE_TOOL_SEARCH), `claude mcp serve`, output limits (10,000 tokens warning; 25,000 tokens default max via `MAX_MCP_OUTPUT_TOKENS`; 50,000 characters disk-persistence threshold)\n- Done when: You have a project .mcp.json and understand how tool search defers MCP tools by default and what `ENABLE_TOOL_SEARCH=auto`/`false` change\n\n**Subagents (score 0)**:\n- Tutorial: [04-subagents/](../../../04-subagents/)\n- Focus on: Agent file format (.claude/agents/*.md), built-in agents (Explore, Plan, general-purpose, claude, statusline-setup, claude-code-guide), tools/model/permissionMode config, spawn limits (depth default 3 since v2.1.219, concurrency default 20, and the 200-per-session spawn cap removed in v2.1.224)\n- Key exercise: Create a code-reviewer subagent and test delegation\n- Done when: Claude delegates code review to your custom agent\n\n**Subagents (score 1 — review)**:\n- Focus on: Worktree isolation (`isolation: worktree`), persistent agent memory (`memory` field with scopes), background agents (Ctrl+B to background; Ctrl+X Ctrl+K twice to stop them all), agent allowlists with `Agent(agent_type)` for a main-thread agent started with `claude --agent` (`Task(...)` remains a back-compat alias; in a subagent's own `tools` the type list is ignored), agent teams (`--teammate-mode`)\n- Done when: You have a subagent with persistent memory running in worktree isolation\n\n**Checkpoints (score 0)**:\n- Tutorial: [08-checkpoints/](../../../08-checkpoints/)\n- Focus on: Esc+Esc and /rewind access, 6 rewind options (restore code and conversation, restore conversation, restore code, summarize from here, summarize up to here, never mind), limitations — bash filesystem ops, subagent edits (except a foreground `context: fork` skill), edits made outside Claude Code are untracked, and symlinked/hard-linked paths are skipped on restore\n- Key exercise: Make experimental changes, then rewind to restore\n- Done when: You can confidently experiment knowing you can rewind\n\n**Advanced Features (score 0)**:\n- Tutorial: [09-advanced-features/](../../../09-advanced-features/)\n- Focus on: Planning mode (/plan or Shift+Tab), permission modes (6 types: manual — config value `default`, shown as Manual since v2.1.200 — acceptEdits, plan, auto, dontAsk, bypassPermissions), extended thinking (Alt+T/Option+T toggle — no effect on Opus 5.5 (the default model), Sonnet 5.5, Haiku 5.5, or the Fable models, where thinking stays on)\n- Key exercise: Use planning mode to design a feature, then implement it\n- Done when: You can switch between planning and implementation modes fluently\n\n**Advanced Features (score 1 — review)**:\n- Focus on: Remote control (`claude --remote-control`, alias `--rc`), web sessions (`claude --cloud`; `--remote` is a deprecated alias), desktop handoff (`/desktop`), worktrees (`claude -w`), task lists (Ctrl+T), managed settings for enterprise\n- Done when: You can hand off sessions between CLI, web, and desktop\n\n**Plugins (score 0)**:\n- Tutorial: [07-plugins/](../../../07-plugins/)\n- Focus on: Plugin structure (.claude-plugin/plugin.json), what plugins bundle (skills, agents, MCP, hooks, settings — plus the legacy `commands/` directory, which still works but `skills/` is preferred for new plugins), installation from marketplace (`/plugin install`, or `claude plugin install <plugin> --marketplace <source>` from the shell)\n- Key exercise: Install a plugin and explore its components\n- Done when: You understand when to use a plugin vs standalone components\n\n**Plugins (score 1 — review)**:\n- Focus on: Creating plugin.json manifest, plugin hooks (hooks/hooks.json), LSP configuration (.lsp.json), `${CLAUDE_PLUGIN_ROOT}` variable, --plugin-dir for testing, marketplace publishing, mods (hooks modules shipped in a plugin that add panes, commands, and tool-call rules — v2.1.287+)\n- Done when: You can create and test a plugin for your team\n\n**CLI (score 0)**:\n- Tutorial: [10-cli/](../../../10-cli/)\n- Focus on: Interactive vs print mode, `claude -p` with piping, `--output-format json`, session management (-c/-r)\n- Key exercise: Pipe a file to `claude -p` and get JSON output\n- Done when: You can use Claude non-interactively in a script\n\n**CLI (score 1 — review)**:\n- Focus on: --agents flag with JSON config, --json-schema for structured output, --fallback-model, --from-pr, --strict-mcp-config, batch processing with for loops, `claude mcp serve`\n- Done when: You have a CI/CD script that uses Claude with structured JSON output\n\n---\n\n### Step 5: Offer Follow-up Actions\n\nAfter presenting results, ask the user what they'd like to do next:\n\nUse AskUserQuestion with these options:\n- **Start learning** — \"Help me begin the first topic in my learning path right now\"\n- **Deep dive on a gap** — \"Explain one of my gap areas in detail so I can learn it here\"\n- **Practice project** — \"Set up a practice project that covers my gap areas\"\n- **Retake assessment** — \"I want to retake the quiz (maybe the other mode)\"\n\nIf **Start learning**: Read the README.md of the first gap tutorial and walk the user through the first exercise.\nIf **Deep dive on a gap**: Ask which gap topic, then read the relevant tutorial README.md and explain the key concepts with examples.\nIf **Practice project**: Design a small project that combines 2-3 of their gap topics with concrete steps.\nIf **Retake assessment**: Go back to Step 1.\n\n## Error Handling\n\n### User selects no items in a round\nTreat as 0 points for that round's topics. Continue to next round.\n\n### User selects no items in any round\nAssign Level 1: Beginner. Encourage starting from the beginning. Output the full Level 1 path.\n\n### User wants to retake\nRe-run from Step 1 with a fresh assessment.\n\n### User disagrees with their level\nAcknowledge their preference. Ask which level they identify with. Present the path for their chosen level with a prerequisites check for topics they may have missed.\n\n### User asks about a specific topic\nIf the user says something like \"tell me about hooks\" or \"I want to learn MCP\" during the assessment, note it. After presenting results, highlight that topic in their learning path regardless of score.\n\n## Validation\n\n### Triggering test suite\n\n**Should trigger:**\n- \"assess my level\"\n- \"take the quiz\"\n- \"find my level\"\n- \"where should I start\"\n- \"what level am I\"\n- \"learning path quiz\"\n- \"self-assessment\"\n- \"what should I learn next\"\n- \"check my skills\"\n- \"skill check\"\n- \"level up\"\n- \"how good am I at Claude Code\"\n- \"evaluate my Claude Code knowledge\"\n\n**Should NOT trigger:**\n- \"review my code\"\n- \"create a skill\"\n- \"help me with MCP\"\n- \"explain slash commands\"\n- \"what is a checkpoint\"\n","frontmatter":{"name":"self-assessment","version":"2.5.5","description":"Comprehensive Claude Code self-assessment and learning path advisor. Runs a multi-category quiz covering 10 feature areas, produces a detailed skill profile with per-topic scores, identifies specific gaps, and generates a personalized learning path with prioritized next steps. Use when asked to \"assess my level\", \"take the quiz\", \"find my level\", \"where should I start\", \"what should I learn next\", \"check my skills\", \"skill check\", or \"level up\"."},"isInternal":false,"tokens":5873,"sizeBytes":23354},{"name":"SKILL.md","path":"03-skills/blog-draft/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/03-skills/blog-draft/SKILL.md","title":"blog-draft","category":"anthropic-skill","format":"markdown","content":"---\nname: blog-draft\ndescription: Draft a blog post from ideas and resources. Use when users want to write a blog post, create content from research, or draft articles. Guides through research, brainstorming, outlining, and iterative drafting with version control.\n---\n\n## User Input\n\n```text\n$ARGUMENTS\n```\n\nYou **MUST** consider the user input before proceeding. User should provide:\n- **Idea/Topic**: The main concept or theme for the blog post\n- **Resources**: URLs, files, or references to research (optional but recommended)\n- **Target audience**: Who the blog post is for (optional)\n- **Tone/Style**: Formal, casual, technical, etc. (optional)\n\n**IMPORTANT**: If the user is requesting updates to an **existing blog post**, skip steps 0-8 and start directly at **Step 9**. Read the existing draft file(s) first, then proceed with the iteration process.\n\n## Execution Flow\n\nFollow these steps sequentially. **Do not skip steps or proceed without user approval where indicated.**\n\n### Step 0: Create Project Folder\n\n1. Generate a folder name using format: `YYYY-MM-DD-short-topic-name`\n   - Use today's date\n   - Create a short, URL-friendly slug from the topic (lowercase, hyphens, max 5 words)\n\n2. Create the folder structure:\n   ```\n   blog-posts/\n   └── YYYY-MM-DD-short-topic-name/\n       └── resources/\n   ```\n\n3. Confirm folder creation with user before proceeding.\n\n### Step 1: Research & Resource Collection\n\n1. Create `resources/` subfolder in the blog post directory\n\n2. For each provided resource:\n   - **URLs**: Fetch and save key information to `resources/` as markdown files\n   - **Files**: Read and summarize in `resources/`\n   - **Topics**: Use web search to gather up-to-date information\n\n3. For each resource, create a summary file in `resources/`:\n   - `resources/source-1-[short-name].md`\n   - `resources/source-2-[short-name].md`\n   - etc.\n\n4. Each summary should include:\n   ```markdown\n   # Source: [Title/URL]\n\n   ## Key Points\n   - Point 1\n   - Point 2\n\n   ## Relevant Quotes/Data\n   - Quote or statistic 1\n   - Quote or statistic 2\n\n   ## How This Relates to Topic\n   Brief explanation of relevance\n   ```\n\n5. Present research summary to user.\n\n### Step 2: Brainstorm & Clarify\n\n1. Based on the idea and researched resources, present:\n   - **Main themes** identified from research\n   - **Potential angles** for the blog post\n   - **Key points** that should be covered\n   - **Gaps** in information that need clarification\n\n2. Ask clarifying questions:\n   - What is the main takeaway you want readers to have?\n   - Are there specific points from the research you want to emphasize?\n   - What's the target length? (short: 500-800 words, medium: 1000-1500, long: 2000+)\n   - Any points you want to exclude?\n\n3. **Wait for user responses before proceeding.**\n\n### Step 3: Propose Outline\n\n1. Create a structured outline including:\n\n   ```markdown\n   # Blog Post Outline: [Title]\n\n   ## Meta Information\n   - **Target Audience**: [who]\n   - **Tone**: [style]\n   - **Target Length**: [word count]\n   - **Main Takeaway**: [key message]\n\n   ## Proposed Structure\n\n   ### Hook/Introduction\n   - Opening hook idea\n   - Context setting\n   - Thesis statement\n\n   ### Section 1: [Title]\n   - Key point A\n   - Key point B\n   - Supporting evidence from [source]\n\n   ### Section 2: [Title]\n   - Key point A\n   - Key point B\n\n   [Continue for all sections...]\n\n   ### Conclusion\n   - Summary of key points\n   - Call to action or final thought\n\n   ## Sources to Cite\n   - Source 1\n   - Source 2\n   ```\n\n2. Present outline to user and **ask for approval or modifications**.\n\n### Step 4: Save Approved Outline\n\n1. Once user approves the outline, save it to `OUTLINE.md` in the blog post folder.\n\n2. Confirm the outline has been saved.\n\n### Step 5: Commit Outline (if in git repo)\n\n1. Check if current directory is a git repository.\n\n2. If yes:\n   - Stage the new files: blog post folder, resources, and OUTLINE.md\n   - Create commit with message: `docs: Add outline for blog post - [topic-name]`\n   - Push to remote\n\n3. If not a git repo, skip this step and inform user.\n\n### Step 6: Write Draft\n\n1. Based on the approved outline, write the full blog post draft.\n\n2. Follow the structure from OUTLINE.md exactly.\n\n3. Include:\n   - Engaging introduction with hook\n   - Clear section headers\n   - Supporting evidence and examples from research\n   - Smooth transitions between sections\n   - Strong conclusion with takeaway\n   - **Citations**: All comparisons, statistics, data points, and factual claims MUST cite the original source\n\n4. Save the draft as `draft-v0.1.md` in the blog post folder.\n\n5. Format:\n   ```markdown\n   # [Blog Post Title]\n\n   *[Optional: subtitle or tagline]*\n\n   [Full content with inline citations...]\n\n   ---\n\n   ## References\n   - [1] Source 1 Title - URL or Citation\n   - [2] Source 2 Title - URL or Citation\n   - [3] Source 3 Title - URL or Citation\n   ```\n\n6. **Citation Requirements**:\n   - Every data point, statistic, or comparison MUST have an inline citation\n   - Use numbered references [1], [2], etc., or named citations [Source Name]\n   - Link citations to the References section at the end\n   - Example: \"Studies show that 65% of developers prefer TypeScript [1]\"\n   - Example: \"React outperforms Vue in rendering speed by 20% [React Benchmarks 2024]\"\n\n### Step 7: Commit Draft (if in git repo)\n\n1. Check if in git repository.\n\n2. If yes:\n   - Stage the draft file\n   - Create commit with message: `docs: Add draft v0.1 for blog post - [topic-name]`\n   - Push to remote\n\n3. If not a git repo, skip and inform user.\n\n### Step 8: Present Draft for Review\n\n1. Present the draft content to user.\n\n2. Ask for feedback:\n   - Overall impression?\n   - Sections that need expansion or reduction?\n   - Tone adjustments needed?\n   - Missing information?\n   - Specific edits or rewrites?\n\n3. **Wait for user response.**\n\n### Step 9: Iterate or Finalize\n\n**If user requests changes:**\n1. Note all requested modifications\n2. Return to Step 6 with the following adjustments:\n   - Increment version number (v0.2, v0.3, etc.)\n   - Incorporate all feedback\n   - Save as `draft-v[X.Y].md`\n   - Repeat Steps 7-8\n\n**If user approves:**\n1. Confirm the final draft version\n2. Optionally rename to `final.md` if user requests\n3. Summarize the blog post creation process:\n   - Total versions created\n   - Key changes between versions\n   - Final word count\n   - Files created\n\n## Version Tracking\n\nAll drafts are preserved with incremental versioning:\n- `draft-v0.1.md` - Initial draft\n- `draft-v0.2.md` - After first round of feedback\n- `draft-v0.3.md` - After second round of feedback\n- etc.\n\nThis allows tracking the evolution of the blog post and reverting if needed.\n\n## Output Files Structure\n\n```\nblog-posts/\n└── YYYY-MM-DD-topic-name/\n    ├── resources/\n    │   ├── source-1-name.md\n    │   ├── source-2-name.md\n    │   └── ...\n    ├── OUTLINE.md\n    ├── draft-v0.1.md\n    ├── draft-v0.2.md (if iterations)\n    └── draft-v0.3.md (if more iterations)\n```\n\n## Tips for Quality\n\n- **Hook**: Start with a question, surprising fact, or relatable scenario\n- **Flow**: Each paragraph should connect to the next\n- **Evidence**: Support claims with data from research\n- **Citations**: ALWAYS cite sources for:\n  - All statistics and data points (e.g., \"According to [Source], 75% of...\")\n  - Comparisons between products, services, or approaches (e.g., \"X performs 2x faster than Y [Source]\")\n  - Factual claims about market trends, research findings, or benchmarks\n  - Use inline citations with format: [Source Name] or [Author, Year]\n- **Voice**: Maintain consistent tone throughout\n- **Length**: Respect the target word count\n- **Readability**: Use short paragraphs, bullet points where appropriate\n- **CTA**: End with a clear call-to-action or thought-provoking question\n\n## Notes\n\n- Always wait for user approval at outlined checkpoints\n- Preserve all draft versions for history\n- Use web search for up-to-date information when URLs are provided\n- If resources are insufficient, ask user for more or suggest additional research\n- Adapt tone based on target audience (technical, general, business, etc.)\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","frontmatter":{"name":"blog-draft","description":"Draft a blog post from ideas and resources. Use when users want to write a blog post, create content from research, or draft articles. Guides through research, brainstorming, outlining, and iterative drafting with version control."},"isInternal":false,"tokens":2136,"sizeBytes":8452},{"name":"SKILL.md","path":"03-skills/brand-voice/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/03-skills/brand-voice/SKILL.md","title":"brand-voice","category":"anthropic-skill","format":"markdown","content":"---\nname: brand-voice\ndescription: Ensure all communication matches brand voice and tone guidelines. Use when creating marketing copy, customer communications, public-facing content, or when users mention brand voice, tone, or writing style.\nuser-invocable: false\n---\n\n# Brand Voice Skill\n\n## Overview\nThis skill ensures all communications maintain consistent brand voice, tone, and messaging.\n\n## Brand Identity\n\n### Mission\nHelp teams automate their development workflows with AI\n\n### Values\n- **Simplicity**: Make complex things simple\n- **Reliability**: Rock-solid execution\n- **Empowerment**: Enable human creativity\n\n### Tone of Voice\n- **Friendly but professional** - approachable without being casual\n- **Clear and concise** - avoid jargon, explain technical concepts simply\n- **Confident** - we know what we're doing\n- **Empathetic** - understand user needs and pain points\n\n## Writing Guidelines\n\n### Do's ✅\n- Use \"you\" when addressing readers\n- Use active voice: \"Claude generates reports\" not \"Reports are generated by Claude\"\n- Start with value proposition\n- Use concrete examples\n- Keep sentences under 20 words\n- Use lists for clarity\n- Include calls-to-action\n\n### Don'ts ❌\n- Don't use corporate jargon\n- Don't patronize or oversimplify\n- Don't use \"we believe\" or \"we think\"\n- Don't use ALL CAPS except for emphasis\n- Don't create walls of text\n- Don't assume technical knowledge\n\n## Vocabulary\n\n### ✅ Preferred Terms\n- Claude (not \"the Claude AI\")\n- Code generation (not \"auto-coding\")\n- Agent (not \"bot\")\n- Streamline (not \"revolutionize\")\n- Integrate (not \"synergize\")\n\n### ❌ Avoid Terms\n- \"Cutting-edge\" (overused)\n- \"Game-changer\" (vague)\n- \"Leverage\" (corporate-speak)\n- \"Utilize\" (use \"use\")\n- \"Paradigm shift\" (unclear)\n\n## Examples\n\n### ✅ Good Example\n\"Claude automates your code review process. Instead of manually checking each PR, Claude reviews security, performance, and quality—saving your team hours every week.\"\n\nWhy it works: Clear value, specific benefits, action-oriented\n\n### ❌ Bad Example\n\"Claude leverages cutting-edge AI to provide comprehensive software development solutions.\"\n\nWhy it doesn't work: Vague, corporate jargon, no specific value\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","frontmatter":{"name":"brand-voice","description":"Ensure all communication matches brand voice and tone guidelines. Use when creating marketing copy, customer communications, public-facing content, or when users mention brand voice, tone, or writing style.","user-invocable":false},"isInternal":false,"tokens":613,"sizeBytes":2449},{"name":"SKILL.md","path":"03-skills/claude-md/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/03-skills/claude-md/SKILL.md","title":"claude-md","category":"anthropic-skill","format":"markdown","content":"---\nname: claude-md\ndescription: Create or update CLAUDE.md files following best practices for optimal AI agent onboarding\n---\n\n## User Input\n\n```text\n$ARGUMENTS\n```\n\nYou **MUST** consider the user input before proceeding (if not empty). User may specify:\n- `create` - Create new CLAUDE.md from scratch\n- `update` - Improve existing CLAUDE.md\n- `audit` - Analyze and report on current CLAUDE.md quality\n- A specific path to create/update (e.g., `src/api/CLAUDE.md` for directory-specific instructions)\n\n## Core Principles\n\n**LLMs are stateless**: CLAUDE.md is the main project file loaded into every conversation (alongside auto memory and unscoped rules). It serves as the primary onboarding document for AI agents into your codebase.\n\n### The Golden Rules\n\n1. **Less is More**: Frontier LLMs can follow ~150-200 instructions. Claude Code's system prompt already uses ~50. Keep your CLAUDE.md focused and concise.\n\n2. **Universal Applicability**: Only include information relevant to EVERY session. Task-specific instructions belong in separate files.\n\n3. **Don't Use Claude as a Linter**: Style guidelines bloat context and degrade instruction-following. Use deterministic tools (prettier, eslint, etc.) instead.\n\n4. **Never Auto-Generate**: CLAUDE.md is the highest leverage point of the AI harness. Craft it manually with careful consideration.\n\n## Execution Flow\n\n### 1. Project Analysis\n\nFirst, analyze the current project state:\n\n1. Check for existing CLAUDE.md files:\n   - Root level: `./CLAUDE.md` or `.claude/CLAUDE.md`\n   - Directory-specific: `**/CLAUDE.md`\n   - Global user config: `~/.claude/CLAUDE.md`\n\n2. Identify the project structure:\n   - Technology stack (languages, frameworks)\n   - Project type (monorepo, single app, library)\n   - Development tools (package manager, build system, test runner)\n\n3. Review existing documentation:\n   - README.md\n   - CONTRIBUTING.md\n   - package.json, pyproject.toml, Cargo.toml, etc.\n\n### 2. Content Strategy (WHAT, WHY, HOW)\n\nStructure CLAUDE.md around three dimensions:\n\n#### WHAT - Technology & Structure\n- Technology stack overview\n- Project organization (especially important for monorepos)\n- Key directories and their purposes\n\n#### WHY - Purpose & Context\n- What the project does\n- Why certain architectural decisions were made\n- What each major component is responsible for\n\n#### HOW - Workflow & Conventions\n- Development workflow (bun vs node, pip vs uv, etc.)\n- Testing procedures and commands\n- Verification and build methods\n- Critical \"gotchas\" or non-obvious requirements\n\n### 3. Progressive Disclosure Strategy\n\nFor larger projects, recommend creating an `agent_docs/` folder:\n\n```\nagent_docs/\n  |- building_the_project.md\n  |- running_tests.md\n  |- code_conventions.md\n  |- architecture_decisions.md\n```\n\nIn CLAUDE.md, reference these files with instructions like:\n```markdown\nFor detailed build instructions, refer to `agent_docs/building_the_project.md`\n```\n\n**Important**: Use `file:line` references instead of code snippets to avoid outdated context.\n\n### 4. Quality Constraints\n\nWhen creating or updating CLAUDE.md:\n\n1. **Target Length**: Keep it under 200 lines; shorter is better\n2. **No Style Rules**: Remove any linting/formatting instructions\n3. **No Task-Specific Instructions**: Move to separate files\n4. **No Code Snippets**: Use file references instead\n5. **No Redundant Information**: Don't repeat what's in package.json or README\n\n### 5. Essential Sections\n\nA well-structured CLAUDE.md should include:\n\n```markdown\n# Project Name\n\nBrief one-line description.\n\n## Tech Stack\n- Primary language and version\n- Key frameworks/libraries\n- Database/storage (if any)\n\n## Project Structure\n[Only for monorepos or complex structures]\n- `apps/` - Application entry points\n- `packages/` - Shared libraries\n\n## Development Commands\n- Install: `command`\n- Test: `command`\n- Build: `command`\n\n## Critical Conventions\n[Only non-obvious, high-impact conventions]\n- Convention 1 with brief explanation\n- Convention 2 with brief explanation\n\n## Known Issues / Gotchas\n[Things that consistently trip up developers]\n- Issue 1\n- Issue 2\n```\n\n### 6. Anti-Patterns to Avoid\n\n**DO NOT include:**\n- Code style guidelines (use linters)\n- Documentation on how to use Claude\n- Long explanations of obvious patterns\n- Copy-pasted code examples\n- Generic best practices (\"write clean code\")\n- Instructions for specific tasks\n- Auto-generated content\n- Extensive TODO lists\n\n### 7. Validation Checklist\n\nBefore finalizing, verify:\n\n- [ ] Kept under 200 lines; shorter is better\n- [ ] Every line applies to ALL sessions\n- [ ] No style/formatting rules\n- [ ] No code snippets (use file references)\n- [ ] Commands are verified to work\n- [ ] Progressive disclosure used for complex projects\n- [ ] Critical gotchas are documented\n- [ ] No redundancy with README.md\n\n## Output Format\n\n### For `create` or default:\n\n1. Analyze the project\n2. Draft a CLAUDE.md following the structure above\n3. Present the draft for review\n4. Write to the appropriate location after approval\n\n### For `update`:\n\n1. Read existing CLAUDE.md\n2. Audit against best practices\n3. Identify:\n   - Content to remove (style rules, code snippets, task-specific)\n   - Content to condense\n   - Missing essential information\n4. Present changes for review\n5. Apply changes after approval\n\n### For `audit`:\n\n1. Read existing CLAUDE.md\n2. Generate a report with:\n   - Current line count vs target\n   - Percentage of universally-applicable content\n   - List of anti-patterns found\n   - Recommendations for improvement\n3. Do NOT modify the file, only report\n\n## AGENTS.md Handling\n\nIf the user requests AGENTS.md creation/update:\n\n**Since v2.1.277, Claude Code reads `AGENTS.md` directly as project instructions** — but only when the working directory and every directory above it contain no `CLAUDE.md`, `.claude/CLAUDE.md`, or `CLAUDE.local.md`. `~/.claude/CLAUDE.md`, managed CLAUDE.md, and `.claude/rules/` do not count for that check and keep loading alongside. Which files are read is controlled by **Project instructions** in `/config`: `claude-md-or-agents-md` (default), `claude-md-and-agents-md`, `claude-md`, or `managed-only`. Where direct reading is unavailable — versions before v2.1.277 (before v2.1.281 on Bedrock/Vertex/Foundry, LLM gateways, or with telemetry disabled), or the first session after upgrading — fall back to importing it from CLAUDE.md with `@AGENTS.md`, or symlinking `CLAUDE.md` to it.\n\nAGENTS.md is a cross-tool project-context file — the same *category* of document as CLAUDE.md, not an agent-definition format. It exists so several coding agents can share one set of project conventions:\n- Build, test, and lint commands\n- Code style and architectural conventions\n- Repository layout and where things live\n\nSubagents are defined separately, in `.claude/agents/*.md` — not in AGENTS.md.\n\nApply similar principles:\n- Keep focused and concise\n- Use progressive disclosure\n- Reference external docs instead of embedding content\n\n## Notes\n\n- Always verify commands work before including them\n- When in doubt, leave it out - less is more\n- The system reminder tells Claude that CLAUDE.md \"may or may not be relevant\" - the more noise, the more it gets ignored\n- Monorepos benefit most from clear WHAT/WHY/HOW structure\n- Directory-specific CLAUDE.md files should be even more focused\n\n---\n\n**Last Updated**: October 18, 2026\n**Claude Code Version**: 2.1.302\n**Sources**:\n- https://code.claude.com/docs/en/skills\n- https://code.claude.com/docs/en/memory#agents-md\n- https://code.claude.com/docs/en/memory#when-agents-md-support-is-unavailable\n- https://code.claude.com/docs/en/memory\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","frontmatter":{"name":"claude-md","description":"Create or update CLAUDE.md files following best practices for optimal AI agent onboarding"},"isInternal":false,"tokens":1894,"sizeBytes":7763},{"name":"SKILL.md","path":"03-skills/code-review-specialist/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/03-skills/code-review-specialist/SKILL.md","title":"code-review-specialist","category":"anthropic-skill","format":"markdown","content":"---\nname: code-review-specialist\ndescription: Comprehensive code review with security, performance, and quality analysis. Use when users ask to review code, analyze code quality, evaluate pull requests, or mention code review, security analysis, or performance optimization.\n---\n\n# Code Review Skill\n\nThis skill provides comprehensive code review capabilities focusing on:\n\n1. **Security Analysis**\n   - Authentication/authorization issues\n   - Data exposure risks\n   - Injection vulnerabilities\n   - Cryptographic weaknesses\n   - Sensitive data logging\n\n2. **Performance Review**\n   - Algorithm efficiency (Big O analysis)\n   - Memory optimization\n   - Database query optimization\n   - Caching opportunities\n   - Concurrency issues\n\n3. **Code Quality**\n   - SOLID principles\n   - Design patterns\n   - Naming conventions\n   - Documentation\n   - Test coverage\n\n4. **Maintainability**\n   - Code readability\n   - Function size (should be < 50 lines)\n   - Cyclomatic complexity\n   - Dependency management\n   - Type safety\n\n## Reference Files\n\nThis skill includes supporting files that you should read when performing reviews:\n\n- **`templates/review-checklist.md`** — Structured checklist covering security, performance, quality, and testing. Read this file and use it as a guide to ensure no category is missed during review.\n- **`templates/finding-template.md`** — Standard template for documenting individual findings with severity, location, code examples, and impact analysis. Read this file and use its format when reporting issues.\n- **`scripts/analyze-metrics.py`** — Python script that calculates code metrics (function count, class count, average line length, complexity score). Run this on the file under review to gather quantitative data.\n- **`scripts/compare-complexity.py`** — Python script that compares cyclomatic and cognitive complexity between two versions of a file. Run this with the before and after versions when reviewing refactoring changes.\n\n## Review Template\n\nFor each piece of code reviewed, provide:\n\n### Summary\n- Overall quality assessment (1-5)\n- Key findings count\n- Recommended priority areas\n\n### Critical Issues (if any)\n- **Issue**: Clear description\n- **Location**: File and line number\n- **Impact**: Why this matters\n- **Severity**: Critical/High/Medium\n- **Fix**: Code example\n\n### Findings by Category\n\n#### Security (if issues found)\nList security vulnerabilities with examples\n\n#### Performance (if issues found)\nList performance problems with complexity analysis\n\n#### Quality (if issues found)\nList code quality issues with refactoring suggestions\n\n#### Maintainability (if issues found)\nList maintainability problems with improvements\n\n## Version History\n\n- v1.0.0 (2024-12-10): Initial release with security, performance, quality, and maintainability analysis\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","frontmatter":{"name":"code-review-specialist","description":"Comprehensive code review with security, performance, and quality analysis. Use when users ask to review code, analyze code quality, evaluate pull requests, or mention code review, security analysis, or performance optimization."},"isInternal":false,"tokens":668,"sizeBytes":3062},{"name":"SKILL.md","path":"03-skills/doc-generator/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/03-skills/doc-generator/SKILL.md","title":"doc-generator","category":"anthropic-skill","format":"markdown","content":"---\nname: doc-generator\ndescription: Generate comprehensive, accurate API documentation from source code. Use when creating or updating API documentation, generating OpenAPI specs, or when users mention API docs, endpoints, or documentation.\n---\n\n# API Documentation Generator Skill\n\n## Generates\n\n- OpenAPI/Swagger specifications\n- API endpoint documentation\n- SDK usage examples\n- Integration guides\n- Error code references\n- Authentication guides\n\n## Documentation Structure\n\n### For Each Endpoint\n\n````markdown\n## GET /api/v1/users/:id\n\n### Description\nBrief explanation of what this endpoint does\n\n### Parameters\n\n| Name | Type | Required | Description |\n|------|------|----------|-------------|\n| id | string | Yes | User ID |\n\n### Response\n\n**200 Success**\n```json\n{\n  \"id\": \"usr_123\",\n  \"name\": \"John Doe\",\n  \"email\": \"john@example.com\",\n  \"created_at\": \"2025-01-15T10:30:00Z\"\n}\n```\n\n**404 Not Found**\n```json\n{\n  \"error\": \"USER_NOT_FOUND\",\n  \"message\": \"User does not exist\"\n}\n```\n\n### Examples\n\n**cURL**\n```bash\ncurl -X GET \"https://api.example.com/api/v1/users/usr_123\" \\\n  -H \"Authorization: Bearer YOUR_TOKEN\"\n```\n\n**JavaScript**\n```javascript\nconst user = await fetch('/api/v1/users/usr_123', {\n  headers: { 'Authorization': 'Bearer token' }\n}).then(r => r.json());\n```\n\n**Python**\n```python\nresponse = requests.get(\n    'https://api.example.com/api/v1/users/usr_123',\n    headers={'Authorization': 'Bearer token'}\n)\nuser = response.json()\n```\n````\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","frontmatter":{"name":"doc-generator","description":"Generate comprehensive, accurate API documentation from source code. Use when creating or updating API documentation, generating OpenAPI specs, or when users mention API docs, endpoints, or documentation."},"isInternal":false,"tokens":459,"sizeBytes":1713},{"name":"code-smells.md","path":"03-skills/refactor/references/code-smells.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/03-skills/refactor/references/code-smells.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Code Smells Catalog\n\nA comprehensive reference of code smells based on Martin Fowler's *Refactoring* (2nd Edition). Code smells are symptoms of deeper problems—they indicate that something might be wrong with your code's design.\n\n> \"A code smell is a surface indication that usually corresponds to a deeper problem in the system.\" — Martin Fowler\n\n---\n\n## Bloaters\n\nCode smells representing something that has grown too large to be handled effectively.\n\n### Long Method\n\n**Signs:**\n- Method exceeds 30-50 lines\n- Need to scroll to see the whole method\n- Multiple levels of nesting\n- Comments explaining what sections do\n\n**Why it's bad:**\n- Hard to understand\n- Difficult to test in isolation\n- Changes have unintended consequences\n- Duplicate logic hides inside\n\n**Refactorings:**\n- Extract Method\n- Replace Temp with Query\n- Introduce Parameter Object\n- Replace Method with Method Object\n- Decompose Conditional\n\n**Example (Before):**\n```javascript\nfunction processOrder(order) {\n  // Validate order (20 lines)\n  if (!order.items) throw new Error('No items');\n  if (order.items.length === 0) throw new Error('Empty order');\n  // ... more validation\n\n  // Calculate totals (30 lines)\n  let subtotal = 0;\n  for (const item of order.items) {\n    subtotal += item.price * item.quantity;\n  }\n  // ... tax, shipping, discounts\n\n  // Send notifications (20 lines)\n  // ... email logic\n}\n```\n\n**Example (After):**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const totals = calculateOrderTotals(order);\n  sendOrderNotifications(order, totals);\n  return { order, totals };\n}\n```\n\n---\n\n### Large Class\n\n**Signs:**\n- Class has many instance variables (>7-10)\n- Class has many methods (>15-20)\n- Class name is vague (Manager, Handler, Processor)\n- Methods don't use all instance variables\n\n**Why it's bad:**\n- Violates Single Responsibility Principle\n- Hard to test\n- Changes ripple through unrelated features\n- Difficult to reuse parts\n\n**Refactorings:**\n- Extract Class\n- Extract Subclass\n- Extract Interface\n\n**Detection:**\n```\nLines of code > 300\nNumber of methods > 15\nNumber of fields > 10\n```\n\n---\n\n### Primitive Obsession\n\n**Signs:**\n- Using primitives for domain concepts (string for email, int for money)\n- Arrays of primitives instead of objects\n- String constants for type codes\n- Magic numbers/strings\n\n**Why it's bad:**\n- No validation at type level\n- Logic scattered across codebase\n- Easy to pass wrong values\n- Missing domain concepts\n\n**Refactorings:**\n- Replace Primitive with Object\n- Replace Type Code with Class\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**Example (Before):**\n```javascript\nconst user = {\n  email: 'john@example.com',     // Just a string\n  phone: '1234567890',           // Just a string\n  status: 'active',              // Magic string\n  balance: 10050                 // Cents as integer\n};\n```\n\n**Example (After):**\n```javascript\nconst user = {\n  email: new Email('john@example.com'),\n  phone: new PhoneNumber('1234567890'),\n  status: UserStatus.ACTIVE,\n  balance: Money.cents(10050)\n};\n```\n\n---\n\n### Long Parameter List\n\n**Signs:**\n- Methods with 4+ parameters\n- Parameters that always appear together\n- Boolean flags changing method behavior\n- Null/undefined passed frequently\n\n**Why it's bad:**\n- Hard to call correctly\n- Parameter order confusion\n- Indicates method doing too much\n- Hard to add new parameters\n\n**Refactorings:**\n- Introduce Parameter Object\n- Preserve Whole Object\n- Replace Parameter with Method Call\n- Remove Flag Argument\n\n**Example (Before):**\n```javascript\nfunction createUser(firstName, lastName, email, phone,\n                    street, city, state, zip,\n                    isAdmin, isActive, createdBy) {\n  // ...\n}\n```\n\n**Example (After):**\n```javascript\nfunction createUser(personalInfo, address, options) {\n  // personalInfo: { firstName, lastName, email, phone }\n  // address: { street, city, state, zip }\n  // options: { isAdmin, isActive, createdBy }\n}\n```\n\n---\n\n### Data Clumps\n\n**Signs:**\n- Same 3+ fields appear together repeatedly\n- Parameters that always travel together\n- Classes with field subsets belonging together\n\n**Why it's bad:**\n- Duplicate handling logic\n- Missing abstraction\n- Harder to extend\n- Indicates hidden class\n\n**Refactorings:**\n- Extract Class\n- Introduce Parameter Object\n- Preserve Whole Object\n\n**Example:**\n```javascript\n// Data clump: (x, y, z) coordinates\nfunction movePoint(x, y, z, dx, dy, dz) { }\nfunction scalePoint(x, y, z, factor) { }\nfunction distanceBetween(x1, y1, z1, x2, y2, z2) { }\n\n// Extract Point3D class\nclass Point3D {\n  constructor(x, y, z) { }\n  move(delta) { }\n  scale(factor) { }\n  distanceTo(other) { }\n}\n```\n\n---\n\n## Object-Orientation Abusers\n\nSmells indicating incomplete or incorrect use of OOP principles.\n\n### Switch Statements\n\n**Signs:**\n- Long switch/case or if/else chains\n- Same switch in multiple places\n- Switch on type codes\n- Adding new cases requires changes everywhere\n\n**Why it's bad:**\n- Violates Open/Closed Principle\n- Changes ripple to all switch locations\n- Hard to extend\n- Often indicates missing polymorphism\n\n**Refactorings:**\n- Replace Conditional with Polymorphism\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**Example (Before):**\n```javascript\nfunction calculatePay(employee) {\n  switch (employee.type) {\n    case 'hourly':\n      return employee.hours * employee.rate;\n    case 'salaried':\n      return employee.salary / 12;\n    case 'commissioned':\n      return employee.sales * employee.commission;\n  }\n}\n```\n\n**Example (After):**\n```javascript\nclass HourlyEmployee {\n  calculatePay() {\n    return this.hours * this.rate;\n  }\n}\n\nclass SalariedEmployee {\n  calculatePay() {\n    return this.salary / 12;\n  }\n}\n```\n\n---\n\n### Temporary Field\n\n**Signs:**\n- Instance variables only used in some methods\n- Fields set conditionally\n- Complex initialization for certain cases\n\n**Why it's bad:**\n- Confusing—field exists but might be null\n- Hard to understand object state\n- Indicates conditional logic hiding\n\n**Refactorings:**\n- Extract Class\n- Introduce Null Object\n- Replace Temp Field with Local\n\n---\n\n### Refused Bequest\n\n**Signs:**\n- Subclass doesn't use inherited methods/data\n- Subclass overrides to do nothing\n- Inheritance used for code reuse, not IS-A relationship\n\n**Why it's bad:**\n- Wrong abstraction\n- Violates Liskov Substitution Principle\n- Misleading hierarchy\n\n**Refactorings:**\n- Push Down Method/Field\n- Replace Subclass with Delegate\n- Replace Inheritance with Delegation\n\n---\n\n### Alternative Classes with Different Interfaces\n\n**Signs:**\n- Two classes that do similar things\n- Different method names for same concept\n- Could be used interchangeably\n\n**Why it's bad:**\n- Duplicate implementations\n- No common interface\n- Hard to switch between\n\n**Refactorings:**\n- Rename Method\n- Move Method\n- Extract Superclass\n- Extract Interface\n\n---\n\n## Change Preventers\n\nSmells that make changes difficult—changing one thing requires changing many others.\n\n### Divergent Change\n\n**Signs:**\n- One class changed for multiple different reasons\n- Changes in different areas trigger same class edits\n- Class is a \"God class\"\n\n**Why it's bad:**\n- Violates Single Responsibility\n- High change frequency\n- Merge conflicts\n\n**Refactorings:**\n- Extract Class\n- Extract Superclass\n- Extract Subclass\n\n**Example:**\nA `User` class changes for:\n- Authentication changes\n- Profile changes\n- Billing changes\n- Notification changes\n\n→ Extract: `AuthService`, `ProfileService`, `BillingService`, `NotificationService`\n\n---\n\n### Shotgun Surgery\n\n**Signs:**\n- One change requires edits in many classes\n- Small feature needs touching 10+ files\n- Changes are scattered, hard to find all\n\n**Why it's bad:**\n- Easy to miss a spot\n- High coupling\n- Changes are error-prone\n\n**Refactorings:**\n- Move Method\n- Move Field\n- Inline Class\n\n**Detection:**\nLook for: adding one field requires changes in >5 files.\n\n---\n\n### Parallel Inheritance Hierarchies\n\n**Signs:**\n- Creating subclass in one hierarchy requires subclass in another\n- Class prefixes match (e.g., `DatabaseOrder`, `DatabaseProduct`)\n\n**Why it's bad:**\n- Double the maintenance\n- Coupling between hierarchies\n- Easy to forget one side\n\n**Refactorings:**\n- Move Method\n- Move Field\n- Eliminate one hierarchy\n\n---\n\n## Dispensables\n\nSomething unnecessary that should be removed.\n\n### Comments (Excessive)\n\n**Signs:**\n- Comments explaining what code does\n- Commented-out code\n- TODO/FIXME that linger forever\n- Apologies in comments\n\n**Why it's bad:**\n- Comments lie (get out of sync)\n- Code should be self-documenting\n- Dead code causes confusion\n\n**Refactorings:**\n- Extract Method (name explains what)\n- Rename (clarity without comments)\n- Remove commented code\n- Introduce Assertion\n\n**Good vs Bad Comments:**\n```javascript\n// BAD: Explaining what\n// Loop through users and check if active\nfor (const user of users) {\n  if (user.status === 'active') { }\n}\n\n// GOOD: Explaining why\n// Active users only - inactive are handled by cleanup job\nconst activeUsers = users.filter(u => u.isActive);\n```\n\n---\n\n### Duplicate Code\n\n**Signs:**\n- Same code in multiple places\n- Similar code with small variations\n- Copy-paste patterns\n\n**Why it's bad:**\n- Bug fixes needed in multiple places\n- Inconsistency risk\n- Bloated codebase\n\n**Refactorings:**\n- Extract Method\n- Extract Class\n- Pull Up Method (in hierarchies)\n- Form Template Method\n\n**Detection Rule:**\nAny code duplicated 3+ times should be extracted.\n\n---\n\n### Lazy Class\n\n**Signs:**\n- Class doesn't do enough to justify existence\n- Wrapper with no added value\n- Result of over-engineering\n\n**Why it's bad:**\n- Maintenance overhead\n- Unnecessary indirection\n- Complexity without benefit\n\n**Refactorings:**\n- Inline Class\n- Collapse Hierarchy\n\n---\n\n### Dead Code\n\n**Signs:**\n- Unreachable code\n- Unused variables/methods/classes\n- Commented-out code\n- Code behind impossible conditions\n\n**Why it's bad:**\n- Confusion\n- Maintenance burden\n- Slows down understanding\n\n**Refactorings:**\n- Remove Dead Code\n- Safe Delete\n\n**Detection:**\n```bash\n# Look for unused exports\n# Look for unreferenced functions\n# IDE \"unused\" warnings\n```\n\n---\n\n### Speculative Generality\n\n**Signs:**\n- Abstract classes with one subclass\n- Unused parameters \"for future use\"\n- Methods that only delegate\n- \"Framework\" for one use case\n\n**Why it's bad:**\n- Complexity without benefit\n- YAGNI (You Ain't Gonna Need It)\n- Harder to understand\n\n**Refactorings:**\n- Collapse Hierarchy\n- Inline Class\n- Remove Parameter\n- Rename Method\n\n---\n\n## Couplers\n\nSmells that represent excessive coupling between classes.\n\n### Feature Envy\n\n**Signs:**\n- Method uses more data from another class than its own\n- Many getter calls to another object\n- Data and behavior are separated\n\n**Why it's bad:**\n- Wrong location for behavior\n- Poor encapsulation\n- Hard to maintain\n\n**Refactorings:**\n- Move Method\n- Move Field\n- Extract Method (then move)\n\n**Example (Before):**\n```javascript\nclass Order {\n  getDiscountedPrice(customer) {\n    // Uses customer data heavily\n    if (customer.loyaltyYears > 5) {\n      return this.price * customer.discountRate;\n    }\n    return this.price;\n  }\n}\n```\n\n**Example (After):**\n```javascript\nclass Customer {\n  getDiscountedPriceFor(price) {\n    if (this.loyaltyYears > 5) {\n      return price * this.discountRate;\n    }\n    return price;\n  }\n}\n```\n\n---\n\n### Inappropriate Intimacy\n\n**Signs:**\n- Classes access each other's private parts\n- Bidirectional references\n- Subclasses know too much about parents\n\n**Why it's bad:**\n- High coupling\n- Changes cascade\n- Hard to modify one without other\n\n**Refactorings:**\n- Move Method\n- Move Field\n- Change Bidirectional to Unidirectional\n- Extract Class\n- Hide Delegate\n\n---\n\n### Message Chains\n\n**Signs:**\n- Long chains of method calls: `a.getB().getC().getD().getValue()`\n- Client depends on navigation structure\n- \"Train wreck\" code\n\n**Why it's bad:**\n- Fragile—any change breaks chain\n- Violates Law of Demeter\n- Coupling to structure\n\n**Refactorings:**\n- Hide Delegate\n- Extract Method\n- Move Method\n\n**Example:**\n```javascript\n// Bad: Message chain\nconst managerName = employee.getDepartment().getManager().getName();\n\n// Better: Hide delegation\nconst managerName = employee.getManagerName();\n```\n\n---\n\n### Middle Man\n\n**Signs:**\n- Class that only delegates to another\n- Half the methods are delegations\n- No added value\n\n**Why it's bad:**\n- Unnecessary indirection\n- Maintenance overhead\n- Confusing architecture\n\n**Refactorings:**\n- Remove Middle Man\n- Inline Method\n\n---\n\n## Smell Severity Guide\n\n| Severity | Description | Action |\n|----------|-------------|--------|\n| **Critical** | Blocks development, causes bugs | Fix immediately |\n| **High** | Significant maintenance burden | Fix in current sprint |\n| **Medium** | Noticeable but manageable | Plan for near future |\n| **Low** | Minor inconvenience | Fix opportunistically |\n\n---\n\n## Quick Detection Checklist\n\nUse this checklist when scanning code:\n\n- [ ] Any method > 30 lines?\n- [ ] Any class > 300 lines?\n- [ ] Any method with > 4 parameters?\n- [ ] Any duplicated code blocks?\n- [ ] Any switch/case on type codes?\n- [ ] Any unused code?\n- [ ] Any methods using another class's data heavily?\n- [ ] Any long chains of method calls?\n- [ ] Any comments explaining \"what\" not \"why\"?\n- [ ] Any primitives that should be objects?\n\n---\n\n## Further Reading\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Kerievsky, J. (2004). *Refactoring to Patterns*\n- Feathers, M. (2004). *Working Effectively with Legacy Code*\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","isInternal":false,"tokens":3406,"sizeBytes":13848},{"name":"refactoring-catalog.md","path":"03-skills/refactor/references/refactoring-catalog.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/03-skills/refactor/references/refactoring-catalog.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Refactoring Catalog\n\nA curated catalog of refactoring techniques from Martin Fowler's *Refactoring* (2nd Edition). Each refactoring includes motivation, step-by-step mechanics, and examples.\n\n> \"A refactoring is defined by its mechanics—the precise sequence of steps that you follow to carry out the change.\" — Martin Fowler\n\n---\n\n## How to Use This Catalog\n\n1. **Identify the smell** using the code smells reference\n2. **Find the matching refactoring** in this catalog\n3. **Follow the mechanics** step by step\n4. **Test after each step** to ensure behavior is preserved\n\n**Golden Rule**: If any step takes more than 10 minutes, break it into smaller steps.\n\n---\n\n## Most Common Refactorings\n\n### Extract Method\n\n**When to use**: Long method, duplicate code, need to name a concept\n\n**Motivation**: Turn a code fragment into a method whose name explains the purpose.\n\n**Mechanics**:\n1. Create a new method named for what it does (not how)\n2. Copy the code fragment into the new method\n3. Scan for local variables used in the fragment\n4. Pass local variables as parameters (or declare in method)\n5. Handle return values appropriately\n6. Replace the original fragment with a call to the new method\n7. Test\n\n**Before**:\n```javascript\nfunction printOwing(invoice) {\n  let outstanding = 0;\n\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n\n  // Calculate outstanding\n  for (const order of invoice.orders) {\n    outstanding += order.amount;\n  }\n\n  // Print details\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n**After**:\n```javascript\nfunction printOwing(invoice) {\n  printBanner();\n  const outstanding = calculateOutstanding(invoice);\n  printDetails(invoice, outstanding);\n}\n\nfunction printBanner() {\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n}\n\nfunction calculateOutstanding(invoice) {\n  return invoice.orders.reduce((sum, order) => sum + order.amount, 0);\n}\n\nfunction printDetails(invoice, outstanding) {\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n---\n\n### Inline Method\n\n**When to use**: Method body is as clear as its name, excessive delegation\n\n**Motivation**: Remove needless indirection when the method doesn't add value.\n\n**Mechanics**:\n1. Check that the method isn't polymorphic\n2. Find all calls to the method\n3. Replace each call with the method body\n4. Test after each replacement\n5. Remove the method definition\n\n**Before**:\n```javascript\nfunction getRating(driver) {\n  return moreThanFiveLateDeliveries(driver) ? 2 : 1;\n}\n\nfunction moreThanFiveLateDeliveries(driver) {\n  return driver.numberOfLateDeliveries > 5;\n}\n```\n\n**After**:\n```javascript\nfunction getRating(driver) {\n  return driver.numberOfLateDeliveries > 5 ? 2 : 1;\n}\n```\n\n---\n\n### Extract Variable\n\n**When to use**: Complex expression that is hard to understand\n\n**Motivation**: Give a name to a piece of a complex expression.\n\n**Mechanics**:\n1. Ensure the expression has no side effects\n2. Declare an immutable variable\n3. Set it to the result of the expression (or part)\n4. Replace the original expression with the variable\n5. Test\n\n**Before**:\n```javascript\nreturn order.quantity * order.itemPrice -\n  Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +\n  Math.min(order.quantity * order.itemPrice * 0.1, 100);\n```\n\n**After**:\n```javascript\nconst basePrice = order.quantity * order.itemPrice;\nconst quantityDiscount = Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;\nconst shipping = Math.min(basePrice * 0.1, 100);\nreturn basePrice - quantityDiscount + shipping;\n```\n\n---\n\n### Inline Variable\n\n**When to use**: Variable name doesn't communicate more than the expression\n\n**Motivation**: Remove unnecessary indirection.\n\n**Mechanics**:\n1. Check that the right-hand side has no side effects\n2. If variable isn't immutable, make it so and test\n3. Find the first reference and replace with the expression\n4. Test\n5. Repeat for all references\n6. Remove the declaration and assignment\n7. Test\n\n---\n\n### Rename Variable\n\n**When to use**: Name doesn't clearly communicate purpose\n\n**Motivation**: Good names are crucial for clean code.\n\n**Mechanics**:\n1. If variable is widely used, consider encapsulating\n2. Find all references\n3. Change each reference\n4. Test\n\n**Tips**:\n- Use intention-revealing names\n- Avoid abbreviations\n- Use domain terminology\n\n```javascript\n// Bad\nconst d = 30;\nconst x = users.filter(u => u.a);\n\n// Good\nconst daysSinceLastLogin = 30;\nconst activeUsers = users.filter(user => user.isActive);\n```\n\n---\n\n### Change Function Declaration\n\n**When to use**: Function name doesn't explain purpose, parameters need change\n\n**Motivation**: Good function names make code self-documenting.\n\n**Mechanics (Simple)**:\n1. Remove parameters not needed\n2. Change the name\n3. Add parameters needed\n4. Test\n\n**Mechanics (Migration - for complex changes)**:\n1. If removing parameter, make sure it's not used\n2. Create new function with desired declaration\n3. Have old function call new function\n4. Test\n5. Change callers to use new function\n6. Test after each\n7. Remove old function\n\n**Before**:\n```javascript\nfunction circum(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n**After**:\n```javascript\nfunction circumference(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n---\n\n### Encapsulate Variable\n\n**When to use**: Direct access to data from multiple places\n\n**Motivation**: Provide a clear access point for data manipulation.\n\n**Mechanics**:\n1. Create getter and setter functions\n2. Find all references\n3. Replace reads with getter\n4. Replace writes with setter\n5. Test after each change\n6. Restrict visibility of the variable\n\n**Before**:\n```javascript\nlet defaultOwner = { firstName: \"Martin\", lastName: \"Fowler\" };\n\n// Used in many places\nspaceship.owner = defaultOwner;\n```\n\n**After**:\n```javascript\nlet defaultOwnerData = { firstName: \"Martin\", lastName: \"Fowler\" };\n\nfunction defaultOwner() { return defaultOwnerData; }\nfunction setDefaultOwner(arg) { defaultOwnerData = arg; }\n\nspaceship.owner = defaultOwner();\n```\n\n---\n\n### Introduce Parameter Object\n\n**When to use**: Several parameters that frequently go together\n\n**Motivation**: Group data that naturally belongs together.\n\n**Mechanics**:\n1. Create a new class/structure for the grouped parameters\n2. Test\n3. Use Change Function Declaration to add the new object\n4. Test\n5. For each parameter in the group, remove it from the function and use the new object\n6. Test after each\n\n**Before**:\n```javascript\nfunction amountInvoiced(startDate, endDate) { ... }\nfunction amountReceived(startDate, endDate) { ... }\nfunction amountOverdue(startDate, endDate) { ... }\n```\n\n**After**:\n```javascript\nclass DateRange {\n  constructor(start, end) {\n    this.start = start;\n    this.end = end;\n  }\n}\n\nfunction amountInvoiced(dateRange) { ... }\nfunction amountReceived(dateRange) { ... }\nfunction amountOverdue(dateRange) { ... }\n```\n\n---\n\n### Combine Functions into Class\n\n**When to use**: Several functions operate on the same data\n\n**Motivation**: Group functions with the data they operate on.\n\n**Mechanics**:\n1. Apply Encapsulate Record to the common data\n2. Move each function into the class\n3. Test after each move\n4. Replace data arguments with uses of class fields\n\n**Before**:\n```javascript\nfunction base(reading) { ... }\nfunction taxableCharge(reading) { ... }\nfunction calculateBaseCharge(reading) { ... }\n```\n\n**After**:\n```javascript\nclass Reading {\n  constructor(data) { this._data = data; }\n\n  get base() { ... }\n  get taxableCharge() { ... }\n  get calculateBaseCharge() { ... }\n}\n```\n\n---\n\n### Split Phase\n\n**When to use**: Code deals with two different things\n\n**Motivation**: Separate code into distinct phases with clear boundaries.\n\n**Mechanics**:\n1. Create a second function for the second phase\n2. Test\n3. Introduce an intermediate data structure between phases\n4. Test\n5. Extract first phase into its own function\n6. Test\n\n**Before**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  const shippingPerCase = (basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = quantity * shippingPerCase;\n  return basePrice - discount + shippingCost;\n}\n```\n\n**After**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const priceData = calculatePricingData(product, quantity);\n  return applyShipping(priceData, shippingMethod);\n}\n\nfunction calculatePricingData(product, quantity) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  return { basePrice, quantity, discount };\n}\n\nfunction applyShipping(priceData, shippingMethod) {\n  const shippingPerCase = (priceData.basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = priceData.quantity * shippingPerCase;\n  return priceData.basePrice - priceData.discount + shippingCost;\n}\n```\n\n---\n\n## Moving Features\n\n### Move Method\n\n**When to use**: Method uses more features of another class than its own\n\n**Motivation**: Put functions with the data they use most.\n\n**Mechanics**:\n1. Examine all program elements used by method in its class\n2. Check if method is polymorphic\n3. Copy method to target class\n4. Adjust for new context\n5. Make original method delegate to target\n6. Test\n7. Consider removing original method\n\n---\n\n### Move Field\n\n**When to use**: Field is used more by another class\n\n**Motivation**: Keep data with the functions that use it.\n\n**Mechanics**:\n1. Encapsulate the field if not already\n2. Test\n3. Create field in target\n4. Update references to use target field\n5. Test\n6. Remove original field\n\n---\n\n### Move Statements into Function\n\n**When to use**: Same code always appears with a function call\n\n**Motivation**: Remove duplication by moving repeated code into the function.\n\n**Mechanics**:\n1. Extract the repeated code into a function if not already\n2. Move statements into that function\n3. Test\n4. If callers no longer need standalone statements, remove them\n\n---\n\n### Move Statements to Callers\n\n**When to use**: Common behavior varies between callers\n\n**Motivation**: When behavior needs to differ, move it out of the function.\n\n**Mechanics**:\n1. Use Extract Method on the code to move\n2. Use Inline Method on the original function\n3. Remove the now-inlined call\n4. Move extracted code to each caller\n5. Test\n\n---\n\n## Organizing Data\n\n### Replace Primitive with Object\n\n**When to use**: Data item needs more behavior than simple value\n\n**Motivation**: Encapsulate data with its behavior.\n\n**Mechanics**:\n1. Apply Encapsulate Variable\n2. Create a simple value class\n3. Change the setter to create a new instance\n4. Change the getter to return the value\n5. Test\n6. Add richer behavior to the new class\n\n**Before**:\n```javascript\nclass Order {\n  constructor(data) {\n    this.priority = data.priority; // string: \"high\", \"rush\", etc.\n  }\n}\n\n// Usage\nif (order.priority === \"high\" || order.priority === \"rush\") { ... }\n```\n\n**After**:\n```javascript\nclass Priority {\n  constructor(value) {\n    if (!Priority.legalValues().includes(value))\n      throw new Error(`Invalid priority: ${value}`);\n    this._value = value;\n  }\n\n  static legalValues() { return ['low', 'normal', 'high', 'rush']; }\n  get value() { return this._value; }\n\n  higherThan(other) {\n    return Priority.legalValues().indexOf(this._value) >\n           Priority.legalValues().indexOf(other._value);\n  }\n}\n\n// Usage\nif (order.priority.higherThan(new Priority(\"normal\"))) { ... }\n```\n\n---\n\n### Replace Temp with Query\n\n**When to use**: Temporary variable holds result of an expression\n\n**Motivation**: Make the code clearer by extracting the expression into a function.\n\n**Mechanics**:\n1. Check that the variable is assigned only once\n2. Extract the assignment's right-hand side into a method\n3. Replace references to the temp with the method call\n4. Test\n5. Remove the temp declaration and assignment\n\n**Before**:\n```javascript\nconst basePrice = this._quantity * this._itemPrice;\nif (basePrice > 1000) {\n  return basePrice * 0.95;\n} else {\n  return basePrice * 0.98;\n}\n```\n\n**After**:\n```javascript\nget basePrice() {\n  return this._quantity * this._itemPrice;\n}\n\n// In the method\nif (this.basePrice > 1000) {\n  return this.basePrice * 0.95;\n} else {\n  return this.basePrice * 0.98;\n}\n```\n\n---\n\n## Simplifying Conditional Logic\n\n### Decompose Conditional\n\n**When to use**: Complex conditional (if-then-else) statement\n\n**Motivation**: Make the intention clear by extracting conditions and actions.\n\n**Mechanics**:\n1. Apply Extract Method on the condition\n2. Apply Extract Method on the then-branch\n3. Apply Extract Method on the else-branch (if present)\n\n**Before**:\n```javascript\nif (!aDate.isBefore(plan.summerStart) && !aDate.isAfter(plan.summerEnd)) {\n  charge = quantity * plan.summerRate;\n} else {\n  charge = quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n**After**:\n```javascript\nif (isSummer(aDate, plan)) {\n  charge = summerCharge(quantity, plan);\n} else {\n  charge = regularCharge(quantity, plan);\n}\n\nfunction isSummer(date, plan) {\n  return !date.isBefore(plan.summerStart) && !date.isAfter(plan.summerEnd);\n}\n\nfunction summerCharge(quantity, plan) {\n  return quantity * plan.summerRate;\n}\n\nfunction regularCharge(quantity, plan) {\n  return quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n---\n\n### Consolidate Conditional Expression\n\n**When to use**: Multiple conditions with the same result\n\n**Motivation**: Make it clear that conditions are a single check.\n\n**Mechanics**:\n1. Verify no side effects in conditions\n2. Combine conditions using `and` or `or`\n3. Consider Extract Method on the combined condition\n\n**Before**:\n```javascript\nif (employee.seniority < 2) return 0;\nif (employee.monthsDisabled > 12) return 0;\nif (employee.isPartTime) return 0;\n```\n\n**After**:\n```javascript\nif (isNotEligibleForDisability(employee)) return 0;\n\nfunction isNotEligibleForDisability(employee) {\n  return employee.seniority < 2 ||\n         employee.monthsDisabled > 12 ||\n         employee.isPartTime;\n}\n```\n\n---\n\n### Replace Nested Conditional with Guard Clauses\n\n**When to use**: Deeply nested conditionals making flow hard to follow\n\n**Motivation**: Use guard clauses for special cases, keeping normal flow clear.\n\n**Mechanics**:\n1. Find the special case conditions\n2. Replace them with guard clauses that return early\n3. Test after each change\n\n**Before**:\n```javascript\nfunction payAmount(employee) {\n  let result;\n  if (employee.isSeparated) {\n    result = { amount: 0, reasonCode: \"SEP\" };\n  } else {\n    if (employee.isRetired) {\n      result = { amount: 0, reasonCode: \"RET\" };\n    } else {\n      result = calculateNormalPay(employee);\n    }\n  }\n  return result;\n}\n```\n\n**After**:\n```javascript\nfunction payAmount(employee) {\n  if (employee.isSeparated) return { amount: 0, reasonCode: \"SEP\" };\n  if (employee.isRetired) return { amount: 0, reasonCode: \"RET\" };\n  return calculateNormalPay(employee);\n}\n```\n\n---\n\n### Replace Conditional with Polymorphism\n\n**When to use**: Switch/case based on type, conditional logic varying by type\n\n**Motivation**: Let objects handle their own behavior.\n\n**Mechanics**:\n1. Create class hierarchy (if not exists)\n2. Use Factory Function for object creation\n3. Move conditional logic into superclass method\n4. Create subclass method for each case\n5. Remove original conditional\n\n**Before**:\n```javascript\nfunction plumages(birds) {\n  return birds.map(b => plumage(b));\n}\n\nfunction plumage(bird) {\n  switch (bird.type) {\n    case 'EuropeanSwallow':\n      return \"average\";\n    case 'AfricanSwallow':\n      return (bird.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n    case 'NorwegianBlueParrot':\n      return (bird.voltage > 100) ? \"scorched\" : \"beautiful\";\n    default:\n      return \"unknown\";\n  }\n}\n```\n\n**After**:\n```javascript\nclass Bird {\n  get plumage() { return \"unknown\"; }\n}\n\nclass EuropeanSwallow extends Bird {\n  get plumage() { return \"average\"; }\n}\n\nclass AfricanSwallow extends Bird {\n  get plumage() {\n    return (this.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n  }\n}\n\nclass NorwegianBlueParrot extends Bird {\n  get plumage() {\n    return (this.voltage > 100) ? \"scorched\" : \"beautiful\";\n  }\n}\n\nfunction createBird(data) {\n  switch (data.type) {\n    case 'EuropeanSwallow': return new EuropeanSwallow(data);\n    case 'AfricanSwallow': return new AfricanSwallow(data);\n    case 'NorwegianBlueParrot': return new NorwegianBlueParrot(data);\n    default: return new Bird(data);\n  }\n}\n```\n\n---\n\n### Introduce Special Case (Null Object)\n\n**When to use**: Repeated null checks for special cases\n\n**Motivation**: Return a special object that handles the special case.\n\n**Mechanics**:\n1. Create special case class with expected interface\n2. Add isSpecialCase check\n3. Introduce factory method\n4. Replace null checks with special case object usage\n5. Test\n\n**Before**:\n```javascript\nconst customer = site.customer;\n// ... many places checking\nif (customer === \"unknown\") {\n  customerName = \"occupant\";\n} else {\n  customerName = customer.name;\n}\n```\n\n**After**:\n```javascript\nclass UnknownCustomer {\n  get name() { return \"occupant\"; }\n  get billingPlan() { return registry.defaultPlan; }\n}\n\n// Factory method\nfunction customer(site) {\n  return site.customer === \"unknown\"\n    ? new UnknownCustomer()\n    : site.customer;\n}\n\n// Usage - no null checks needed\nconst customerName = customer.name;\n```\n\n---\n\n## Refactoring APIs\n\n### Separate Query from Modifier\n\n**When to use**: Function both returns a value and has side effects\n\n**Motivation**: Make it clear which operations have side effects.\n\n**Mechanics**:\n1. Create a new query function\n2. Copy original function's return logic\n3. Modify original to return void\n4. Replace calls that use return value\n5. Test\n\n**Before**:\n```javascript\nfunction alertForMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") {\n      setOffAlarms();\n      return \"Don\";\n    }\n    if (p === \"John\") {\n      setOffAlarms();\n      return \"John\";\n    }\n  }\n  return \"\";\n}\n```\n\n**After**:\n```javascript\nfunction findMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") return \"Don\";\n    if (p === \"John\") return \"John\";\n  }\n  return \"\";\n}\n\nfunction alertForMiscreant(people) {\n  if (findMiscreant(people) !== \"\") setOffAlarms();\n}\n```\n\n---\n\n### Parameterize Function\n\n**When to use**: Several functions doing similar things with different values\n\n**Motivation**: Remove duplication by adding a parameter.\n\n**Mechanics**:\n1. Select one function\n2. Add parameter for the varying literal\n3. Change body to use the parameter\n4. Test\n5. Change callers to use the parameterized version\n6. Remove now-unused functions\n\n**Before**:\n```javascript\nfunction tenPercentRaise(person) {\n  person.salary = person.salary * 1.10;\n}\n\nfunction fivePercentRaise(person) {\n  person.salary = person.salary * 1.05;\n}\n```\n\n**After**:\n```javascript\nfunction raise(person, factor) {\n  person.salary = person.salary * (1 + factor);\n}\n\n// Usage\nraise(person, 0.10);\nraise(person, 0.05);\n```\n\n---\n\n### Remove Flag Argument\n\n**When to use**: Boolean parameter that changes function behavior\n\n**Motivation**: Make the behavior explicit through separate functions.\n\n**Mechanics**:\n1. Create explicit function for each flag value\n2. Replace each call with appropriate new function\n3. Test after each change\n4. Remove original function\n\n**Before**:\n```javascript\nfunction bookConcert(customer, isPremium) {\n  if (isPremium) {\n    // premium booking logic\n  } else {\n    // regular booking logic\n  }\n}\n\nbookConcert(customer, true);\nbookConcert(customer, false);\n```\n\n**After**:\n```javascript\nfunction bookPremiumConcert(customer) {\n  // premium booking logic\n}\n\nfunction bookRegularConcert(customer) {\n  // regular booking logic\n}\n\nbookPremiumConcert(customer);\nbookRegularConcert(customer);\n```\n\n---\n\n## Dealing with Inheritance\n\n### Pull Up Method\n\n**When to use**: Same method in multiple subclasses\n\n**Motivation**: Remove duplication in class hierarchy.\n\n**Mechanics**:\n1. Inspect methods to ensure they are identical\n2. Check signatures are the same\n3. Create new method in superclass\n4. Copy body from one subclass\n5. Delete one subclass method, test\n6. Delete other subclass methods, test each\n\n---\n\n### Push Down Method\n\n**When to use**: Behavior relevant only to a subset of subclasses\n\n**Motivation**: Put method where it's used.\n\n**Mechanics**:\n1. Copy method to each subclass that needs it\n2. Remove method from superclass\n3. Test\n4. Remove from subclasses that don't need it\n5. Test\n\n---\n\n### Replace Subclass with Delegate\n\n**When to use**: Inheritance is being used incorrectly, need more flexibility\n\n**Motivation**: Prefer composition over inheritance when appropriate.\n\n**Mechanics**:\n1. Create empty class for delegate\n2. Add field to host class holding delegate\n3. Create constructor for delegate, called from host\n4. Move features to delegate\n5. Test after each move\n6. Replace inheritance with delegation\n\n---\n\n## Extract Class\n\n**When to use**: Large class with multiple responsibilities\n\n**Motivation**: Split class to maintain single responsibility.\n\n**Mechanics**:\n1. Decide how to split responsibilities\n2. Create new class\n3. Move field from original to new class\n4. Test\n5. Move methods from original to new class\n6. Test after each move\n7. Review and rename both classes\n8. Decide how to expose new class\n\n**Before**:\n```javascript\nclass Person {\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get officeAreaCode() { return this._officeAreaCode; }\n  set officeAreaCode(arg) { this._officeAreaCode = arg; }\n  get officeNumber() { return this._officeNumber; }\n  set officeNumber(arg) { this._officeNumber = arg; }\n\n  get telephoneNumber() {\n    return `(${this._officeAreaCode}) ${this._officeNumber}`;\n  }\n}\n```\n\n**After**:\n```javascript\nclass Person {\n  constructor() {\n    this._telephoneNumber = new TelephoneNumber();\n  }\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get telephoneNumber() { return this._telephoneNumber.toString(); }\n  get officeAreaCode() { return this._telephoneNumber.areaCode; }\n  set officeAreaCode(arg) { this._telephoneNumber.areaCode = arg; }\n}\n\nclass TelephoneNumber {\n  get areaCode() { return this._areaCode; }\n  set areaCode(arg) { this._areaCode = arg; }\n  get number() { return this._number; }\n  set number(arg) { this._number = arg; }\n  toString() { return `(${this._areaCode}) ${this._number}`; }\n}\n```\n\n---\n\n## Quick Reference: Smell to Refactoring\n\n| Code Smell | Primary Refactoring | Alternative |\n|------------|-------------------|-------------|\n| Long Method | Extract Method | Replace Temp with Query |\n| Duplicate Code | Extract Method | Pull Up Method |\n| Large Class | Extract Class | Extract Subclass |\n| Long Parameter List | Introduce Parameter Object | Preserve Whole Object |\n| Feature Envy | Move Method | Extract Method + Move |\n| Data Clumps | Extract Class | Introduce Parameter Object |\n| Primitive Obsession | Replace Primitive with Object | Replace Type Code |\n| Switch Statements | Replace Conditional with Polymorphism | Replace Type Code |\n| Temporary Field | Extract Class | Introduce Null Object |\n| Message Chains | Hide Delegate | Extract Method |\n| Middle Man | Remove Middle Man | Inline Method |\n| Divergent Change | Extract Class | Split Phase |\n| Shotgun Surgery | Move Method | Inline Class |\n| Dead Code | Remove Dead Code | - |\n| Speculative Generality | Collapse Hierarchy | Inline Class |\n\n---\n\n## Further Reading\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Online catalog: https://refactoring.com/catalog/\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","isInternal":false,"tokens":5933,"sizeBytes":24313},{"name":"SKILL.md","path":"03-skills/refactor/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/03-skills/refactor/SKILL.md","title":"refactor","category":"anthropic-skill","format":"markdown","content":"---\nname: refactor\ndescription: Systematic code refactoring based on Martin Fowler's methodology. Use when users ask to refactor code, improve code structure, reduce technical debt, clean up legacy code, eliminate code smells, or improve code maintainability. This skill guides through a phased approach with research, planning, and safe incremental implementation.\n---\n\n# Code Refactoring Skill\n\nA systematic approach to refactoring code based on Martin Fowler's *Refactoring: Improving the Design of Existing Code* (2nd Edition). This skill emphasizes safe, incremental changes backed by tests.\n\n> \"Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure.\" — Martin Fowler\n\n## Core Principles\n\n1. **Behavior Preservation**: External behavior must remain unchanged\n2. **Small Steps**: Make tiny, testable changes\n3. **Test-Driven**: Tests are the safety net\n4. **Continuous**: Refactoring is ongoing, not a one-time event\n5. **Collaborative**: User approval required at each phase\n\n## Workflow Overview\n\n```\nPhase 1: Research & Analysis\n    ↓\nPhase 2: Test Coverage Assessment\n    ↓\nPhase 3: Code Smell Identification\n    ↓\nPhase 4: Refactoring Plan Creation\n    ↓\nPhase 5: Incremental Implementation\n    ↓\nPhase 6: Review & Iteration\n```\n\n---\n\n## Phase 1: Research & Analysis\n\n### Objectives\n- Understand the codebase structure and purpose\n- Identify the scope of refactoring\n- Gather context about business requirements\n\n### Questions to Ask User\nBefore starting, clarify:\n\n1. **Scope**: Which files/modules/functions need refactoring?\n2. **Goals**: What problems are you trying to solve? (readability, performance, maintainability)\n3. **Constraints**: Are there any areas that should NOT be changed?\n4. **Timeline pressure**: Is this blocking other work?\n5. **Test status**: Do tests exist? Are they passing?\n\n### Actions\n- [ ] Read and understand the target code\n- [ ] Identify dependencies and integrations\n- [ ] Document current architecture\n- [ ] Note any existing technical debt markers (TODOs, FIXMEs)\n\n### Output\nPresent findings to user:\n- Code structure summary\n- Identified problem areas\n- Initial recommendations\n- **Request approval to proceed**\n\n---\n\n## Phase 2: Test Coverage Assessment\n\n### Why Tests Matter\n> \"Refactoring without tests is like driving without a seatbelt.\" — Martin Fowler\n\nTests are the **key enabler** of safe refactoring. Without them, you risk introducing bugs.\n\n### Assessment Steps\n\n1. **Check for existing tests**\n   ```bash\n   # Look for test files\n   find . -name \"*test*\" -o -name \"*spec*\" | head -20\n   ```\n\n2. **Run existing tests**\n   ```bash\n   # JavaScript/TypeScript\n   npm test\n\n   # Python\n   pytest -v\n\n   # Java\n   mvn test\n   ```\n\n3. **Check coverage (if available)**\n   ```bash\n   # JavaScript\n   npm run test:coverage\n\n   # Python\n   pytest --cov=.\n   ```\n\n### Decision Point: Ask User\n\n**If tests exist and pass:**\n- Proceed to Phase 3\n\n**If tests are missing or incomplete:**\nPresent options:\n1. Write tests first (recommended)\n2. Add tests incrementally during refactoring\n3. Proceed without tests (risky - requires user acknowledgment)\n\n**If tests are failing:**\n- STOP. Fix failing tests before refactoring\n- Ask user: Should we fix tests first?\n\n### Test Writing Guidelines (if needed)\n\nFor each function being refactored, ensure tests cover:\n- Happy path (normal operation)\n- Edge cases (empty inputs, null, boundaries)\n- Error scenarios (invalid inputs, exceptions)\n\nUse the \"red-green-refactor\" cycle:\n1. Write failing test (red)\n2. Make it pass (green)\n3. Refactor\n\n---\n\n## Phase 3: Code Smell Identification\n\n### What Are Code Smells?\nSymptoms of deeper problems in code. They're not bugs, but indicators that the code could be improved.\n\n### Common Code Smells to Check\n\nSee [references/code-smells.md](references/code-smells.md) for the complete catalog.\n\n#### Quick Reference\n\n| Smell | Signs | Impact |\n|-------|-------|--------|\n| **Long Method** | Methods > 30-50 lines | Hard to understand, test, maintain |\n| **Duplicated Code** | Same logic in multiple places | Bug fixes needed in multiple places |\n| **Large Class** | Class with too many responsibilities | Violates Single Responsibility |\n| **Feature Envy** | Method uses another class's data more | Poor encapsulation |\n| **Primitive Obsession** | Overuse of primitives instead of objects | Missing domain concepts |\n| **Long Parameter List** | Methods with 4+ parameters | Hard to call correctly |\n| **Data Clumps** | Same data items appearing together | Missing abstraction |\n| **Switch Statements** | Complex switch/if-else chains | Hard to extend |\n| **Speculative Generality** | Code \"just in case\" | Unnecessary complexity |\n| **Dead Code** | Unused code | Confusion, maintenance burden |\n\n### Analysis Steps\n\n1. **Automated Analysis** (if scripts available)\n   ```bash\n   python scripts/detect-smells.py <file>\n   ```\n\n2. **Manual Review**\n   - Walk through code systematically\n   - Note each smell with location and severity\n   - Categorize by impact (Critical/High/Medium/Low)\n\n3. **Prioritization**\n   Focus on smells that:\n   - Block current development\n   - Cause bugs or confusion\n   - Affect most-changed code paths\n\n### Output: Smell Report\n\nPresent to user:\n- List of identified smells with locations\n- Severity assessment for each\n- Recommended priority order\n- **Request approval on priorities**\n\n---\n\n## Phase 4: Refactoring Plan Creation\n\n### Selecting Refactorings\n\nFor each smell, select an appropriate refactoring from the catalog.\n\nSee [references/refactoring-catalog.md](references/refactoring-catalog.md) for the complete list.\n\n#### Smell-to-Refactoring Mapping\n\n| Code Smell | Recommended Refactoring(s) |\n|------------|---------------------------|\n| Long Method | Extract Method, Replace Temp with Query |\n| Duplicated Code | Extract Method, Pull Up Method, Form Template Method |\n| Large Class | Extract Class, Extract Subclass |\n| Feature Envy | Move Method, Move Field |\n| Primitive Obsession | Replace Primitive with Object, Replace Type Code with Class |\n| Long Parameter List | Introduce Parameter Object, Preserve Whole Object |\n| Data Clumps | Extract Class, Introduce Parameter Object |\n| Switch Statements | Replace Conditional with Polymorphism |\n| Speculative Generality | Collapse Hierarchy, Inline Class, Remove Dead Code |\n| Dead Code | Remove Dead Code |\n\n### Plan Structure\n\nUse the template at [templates/refactoring-plan.md](templates/refactoring-plan.md).\n\nFor each refactoring:\n1. **Target**: What code will change\n2. **Smell**: What problem it addresses\n3. **Refactoring**: Which technique to apply\n4. **Steps**: Detailed micro-steps\n5. **Risks**: What could go wrong\n6. **Rollback**: How to undo if needed\n\n### Phased Approach\n\n**CRITICAL**: Introduce refactoring gradually in phases.\n\n**Phase A: Quick Wins** (Low risk, high value)\n- Rename variables for clarity\n- Extract obvious duplicate code\n- Remove dead code\n\n**Phase B: Structural Improvements** (Medium risk)\n- Extract methods from long functions\n- Introduce parameter objects\n- Move methods to appropriate classes\n\n**Phase C: Architectural Changes** (Higher risk)\n- Replace conditionals with polymorphism\n- Extract classes\n- Introduce design patterns\n\n### Decision Point: Present Plan to User\n\nBefore implementation:\n- Show complete refactoring plan\n- Explain each phase and its risks\n- Get explicit approval for each phase\n- **Ask**: \"Should I proceed with Phase A?\"\n\n---\n\n## Phase 5: Incremental Implementation\n\n### The Golden Rule\n> \"Change → Test → Green? → Commit → Next step\"\n\n### Implementation Rhythm\n\nFor each refactoring step:\n\n1. **Pre-check**\n   - Tests are passing (green)\n   - Code compiles\n\n2. **Make ONE small change**\n   - Follow the mechanics from the catalog\n   - Keep changes minimal\n\n3. **Verify**\n   - Run tests immediately\n   - Check for compilation errors\n\n4. **If tests pass (green)**\n   - Commit with descriptive message\n   - Move to next step\n\n5. **If tests fail (red)**\n   - STOP immediately\n   - Undo the change\n   - Analyze what went wrong\n   - Ask user if unclear\n\n### Commit Strategy\n\nEach commit should be:\n- **Atomic**: One logical change\n- **Reversible**: Easy to revert\n- **Descriptive**: Clear commit message\n\nExample commit messages:\n```\nrefactor: Extract calculateTotal() from processOrder()\nrefactor: Rename 'x' to 'customerCount' for clarity\nrefactor: Remove unused validateOldFormat() method\n```\n\n### Progress Reporting\n\nAfter each sub-phase, report to user:\n- Changes made\n- Tests still passing?\n- Any issues encountered\n- **Ask**: \"Continue with next batch?\"\n\n---\n\n## Phase 6: Review & Iteration\n\n### Post-Refactoring Checklist\n\n- [ ] All tests passing\n- [ ] No new warnings/errors\n- [ ] Code compiles successfully\n- [ ] Behavior unchanged (manual verification)\n- [ ] Documentation updated if needed\n- [ ] Commit history is clean\n\n### Metrics Comparison\n\nRun complexity analysis before and after:\n```bash\npython scripts/analyze-complexity.py <file>\n```\n\nPresent improvements:\n- Lines of code change\n- Cyclomatic complexity change\n- Maintainability index change\n\n### User Review\n\nPresent final results:\n- Summary of all changes\n- Before/after code comparison\n- Metrics improvements\n- Remaining technical debt\n- **Ask**: \"Are you satisfied with these changes?\"\n\n### Next Steps\n\nDiscuss with user:\n- Additional smells to address?\n- Schedule follow-up refactoring?\n- Apply similar changes elsewhere?\n\n---\n\n## Important Guidelines\n\n### When to STOP and Ask\n\nAlways pause and consult user when:\n- Unsure about business logic\n- Change might affect external APIs\n- Test coverage is inadequate\n- Significant architectural decision needed\n- Risk level increases\n- You encounter unexpected complexity\n\n### Safety Rules\n\n1. **Never refactor without tests** (unless user explicitly acknowledges risk)\n2. **Never make big changes** - break into tiny steps\n3. **Never skip the test run** after each change\n4. **Never continue if tests fail** - fix or rollback first\n5. **Never assume** - when in doubt, ask\n\n### What NOT to Do\n\n- Don't combine refactoring with feature additions\n- Don't refactor during production emergencies\n- Don't refactor code you don't understand\n- Don't over-engineer - keep it simple\n- Don't refactor everything at once\n\n---\n\n## Quick Start Example\n\n### Scenario: Long Method with Duplication\n\n**Before:**\n```javascript\nfunction processOrder(order) {\n  // 150 lines of code with:\n  // - Duplicated validation logic\n  // - Inline calculations\n  // - Mixed responsibilities\n}\n```\n\n**Refactoring Steps:**\n\n1. **Ensure tests exist** for processOrder()\n2. **Extract** validation into validateOrder()\n3. **Test** - should pass\n4. **Extract** calculation into calculateOrderTotal()\n5. **Test** - should pass\n6. **Extract** notification into notifyCustomer()\n7. **Test** - should pass\n8. **Review** - processOrder() now orchestrates 3 clear functions\n\n**After:**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const total = calculateOrderTotal(order);\n  notifyCustomer(order, total);\n  return { order, total };\n}\n```\n\n---\n\n## References\n\n- [Code Smells Catalog](references/code-smells.md) - Complete list of code smells\n- [Refactoring Catalog](references/refactoring-catalog.md) - Refactoring techniques\n- [Refactoring Plan Template](templates/refactoring-plan.md) - Planning template\n\n## Scripts\n\n- `scripts/analyze-complexity.py` - Analyze code complexity metrics\n- `scripts/detect-smells.py` - Automated smell detection\n\n## Version History\n\n- v1.0.0 (2025-01-15): Initial release with Fowler methodology, phased approach, user consultation points\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n","frontmatter":{"name":"refactor","description":"Systematic code refactoring based on Martin Fowler's methodology. Use when users ask to refactor code, improve code structure, reduce technical debt, clean up legacy code, eliminate code smells, or improve code maintainability. This skill guides through a phased approach with research, planning, and safe incremental implementation."},"isInternal":false,"tokens":2770,"sizeBytes":11944},{"name":"SKILL.md","path":"ja/03-skills/blog-draft/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/ja/03-skills/blog-draft/SKILL.md","title":"blog-draft","category":"anthropic-skill","format":"markdown","content":"<!-- i18n-source: 03-skills/blog-draft/SKILL.md -->\n<!-- i18n-source-sha: f396788 -->\n<!-- i18n-date: 2026-04-27 -->\n\n---\nname: blog-draft\ndescription: アイデアとリソースからブログ記事の下書きを作成する。ブログ記事の執筆、リサーチからのコンテンツ作成、記事の下書き作成時に使用する。リサーチ、ブレインストーミング、アウトライン作成、バージョン管理付きの反復的な下書き作成を案内する。\n---\n\n## ユーザー入力\n\n```text\n$ARGUMENTS\n```\n\n進める前にユーザー入力を**必ず**考慮する。ユーザーは以下を提供すべきである。\n- **Idea/Topic**: ブログ記事の主要なコンセプトやテーマ\n- **Resources**: URL、ファイル、リサーチ用の参考情報（任意だが推奨）\n- **Target audience**: ブログ記事の対象読者（任意）\n- **Tone/Style**: フォーマル、カジュアル、技術的、など（任意）\n\n**重要**: ユーザーが**既存のブログ記事**の更新を要求している場合、ステップ 0-8 をスキップして直接**ステップ 9**から開始する。まず既存の下書きファイルを読み、その後で反復プロセスを進める。\n\n## 実行フロー\n\n以下のステップを順次実行する。**ステップをスキップしたり、指示された箇所でユーザー承認なしに進めたりしてはならない。**\n\n### Step 0: プロジェクトフォルダの作成\n\n1. 次の形式でフォルダ名を生成する: `YYYY-MM-DD-short-topic-name`\n   - 今日の日付を使用\n   - トピックから短く URL フレンドリーなスラッグを作成（小文字、ハイフン、最大 5 単語）\n\n2. フォルダ構造を作成:\n   ```\n   blog-posts/\n   └── YYYY-MM-DD-short-topic-name/\n       └── resources/\n   ```\n\n3. 進める前にフォルダ作成をユーザーに確認する。\n\n### Step 1: リサーチとリソース収集\n\n1. ブログ記事ディレクトリ内に `resources/` サブフォルダを作成\n\n2. 提供された各リソースに対して:\n   - **URLs**: 取得して主要情報を `resources/` にマークダウンファイルとして保存\n   - **Files**: 読み込んで `resources/` に要約\n   - **Topics**: ウェブ検索を使用して最新情報を収集\n\n3. 各リソースについて、`resources/` に要約ファイルを作成:\n   - `resources/source-1-[short-name].md`\n   - `resources/source-2-[short-name].md`\n   - など\n\n4. 各要約には以下を含める:\n   ```markdown\n   # Source: [Title/URL]\n\n   ## Key Points\n   - Point 1\n   - Point 2\n\n   ## Relevant Quotes/Data\n   - Quote or statistic 1\n   - Quote or statistic 2\n\n   ## How This Relates to Topic\n   関連性の簡潔な説明\n   ```\n\n5. リサーチの要約をユーザーに提示する。\n\n### Step 2: ブレインストーミングと明確化\n\n1. アイデアとリサーチしたリソースに基づき、以下を提示:\n   - リサーチから特定された**主要テーマ**\n   - ブログ記事の**取りうる切り口**\n   - カバーすべき**重要ポイント**\n   - 明確化が必要な情報の**ギャップ**\n\n2. 明確化のための質問:\n   - 読者に持って帰ってほしい主要なテイクアウェイは何か？\n   - リサーチの中で特に強調したい点はあるか？\n   - 目標の長さは？（short: 500-800 words、medium: 1000-1500、long: 2000+）\n   - 除外したい点はあるか？\n\n3. **進める前にユーザー応答を待つ。**\n\n### Step 3: アウトライン提案\n\n1. 以下を含む構造化されたアウトラインを作成:\n\n   ```markdown\n   # Blog Post Outline: [Title]\n\n   ## Meta Information\n   - **Target Audience**: [who]\n   - **Tone**: [style]\n   - **Target Length**: [word count]\n   - **Main Takeaway**: [key message]\n\n   ## Proposed Structure\n\n   ### Hook/Introduction\n   - Opening hook idea\n   - Context setting\n   - Thesis statement\n\n   ### Section 1: [Title]\n   - Key point A\n   - Key point B\n   - Supporting evidence from [source]\n\n   ### Section 2: [Title]\n   - Key point A\n   - Key point B\n\n   [全セクションについて続ける...]\n\n   ### Conclusion\n   - Summary of key points\n   - Call to action or final thought\n\n   ## Sources to Cite\n   - Source 1\n   - Source 2\n   ```\n\n2. アウトラインをユーザーに提示し、**承認または修正を求める**。\n\n### Step 4: 承認されたアウトラインの保存\n\n1. ユーザーがアウトラインを承認したら、ブログ記事フォルダ内の `OUTLINE.md` に保存する。\n\n2. アウトラインが保存されたことを確認する。\n\n### Step 5: アウトラインのコミット（git リポジトリの場合）\n\n1. カレントディレクトリが git リポジトリかどうか確認する。\n\n2. はいの場合:\n   - 新しいファイル（ブログ記事フォルダ、resources、OUTLINE.md）をステージング\n   - 次のメッセージでコミットを作成: `docs: Add outline for blog post - [topic-name]`\n   - リモートへプッシュ\n\n3. git リポジトリでない場合は、このステップをスキップしユーザーに伝える。\n\n### Step 6: 下書き作成\n\n1. 承認されたアウトラインに基づき、ブログ記事の下書き全文を作成する。\n\n2. OUTLINE.md の構造に厳密に従う。\n\n3. 含めるもの:\n   - フック付きの魅力的な導入\n   - 明確なセクション見出し\n   - リサーチからの裏付けとなる証拠と例\n   - セクション間の滑らかな遷移\n   - テイクアウェイのある力強い結論\n   - **Citations**: すべての比較、統計、データポイント、事実主張は元のソースを必ず引用すること\n\n4. 下書きをブログ記事フォルダ内に `draft-v0.1.md` として保存する。\n\n5. フォーマット:\n   ```markdown\n   # [Blog Post Title]\n\n   *[Optional: subtitle or tagline]*\n\n   [インライン引用付きの本文...]\n\n   ---\n\n   ## References\n   - [1] Source 1 Title - URL or Citation\n   - [2] Source 2 Title - URL or Citation\n   - [3] Source 3 Title - URL or Citation\n   ```\n\n6. **引用要件**:\n   - すべてのデータポイント、統計、比較にはインライン引用を必ず付ける\n   - [1]、[2] などの番号引用、または [Source Name] のような名前付き引用を使用\n   - 引用を末尾の References セクションへリンクする\n   - 例: \"Studies show that 65% of developers prefer TypeScript [1]\"\n   - 例: \"React outperforms Vue in rendering speed by 20% [React Benchmarks 2024]\"\n\n### Step 7: 下書きのコミット（git リポジトリの場合）\n\n1. git リポジトリかどうか確認する。\n\n2. はいの場合:\n   - 下書きファイルをステージング\n   - 次のメッセージでコミットを作成: `docs: Add draft v0.1 for blog post - [topic-name]`\n   - リモートへプッシュ\n\n3. git リポジトリでない場合は、スキップしてユーザーに伝える。\n\n### Step 8: レビュー用に下書きを提示\n\n1. 下書きの内容をユーザーに提示する。\n\n2. フィードバックを求める:\n   - 全体の印象は？\n   - 拡張または削減が必要なセクションは？\n   - トーン調整は必要か？\n   - 不足している情報は？\n   - 具体的な編集や書き直しは？\n\n3. **ユーザー応答を待つ。**\n\n### Step 9: 反復または最終化\n\n**ユーザーが変更を要求した場合:**\n1. すべての要望を記録する\n2. 以下の調整を加えてステップ 6 へ戻る:\n   - バージョン番号を増加（v0.2、v0.3 など）\n   - すべてのフィードバックを反映\n   - `draft-v[X.Y].md` として保存\n   - ステップ 7-8 を繰り返す\n\n**ユーザーが承認した場合:**\n1. 最終下書きのバージョンを確認\n2. ユーザーが要求すれば任意で `final.md` にリネーム\n3. ブログ記事作成プロセスを要約:\n   - 作成したバージョンの総数\n   - バージョン間の主要な変更\n   - 最終ワード数\n   - 作成したファイル\n\n## バージョン追跡\n\nすべての下書きは段階的なバージョン番号付きで保持する:\n- `draft-v0.1.md` - 初回下書き\n- `draft-v0.2.md` - 1 回目のフィードバック反映後\n- `draft-v0.3.md` - 2 回目のフィードバック反映後\n- など\n\nこれによりブログ記事の進化を追跡し、必要に応じて差し戻すことができる。\n\n## 出力ファイル構造\n\n```\nblog-posts/\n└── YYYY-MM-DD-topic-name/\n    ├── resources/\n    │   ├── source-1-name.md\n    │   ├── source-2-name.md\n    │   └── ...\n    ├── OUTLINE.md\n    ├── draft-v0.1.md\n    ├── draft-v0.2.md (反復した場合)\n    └── draft-v0.3.md (さらに反復した場合)\n```\n\n## 品質のためのヒント\n\n- **Hook**: 質問、意外な事実、共感できるシナリオで始める\n- **Flow**: 各段落は次の段落と接続させる\n- **Evidence**: リサーチデータで主張を裏付ける\n- **Citations**: 以下については必ずソースを引用する:\n  - すべての統計とデータポイント（例: \"According to [Source], 75% of...\"）\n  - 製品、サービス、アプローチ間の比較（例: \"X performs 2x faster than Y [Source]\"）\n  - 市場トレンド、リサーチ結果、ベンチマークについての事実主張\n  - 形式: [Source Name] または [Author, Year] のインライン引用を使用\n- **Voice**: 全体を通じて一貫したトーンを保つ\n- **Length**: 目標ワード数を尊重\n- **Readability**: 短い段落、適切な箇所での箇条書きを使用\n- **CTA**: 明確な CTA または考えさせる問いで終える\n\n## 注意事項\n\n- 指定されたチェックポイントでは必ずユーザー承認を待つ\n- 履歴のためすべての下書きバージョンを保持する\n- URL が提供された場合は最新情報のためウェブ検索を使用する\n- リソースが不十分な場合はユーザーに追加を求めるか、追加リサーチを提案する\n- 対象読者（技術系、一般、ビジネスなど）に応じてトーンを適応させる\n","isInternal":false,"tokens":3653,"sizeBytes":10270},{"name":"SKILL.md","path":"ja/03-skills/brand-voice/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/ja/03-skills/brand-voice/SKILL.md","title":"brand-voice","category":"anthropic-skill","format":"markdown","content":"<!-- i18n-source: 03-skills/brand-voice/SKILL.md -->\n<!-- i18n-source-sha: a6380d8 -->\n<!-- i18n-date: 2026-04-27 -->\n\n---\nname: brand-voice\ndescription: すべてのコミュニケーションがブランドボイスとトーンのガイドラインに沿うことを保証する。マーケティングコピー、顧客向け連絡、公開コンテンツの作成時、またはブランドボイス、トーン、文体について言及がある場合に使用する。\nuser-invocable: false\n---\n\n# ブランドボイス・スキル\n\n## 概要\nこのスキルは、すべてのコミュニケーションにおいて一貫したブランドボイス、トーン、メッセージングを維持する。\n\n## ブランドアイデンティティ\n\n### ミッション\nチームが AI で開発ワークフローを自動化することを支援する\n\n### バリュー\n- **シンプリシティ**: 複雑なものをシンプルにする\n- **信頼性**: 揺るぎない実行\n- **エンパワーメント**: 人間の創造性を引き出す\n\n### トーン・オブ・ボイス\n- **フレンドリーかつプロフェッショナル** - カジュアルにならず、親しみやすい\n- **明快で簡潔** - 専門用語を避け、技術的な概念をわかりやすく説明する\n- **自信を持って** - 自分たちが何をしているかを理解している\n- **共感的** - ユーザーのニーズと痛みを理解する\n\n## 執筆ガイドライン\n\n### やるべきこと ✅\n- 読者を指す際には「you」を使用\n- 能動態を使用: 「Claude generates reports」とし、「Reports are generated by Claude」としない\n- 価値提案から始める\n- 具体例を用いる\n- 1 文を 20 語未満に保つ\n- 明確化のためリストを使用\n- CTA（行動喚起）を含める\n\n### 避けるべきこと ❌\n- 企業ジャーゴンを使わない\n- 見下したり過度に単純化したりしない\n- 「we believe」や「we think」を使わない\n- 強調以外で全大文字を使わない\n- 文章の壁を作らない\n- 技術的な前提知識を仮定しない\n\n## ボキャブラリー\n\n### ✅ 推奨用語\n- Claude（「the Claude AI」ではなく）\n- Code generation（「auto-coding」ではなく）\n- Agent（「bot」ではなく）\n- Streamline（「revolutionize」ではなく）\n- Integrate（「synergize」ではなく）\n\n### ❌ 避ける用語\n- 「Cutting-edge」（使い古されている）\n- 「Game-changer」（曖昧）\n- 「Leverage」（企業用語的）\n- 「Utilize」（「use」を使う）\n- 「Paradigm shift」（不明瞭）\n\n## 例\n\n### ✅ 良い例\n\"Claude automates your code review process. Instead of manually checking each PR, Claude reviews security, performance, and quality—saving your team hours every week.\"\n\nなぜ機能するか: 明確な価値、具体的なメリット、行動志向\n\n### ❌ 悪い例\n\"Claude leverages cutting-edge AI to provide comprehensive software development solutions.\"\n\nなぜ機能しないか: 曖昧、企業ジャーゴン、具体的な価値がない\n","isInternal":false,"tokens":1085,"sizeBytes":3094},{"name":"SKILL.md","path":"ja/03-skills/claude-md/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/ja/03-skills/claude-md/SKILL.md","title":"claude-md","category":"anthropic-skill","format":"markdown","content":"<!-- i18n-source: 03-skills/claude-md/SKILL.md -->\n<!-- i18n-source-sha: f78c094 -->\n<!-- i18n-date: 2026-04-27 -->\n---\nname: claude-md\ndescription: Create or update CLAUDE.md files following best practices for optimal AI agent onboarding\n---\n\n## ユーザー入力\n\n```text\n$ARGUMENTS\n```\n\nユーザー入力が空でない場合、進める前に **必ず** 内容を考慮すること。ユーザーは以下を指定する場合がある:\n- `create` - 新しい CLAUDE.md をゼロから作成\n- `update` - 既存 CLAUDE.md を改善\n- `audit` - 現在の CLAUDE.md の品質を分析しレポート\n- 作成・更新する具体的なパス（例: ディレクトリ固有命令向けの `src/api/CLAUDE.md`）\n\n## 基本原則\n\n**LLM はステートレス**: CLAUDE.md は、すべての会話に読み込まれる主要なプロジェクトファイルである（自動メモリやスコープなしのルールと並んで読み込まれる）。コードベースに対する AI エージェントの主要なオンボーディングドキュメントとして機能する。\n\n### ゴールデンルール\n\n1. **少ないほど良い**: フロンティア LLM は約 150〜200 個の命令に従える。Claude Code のシステムプロンプトはすでに約 50 個を使用している。CLAUDE.md は焦点を絞り簡潔に保つこと。\n\n2. **普遍的な適用性**: あらゆるセッションに関係する情報のみを含める。タスク固有の命令は別ファイルに置く。\n\n3. **Claude をリンターとして使わない**: スタイルガイドラインはコンテキストを膨張させ命令の遵守を低下させる。代わりに決定論的なツール（prettier, eslint など）を使う。\n\n4. **絶対に自動生成しない**: CLAUDE.md は AI ハーネスにおける最も影響力の高いポイントである。慎重に手作業で作り上げること。\n\n## 実行フロー\n\n### 1. プロジェクト分析\n\nまず現在のプロジェクト状態を分析する:\n\n1. 既存の CLAUDE.md ファイルを確認:\n   - ルートレベル: `./CLAUDE.md` または `.claude/CLAUDE.md`\n   - ディレクトリ固有: `**/CLAUDE.md`\n   - グローバルユーザー設定: `~/.claude/CLAUDE.md`\n\n2. プロジェクト構造を特定:\n   - 技術スタック（言語、フレームワーク）\n   - プロジェクト種別（モノレポ、単一アプリ、ライブラリ）\n   - 開発ツール（パッケージマネージャー、ビルドシステム、テストランナー）\n\n3. 既存ドキュメントをレビュー:\n   - README.md\n   - CONTRIBUTING.md\n   - package.json, pyproject.toml, Cargo.toml など\n\n### 2. コンテンツ戦略（WHAT, WHY, HOW）\n\nCLAUDE.md を 3 つの観点で構成する:\n\n#### WHAT - 技術と構造\n- 技術スタックの概要\n- プロジェクトの編成（モノレポでは特に重要）\n- 主要ディレクトリとその目的\n\n#### WHY - 目的と背景\n- プロジェクトが何をするか\n- なぜ特定の設計判断が下されたのか\n- 各主要コンポーネントが何を担当するか\n\n#### HOW - ワークフローと規約\n- 開発ワークフロー（bun と node、pip と uv など）\n- テスト手順とコマンド\n- 検証およびビルド手段\n- 重要な「ハマりどころ」や明示されない要件\n\n### 3. プログレッシブディスクロージャ戦略\n\n大規模プロジェクトでは `agent_docs/` フォルダの作成を推奨する:\n\n```\nagent_docs/\n  |- building_the_project.md\n  |- running_tests.md\n  |- code_conventions.md\n  |- architecture_decisions.md\n```\n\nCLAUDE.md からは以下のような命令でこれらのファイルを参照する:\n```markdown\nFor detailed build instructions, refer to `agent_docs/building_the_project.md`\n```\n\n**重要**: 古くなるコンテキストを避けるため、コードスニペットではなく `file:line` 参照を用いる。\n\n### 4. 品質制約\n\nCLAUDE.md を作成・更新する際:\n\n1. **目標の長さ**: 200 行未満\n2. **スタイルルールなし**: lint やフォーマットの命令は除く\n3. **タスク固有命令なし**: 別ファイルへ移す\n4. **コードスニペットなし**: ファイル参照を用いる\n5. **冗長情報なし**: package.json や README にあるものを繰り返さない\n\n### 5. 必須セクション\n\n良く構成された CLAUDE.md には以下を含めるべきである:\n\n```markdown\n# Project Name\n\nBrief one-line description.\n\n## Tech Stack\n- Primary language and version\n- Key frameworks/libraries\n- Database/storage (if any)\n\n## Project Structure\n[Only for monorepos or complex structures]\n- `apps/` - Application entry points\n- `packages/` - Shared libraries\n\n## Development Commands\n- Install: `command`\n- Test: `command`\n- Build: `command`\n\n## Critical Conventions\n[Only non-obvious, high-impact conventions]\n- Convention 1 with brief explanation\n- Convention 2 with brief explanation\n\n## Known Issues / Gotchas\n[Things that consistently trip up developers]\n- Issue 1\n- Issue 2\n```\n\n### 6. 避けるべきアンチパターン\n\n**含めてはいけないもの:**\n- コードスタイルガイドライン（リンターを使う）\n- Claude の使い方に関するドキュメント\n- 自明なパターンへの長い説明\n- コピー＆ペーストされたコード例\n- 一般的なベストプラクティス（\"write clean code\"）\n- 特定タスク向けの命令\n- 自動生成された内容\n- 大量の TODO リスト\n\n### 7. 検証チェックリスト\n\n最終化前に確認:\n\n- [ ] 200 行未満\n- [ ] すべての行があらゆるセッションに適用される\n- [ ] スタイルやフォーマットのルールがない\n- [ ] コードスニペットがない（ファイル参照を使う）\n- [ ] コマンドが動作することを検証済み\n- [ ] 複雑なプロジェクトでプログレッシブディスクロージャを利用\n- [ ] 重要なハマりどころがドキュメント化されている\n- [ ] README.md と内容が重複していない\n\n## 出力形式\n\n### `create` または既定の場合:\n\n1. プロジェクトを分析する\n2. 上記の構造に従って CLAUDE.md の草案を作る\n3. 草案をレビュー用に提示する\n4. 承認後、適切な場所へ書き込む\n\n### `update` の場合:\n\n1. 既存 CLAUDE.md を読む\n2. ベストプラクティスに照らして監査する\n3. 以下を特定する:\n   - 削除する内容（スタイルルール、コードスニペット、タスク固有）\n   - 凝縮する内容\n   - 不足している必須情報\n4. 変更内容をレビュー用に提示する\n5. 承認後、変更を適用する\n\n### `audit` の場合:\n\n1. 既存 CLAUDE.md を読む\n2. 以下を含むレポートを生成する:\n   - 現在の行数と目標値\n   - 普遍的に適用可能なコンテンツの割合\n   - 検出されたアンチパターンの一覧\n   - 改善のための推奨\n3. ファイルを変更しない、レポートのみを行う\n\n## AGENTS.md の取り扱い\n\nユーザーが AGENTS.md の作成・更新を求めた場合:\n\n**v2.1.277 以降、Claude Code は `AGENTS.md` をプロジェクト指示として直接読み込む。** ただし、作業ディレクトリとその上位すべてのディレクトリに `CLAUDE.md`、`.claude/CLAUDE.md`、`CLAUDE.local.md` のいずれも存在しない場合に限る。`~/.claude/CLAUDE.md`、管理 CLAUDE.md、`.claude/rules/` はこの判定の対象外であり、引き続き併せて読み込まれる。この挙動は `/config` の **Project instructions** で制御する: `claude-md-or-agents-md`（デフォルト）、`claude-md-and-agents-md`、`claude-md`、`managed-only`。直接読み込みが利用できない環境 — v2.1.277 より前のバージョン（Bedrock/Vertex/Foundry、LLM ゲートウェイ、テレメトリ無効の場合は v2.1.281 より前）、またはアップグレード後の最初のセッション — では、CLAUDE.md から `@AGENTS.md` でインポートするか、`CLAUDE.md` をこのファイルへのシンボリックリンクにするフォールバックを使う。\n\nAGENTS.md はツール横断のプロジェクトコンテキストファイルであり、CLAUDE.md と同じ *種類* のドキュメントである。エージェント定義フォーマットではない。複数のコーディングエージェントが 1 つのプロジェクト規約を共有できるようにするために存在する:\n- ビルド、テスト、リントのコマンド\n- コードスタイルとアーキテクチャ上の規約\n- リポジトリの構成と各要素の所在\n\nサブエージェントは AGENTS.md ではなく、`.claude/agents/*.md` で別途定義する。\n\n同様の原則を適用する:\n- 焦点を絞り簡潔に保つ\n- プログレッシブディスクロージャを用いる\n- 内容を埋め込むのではなく外部ドキュメントを参照する\n\n## 注意事項\n\n- コマンドを含める前に必ず動作確認する\n- 迷ったら省略する。少ないほど良い\n- システムリマインダーは Claude に対して CLAUDE.md は「関係があるかどうかわからない」と告げている。ノイズが多いほど無視されやすい\n- モノレポは明確な WHAT/WHY/HOW 構造の恩恵が最も大きい\n- ディレクトリ固有の CLAUDE.md ファイルはさらに焦点を絞るべきである\n\n---\n\n**最終更新**: 2026 年 10 月 18 日\n**Claude Code バージョン**: 2.1.302\n**Sources**:\n- https://code.claude.com/docs/en/memory\n","isInternal":false,"tokens":3486,"sizeBytes":9614},{"name":"SKILL.md","path":"ja/03-skills/code-review-specialist/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/ja/03-skills/code-review-specialist/SKILL.md","title":"code-review-specialist","category":"anthropic-skill","format":"markdown","content":"<!-- i18n-source: 03-skills/code-review-specialist/SKILL.md -->\n<!-- i18n-source-sha: e978c49 -->\n<!-- i18n-date: 2026-04-27 -->\n\n---\nname: code-review-specialist\ndescription: セキュリティ、パフォーマンス、品質分析を含む包括的なコードレビュー。コードレビュー、コード品質分析、プルリクエスト評価の依頼があった場合、またはコードレビュー、セキュリティ分析、パフォーマンス最適化について言及がある場合に使用する。\n---\n\n# コードレビュー・スキル\n\nこのスキルは、以下に焦点を当てた包括的なコードレビュー機能を提供する。\n\n1. **セキュリティ分析**\n   - 認証・認可の問題\n   - データ漏洩リスク\n   - インジェクション脆弱性\n   - 暗号の弱点\n   - 機密データのロギング\n\n2. **パフォーマンス・レビュー**\n   - アルゴリズム効率（Big O 分析）\n   - メモリ最適化\n   - データベースクエリ最適化\n   - キャッシュ機会\n   - 並行性の問題\n\n3. **コード品質**\n   - SOLID 原則\n   - デザインパターン\n   - 命名規則\n   - ドキュメント\n   - テストカバレッジ\n\n4. **保守性**\n   - コードの可読性\n   - 関数サイズ（50 行未満が望ましい）\n   - 循環的複雑度\n   - 依存関係管理\n   - 型安全性\n\n## レビュー・テンプレート\n\nレビューしたコードごとに、以下を提供する。\n\n### サマリー\n- 全体品質評価（1-5）\n- 主要な指摘件数\n- 推奨される優先領域\n\n### クリティカルな問題（あれば）\n- **Issue**: 明確な説明\n- **Location**: ファイルと行番号\n- **Impact**: なぜ重要か\n- **Severity**: Critical/High/Medium\n- **Fix**: コード例\n\n### カテゴリ別の指摘事項\n\n#### セキュリティ（問題が見つかった場合）\nセキュリティ脆弱性を例示しながら列挙\n\n#### パフォーマンス（問題が見つかった場合）\n複雑度分析を含めパフォーマンス問題を列挙\n\n#### 品質（問題が見つかった場合）\nリファクタリング提案を含めコード品質の問題を列挙\n\n#### 保守性（問題が見つかった場合）\n改善案を含め保守性の問題を列挙\n\n## バージョン履歴\n\n- v1.0.0 (2024-12-10): セキュリティ、パフォーマンス、品質、保守性分析を含む初回リリース\n","isInternal":false,"tokens":937,"sizeBytes":2439},{"name":"SKILL.md","path":"ja/03-skills/doc-generator/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/ja/03-skills/doc-generator/SKILL.md","title":"doc-generator","category":"anthropic-skill","format":"markdown","content":"<!-- i18n-source: 03-skills/doc-generator/SKILL.md -->\n<!-- i18n-source-sha: a6380d8 -->\n<!-- i18n-date: 2026-04-27 -->\n\n---\nname: doc-generator\ndescription: ソースコードから包括的かつ正確な API ドキュメントを生成する。API ドキュメントの作成・更新、OpenAPI 仕様の生成時、または API ドキュメント、エンドポイント、ドキュメントについて言及がある場合に使用する。\n---\n\n# API ドキュメント生成スキル\n\n## 生成するもの\n\n- OpenAPI/Swagger 仕様\n- API エンドポイントのドキュメント\n- SDK 利用例\n- 統合ガイド\n- エラーコード・リファレンス\n- 認証ガイド\n\n## ドキュメント構造\n\n### 各エンドポイントごと\n\n````markdown\n## GET /api/v1/users/:id\n\n### Description\nこのエンドポイントの動作を簡潔に説明\n\n### Parameters\n\n| Name | Type | Required | Description |\n|------|------|----------|-------------|\n| id | string | Yes | User ID |\n\n### Response\n\n**200 Success**\n```json\n{\n  \"id\": \"usr_123\",\n  \"name\": \"John Doe\",\n  \"email\": \"john@example.com\",\n  \"created_at\": \"2025-01-15T10:30:00Z\"\n}\n```\n\n**404 Not Found**\n```json\n{\n  \"error\": \"USER_NOT_FOUND\",\n  \"message\": \"User does not exist\"\n}\n```\n\n### Examples\n\n**cURL**\n```bash\ncurl -X GET \"https://api.example.com/api/v1/users/usr_123\" \\\n  -H \"Authorization: Bearer YOUR_TOKEN\"\n```\n\n**JavaScript**\n```javascript\nconst user = await fetch('/api/v1/users/usr_123', {\n  headers: { 'Authorization': 'Bearer token' }\n}).then(r => r.json());\n```\n\n**Python**\n```python\nresponse = requests.get(\n    'https://api.example.com/api/v1/users/usr_123',\n    headers={'Authorization': 'Bearer token'}\n)\nuser = response.json()\n```\n````\n","isInternal":false,"tokens":541,"sizeBytes":1722},{"name":"code-smells.md","path":"ja/03-skills/refactor/references/code-smells.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/ja/03-skills/refactor/references/code-smells.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- i18n-source: 03-skills/refactor/references/code-smells.md -->\n<!-- i18n-source-sha: 245272f -->\n<!-- i18n-date: 2026-04-27 -->\n# コードスメルカタログ\n\nMartin Fowler 著『Refactoring』(第 2 版) に基づく、コードスメルの包括的なリファレンスである。コードスメルはより深い問題の症状であり、コード設計に何か問題がある可能性を示す指標となる。\n\n> \"A code smell is a surface indication that usually corresponds to a deeper problem in the system.\" — Martin Fowler\n\n---\n\n## Bloaters（肥満児）\n\n効果的に扱うには大きくなりすぎたものを表すコードスメル群である。\n\n### Long Method（長すぎる関数）\n\n**兆候:**\n- メソッドが 30〜50 行を超える\n- メソッド全体を見るのにスクロールが必要\n- ネストが多重になっている\n- セクションごとに何をしているかを説明するコメントがある\n\n**なぜ悪いか:**\n- 理解しづらい\n- 単独でテストするのが難しい\n- 変更が予期しない影響を及ぼす\n- 内部に重複ロジックが隠れる\n\n**リファクタリング:**\n- メソッドの抽出\n- Replace Temp with Query\n- パラメータオブジェクトの導入\n- Replace Method with Method Object\n- 条件記述の分解\n\n**例（Before）:**\n```javascript\nfunction processOrder(order) {\n  // 注文の検証 (20 行)\n  if (!order.items) throw new Error('No items');\n  if (order.items.length === 0) throw new Error('Empty order');\n  // ... さらに検証\n\n  // 合計金額の計算 (30 行)\n  let subtotal = 0;\n  for (const item of order.items) {\n    subtotal += item.price * item.quantity;\n  }\n  // ... 税、送料、割引\n\n  // 通知の送信 (20 行)\n  // ... メール送信ロジック\n}\n```\n\n**例（After）:**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const totals = calculateOrderTotals(order);\n  sendOrderNotifications(order, totals);\n  return { order, totals };\n}\n```\n\n---\n\n### Large Class（巨大なクラス）\n\n**兆候:**\n- クラスのインスタンス変数が多い(7〜10 個超)\n- クラスのメソッドが多い(15〜20 個超)\n- クラス名が漠然としている(Manager、Handler、Processor)\n- 全インスタンス変数を使わないメソッドがある\n\n**なぜ悪いか:**\n- 単一責任原則に違反する\n- テストが困難\n- 変更が無関係な機能にも波及する\n- 部分的な再利用が難しい\n\n**リファクタリング:**\n- クラスの抽出\n- Extract Subclass\n- Extract Interface\n\n**検出基準:**\n```\nコード行数 > 300\nメソッド数 > 15\nフィールド数 > 10\n```\n\n---\n\n### Primitive Obsession（プリミティブ型への執着）\n\n**兆候:**\n- ドメイン概念にプリミティブを使う(メールに string、金額に int)\n- オブジェクトでなくプリミティブの配列を使う\n- タイプコードに文字列定数を使う\n- マジックナンバーやマジックストリング\n\n**なぜ悪いか:**\n- 型レベルでの検証ができない\n- ロジックがコードベース全体に散らばる\n- 誤った値を渡しやすい\n- ドメイン概念が欠落する\n\n**リファクタリング:**\n- Replace Primitive with Object\n- Replace Type Code with Class\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**例（Before）:**\n```javascript\nconst user = {\n  email: 'john@example.com',     // 単なる文字列\n  phone: '1234567890',           // 単なる文字列\n  status: 'active',              // マジックストリング\n  balance: 10050                 // セント単位の整数\n};\n```\n\n**例（After）:**\n```javascript\nconst user = {\n  email: new Email('john@example.com'),\n  phone: new PhoneNumber('1234567890'),\n  status: UserStatus.ACTIVE,\n  balance: Money.cents(10050)\n};\n```\n\n---\n\n### Long Parameter List（長すぎるパラメータリスト）\n\n**兆候:**\n- パラメータが 4 個以上のメソッド\n- 常に一緒に現れるパラメータ\n- メソッドの振る舞いを切り替える真偽値フラグ\n- null/undefined が頻繁に渡される\n\n**なぜ悪いか:**\n- 正しく呼び出すのが難しい\n- 引数順序の混乱を招く\n- メソッドが多くを抱え込んでいるサイン\n- パラメータの追加が難しい\n\n**リファクタリング:**\n- パラメータオブジェクトの導入\n- Preserve Whole Object\n- Replace Parameter with Method Call\n- Remove Flag Argument\n\n**例（Before）:**\n```javascript\nfunction createUser(firstName, lastName, email, phone,\n                    street, city, state, zip,\n                    isAdmin, isActive, createdBy) {\n  // ...\n}\n```\n\n**例（After）:**\n```javascript\nfunction createUser(personalInfo, address, options) {\n  // personalInfo: { firstName, lastName, email, phone }\n  // address: { street, city, state, zip }\n  // options: { isAdmin, isActive, createdBy }\n}\n```\n\n---\n\n### Data Clumps（データの群れ）\n\n**兆候:**\n- 同じ 3 個以上のフィールドが繰り返し一緒に現れる\n- 常に一緒に渡されるパラメータ群\n- 一塊として属するべきフィールド集合を持つクラス\n\n**なぜ悪いか:**\n- 取り扱いロジックが重複する\n- 抽象化が欠けている\n- 拡張しづらい\n- 隠れたクラスの存在を示す\n\n**リファクタリング:**\n- クラスの抽出\n- パラメータオブジェクトの導入\n- Preserve Whole Object\n\n**例:**\n```javascript\n// データの群れ: (x, y, z) 座標\nfunction movePoint(x, y, z, dx, dy, dz) { }\nfunction scalePoint(x, y, z, factor) { }\nfunction distanceBetween(x1, y1, z1, x2, y2, z2) { }\n\n// Point3D クラスを抽出\nclass Point3D {\n  constructor(x, y, z) { }\n  move(delta) { }\n  scale(factor) { }\n  distanceTo(other) { }\n}\n```\n\n---\n\n## Object-Orientation Abusers（オブジェクト指向の濫用者）\n\nオブジェクト指向の原則を不完全または誤って使っていることを示すスメル群である。\n\n### Switch Statements（スイッチ文）\n\n**兆候:**\n- 長い switch/case や if/else の連鎖\n- 同じ switch が複数箇所に存在\n- タイプコードに対する switch\n- 新ケース追加で各所を変更する必要がある\n\n**なぜ悪いか:**\n- 開放閉鎖原則に違反する\n- 全ての switch 箇所に変更が波及する\n- 拡張が困難\n- ポリモーフィズム不在のサインであることが多い\n\n**リファクタリング:**\n- ポリモーフィズムによる条件記述の置き換え\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**例（Before）:**\n```javascript\nfunction calculatePay(employee) {\n  switch (employee.type) {\n    case 'hourly':\n      return employee.hours * employee.rate;\n    case 'salaried':\n      return employee.salary / 12;\n    case 'commissioned':\n      return employee.sales * employee.commission;\n  }\n}\n```\n\n**例（After）:**\n```javascript\nclass HourlyEmployee {\n  calculatePay() {\n    return this.hours * this.rate;\n  }\n}\n\nclass SalariedEmployee {\n  calculatePay() {\n    return this.salary / 12;\n  }\n}\n```\n\n---\n\n### Temporary Field（一時的フィールド）\n\n**兆候:**\n- 一部のメソッドでのみ使用されるインスタンス変数\n- 条件付きで設定されるフィールド\n- 特定ケースのために複雑な初期化を要する\n\n**なぜ悪いか:**\n- 紛らわしい - フィールドが存在するが null の場合がある\n- オブジェクトの状態が理解しづらい\n- 隠れた条件分岐ロジックを示す\n\n**リファクタリング:**\n- クラスの抽出\n- Introduce Null Object\n- Replace Temp Field with Local\n\n---\n\n### Refused Bequest（相続拒否）\n\n**兆候:**\n- サブクラスが継承したメソッド/データを使わない\n- サブクラスがオーバーライドして何もしない\n- IS-A 関係ではなくコード再利用目的の継承\n\n**なぜ悪いか:**\n- 抽象化が誤っている\n- リスコフの置換原則に違反する\n- 階層が誤解を招く\n\n**リファクタリング:**\n- Push Down Method/Field\n- Replace Subclass with Delegate\n- Replace Inheritance with Delegation\n\n---\n\n### Alternative Classes with Different Interfaces（異なるインターフェイスの代替クラス）\n\n**兆候:**\n- 似たことをする 2 つのクラス\n- 同じ概念に異なるメソッド名を使っている\n- 互いに置換可能だが共通インターフェイスがない\n\n**なぜ悪いか:**\n- 実装が重複する\n- 共通インターフェイスがない\n- 切り替えが難しい\n\n**リファクタリング:**\n- Rename Method\n- Move Method\n- Extract Superclass\n- Extract Interface\n\n---\n\n## Change Preventers（変更の妨げ）\n\n変更を困難にするスメル群 - ある変更のために他の多くを変える必要が生じる。\n\n### Divergent Change（変更の発散）\n\n**兆候:**\n- 1 つのクラスが異なる複数の理由で変更される\n- 異なる領域の変更が同じクラスへの編集を引き起こす\n- そのクラスは「神クラス」化している\n\n**なぜ悪いか:**\n- 単一責任原則に違反する\n- 変更頻度が高くなる\n- マージコンフリクトを招く\n\n**リファクタリング:**\n- クラスの抽出\n- Extract Superclass\n- Extract Subclass\n\n**例:**\n`User` クラスが次の理由で変更される:\n- 認証の変更\n- プロフィールの変更\n- 課金の変更\n- 通知の変更\n\n→ 抽出: `AuthService`、`ProfileService`、`BillingService`、`NotificationService`\n\n---\n\n### Shotgun Surgery（散弾銃手術）\n\n**兆候:**\n- 1 つの変更で多くのクラスへの編集が必要\n- 小さな機能でも 10 ファイル以上に手を入れる\n- 変更箇所が散在し、すべてを見つけにくい\n\n**なぜ悪いか:**\n- 修正漏れが起きやすい\n- 結合度が高い\n- 変更がエラーを誘発しやすい\n\n**リファクタリング:**\n- Move Method\n- Move Field\n- Inline Class\n\n**検出基準:**\n1 フィールドの追加で 5 ファイル以上の変更が必要かを確認する。\n\n---\n\n### Parallel Inheritance Hierarchies（並行継承階層）\n\n**兆候:**\n- 一方の階層にサブクラスを作ると、もう一方にも作る必要がある\n- クラス名のプレフィックスが揃っている(例: `DatabaseOrder`、`DatabaseProduct`)\n\n**なぜ悪いか:**\n- 保守コストが倍になる\n- 階層間の結合度が高い\n- 片側を忘れやすい\n\n**リファクタリング:**\n- Move Method\n- Move Field\n- 一方の階層を削除する\n\n---\n\n## Dispensables（不要物）\n\n不要であり削除すべきものを表すスメル群である。\n\n### Comments（過剰なコメント）\n\n**兆候:**\n- コードが何をしているかを説明するコメント\n- コメントアウトされたコード\n- 永遠に残る TODO/FIXME\n- 言い訳のコメント\n\n**なぜ悪いか:**\n- コメントは嘘をつく(コードと乖離する)\n- コードは自己文書化されているべき\n- 死んだコードは混乱を生む\n\n**リファクタリング:**\n- メソッドの抽出(名前で「何」を表す)\n- Rename(コメントなしで明確化)\n- コメントアウトされたコードの削除\n- Introduce Assertion\n\n**良いコメントと悪いコメント:**\n```javascript\n// 悪い: 「何」を説明している\n// users をループしてアクティブかどうか確認\nfor (const user of users) {\n  if (user.status === 'active') { }\n}\n\n// 良い: 「なぜ」を説明している\n// アクティブなユーザーのみ。非アクティブはクリーンアップジョブで処理される\nconst activeUsers = users.filter(u => u.isActive);\n```\n\n---\n\n### Duplicate Code（重複したコード）\n\n**兆候:**\n- 同じコードが複数箇所にある\n- わずかな違いだけの似たコード\n- コピペのパターン\n\n**なぜ悪いか:**\n- バグ修正を複数箇所で行う必要がある\n- 不整合のリスク\n- コードベースが肥大化する\n\n**リファクタリング:**\n- メソッドの抽出\n- クラスの抽出\n- Pull Up Method(階層内)\n- Form Template Method\n\n**検出ルール:**\n3 回以上重複するコードは抽出すべきである。\n\n---\n\n### Lazy Class（怠け者のクラス）\n\n**兆候:**\n- クラスが存在を正当化できるほど働いていない\n- 付加価値のないラッパー\n- 過剰設計の結果\n\n**なぜ悪いか:**\n- 保守オーバーヘッド\n- 不要な間接参照\n- メリットなき複雑さ\n\n**リファクタリング:**\n- Inline Class\n- Collapse Hierarchy\n\n---\n\n### Dead Code（デッドコード）\n\n**兆候:**\n- 到達不能なコード\n- 使われていない変数/メソッド/クラス\n- コメントアウトされたコード\n- 起こり得ない条件下にあるコード\n\n**なぜ悪いか:**\n- 混乱を招く\n- 保守の負担\n- 理解の速度を落とす\n\n**リファクタリング:**\n- デッドコードの削除\n- Safe Delete\n\n**検出基準:**\n```bash\n# 未使用のエクスポートを探す\n# 参照されない関数を探す\n# IDE の「未使用」警告を確認\n```\n\n---\n\n### Speculative Generality（投機的一般化）\n\n**兆候:**\n- サブクラスが 1 つしかない抽象クラス\n- 「将来のため」の未使用パラメータ\n- 委譲のみのメソッド\n- 1 用途しかない「フレームワーク」\n\n**なぜ悪いか:**\n- メリットなき複雑さ\n- YAGNI(You Ain't Gonna Need It)\n- 理解しづらい\n\n**リファクタリング:**\n- Collapse Hierarchy\n- Inline Class\n- Remove Parameter\n- Rename Method\n\n---\n\n## Couplers（結合の問題）\n\nクラス間の過剰な結合を表すスメル群である。\n\n### Feature Envy（機能の横恋慕）\n\n**兆候:**\n- メソッドが自クラスより他クラスのデータを多く使う\n- 他オブジェクトへの getter 呼び出しが多い\n- データと振る舞いが分離している\n\n**なぜ悪いか:**\n- 振る舞いの置き場所が誤っている\n- カプセル化が不十分\n- 保守が難しい\n\n**リファクタリング:**\n- Move Method\n- Move Field\n- メソッドの抽出(その後 move)\n\n**例（Before）:**\n```javascript\nclass Order {\n  getDiscountedPrice(customer) {\n    // customer のデータを多く使っている\n    if (customer.loyaltyYears > 5) {\n      return this.price * customer.discountRate;\n    }\n    return this.price;\n  }\n}\n```\n\n**例（After）:**\n```javascript\nclass Customer {\n  getDiscountedPriceFor(price) {\n    if (this.loyaltyYears > 5) {\n      return price * this.discountRate;\n    }\n    return price;\n  }\n}\n```\n\n---\n\n### Inappropriate Intimacy（不適切な親密さ）\n\n**兆候:**\n- クラスが互いのプライベート部分にアクセスする\n- 双方向の参照\n- サブクラスが親について詳しすぎる\n\n**なぜ悪いか:**\n- 結合度が高い\n- 変更が連鎖する\n- 一方を変えると他方も変える必要がある\n\n**リファクタリング:**\n- Move Method\n- Move Field\n- Change Bidirectional to Unidirectional\n- クラスの抽出\n- Hide Delegate\n\n---\n\n### Message Chains（メッセージの連鎖）\n\n**兆候:**\n- メソッド呼び出しの長い連鎖: `a.getB().getC().getD().getValue()`\n- クライアントがナビゲーション構造に依存している\n- 「列車事故」コード\n\n**なぜ悪いか:**\n- 脆弱 - 連鎖中のいずれかが変わると壊れる\n- デメテルの法則に違反する\n- 構造への結合\n\n**リファクタリング:**\n- Hide Delegate\n- メソッドの抽出\n- Move Method\n\n**例:**\n```javascript\n// 悪い: メッセージの連鎖\nconst managerName = employee.getDepartment().getManager().getName();\n\n// 良い: 委譲を隠す\nconst managerName = employee.getManagerName();\n```\n\n---\n\n### Middle Man（仲介人）\n\n**兆候:**\n- 他クラスへ委譲するだけのクラス\n- メソッドの半数が委譲\n- 付加価値がない\n\n**なぜ悪いか:**\n- 不要な間接参照\n- 保守オーバーヘッド\n- アーキテクチャが分かりにくい\n\n**リファクタリング:**\n- Remove Middle Man\n- メソッドのインライン化\n\n---\n\n## スメル深刻度ガイド\n\n| 深刻度 | 説明 | 対応 |\n|----------|-------------|--------|\n| **Critical** | 開発をブロックし、バグの原因となる | 直ちに修正 |\n| **High** | 保守負担が大きい | 当該スプリント中に修正 |\n| **Medium** | 目に付くが許容範囲 | 近い将来に計画 |\n| **Low** | 軽微な不便 | 機会があれば修正 |\n\n---\n\n## 簡易検出チェックリスト\n\nコードをスキャンする際に使うチェックリストである。\n\n- [ ] 30 行を超えるメソッドはあるか?\n- [ ] 300 行を超えるクラスはあるか?\n- [ ] 4 個を超えるパラメータを持つメソッドはあるか?\n- [ ] 重複したコードブロックはあるか?\n- [ ] タイプコードに対する switch/case はあるか?\n- [ ] 使われていないコードはあるか?\n- [ ] 他クラスのデータを多く使っているメソッドはあるか?\n- [ ] メソッド呼び出しの長い連鎖はあるか?\n- [ ] 「なぜ」ではなく「何」を説明しているコメントはあるか?\n- [ ] オブジェクト化すべきプリミティブはあるか?\n\n---\n\n## 参考文献\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Kerievsky, J. (2004). *Refactoring to Patterns*\n- Feathers, M. (2004). *Working Effectively with Legacy Code*\n","isInternal":false,"tokens":6263,"sizeBytes":17480},{"name":"refactoring-catalog.md","path":"ja/03-skills/refactor/references/refactoring-catalog.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/ja/03-skills/refactor/references/refactoring-catalog.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"<!-- i18n-source: 03-skills/refactor/references/refactoring-catalog.md -->\n<!-- i18n-source-sha: 245272f -->\n<!-- i18n-date: 2026-04-27 -->\n\n# リファクタリングカタログ\n\nMartin Fowler 著『Refactoring』(第 2 版) から厳選したリファクタリング技法のカタログである。各リファクタリングには動機、手順、例を掲載している。\n\n> 「リファクタリングは、その手順、すなわち変更を実施するための正確なステップ列によって定義される。」 — Martin Fowler\n\n---\n\n## このカタログの使い方\n\n1. コードスメルのリファレンスを使って **コードスメルを特定する**\n2. このカタログから **対応するリファクタリングを探す**\n3. **手順に沿って一段ずつ進める**\n4. **各ステップごとにテスト** を実行し、振る舞いが保たれていることを確認する\n\n**鉄則**: ある手順に 10 分以上かかるのであれば、もっと小さなステップに分割すること。\n\n---\n\n## 最も頻出するリファクタリング\n\n### メソッドの抽出 (Extract Method)\n\n**使う場面**: 長いメソッド、重複コード、概念に名前を付けたいとき\n\n**動機**: コード片を、目的を表す名前を持つメソッドに切り出す。\n\n**手順**:\n1. やっていること(どうやってではなく)にちなんだ名前で新しいメソッドを作成する\n2. コード片を新しいメソッドへコピーする\n3. コード片で使われているローカル変数を洗い出す\n4. ローカル変数をパラメータとして渡す(あるいはメソッド内で宣言する)\n5. 戻り値を適切に処理する\n6. 元のコード片を新しいメソッドの呼び出しに置き換える\n7. テストする\n\n**Before**:\n```javascript\nfunction printOwing(invoice) {\n  let outstanding = 0;\n\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n\n  // 未払額の計算\n  for (const order of invoice.orders) {\n    outstanding += order.amount;\n  }\n\n  // 詳細の出力\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n**After**:\n```javascript\nfunction printOwing(invoice) {\n  printBanner();\n  const outstanding = calculateOutstanding(invoice);\n  printDetails(invoice, outstanding);\n}\n\nfunction printBanner() {\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n}\n\nfunction calculateOutstanding(invoice) {\n  return invoice.orders.reduce((sum, order) => sum + order.amount, 0);\n}\n\nfunction printDetails(invoice, outstanding) {\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n---\n\n### メソッドのインライン化 (Inline Method)\n\n**使う場面**: メソッド本体が名前と同じくらい明快な場合、過度な委譲が見られる場合\n\n**動機**: メソッドが価値を加えていない場合、不要な間接参照を取り除く。\n\n**手順**:\n1. メソッドがポリモーフィックでないことを確認する\n2. メソッドの呼び出し箇所をすべて見つける\n3. 各呼び出しをメソッド本体で置き換える\n4. 置き換えるたびにテストする\n5. メソッド定義を削除する\n\n**Before**:\n```javascript\nfunction getRating(driver) {\n  return moreThanFiveLateDeliveries(driver) ? 2 : 1;\n}\n\nfunction moreThanFiveLateDeliveries(driver) {\n  return driver.numberOfLateDeliveries > 5;\n}\n```\n\n**After**:\n```javascript\nfunction getRating(driver) {\n  return driver.numberOfLateDeliveries > 5 ? 2 : 1;\n}\n```\n\n---\n\n### 変数の抽出 (Extract Variable)\n\n**使う場面**: 複雑で理解しづらい式があるとき\n\n**動機**: 複雑な式の一部に名前を付ける。\n\n**手順**:\n1. 式に副作用がないことを確認する\n2. イミュータブルな変数を宣言する\n3. 式(または式の一部)の結果をその変数に代入する\n4. 元の式を変数で置き換える\n5. テストする\n\n**Before**:\n```javascript\nreturn order.quantity * order.itemPrice -\n  Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +\n  Math.min(order.quantity * order.itemPrice * 0.1, 100);\n```\n\n**After**:\n```javascript\nconst basePrice = order.quantity * order.itemPrice;\nconst quantityDiscount = Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;\nconst shipping = Math.min(basePrice * 0.1, 100);\nreturn basePrice - quantityDiscount + shipping;\n```\n\n---\n\n### 変数のインライン化 (Inline Variable)\n\n**使う場面**: 変数名が式以上の情報を伝えていないとき\n\n**動機**: 不要な間接参照を取り除く。\n\n**手順**:\n1. 右辺に副作用がないことを確認する\n2. 変数がイミュータブルでなければイミュータブルにし、テストする\n3. 最初の参照箇所を見つけて式で置き換える\n4. テストする\n5. すべての参照箇所について繰り返す\n6. 宣言と代入を削除する\n7. テストする\n\n---\n\n### 変数名の変更 (Rename Variable)\n\n**使う場面**: 名前が目的を明確に伝えていないとき\n\n**動機**: クリーンなコードには良い名前が不可欠である。\n\n**手順**:\n1. 変数が広く使われている場合は、カプセル化を検討する\n2. すべての参照箇所を見つける\n3. 各参照箇所を変更する\n4. テストする\n\n**Tips**:\n- 意図を明らかにする名前を使う\n- 略語を避ける\n- ドメイン用語を用いる\n\n```javascript\n// 悪い例\nconst d = 30;\nconst x = users.filter(u => u.a);\n\n// 良い例\nconst daysSinceLastLogin = 30;\nconst activeUsers = users.filter(user => user.isActive);\n```\n\n---\n\n### 関数宣言の変更 (Change Function Declaration)\n\n**使う場面**: 関数名が目的を表していない、パラメータの変更が必要な場合\n\n**動機**: 良い関数名はコードを自己説明的にする。\n\n**手順 (シンプル版)**:\n1. 不要なパラメータを削除する\n2. 名前を変更する\n3. 必要なパラメータを追加する\n4. テストする\n\n**手順 (マイグレーション版 — 複雑な変更向け)**:\n1. パラメータを削除する場合、それが使われていないことを確認する\n2. 望ましい宣言の新しい関数を作成する\n3. 古い関数から新しい関数を呼び出すようにする\n4. テストする\n5. 呼び出し側を新しい関数を使うように変更する\n6. 各変更後にテストする\n7. 古い関数を削除する\n\n**Before**:\n```javascript\nfunction circum(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n**After**:\n```javascript\nfunction circumference(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n---\n\n### 変数のカプセル化 (Encapsulate Variable)\n\n**使う場面**: データに複数箇所から直接アクセスしているとき\n\n**動機**: データ操作のための明確なアクセスポイントを提供する。\n\n**手順**:\n1. getter と setter 関数を作成する\n2. すべての参照箇所を見つける\n3. 読み取りを getter で置き換える\n4. 書き込みを setter で置き換える\n5. 各変更後にテストする\n6. 変数の可視性を制限する\n\n**Before**:\n```javascript\nlet defaultOwner = { firstName: \"Martin\", lastName: \"Fowler\" };\n\n// 多くの場所で利用される\nspaceship.owner = defaultOwner;\n```\n\n**After**:\n```javascript\nlet defaultOwnerData = { firstName: \"Martin\", lastName: \"Fowler\" };\n\nfunction defaultOwner() { return defaultOwnerData; }\nfunction setDefaultOwner(arg) { defaultOwnerData = arg; }\n\nspaceship.owner = defaultOwner();\n```\n\n---\n\n### パラメータオブジェクトの導入 (Introduce Parameter Object)\n\n**使う場面**: いくつかのパラメータがしばしばまとまって登場する場合\n\n**動機**: 自然にまとまるべきデータをグループ化する。\n\n**手順**:\n1. グループ化したパラメータ用の新しいクラス/構造体を作成する\n2. テストする\n3. 「関数宣言の変更」で新しいオブジェクトを追加する\n4. テストする\n5. グループ内の各パラメータについて、関数から取り除き新しいオブジェクトを使うようにする\n6. 各変更後にテストする\n\n**Before**:\n```javascript\nfunction amountInvoiced(startDate, endDate) { ... }\nfunction amountReceived(startDate, endDate) { ... }\nfunction amountOverdue(startDate, endDate) { ... }\n```\n\n**After**:\n```javascript\nclass DateRange {\n  constructor(start, end) {\n    this.start = start;\n    this.end = end;\n  }\n}\n\nfunction amountInvoiced(dateRange) { ... }\nfunction amountReceived(dateRange) { ... }\nfunction amountOverdue(dateRange) { ... }\n```\n\n---\n\n### 関数群のクラス化 (Combine Functions into Class)\n\n**使う場面**: 複数の関数が同じデータを操作している場合\n\n**動機**: 関数を、それらが操作するデータと共にまとめる。\n\n**手順**:\n1. 共通データに「レコードのカプセル化 (Encapsulate Record)」を適用する\n2. 各関数をクラス内に移動する\n3. 移動するたびにテストする\n4. データ引数をクラスのフィールド利用に置き換える\n\n**Before**:\n```javascript\nfunction base(reading) { ... }\nfunction taxableCharge(reading) { ... }\nfunction calculateBaseCharge(reading) { ... }\n```\n\n**After**:\n```javascript\nclass Reading {\n  constructor(data) { this._data = data; }\n\n  get base() { ... }\n  get taxableCharge() { ... }\n  get calculateBaseCharge() { ... }\n}\n```\n\n---\n\n### 段階の分割 (Split Phase)\n\n**使う場面**: コードが 2 つの異なる事柄を扱っている場合\n\n**動機**: コードを明確な境界を持つ別々のフェーズに分離する。\n\n**手順**:\n1. 第 2 フェーズ用の関数を作成する\n2. テストする\n3. フェーズ間の中間データ構造を導入する\n4. テストする\n5. 第 1 フェーズを独立した関数として抽出する\n6. テストする\n\n**Before**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  const shippingPerCase = (basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = quantity * shippingPerCase;\n  return basePrice - discount + shippingCost;\n}\n```\n\n**After**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const priceData = calculatePricingData(product, quantity);\n  return applyShipping(priceData, shippingMethod);\n}\n\nfunction calculatePricingData(product, quantity) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  return { basePrice, quantity, discount };\n}\n\nfunction applyShipping(priceData, shippingMethod) {\n  const shippingPerCase = (priceData.basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = priceData.quantity * shippingPerCase;\n  return priceData.basePrice - priceData.discount + shippingCost;\n}\n```\n\n---\n\n## 機能の移動\n\n### メソッドの移動 (Move Method)\n\n**使う場面**: メソッドが自分のクラスより他のクラスの機能を多く使っている場合\n\n**動機**: 関数を、最もよく利用するデータの近くに置く。\n\n**手順**:\n1. 自クラス内でメソッドが利用しているプログラム要素をすべて調べる\n2. メソッドがポリモーフィックかどうか確認する\n3. 移動先クラスにメソッドをコピーする\n4. 新しいコンテキストに合わせて調整する\n5. 元のメソッドが移動先に委譲するようにする\n6. テストする\n7. 元のメソッドの削除を検討する\n\n---\n\n### フィールドの移動 (Move Field)\n\n**使う場面**: フィールドが他のクラスでより多く使われている場合\n\n**動機**: データを、それを使う関数と共に保持する。\n\n**手順**:\n1. まだの場合はフィールドをカプセル化する\n2. テストする\n3. 移動先にフィールドを作成する\n4. 参照箇所を移動先のフィールドを使うように更新する\n5. テストする\n6. 元のフィールドを削除する\n\n---\n\n### 関数への文の移動 (Move Statements into Function)\n\n**使う場面**: 同じコードが必ずある関数呼び出しと一緒に現れる場合\n\n**動機**: 繰り返しコードを関数内に移動して重複を取り除く。\n\n**手順**:\n1. まだの場合は繰り返しコードを関数として抽出する\n2. その関数の中に文を移動する\n3. テストする\n4. 呼び出し側で単独の文が不要になったら削除する\n\n---\n\n### 呼び出し側への文の移動 (Move Statements to Callers)\n\n**使う場面**: 共通の振る舞いが呼び出し側ごとに異なる場合\n\n**動機**: 振る舞いを変える必要があるなら、関数の外に移す。\n\n**手順**:\n1. 移動するコードに「メソッドの抽出」を適用する\n2. 元の関数に「メソッドのインライン化」を適用する\n3. インライン化された呼び出しを削除する\n4. 抽出したコードを各呼び出し側に移動する\n5. テストする\n\n---\n\n## データの再編成\n\n### プリミティブをオブジェクトで置き換える (Replace Primitive with Object)\n\n**使う場面**: データ項目に単純な値以上の振る舞いが必要な場合\n\n**動機**: データを振る舞いと共にカプセル化する。\n\n**手順**:\n1. 「変数のカプセル化」を適用する\n2. シンプルな値クラスを作成する\n3. setter を新しいインスタンス生成に変更する\n4. getter を値の返却に変更する\n5. テストする\n6. 新しいクラスにより豊かな振る舞いを追加する\n\n**Before**:\n```javascript\nclass Order {\n  constructor(data) {\n    this.priority = data.priority; // 文字列: \"high\"、\"rush\" など\n  }\n}\n\n// 利用箇所\nif (order.priority === \"high\" || order.priority === \"rush\") { ... }\n```\n\n**After**:\n```javascript\nclass Priority {\n  constructor(value) {\n    if (!Priority.legalValues().includes(value))\n      throw new Error(`Invalid priority: ${value}`);\n    this._value = value;\n  }\n\n  static legalValues() { return ['low', 'normal', 'high', 'rush']; }\n  get value() { return this._value; }\n\n  higherThan(other) {\n    return Priority.legalValues().indexOf(this._value) >\n           Priority.legalValues().indexOf(other._value);\n  }\n}\n\n// 利用箇所\nif (order.priority.higherThan(new Priority(\"normal\"))) { ... }\n```\n\n---\n\n### 一時変数を問い合わせで置き換える (Replace Temp with Query)\n\n**使う場面**: 一時変数が式の結果を保持している場合\n\n**動機**: 式を関数として切り出すことでコードを明快にする。\n\n**手順**:\n1. 変数が一度だけ代入されていることを確認する\n2. 代入の右辺をメソッドとして抽出する\n3. 一時変数の参照箇所をメソッド呼び出しで置き換える\n4. テストする\n5. 一時変数の宣言と代入を削除する\n\n**Before**:\n```javascript\nconst basePrice = this._quantity * this._itemPrice;\nif (basePrice > 1000) {\n  return basePrice * 0.95;\n} else {\n  return basePrice * 0.98;\n}\n```\n\n**After**:\n```javascript\nget basePrice() {\n  return this._quantity * this._itemPrice;\n}\n\n// メソッド内\nif (this.basePrice > 1000) {\n  return this.basePrice * 0.95;\n} else {\n  return this.basePrice * 0.98;\n}\n```\n\n---\n\n## 条件記述の単純化\n\n### 条件記述の分解 (Decompose Conditional)\n\n**使う場面**: 複雑な条件分岐 (if-then-else) があるとき\n\n**動機**: 条件と動作を抽出して意図を明確にする。\n\n**手順**:\n1. 条件部分に「メソッドの抽出」を適用する\n2. then 節に「メソッドの抽出」を適用する\n3. else 節 (もしあれば) に「メソッドの抽出」を適用する\n\n**Before**:\n```javascript\nif (!aDate.isBefore(plan.summerStart) && !aDate.isAfter(plan.summerEnd)) {\n  charge = quantity * plan.summerRate;\n} else {\n  charge = quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n**After**:\n```javascript\nif (isSummer(aDate, plan)) {\n  charge = summerCharge(quantity, plan);\n} else {\n  charge = regularCharge(quantity, plan);\n}\n\nfunction isSummer(date, plan) {\n  return !date.isBefore(plan.summerStart) && !date.isAfter(plan.summerEnd);\n}\n\nfunction summerCharge(quantity, plan) {\n  return quantity * plan.summerRate;\n}\n\nfunction regularCharge(quantity, plan) {\n  return quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n---\n\n### 条件式の統合 (Consolidate Conditional Expression)\n\n**使う場面**: 同じ結果を返す条件が複数あるとき\n\n**動機**: それらの条件が単一のチェックであることを明らかにする。\n\n**手順**:\n1. 条件に副作用がないことを確認する\n2. 条件を `and` または `or` で結合する\n3. 結合した条件に「メソッドの抽出」を検討する\n\n**Before**:\n```javascript\nif (employee.seniority < 2) return 0;\nif (employee.monthsDisabled > 12) return 0;\nif (employee.isPartTime) return 0;\n```\n\n**After**:\n```javascript\nif (isNotEligibleForDisability(employee)) return 0;\n\nfunction isNotEligibleForDisability(employee) {\n  return employee.seniority < 2 ||\n         employee.monthsDisabled > 12 ||\n         employee.isPartTime;\n}\n```\n\n---\n\n### ガード節による入れ子の条件記述の置き換え (Replace Nested Conditional with Guard Clauses)\n\n**使う場面**: 入れ子の条件分岐が深く、流れを追いにくいとき\n\n**動機**: 特殊ケースにガード節を使い、通常フローを明確に保つ。\n\n**手順**:\n1. 特殊ケースの条件を見つける\n2. それらを早期 return するガード節で置き換える\n3. 各変更後にテストする\n\n**Before**:\n```javascript\nfunction payAmount(employee) {\n  let result;\n  if (employee.isSeparated) {\n    result = { amount: 0, reasonCode: \"SEP\" };\n  } else {\n    if (employee.isRetired) {\n      result = { amount: 0, reasonCode: \"RET\" };\n    } else {\n      result = calculateNormalPay(employee);\n    }\n  }\n  return result;\n}\n```\n\n**After**:\n```javascript\nfunction payAmount(employee) {\n  if (employee.isSeparated) return { amount: 0, reasonCode: \"SEP\" };\n  if (employee.isRetired) return { amount: 0, reasonCode: \"RET\" };\n  return calculateNormalPay(employee);\n}\n```\n\n---\n\n### ポリモーフィズムによる条件記述の置き換え (Replace Conditional with Polymorphism)\n\n**使う場面**: 型に基づく switch/case、型ごとに変化する条件ロジック\n\n**動機**: オブジェクト自身に振る舞いを担わせる。\n\n**手順**:\n1. クラス階層を作成する (なければ)\n2. オブジェクト生成にファクトリ関数を使う\n3. 条件ロジックをスーパークラスのメソッドに移す\n4. ケースごとにサブクラスのメソッドを作成する\n5. 元の条件記述を削除する\n\n**Before**:\n```javascript\nfunction plumages(birds) {\n  return birds.map(b => plumage(b));\n}\n\nfunction plumage(bird) {\n  switch (bird.type) {\n    case 'EuropeanSwallow':\n      return \"average\";\n    case 'AfricanSwallow':\n      return (bird.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n    case 'NorwegianBlueParrot':\n      return (bird.voltage > 100) ? \"scorched\" : \"beautiful\";\n    default:\n      return \"unknown\";\n  }\n}\n```\n\n**After**:\n```javascript\nclass Bird {\n  get plumage() { return \"unknown\"; }\n}\n\nclass EuropeanSwallow extends Bird {\n  get plumage() { return \"average\"; }\n}\n\nclass AfricanSwallow extends Bird {\n  get plumage() {\n    return (this.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n  }\n}\n\nclass NorwegianBlueParrot extends Bird {\n  get plumage() {\n    return (this.voltage > 100) ? \"scorched\" : \"beautiful\";\n  }\n}\n\nfunction createBird(data) {\n  switch (data.type) {\n    case 'EuropeanSwallow': return new EuropeanSwallow(data);\n    case 'AfricanSwallow': return new AfricanSwallow(data);\n    case 'NorwegianBlueParrot': return new NorwegianBlueParrot(data);\n    default: return new Bird(data);\n  }\n}\n```\n\n---\n\n### 特殊ケースの導入 (Introduce Special Case / Null Object)\n\n**使う場面**: 特殊ケースに対する null チェックが繰り返される場合\n\n**動機**: 特殊ケースを処理する特殊オブジェクトを返す。\n\n**手順**:\n1. 期待されるインターフェースを持つ特殊ケースクラスを作成する\n2. isSpecialCase チェックを追加する\n3. ファクトリメソッドを導入する\n4. null チェックを特殊ケースオブジェクトの利用で置き換える\n5. テストする\n\n**Before**:\n```javascript\nconst customer = site.customer;\n// ... 多数の箇所でチェック\nif (customer === \"unknown\") {\n  customerName = \"occupant\";\n} else {\n  customerName = customer.name;\n}\n```\n\n**After**:\n```javascript\nclass UnknownCustomer {\n  get name() { return \"occupant\"; }\n  get billingPlan() { return registry.defaultPlan; }\n}\n\n// ファクトリメソッド\nfunction customer(site) {\n  return site.customer === \"unknown\"\n    ? new UnknownCustomer()\n    : site.customer;\n}\n\n// 利用箇所 — null チェック不要\nconst customerName = customer.name;\n```\n\n---\n\n## API のリファクタリング\n\n### 問い合わせと変更の分離 (Separate Query from Modifier)\n\n**使う場面**: 関数が値を返すと同時に副作用も持つ場合\n\n**動機**: どの操作に副作用があるのかを明確にする。\n\n**手順**:\n1. 新しい問い合わせ関数を作成する\n2. 元の関数の戻り値ロジックをコピーする\n3. 元の関数を void を返すように変更する\n4. 戻り値を使っていた呼び出しを置き換える\n5. テストする\n\n**Before**:\n```javascript\nfunction alertForMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") {\n      setOffAlarms();\n      return \"Don\";\n    }\n    if (p === \"John\") {\n      setOffAlarms();\n      return \"John\";\n    }\n  }\n  return \"\";\n}\n```\n\n**After**:\n```javascript\nfunction findMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") return \"Don\";\n    if (p === \"John\") return \"John\";\n  }\n  return \"\";\n}\n\nfunction alertForMiscreant(people) {\n  if (findMiscreant(people) !== \"\") setOffAlarms();\n}\n```\n\n---\n\n### 関数のパラメータ化 (Parameterize Function)\n\n**使う場面**: 似たような処理を異なる値で行う関数が複数あるとき\n\n**動機**: パラメータを追加することで重複を取り除く。\n\n**手順**:\n1. 一つの関数を選ぶ\n2. 変動するリテラル用のパラメータを追加する\n3. 本体をそのパラメータを使うように変更する\n4. テストする\n5. 呼び出し側をパラメータ化された版を使うように変更する\n6. 不要になった関数を削除する\n\n**Before**:\n```javascript\nfunction tenPercentRaise(person) {\n  person.salary = person.salary * 1.10;\n}\n\nfunction fivePercentRaise(person) {\n  person.salary = person.salary * 1.05;\n}\n```\n\n**After**:\n```javascript\nfunction raise(person, factor) {\n  person.salary = person.salary * (1 + factor);\n}\n\n// 利用箇所\nraise(person, 0.10);\nraise(person, 0.05);\n```\n\n---\n\n### フラグ引数の削除 (Remove Flag Argument)\n\n**使う場面**: 関数の振る舞いを切り替えるブール型パラメータがある場合\n\n**動機**: 別々の関数を通して振る舞いを明示的にする。\n\n**手順**:\n1. フラグの値ごとに明示的な関数を作成する\n2. 各呼び出しを適切な新しい関数で置き換える\n3. 各変更後にテストする\n4. 元の関数を削除する\n\n**Before**:\n```javascript\nfunction bookConcert(customer, isPremium) {\n  if (isPremium) {\n    // プレミアム予約のロジック\n  } else {\n    // 通常予約のロジック\n  }\n}\n\nbookConcert(customer, true);\nbookConcert(customer, false);\n```\n\n**After**:\n```javascript\nfunction bookPremiumConcert(customer) {\n  // プレミアム予約のロジック\n}\n\nfunction bookRegularConcert(customer) {\n  // 通常予約のロジック\n}\n\nbookPremiumConcert(customer);\nbookRegularConcert(customer);\n```\n\n---\n\n## 継承の取り扱い\n\n### メソッドの引き上げ (Pull Up Method)\n\n**使う場面**: 同じメソッドが複数のサブクラスにあるとき\n\n**動機**: クラス階層内の重複を取り除く。\n\n**手順**:\n1. メソッド同士が同一であることを確認する\n2. シグネチャが同じであることを確認する\n3. スーパークラスに新しいメソッドを作成する\n4. 一つのサブクラスから本体をコピーする\n5. 一つのサブクラスからメソッドを削除し、テストする\n6. 他のサブクラスのメソッドも順次削除し、その都度テストする\n\n---\n\n### メソッドの押し下げ (Push Down Method)\n\n**使う場面**: サブクラスの一部のみに関係する振る舞いがあるとき\n\n**動機**: メソッドを使われる場所に置く。\n\n**手順**:\n1. メソッドを必要とする各サブクラスにコピーする\n2. スーパークラスからメソッドを削除する\n3. テストする\n4. 必要としないサブクラスからは削除する\n5. テストする\n\n---\n\n### サブクラスを委譲で置き換える (Replace Subclass with Delegate)\n\n**使う場面**: 継承が誤って使われている、もしくはより柔軟性が必要な場合\n\n**動機**: 適切な場面では継承よりコンポジションを優先する。\n\n**手順**:\n1. 委譲先用の空クラスを作成する\n2. 委譲先を保持するフィールドをホストクラスに追加する\n3. ホストから呼ばれる委譲先のコンストラクタを作成する\n4. 機能を委譲先へ移動する\n5. 移動するたびにテストする\n6. 継承を委譲で置き換える\n\n---\n\n## クラスの抽出 (Extract Class)\n\n**使う場面**: 複数の責務を持つ大きなクラスがあるとき\n\n**動機**: クラスを分割して単一責務を保つ。\n\n**手順**:\n1. 責務をどう分けるか決める\n2. 新しいクラスを作成する\n3. フィールドを元のクラスから新しいクラスへ移動する\n4. テストする\n5. メソッドを元のクラスから新しいクラスへ移動する\n6. 移動するたびにテストする\n7. 両クラスを見直して必要なら名前を変更する\n8. 新しいクラスをどう公開するかを決める\n\n**Before**:\n```javascript\nclass Person {\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get officeAreaCode() { return this._officeAreaCode; }\n  set officeAreaCode(arg) { this._officeAreaCode = arg; }\n  get officeNumber() { return this._officeNumber; }\n  set officeNumber(arg) { this._officeNumber = arg; }\n\n  get telephoneNumber() {\n    return `(${this._officeAreaCode}) ${this._officeNumber}`;\n  }\n}\n```\n\n**After**:\n```javascript\nclass Person {\n  constructor() {\n    this._telephoneNumber = new TelephoneNumber();\n  }\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get telephoneNumber() { return this._telephoneNumber.toString(); }\n  get officeAreaCode() { return this._telephoneNumber.areaCode; }\n  set officeAreaCode(arg) { this._telephoneNumber.areaCode = arg; }\n}\n\nclass TelephoneNumber {\n  get areaCode() { return this._areaCode; }\n  set areaCode(arg) { this._areaCode = arg; }\n  get number() { return this._number; }\n  set number(arg) { this._number = arg; }\n  toString() { return `(${this._areaCode}) ${this._number}`; }\n}\n```\n\n---\n\n## クイックリファレンス: スメルからリファクタリングへ\n\n| コードスメル | 主なリファクタリング | 代替 |\n|------------|-------------------|-------------|\n| 長すぎるメソッド (Long Method) | メソッドの抽出 | 一時変数を問い合わせで置き換える |\n| 重複コード (Duplicate Code) | メソッドの抽出 | メソッドの引き上げ |\n| 大きすぎるクラス (Large Class) | クラスの抽出 | サブクラスの抽出 |\n| 長すぎるパラメータリスト (Long Parameter List) | パラメータオブジェクトの導入 | オブジェクトそのものの受け渡し |\n| 機能の横恋慕 (Feature Envy) | メソッドの移動 | メソッドの抽出 + 移動 |\n| データのかたまり (Data Clumps) | クラスの抽出 | パラメータオブジェクトの導入 |\n| プリミティブ依存症 (Primitive Obsession) | プリミティブをオブジェクトで置き換える | タイプコードの置き換え |\n| switch 文 (Switch Statements) | ポリモーフィズムによる条件記述の置き換え | タイプコードの置き換え |\n| 一時的属性 (Temporary Field) | クラスの抽出 | Null オブジェクトの導入 |\n| メッセージの連鎖 (Message Chains) | 委譲の隠蔽 | メソッドの抽出 |\n| 仲介人 (Middle Man) | 中間者の除去 | メソッドのインライン化 |\n| 変更の分散 (Divergent Change) | クラスの抽出 | 段階の分割 |\n| 散弾銃手術 (Shotgun Surgery) | メソッドの移動 | クラスのインライン化 |\n| 死せるコード (Dead Code) | 死せるコードの除去 | - |\n| 投機的一般性 (Speculative Generality) | 階層の平坦化 | クラスのインライン化 |\n\n---\n\n## 参考文献\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- オンラインカタログ: https://refactoring.com/catalog/\n","isInternal":false,"tokens":9860,"sizeBytes":29707},{"name":"SKILL.md","path":"ja/03-skills/refactor/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/ja/03-skills/refactor/SKILL.md","title":"refactor","category":"anthropic-skill","format":"markdown","content":"<!-- i18n-source: 03-skills/refactor/SKILL.md -->\n<!-- i18n-source-sha: 245272f -->\n<!-- i18n-date: 2026-04-27 -->\n---\nname: refactor\ndescription: Martin Fowler の方法論に基づく体系的なコードリファクタリング。ユーザーがコードのリファクタリング、コード構造の改善、技術的負債の削減、レガシーコードのクリーンアップ、コードスメルの解消、コード保守性の向上を求めた際に使用する。本スキルは、リサーチ・計画・安全な段階的実装からなる段階的アプローチを案内する。\n---\n\n# コードリファクタリングスキル\n\nMartin Fowler 著『Refactoring: Improving the Design of Existing Code』(第 2 版) に基づくコードリファクタリングへの体系的アプローチ。本スキルは、テストに支えられた安全で段階的な変更を重視する。\n\n> \"Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure.\" — Martin Fowler\n\n## 中核となる原則\n\n1. **振る舞いの保全**: 外部から見える振る舞いは変えてはならない\n2. **小さなステップ**: テスト可能な微小な変更を積み重ねる\n3. **テスト駆動**: テストはセーフティネットである\n4. **継続的**: リファクタリングは一度きりの作業ではなく継続的に行う\n5. **協調的**: 各フェーズでユーザーの承認が必要\n\n## ワークフロー概要\n\n```\nPhase 1: Research & Analysis\n    ↓\nPhase 2: Test Coverage Assessment\n    ↓\nPhase 3: Code Smell Identification\n    ↓\nPhase 4: Refactoring Plan Creation\n    ↓\nPhase 5: Incremental Implementation\n    ↓\nPhase 6: Review & Iteration\n```\n\n---\n\n## フェーズ 1: リサーチと分析\n\n### 目的\n- コードベースの構造と目的を把握する\n- リファクタリングの範囲を特定する\n- ビジネス要件に関するコンテキストを収集する\n\n### ユーザーへの確認事項\n開始前に次の点を明確化する。\n\n1. **範囲**: どのファイル/モジュール/関数をリファクタリングするのか?\n2. **目標**: 何を解決したいのか?(可読性、性能、保守性)\n3. **制約**: 変更してはいけない領域はあるか?\n4. **時間的圧力**: 他作業のブロッカーになっているか?\n5. **テスト状況**: テストは存在するか?パスしているか?\n\n### アクション\n- [ ] 対象コードを読み、理解する\n- [ ] 依存関係と統合箇所を洗い出す\n- [ ] 現行アーキテクチャを文書化する\n- [ ] 既存の技術的負債マーカー(TODO、FIXME)を控える\n\n### 出力\nユーザーへの提示内容:\n- コード構造のサマリー\n- 検出された問題箇所\n- 初期推奨事項\n- **着手の承認を依頼する**\n\n---\n\n## フェーズ 2: テストカバレッジの評価\n\n### なぜテストが重要か\n> \"Refactoring without tests is like driving without a seatbelt.\" — Martin Fowler\n\nテストは安全なリファクタリングを可能にする**鍵となる要素**である。テストがなければ、バグを混入させるリスクがある。\n\n### 評価ステップ\n\n1. **既存テストの確認**\n   ```bash\n   # テストファイルを探す\n   find . -name \"*test*\" -o -name \"*spec*\" | head -20\n   ```\n\n2. **既存テストの実行**\n   ```bash\n   # JavaScript/TypeScript\n   npm test\n\n   # Python\n   pytest -v\n\n   # Java\n   mvn test\n   ```\n\n3. **カバレッジの確認(可能な場合)**\n   ```bash\n   # JavaScript\n   npm run test:coverage\n\n   # Python\n   pytest --cov=.\n   ```\n\n### 判断ポイント: ユーザーへの確認\n\n**テストが存在し、かつパスしている場合:**\n- フェーズ 3 へ進む\n\n**テストが不足、または不完全な場合:**\n次の選択肢を提示する。\n1. 先にテストを書く(推奨)\n2. リファクタリング中に段階的にテストを追加する\n3. テストなしで進める(リスクあり、ユーザーの明示的同意が必要)\n\n**テストが失敗している場合:**\n- STOP。リファクタリング前に失敗テストを修正する\n- ユーザーに確認: 先にテストを直すべきか?\n\n### テスト作成のガイドライン(必要時)\n\nリファクタリング対象の各関数について、以下をテストでカバーする。\n- ハッピーパス(通常動作)\n- エッジケース(空入力、null、境界値)\n- エラーシナリオ(無効入力、例外)\n\n「red-green-refactor」サイクルを用いる。\n1. 失敗するテストを書く(red)\n2. パスさせる(green)\n3. リファクタリングする\n\n---\n\n## フェーズ 3: コードスメルの特定\n\n### コードスメルとは?\nコードに潜むより深い問題の症状である。バグそのものではないが、コード改善の余地を示す指標となる。\n\n### よくチェックすべきコードスメル\n\n完全なカタログは [references/code-smells.md](references/code-smells.md) を参照。\n\n#### クイックリファレンス\n\n| スメル | 兆候 | 影響 |\n|-------|-------|--------|\n| **Long Method（長すぎる関数）** | メソッドが 30〜50 行を超える | 理解、テスト、保守が困難 |\n| **Duplicated Code（重複したコード）** | 同じロジックが複数箇所に存在 | バグ修正を複数箇所で行う必要がある |\n| **Large Class（巨大なクラス）** | 責務が多すぎるクラス | 単一責任原則に違反 |\n| **Feature Envy（機能の横恋慕）** | 他クラスのデータを多く使用するメソッド | カプセル化が不十分 |\n| **Primitive Obsession（プリミティブ型への執着）** | オブジェクト化すべき所をプリミティブで多用 | ドメイン概念が欠落 |\n| **Long Parameter List（長すぎるパラメータリスト）** | パラメータが 4 個以上 | 正しく呼び出すのが困難 |\n| **Data Clumps（データの群れ）** | 同じデータ項目が常に一緒に現れる | 抽象化が欠落 |\n| **Switch Statements（スイッチ文)** | 複雑な switch / if-else の連鎖 | 拡張が困難 |\n| **Speculative Generality（投機的一般化）** | 「念のため」のコード | 不要な複雑さ |\n| **Dead Code（デッドコード）** | 使われていないコード | 混乱と保守負担 |\n\n### 分析ステップ\n\n1. **自動分析**(スクリプトが利用可能な場合)\n   ```bash\n   python scripts/detect-smells.py <file>\n   ```\n\n2. **手動レビュー**\n   - コードを体系的に読み進める\n   - 各スメルを場所と深刻度とともに記録する\n   - 影響度別に分類する(Critical / High / Medium / Low)\n\n3. **優先順位付け**\n   次のようなスメルに注力する。\n   - 現在の開発をブロックしているもの\n   - バグや混乱を引き起こしているもの\n   - 変更頻度が高いコードパスに影響するもの\n\n### 出力: スメルレポート\n\nユーザーへの提示内容:\n- 検出されたスメルの一覧と場所\n- 各スメルの深刻度評価\n- 推奨される優先順位\n- **優先順位の承認を依頼する**\n\n---\n\n## フェーズ 4: リファクタリング計画の作成\n\n### リファクタリング技法の選定\n\n各スメルに対して、カタログから適切なリファクタリング技法を選ぶ。\n\n完全な一覧は [references/refactoring-catalog.md](references/refactoring-catalog.md) を参照。\n\n#### スメル別の推奨リファクタリング\n\n| コードスメル | 推奨リファクタリング |\n|------------|---------------------------|\n| Long Method（長すぎる関数） | メソッドの抽出、Replace Temp with Query |\n| Duplicated Code（重複したコード） | メソッドの抽出、Pull Up Method、Form Template Method |\n| Large Class（巨大なクラス） | クラスの抽出、Extract Subclass |\n| Feature Envy（機能の横恋慕） | Move Method、Move Field |\n| Primitive Obsession（プリミティブ型への執着） | Replace Primitive with Object、Replace Type Code with Class |\n| Long Parameter List（長すぎるパラメータリスト） | パラメータオブジェクトの導入、Preserve Whole Object |\n| Data Clumps（データの群れ） | クラスの抽出、パラメータオブジェクトの導入 |\n| Switch Statements（スイッチ文） | ポリモーフィズムによる条件記述の置き換え |\n| Speculative Generality（投機的一般化） | Collapse Hierarchy、Inline Class、デッドコードの削除 |\n| Dead Code（デッドコード） | デッドコードの削除 |\n\n### 計画の構成\n\n[templates/refactoring-plan.md](templates/refactoring-plan.md) のテンプレートを使用する。\n\n各リファクタリングごとに次の項目を埋める。\n1. **対象**: 何を変更するか\n2. **スメル**: どの問題に対処するか\n3. **リファクタリング**: どの技法を適用するか\n4. **手順**: 細かいマイクロステップ\n5. **リスク**: 何が失敗しうるか\n6. **ロールバック**: 取り消す方法\n\n### 段階的アプローチ\n\n**重要**: リファクタリングはフェーズに分けて段階的に導入する。\n\n**フェーズ A: クイックウィン**(低リスク、高価値)\n- 明確化のための変数名変更\n- 明らかな重複コードの抽出\n- デッドコードの削除\n\n**フェーズ B: 構造改善**(中リスク)\n- 長すぎる関数からのメソッド抽出\n- パラメータオブジェクトの導入\n- メソッドを適切なクラスへ移動\n\n**フェーズ C: アーキテクチャ変更**(高リスク)\n- 条件分岐をポリモーフィズムで置換\n- クラスの抽出\n- デザインパターンの導入\n\n### 判断ポイント: ユーザーへの計画提示\n\n実装前に:\n- 完全なリファクタリング計画を提示する\n- 各フェーズの内容とリスクを説明する\n- 各フェーズについて明示的な承認を得る\n- **質問**: 「フェーズ A を進めてもよいか?」\n\n---\n\n## フェーズ 5: 段階的な実装\n\n### ゴールデンルール\n> \"Change → Test → Green? → Commit → Next step\"\n\n### 実装のリズム\n\n各リファクタリングステップで:\n\n1. **事前チェック**\n   - テストがパスしている(green)\n   - コードがコンパイルできる\n\n2. **小さな変更を 1 つだけ行う**\n   - カタログのメカニクスに従う\n   - 変更は最小限に保つ\n\n3. **検証**\n   - 直ちにテストを実行\n   - コンパイルエラーがないか確認\n\n4. **テストがパス(green)した場合**\n   - 説明的なコミットメッセージでコミット\n   - 次のステップへ進む\n\n5. **テストが失敗(red)した場合**\n   - 直ちに STOP\n   - 変更を取り消す\n   - 何が起きたかを分析する\n   - 不明な場合はユーザーに確認する\n\n### コミット戦略\n\n各コミットは次の性質を満たすこと。\n- **アトミック**: 論理的に 1 つの変更\n- **可逆**: 容易に revert できる\n- **説明的**: 明確なコミットメッセージ\n\nコミットメッセージ例:\n```\nrefactor: Extract calculateTotal() from processOrder()\nrefactor: Rename 'x' to 'customerCount' for clarity\nrefactor: Remove unused validateOldFormat() method\n```\n\n### 進捗報告\n\nサブフェーズごとに、ユーザーへ次を報告する。\n- 行った変更\n- テストはまだパスしているか\n- 発生した問題\n- **質問**: 「次のバッチへ進めてもよいか?」\n\n---\n\n## フェーズ 6: レビューと反復\n\n### リファクタリング後チェックリスト\n\n- [ ] 全テストがパスする\n- [ ] 新たな警告/エラーが出ていない\n- [ ] コードが正常にコンパイルできる\n- [ ] 振る舞いが変わっていない(手動検証)\n- [ ] 必要に応じてドキュメントが更新されている\n- [ ] コミット履歴が整理されている\n\n### メトリクス比較\n\nリファクタリング前後で複雑度解析を実施する。\n```bash\npython scripts/analyze-complexity.py <file>\n```\n\n改善点を提示する。\n- コード行数の変化\n- 循環的複雑度の変化\n- 保守性指数の変化\n\n### ユーザーレビュー\n\n最終結果を提示する。\n- 全変更のサマリー\n- Before / After のコード比較\n- メトリクスの改善\n- 残る技術的負債\n- **質問**: 「この変更内容で問題ないか?」\n\n### 次のステップ\n\nユーザーと議論する。\n- 追加で対処すべきスメルはあるか?\n- フォローアップのリファクタリングを計画するか?\n- 同様の変更を他箇所にも適用するか?\n\n---\n\n## 重要なガイドライン\n\n### STOP してユーザーに相談すべきタイミング\n\n次の場合、必ず一旦止まりユーザーに相談する。\n- ビジネスロジックに不確実性がある\n- 外部 API に影響しうる変更\n- テストカバレッジが不十分\n- 重大なアーキテクチャ判断が必要\n- リスクレベルが上昇する\n- 想定外の複雑さに遭遇した\n\n### 安全のためのルール\n\n1. **テストなしでリファクタリングしない**(ユーザーが明示的にリスクを受容しない限り)\n2. **大きな変更を一度にしない** - 微小なステップに分割する\n3. **各変更後のテスト実行を省略しない**\n4. **テスト失敗時は続行しない** - 修正かロールバックを先に行う\n5. **思い込みで進めない** - 疑問があれば確認する\n\n### やってはいけないこと\n\n- リファクタリングと機能追加を同時に行わない\n- 本番障害対応中にリファクタリングしない\n- 理解していないコードをリファクタリングしない\n- 過剰設計をしない - シンプルに保つ\n- 全てを一度にリファクタリングしない\n\n---\n\n## クイックスタート例\n\n### シナリオ: 重複を含む長い関数\n\n**Before:**\n```javascript\nfunction processOrder(order) {\n  // 150 行のコードに以下が混在:\n  // - 重複したバリデーションロジック\n  // - インラインの計算処理\n  // - 複数の責務\n}\n```\n\n**リファクタリング手順:**\n\n1. processOrder() に対する**テストの存在を確認**\n2. バリデーションを validateOrder() に**抽出**\n3. **テスト** - パスすること\n4. 計算を calculateOrderTotal() に**抽出**\n5. **テスト** - パスすること\n6. 通知を notifyCustomer() に**抽出**\n7. **テスト** - パスすること\n8. **レビュー** - processOrder() は明確な 3 関数の調整役となる\n\n**After:**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const total = calculateOrderTotal(order);\n  notifyCustomer(order, total);\n  return { order, total };\n}\n```\n\n---\n\n## 参考文献\n\n- [Code Smells Catalog](references/code-smells.md) - コードスメルの完全な一覧\n- [Refactoring Catalog](references/refactoring-catalog.md) - リファクタリング技法\n- [Refactoring Plan Template](templates/refactoring-plan.md) - 計画用テンプレート\n\n## スクリプト\n\n- `scripts/analyze-complexity.py` - コード複雑度メトリクスの分析\n- `scripts/detect-smells.py` - スメルの自動検出\n\n## バージョン履歴\n\n- v1.0.0 (2025-01-15): Fowler の方法論、段階的アプローチ、ユーザー相談ポイントを備えた初版リリース\n","isInternal":false,"tokens":5617,"sizeBytes":15546},{"name":"SKILL.md","path":"uk/03-skills/blog-draft/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/uk/03-skills/blog-draft/SKILL.md","title":"blog-draft","category":"anthropic-skill","format":"markdown","content":"---\nname: blog-draft\ndescription: Створення чернетки блог-посту з ідей та ресурсів. Використовуйте, коли користувачі хочуть написати блог-пост, створити контент з дослідження або підготувати статтю. Проводить через дослідження, мозковий штурм, складання плану та ітеративне написання з контролем версій.\n---\n\n## Введення користувача\n\n```text\n$ARGUMENTS\n```\n\nВи **ПОВИННІ** врахувати введення користувача перед продовженням. Користувач має надати:\n- **Ідея/Тема**: Основна концепція або тематика блог-посту\n- **Ресурси**: URL, файли або посилання на дослідження (необовʼязково, але рекомендовано)\n- **Цільова аудиторія**: Для кого блог-пост (необовʼязково)\n- **Тон/Стиль**: Формальний, невимушений, технічний тощо (необовʼязково)\n\n**ВАЖЛИВО**: Якщо користувач запитує оновлення **існуючого блог-посту**, пропустіть кроки 0-8 і починайте безпосередньо з **Кроку 9**. Спочатку прочитайте існуючий файл(и) чернетки, потім продовжуйте з процесом ітерації.\n\n## Потік виконання\n\nВиконуйте ці кроки послідовно. **Не пропускайте кроки та не продовжуйте без затвердження користувача, де це зазначено.**\n\n### Крок 0: Створення папки проєкту\n\n1. Згенерувати назву папки у форматі: `YYYY-MM-DD-short-topic-name`\n   - Використати сьогоднішню дату\n   - Створити короткий, URL-дружній slug з теми (малі літери, дефіси, макс. 5 слів)\n\n2. Створити структуру папок:\n   ```\n   blog-posts/\n   └── YYYY-MM-DD-short-topic-name/\n       └── resources/\n   ```\n\n3. Підтвердити створення папки з користувачем перед продовженням.\n\n### Крок 1: Дослідження та збір ресурсів\n\n1. Створити підпапку `resources/` у каталозі блог-посту\n\n2. Для кожного наданого ресурсу:\n   - **URL-адреси**: Отримати та зберегти ключову інформацію до `resources/` як markdown-файли\n   - **Файли**: Прочитати та підсумувати в `resources/`\n   - **Теми**: Використати веб-пошук для збору актуальної інформації\n\n3. Для кожного ресурсу створити файл резюме в `resources/`:\n   - `resources/source-1-[short-name].md`\n   - `resources/source-2-[short-name].md`\n   - тощо\n\n4. Кожне резюме має включати:\n   ```markdown\n   # Джерело: [Назва/URL]\n\n   ## Ключові тези\n   - Теза 1\n   - Теза 2\n\n   ## Релевантні цитати/дані\n   - Цитата або статистика 1\n   - Цитата або статистика 2\n\n   ## Як це стосується теми\n   Короткий опис релевантності\n   ```\n\n5. Представити резюме дослідження користувачу.\n\n### Крок 2: Мозковий штурм та уточнення\n\n1. На основі ідеї та досліджених ресурсів представити:\n   - **Основні теми**, виявлені з дослідження\n   - **Потенційні ракурси** для блог-посту\n   - **Ключові тези**, які слід розкрити\n   - **Прогалини** в інформації, що потребують уточнення\n\n2. Поставити уточнюючі запитання:\n   - Який головний висновок ви хочете донести до читачів?\n   - Чи є конкретні тези з дослідження, які хочете виділити?\n   - Яка цільова довжина? (коротка: 500-800 слів, середня: 1000-1500, довга: 2000+)\n   - Щось хочете виключити?\n\n3. **Чекати відповідей користувача перед продовженням.**\n\n### Крок 3: Запропонувати план\n\n1. Створити структурований план, що включає:\n\n   ```markdown\n   # План блог-посту: [Назва]\n\n   ## Метаінформація\n   - **Цільова аудиторія**: [хто]\n   - **Тон**: [стиль]\n   - **Цільова довжина**: [кількість слів]\n   - **Головний висновок**: [ключове повідомлення]\n\n   ## Запропонована структура\n\n   ### Зачіпка/Вступ\n   - Ідея вступної зачіпки\n   - Встановлення контексту\n   - Теза\n\n   ### Розділ 1: [Назва]\n   - Ключова теза A\n   - Ключова теза B\n   - Підтверджуючі докази з [джерела]\n\n   ### Розділ 2: [Назва]\n   - Ключова теза A\n   - Ключова теза B\n\n   [Продовжити для всіх розділів...]\n\n   ### Висновок\n   - Резюме ключових тез\n   - Заклик до дії або завершальна думка\n\n   ## Джерела для цитування\n   - Джерело 1\n   - Джерело 2\n   ```\n\n2. Представити план користувачу та **запитати затвердження або модифікації**.\n\n### Крок 4: Зберегти затверджений план\n\n1. Після затвердження плану користувачем зберегти його як `OUTLINE.md` у папці блог-посту.\n\n2. Підтвердити збереження плану.\n\n### Крок 5: Закомітити план (якщо в git-репо)\n\n1. Перевірити, чи поточний каталог є git-репозиторієм.\n\n2. Якщо так:\n   - Додати нові файли до індексу: папку блог-посту, ресурси та OUTLINE.md\n   - Створити коміт з повідомленням: `docs: Add outline for blog post - [topic-name]`\n   - Відправити на віддалений сервер\n\n3. Якщо не git-репо, пропустити цей крок та повідомити користувача.\n\n### Крок 6: Написати чернетку\n\n1. На основі затвердженого плану написати повну чернетку блог-посту.\n\n2. Точно дотримуватися структури з OUTLINE.md.\n\n3. Включити:\n   - Захопливий вступ із зачіпкою\n   - Чіткі заголовки розділів\n   - Підтверджуючі докази та приклади з дослідження\n   - Плавні переходи між розділами\n   - Сильний висновок з головною тезою\n   - **Цитування**: Усі порівняння, статистика, дані та фактичні твердження ПОВИННІ цитувати оригінальне джерело\n\n4. Зберегти чернетку як `draft-v0.1.md` у папці блог-посту.\n\n5. Формат:\n   ```markdown\n   # [Назва блог-посту]\n\n   *[Необовʼязково: підзаголовок або слоган]*\n\n   [Повний вміст з інлайн-цитатами...]\n\n   ---\n\n   ## Список джерел\n   - [1] Назва джерела 1 - URL або цитата\n   - [2] Назва джерела 2 - URL або цитата\n   - [3] Назва джерела 3 - URL або цитата\n   ```\n\n6. **Вимоги до цитування**:\n   - Кожна точка даних, статистика або порівняння ПОВИННІ мати інлайн-цитату\n   - Використовуйте нумеровані посилання [1], [2] тощо, або іменовані цитати [Назва джерела]\n   - Звʼязуйте цитати з розділом Список джерел наприкінці\n   - Приклад: «Дослідження показують, що 65% розробників віддають перевагу TypeScript [1]»\n   - Приклад: «React перевершує Vue за швидкістю рендерингу на 20% [React Benchmarks 2024]»\n\n### Крок 7: Закомітити чернетку (якщо в git-репо)\n\n1. Перевірити, чи в git-репозиторії.\n\n2. Якщо так:\n   - Додати файл чернетки до індексу\n   - Створити коміт з повідомленням: `docs: Add draft v0.1 for blog post - [topic-name]`\n   - Відправити на віддалений сервер\n\n3. Якщо не git-репо, пропустити та повідомити користувача.\n\n### Крок 8: Представити чернетку для перегляду\n\n1. Представити вміст чернетки користувачу.\n\n2. Запитати зворотний звʼязок:\n   - Загальне враження?\n   - Розділи, що потребують розширення або скорочення?\n   - Потрібні корекції тону?\n   - Відсутня інформація?\n   - Конкретні правки або переписування?\n\n3. **Чекати відповіді користувача.**\n\n### Крок 9: Ітерація або фіналізація\n\n**Якщо користувач запитує зміни:**\n1. Зафіксувати всі запитані модифікації\n2. Повернутися до Кроку 6 з такими змінами:\n   - Збільшити номер версії (v0.2, v0.3 тощо)\n   - Врахувати всі зауваження\n   - Зберегти як `draft-v[X.Y].md`\n   - Повторити Кроки 7-8\n\n**Якщо користувач затверджує:**\n1. Підтвердити фінальну версію чернетки\n2. За бажанням перейменувати на `final.md`\n3. Підсумувати процес створення блог-посту:\n   - Загальна кількість створених версій\n   - Ключові зміни між версіями\n   - Фінальна кількість слів\n   - Створені файли\n\n## Відстеження версій\n\nУсі чернетки зберігаються з інкрементальним версіонуванням:\n- `draft-v0.1.md` — початкова чернетка\n- `draft-v0.2.md` — після першого раунду зауважень\n- `draft-v0.3.md` — після другого раунду зауважень\n- тощо\n\nЦе дозволяє відстежувати еволюцію блог-посту та повертатися до попередніх версій за потреби.\n\n## Структура вихідних файлів\n\n```\nblog-posts/\n└── YYYY-MM-DD-topic-name/\n    ├── resources/\n    │   ├── source-1-name.md\n    │   ├── source-2-name.md\n    │   └── ...\n    ├── OUTLINE.md\n    ├── draft-v0.1.md\n    ├── draft-v0.2.md (якщо ітерації)\n    └── draft-v0.3.md (якщо більше ітерацій)\n```\n\n## Поради щодо якості\n\n- **Зачіпка**: Починайте з питання, дивовижного факту або знайомого сценарію\n- **Потік**: Кожен абзац має зʼєднуватися з наступним\n- **Докази**: Підтверджуйте твердження даними з дослідження\n- **Цитування**: ЗАВЖДИ цитуйте джерела для:\n  - Усіх статистик та даних (напр., «За даними [Джерело], 75%...»)\n  - Порівнянь між продуктами, сервісами або підходами (напр., «X працює у 2 рази швидше за Y [Джерело]»)\n  - Фактичних тверджень про ринкові тенденції, результати досліджень або бенчмарки\n  - Використовуйте інлайн-цитати у форматі: [Назва джерела] або [Автор, Рік]\n- **Голос**: Підтримуйте послідовний тон протягом усього тексту\n- **Довжина**: Дотримуйтесь цільової кількості слів\n- **Читабельність**: Використовуйте короткі абзаци, маркери де доречно\n- **CTA**: Завершуйте чітким закликом до дії або питанням, що провокує думки\n\n## Примітки\n\n- Завжди чекайте затвердження користувача у зазначених контрольних точках\n- Зберігайте всі версії чернеток для історії\n- Використовуйте веб-пошук для актуальної інформації, коли надані URL\n- Якщо ресурсів недостатньо, попросіть користувача надати більше або запропонуйте додаткове дослідження\n- Адаптуйте тон відповідно до цільової аудиторії (технічна, загальна, бізнес тощо)\n","frontmatter":{"name":"blog-draft","description":"Створення чернетки блог-посту з ідей та ресурсів. Використовуйте, коли користувачі хочуть написати блог-пост, створити контент з дослідження або підготувати статтю. Проводить через дослідження, мозковий штурм, складання плану та ітеративне написання з контролем версій."},"isInternal":false,"tokens":4730,"sizeBytes":14428},{"name":"SKILL.md","path":"uk/03-skills/brand-voice/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/uk/03-skills/brand-voice/SKILL.md","title":"brand-voice","category":"anthropic-skill","format":"markdown","content":"---\nname: brand-voice\ndescription: Забезпечення відповідності всіх комунікацій голосу та тону бренду. Використовуйте при створенні маркетингових текстів, клієнтських комунікацій, публічного контенту, або коли користувачі згадують голос бренду, тон чи стиль написання.\nuser-invocable: false\n---\n\n# Навичка голосу бренду\n\n## Огляд\nЦя навичка забезпечує послідовність голосу бренду, тону та повідомлень у всіх комунікаціях.\n\n## Ідентичність бренду\n\n### Місія\nДопомогти командам автоматизувати робочі процеси розробки за допомогою AI\n\n### Цінності\n- **Простота**: Робити складне простим\n- **Надійність**: Непохитне виконання\n- **Розширення можливостей**: Дати простір людській креативності\n\n### Тон голосу\n- **Дружній, але професійний** — доступний, але не панібратський\n- **Зрозумілий і лаконічний** — уникати жаргону, пояснювати технічні концепції просто\n- **Впевнений** — ми знаємо, що робимо\n- **Емпатичний** — розуміємо потреби та болі користувачів\n\n## Рекомендації щодо написання\n\n### Рекомендовано ✅\n- Використовуйте «ви» при зверненні до читачів\n- Використовуйте активний стан: «Claude генерує звіти», а не «Звіти генеруються Claude»\n- Починайте з ціннісної пропозиції\n- Використовуйте конкретні приклади\n- Тримайте речення до 20 слів\n- Використовуйте списки для ясності\n- Включайте заклики до дії\n\n### Не рекомендовано ❌\n- Не використовуйте корпоративний жаргон\n- Не будьте поблажливими та не надмірно спрощуйте\n- Не використовуйте «ми вважаємо» або «ми думаємо»\n- Не використовуйте ВСІ ВЕЛИКІ ЛІТЕРИ, крім виділення\n- Не створюйте стіни тексту\n- Не припускайте наявність технічних знань\n\n## Словник\n\n### ✅ Бажані терміни\n- Claude (не «AI Claude»)\n- Генерація коду (не «автокодування»)\n- Агент (не «бот»)\n- Оптимізувати (не «революціонізувати»)\n- Інтегрувати (не «синергізувати»)\n\n### ❌ Уникати\n- «Передовий» (заїжджено)\n- «Проривний» (розмито)\n- «Левериджити» (корпоративний жаргон)\n- «Утилізувати» (використовуйте «використовувати»)\n- «Зміна парадигми» (незрозуміло)\n\n## Приклади\n\n### ✅ Вдалий приклад\n«Claude автоматизує ваш процес код-рев'ю. Замість ручної перевірки кожного PR, Claude перевіряє безпеку, продуктивність та якість — заощаджуючи вашій команді години щотижня.»\n\nЧому працює: Зрозуміла цінність, конкретні переваги, орієнтація на дію\n\n### ❌ Невдалий приклад\n«Claude левериджить передовий AI для надання комплексних рішень розробки програмного забезпечення.»\n\nЧому не працює: Розмито, корпоративний жаргон, немає конкретної цінності\n","frontmatter":{"name":"brand-voice","description":"Забезпечення відповідності всіх комунікацій голосу та тону бренду. Використовуйте при створенні маркетингових текстів, клієнтських комунікацій, публічного контенту, або коли користувачі згадують голос бренду, тон чи стиль написання.","user-invocable":false},"isInternal":false,"tokens":1401,"sizeBytes":4322},{"name":"SKILL.md","path":"uk/03-skills/claude-md/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/uk/03-skills/claude-md/SKILL.md","title":"claude-md","category":"anthropic-skill","format":"markdown","content":"---\nname: claude-md\ndescription: Створення або оновлення файлів CLAUDE.md відповідно до найкращих практик для оптимального онбордингу AI-агента\n---\n\n## Введення користувача\n\n```text\n$ARGUMENTS\n```\n\nВи **ПОВИННІ** врахувати введення користувача перед продовженням (якщо не порожнє). Користувач може вказати:\n- `create` — створити новий CLAUDE.md з нуля\n- `update` — покращити існуючий CLAUDE.md\n- `audit` — проаналізувати та звітувати про якість поточного CLAUDE.md\n- Конкретний шлях для створення/оновлення (напр., `src/api/CLAUDE.md` для інструкцій, специфічних для каталогу)\n\n## Основні принципи\n\n**LLM не мають стану**: CLAUDE.md — головний файл проєкту, що завантажується в кожну розмову (разом з автоматичною пам'яттю та правилами без обмеження області). Він слугує головним документом онбордингу AI-агентів у вашу кодову базу.\n\n### Золоті правила\n\n1. **Менше — краще**: Найсучасніші LLM можуть дотримуватись ~150-200 інструкцій. Системний промпт Claude Code вже використовує ~50. Тримайте CLAUDE.md зосередженим та лаконічним.\n\n2. **Універсальна застосовність**: Включайте лише інформацію, релевантну для КОЖНОЇ сесії. Інструкції для конкретних завдань належать до окремих файлів.\n\n3. **Не використовуйте Claude як лінтер**: Рекомендації зі стилю роздувають контекст та погіршують дотримання інструкцій. Використовуйте натомість детерміністичні інструменти (prettier, eslint тощо).\n\n4. **Ніколи не генеруйте автоматично**: CLAUDE.md — найвпливовіша точка AI-системи. Створюйте його вручну з ретельним обмірковуванням.\n\n## Потік виконання\n\n### 1. Аналіз проєкту\n\nСпочатку проаналізуйте поточний стан проєкту:\n\n1. Перевірити наявні файли CLAUDE.md:\n   - Кореневий рівень: `./CLAUDE.md` або `.claude/CLAUDE.md`\n   - Специфічні для каталогу: `**/CLAUDE.md`\n   - Глобальний конфіг користувача: `~/.claude/CLAUDE.md`\n\n2. Визначити структуру проєкту:\n   - Технологічний стек (мови, фреймворки)\n   - Тип проєкту (монорепо, окремий додаток, бібліотека)\n   - Інструменти розробки (пакетний менеджер, система збірки, тест-раннер)\n\n3. Переглянути існуючу документацію:\n   - README.md\n   - CONTRIBUTING.md\n   - package.json, pyproject.toml, Cargo.toml тощо\n\n### 2. Стратегія контенту (ЩО, ЧОМУ, ЯК)\n\nСтруктуруйте CLAUDE.md навколо трьох вимірів:\n\n#### ЩО — Технологія та структура\n- Огляд технологічного стеку\n- Організація проєкту (особливо важливо для монорепо)\n- Ключові каталоги та їхнє призначення\n\n#### ЧОМУ — Призначення та контекст\n- Що робить проєкт\n- Чому були прийняті певні архітектурні рішення\n- За що відповідає кожен основний компонент\n\n#### ЯК — Робочий процес та конвенції\n- Робочий процес розробки (bun vs node, pip vs uv тощо)\n- Процедури та команди тестування\n- Методи верифікації та збірки\n- Критичні «підводні камені» або неочевидні вимоги\n\n### 3. Стратегія поступового розкриття\n\nДля великих проєктів рекомендуйте створити папку `agent_docs/`:\n\n```\nagent_docs/\n  |- building_the_project.md\n  |- running_tests.md\n  |- code_conventions.md\n  |- architecture_decisions.md\n```\n\nУ CLAUDE.md посилайтесь на ці файли інструкціями:\n```markdown\nFor detailed build instructions, refer to `agent_docs/building_the_project.md`\n```\n\n**Важливо**: Використовуйте посилання `файл:рядок` замість фрагментів коду, щоб уникнути застарілого контексту.\n\n### 4. Обмеження якості\n\nПри створенні або оновленні CLAUDE.md:\n\n1. **Цільова довжина**: Менше 200 рядків\n2. **Без правил стилю**: Видалити будь-які інструкції лінтингу/форматування\n3. **Без інструкцій для конкретних завдань**: Перемістити до окремих файлів\n4. **Без фрагментів коду**: Використовувати посилання на файли замість цього\n5. **Без надлишкової інформації**: Не повторювати те, що є в package.json або README\n\n### 5. Обовʼязкові секції\n\nДобре структурований CLAUDE.md має включати:\n\n```markdown\n# Назва проєкту\n\nКороткий однорядковий опис.\n\n## Технологічний стек\n- Основна мова та версія\n- Ключові фреймворки/бібліотеки\n- База даних/сховище (якщо є)\n\n## Структура проєкту\n[Лише для монорепо або складних структур]\n- `apps/` - Точки входу додатків\n- `packages/` - Спільні бібліотеки\n\n## Команди розробки\n- Встановлення: `команда`\n- Тестування: `команда`\n- Збірка: `команда`\n\n## Критичні конвенції\n[Лише неочевидні, високовпливові конвенції]\n- Конвенція 1 з коротким поясненням\n- Конвенція 2 з коротким поясненням\n\n## Відомі проблеми / Підводні камені\n[Речі, що постійно створюють труднощі розробникам]\n- Проблема 1\n- Проблема 2\n```\n\n### 6. Антипатерни, яких слід уникати\n\n**НЕ включайте:**\n- Рекомендації зі стилю коду (використовуйте лінтери)\n- Документацію щодо використання Claude\n- Довгі пояснення очевидних патернів\n- Скопійовані приклади коду\n- Загальні найкращі практики («пишіть чистий код»)\n- Інструкції для конкретних завдань\n- Автозгенерований контент\n- Розлогі списки TODO\n\n### 7. Контрольний список валідації\n\nПеред фіналізацією перевірте:\n\n- [ ] Менше 200 рядків\n- [ ] Кожен рядок застосовний до ВСІХ сесій\n- [ ] Без правил стилю/форматування\n- [ ] Без фрагментів коду (використані посилання на файли)\n- [ ] Команди перевірені на працездатність\n- [ ] Поступове розкриття використано для складних проєктів\n- [ ] Критичні підводні камені задокументовані\n- [ ] Немає надлишковості з README.md\n\n## Формат виводу\n\n### Для `create` або за замовчуванням:\n\n1. Проаналізувати проєкт\n2. Створити чернетку CLAUDE.md за структурою вище\n3. Представити чернетку для перегляду\n4. Записати у відповідне місце після затвердження\n\n### Для `update`:\n\n1. Прочитати існуючий CLAUDE.md\n2. Аудит за найкращими практиками\n3. Визначити:\n   - Контент для видалення (правила стилю, фрагменти коду, специфічне для завдань)\n   - Контент для скорочення\n   - Відсутню важливу інформацію\n4. Представити зміни для перегляду\n5. Застосувати зміни після затвердження\n\n### Для `audit`:\n\n1. Прочитати існуючий CLAUDE.md\n2. Згенерувати звіт з:\n   - Поточна кількість рядків vs ціль\n   - Відсоток універсально застосовного контенту\n   - Список знайдених антипатернів\n   - Рекомендації для покращення\n3. НЕ модифікувати файл, лише звітувати\n\n## Обробка AGENTS.md\n\nЯкщо користувач запитує створення/оновлення AGENTS.md:\n\n**Починаючи з v2.1.277, Claude Code читає `AGENTS.md` напряму як інструкції проєкту** — але лише тоді, коли ні в робочому каталозі, ні в жодному каталозі вище немає `CLAUDE.md`, `.claude/CLAUDE.md` чи `CLAUDE.local.md`. `~/.claude/CLAUDE.md`, керований CLAUDE.md і `.claude/rules/` не враховуються в цій перевірці та завантажуються паралельно. Поведінку визначає **Project instructions** у `/config`: `claude-md-or-agents-md` (за замовчуванням), `claude-md-and-agents-md`, `claude-md` або `managed-only`. Там, де пряме читання недоступне — версії до v2.1.277 (до v2.1.281 на Bedrock/Vertex/Foundry, за LLM-шлюзами або з вимкненою телеметрією) або перша сесія після оновлення — використовуйте запасний варіант: імпортуйте файл з CLAUDE.md через `@AGENTS.md` або зробіть `CLAUDE.md` символічним посиланням на нього.\n\nAGENTS.md — це міжінструментальний файл контексту проєкту, тобто документ тієї ж *категорії*, що й CLAUDE.md, а не формат визначення агентів. Він існує для того, щоб кілька кодових агентів могли користуватися спільним набором конвенцій проєкту:\n- Команди збірки, тестування та лінтингу\n- Стиль коду та архітектурні конвенції\n- Структура репозиторію та розташування компонентів\n\nСубагенти визначаються окремо — у `.claude/agents/*.md`, а не в AGENTS.md.\n\nЗастосовуйте аналогічні принципи:\n- Тримайте зосередженим та лаконічним\n- Використовуйте поступове розкриття\n- Посилайтесь на зовнішні документи замість вбудовування контенту\n\n## Примітки\n\n- Завжди перевіряйте працездатність команд перед їх включенням\n- Якщо сумніваєтесь — не включайте; менше — краще\n- Системне нагадування повідомляє Claude, що CLAUDE.md «може бути або не бути релевантним» — чим більше шуму, тим більше він ігнорується\n- Монорепо найбільше виграють від чіткої структури ЩО/ЧОМУ/ЯК\n- Файли CLAUDE.md для конкретних каталогів мають бути ще більш зосередженими\n\n---\n\n**Останнє оновлення**: 18 жовтня 2026\n**Версія Claude Code**: 2.1.302\n**Джерела**:\n- https://code.claude.com/docs/en/memory\n","frontmatter":{"name":"claude-md","description":"Створення або оновлення файлів CLAUDE.md відповідно до найкращих практик для оптимального онбордингу AI-агента"},"isInternal":false,"tokens":4243,"sizeBytes":13261},{"name":"SKILL.md","path":"uk/03-skills/code-review-specialist/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/uk/03-skills/code-review-specialist/SKILL.md","title":"code-review-specialist","category":"anthropic-skill","format":"markdown","content":"---\nname: code-review-specialist\ndescription: Комплексне код-рев'ю з аналізом безпеки, продуктивності та якості. Використовуйте, коли користувачі просять переглянути код, проаналізувати якість коду, оцінити pull request, або згадують код-рев'ю, аналіз безпеки чи оптимізацію продуктивності.\n---\n\n# Навичка код-рев'ю\n\nЦя навичка забезпечує комплексні можливості код-рев'ю з фокусом на:\n\n1. **Аналіз безпеки**\n   - Проблеми автентифікації/авторизації\n   - Ризики розкриття даних\n   - Вразливості інʼєкцій\n   - Криптографічні слабкості\n   - Логування чутливих даних\n\n2. **Аналіз продуктивності**\n   - Ефективність алгоритмів (аналіз Big O)\n   - Оптимізація памʼяті\n   - Оптимізація запитів до БД\n   - Можливості кешування\n   - Проблеми конкурентності\n\n3. **Якість коду**\n   - Принципи SOLID\n   - Патерни проєктування\n   - Конвенції іменування\n   - Документація\n   - Покриття тестами\n\n4. **Супровідність**\n   - Читабельність коду\n   - Розмір функцій (має бути < 50 рядків)\n   - Цикломатична складність\n   - Управління залежностями\n   - Безпека типів\n\n## Шаблон рев'ю\n\nДля кожного фрагмента перевіреного коду надати:\n\n### Резюме\n- Загальна оцінка якості (1-5)\n- Кількість виявлених проблем\n- Рекомендовані пріоритетні зони\n\n### Критичні проблеми (якщо є)\n- **Проблема**: Чіткий опис\n- **Розташування**: Файл і номер рядка\n- **Вплив**: Чому це важливо\n- **Серйозність**: Критична/Висока/Середня\n- **Виправлення**: Приклад коду\n\n### Знахідки за категоріями\n\n#### Безпека (якщо знайдено проблеми)\nПерелік вразливостей безпеки з прикладами\n\n#### Продуктивність (якщо знайдено проблеми)\nПерелік проблем продуктивності з аналізом складності\n\n#### Якість (якщо знайдено проблеми)\nПерелік проблем якості коду з пропозиціями рефакторингу\n\n#### Супровідність (якщо знайдено проблеми)\nПерелік проблем супровідності з покращеннями\n\n## Історія версій\n\n- v1.0.0 (2024-12-10): Початковий випуск з аналізом безпеки, продуктивності, якості та супровідності\n","frontmatter":{"name":"code-review-specialist","description":"Комплексне код-рев'ю з аналізом безпеки, продуктивності та якості. Використовуйте, коли користувачі просять переглянути код, проаналізувати якість коду, оцінити pull request, або згадують код-рев'ю, аналіз безпеки чи оптимізацію продуктивності."},"isInternal":false,"tokens":1059,"sizeBytes":3315},{"name":"SKILL.md","path":"uk/03-skills/doc-generator/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/uk/03-skills/doc-generator/SKILL.md","title":"doc-generator","category":"anthropic-skill","format":"markdown","content":"---\nname: doc-generator\ndescription: Генерація вичерпної, точної документації API з вихідного коду. Використовуйте при створенні або оновленні документації API, генерації специфікацій OpenAPI, або коли користувачі згадують документацію API, ендпоінти чи документацію.\n---\n\n# Навичка генерації документації API\n\n## Генерує\n\n- Специфікації OpenAPI/Swagger\n- Документацію ендпоінтів API\n- Приклади використання SDK\n- Посібники з інтеграції\n- Довідники кодів помилок\n- Посібники з автентифікації\n\n## Структура документації\n\n### Для кожного ендпоінту\n\n````markdown\n## GET /api/v1/users/:id\n\n### Опис\nКороткий опис призначення цього ендпоінту\n\n### Параметри\n\n| Назва | Тип | Обовʼязковий | Опис |\n|-------|-----|-------------|------|\n| id | string | Так | ID користувача |\n\n### Відповідь\n\n**200 Успіх**\n```json\n{\n  \"id\": \"usr_123\",\n  \"name\": \"John Doe\",\n  \"email\": \"john@example.com\",\n  \"created_at\": \"2025-01-15T10:30:00Z\"\n}\n```\n\n**404 Не знайдено**\n```json\n{\n  \"error\": \"USER_NOT_FOUND\",\n  \"message\": \"Користувач не існує\"\n}\n```\n\n### Приклади\n\n**cURL**\n```bash\ncurl -X GET \"https://api.example.com/api/v1/users/usr_123\" \\\n  -H \"Authorization: Bearer YOUR_TOKEN\"\n```\n\n**JavaScript**\n```javascript\nconst user = await fetch('/api/v1/users/usr_123', {\n  headers: { 'Authorization': 'Bearer token' }\n}).then(r => r.json());\n```\n\n**Python**\n```python\nresponse = requests.get(\n    'https://api.example.com/api/v1/users/usr_123',\n    headers={'Authorization': 'Bearer token'}\n)\nuser = response.json()\n```\n````\n","frontmatter":{"name":"doc-generator","description":"Генерація вичерпної, точної документації API з вихідного коду. Використовуйте при створенні або оновленні документації API, генерації специфікацій OpenAPI, або коли користувачі згадують документацію API, ендпоінти чи документацію."},"isInternal":false,"tokens":633,"sizeBytes":2011},{"name":"code-smells.md","path":"uk/03-skills/refactor/references/code-smells.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/uk/03-skills/refactor/references/code-smells.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Каталог запахів коду\n\nКомплексний довідник запахів коду на основі книги Мартіна Фаулера *Refactoring* (2-ге видання). Запахи коду — це симптоми глибших проблем; вони вказують на те, що щось може бути не так з дизайном вашого коду.\n\n> «Запах коду — це поверхнева ознака, яка зазвичай відповідає глибшій проблемі в системі.» — Мартін Фаулер\n\n---\n\n## Роздуті елементи (Bloaters)\n\nЗапахи коду, що представляють щось, що розрослося занадто великим для ефективної роботи.\n\n### Long Method (Довгий метод)\n\n**Ознаки:**\n- Метод перевищує 30-50 рядків\n- Потрібно прокручувати, щоб побачити весь метод\n- Кілька рівнів вкладеності\n- Коментарі пояснюють, що роблять секції\n\n**Чому це погано:**\n- Важко зрозуміти\n- Складно тестувати ізольовано\n- Зміни мають непередбачувані наслідки\n- Дубльована логіка ховається всередині\n\n**Рефакторинги:**\n- Extract Method\n- Replace Temp with Query\n- Introduce Parameter Object\n- Replace Method with Method Object\n- Decompose Conditional\n\n**Приклад (до):**\n```javascript\nfunction processOrder(order) {\n  // Валідація замовлення (20 рядків)\n  if (!order.items) throw new Error('No items');\n  if (order.items.length === 0) throw new Error('Empty order');\n  // ... ще валідація\n\n  // Обчислення підсумків (30 рядків)\n  let subtotal = 0;\n  for (const item of order.items) {\n    subtotal += item.price * item.quantity;\n  }\n  // ... податок, доставка, знижки\n\n  // Надсилання сповіщень (20 рядків)\n  // ... логіка email\n}\n```\n\n**Приклад (після):**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const totals = calculateOrderTotals(order);\n  sendOrderNotifications(order, totals);\n  return { order, totals };\n}\n```\n\n---\n\n### Large Class (Великий клас)\n\n**Ознаки:**\n- Клас має багато полів екземпляра (>7-10)\n- Клас має багато методів (>15-20)\n- Назва класу розмита (Manager, Handler, Processor)\n- Методи не використовують усі поля екземпляра\n\n**Чому це погано:**\n- Порушує принцип єдиної відповідальності\n- Важко тестувати\n- Зміни поширюються на неповʼязані функції\n- Складно повторно використовувати частини\n\n**Рефакторинги:**\n- Extract Class\n- Extract Subclass\n- Extract Interface\n\n**Виявлення:**\n```\nРядків коду > 300\nКількість методів > 15\nКількість полів > 10\n```\n\n---\n\n### Primitive Obsession (Одержимість примітивами)\n\n**Ознаки:**\n- Використання примітивів для доменних концепцій (string для email, int для грошей)\n- Масиви примітивів замість обʼєктів\n- Рядкові константи для кодів типів\n- Магічні числа/рядки\n\n**Чому це погано:**\n- Немає валідації на рівні типу\n- Логіка розкидана по кодовій базі\n- Легко передати неправильні значення\n- Відсутні доменні концепції\n\n**Рефакторинги:**\n- Replace Primitive with Object\n- Replace Type Code with Class\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**Приклад (до):**\n```javascript\nconst user = {\n  email: 'john@example.com',     // Просто рядок\n  phone: '1234567890',           // Просто рядок\n  status: 'active',              // Магічний рядок\n  balance: 10050                 // Копійки як ціле число\n};\n```\n\n**Приклад (після):**\n```javascript\nconst user = {\n  email: new Email('john@example.com'),\n  phone: new PhoneNumber('1234567890'),\n  status: UserStatus.ACTIVE,\n  balance: Money.cents(10050)\n};\n```\n\n---\n\n### Long Parameter List (Довгий список параметрів)\n\n**Ознаки:**\n- Методи з 4+ параметрами\n- Параметри, що завжди зʼявляються разом\n- Булеві прапорці, що змінюють поведінку методу\n- Часте передавання null/undefined\n\n**Чому це погано:**\n- Важко викликати правильно\n- Плутанина з порядком параметрів\n- Вказує, що метод робить занадто багато\n- Важко додавати нові параметри\n\n**Рефакторинги:**\n- Introduce Parameter Object\n- Preserve Whole Object\n- Replace Parameter with Method Call\n- Remove Flag Argument\n\n**Приклад (до):**\n```javascript\nfunction createUser(firstName, lastName, email, phone,\n                    street, city, state, zip,\n                    isAdmin, isActive, createdBy) {\n  // ...\n}\n```\n\n**Приклад (після):**\n```javascript\nfunction createUser(personalInfo, address, options) {\n  // personalInfo: { firstName, lastName, email, phone }\n  // address: { street, city, state, zip }\n  // options: { isAdmin, isActive, createdBy }\n}\n```\n\n---\n\n### Data Clumps (Групи даних)\n\n**Ознаки:**\n- Ті самі 3+ поля зʼявляються разом повторно\n- Параметри, що завжди подорожують разом\n- Класи з підмножинами полів, що належать один одному\n\n**Чому це погано:**\n- Дубльована логіка обробки\n- Відсутня абстракція\n- Важче розширювати\n- Вказує на прихований клас\n\n**Рефакторинги:**\n- Extract Class\n- Introduce Parameter Object\n- Preserve Whole Object\n\n**Приклад:**\n```javascript\n// Група даних: координати (x, y, z)\nfunction movePoint(x, y, z, dx, dy, dz) { }\nfunction scalePoint(x, y, z, factor) { }\nfunction distanceBetween(x1, y1, z1, x2, y2, z2) { }\n\n// Витяг класу Point3D\nclass Point3D {\n  constructor(x, y, z) { }\n  move(delta) { }\n  scale(factor) { }\n  distanceTo(other) { }\n}\n```\n\n---\n\n## Зловживання обʼєктною орієнтацією (OO Abusers)\n\nЗапахи, що вказують на неповне або некоректне використання принципів ООП.\n\n### Switch Statements (Оператори Switch)\n\n**Ознаки:**\n- Довгі ланцюжки switch/case або if/else\n- Той самий switch у кількох місцях\n- Switch за кодами типів\n- Додавання нових випадків вимагає змін всюди\n\n**Чому це погано:**\n- Порушує принцип відкритості/закритості\n- Зміни поширюються на всі місця з switch\n- Важко розширювати\n- Часто вказує на відсутній поліморфізм\n\n**Рефакторинги:**\n- Replace Conditional with Polymorphism\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**Приклад (до):**\n```javascript\nfunction calculatePay(employee) {\n  switch (employee.type) {\n    case 'hourly':\n      return employee.hours * employee.rate;\n    case 'salaried':\n      return employee.salary / 12;\n    case 'commissioned':\n      return employee.sales * employee.commission;\n  }\n}\n```\n\n**Приклад (після):**\n```javascript\nclass HourlyEmployee {\n  calculatePay() {\n    return this.hours * this.rate;\n  }\n}\n\nclass SalariedEmployee {\n  calculatePay() {\n    return this.salary / 12;\n  }\n}\n```\n\n---\n\n### Temporary Field (Тимчасове поле)\n\n**Ознаки:**\n- Поля екземпляра, що використовуються лише в деяких методах\n- Поля, що встановлюються умовно\n- Складна ініціалізація для певних випадків\n\n**Чому це погано:**\n- Плутанина — поле існує, але може бути null\n- Важко зрозуміти стан обʼєкта\n- Вказує на приховану умовну логіку\n\n**Рефакторинги:**\n- Extract Class\n- Introduce Null Object\n- Replace Temp Field with Local\n\n---\n\n### Refused Bequest (Відхилена спадщина)\n\n**Ознаки:**\n- Підклас не використовує успадковані методи/дані\n- Підклас перевизначає, щоб нічого не робити\n- Успадкування використовується для повторного використання коду, а не для відношення IS-A\n\n**Чому це погано:**\n- Неправильна абстракція\n- Порушує принцип підстановки Лісков\n- Оманлива ієрархія\n\n**Рефакторинги:**\n- Push Down Method/Field\n- Replace Subclass with Delegate\n- Replace Inheritance with Delegation\n\n---\n\n### Alternative Classes with Different Interfaces (Альтернативні класи з різними інтерфейсами)\n\n**Ознаки:**\n- Два класи, що роблять схожі речі\n- Різні назви методів для тієї самої концепції\n- Можуть використовуватися взаємозамінно\n\n**Чому це погано:**\n- Дубльовані реалізації\n- Немає спільного інтерфейсу\n- Важко перемикатися між ними\n\n**Рефакторинги:**\n- Rename Method\n- Move Method\n- Extract Superclass\n- Extract Interface\n\n---\n\n## Перешкоди для змін (Change Preventers)\n\nЗапахи, що ускладнюють зміни — зміна однієї речі вимагає зміни багатьох інших.\n\n### Divergent Change (Дивергентна зміна)\n\n**Ознаки:**\n- Один клас змінюється з кількох різних причин\n- Зміни в різних областях запускають редагування того самого класу\n- Клас є «God-класом»\n\n**Чому це погано:**\n- Порушує принцип єдиної відповідальності\n- Висока частота змін\n- Конфлікти злиття\n\n**Рефакторинги:**\n- Extract Class\n- Extract Superclass\n- Extract Subclass\n\n**Приклад:**\nКлас `User` змінюється через:\n- Зміни автентифікації\n- Зміни профілю\n- Зміни білінгу\n- Зміни сповіщень\n\n→ Витягти: `AuthService`, `ProfileService`, `BillingService`, `NotificationService`\n\n---\n\n### Shotgun Surgery (Хірургія дробовиком)\n\n**Ознаки:**\n- Одна зміна вимагає редагування в багатьох класах\n- Мала функція потребує правок у 10+ файлах\n- Зміни розкидані, важко знайти всі\n\n**Чому це погано:**\n- Легко пропустити місце\n- Високий звʼязок (coupling)\n- Зміни схильні до помилок\n\n**Рефакторинги:**\n- Move Method\n- Move Field\n- Inline Class\n\n**Виявлення:**\nШукайте: додавання одного поля вимагає змін у >5 файлах.\n\n---\n\n### Parallel Inheritance Hierarchies (Паралельні ієрархії успадкування)\n\n**Ознаки:**\n- Створення підкласу в одній ієрархії вимагає підкласу в іншій\n- Префікси класів збігаються (напр., `DatabaseOrder`, `DatabaseProduct`)\n\n**Чому це погано:**\n- Подвійне обслуговування\n- Звʼязок між ієрархіями\n- Легко забути одну сторону\n\n**Рефакторинги:**\n- Move Method\n- Move Field\n- Усунути одну ієрархію\n\n---\n\n## Непотрібне (Dispensables)\n\nЩось непотрібне, що слід видалити.\n\n### Comments (Надмірні коментарі)\n\n**Ознаки:**\n- Коментарі, що пояснюють, що робить код\n- Закоментований код\n- TODO/FIXME, що залишаються назавжди\n- Вибачення в коментарях\n\n**Чому це погано:**\n- Коментарі брешуть (розсинхронізуються)\n- Код має бути самодокументованим\n- Мертвий код створює плутанину\n\n**Рефакторинги:**\n- Extract Method (назва пояснює що)\n- Rename (ясність без коментарів)\n- Видалити закоментований код\n- Introduce Assertion\n\n**Хороші vs погані коментарі:**\n```javascript\n// ПОГАНО: Пояснює що\n// Цикл по користувачах і перевірка чи активні\nfor (const user of users) {\n  if (user.status === 'active') { }\n}\n\n// ДОБРЕ: Пояснює чому\n// Лише активні — неактивні обробляються задачею очищення\nconst activeUsers = users.filter(u => u.isActive);\n```\n\n---\n\n### Duplicate Code (Дубльований код)\n\n**Ознаки:**\n- Той самий код у кількох місцях\n- Схожий код з малими варіаціями\n- Патерни копі-пасту\n\n**Чому це погано:**\n- Виправлення помилок потрібне в кількох місцях\n- Ризик неконсистентності\n- Роздута кодова база\n\n**Рефакторинги:**\n- Extract Method\n- Extract Class\n- Pull Up Method (в ієрархіях)\n- Form Template Method\n\n**Правило виявлення:**\nБудь-який код, дубльований 3+ разів, слід витягти.\n\n---\n\n### Lazy Class (Ледачий клас)\n\n**Ознаки:**\n- Клас не робить достатньо для виправдання свого існування\n- Обгортка без доданої цінності\n- Результат надмірної інженерії\n\n**Чому це погано:**\n- Накладні витрати обслуговування\n- Непотрібна непрямість\n- Складність без користі\n\n**Рефакторинги:**\n- Inline Class\n- Collapse Hierarchy\n\n---\n\n### Dead Code (Мертвий код)\n\n**Ознаки:**\n- Недосяжний код\n- Невикористані змінні/методи/класи\n- Закоментований код\n- Код за неможливими умовами\n\n**Чому це погано:**\n- Плутанина\n- Тягар обслуговування\n- Уповільнює розуміння\n\n**Рефакторинги:**\n- Remove Dead Code\n- Safe Delete\n\n**Виявлення:**\n```bash\n# Шукати невикористані експорти\n# Шукати невикористані функції\n# Попередження IDE \"unused\"\n```\n\n---\n\n### Speculative Generality (Спекулятивна загальність)\n\n**Ознаки:**\n- Абстрактні класи з одним підкласом\n- Невикористані параметри «на майбутнє»\n- Методи, що лише делегують\n- «Фреймворк» для одного випадку\n\n**Чому це погано:**\n- Складність без користі\n- YAGNI (You Ain't Gonna Need It — Вам це не знадобиться)\n- Важче зрозуміти\n\n**Рефакторинги:**\n- Collapse Hierarchy\n- Inline Class\n- Remove Parameter\n- Rename Method\n\n---\n\n## Звʼязувачі (Couplers)\n\nЗапахи, що представляють надмірний звʼязок між класами.\n\n### Feature Envy (Заздрість до функцій)\n\n**Ознаки:**\n- Метод використовує більше даних іншого класу, ніж свого\n- Багато викликів геттерів іншого обʼєкта\n- Дані та поведінка розділені\n\n**Чому це погано:**\n- Неправильне розташування поведінки\n- Погана інкапсуляція\n- Важко супроводжувати\n\n**Рефакторинги:**\n- Move Method\n- Move Field\n- Extract Method (потім перемістити)\n\n**Приклад (до):**\n```javascript\nclass Order {\n  getDiscountedPrice(customer) {\n    // Інтенсивно використовує дані customer\n    if (customer.loyaltyYears > 5) {\n      return this.price * customer.discountRate;\n    }\n    return this.price;\n  }\n}\n```\n\n**Приклад (після):**\n```javascript\nclass Customer {\n  getDiscountedPriceFor(price) {\n    if (this.loyaltyYears > 5) {\n      return price * this.discountRate;\n    }\n    return price;\n  }\n}\n```\n\n---\n\n### Inappropriate Intimacy (Недоречна інтимність)\n\n**Ознаки:**\n- Класи отримують доступ до приватних частин один одного\n- Двосторонні посилання\n- Підкласи знають занадто багато про батьків\n\n**Чому це погано:**\n- Високий звʼязок\n- Зміни каскадуються\n- Важко модифікувати один без іншого\n\n**Рефакторинги:**\n- Move Method\n- Move Field\n- Change Bidirectional to Unidirectional\n- Extract Class\n- Hide Delegate\n\n---\n\n### Message Chains (Ланцюжки повідомлень)\n\n**Ознаки:**\n- Довгі ланцюжки викликів: `a.getB().getC().getD().getValue()`\n- Клієнт залежить від структури навігації\n- Код типу «потяг-катастрофа» (train wreck)\n\n**Чому це погано:**\n- Крихкий — будь-яка зміна ламає ланцюжок\n- Порушує Закон Деметри\n- Звʼязок зі структурою\n\n**Рефакторинги:**\n- Hide Delegate\n- Extract Method\n- Move Method\n\n**Приклад:**\n```javascript\n// Погано: Ланцюжок повідомлень\nconst managerName = employee.getDepartment().getManager().getName();\n\n// Краще: Приховати делегування\nconst managerName = employee.getManagerName();\n```\n\n---\n\n### Middle Man (Посередник)\n\n**Ознаки:**\n- Клас, що лише делегує іншому\n- Половина методів — делегування\n- Немає доданої цінності\n\n**Чому це погано:**\n- Непотрібна непрямість\n- Накладні витрати обслуговування\n- Заплутана архітектура\n\n**Рефакторинги:**\n- Remove Middle Man\n- Inline Method\n\n---\n\n## Посібник серйозності запахів\n\n| Серйозність | Опис | Дія |\n|-------------|------|-----|\n| **Критичний** | Блокує розробку, спричиняє помилки | Виправити негайно |\n| **Високий** | Значний тягар обслуговування | Виправити в поточному спринті |\n| **Середній** | Помітний, але керований | Запланувати на найближче майбутнє |\n| **Низький** | Незначна незручність | Виправляти при нагоді |\n\n---\n\n## Контрольний список швидкого виявлення\n\nВикористовуйте цей список при скануванні коду:\n\n- [ ] Є методи > 30 рядків?\n- [ ] Є класи > 300 рядків?\n- [ ] Є методи з > 4 параметрами?\n- [ ] Є дубльовані блоки коду?\n- [ ] Є switch/case за кодами типів?\n- [ ] Є невикористаний код?\n- [ ] Є методи, що інтенсивно використовують дані іншого класу?\n- [ ] Є довгі ланцюжки викликів?\n- [ ] Є коментарі, що пояснюють «що», а не «чому»?\n- [ ] Є примітиви, що мають бути обʼєктами?\n\n---\n\n## Додаткове читання\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Kerievsky, J. (2004). *Refactoring to Patterns*\n- Feathers, M. (2004). *Working Effectively with Legacy Code*\n","isInternal":false,"tokens":6722,"sizeBytes":21537},{"name":"refactoring-catalog.md","path":"uk/03-skills/refactor/references/refactoring-catalog.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/uk/03-skills/refactor/references/refactoring-catalog.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Каталог рефакторингів\n\nКурований каталог технік рефакторингу з книги Мартіна Фаулера *Refactoring* (2-ге видання). Кожен рефакторинг включає мотивацію, покрокову механіку та приклади.\n\n> «Рефакторинг визначається своєю механікою — точною послідовністю кроків, яких ви дотримуєтесь для здійснення зміни.» — Мартін Фаулер\n\n---\n\n## Як використовувати цей каталог\n\n1. **Виявити запах** за допомогою довідника запахів коду\n2. **Знайти відповідний рефакторинг** у цьому каталозі\n3. **Дотримуватися механіки** крок за кроком\n4. **Тестувати після кожного кроку** для збереження поведінки\n\n**Золоте правило**: Якщо будь-який крок займає більше 10 хвилин, розбийте його на менші кроки.\n\n---\n\n## Найпоширеніші рефакторинги\n\n### Extract Method\n\n**Коли використовувати**: Довгий метод, дубльований код, потрібно назвати концепцію\n\n**Мотивація**: Перетворити фрагмент коду на метод, назва якого пояснює призначення.\n\n**Механіка**:\n1. Створити новий метод, названий за тим, що він робить (не як)\n2. Скопіювати фрагмент коду в новий метод\n3. Просканувати локальні змінні, використані у фрагменті\n4. Передати локальні змінні як параметри (або оголосити в методі)\n5. Обробити повернені значення належним чином\n6. Замінити оригінальний фрагмент викликом нового методу\n7. Тестувати\n\n**До**:\n```javascript\nfunction printOwing(invoice) {\n  let outstanding = 0;\n\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n\n  // Обчислення заборгованості\n  for (const order of invoice.orders) {\n    outstanding += order.amount;\n  }\n\n  // Друк деталей\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n**Після**:\n```javascript\nfunction printOwing(invoice) {\n  printBanner();\n  const outstanding = calculateOutstanding(invoice);\n  printDetails(invoice, outstanding);\n}\n\nfunction printBanner() {\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n}\n\nfunction calculateOutstanding(invoice) {\n  return invoice.orders.reduce((sum, order) => sum + order.amount, 0);\n}\n\nfunction printDetails(invoice, outstanding) {\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n---\n\n### Inline Method\n\n**Коли використовувати**: Тіло методу таке ж зрозуміле, як його назва; надмірне делегування\n\n**Мотивація**: Видалити непотрібну непрямість, коли метод не додає цінності.\n\n**Механіка**:\n1. Перевірити, що метод не є поліморфним\n2. Знайти всі виклики методу\n3. Замінити кожен виклик тілом методу\n4. Тестувати після кожної заміни\n5. Видалити визначення методу\n\n**До**:\n```javascript\nfunction getRating(driver) {\n  return moreThanFiveLateDeliveries(driver) ? 2 : 1;\n}\n\nfunction moreThanFiveLateDeliveries(driver) {\n  return driver.numberOfLateDeliveries > 5;\n}\n```\n\n**Після**:\n```javascript\nfunction getRating(driver) {\n  return driver.numberOfLateDeliveries > 5 ? 2 : 1;\n}\n```\n\n---\n\n### Extract Variable\n\n**Коли використовувати**: Складний вираз, важкий для розуміння\n\n**Мотивація**: Дати назву частині складного виразу.\n\n**Механіка**:\n1. Переконатися, що вираз не має побічних ефектів\n2. Оголосити незмінну змінну\n3. Встановити її як результат виразу (або частини)\n4. Замінити оригінальний вираз змінною\n5. Тестувати\n\n**До**:\n```javascript\nreturn order.quantity * order.itemPrice -\n  Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +\n  Math.min(order.quantity * order.itemPrice * 0.1, 100);\n```\n\n**Після**:\n```javascript\nconst basePrice = order.quantity * order.itemPrice;\nconst quantityDiscount = Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;\nconst shipping = Math.min(basePrice * 0.1, 100);\nreturn basePrice - quantityDiscount + shipping;\n```\n\n---\n\n### Inline Variable\n\n**Коли використовувати**: Назва змінної не передає більше, ніж вираз\n\n**Мотивація**: Видалити непотрібну непрямість.\n\n**Механіка**:\n1. Перевірити, що права частина не має побічних ефектів\n2. Якщо змінна не незмінна, зробити її такою і тестувати\n3. Знайти перше посилання та замінити виразом\n4. Тестувати\n5. Повторити для всіх посилань\n6. Видалити оголошення та присвоєння\n7. Тестувати\n\n---\n\n### Rename Variable\n\n**Коли використовувати**: Назва не чітко передає призначення\n\n**Мотивація**: Хороші назви критичні для чистого коду.\n\n**Механіка**:\n1. Якщо змінна широко використовується, розглянути інкапсуляцію\n2. Знайти всі посилання\n3. Змінити кожне посилання\n4. Тестувати\n\n**Поради**:\n- Використовуйте назви, що розкривають намір\n- Уникайте абревіатур\n- Використовуйте доменну термінологію\n\n```javascript\n// Погано\nconst d = 30;\nconst x = users.filter(u => u.a);\n\n// Добре\nconst daysSinceLastLogin = 30;\nconst activeUsers = users.filter(user => user.isActive);\n```\n\n---\n\n### Change Function Declaration\n\n**Коли використовувати**: Назва функції не пояснює призначення, параметри потребують зміни\n\n**Мотивація**: Хороші назви функцій роблять код самодокументованим.\n\n**Механіка (проста)**:\n1. Видалити непотрібні параметри\n2. Змінити назву\n3. Додати потрібні параметри\n4. Тестувати\n\n**Механіка (міграція — для складних змін)**:\n1. Якщо видаляєте параметр, переконайтеся, що він не використовується\n2. Створити нову функцію з бажаним оголошенням\n3. Зробити так, щоб стара функція викликала нову\n4. Тестувати\n5. Змінити виклики на нову функцію\n6. Тестувати після кожного\n7. Видалити стару функцію\n\n**До**:\n```javascript\nfunction circum(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n**Після**:\n```javascript\nfunction circumference(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n---\n\n### Encapsulate Variable\n\n**Коли використовувати**: Прямий доступ до даних з кількох місць\n\n**Мотивація**: Забезпечити чітку точку доступу для маніпуляції даними.\n\n**Механіка**:\n1. Створити функції getter та setter\n2. Знайти всі посилання\n3. Замінити читання на getter\n4. Замінити записи на setter\n5. Тестувати після кожної зміни\n6. Обмежити видимість змінної\n\n**До**:\n```javascript\nlet defaultOwner = { firstName: \"Martin\", lastName: \"Fowler\" };\n\n// Використовується в багатьох місцях\nspaceship.owner = defaultOwner;\n```\n\n**Після**:\n```javascript\nlet defaultOwnerData = { firstName: \"Martin\", lastName: \"Fowler\" };\n\nfunction defaultOwner() { return defaultOwnerData; }\nfunction setDefaultOwner(arg) { defaultOwnerData = arg; }\n\nspaceship.owner = defaultOwner();\n```\n\n---\n\n### Introduce Parameter Object\n\n**Коли використовувати**: Кілька параметрів, що часто зʼявляються разом\n\n**Мотивація**: Згрупувати дані, що природно належать разом.\n\n**Механіка**:\n1. Створити новий клас/структуру для згрупованих параметрів\n2. Тестувати\n3. Використати Change Function Declaration для додавання нового обʼєкта\n4. Тестувати\n5. Для кожного параметра в групі видалити його з функції та використати новий обʼєкт\n6. Тестувати після кожного\n\n**До**:\n```javascript\nfunction amountInvoiced(startDate, endDate) { ... }\nfunction amountReceived(startDate, endDate) { ... }\nfunction amountOverdue(startDate, endDate) { ... }\n```\n\n**Після**:\n```javascript\nclass DateRange {\n  constructor(start, end) {\n    this.start = start;\n    this.end = end;\n  }\n}\n\nfunction amountInvoiced(dateRange) { ... }\nfunction amountReceived(dateRange) { ... }\nfunction amountOverdue(dateRange) { ... }\n```\n\n---\n\n### Combine Functions into Class\n\n**Коли використовувати**: Кілька функцій оперують тими самими даними\n\n**Мотивація**: Згрупувати функції з даними, над якими вони працюють.\n\n**Механіка**:\n1. Застосувати Encapsulate Record до спільних даних\n2. Перемістити кожну функцію в клас\n3. Тестувати після кожного переміщення\n4. Замінити аргументи даних використанням полів класу\n\n**До**:\n```javascript\nfunction base(reading) { ... }\nfunction taxableCharge(reading) { ... }\nfunction calculateBaseCharge(reading) { ... }\n```\n\n**Після**:\n```javascript\nclass Reading {\n  constructor(data) { this._data = data; }\n\n  get base() { ... }\n  get taxableCharge() { ... }\n  get calculateBaseCharge() { ... }\n}\n```\n\n---\n\n### Split Phase\n\n**Коли використовувати**: Код працює з двома різними речами\n\n**Мотивація**: Розділити код на окремі фази з чіткими межами.\n\n**Механіка**:\n1. Створити другу функцію для другої фази\n2. Тестувати\n3. Ввести проміжну структуру даних між фазами\n4. Тестувати\n5. Витягти першу фазу в окрему функцію\n6. Тестувати\n\n**До**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  const shippingPerCase = (basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = quantity * shippingPerCase;\n  return basePrice - discount + shippingCost;\n}\n```\n\n**Після**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const priceData = calculatePricingData(product, quantity);\n  return applyShipping(priceData, shippingMethod);\n}\n\nfunction calculatePricingData(product, quantity) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  return { basePrice, quantity, discount };\n}\n\nfunction applyShipping(priceData, shippingMethod) {\n  const shippingPerCase = (priceData.basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = priceData.quantity * shippingPerCase;\n  return priceData.basePrice - priceData.discount + shippingCost;\n}\n```\n\n---\n\n## Переміщення функцій (Moving Features)\n\n### Move Method\n\n**Коли використовувати**: Метод використовує більше можливостей іншого класу, ніж свого\n\n**Мотивація**: Розміщувати функції разом з даними, які вони використовують найбільше.\n\n**Механіка**:\n1. Дослідити всі елементи програми, використані методом у своєму класі\n2. Перевірити, чи метод є поліморфним\n3. Скопіювати метод у цільовий клас\n4. Адаптувати до нового контексту\n5. Зробити оригінальний метод делегуючим до цільового\n6. Тестувати\n7. Розглянути видалення оригінального методу\n\n---\n\n### Move Field\n\n**Коли використовувати**: Поле використовується більше іншим класом\n\n**Мотивація**: Тримати дані разом з функціями, що їх використовують.\n\n**Механіка**:\n1. Інкапсулювати поле, якщо ще не зроблено\n2. Тестувати\n3. Створити поле в цільовому класі\n4. Оновити посилання на використання цільового поля\n5. Тестувати\n6. Видалити оригінальне поле\n\n---\n\n### Move Statements into Function\n\n**Коли використовувати**: Той самий код завжди зʼявляється разом з викликом функції\n\n**Мотивація**: Видалити дублювання, перемістивши повторюваний код у функцію.\n\n**Механіка**:\n1. Витягти повторюваний код у функцію, якщо ще не зроблено\n2. Перемістити оператори в цю функцію\n3. Тестувати\n4. Якщо виклики більше не потребують окремих операторів, видалити їх\n\n---\n\n### Move Statements to Callers\n\n**Коли використовувати**: Загальна поведінка різниться між викликачами\n\n**Мотивація**: Коли поведінка має відрізнятися, перемістити її з функції.\n\n**Механіка**:\n1. Використати Extract Method на коді для переміщення\n2. Використати Inline Method на оригінальній функції\n3. Видалити тепер вбудований виклик\n4. Перемістити витягнутий код до кожного виклику\n5. Тестувати\n\n---\n\n## Організація даних (Organizing Data)\n\n### Replace Primitive with Object\n\n**Коли використовувати**: Елемент даних потребує більше поведінки, ніж просте значення\n\n**Мотивація**: Інкапсулювати дані разом з їхньою поведінкою.\n\n**Механіка**:\n1. Застосувати Encapsulate Variable\n2. Створити простий клас значення\n3. Змінити setter для створення нового екземпляра\n4. Змінити getter для повернення значення\n5. Тестувати\n6. Додати багатшу поведінку до нового класу\n\n**До**:\n```javascript\nclass Order {\n  constructor(data) {\n    this.priority = data.priority; // рядок: \"high\", \"rush\" тощо\n  }\n}\n\n// Використання\nif (order.priority === \"high\" || order.priority === \"rush\") { ... }\n```\n\n**Після**:\n```javascript\nclass Priority {\n  constructor(value) {\n    if (!Priority.legalValues().includes(value))\n      throw new Error(`Invalid priority: ${value}`);\n    this._value = value;\n  }\n\n  static legalValues() { return ['low', 'normal', 'high', 'rush']; }\n  get value() { return this._value; }\n\n  higherThan(other) {\n    return Priority.legalValues().indexOf(this._value) >\n           Priority.legalValues().indexOf(other._value);\n  }\n}\n\n// Використання\nif (order.priority.higherThan(new Priority(\"normal\"))) { ... }\n```\n\n---\n\n### Replace Temp with Query\n\n**Коли використовувати**: Тимчасова змінна зберігає результат виразу\n\n**Мотивація**: Зробити код зрозумілішим, витягнувши вираз у функцію.\n\n**Механіка**:\n1. Перевірити, що змінна присвоюється лише один раз\n2. Витягти праву частину присвоєння в метод\n3. Замінити посилання на тимчасову змінну викликом методу\n4. Тестувати\n5. Видалити оголошення та присвоєння тимчасової змінної\n\n**До**:\n```javascript\nconst basePrice = this._quantity * this._itemPrice;\nif (basePrice > 1000) {\n  return basePrice * 0.95;\n} else {\n  return basePrice * 0.98;\n}\n```\n\n**Після**:\n```javascript\nget basePrice() {\n  return this._quantity * this._itemPrice;\n}\n\n// В методі\nif (this.basePrice > 1000) {\n  return this.basePrice * 0.95;\n} else {\n  return this.basePrice * 0.98;\n}\n```\n\n---\n\n## Спрощення умовної логіки (Simplifying Conditional Logic)\n\n### Decompose Conditional\n\n**Коли використовувати**: Складний умовний оператор (if-then-else)\n\n**Мотивація**: Зробити намір зрозумілим, витягнувши умови та дії.\n\n**Механіка**:\n1. Застосувати Extract Method на умові\n2. Застосувати Extract Method на then-гілці\n3. Застосувати Extract Method на else-гілці (якщо є)\n\n**До**:\n```javascript\nif (!aDate.isBefore(plan.summerStart) && !aDate.isAfter(plan.summerEnd)) {\n  charge = quantity * plan.summerRate;\n} else {\n  charge = quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n**Після**:\n```javascript\nif (isSummer(aDate, plan)) {\n  charge = summerCharge(quantity, plan);\n} else {\n  charge = regularCharge(quantity, plan);\n}\n\nfunction isSummer(date, plan) {\n  return !date.isBefore(plan.summerStart) && !date.isAfter(plan.summerEnd);\n}\n\nfunction summerCharge(quantity, plan) {\n  return quantity * plan.summerRate;\n}\n\nfunction regularCharge(quantity, plan) {\n  return quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n---\n\n### Consolidate Conditional Expression\n\n**Коли використовувати**: Кілька умов з однаковим результатом\n\n**Мотивація**: Зробити зрозумілим, що умови є однією перевіркою.\n\n**Механіка**:\n1. Перевірити відсутність побічних ефектів в умовах\n2. Обʼєднати умови за допомогою `and` або `or`\n3. Розглянути Extract Method на обʼєднаній умові\n\n**До**:\n```javascript\nif (employee.seniority < 2) return 0;\nif (employee.monthsDisabled > 12) return 0;\nif (employee.isPartTime) return 0;\n```\n\n**Після**:\n```javascript\nif (isNotEligibleForDisability(employee)) return 0;\n\nfunction isNotEligibleForDisability(employee) {\n  return employee.seniority < 2 ||\n         employee.monthsDisabled > 12 ||\n         employee.isPartTime;\n}\n```\n\n---\n\n### Replace Nested Conditional with Guard Clauses\n\n**Коли використовувати**: Глибоко вкладені умови ускладнюють відстеження потоку\n\n**Мотивація**: Використовувати захисні вирази (guard clauses) для спеціальних випадків, зберігаючи нормальний потік зрозумілим.\n\n**Механіка**:\n1. Знайти умови спеціальних випадків\n2. Замінити їх захисними виразами з раннім поверненням\n3. Тестувати після кожної зміни\n\n**До**:\n```javascript\nfunction payAmount(employee) {\n  let result;\n  if (employee.isSeparated) {\n    result = { amount: 0, reasonCode: \"SEP\" };\n  } else {\n    if (employee.isRetired) {\n      result = { amount: 0, reasonCode: \"RET\" };\n    } else {\n      result = calculateNormalPay(employee);\n    }\n  }\n  return result;\n}\n```\n\n**Після**:\n```javascript\nfunction payAmount(employee) {\n  if (employee.isSeparated) return { amount: 0, reasonCode: \"SEP\" };\n  if (employee.isRetired) return { amount: 0, reasonCode: \"RET\" };\n  return calculateNormalPay(employee);\n}\n```\n\n---\n\n### Replace Conditional with Polymorphism\n\n**Коли використовувати**: Switch/case за типом, умовна логіка що варіюється за типом\n\n**Мотивація**: Дозволити обʼєктам обробляти свою поведінку самостійно.\n\n**Механіка**:\n1. Створити ієрархію класів (якщо не існує)\n2. Використати фабричну функцію для створення обʼєктів\n3. Перемістити умовну логіку в метод суперкласу\n4. Створити метод підкласу для кожного випадку\n5. Видалити оригінальну умову\n\n**До**:\n```javascript\nfunction plumage(bird) {\n  switch (bird.type) {\n    case 'EuropeanSwallow':\n      return \"average\";\n    case 'AfricanSwallow':\n      return (bird.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n    case 'NorwegianBlueParrot':\n      return (bird.voltage > 100) ? \"scorched\" : \"beautiful\";\n    default:\n      return \"unknown\";\n  }\n}\n```\n\n**Після**:\n```javascript\nclass Bird {\n  get plumage() { return \"unknown\"; }\n}\n\nclass EuropeanSwallow extends Bird {\n  get plumage() { return \"average\"; }\n}\n\nclass AfricanSwallow extends Bird {\n  get plumage() {\n    return (this.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n  }\n}\n\nclass NorwegianBlueParrot extends Bird {\n  get plumage() {\n    return (this.voltage > 100) ? \"scorched\" : \"beautiful\";\n  }\n}\n\nfunction createBird(data) {\n  switch (data.type) {\n    case 'EuropeanSwallow': return new EuropeanSwallow(data);\n    case 'AfricanSwallow': return new AfricanSwallow(data);\n    case 'NorwegianBlueParrot': return new NorwegianBlueParrot(data);\n    default: return new Bird(data);\n  }\n}\n```\n\n---\n\n### Introduce Special Case (Null Object)\n\n**Коли використовувати**: Повторні перевірки на null для спеціальних випадків\n\n**Мотивація**: Повертати спеціальний обʼєкт, що обробляє спеціальний випадок.\n\n**Механіка**:\n1. Створити клас спеціального випадку з очікуваним інтерфейсом\n2. Додати перевірку isSpecialCase\n3. Ввести фабричний метод\n4. Замінити перевірки на null використанням обʼєкта спеціального випадку\n5. Тестувати\n\n**До**:\n```javascript\nconst customer = site.customer;\n// ... багато місць з перевіркою\nif (customer === \"unknown\") {\n  customerName = \"occupant\";\n} else {\n  customerName = customer.name;\n}\n```\n\n**Після**:\n```javascript\nclass UnknownCustomer {\n  get name() { return \"occupant\"; }\n  get billingPlan() { return registry.defaultPlan; }\n}\n\n// Фабричний метод\nfunction customer(site) {\n  return site.customer === \"unknown\"\n    ? new UnknownCustomer()\n    : site.customer;\n}\n\n// Використання — перевірки на null не потрібні\nconst customerName = customer.name;\n```\n\n---\n\n## Рефакторинг API (Refactoring APIs)\n\n### Separate Query from Modifier\n\n**Коли використовувати**: Функція і повертає значення, і має побічні ефекти\n\n**Мотивація**: Зробити зрозумілим, які операції мають побічні ефекти.\n\n**Механіка**:\n1. Створити нову функцію-запит\n2. Скопіювати логіку повернення оригінальної функції\n3. Змінити оригінал, щоб повертав void\n4. Замінити виклики, що використовують повернене значення\n5. Тестувати\n\n**До**:\n```javascript\nfunction alertForMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") {\n      setOffAlarms();\n      return \"Don\";\n    }\n    if (p === \"John\") {\n      setOffAlarms();\n      return \"John\";\n    }\n  }\n  return \"\";\n}\n```\n\n**Після**:\n```javascript\nfunction findMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") return \"Don\";\n    if (p === \"John\") return \"John\";\n  }\n  return \"\";\n}\n\nfunction alertForMiscreant(people) {\n  if (findMiscreant(people) !== \"\") setOffAlarms();\n}\n```\n\n---\n\n### Parameterize Function\n\n**Коли використовувати**: Кілька функцій роблять схожі речі з різними значеннями\n\n**Мотивація**: Видалити дублювання додаванням параметра.\n\n**Механіка**:\n1. Обрати одну функцію\n2. Додати параметр для варійованого літерала\n3. Змінити тіло для використання параметра\n4. Тестувати\n5. Змінити виклики на параметризовану версію\n6. Видалити тепер невикористані функції\n\n**До**:\n```javascript\nfunction tenPercentRaise(person) {\n  person.salary = person.salary * 1.10;\n}\n\nfunction fivePercentRaise(person) {\n  person.salary = person.salary * 1.05;\n}\n```\n\n**Після**:\n```javascript\nfunction raise(person, factor) {\n  person.salary = person.salary * (1 + factor);\n}\n\n// Використання\nraise(person, 0.10);\nraise(person, 0.05);\n```\n\n---\n\n### Remove Flag Argument\n\n**Коли використовувати**: Булевий параметр, що змінює поведінку функції\n\n**Мотивація**: Зробити поведінку явною через окремі функції.\n\n**Механіка**:\n1. Створити явну функцію для кожного значення прапорця\n2. Замінити кожен виклик відповідною новою функцією\n3. Тестувати після кожної зміни\n4. Видалити оригінальну функцію\n\n**До**:\n```javascript\nfunction bookConcert(customer, isPremium) {\n  if (isPremium) {\n    // логіка преміум-бронювання\n  } else {\n    // логіка звичайного бронювання\n  }\n}\n\nbookConcert(customer, true);\nbookConcert(customer, false);\n```\n\n**Після**:\n```javascript\nfunction bookPremiumConcert(customer) {\n  // логіка преміум-бронювання\n}\n\nfunction bookRegularConcert(customer) {\n  // логіка звичайного бронювання\n}\n\nbookPremiumConcert(customer);\nbookRegularConcert(customer);\n```\n\n---\n\n## Робота з успадкуванням (Dealing with Inheritance)\n\n### Pull Up Method\n\n**Коли використовувати**: Той самий метод у кількох підкласах\n\n**Мотивація**: Видалити дублювання в ієрархії класів.\n\n**Механіка**:\n1. Перевірити, що методи ідентичні\n2. Перевірити, що сигнатури однакові\n3. Створити новий метод у суперкласі\n4. Скопіювати тіло з одного підкласу\n5. Видалити один метод підкласу, тестувати\n6. Видалити інші методи підкласів, тестувати кожен\n\n---\n\n### Push Down Method\n\n**Коли використовувати**: Поведінка релевантна лише для підмножини підкласів\n\n**Мотивація**: Розмістити метод там, де він використовується.\n\n**Механіка**:\n1. Скопіювати метод у кожен підклас, що його потребує\n2. Видалити метод із суперкласу\n3. Тестувати\n4. Видалити з підкласів, що його не потребують\n5. Тестувати\n\n---\n\n### Replace Subclass with Delegate\n\n**Коли використовувати**: Успадкування використовується некоректно, потрібна більша гнучкість\n\n**Мотивація**: Віддавати перевагу композиції над успадкуванням, коли доречно.\n\n**Механіка**:\n1. Створити порожній клас для делегата\n2. Додати поле в клас-хост для утримання делегата\n3. Створити конструктор для делегата, що викликається з хоста\n4. Перемістити функціональність до делегата\n5. Тестувати після кожного переміщення\n6. Замінити успадкування делегуванням\n\n---\n\n## Extract Class\n\n**Коли використовувати**: Великий клас з кількома відповідальностями\n\n**Мотивація**: Розділити клас для збереження єдиної відповідальності.\n\n**Механіка**:\n1. Вирішити, як розділити відповідальності\n2. Створити новий клас\n3. Перемістити поле з оригіналу до нового класу\n4. Тестувати\n5. Перемістити методи з оригіналу до нового класу\n6. Тестувати після кожного переміщення\n7. Переглянути та перейменувати обидва класи\n8. Вирішити, як відкрити новий клас\n\n**До**:\n```javascript\nclass Person {\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get officeAreaCode() { return this._officeAreaCode; }\n  set officeAreaCode(arg) { this._officeAreaCode = arg; }\n  get officeNumber() { return this._officeNumber; }\n  set officeNumber(arg) { this._officeNumber = arg; }\n\n  get telephoneNumber() {\n    return `(${this._officeAreaCode}) ${this._officeNumber}`;\n  }\n}\n```\n\n**Після**:\n```javascript\nclass Person {\n  constructor() {\n    this._telephoneNumber = new TelephoneNumber();\n  }\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get telephoneNumber() { return this._telephoneNumber.toString(); }\n  get officeAreaCode() { return this._telephoneNumber.areaCode; }\n  set officeAreaCode(arg) { this._telephoneNumber.areaCode = arg; }\n}\n\nclass TelephoneNumber {\n  get areaCode() { return this._areaCode; }\n  set areaCode(arg) { this._areaCode = arg; }\n  get number() { return this._number; }\n  set number(arg) { this._number = arg; }\n  toString() { return `(${this._areaCode}) ${this._number}`; }\n}\n```\n\n---\n\n## Короткий довідник: Запах → Рефакторинг\n\n| Запах коду | Основний рефакторинг | Альтернатива |\n|------------|---------------------|--------------|\n| Long Method | Extract Method | Replace Temp with Query |\n| Duplicate Code | Extract Method | Pull Up Method |\n| Large Class | Extract Class | Extract Subclass |\n| Long Parameter List | Introduce Parameter Object | Preserve Whole Object |\n| Feature Envy | Move Method | Extract Method + Move |\n| Data Clumps | Extract Class | Introduce Parameter Object |\n| Primitive Obsession | Replace Primitive with Object | Replace Type Code |\n| Switch Statements | Replace Conditional with Polymorphism | Replace Type Code |\n| Temporary Field | Extract Class | Introduce Null Object |\n| Message Chains | Hide Delegate | Extract Method |\n| Middle Man | Remove Middle Man | Inline Method |\n| Divergent Change | Extract Class | Split Phase |\n| Shotgun Surgery | Move Method | Inline Class |\n| Dead Code | Remove Dead Code | - |\n| Speculative Generality | Collapse Hierarchy | Inline Class |\n\n---\n\n## Додаткове читання\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Онлайн-каталог: https://refactoring.com/catalog/\n","isInternal":false,"tokens":10211,"sizeBytes":34287},{"name":"SKILL.md","path":"uk/03-skills/refactor/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/uk/03-skills/refactor/SKILL.md","title":"refactor","category":"anthropic-skill","format":"markdown","content":"---\nname: refactor\ndescription: Систематичний рефакторинг коду на основі методології Мартіна Фаулера. Використовуйте, коли користувачі просять рефакторити код, покращити структуру коду, зменшити технічний борг, очистити застарілий код, усунути запахи коду (code smells) або покращити супровідність коду. Ця навичка проводить через поетапний підхід з дослідженням, плануванням та безпечною інкрементальною реалізацією.\n---\n\n# Навичка рефакторингу коду\n\nСистематичний підхід до рефакторингу коду на основі книги Мартіна Фаулера *Refactoring: Improving the Design of Existing Code* (2-ге видання). Ця навичка наголошує на безпечних, інкрементальних змінах, підкріплених тестами.\n\n> «Рефакторинг — це процес зміни програмної системи таким чином, що не змінює зовнішню поведінку коду, але покращує його внутрішню структуру.» — Мартін Фаулер\n\n## Основні принципи\n\n1. **Збереження поведінки**: Зовнішня поведінка повинна залишатися незмінною\n2. **Малі кроки**: Робити крихітні, тестовані зміни\n3. **Тест-орієнтованість**: Тести — це страхувальна сітка\n4. **Безперервність**: Рефакторинг — постійний процес, а не одноразова подія\n5. **Співпраця**: Затвердження користувача потрібне на кожній фазі\n\n## Огляд робочого процесу\n\n```\nФаза 1: Дослідження та аналіз\n    ↓\nФаза 2: Оцінка покриття тестами\n    ↓\nФаза 3: Виявлення запахів коду\n    ↓\nФаза 4: Створення плану рефакторингу\n    ↓\nФаза 5: Інкрементальна реалізація\n    ↓\nФаза 6: Перегляд та ітерація\n```\n\n---\n\n## Фаза 1: Дослідження та аналіз\n\n### Цілі\n- Зрозуміти структуру та призначення кодової бази\n- Визначити обсяг рефакторингу\n- Зібрати контекст про бізнес-вимоги\n\n### Запитання до користувача\nПеред початком уточніть:\n\n1. **Обсяг**: Які файли/модулі/функції потребують рефакторингу?\n2. **Цілі**: Які проблеми ви намагаєтесь вирішити? (читабельність, продуктивність, супровідність)\n3. **Обмеження**: Чи є зони, які НЕ слід змінювати?\n4. **Тиск термінів**: Чи блокує це іншу роботу?\n5. **Стан тестів**: Чи існують тести? Чи проходять вони?\n\n### Дії\n- [ ] Прочитати та зрозуміти цільовий код\n- [ ] Виявити залежності та інтеграції\n- [ ] Задокументувати поточну архітектуру\n- [ ] Зафіксувати існуючі маркери технічного боргу (TODOs, FIXMEs)\n\n### Вивід\nПредставити знахідки користувачу:\n- Резюме структури коду\n- Виявлені проблемні зони\n- Початкові рекомендації\n- **Запросити затвердження для продовження**\n\n---\n\n## Фаза 2: Оцінка покриття тестами\n\n### Чому тести важливі\n> «Рефакторинг без тестів — як їзда без пасків безпеки.» — Мартін Фаулер\n\nТести — **ключовий засіб** безпечного рефакторингу. Без них ви ризикуєте внести помилки.\n\n### Кроки оцінки\n\n1. **Перевірити наявні тести**\n   ```bash\n   # Пошук файлів тестів\n   find . -name \"*test*\" -o -name \"*spec*\" | head -20\n   ```\n\n2. **Запустити існуючі тести**\n   ```bash\n   # JavaScript/TypeScript\n   npm test\n\n   # Python\n   pytest -v\n\n   # Java\n   mvn test\n   ```\n\n3. **Перевірити покриття (якщо доступно)**\n   ```bash\n   # JavaScript\n   npm run test:coverage\n\n   # Python\n   pytest --cov=.\n   ```\n\n### Точка рішення: Запитати користувача\n\n**Якщо тести існують та проходять:**\n- Перейти до Фази 3\n\n**Якщо тести відсутні або неповні:**\nПредставити варіанти:\n1. Спочатку написати тести (рекомендовано)\n2. Додавати тести інкрементально під час рефакторингу\n3. Продовжити без тестів (ризиковано — потребує підтвердження користувача)\n\n**Якщо тести не проходять:**\n- ЗУПИНИТИСЯ. Виправити тести перед рефакторингом\n- Запитати користувача: Чи слід спочатку виправити тести?\n\n### Рекомендації щодо написання тестів (якщо потрібно)\n\nДля кожної функції, що рефакториться, забезпечити тести для:\n- Успішний шлях (нормальна робота)\n- Граничні випадки (порожні введення, null, межі)\n- Сценарії помилок (невалідні введення, виключення)\n\nВикористовуйте цикл «red-green-refactor»:\n1. Написати тест, що не проходить (red)\n2. Зробити так, щоб пройшов (green)\n3. Рефакторити\n\n---\n\n## Фаза 3: Виявлення запахів коду\n\n### Що таке запахи коду?\nСимптоми глибших проблем у коді. Це не помилки, а індикатори того, що код можна покращити.\n\n### Типові запахи коду для перевірки\n\nДив. [references/code-smells.md](references/code-smells.md) для повного каталогу.\n\n#### Короткий довідник\n\n| Запах | Ознаки | Вплив |\n|-------|--------|-------|\n| **Довгий метод** | Методи > 30-50 рядків | Важко зрозуміти, тестувати, супроводжувати |\n| **Дубльований код** | Та сама логіка в кількох місцях | Виправлення помилок потрібне в кількох місцях |\n| **Великий клас** | Клас з занадто багатьма відповідальностями | Порушує принцип єдиної відповідальності |\n| **Заздрість до функцій** | Метод використовує дані іншого класу більше | Погана інкапсуляція |\n| **Одержимість примітивами** | Надмірне використання примітивів замість обʼєктів | Відсутні доменні концепції |\n| **Довгий список параметрів** | Методи з 4+ параметрами | Складно викликати правильно |\n| **Групи даних** | Ті самі елементи даних зʼявляються разом | Відсутня абстракція |\n| **Оператори Switch** | Складні ланцюжки switch/if-else | Важко розширювати |\n| **Спекулятивна загальність** | Код «на всякий випадок» | Зайва складність |\n| **Мертвий код** | Невикористаний код | Плутанина, тягар супровідності |\n\n### Кроки аналізу\n\n1. **Автоматичний аналіз** (якщо скрипти доступні)\n   ```bash\n   python scripts/detect-smells.py <file>\n   ```\n\n2. **Ручний перегляд**\n   - Систематично пройти код\n   - Зафіксувати кожен запах з розташуванням та серйозністю\n   - Категоризувати за впливом (Критичний/Високий/Середній/Низький)\n\n3. **Пріоритезація**\n   Зосередитися на запахах, які:\n   - Блокують поточну розробку\n   - Спричиняють помилки або плутанину\n   - Впливають на найчастіше змінювані шляхи коду\n\n### Вивід: Звіт про запахи\n\nПредставити користувачу:\n- Список виявлених запахів з розташуванням\n- Оцінку серйозності для кожного\n- Рекомендований порядок пріоритету\n- **Запросити затвердження пріоритетів**\n\n---\n\n## Фаза 4: Створення плану рефакторингу\n\n### Вибір рефакторингів\n\nДля кожного запаху обрати відповідний рефакторинг з каталогу.\n\nДив. [references/refactoring-catalog.md](references/refactoring-catalog.md) для повного списку.\n\n#### Відповідність запахів рефакторингам\n\n| Запах коду | Рекомендований рефакторинг |\n|------------|---------------------------|\n| Long Method | Extract Method, Replace Temp with Query |\n| Duplicated Code | Extract Method, Pull Up Method, Form Template Method |\n| Large Class | Extract Class, Extract Subclass |\n| Feature Envy | Move Method, Move Field |\n| Primitive Obsession | Replace Primitive with Object, Replace Type Code with Class |\n| Long Parameter List | Introduce Parameter Object, Preserve Whole Object |\n| Data Clumps | Extract Class, Introduce Parameter Object |\n| Switch Statements | Replace Conditional with Polymorphism |\n| Speculative Generality | Collapse Hierarchy, Inline Class, Remove Dead Code |\n| Dead Code | Remove Dead Code |\n\n### Структура плану\n\nВикористовуйте шаблон [templates/refactoring-plan.md](templates/refactoring-plan.md).\n\nДля кожного рефакторингу:\n1. **Ціль**: Який код зміниться\n2. **Запах**: Яку проблему вирішує\n3. **Рефакторинг**: Яку техніку застосувати\n4. **Кроки**: Детальні мікрокроки\n5. **Ризики**: Що може піти не так\n6. **Відкат**: Як скасувати за потреби\n\n### Поетапний підхід\n\n**КРИТИЧНО**: Впроваджуйте рефакторинг поступово, фазами.\n\n**Фаза A: Швидкі перемоги** (Низький ризик, висока цінність)\n- Перейменування змінних для ясності\n- Витяг очевидного дубльованого коду\n- Видалення мертвого коду\n\n**Фаза B: Структурні покращення** (Середній ризик)\n- Витяг методів з довгих функцій\n- Введення обʼєктів параметрів\n- Переміщення методів до відповідних класів\n\n**Фаза C: Архітектурні зміни** (Вищий ризик)\n- Заміна умовних конструкцій поліморфізмом\n- Витяг класів\n- Введення патернів проєктування\n\n### Точка рішення: Представити план користувачу\n\nПеред реалізацією:\n- Показати повний план рефакторингу\n- Пояснити кожну фазу та її ризики\n- Отримати явне затвердження для кожної фази\n- **Запитати**: «Чи продовжити з Фазою A?»\n\n---\n\n## Фаза 5: Інкрементальна реалізація\n\n### Золоте правило\n> «Зміна → Тест → Зелений? → Коміт → Наступний крок»\n\n### Ритм реалізації\n\nДля кожного кроку рефакторингу:\n\n1. **Попередня перевірка**\n   - Тести проходять (зелені)\n   - Код компілюється\n\n2. **Зробити ОДНУ малу зміну**\n   - Дотримуватися механіки з каталогу\n   - Тримати зміни мінімальними\n\n3. **Верифікація**\n   - Негайно запустити тести\n   - Перевірити на помилки компіляції\n\n4. **Якщо тести проходять (зелені)**\n   - Закомітити з описовим повідомленням\n   - Перейти до наступного кроку\n\n5. **Якщо тести не проходять (червоні)**\n   - ЗУПИНИТИСЯ негайно\n   - Скасувати зміну\n   - Проаналізувати, що пішло не так\n   - Запитати користувача, якщо незрозуміло\n\n### Стратегія комітів\n\nКожен коміт має бути:\n- **Атомарний**: Одна логічна зміна\n- **Оборотний**: Легко відкатити\n- **Описовий**: Зрозуміле повідомлення коміту\n\nПриклади повідомлень комітів:\n```\nrefactor: Extract calculateTotal() from processOrder()\nrefactor: Rename 'x' to 'customerCount' for clarity\nrefactor: Remove unused validateOldFormat() method\n```\n\n### Звіт про прогрес\n\nПісля кожної підфази звітувати користувачу:\n- Внесені зміни\n- Тести досі проходять?\n- Виявлені проблеми\n- **Запитати**: «Продовжити з наступною порцією?»\n\n---\n\n## Фаза 6: Перегляд та ітерація\n\n### Контрольний список після рефакторингу\n\n- [ ] Усі тести проходять\n- [ ] Немає нових попереджень/помилок\n- [ ] Код успішно компілюється\n- [ ] Поведінка не змінилася (ручна верифікація)\n- [ ] Документація оновлена за потреби\n- [ ] Історія комітів чиста\n\n### Порівняння метрик\n\nЗапустити аналіз складності до і після:\n```bash\npython scripts/analyze-complexity.py <file>\n```\n\nПредставити покращення:\n- Зміна кількості рядків коду\n- Зміна цикломатичної складності\n- Зміна індексу супровідності\n\n### Перегляд користувачем\n\nПредставити фінальні результати:\n- Резюме всіх змін\n- Порівняння коду до/після\n- Покращення метрик\n- Залишковий технічний борг\n- **Запитати**: «Чи задоволені ви цими змінами?»\n\n### Наступні кроки\n\nОбговорити з користувачем:\n- Додаткові запахи для усунення?\n- Запланувати подальший рефакторинг?\n- Застосувати аналогічні зміни в інших місцях?\n\n---\n\n## Важливі рекомендації\n\n### Коли ЗУПИНИТИСЯ та запитати\n\nЗавжди паузу та консультацію з користувачем, коли:\n- Невпевненість щодо бізнес-логіки\n- Зміна може вплинути на зовнішні API\n- Покриття тестами недостатнє\n- Потрібне значне архітектурне рішення\n- Рівень ризику зростає\n- Зустрічаєте неочікувану складність\n\n### Правила безпеки\n\n1. **Ніколи не рефакторити без тестів** (якщо користувач явно не підтвердив ризик)\n2. **Ніколи не робити великих змін** — розбивати на крихітні кроки\n3. **Ніколи не пропускати запуск тестів** після кожної зміни\n4. **Ніколи не продовжувати, якщо тести не проходять** — виправити або відкатити\n5. **Ніколи не припускати** — якщо сумніваєтесь, запитайте\n\n### Чого НЕ робити\n\n- Не поєднуйте рефакторинг з додаванням функцій\n- Не рефакторте під час аварій на продакшні\n- Не рефакторте код, який не розумієте\n- Не переускладнюйте — тримайте просто\n- Не рефакторте все одразу\n\n---\n\n## Приклад швидкого старту\n\n### Сценарій: Довгий метод з дублюванням\n\n**До:**\n```javascript\nfunction processOrder(order) {\n  // 150 рядків коду з:\n  // - Дубльованою логікою валідації\n  // - Інлайн-обчисленнями\n  // - Змішаними відповідальностями\n}\n```\n\n**Кроки рефакторингу:**\n\n1. **Переконатися, що тести існують** для processOrder()\n2. **Витягти** валідацію у validateOrder()\n3. **Тест** — має пройти\n4. **Витягти** обчислення у calculateOrderTotal()\n5. **Тест** — має пройти\n6. **Витягти** сповіщення у notifyCustomer()\n7. **Тест** — має пройти\n8. **Перегляд** — processOrder() тепер оркеструє 3 чіткі функції\n\n**Після:**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const total = calculateOrderTotal(order);\n  notifyCustomer(order, total);\n  return { order, total };\n}\n```\n\n---\n\n## Довідники\n\n- [Каталог запахів коду](references/code-smells.md) — повний список запахів коду\n- [Каталог рефакторингів](references/refactoring-catalog.md) — техніки рефакторингу\n- [Шаблон плану рефакторингу](templates/refactoring-plan.md) — шаблон планування\n\n## Скрипти\n\n- `scripts/analyze-complexity.py` — аналіз метрик складності коду\n- `scripts/detect-smells.py` — автоматичне виявлення запахів\n\n## Історія версій\n\n- v1.0.0 (2025-01-15): Початковий випуск з методологією Фаулера, поетапним підходом, точками консультації з користувачем\n","frontmatter":{"name":"refactor","description":"Систематичний рефакторинг коду на основі методології Мартіна Фаулера. Використовуйте, коли користувачі просять рефакторити код, покращити структуру коду, зменшити технічний борг, очистити застарілий код, усунути запахи коду (code smells) або покращити супровідність коду. Ця навичка проводить через поетапний підхід з дослідженням, плануванням та безпечною інкрементальною реалізацією."},"isInternal":false,"tokens":6346,"sizeBytes":20085},{"name":"SKILL.md","path":"vi/03-skills/blog-draft/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/vi/03-skills/blog-draft/SKILL.md","title":"blog-draft","category":"anthropic-skill","format":"markdown","content":"---\nname: blog-draft\ndescription: Soạn thảo bài đăng blog từ ý tưởng và tài nguyên. Sử dụng khi người dùng muốn viết bài blog, tạo nội dung từ nghiên cứu, hoặc soạn thảo bài viết. Hướng dẫn qua nghiên cứu, động não, lập dàn ý, và soạn thảo lặp lại với kiểm soát phiên bản.\n---\n\n## Đầu Vào Người Dùng\n\n```text\n$ARGUMENTS\n```\n\nBạn **BẮT BUỘC** phải xem xét đầu vào của người dùng trước khi tiếp tục. Người dùng nên cung cấp:\n- **Ý tưởng/Chủ đề**: Khái niệm hoặc chủ đề chính cho bài đăng blog\n- **Tài nguyên**: URLs, files, hoặc tài liệu tham khảo để nghiên cứu (tùy chọn nhưng được khuyến nghị)\n- **Đối tượng mục tiêu**: Bài đăng blog dành cho ai (tùy chọn)\n- **Giọng điệu/Phong cách**: Trang trọng, thân mật, kỹ thuật, v.v. (tùy chọn)\n\n**QUAN TRỌNG**: Nếu người dùng đang yêu cầu cập nhật cho một **bài đăng blog hiện có**, bỏ qua các bước 0-8 và bắt đầu trực tiếp tại **Bước 9**. Đọc các file draft hiện có trước, sau đó tiếp tục với quy trình lặp lại.\n\n## Quy Trình Thực Thi\n\nLàm theo các bước này tuần tự. **Đừng bỏ qua bước hoặc tiếp tục mà không có sự chấp thuận của người dùng nơi được chỉ ra.**\n\n### Bước 0: Tạo Thư Mục Dự Án\n\n1. Tạo tên thư mục sử dụng định dạng: `YYYY-MM-DD-ten-chu-de-ngan`\n   - Sử dụng ngày hôm nay\n   - Tạo một slug ngắn, thân thiện với URL từ chủ đề (chữ thường, gạch ngang, tối đa 5 từ)\n\n2. Tạo cấu trúc thư mục:\n   ```\n   blog-posts/\n   └── YYYY-MM-DD-ten-chu-de-ngan/\n       └── resources/\n   ```\n\n3. Xác nhận việc tạo thư mục với người dùng trước khi tiếp tục.\n\n### Bước 1: Nghiên Cứu & Thu Thập Tài Nguyên\n\n1. Tạo thư mục con `resources/` trong thư mục bài đăng blog\n\n2. Với mỗi tài nguyên được cung cấp:\n   - **URLs**: Lấy và lưu thông tin chính vào `resources/` dưới dạng files markdown\n   - **Files**: Đọc và tóm tắt trong `resources/`\n   - **Chủ đề**: Sử dụng tìm kiếm web để thu thập thông tin cập nhật\n\n3. Với mỗi tài nguyên, tạo một file tóm tắt trong `resources/`:\n   - `resources/source-1-[ten-ngan].md`\n   - `resources/source-2-[ten-ngan].md`\n   - v.v.\n\n4. Mỗi tóm tắt nên bao gồm:\n   ```markdown\n   # Nguồn: [Tiêu Đề/URL]\n\n   ## Các Điểm Chính\n   - Điểm 1\n   - Điểm 2\n\n   ## Trích Dẫn/Dữ Liệu Liên Quan\n   - Trích dẫn hoặc thống kê 1\n   - Trích dẫn hoặc thống kê 2\n\n   ## Cái Này Liên Quan Đến Chủ Đề Như Thế Nào\n   Giải thích ngắn về sự liên quan\n   ```\n\n5. Trình bày tóm tắt nghiên cứu cho người dùng.\n\n### Bước 2: Động Não & Làm Rõ\n\n1. Dựa trên ý tưởng và các tài nguyên đã nghiên cứu, trình bày:\n   - **Chủ đề chính** được xác định từ nghiên cứu\n   - **Góc độ tiềm năng** cho bài đăng blog\n   - **Các điểm chính** nên được bao phủ\n   - **Khoảng trống** trong thông tin cần làm rõ\n\n2. Đặt các câu hỏi làm rõ:\n   - Điều chính bạn muốn người đọc nhận được là gì?\n   - Có điểm cụ thể nào từ nghiên cứu bạn muốn nhấn mạnh không?\n   - Độ dài mục tiêu là bao nhiêu? (ngắn: 500-800 từ, trung bình: 1000-1500, dài: 2000+)\n   - Có điểm nào bạn muốn loại bỏ không?\n\n3. **Chờ phản hồi của người dùng trước khi tiếp tục.**\n\n### Bước 3: Đề Xuất Dàn Ý\n\n1. Tạo một dàn ý có cấu trúc bao gồm:\n\n   ```markdown\n   # Dàn Ý Bài Đăng Blog: [Tiêu Đề]\n\n   ## Thông Tin Meta\n   - **Đối Tượng Mục Tiêu**: [ai]\n   - **Giọng Điệu**: [phong cách]\n   - **Độ Dài Mục Tiêu**: [số lượng từ]\n   - **Điểm Chính Lấy Được**: [thông điệp chính]\n\n   ## Cấu Trúc Được Đề Xuất\n\n   ### Mở Bài/Giới Thiệu\n   - Ý tưởng mở bài hấp dẫn\n   - Thiết lập bối cảnh\n   - Tuyên bố luận điểm\n\n   ### Phần 1: [Tiêu Đề]\n   - Điểm chính A\n   - Điểm chính B\n   - Bằng chứng hỗ trợ từ [nguồn]\n\n   ### Phần 2: [Tiêu Đề]\n   - Điểm chính A\n   - Điểm chính B\n\n   [Tiếp tục cho tất cả các phần...]\n\n   ### Kết Luận\n   - Tóm tắt các điểm chính\n   - Kêu gọi hành động hoặc suy nghĩ cuối cùng\n\n   ## Nguồn Để Trích Dẫn\n   - Nguồn 1\n   - Nguồn 2\n   ```\n\n2. Trình bày dàn ý cho người dùng và **yêu cầu chấp thuận hoặc chỉnh sửa**.\n\n### Bước 4: Lưu Dàn Ý Được Chấp Thuận\n\n1. Khi người dùng chấp thuận dàn ý, lưu nó vào `OUTLINE.md` trong thư mục bài đăng blog.\n\n2. Xác nhận dàn ý đã được lưu.\n\n### Bước 5: Commit Dàn Ý (nếu trong git repo)\n\n1. Kiểm tra xem thư mục hiện tại có phải là một git repository không.\n\n2. Nếu có:\n   - Stage các file mới: thư mục bài đăng blog, resources, và OUTLINE.md\n   - Tạo commit với thông điệp: `docs: Add outline for blog post - [ten-chu-de]`\n   - Push đến remote\n\n3. Nếu không phải là git repo, bỏ qua bước này và thông báo cho người dùng.\n\n### Bước 6: Viết Bản Nháp\n\n1. Dựa trên dàn ý được chấp thuận, viết bản nháp bài đăng blog đầy đủ.\n\n2. Làm theo cấu trúc từ OUTLINE.md chính xác.\n\n3. Bao gồm:\n   - Giới thiệu hấp dẫn với mở bài\n   - Các tiêu đề phần rõ ràng\n   - Bằng chứng hỗ trợ và ví dụ từ nghiên cứu\n   - Chuyển tiếp mượt mà giữa các phần\n   - Kết luận mạnh mẽ với điểm chính\n   - **Trích dẫn**: Tất cả các so sánh, thống kê, dữ liệu, và yêu cầu thực tế PHẢI trích dẫn nguồn gốc\n\n4. Lưu bản nháp dưới dạng `draft-v0.1.md` trong thư mục bài đăng blog.\n\n5. Định dạng:\n   ```markdown\n   # [Tiêu Đề Bài Đăng Blog]\n\n   *[Tùy chọn: phụ đề hoặc câu khẩu hiệu]*\n\n   [Nội dung đầy đủ với các trích dẫn nội tuyến...]\n\n   ---\n\n   ## Tài Liệu Tham Khảo\n   - [1] Tiêu Đề Nguồn 1 - URL hoặc Trích Dẫn\n   - [2] Tiêu Đề Nguồn 2 - URL hoặc Trích Dẫn\n   - [3] Tiêu Đề Nguồn 3 - URL hoặc Trích Dẫn\n   ```\n\n6. **Yêu Cầu Trích Dẫn**:\n   - Mọi điểm dữ liệu, thống kê, hoặc so sánh PHẢI có trích dẫn nội tuyến\n   - Sử dụng tài liệu tham khảo đánh số [1], [2], v.v., hoặc trích dẫn có tên [Tên Nguồn]\n   - Liên kết các trích dẫn với phần Tài Liệu Tham Khảo ở cuối\n   - Ví dụ: \"Các nghiên cứu cho thấy 65% nhà phát triển ưa thích TypeScript [1]\"\n   - Ví dụ: \"React hoạt động tốt hơn Vue 20% về tốc độ render [React Benchmarks 2024]\"\n\n### Bước 7: Commit Bản Nháp (nếu trong git repo)\n\n1. Kiểm tra xem có trong git repository không.\n\n2. Nếu có:\n   - Stage file bản nháp\n   - Tạo commit với thông điệp: `docs: Add draft v0.1 for blog post - [ten-chu-de]`\n   - Push đến remote\n\n3. Nếu không phải là git repo, bỏ qua và thông báo cho người dùng.\n\n### Bước 8: Trình Bày Bản Nháp Để Xem Xét\n\n1. Trình bày nội dung bản nháp cho người dùng.\n\n2. Yêu cầu phản hồi:\n   - Ấn tượng tổng thể?\n   - Các phần cần mở rộng hoặc giảm bớt?\n   - Cần điều chỉnh giọng điệu?\n   - Thiếu thông tin?\n   - Chỉnh sửa hoặc viết lại cụ thể?\n\n3. **Chờ phản hồi của người dùng.**\n\n### Bước 9: Lặp Lại Hoặc Hoàn Thành\n\n**Nếu người dùng yêu cầu thay đổi:**\n1. Ghi chú tất cả các chỉnh sửa được yêu cầu\n2. Quay lại Bước 6 với các điều chỉnh sau:\n   - Tăng số phiên bản (v0.2, v0.3, v.v.)\n   - Kết hợp tất cả phản hồi\n   - Lưu dưới dạng `draft-v[X.Y].md`\n   - Lặp lại Các bước 7-8\n\n**Nếu người dùng chấp thuận:**\n1. Xác nhận phiên bản bản nháp cuối cùng\n2. Tùy chọn đổi tên thành `final.md` nếu người dùng yêu cầu\n3. Tóm tắt quy trình tạo bài đăng blog:\n   - Tổng số phiên bản được tạo\n   - Các thay đổi chính giữa các phiên bản\n   - Số lượng từ cuối cùng\n   - Các file được tạo\n\n## Theo Dõi Phiên Bản\n\nTất cả bản nháp được bảo tồn với việc đánh số phiên bản tăng dần:\n- `draft-v0.1.md` - Bản nháp ban đầu\n- `draft-v0.2.md` - Sau vòng phản hồi đầu tiên\n- `draft-v0.3.md` - Sau vòng phản hồi thứ hai\n- v.v.\n\nĐiều này cho phép theo dõi sự phát triển của bài đăng blog và hoàn tác nếu cần.\n\n## Cấu Trúc File Đầu Ra\n\n```\nblog-posts/\n└── YYYY-MM-DD-ten-chu-de/\n    ├── resources/\n    │   ├── source-1-name.md\n    │   ├── source-2-name.md\n    │   └── ...\n    ├── OUTLINE.md\n    ├── draft-v0.1.md\n    ├── draft-v0.2.md (nếu có lặp lại)\n    └── draft-v0.3.md (nếu có nhiều lặp lại hơn)\n```\n\n## Mẹo Để Chất Lượng\n\n- **Mở bài**: Bắt đầu với một câu hỏi, sự thật đáng ngạc nhiên, hoặc kịch bản có thể liên quan\n- **Dòng Chảy**: Mỗi đoạn nên kết nối với đoạn tiếp theo\n- **Bằng Chứng**: Hỗ trợ các yêu cầu với dữ liệu từ nghiên cứu\n- **Trích Dẫn**: LUÔN LUÔN trích dẫn nguồn cho:\n  - Tất cả thống kê và điểm dữ liệu (ví dụ: \"Theo [Nguồn], 75% của...\")\n  - So sánh giữa các sản phẩm, dịch vụ, hoặc cách tiếp cận (ví dụ: \"X hoạt động nhanh hơn gấp 2 lần so với Y [Nguồn]\")\n  - Các yêu cầu thực tế về xu hướng thị trường, phát hiện nghiên cứu, hoặc điểm chuẩn\n  - Sử dụng trích dẫn nội tuyến với định dạng: [Tên Nguồn] hoặc [Tác Giả, Năm]\n- **Giọng**: Duy trì giọng điệu nhất quán throughout\n- **Độ Dài**: Tôn trọng số lượng từ mục tiêu\n- **Khả Đọc**: Sử dụng các đoạn ngắn, gạch đầu dòng nơi phù hợp\n- **CTA**: Kết thúc với một lời kêu gọi hành động rõ ràng hoặc câu hỏi đáng suy ngẫm\n\n## Ghi Chú\n\n- Luôn chờ chấp thuận của người dùng tại các điểm kiểm tra được phác thảo\n- Bảo tồn tất cả các phiên bản bản nháp để lịch sử\n- Sử dụng tìm kiếm web để có thông tin cập nhật khi URLs được cung cấp\n- Nếu tài nguyên không đủ, yêu cầu người dùng thêm hoặc đề xuất nghiên cứu bổ sung\n- Thích ứng giọng điệu dựa trên đối tượng mục tiêu (kỹ thuật, chung, kinh doanh, v.v.)\n","frontmatter":{"name":"blog-draft","description":"Soạn thảo bài đăng blog từ ý tưởng và tài nguyên. Sử dụng khi người dùng muốn viết bài blog, tạo nội dung từ nghiên cứu, hoặc soạn thảo bài viết. Hướng dẫn qua nghiên cứu, động não, lập dàn ý, và soạn thảo lặp lại với kiểm soát phiên bản."},"isInternal":false,"tokens":4216,"sizeBytes":11076},{"name":"SKILL.md","path":"vi/03-skills/brand-voice/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/vi/03-skills/brand-voice/SKILL.md","title":"brand-voice","category":"anthropic-skill","format":"markdown","content":"---\nname: brand-voice\ndescription: Đảm bảo tất cả các truyền thông phù hợp với hướng dẫn giọng điệu và phong cách thương hiệu. Sử dụng khi tạo bản sao marketing, truyền thông khách hàng, nội dung công khai, hoặc khi người dùng đề cập đến giọng điệu thương hiệu, ngữ điệu, hoặc phong cách viết.\nuser-invocable: false\n---\n\n# Brand Voice Skill\n\n## Tổng Quan\nSkill này đảm bảo tất cả các truyền thông duy trì giọng điệu, ngữ điệu, và thông điệp thương hiệu nhất quán.\n\n## Danh Tính Thương Hiệu\n\n### Sứ Mệnh\nGiúp các đội tự động hóa workflows phát triển của họ với AI\n\n### Giá Trị\n- **Sự Đơn Giản**: Làm cho những điều phức tạp trở nên đơn giản\n- **Độ Tin Cậy**: Thực thi vững chắc\n- **Sự Trao Quyền**: Cho phép sự sáng tạo của con người\n\n### Giọng Điệu\n- **Thân thiện nhưng chuyên nghiệp** - có thể tiếp cận mà không thân mật quá\n- **Rõ ràng và ngắn gọn** - tránh thuật ngữ, giải thích các khái niệm kỹ thuật một cách đơn giản\n- **Tự Tin** - chúng tôi biết chúng tôi đang làm gì\n- **Thấu Cảm** - hiểu nhu cầu và nỗi đau của người dùng\n\n## Hướng Dẫn Viết\n\n### Nên Làm ✅\n- Sử dụng \"bạn\" khi người đọc\n- Sử dụng chủ động: \"Claude tạo báo cáo\" không \"Báo cáo được tạo bởi Claude\"\n- Bắt đầu với giá trị\n- Sử dụng các ví dụ cụ thể\n- Giữ câu dưới 20 từ\n- Sử dụng danh sách để rõ ràng\n- Bao gồm các lời kêu gọi hành động\n\n### Không Nên Làm ❌\n- Đừng sử dụng thuật ngữ công ty\n- Đừng cư xử như trên hoặc đơn giản hóa quá mức\n- Đừng sử dụng \"chúng tôi tin\" hoặc \"chúng tôi nghĩ\"\n- Đừng sử dụng HOA TOÀN THỨ TRỪ khi nhấn mạnh\n- Đừng tạo các bức tường văn bản\n- Đừng giả định kiến thức kỹ thuật\n\n## Từ Vựng\n\n### ✅ Thuật Ngữ Ưu Tiên\n- Claude (not \"the Claude AI\")\n- Code generation (not \"auto-coding\")\n- Agent (not \"bot\")\n- Streamline (not \"revolutionize\")\n- Integrate (not \"synergize\")\n\n### ❌ Tránh Thuật Ngữ\n- \"Cutting-edge\" (bị lạm dụng)\n- \"Game-changer\" (mơ hồ)\n- \"Leverage\" (ngôn ngữ công ty)\n- \"Utilize\" (use \"use\")\n- \"Paradigm shift\" (không rõ)\n\n## Ví Dụ\n\n### ✅ Ví Dụ Tốt\n\"Claude tự động hóa quy trình review code của bạn. Thay vì kiểm tra thủ công từng PR, Claude review bảo mật, hiệu suất, và chất lượng—tiết kiệm cho đội của bạn hàng mỗi tuần.\"\n\nTại sao nó hoạt động: Giá trị rõ ràng, lợi ích cụ thể, hướng hành động\n\n### ❌ Ví Dụ Xấu\n\"Claude leverages cutting-edge AI to provide comprehensive software development solutions.\"\n\nTại sao nó không hoạt động: Mơ hồ, thuật ngữ công ty, không có giá trị cụ thể\n","frontmatter":{"name":"brand-voice","description":"Đảm bảo tất cả các truyền thông phù hợp với hướng dẫn giọng điệu và phong cách thương hiệu. Sử dụng khi tạo bản sao marketing, truyền thông khách hàng, nội dung công khai, hoặc khi người dùng đề cập đến giọng điệu thương hiệu, ngữ điệu, hoặc phong cách viết.","user-invocable":false},"isInternal":false,"tokens":1101,"sizeBytes":3033},{"name":"SKILL.md","path":"vi/03-skills/claude-md/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/vi/03-skills/claude-md/SKILL.md","title":"claude-md","category":"anthropic-skill","format":"markdown","content":"---\nname: claude-md\ndescription: Tạo hoặc cập nhật các file CLAUDE.md theo các thực hành tốt nhất để onboarding tác nhân AI tối ưu\n---\n\n## Đầu Vào Người Dùng\n\n```text\n$ARGUMENTS\n```\n\nBạn **BẮT BUỘC** phải xem xét đầu vào của người dùng trước khi tiếp tục (nếu không trống). Người dùng có thể chỉ định:\n- `create` - Tạo CLAUDE.md mới từ đầu\n- `update` - Cải thiện CLAUDE.md hiện có\n- `audit` - Phân tích và báo cáo về chất lượng CLAUDE.md hiện tại\n- Một đường dẫn cụ thể để tạo/cập nhật (ví dụ: `src/api/CLAUDE.md` cho hướng dẫn cụ thể thư mục)\n\n## Nguyên Tắc Cốt Lõi\n\n**LLMs là không trạng thái**: CLAUDE.md là file dự án chính được tải vào mọi cuộc hội thoại (cùng với auto memory và các rules không giới hạn phạm vi). Nó phục vụ như tài liệu onboarding chính cho các tác nhân AI vào codebase của bạn.\n\n### Các Quy Tắc Vàng\n\n1. **Less is More**: Các LLM biên giới có thể theo ~150-200 hướng dẫn. System prompt của Claude Code đã sử dụng ~50. Giữ CLAUDE.md của bạn tập trung và ngắn gọn.\n\n2. **Ứng Dụng Phổ Biến**: Chỉ bao gồm thông tin liên quan đến MỌI phiên. Hướng dẫn cụ thể theo tác vụ thuộc về các file riêng.\n\n3. **Đừng Sử Dụng Claude như Linter**: Hướng dẫn phong cách làm phình bối cảnh và làm giảm khả năng tuân theo hướng dẫn. Sử dụng các công cụ xác định (prettier, eslint, v.v.) thay thế.\n\n4. **Không Bao Giờ Tự Động Tạo**: CLAUDE.md là điểm đòn bẩy cao nhất của hệ thống AI. Tạo nó thủ công với sự xem xét cẩn thận.\n\n## Quy Trình Thực Thi\n\n### 1. Phân Tích Dự Án\n\nĐầu tiên, phân tích trạng thái dự án hiện tại:\n\n1. Kiểm tra các file CLAUDE.md hiện có:\n   - Cấp root: `./CLAUDE.md` hoặc `.claude/CLAUDE.md`\n   - Cụ thể thư mục: `**/CLAUDE.md`\n   - Cấu hình người dùng toàn cầu: `~/.claude/CLAUDE.md`\n\n2. Xác định cấu trúc dự án:\n   - Technology stack (ngôn ngữ, frameworks)\n   - Loại dự án (monorepo, ứng dụng đơn, library)\n   - Công cụ phát triển (quản lý package, hệ thống build, trình chạy test)\n\n3. Xem lại tài liệu hiện có:\n   - README.md\n   - CONTRIBUTING.md\n   - package.json, pyproject.toml, Cargo.toml, v.v.\n\n### 2. Chiến Lược Nội Dung (WHAT, WHY, HOW)\n\nCấu trúc CLAUDE.md xung quanh ba chiều:\n\n#### WHAT - Công Nghệ & Cấu Trúc\n- Tổng quan technology stack\n- Tổ chức dự án (đặc biệt quan trọng cho monorepos)\n- Các thư mục chính và mục đích của chúng\n\n#### WHY - Mục Đích & Bối Cảnh\n- Dự án làm gì\n- Tại sao các quyết định kiến trúc nhất định được đưa ra\n- Mỗi thành phần chính chịu trách nhiệm cho gì\n\n#### HOW - Workflow & Quy Ước\n- Workflow phát triển (bun vs node, pip vs uv, v.v.)\n- Thủ tục và lệnh testing\n- Phương pháp xác minh và build\n- Các \"gotchas\" quan trọng hoặc yêu cầu không rõ ràng\n\n### 3. Chiến Lược Progressive Disclosure\n\nĐối với các dự án lớn, khuyến nghị tạo thư mục `agent_docs/`:\n\n```\nagent_docs/\n  |- building_the_project.md\n  |- running_tests.md\n  |- code_conventions.md\n  |- architecture_decisions.md\n```\n\nTrong CLAUDE.md, tham khảo các file này với các hướng dẫn như:\n```markdown\nĐể có hướng dẫn build chi tiết, tham khảo `agent_docs/building_the_project.md`\n```\n\n**Quan Trọng**: Sử dụng các tham chiếu `file:line` thay vì các đoạn code để tránh bối cảnh lỗi thời.\n\n### 4. Ràng Buộc Chất Lượng\n\nKhi tạo hoặc cập nhật CLAUDE.md:\n\n1. **Độ Dài Mục Tiêu**: Dưới 200 dòng\n2. **Không Quy Tắc Phong Cách**: Loại bỏ bất kỳ hướng dẫn linting/formatting nào\n3. **Không Hướng Dẫn Cụ Theo Tác Vụ**: Di chuyển sang các file riêng\n4. **Không Đoạn Code**: Sử dụng tham chiếu file thay thế\n5. **Không Thông Tin Dư Thừa**: Đừng lặp lại những gì trong package.json hoặc README\n\n### 5. Các Phần Thiết Yếu\n\nMột CLAUDE.md được cấu trúc tốt nên bao gồm:\n\n```markdown\n# Tên Dự Án\n\nMô tả ngắn một dòng.\n\n## Tech Stack\n- Ngôn ngữ chính và phiên bản\n- Frameworks/thư viện chính\n- Database/lưu trữ (nếu có)\n\n## Cấu Trúc Dự Án\n[Chỉ cho monorepos hoặc cấu trúc phức tạp]\n- `apps/` - Điểm vào ứng dụng\n- `packages/` - Thư viện được chia sẻ\n\n## Lệnh Phát Triển\n- Install: `command`\n- Test: `command`\n- Build: `command`\n\n## Quy Ước Quan Trọng\n[Chỉ các quy ước không rõ ràng, tác động cao]\n- Quy ước 1 với giải thích ngắn\n- Quy ước 2 với giải thích ngắn\n\n## Vấn Đế Đã Biết / Gotchas\n[Những gì luôn làm các nhà phát triển vấp phải]\n- Vấn đề 1\n- Vấn đề 2\n```\n\n### 6. Các Anti-Patterns Cần Tránh\n\n**KHÔNG bao gồm:**\n- Hướng dẫn phong cách code (sử dụng linters)\n- Tài liệu về cách sử dụng Claude\n- Giải thích dài về các mẫu rõ ràng\n- Các ví dụ code copy-paste\n- Thực hành tốt chung (\"viết code sạch\")\n- Hướng dẫn cho các tác vụ cụ thể\n- Nội dung được tạo tự động\n- Danh sách TODO mở rộng\n\n### 7. Checklist Xác Minh\n\nTrước khi hoàn thành, xác minh:\n\n- [ ] Dưới 200 dòng\n- [ ] Mọi dòng áp dụng cho TẤT CẢ các phiên\n- [ ] Không quy tắc phong cách/formatting\n- [ ] Không đoạn code (sử dụng tham chiếu file)\n- [ ] Các lệnh được xác minh hoạt động\n- [ ] Progressive disclosure được sử dụng cho các dự án phức tạp\n- [ ] Các gotchas quan trọng được tài liệu hóa\n- [ ] Không dư thừa với README.md\n\n## Định Dạng Đầu Ra\n\n### Cho `create` hoặc mặc định:\n\n1. Phân tích dự án\n2. Soạn thảo CLAUDE.md theo cấu trúc ở trên\n3. Trình bày bản nháp để xem xét\n4. Ghi vào vị trí phù hợp sau khi được chấp thuận\n\n### Cho `update`:\n\n1. Đọc CLAUDE.md hiện có\n2. Kiểm tra theo các thực hành tốt nhất\n3. Xác định:\n   - Nội dung để loại bỏ (quy tắc phong cách, đoạn code, cụ thể tác vụ)\n   - Nội dung để cô đọng\n   - Thông tin thiết bị còn thiếu\n4. Trình bày các thay đổi để xem xét\n5. Áp dụng các thay đổi sau khi được chấp thuận\n\n### Cho `audit`:\n\n1. Đọc CLAUDE.md hiện có\n2. Tạo một báo cáo với:\n   - Số dòng hiện tại vs mục tiêu\n   - Phần trăm nội dung áp dụng phổ biến\n   - Danh sách các anti-patterns được tìm thấy\n   - Khuyến nghị cải thiện\n3. KHÔNG chỉnh sửa file, chỉ báo cáo\n\n## Xử Lý AGENTS.md\n\nNếu người dùng yêu cầu tạo/cập nhật AGENTS.md:\n\n**Từ v2.1.277, Claude Code đọc `AGENTS.md` trực tiếp như hướng dẫn dự án** — nhưng chỉ khi thư mục làm việc và mọi thư mục phía trên nó đều không có `CLAUDE.md`, `.claude/CLAUDE.md`, hay `CLAUDE.local.md`. `~/.claude/CLAUDE.md`, CLAUDE.md được quản lý, và `.claude/rules/` không tính vào kiểm tra đó và vẫn được tải song song. Hành vi này được điều khiển bởi **Project instructions** trong `/config`: `claude-md-or-agents-md` (mặc định), `claude-md-and-agents-md`, `claude-md`, hoặc `managed-only`. Ở nơi không hỗ trợ đọc trực tiếp — phiên bản trước v2.1.277 (trước v2.1.281 trên Bedrock/Vertex/Foundry, LLM gateway, hoặc khi telemetry bị tắt), hoặc phiên đầu tiên sau khi nâng cấp — hãy dùng cách dự phòng: import từ CLAUDE.md bằng `@AGENTS.md`, hoặc symlink `CLAUDE.md` tới nó.\n\nAGENTS.md là file bối cảnh dự án dùng chung giữa nhiều công cụ — cùng *loại* tài liệu với CLAUDE.md, không phải định dạng định nghĩa tác nhân. Nó tồn tại để nhiều coding agent có thể dùng chung một bộ quy ước dự án:\n- Các lệnh build, test, và lint\n- Quy ước code style và kiến trúc\n- Bố cục repository và vị trí của các thành phần\n\nSubagents được định nghĩa riêng, trong `.claude/agents/*.md` — không phải trong AGENTS.md.\n\nÁp dụng các nguyên tắc tương tự:\n- Giữ tập trung và ngắn gọn\n- Sử dụng progressive disclosure\n- Tham khảo tài liệu bên ngoài thay vì nhúng nội dung\n\n## Ghi Chú\n\n- Luôn xác minh các lệnh hoạt động trước khi bao gồm chúng\n- Khi nghi ngờ, hãy loại bỏ - less is more\n- Lời nhắc hệ thống cho Claude biết rằng CLAUDE.md \"có thể hoặc có thể không liên quan\" - càng nhiều tiếng ồn, càng bị bỏ qua\n- Monorepos hưởng lợi nhất từ cấu trúc WHAT/WHY/HOW rõ ràng\n- Các file CLAUDE.md cụ thể thư mục nên được tập trung hơn nữa\n\n---\n\n**Cập Nhật Lần Cuối**: Ngày 18 tháng 10 năm 2026\n**Phiên Bản Claude Code**: 2.1.302\n**Nguồn**:\n- https://code.claude.com/docs/en/memory\n","frontmatter":{"name":"claude-md","description":"Tạo hoặc cập nhật các file CLAUDE.md theo các thực hành tốt nhất để onboarding tác nhân AI tối ưu"},"isInternal":false,"tokens":3393,"sizeBytes":9289},{"name":"SKILL.md","path":"vi/03-skills/code-review-specialist/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/vi/03-skills/code-review-specialist/SKILL.md","title":"code-review-specialist","category":"anthropic-skill","format":"markdown","content":"---\nname: code-review-specialist\ndescription: Review code toàn diện với phân tích bảo mật, hiệu suất, và chất lượng. Sử dụng khi người dùng yêu cầu review code, phân tích chất lượng code, đánh giá pull requests, hoặc đề cập đến review code, phân tích bảo mật, hoặc tối ưu hóa hiệu suất.\n---\n\n# Code Review Skill\n\nSkill này cung cấp các khả năng review code toàn diện tập trung vào:\n\n1. **Phân Tích Bảo Mật**\n   - Các vấn đề xác thực/uỷ quyền\n   - Rủi ro lộ dữ liệu\n   - Lỗ hổng tiêm nhiễm\n   - Điểm yếu mật mã\n   - Ghi log dữ liệu nhạy cảm\n\n2. **Review Hiệu Suất**\n   - Hiệu quả thuật toán (phân tích Big O)\n   - Tối ưu hóa bộ nhớ\n   - Tối ưu hóa truy vấn cơ sở dữ liệu\n   - Cơ hội caching\n   - Các vấn đề đồng thời\n\n3. **Chất Lượng Code**\n   - Nguyên tắc SOLID\n   - Mẫu thiết kế\n   - Quy ước đặt tên\n   - Tài liệu hóa\n   - Phủ vùng test\n\n4. **Khả Năng Duy Trì**\n   - Khả năng đọc code\n   - Kích thước hàm (nên < 50 dòng)\n   - Độ phức tạp vòng lục\n   - Quản lý dependency\n   - An toàn kiểu\n\n## Mẫu Review\n\nĐối với mỗi đoạn code được review, cung cấp:\n\n### Tóm Tắt\n- Đánh giá chất lượng tổng thể (1-5)\n- Số lượng phát hiện chính\n- Các khu vực ưu tiên được khuyến nghị\n\n### Vấn Đề Nguy Kịch (nếu có)\n- **Vấn đề**: Mô tả rõ ràng\n- **Vị Trí**: File và số dòng\n- **Tác Động**: Tại sao điều này quan trọng\n- **Mức Độ**: Nguy Kịch/Cao/Trung Bình\n- **Khắc Phục**: Ví dụ code\n\n### Các Phát Hiện Theo Danh Mục\n\n#### Bảo Mật (nếu tìm thấy vấn đề)\nLiệt kê các lỗ hổng bảo mật với ví dụ\n\n#### Hiệu Suất (nếu tìm thấy vấn đề)\nLiệt kê các vấn đề hiệu suất với phân tích độ phức tạp\n\n#### Chất Lượng (nếu tìm thấy vấn đề)\nLiệt kê các vấn đề chất lượng code với các đề xuất refactor\n\n#### Khả Năng Duy Trì (nếu tìm thấy vấn đề)\nLiệt kê các vấn đề duy trì với các cải tiến\n\n## Lịch Sử Phiên Bản\n\n- v1.0.0 (2024-12-10): Phiên bản phát hành ban đầu với phân tích bảo mật, hiệu suất, chất lượng, và khả năng duy trì\n","frontmatter":{"name":"code-review-specialist","description":"Review code toàn diện với phân tích bảo mật, hiệu suất, và chất lượng. Sử dụng khi người dùng yêu cầu review code, phân tích chất lượng code, đánh giá pull requests, hoặc đề cập đến review code, phân tích bảo mật, hoặc tối ưu hóa hiệu suất."},"isInternal":false,"tokens":900,"sizeBytes":2424},{"name":"SKILL.md","path":"vi/03-skills/refactor/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/vi/03-skills/refactor/SKILL.md","title":"refactor","category":"anthropic-skill","format":"markdown","content":"---\nname: refactor\ndescription: Refactor code có hệ thống dựa trên phương pháp luận của Martin Fowler. Sử dụng khi người dùng yêu cầu refactor code, cải thiện cấu trúc code, giảm nợ kỹ thuật, dọn code legacy, loại bỏ code smells, hoặc cải thiện khả năng duy trì code. Skill này hướng dẫn qua cách tiếp theo từng giai đoạn với nghiên cứu, lập kế hoạch, và triển khai tăng dần an toàn.\n---\n\n# Code Refactoring Skill\n\nMột cách tiếp có hệ thống để refactor code dựa trên *Refactoring: Improving the Design of Existing Code* (ấn bản 2) của Martin Fowler. Skill này nhấn mạnh các thay đổi tăng dần, an toàn được hỗ trợ bởi tests.\n\n> \"Refactoring là quá trình thay đổi một hệ thống phần mềm theo cách mà nó không làm thay đổi hành vi bên ngoài của code nhưng cải thiện cấu trúc nội bộ của nó.\" — Martin Fowler\n\n## Nguyên Tắc Cốt Lõi\n\n1. **Bảo Tồn Hành Vi**: Hành vi bên ngoài phải không thay đổi\n2. **Các Bước Nhỏ**: Thực hiện các thay đổi nhỏ, có thể test\n3. **Được Dẫn Bởi Test**: Tests là lưới an toàn\n4. **Liên Tục**: Refactoring là liên tục, không phải sự kiện một lần\n5. **Hợp Tác**: Cần sự chấp thuận của người dùng tại mỗi giai đoạn\n\n## Tổng Quan Workflow\n\n```\nGiai Đoạn 1: Nghiên Cứu & Phân Tích\n    ↓\nGiai Đoạn 2: Đánh Giá Phủ Vùng Test\n    ↓\nGiai Đoạn 3: Xác Định Code Smell\n    ↓\nGiai Đoạn 4: Tạo Kế Hoạch Refactoring\n    ↓\nGiai Đoạn 5: Triển Khai Tăng Dần\n    ↓\nGiai Đoạn 6: Review & Lặp Lại\n```\n\n---\n\n## Giai Đoạn 1: Nghiên Cứu & Phân Tích\n\n### Mục Tiêu\n- Hiểu cấu trúc và mục đích của codebase\n- Xác định phạm vi của refactoring\n- Thu thập bối cảnh về các yêu cầu kinh doanh\n\n### Câu Hỏi Đặt Cho Người Dùng\nTrước khi bắt đầu, làm rõ:\n\n1. **Phạm Vi**: Những file/module/hàm nào cần refactor?\n2. **Mục Tiêu**: Bạn đang cố gắng giải quyết vấn đề gì? (khả đọc, hiệu suất, khả năng duy trì)\n3. **Ràng Buộc**: Có những khu vực nào KHÔNG NÊN thay đổi không?\n4. **Áp Lực Thời Gian**: Điều này có chặn công việc khác không?\n5. **Trạng Thái Test**: Tests có tồn tại không? Chúng có pass không?\n\n### Hành Động\n- [ ] Đọc và hiểu code mục tiêu\n- [ ] Xác định dependencies và integrations\n- [ ] Tài liệu hóa kiến trúc hiện tại\n- [ ] Ghi chú bất kỳ markers nợ kỹ thuật hiện có (TODOs, FIXMEs)\n\n### Đầu Ra\nTrình bày phát hiện cho người dùng:\n- Tóm tắt cấu trúc code\n- Các khu vực vấn đề được xác định\n- Khuyến nghị ban đầu\n- **Yêu cầu chấp thuận để tiếp tục**\n\n---\n\n## Giai Đoạn 2: Đánh Giá Phủ Vùng Test\n\n### Tại Sao Tests Quan Trọng\n> \"Refactoring mà không có tests giống như lái xe mà không có thắt dây an toàn.\" — Martin Fowler\n\nTests là **bật dụng chính** của refactoring an toàn. Không có chúng, bạn có nguy cơ giới thiệu bugs.\n\n### Các Bước Đánh Giá\n\n1. **Kiểm tra các test hiện có**\n   ```bash\n   # Tìm các file test\n   find . -name \"*test*\" -o -name \"*spec*\" | head -20\n   ```\n\n2. **Chạy các test hiện có**\n   ```bash\n   # JavaScript/TypeScript\n   npm test\n\n   # Python\n   pytest -v\n\n   # Java\n   mvn test\n   ```\n\n3. **Kiểm tra phủ vùng (nếu có)**\n   ```bash\n   # JavaScript\n   npm run test:coverage\n\n   # Python\n   pytest --cov=.\n   ```\n\n### Điểm Quyết Định: Hỏi Người Dùng\n\n**Nếu tests tồn tại và pass:**\n- Tiếp tục đến Giai Đoạn 3\n\n**Nếu tests bị thiếu hoặc không hoàn chỉnh:**\nTrình bày các tùy chọn:\n1. Viết tests trước (khuyến nghị)\n2. Thêm tests tăng dần trong khi refactoring\n3. Tiếp tục mà không có tests (rủi ro - yêu cầu sự thừa nhận của người dùng)\n\n**Nếu tests đang fail:**\n- DỪNG LẠI. Sửa các test fail trước khi refactoring\n- Hỏi người dùng: Chúng ta nên sửa tests trước không?\n\n### Hướng Dẫn Viết Test (nếu cần)\n\nĐối với mỗi hàm được refactor, đảm bảo tests bao phủ:\n- Happy path (hoạt động bình thường)\n- Các trường hợp ngoại lệ (đầu vào trống, null, ranh giới)\n- Các kịch bản lỗi (đầu vào không hợp lệ, ngoại lệ)\n\nSử dụng chu trình \"red-green-refactor\":\n1. Viết test fail (red)\n2. Làm cho nó pass (green)\n3. Refactor\n\n---\n\n## Giai Đoạn 3: Xác Định Code Smell\n\n### Code Smells Là Gì?\nCác triệu chứng của các vấn đề sâu hơn trong code. Chúng không phải là bugs, nhưng là các chỉ báo rằng code có thể được cải thiện.\n\n### Các Code Smells Phổ Biến Để Kiểm Tra\n\nXem [references/code-smells.md](../../../03-skills/refactor/references/code-smells.md) để có danh sách đầy đủ.\n\n#### Tham Khảo Nhanh\n\n| Smell | Dấu Hiệu | Tác Động |\n|-------|-------|--------|\n| **Long Method** | Methods > 30-50 dòng | Khó hiểu, test, duy trì |\n| **Duplicated Code** | Cùng logic ở nhiều nơi | Cần sửa lỗi ở nhiều nơi |\n| **Large Class** | Class với quá nhiều trách nhiệm | Vi phạm Single Responsibility |\n| **Feature Envy** | Method sử dụng dữ liệu class khác nhiều | Đóng gói kém |\n| **Primitive Obsession** | Lạm dụng primitives thay vì objects | Thiếu các khái niệm domain |\n| **Long Parameter List** | Methods với 4+ parameters | Khó gọi đúng |\n| **Data Clumps** | Cùng dữ liệu xuất hiện cùng nhau | Thiếu abstraction |\n| **Switch Statements** | Switch/if-else chains phức tạp | Khó mở rộng |\n| **Speculative Generality** | Code \"trường hợp\" | Độ phức tạp không cần thiết |\n| **Dead Code** | Code không sử dụng | Nhầm lẫn, gánh nặng duy trì |\n\n### Các Bước Phân Tích\n\n1. **Phân Tích Tự Động** (nếu scripts có sẵn)\n   ```bash\n   python scripts/detect-smells.py <file>\n   ```\n\n2. **Review Thủ Công**\n   - Đi qua code một cách có hệ thống\n   - Ghi chú mỗi smell với vị trí và mức độ nghiêm trọng\n   - Phân loại theo tác động (Nguy Kịch/Cao/Trung Bình/Thấp)\n\n3. **Ưu Tiên**\n   Tập trung vào các smells mà:\n   - Chặn phát triển hiện tại\n   - Gây bugs hoặc nhầm lẫn\n   - Ảnh hưởng đến các đường dẫn code được thay đổi nhiều nhất\n\n### Đầu Ra: Báo Cáo Smell\n\nTrình bày cho người dùng:\n- Danh sách các smells được xác định với vị trí\n- Đánh giá mức độ nghiêm trọng cho mỗi smell\n- Thứ tự ưu tiên được khuyến nghị\n- **Yêu cầu chấp thuận về các ưu tiên**\n\n---\n\n## Giai Đoạn 4: Tạo Kế Hoạch Refactoring\n\n### Chọn Refactorings\n\nĐối với mỗi smell, chọn một refactoring phù hợp từ catalog.\n\nXem [references/refactoring-catalog.md](../../../03-skills/refactor/references/refactoring-catalog.md) để có danh sách đầy đủ.\n\n#### Smell-to-Refactoring Mapping\n\n| Code Smell | Refactoring Khuyến Nghị |\n|------------|---------------------------|\n| Long Method | Extract Method, Replace Temp with Query |\n| Duplicated Code | Extract Method, Pull Up Method, Form Template Method |\n| Large Class | Extract Class, Extract Subclass |\n| Feature Envy | Move Method, Move Field |\n| Primitive Obsession | Replace Primitive with Object, Replace Type Code with Class |\n| Long Parameter List | Introduce Parameter Object, Preserve Whole Object |\n| Data Clumps | Extract Class, Introduce Parameter Object |\n| Switch Statements | Replace Conditional with Polymorphism |\n| Speculative Generality | Collapse Hierarchy, Inline Class, Remove Dead Code |\n| Dead Code | Remove Dead Code |\n\n### Cấu Trúc Kế Hoạch\n\nSử dụng mẫu tại [templates/refactoring-plan.md](../../../03-skills/refactor/templates/refactoring-plan.md).\n\nĐối với mỗi refactoring:\n1. **Mục Tiêu**: Code nào sẽ thay đổi\n2. **Smell**: Vấn đề nào nó giải quyết\n3. **Refactoring**: Kỹ thuật nào để áp dụng\n4. **Các Bước**: Các micro-bước chi tiết\n5. **Rủi Ro**: Điều gì có thể sai\n6. **Hoàn Tác**: Cách hoàn tác nếu cần\n\n### Cách Tiếp Theo Giai Đoạn\n\n**QUAN TRỌNG**: Introduce refactoring tăng dần theo các giai đoạn.\n\n**Giai Đoạn A: Quick Wins** (Rủi ro thấp, giá trị cao)\n- Đổi tên biến để rõ hơn\n- Extract code trùng lặp rõ ràng\n- Loại bỏ dead code\n\n**Giai Đoạn B: Cải Tiến Cấu Trúc** (Rủi ro trung bình)\n- Extract methods từ các hàm dài\n- Introduce parameter objects\n- Move methods đến các lớp phù hợp\n\n**Giai Đoạn C: Thay Đổi Kiến Trúc** (Rủi ro cao hơn)\n- Thay thế conditionals với polymorphism\n- Extract classes\n- Introduce design patterns\n\n### Điểm Quyết Định: Trình Bày Kế Hoạch Cho Người Dùng\n\nTrước khi triển khai:\n- Hiển thị kế hoạch refactoring hoàn chỉnh\n- Giải thích mỗi giai đoạn và rủi ro của nó\n- Nhận sự chấp thuận rõ ràng cho mỗi giai đoạn\n- **Hỏi**: \"Tôi có nên tiếp tục với Giai Đoạn A không?\"\n\n---\n\n## Giai Đoạn 5: Triển Khai Tăng Dần\n\n### Quy Tắc Vàng\n> \"Thay Đổi → Test → Xanh? → Commit → Bước tiếp theo\"\n\n### Nhịp Triển Khai\n\nĐối với mỗi bước refactoring:\n\n1. **Kiểm tra trước**\n   - Tests đang pass (xanh)\n   - Code biên dịch\n\n2. **Thực hiện MỘT thay đổi nhỏ**\n   - Làm theo các cơ chế từ catalog\n   - Giữ thay đổi tối thiểu\n\n3. **Xác Minh**\n   - Chạy tests ngay lập tức\n   - Kiểm tra lỗi biên dịch\n\n4. **Nếu tests pass (xanh)**\n   - Commit với thông điệp mô tả\n   - Di chuyển đến bước tiếp theo\n\n5. **Nếu tests fail (đỏ)**\n   - DỪNG LẠI ngay lập tức\n   - Hoàn tác thay đổi\n   - Phân tích điều gì sai\n   - Hỏi người dùng nếu không rõ\n\n### Chiến Lược Commit\n\nMỗi commit nên là:\n- **Nguyên Tử**: Một thay đổi logic\n- **Có Thể Hoàn Tác**: Dễ dàng revert\n- **Mô Tả**: Thông điệp commit rõ ràng\n\nVí dụ thông điệp commit:\n```\nrefactor: Extract calculateTotal() from processOrder()\nrefactor: Rename 'x' to 'customerCount' for clarity\nrefactor: Remove unused validateOldFormat() method\n```\n\n### Báo Cáo Tiến Độ\n\nSau mỗi sub-giai đoạn, báo cáo cho người dùng:\n- Các thay đổi được thực hiện\n- Tests vẫn pass?\n- Bất kỳ vấn đề nào gặp phải\n- **Hỏi**: \"Tiếp tục với batch tiếp theo?\"\n\n---\n\n## Giai Đoạn 6: Review & Lặp Lại\n\n### Checklist Sau Refactoring\n\n- [ ] Tất cả tests pass\n- [ ] Không có cảnh báo/lỗi mới\n- [ ] Code biên dịch thành công\n- [ ] Hành vi không thay đổi (xác minh thủ công)\n- [ ] Tài liệu được cập nhật nếu cần\n- [ ] Lịch sử commit sạch\n\n### So Sánh Metrics\n\nChạy phân tích độ phức tạp trước và sau:\n```bash\npython scripts/analyze-complexity.py <file>\n```\n\nTrình bày cải tiến:\n- Thay đổi số dòng code\n- Thay đổi độ phức tạp vòng lục\n- Thay đổi chỉ số khả năng duy trì\n\n### Review Người Dùng\n\nTrình bày kết quả cuối cùng:\n- Tóm tắt tất cả thay đổi\n- So sánh code trước/sau\n- Cải tiến metrics\n- Nợ kỹ thuật còn lại\n- **Hỏi**: \"Bạn có hài lòng với những thay đổi này không?\"\n\n### Các Bước Tiếp Theo\n\nThảo luận với người dùng:\n- Có smells bổ sung để giải quyết không?\n- Lên lịch refactoring tiếp theo?\n- Áp dụng các thay đổi tương tự ở nơi khác?\n\n---\n\n## Hướng Dẫn Quan Trọng\n\n### Khi DỪNG LẠI và Hỏi\n\nLuôn dừng lại và tham khảo người dùng khi:\n- Không chắc về logic kinh doanh\n- Thay đổi có thể ảnh hưởng APIs bên ngoài\n- Phủ vùng test không đủ\n- Cần quyết định kiến trúc quan trọng\n- Mức độ rủi ro tăng\n- Bạn gặp độ phức tạp bất ngờ\n\n### Quy Tắc An Toàn\n\n1. **Không bao giờ refactor mà không có tests** (trừ khi người dùng thừa nhận rủi ro một cách rõ ràng)\n2. **Không bao giờ thực hiện các thay đổi lớn** - chia thành các bước nhỏ\n3. **Không bao giờ bỏ qua chạy test** sau mỗi thay đổi\n4. **Không bao giờ tiếp tục nếu tests fail** - sửa hoặc hoàn tác trước\n5. **Không bao giờ giả định** - khi nghi ngờ, hãy hỏi\n\n### Những Gì KHÔNG Nên Làm\n\n- Đừng kết hợp refactoring với việc thêm tính năng\n- Đừng refactor trong các tình huống khẩn cấp của production\n- Đừng refactor code mà bạn không hiểu\n- Đừng over-engineer - giữ nó đơn giản\n- Đừng refactor tất cả cùng một lúc\n\n---\n\n## Ví Dụ Bắt Đầu Nhanh\n\n### Kịch Bản: Long Method với Duplication\n\n**Trước:**\n```javascript\nfunction processOrder(order) {\n  // 150 dòng code với:\n  // - Logic xác thực trùng lặp\n  // - Tính toán nội tuyến\n  // - Trách nhiệm hỗn hợp\n}\n```\n\n**Các Bước Refactoring:**\n\n1. **Đảm bảo tests tồn tại** cho processOrder()\n2. **Extract** xác thực vào validateOrder()\n3. **Test** - nên pass\n4. **Extract** tính toán vào calculateOrderTotal()\n5. **Test** - nên pass\n6. **Extract** thông báo vào notifyCustomer()\n7. **Test** - nên pass\n8. **Review** - processOrder() giờ điều phối 3 hàm rõ ràng\n\n**Sau:**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const total = calculateOrderTotal(order);\n  notifyCustomer(order, total);\n  return { order, total };\n}\n```\n\n---\n\n## Tài Liệu Tham Khảo\n\n- [Catalog Code Smells](../../../03-skills/refactor/references/code-smells.md) - Danh sách đầy đủ code smells\n- [Catalog Refactoring](../../../03-skills/refactor/references/refactoring-catalog.md) - Các kỹ thuật refactoring\n- [Mẫu Kế Hoạch Refactoring](../../../03-skills/refactor/templates/refactoring-plan.md) - Mẫu lập kế hoạch\n\n## Scripts\n\n- `scripts/analyze-complexity.py` - Phân tích metrics độ phức tạp code\n- `scripts/detect-smells.py` - Phát hiện smell tự động\n\n## Lịch Sử Phiên Bản\n\n- v1.0.0 (2025-01-15): Phiên bản phát hành ban đầu với phương pháp luận Fowler, cách tiếp theo từng giai đoạn, các điểm tham khảo người dùng\n","frontmatter":{"name":"refactor","description":"Refactor code có hệ thống dựa trên phương pháp luận của Martin Fowler. Sử dụng khi người dùng yêu cầu refactor code, cải thiện cấu trúc code, giảm nợ kỹ thuật, dọn code legacy, loại bỏ code smells, hoặc cải thiện khả năng duy trì code. Skill này hướng dẫn qua cách tiếp theo từng giai đoạn với nghiên cứu, lập kế hoạch, và triển khai tăng dần an toàn."},"isInternal":false,"tokens":5025,"sizeBytes":14723},{"name":"SKILL.md","path":"zh/03-skills/blog-draft/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/zh/03-skills/blog-draft/SKILL.md","title":"blog-draft","category":"anthropic-skill","format":"markdown","content":"---\nname: blog-draft\ndescription: 根据想法和资料撰写博客草稿。适用于用户想写博客、基于研究创建内容，或起草文章的场景。流程会引导你完成调研、头脑风暴、提纲编写和带版本控制的迭代撰写。\n---\n\n## 用户输入\n\n```text\n$ARGUMENTS\n```\n\n在继续之前，你**必须**先考虑用户输入。用户应提供：\n- **想法/主题**：博客文章的核心概念或主题\n- **资源**：用于研究的 URL、文件或参考资料（可选，但推荐）\n- **目标读者**：这篇博客是写给谁看的（可选）\n- **语气/风格**：正式、轻松、技术向等（可选）\n\n**重要**：如果用户是在请求更新一篇**已有博客文章**，请跳过步骤 0-8，直接从**步骤 9** 开始。先阅读现有草稿文件，再继续迭代流程。\n\n## 执行流程\n\n请按顺序执行以下步骤。**不要跳步，也不要在未获得用户批准的情况下继续执行标明需要确认的步骤。**\n\n### 步骤 0：创建项目文件夹\n\n1. 使用以下格式生成文件夹名称：`YYYY-MM-DD-short-topic-name`\n   - 使用今天的日期\n   - 根据主题生成一个简短、适合 URL 的 slug（小写、连字符连接，最多 5 个词）\n\n2. 创建文件夹结构：\n   ```text\n   blog-posts/\n   └── YYYY-MM-DD-short-topic-name/\n       └── resources/\n   ```\n\n3. 在继续前，先向用户确认文件夹已创建。\n\n### 步骤 1：研究与资源收集\n\n1. 在博客文章目录中创建 `resources/` 子文件夹\n\n2. 对于每个提供的资源：\n   - **URL**：抓取关键内容并保存到 `resources/` 下的 markdown 文件中\n   - **文件**：读取并在 `resources/` 中做摘要\n   - **主题**：使用网络搜索收集最新信息\n\n3. 为每个资源在 `resources/` 中创建摘要文件：\n   - `resources/source-1-[short-name].md`\n   - `resources/source-2-[short-name].md`\n   - 以此类推\n\n4. 每个摘要都应包含：\n   ```markdown\n   # 来源：[标题/URL]\n\n   ## 要点\n   - 要点 1\n   - 要点 2\n\n   ## 相关引文/数据\n   - 引文或统计 1\n   - 引文或统计 2\n\n   ## 与主题的关联\n   简要说明其相关性\n   ```\n\n5. 向用户展示研究摘要。\n\n### 步骤 2：头脑风暴与澄清\n\n1. 基于想法和已研究的资源，展示：\n   - 从研究中识别出的**主要主题**\n   - 博客文章的**可能切入角度**\n   - 应该覆盖的**关键点**\n   - 仍需进一步澄清的**信息缺口**\n\n2. 提出澄清问题：\n   - 你希望读者最终带走的核心结论是什么？\n   - 研究中有没有哪些点是你希望重点强调的？\n   - 目标长度是多少？（短：500-800 字，中：1000-1500 字，长：2000+ 字）\n   - 有没有哪些内容你希望排除？\n\n3. **在继续之前，等待用户回复。**\n\n### 步骤 3：提出提纲\n\n1. 创建一个结构化提纲，包括：\n\n   ```markdown\n   # 博客文章提纲：[标题]\n\n   ## 元信息\n   - **目标读者**：[谁]\n   - **语气**：[风格]\n   - **目标长度**：[字数]\n   - **核心结论**：[关键信息]\n\n   ## 建议结构\n\n   ### 开场/引子\n   - 开场钩子思路\n   - 背景铺垫\n   - 论点陈述\n\n   ### 第一部分：[标题]\n   - 关键点 A\n   - 关键点 B\n   - 来自 [来源] 的支撑证据\n\n   ### 第二部分：[标题]\n   - 关键点 A\n   - 关键点 B\n\n   [继续列出所有部分...]\n\n   ### 结论\n   - 关键点总结\n   - 行动号召或最终思考\n\n   ## 需要引用的来源\n   - 来源 1\n   - 来源 2\n   ```\n\n2. 向用户展示提纲，并**请求批准或修改意见**。\n\n### 步骤 4：保存已批准的提纲\n\n1. 用户批准提纲后，将其保存为博客文章文件夹中的 `OUTLINE.md`。\n\n2. 确认提纲已保存。\n\n### 步骤 5：提交提纲（如果在 git 仓库中）\n\n1. 检查当前目录是否为 git 仓库。\n\n2. 如果是：\n   - 暂存新文件：博客文章文件夹、resources 和 `OUTLINE.md`\n   - 使用如下提交信息创建 commit：`docs: Add outline for blog post - [topic-name]`\n   - 推送到远程仓库\n\n3. 如果不是 git 仓库，则跳过此步骤并告知用户。\n\n### 步骤 6：撰写草稿\n\n1. 基于已批准的提纲，撰写完整博客草稿。\n\n2. 严格按照 `OUTLINE.md` 的结构进行编写。\n\n3. 包含：\n   - 有吸引力的引言和开场钩子\n   - 清晰的章节标题\n   - 来自研究的支撑证据和示例\n   - 段落之间自然流畅的过渡\n   - 强有力的结尾和核心收获\n   - **引用**：所有比较、统计数据和事实性陈述都必须引用原始来源\n\n4. 将草稿保存为博客文章文件夹中的 `draft-v0.1.md`。\n\n5. 格式：\n   ```markdown\n   # [博客文章标题]\n\n   *[可选：副标题或标语]*\n\n   [包含行内引用的完整正文...]\n\n   ---\n\n   ## 参考资料\n   - [1] 来源 1 标题 - URL 或引用\n   - [2] 来源 2 标题 - URL 或引用\n   - [3] 来源 3 标题 - URL 或引用\n   ```\n\n6. **引用要求**：\n   - 每个数据点、统计信息或比较都必须带有行内引用\n   - 使用编号引用 [1]、[2] 等，或命名引用 [Source Name]\n   - 在文末的参考资料部分链接这些引用\n   - 示例：“研究表明，65% 的开发者更偏好 TypeScript [1]”\n   - 示例：“React 在渲染速度上比 Vue 快 20% [React Benchmarks 2024]”\n\n### 步骤 7：提交草稿（如果在 git 仓库中）\n\n1. 检查是否处于 git 仓库中。\n\n2. 如果是：\n   - 暂存草稿文件\n   - 使用如下提交信息创建 commit：`docs: Add draft v0.1 for blog post - [topic-name]`\n   - 推送到远程仓库\n\n3. 如果不是 git 仓库，则跳过并告知用户。\n\n### 步骤 8：向用户展示草稿以供审阅\n\n1. 向用户展示草稿内容。\n\n2. 询问反馈：\n   - 整体印象如何？\n   - 哪些部分需要扩展或压缩？\n   - 是否需要调整语气？\n   - 是否缺少关键信息？\n   - 有没有具体编辑或重写建议？\n\n3. **等待用户回复。**\n\n### 步骤 9：迭代或定稿\n\n**如果用户要求修改：**\n1. 记录所有修改请求\n2. 返回步骤 6，并做以下调整：\n   - 将版本号递增（v0.2、v0.3 等）\n   - 纳入所有反馈\n   - 保存为 `draft-v[X.Y].md`\n   - 重复步骤 7-8\n\n**如果用户批准：**\n1. 确认最终草稿版本\n2. 如用户要求，可重命名为 `final.md`\n3. 总结博客文章创建过程：\n   - 一共创建了多少个版本\n   - 各版本之间的关键变化\n   - 最终字数\n   - 创建了哪些文件\n\n## 版本跟踪\n\n所有草稿都会以递增版本号保留：\n- `draft-v0.1.md` - 初始草稿\n- `draft-v0.2.md` - 第一轮反馈后\n- `draft-v0.3.md` - 第二轮反馈后\n- 以此类推\n\n这可以跟踪博客文章的演变过程，并在需要时回退。\n\n## 输出文件结构\n\n```text\nblog-posts/\n└── YYYY-MM-DD-topic-name/\n    ├── resources/\n    │   ├── source-1-name.md\n    │   ├── source-2-name.md\n    │   └── ...\n    ├── OUTLINE.md\n    ├── draft-v0.1.md\n    ├── draft-v0.2.md（如果有迭代）\n    └── draft-v0.3.md（如果还有更多迭代）\n```\n\n## 质量建议\n\n- **钩子**：以问题、令人惊讶的事实或贴近读者的场景开头\n- **衔接**：每一段都要自然连接到下一段\n- **证据**：用研究数据支撑观点\n- **引用**：以下内容务必引用来源：\n  - 所有统计数据和数值（例如：“根据 [Source]，75% 的……”）\n  - 对产品、服务或方案的比较（例如：“X 的速度比 Y 快 2 倍 [Source]”）\n  - 关于市场趋势、研究发现或基准测试的事实性陈述\n  - 使用行内引用，格式为：[Source Name] 或 [Author, Year]\n- **语气**：全程保持一致\n- **长度**：尊重目标字数\n- **可读性**：使用短段落，并在适当位置使用项目符号\n- **CTA**：以明确的行动号召或发人深省的问题收尾\n\n## 备注\n\n- 始终在上述需要确认的节点等待用户批准\n- 保留所有草稿版本，方便追踪历史\n- 如果提供了 URL，使用网络搜索获取最新信息\n- 如果资源不足，询问用户补充，或建议进一步研究\n- 根据目标读者调整语气（技术、通用、商业等）\n","frontmatter":{"name":"blog-draft","description":"根据想法和资料撰写博客草稿。适用于用户想写博客、基于研究创建内容，或起草文章的场景。流程会引导你完成调研、头脑风暴、提纲编写和带版本控制的迭代撰写。"},"isInternal":false,"tokens":3082,"sizeBytes":8154},{"name":"SKILL.md","path":"zh/03-skills/brand-voice/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/zh/03-skills/brand-voice/SKILL.md","title":"brand-voice","category":"anthropic-skill","format":"markdown","content":"---\nname: brand-voice\ndescription: 确保所有沟通内容都符合品牌语气和风格指南。适用于撰写营销文案、客户沟通、对外内容，或用户提到品牌语气、tone、写作风格的场景。\nuser-invocable: false\n---\n\n# 品牌语气技能\n\n## 概览\n此技能确保所有沟通内容在品牌语气、风格和信息传达上保持一致。\n\n## 品牌定位\n\n### 使命\n帮助团队用 AI 自动化开发工作流\n\n### 价值观\n- **简洁**：把复杂的事情变简单\n- **可靠**：执行稳健，结果稳定\n- **赋能**：释放人的创造力\n\n### 语气风格\n- **友好但专业** - 平易近人，但不过于随意\n- **清晰简洁** - 避免行话，用通俗方式解释技术概念\n- **自信** - 体现我们知道自己在做什么\n- **有同理心** - 理解用户需求和痛点\n\n## 写作指南\n\n### 应该做的 ✅\n- 对读者使用“你”\n- 使用主动语态：“Claude 会生成报告”，而不是“报告由 Claude 生成”\n- 先讲价值主张\n- 使用具体示例\n- 句子保持在 20 个词以内\n- 使用列表增强清晰度\n- 包含行动号召\n\n### 不应该做的 ❌\n- 不要使用企业黑话\n- 不要居高临下，也不要过度简化\n- 不要使用“我们相信”或“我们认为”\n- 不要全大写，除非为了强调\n- 不要写成大段文字墙\n- 不要默认读者具备技术背景\n\n## 词汇\n\n### ✅ 推荐用词\n- Claude（不要写“the Claude AI”）\n- 代码生成（不要写“auto-coding”）\n- Agent（不要写“bot”）\n- 简化流程（不要写“革命性改变”）\n- 集成（不要写“synergize”）\n\n### ❌ 避免用词\n- “cutting-edge”（过度使用）\n- “game-changer”（过于空泛）\n- “leverage”（企业黑话）\n- “utilize”（直接用“use”）\n- “paradigm shift”（不够清晰）\n\n## 示例\n\n### ✅ 好示例\n“Claude 能自动化你的代码审查流程。它不再需要你手动检查每个 PR，而是会审查安全性、性能和质量，每周为团队节省数小时。”\n\n为什么好：价值明确、收益具体、行动导向强\n\n### ❌ 坏示例\n“Claude 利用前沿 AI 为软件开发提供全面解决方案。”\n\n为什么不好：太空泛、企业黑话太多、没有具体价值\n","frontmatter":{"name":"brand-voice","description":"确保所有沟通内容都符合品牌语气和风格指南。适用于撰写营销文案、客户沟通、对外内容，或用户提到品牌语气、tone、写作风格的场景。","user-invocable":false},"isInternal":false,"tokens":854,"sizeBytes":2261},{"name":"SKILL.md","path":"zh/03-skills/claude-md/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/zh/03-skills/claude-md/SKILL.md","title":"claude-md","category":"anthropic-skill","format":"markdown","content":"---\nname: claude-md\ndescription: 按最佳实践创建或更新 CLAUDE.md 文件，以便为 AI agent 提供最优的项目入门上下文\n---\n\n## 用户输入\n\n```text\n$ARGUMENTS\n```\n\n在继续之前，你**必须**先考虑用户输入（如果不为空）。用户可能会指定：\n- `create` - 从零创建新的 CLAUDE.md\n- `update` - 改进已有的 CLAUDE.md\n- `audit` - 分析并报告当前 CLAUDE.md 的质量\n- 一个具体路径，用于创建或更新（例如 `src/api/CLAUDE.md` 代表目录级说明）\n\n## 核心原则\n\n**LLM 是无状态的**：CLAUDE.md 是每次对话都会加载的主要项目文件（与自动记忆和未限定作用域的 rules 一起加载）。它是让 AI agent 了解代码库的主要入门文档。\n\n### 黄金法则\n\n1. **少即是多**：前沿 LLM 大约能遵循 150-200 条指令。Claude Code 的系统提示词本身已经占了大约 50 条，因此 CLAUDE.md 必须聚焦且简洁。\n\n2. **只放通用信息**：只包含每次会话都适用的内容。任务特定的说明应该放在单独文件里。\n\n3. **不要把 Claude 当成 lint 工具**：风格指南会膨胀上下文并降低指令遵循效果。应改用确定性工具（如 prettier、eslint 等）。\n\n4. **绝不自动生成**：CLAUDE.md 是 AI harness 中杠杆最高的位置。应该经过认真思考后手工编写。\n\n## 执行流程\n\n### 1. 项目分析\n\n首先分析当前项目状态：\n\n1. 检查是否存在已有的 CLAUDE.md 文件：\n   - 根目录：`./CLAUDE.md` 或 `.claude/CLAUDE.md`\n   - 目录级：`**/CLAUDE.md`\n   - 全局用户配置：`~/.claude/CLAUDE.md`\n\n2. 识别项目结构：\n   - 技术栈（语言、框架）\n   - 项目类型（monorepo、单体应用、库）\n   - 开发工具（包管理器、构建系统、测试运行器）\n\n3. 查看已有文档：\n   - README.md\n   - CONTRIBUTING.md\n   - package.json、pyproject.toml、Cargo.toml 等\n\n### 2. 内容策略（WHAT, WHY, HOW）\n\n围绕三个维度组织 CLAUDE.md：\n\n#### WHAT - 技术与结构\n- 技术栈概览\n- 项目组织方式（对 monorepo 尤其重要）\n- 关键目录及其用途\n\n#### WHY - 目的与背景\n- 项目是做什么的\n- 为什么做出这些架构决策\n- 每个主要组件负责什么\n\n#### HOW - 工作流与约定\n- 开发流程（bun vs node、pip vs uv 等）\n- 测试流程和命令\n- 验证与构建方法\n- 关键“坑点”或非显而易见的要求\n\n### 3. 渐进式披露策略\n\n对于较大的项目，建议创建 `agent_docs/` 文件夹：\n\n```text\nagent_docs/\n  |- building_the_project.md\n  |- running_tests.md\n  |- code_conventions.md\n  |- architecture_decisions.md\n```\n\n在 CLAUDE.md 中引用这些文件，并写明：\n```markdown\n关于详细的构建说明，请参考 `agent_docs/building_the_project.md`\n```\n\n**重要**：使用 `file:line` 引用，而不是代码片段，以避免上下文过时。\n\n### 4. 质量约束\n\n创建或更新 CLAUDE.md 时：\n\n1. **目标长度**：少于 200 行\n2. **不要写风格规则**：移除任何 lint/format 相关说明\n3. **不要写任务特定说明**：移到单独文件中\n4. **不要写代码片段**：改用文件引用\n5. **不要重复信息**：不要重复 package.json 或 README 中已有内容\n\n### 5. 必备章节\n\n一个结构良好的 CLAUDE.md 应包含：\n\n```markdown\n# 项目名称\n\n一句简短的项目描述。\n\n## 技术栈\n- 主语言和版本\n- 关键框架/库\n- 数据库/存储（如有）\n\n## 项目结构\n[仅适用于 monorepo 或复杂结构]\n- `apps/` - 应用入口\n- `packages/` - 共享库\n\n## 开发命令\n- 安装：`command`\n- 测试：`command`\n- 构建：`command`\n\n## 关键约定\n[只保留非显而易见、高影响的约定]\n- 约定 1，简要说明\n- 约定 2，简要说明\n\n## 已知问题 / 坑点\n[经常让开发者踩坑的内容]\n- 问题 1\n- 问题 2\n```\n\n### 6. 需要避免的反模式\n\n**不要包含：**\n- 代码风格指南（交给 lint 工具）\n- 如何使用 Claude 的说明\n- 对显而易见模式的冗长解释\n- 复制粘贴的代码示例\n- 泛泛而谈的最佳实践（例如“写干净的代码”）\n- 特定任务的说明\n- 自动生成内容\n- 大量 TODO 列表\n\n### 7. 验证清单\n\n在最终确定前，检查：\n\n- [ ] 少于 200 行\n- [ ] 每一行都适用于所有会话\n- [ ] 没有风格/格式规则\n- [ ] 没有代码片段（使用文件引用）\n- [ ] 命令已经验证可用\n- [ ] 对复杂项目使用了渐进式披露\n- [ ] 已记录关键坑点\n- [ ] 没有与 README.md 重复\n\n## 输出格式\n\n### 对于 `create` 或默认模式：\n\n1. 分析项目\n2. 按上述结构起草 CLAUDE.md\n3. 向用户展示草稿以供审阅\n4. 在获得批准后写入相应位置\n\n### 对于 `update`：\n\n1. 读取现有 CLAUDE.md\n2. 按最佳实践进行审计\n3. 识别：\n   - 需要删除的内容（风格规则、代码片段、任务特定内容）\n   - 需要压缩的内容\n   - 缺失的重要信息\n4. 向用户展示修改建议\n5. 在获得批准后应用修改\n\n### 对于 `audit`：\n\n1. 读取现有 CLAUDE.md\n2. 生成报告，包括：\n   - 当前行数与目标的对比\n   - 可通用于所有会话内容的百分比\n   - 发现的反模式列表\n   - 改进建议\n3. 不要修改文件，只做报告\n\n## AGENTS.md 处理\n\n如果用户请求创建或更新 AGENTS.md：\n\n**从 v2.1.277 起，Claude Code 会直接把 `AGENTS.md` 作为项目指令读取。** 但前提是工作目录以及它上面的每一级目录都没有 `CLAUDE.md`、`.claude/CLAUDE.md` 或 `CLAUDE.local.md`。`~/.claude/CLAUDE.md`、受管理的 CLAUDE.md 和 `.claude/rules/` 不计入这项检查，它们仍会一并加载。该行为由 `/config` 中的 **Project instructions** 控制：`claude-md-or-agents-md`（默认）、`claude-md-and-agents-md`、`claude-md`、`managed-only`。在无法直接读取的环境中 — v2.1.277 之前的版本（在 Bedrock/Vertex/Foundry、LLM 网关或关闭遥测的情况下为 v2.1.281 之前），或升级后的第一个会话 — 退回到在 CLAUDE.md 中用 `@AGENTS.md` 导入，或者把 `CLAUDE.md` 软链接到它。\n\nAGENTS.md 是一个跨工具的项目上下文文件 — 和 CLAUDE.md 属于同一*类*文档，而不是 agent 定义格式。它的存在是为了让多个编码 agent 共用同一套项目约定：\n- 构建、测试和 lint 命令\n- 代码风格与架构约定\n- 仓库结构以及各部分所在位置\n\nSubagents 是单独定义的，放在 `.claude/agents/*.md` 里 — 不在 AGENTS.md 中。\n\n同样适用以下原则：\n- 保持聚焦和简洁\n- 使用渐进式披露\n- 用外部文档引用代替内联内容\n\n## 备注\n\n- 在写入前始终验证命令是否可用\n- 不确定时就不要写，少即是多\n- 系统提醒会告诉 Claude，CLAUDE.md “可能相关，也可能不相关” - 噪音越多，越容易被忽略\n- monorepo 最需要清晰的 WHAT/WHY/HOW 结构\n- 目录级 CLAUDE.md 应该更聚焦\n\n---\n\n**最后更新**: 2026 年 10 月 18 日\n**Claude Code 版本**: 2.1.302\n**来源**:\n- https://code.claude.com/docs/en/memory\n","frontmatter":{"name":"claude-md","description":"按最佳实践创建或更新 CLAUDE.md 文件，以便为 AI agent 提供最优的项目入门上下文"},"isInternal":false,"tokens":2610,"sizeBytes":7037},{"name":"SKILL.md","path":"zh/03-skills/code-review-specialist/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/zh/03-skills/code-review-specialist/SKILL.md","title":"code-review-specialist","category":"anthropic-skill","format":"markdown","content":"---\nname: code-review-specialist\ndescription: 提供全面的代码审查能力，覆盖安全、性能和代码质量分析。适用于用户请求代码审查、代码质量评估、Pull Request 审查，或提到安全分析和性能优化时。\n---\n\n# 代码审查 Skill\n\n这个 skill 提供全面的代码审查能力，重点关注：\n\n1. **安全分析**\n   - 身份验证 / 授权问题\n   - 数据泄露风险\n   - 注入漏洞\n   - 密码学弱点\n   - 敏感数据日志记录\n\n2. **性能审查**\n   - 算法效率（Big O 分析）\n   - 内存优化\n   - 数据库查询优化\n   - 缓存机会\n   - 并发问题\n\n3. **代码质量**\n   - SOLID 原则\n   - 设计模式\n   - 命名规范\n   - 文档\n   - 测试覆盖率\n\n4. **可维护性**\n   - 代码可读性\n   - 函数长度（建议少于 50 行）\n   - 圈复杂度\n   - 依赖管理\n   - 类型安全\n\n## 审查模板\n\n对每一段被审查的代码，请提供：\n\n### 摘要\n- 整体质量评分（1-5）\n- 关键发现数量\n- 建议优先关注的区域\n\n### 关键问题（如有）\n- **问题**：清晰描述\n- **位置**：文件和行号\n- **影响**：为什么这很重要\n- **严重性**：Critical / High / Medium\n- **修复**：代码示例\n\n### 按类别列出发现\n\n#### 安全性（如有问题）\n列出安全漏洞及示例\n\n#### 性能（如有问题）\n列出性能问题，并说明复杂度\n\n#### 质量（如有问题）\n列出代码质量问题，并给出重构建议\n\n#### 可维护性（如有问题）\n列出可维护性问题，并给出改进建议\n\n## 版本历史\n\n- v1.0.0 (2024-12-10)：首次发布，包含安全、性能、质量和可维护性分析\n","frontmatter":{"name":"code-review-specialist","description":"提供全面的代码审查能力，覆盖安全、性能和代码质量分析。适用于用户请求代码审查、代码质量评估、Pull Request 审查，或提到安全分析和性能优化时。"},"isInternal":false,"tokens":613,"sizeBytes":1662},{"name":"SKILL.md","path":"zh/03-skills/doc-generator/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/zh/03-skills/doc-generator/SKILL.md","title":"doc-generator","category":"anthropic-skill","format":"markdown","content":"---\nname: doc-generator\ndescription: 从源代码生成全面且准确的 API 文档。适用于创建或更新 API 文档、生成 OpenAPI 规范，或在用户提到 API 文档、端点或说明时使用。\n---\n\n# API 文档生成 Skill\n\n## 可生成内容\n\n- OpenAPI / Swagger 规范\n- API 端点文档\n- SDK 使用示例\n- 集成指南\n- 错误码参考\n- 认证指南\n\n## 文档结构\n\n### 每个端点的写法\n\n````markdown\n## GET /api/v1/users/:id\n\n### 描述\n简要说明这个端点做什么\n\n### 参数\n\n| 名称 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n| id | string | 是 | 用户 ID |\n\n### 响应\n\n**200 成功**\n```json\n{\n  \"id\": \"usr_123\",\n  \"name\": \"John Doe\",\n  \"email\": \"john@example.com\",\n  \"created_at\": \"2025-01-15T10:30:00Z\"\n}\n```\n\n**404 未找到**\n```json\n{\n  \"error\": \"USER_NOT_FOUND\",\n  \"message\": \"User does not exist\"\n}\n```\n\n### 示例\n\n**cURL**\n```bash\ncurl -X GET \"https://api.example.com/api/v1/users/usr_123\" \\\n  -H \"Authorization: Bearer YOUR_TOKEN\"\n```\n\n**JavaScript**\n```javascript\nconst user = await fetch('/api/v1/users/usr_123', {\n  headers: { 'Authorization': 'Bearer token' }\n}).then(r => r.json());\n```\n\n**Python**\n```python\nresponse = requests.get(\n    'https://api.example.com/api/v1/users/usr_123',\n    headers={'Authorization': 'Bearer token'}\n)\nuser = response.json()\n```\n````\n","frontmatter":{"name":"doc-generator","description":"从源代码生成全面且准确的 API 文档。适用于创建或更新 API 文档、生成 OpenAPI 规范，或在用户提到 API 文档、端点或说明时使用。"},"isInternal":false,"tokens":437,"sizeBytes":1342},{"name":"code-smells.md","path":"zh/03-skills/refactor/references/code-smells.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/zh/03-skills/refactor/references/code-smells.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# 代码异味目录\n\n这是基于 Martin Fowler《Refactoring》（第 2 版）的代码异味参考目录。代码异味是更深层问题的表面症状，它们说明代码设计可能出了问题。\n\n> “代码异味通常是系统中更深层问题的表面信号。” — Martin Fowler\n\n---\n\n## 过度膨胀类异味\n\n表示对象或函数已经大到不再好用。\n\n### 长函数\n\n**迹象：**\n- 函数超过 30-50 行\n- 需要滚动才能看完整个函数\n- 嵌套层级很多\n- 需要注释来解释局部逻辑\n\n**为什么不好：**\n- 难理解\n- 难单独测试\n- 改动容易波及其他逻辑\n- 重复逻辑容易藏在里面\n\n**可用重构：**\n- Extract Method\n- Replace Temp with Query\n- Introduce Parameter Object\n- Replace Method with Method Object\n- Decompose Conditional\n\n**示例（重构前）：**\n```javascript\nfunction processOrder(order) {\n  // Validate order (20 lines)\n  if (!order.items) throw new Error('No items');\n  if (order.items.length === 0) throw new Error('Empty order');\n  // ... more validation\n\n  // Calculate totals (30 lines)\n  let subtotal = 0;\n  for (const item of order.items) {\n    subtotal += item.price * item.quantity;\n  }\n  // ... tax, shipping, discounts\n\n  // Send notifications (20 lines)\n  // ... email logic\n}\n```\n\n**示例（重构后）：**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const totals = calculateOrderTotals(order);\n  sendOrderNotifications(order, totals);\n  return { order, totals };\n}\n```\n\n---\n\n### 大类\n\n**迹象：**\n- 实例变量很多（>7-10）\n- 方法很多（>15-20）\n- 类名含糊（Manager、Handler、Processor）\n- 方法没有用到全部字段\n\n**为什么不好：**\n- 违反单一职责原则\n- 难测试\n- 改动会波及无关功能\n- 难以复用局部能力\n\n**可用重构：**\n- Extract Class\n- Extract Subclass\n- Extract Interface\n\n**检测参考：**\n```text\n代码行数 > 300\n方法数量 > 15\n字段数量 > 10\n```\n\n---\n\n### 基础类型沉迷\n\n**迹象：**\n- 用基础类型表达领域概念（用 string 表示邮箱、用 int 表示金额）\n- 使用基础类型数组，而不是对象\n- 用字符串常量表示类型码\n- 大量 magic number / magic string\n\n**为什么不好：**\n- 类型层面没有验证\n- 逻辑散落在整个代码库里\n- 容易传错值\n- 缺少领域对象\n\n**可用重构：**\n- Replace Primitive with Object\n- Replace Type Code with Class\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**示例（重构前）：**\n```javascript\nconst user = {\n  email: 'john@example.com',     // 只是字符串\n  phone: '1234567890',           // 只是字符串\n  status: 'active',              // 魔法字符串\n  balance: 10050                 // 以分为单位的整数\n};\n```\n\n**示例（重构后）：**\n```javascript\nconst user = {\n  email: new Email('john@example.com'),\n  phone: new PhoneNumber('1234567890'),\n  status: UserStatus.ACTIVE,\n  balance: Money.cents(10050)\n};\n```\n\n---\n\n### 长参数列表\n\n**迹象：**\n- 方法参数超过 4 个\n- 一些参数总是一起出现\n- 布尔参数改变方法行为\n- 经常传 null / undefined\n\n**为什么不好：**\n- 难正确调用\n- 参数顺序容易搞混\n- 暗示方法做了太多事\n- 难以增加新参数\n\n**可用重构：**\n- Introduce Parameter Object\n- Preserve Whole Object\n- Replace Parameter with Method Call\n- Remove Flag Argument\n\n**示例（重构前）：**\n```javascript\nfunction createUser(firstName, lastName, email, phone,\n                    street, city, state, zip,\n                    isAdmin, isActive, createdBy) {\n  // ...\n}\n```\n\n**示例（重构后）：**\n```javascript\nfunction createUser(personalInfo, address, options) {\n  // personalInfo: { firstName, lastName, email, phone }\n  // address: { street, city, state, zip }\n  // options: { isAdmin, isActive, createdBy }\n}\n```\n\n---\n\n### 数据泥团\n\n**迹象：**\n- 同样的 3 个以上字段反复一起出现\n- 参数总是成对或成组传递\n- 类中的字段子集总是一起使用\n\n**为什么不好：**\n- 逻辑重复\n- 缺少抽象\n- 难扩展\n- 暗示隐藏的类应该存在\n\n**可用重构：**\n- Extract Class\n- Introduce Parameter Object\n- Preserve Whole Object\n\n**示例：**\n```javascript\n// 数据泥团：坐标 (x, y, z)\nfunction movePoint(x, y, z, dx, dy, dz) { }\nfunction scalePoint(x, y, z, factor) { }\nfunction distanceBetween(x1, y1, z1, x2, y2, z2) { }\n\n// 提取 Point3D 类\nclass Point3D {\n  constructor(x, y, z) { }\n  move(delta) { }\n  scale(factor) { }\n  distanceTo(other) { }\n}\n```\n\n---\n\n## 面向对象滥用类异味\n\n表示 OOP 原则没有被正确使用。\n\n### switch 语句\n\n**迹象：**\n- 长 switch/case 或 if/else 链\n- 多处出现相同 switch\n- 按类型码分支\n- 新增 case 时需要改很多地方\n\n**为什么不好：**\n- 违反开放 / 封闭原则\n- 改动会扩散到所有 switch 位置\n- 难扩展\n- 往往说明缺少多态\n\n**可用重构：**\n- Replace Conditional with Polymorphism\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**示例（重构前）：**\n```javascript\nfunction calculatePay(employee) {\n  switch (employee.type) {\n    case 'hourly':\n      return employee.hours * employee.rate;\n    case 'salaried':\n      return employee.salary / 12;\n    case 'commissioned':\n      return employee.sales * employee.commission;\n  }\n}\n```\n\n**示例（重构后）：**\n```javascript\nclass HourlyEmployee {\n  calculatePay() {\n    return this.hours * this.rate;\n  }\n}\n\nclass SalariedEmployee {\n  calculatePay() {\n    return this.salary / 12;\n  }\n}\n```\n\n---\n\n### 临时字段\n\n**迹象：**\n- 实例变量只在部分方法中使用\n- 字段只在某些条件下设置\n- 某些情况初始化过程很复杂\n\n**为什么不好：**\n- 容易混淆：字段存在但可能为 null\n- 对象状态难理解\n- 说明条件逻辑被隐藏了\n\n**可用重构：**\n- Extract Class\n- Introduce Null Object\n- Replace Temp Field with Local\n\n---\n\n### 拒绝遗赠\n\n**迹象：**\n- 子类没有用到继承来的方法 / 数据\n- 子类重写方法只是为了不做事\n- 继承被当成代码复用，而不是真正的 IS-A\n\n**为什么不好：**\n- 抽象不对\n- 违反里氏替换原则\n- 继承层次误导人\n\n**可用重构：**\n- Push Down Method / Field\n- Replace Subclass with Delegate\n- Replace Inheritance with Delegation\n\n---\n\n### 不同接口的相似类\n\n**迹象：**\n- 两个类做的事情差不多\n- 同一个概念却用了不同方法名\n- 理论上可以互换使用\n\n**为什么不好：**\n- 重复实现\n- 没有公共接口\n- 难切换\n\n**可用重构：**\n- Rename Method\n- Move Method\n- Extract Superclass\n- Extract Interface\n\n---\n\n## 变更阻碍类异味\n\n这类异味会让改动变得困难，一次改动需要波及很多地方。\n\n### 发散式变化\n\n**迹象：**\n- 一个类因为很多不同原因而被修改\n- 不同区域的变更都会触发同一个类的编辑\n- 类变成了“上帝类”\n\n**为什么不好：**\n- 违反单一职责原则\n- 变更频率高\n- 容易产生合并冲突\n\n**可用重构：**\n- Extract Class\n- Extract Superclass\n- Extract Subclass\n\n**示例：**\n一个 `User` 类同时因为这些原因变化：\n- 身份验证变化\n- 个人资料变化\n- 计费变化\n- 通知变化\n\n→ 可以拆成：`AuthService`、`ProfileService`、`BillingService`、`NotificationService`\n\n---\n\n### 散弹式修改\n\n**迹象：**\n- 一个改动需要编辑很多类\n- 一个小功能要触碰 10+ 个文件\n- 改动分散，难以一次找全\n\n**为什么不好：**\n- 很容易漏改\n- 耦合高\n- 容易出错\n\n**可用重构：**\n- Move Method\n- Move Field\n- Inline Class\n\n**检测参考：**\n如果新增一个字段需要改 5 个以上文件，就要警惕。\n\n---\n\n### 平行继承体系\n\n**迹象：**\n- 在一个继承体系中创建子类，另一个体系也得跟着创建\n- 类前缀相似（如 `DatabaseOrder`、`DatabaseProduct`）\n\n**为什么不好：**\n- 维护成本翻倍\n- 两个层次之间耦合\n- 容易漏掉一边\n\n**可用重构：**\n- Move Method\n- Move Field\n- 消除其中一个层次\n\n---\n\n## 可舍弃类异味\n\n表示有些东西已经不必要了，应该移除。\n\n### 注释过多\n\n**迹象：**\n- 注释在解释代码“做了什么”\n- 注释掉的代码\n- 长期存在的 TODO / FIXME\n- 注释里带道歉语气\n\n**为什么不好：**\n- 注释会过时\n- 代码本身应该能自解释\n- 死代码会造成混乱\n\n**可用重构：**\n- Extract Method（让方法名解释意图）\n- Rename（通过命名提升清晰度）\n- 删除注释掉的代码\n- Introduce Assertion\n\n**好与坏的注释：**\n```javascript\n// BAD: 解释做了什么\n// 遍历用户并检查是否活跃\nfor (const user of users) {\n  if (user.status === 'active') { }\n}\n\n// GOOD: 解释为什么\n// 只保留活跃用户，未活跃用户由清理任务处理\nconst activeUsers = users.filter(u => u.isActive);\n```\n\n---\n\n### 重复代码\n\n**迹象：**\n- 多处出现相同代码\n- 只有少量差异的相似代码\n- 复制粘贴模式\n\n**为什么不好：**\n- 修复要改多处\n- 容易不一致\n- 代码库臃肿\n\n**可用重构：**\n- Extract Method\n- Extract Class\n- Pull Up Method（在继承层次中）\n- Form Template Method\n\n**检测规则：**\n任何重复 3 次以上的代码都应该考虑提取。\n\n---\n\n### 惰性类\n\n**迹象：**\n- 类做的事情不足以支撑它的存在\n- 只是一个没有增值的包装器\n- 过度设计的产物\n\n**为什么不好：**\n- 增加维护开销\n- 多了一层没必要的间接\n- 有复杂度但没收益\n\n**可用重构：**\n- Inline Class\n- Collapse Hierarchy\n\n---\n\n### 死代码\n\n**迹象：**\n- 无法到达的代码\n- 未使用的变量 / 方法 / 类\n- 注释掉的代码\n- 位于不可能条件分支后的代码\n\n**为什么不好：**\n- 造成困惑\n- 增加维护负担\n- 降低理解速度\n\n**可用重构：**\n- Remove Dead Code\n- Safe Delete\n\n**检测：**\n```bash\n# 查找未使用的导出\n# 查找未引用的函数\n# IDE 的“unused”警告\n```\n\n---\n\n### 臆想泛化\n\n**迹象：**\n- 只有一个子类的抽象类\n- 为“未来可能需要”而加的未使用参数\n- 只是转发的函数\n- 为一个用例设计的“框架”\n\n**为什么不好：**\n- 复杂度没有收益\n- 违背 YAGNI\n- 更难理解\n\n**可用重构：**\n- Collapse Hierarchy\n- Inline Class\n- Remove Parameter\n- Rename Method\n\n---\n\n## 耦合类异味\n\n表示类之间耦合过强。\n\n### Feature Envy\n\n**迹象：**\n- 一个方法使用别的类的数据比自己更多\n- 对另一个对象调用很多 getter\n- 数据和行为分离\n\n**为什么不好：**\n- 行为放错地方了\n- 封装性差\n- 难维护\n\n**可用重构：**\n- Move Method\n- Move Field\n- Extract Method（然后移动）\n\n**示例（重构前）：**\n```javascript\nclass Order {\n  getDiscountedPrice(customer) {\n    // 这里大量使用 customer 数据\n    if (customer.loyaltyYears > 5) {\n      return this.price * customer.discountRate;\n    }\n    return this.price;\n  }\n}\n```\n\n**示例（重构后）：**\n```javascript\nclass Customer {\n  getDiscountedPriceFor(price) {\n    if (this.loyaltyYears > 5) {\n      return price * this.discountRate;\n    }\n    return price;\n  }\n}\n```\n\n---\n\n### 不恰当的亲密\n\n**迹象：**\n- 类之间互相访问私有细节\n- 双向引用很多\n- 子类知道父类太多细节\n\n**为什么不好：**\n- 耦合高\n- 改一边会连带另一边\n- 难单独修改\n\n**可用重构：**\n- Move Method\n- Move Field\n- Change Bidirectional to Unidirectional\n- Extract Class\n- Hide Delegate\n\n---\n\n### 消息链\n\n**迹象：**\n- 方法调用链很长：`a.getB().getC().getD().getValue()`\n- 客户端依赖导航结构\n- “火车残骸”式代码\n\n**为什么不好：**\n- 很脆弱，任何一层变动都会坏\n- 违反迪米特法则\n- 绑定到对象结构\n\n**可用重构：**\n- Hide Delegate\n- Extract Method\n- Move Method\n\n**示例：**\n```javascript\n// 差：消息链\nconst managerName = employee.getDepartment().getManager().getName();\n\n// 更好：隐藏委派\nconst managerName = employee.getManagerName();\n```\n\n---\n\n### 中间人\n\n**迹象：**\n- 类只是把调用转发给另一个类\n- 一半以上的方法都是委派\n- 没有额外价值\n\n**为什么不好：**\n- 多了一层没必要的间接\n- 维护成本更高\n- 架构令人困惑\n\n**可用重构：**\n- Remove Middle Man\n- Inline Method\n\n---\n\n## 严重性指南\n\n| 严重性 | 说明 | 处理方式 |\n|--------|------|---------|\n| **Critical** | 阻塞开发，导致 bug | 立刻修复 |\n| **High** | 明显增加维护负担 | 本迭代修复 |\n| **Medium** | 有问题但还能接受 | 近期计划修复 |\n| **Low** | 小问题 | 视情况顺手修 |\n\n---\n\n## 快速检测清单\n\n扫描代码时使用这个清单：\n\n- [ ] 有没有超过 30 行的函数？\n- [ ] 有没有超过 300 行的类？\n- [ ] 有没有参数超过 4 个的函数？\n- [ ] 有没有重复代码块？\n- [ ] 有没有按类型码分支的 switch/case？\n- [ ] 有没有未使用的代码？\n- [ ] 有没有大量使用其他类数据的方法？\n- [ ] 有没有很长的方法调用链？\n- [ ] 有没有解释“是什么”而不是“为什么”的注释？\n- [ ] 有没有应该封装成对象的基础类型？\n\n---\n\n## 延伸阅读\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Kerievsky, J. (2004). *Refactoring to Patterns*\n- Feathers, M. (2004). *Working Effectively with Legacy Code*\n","isInternal":false,"tokens":4555,"sizeBytes":13432},{"name":"refactoring-catalog.md","path":"zh/03-skills/refactor/references/refactoring-catalog.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/zh/03-skills/refactor/references/refactoring-catalog.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# 重构目录\n\n这是 Martin Fowler《Refactoring》（第 2 版）中的一份精选重构目录。每个重构都包含动机、操作步骤和示例。\n\n> “重构由它的操作步骤来定义，也就是你执行这个变化时遵循的精确过程。” — Martin Fowler\n\n---\n\n## 如何使用这个目录\n\n1. **识别异味**：先用代码异味目录定位问题\n2. **找到对应重构**：在这里查找匹配的手法\n3. **按步骤执行**：一步一步来\n4. **每步都测试**：确保行为不变\n\n**黄金法则**：如果某一步超过 10 分钟，就把它拆得更小。\n\n---\n\n## 最常见的重构\n\n### Extract Method\n\n**何时使用**：长函数、重复代码、需要为概念命名\n\n**动机**：把一段代码抽成一个名字能说明意图的方法。\n\n**步骤**：\n1. 创建一个新方法，名字应描述“做什么”而不是“怎么做”\n2. 把代码片段复制到新方法里\n3. 检查片段里用了哪些局部变量\n4. 把局部变量作为参数传入，或在方法内声明\n5. 正确处理返回值\n6. 用新方法调用替换原始片段\n7. 测试\n\n**前：**\n```javascript\nfunction printOwing(invoice) {\n  let outstanding = 0;\n\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n\n  // Calculate outstanding\n  for (const order of invoice.orders) {\n    outstanding += order.amount;\n  }\n\n  // Print details\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n**后：**\n```javascript\nfunction printOwing(invoice) {\n  printBanner();\n  const outstanding = calculateOutstanding(invoice);\n  printDetails(invoice, outstanding);\n}\n\nfunction printBanner() {\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n}\n\nfunction calculateOutstanding(invoice) {\n  return invoice.orders.reduce((sum, order) => sum + order.amount, 0);\n}\n\nfunction printDetails(invoice, outstanding) {\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n---\n\n### Inline Method\n\n**何时使用**：方法体和名字一样清楚，或者只是多余转发\n\n**动机**：当方法没有额外价值时，去掉不必要的间接层。\n\n**步骤**：\n1. 确认这个方法不是多态方法\n2. 找到所有调用点\n3. 用方法体替换每个调用\n4. 每替换一次就测试一次\n5. 删除方法定义\n\n**前：**\n```javascript\nfunction getRating(driver) {\n  return moreThanFiveLateDeliveries(driver) ? 2 : 1;\n}\n\nfunction moreThanFiveLateDeliveries(driver) {\n  return driver.numberOfLateDeliveries > 5;\n}\n```\n\n**后：**\n```javascript\nfunction getRating(driver) {\n  return driver.numberOfLateDeliveries > 5 ? 2 : 1;\n}\n```\n\n---\n\n### Extract Variable\n\n**何时使用**：复杂表达式难以理解\n\n**动机**：给复杂表达式的一部分起名字。\n\n**步骤**：\n1. 确保表达式没有副作用\n2. 声明一个不可变变量\n3. 将表达式结果赋给变量\n4. 用变量替换原表达式\n5. 测试\n\n**前：**\n```javascript\nreturn order.quantity * order.itemPrice -\n  Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +\n  Math.min(order.quantity * order.itemPrice * 0.1, 100);\n```\n\n**后：**\n```javascript\nconst basePrice = order.quantity * order.itemPrice;\nconst quantityDiscount = Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;\nconst shipping = Math.min(basePrice * 0.1, 100);\nreturn basePrice - quantityDiscount + shipping;\n```\n\n---\n\n### Inline Variable\n\n**何时使用**：变量名没有比表达式更清楚\n\n**动机**：移除没必要的间接层。\n\n**步骤**：\n1. 检查右侧表达式没有副作用\n2. 如果变量不是不可变的，先改成不可变并测试\n3. 找到第一次引用并替换成表达式\n4. 测试\n5. 对所有引用重复\n6. 删除变量声明和赋值\n7. 测试\n\n---\n\n### Rename Variable\n\n**何时使用**：名字没有清楚表达用途\n\n**动机**：好名字是清晰代码的基础。\n\n**步骤**：\n1. 如果变量使用范围很广，先考虑封装\n2. 找到所有引用\n3. 逐个修改引用\n4. 测试\n\n**提示**：\n- 使用能体现意图的名字\n- 避免缩写\n- 使用领域术语\n\n```javascript\n// Bad\nconst d = 30;\nconst x = users.filter(u => u.a);\n\n// Good\nconst daysSinceLastLogin = 30;\nconst activeUsers = users.filter(user => user.isActive);\n```\n\n---\n\n### Change Function Declaration\n\n**何时使用**：函数名不能清楚说明用途，参数也需要变化\n\n**动机**：好函数名能让代码自解释。\n\n**步骤（简单情况）**：\n1. 删除不需要的参数\n2. 修改函数名\n3. 添加需要的参数\n4. 测试\n\n**步骤（迁移式，适用于复杂改动）**：\n1. 如果要删除参数，确保它没有被使用\n2. 创建一个新函数，声明符合新设计\n3. 让旧函数调用新函数\n4. 测试\n5. 让调用方逐步改用新函数\n6. 每改一个调用点就测试\n7. 删除旧函数\n\n**前：**\n```javascript\nfunction circum(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n**后：**\n```javascript\nfunction circumference(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n---\n\n### Encapsulate Variable\n\n**何时使用**：多个地方直接访问某个数据\n\n**动机**：为数据访问提供明确入口。\n\n**步骤**：\n1. 创建 getter 和 setter\n2. 找到所有引用\n3. 用 getter 替换读取\n4. 用 setter 替换写入\n5. 每次改动后测试\n6. 降低变量可见性\n\n**前：**\n```javascript\nlet defaultOwner = { firstName: \"Martin\", lastName: \"Fowler\" };\n\n// Used in many places\nspaceship.owner = defaultOwner;\n```\n\n**后：**\n```javascript\nlet defaultOwnerData = { firstName: \"Martin\", lastName: \"Fowler\" };\n\nfunction defaultOwner() { return defaultOwnerData; }\nfunction setDefaultOwner(arg) { defaultOwnerData = arg; }\n\nspaceship.owner = defaultOwner();\n```\n\n---\n\n### Introduce Parameter Object\n\n**何时使用**：一组参数经常一起出现\n\n**动机**：把自然属于一起的数据打包起来。\n\n**步骤**：\n1. 为这组参数创建一个新类 / 结构\n2. 测试\n3. 用 Change Function Declaration 引入新对象\n4. 测试\n5. 逐个移除参数，改用对象字段\n6. 每次移除后测试\n\n**前：**\n```javascript\nfunction amountInvoiced(startDate, endDate) { ... }\nfunction amountReceived(startDate, endDate) { ... }\nfunction amountOverdue(startDate, endDate) { ... }\n```\n\n**后：**\n```javascript\nclass DateRange {\n  constructor(start, end) {\n    this.start = start;\n    this.end = end;\n  }\n}\n\nfunction amountInvoiced(dateRange) { ... }\nfunction amountReceived(dateRange) { ... }\nfunction amountOverdue(dateRange) { ... }\n```\n\n---\n\n### Combine Functions into Class\n\n**何时使用**：多个函数操作同一份数据\n\n**动机**：把函数和它操作的数据放到一起。\n\n**步骤**：\n1. 对公共数据先做 Encapsulate Record\n2. 把每个函数移动到类里\n3. 每移动一次就测试\n4. 用类字段替代数据参数\n\n**前：**\n```javascript\nfunction base(reading) { ... }\nfunction taxableCharge(reading) { ... }\nfunction calculateBaseCharge(reading) { ... }\n```\n\n**后：**\n```javascript\nclass Reading {\n  constructor(data) { this._data = data; }\n\n  get base() { ... }\n  get taxableCharge() { ... }\n  get calculateBaseCharge() { ... }\n}\n```\n\n---\n\n### Split Phase\n\n**何时使用**：代码在处理两件不同的事\n\n**动机**：把代码拆成边界清晰的两个阶段。\n\n**步骤**：\n1. 为第二阶段创建新函数\n2. 测试\n3. 在两个阶段之间引入中间数据结构\n4. 测试\n5. 把第一阶段提取成独立函数\n6. 测试\n\n**前：**\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  const shippingPerCase = (basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = quantity * shippingPerCase;\n  return basePrice - discount + shippingCost;\n}\n```\n\n**后：**\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const priceData = calculatePricingData(product, quantity);\n  return applyShipping(priceData, shippingMethod);\n}\n\nfunction calculatePricingData(product, quantity) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  return { basePrice, quantity, discount };\n}\n\nfunction applyShipping(priceData, shippingMethod) {\n  const shippingPerCase = (priceData.basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = priceData.quantity * shippingPerCase;\n  return priceData.basePrice - priceData.discount + shippingCost;\n}\n```\n\n---\n\n## 移动特性\n\n### Move Method\n\n**何时使用**：方法更依赖另一个类的数据而不是自己类的数据\n\n**动机**：把函数放到它最依赖的数据所在的类里。\n\n**步骤**：\n1. 检查方法使用到的所有程序元素\n2. 确认方法不是多态的\n3. 把方法复制到目标类\n4. 调整上下文\n5. 让原方法委托给目标方法\n6. 测试\n7. 视情况删除原方法\n\n---\n\n### Move Field\n\n**何时使用**：字段更多被另一个类使用\n\n**动机**：让数据和使用它的函数靠在一起。\n\n**步骤**：\n1. 如果还没有，先封装字段\n2. 测试\n3. 在目标类中创建字段\n4. 把引用改成使用目标字段\n5. 测试\n6. 删除原字段\n\n---\n\n### Move Statements into Function\n\n**何时使用**：相同代码总是跟着函数调用一起出现\n\n**动机**：把重复语句移入函数，去掉重复。\n\n**步骤**：\n1. 如果还没有，先把重复代码提取成函数\n2. 把语句移入函数\n3. 测试\n4. 如果调用方不再需要独立语句，就删除它们\n\n---\n\n### Move Statements to Callers\n\n**何时使用**：不同调用方需要不同的行为\n\n**动机**：当行为需要差异化时，把它从函数里移出去。\n\n**步骤**：\n1. 先对要移动的代码做 Extract Method\n2. 再对原函数做 Inline Method\n3. 删除被内联后的调用\n4. 把提取出的代码移到各个调用方\n5. 测试\n\n---\n\n## 数据组织\n\n### Replace Primitive with Object\n\n**何时使用**：数据项需要的不只是简单值\n\n**动机**：把数据和行为封装在一起。\n\n**步骤**：\n1. 先做 Encapsulate Variable\n2. 创建一个简单值对象\n3. 修改 setter，让它创建新实例\n4. 修改 getter，让它返回值\n5. 测试\n6. 给新类增加更丰富的行为\n\n**前：**\n```javascript\nclass Order {\n  constructor(data) {\n    this.priority = data.priority; // string: \"high\", \"rush\", etc.\n  }\n}\n\n// Usage\nif (order.priority === \"high\" || order.priority === \"rush\") { ... }\n```\n\n**后：**\n```javascript\nclass Priority {\n  constructor(value) {\n    if (!Priority.legalValues().includes(value))\n      throw new Error(`Invalid priority: ${value}`);\n    this._value = value;\n  }\n\n  static legalValues() { return ['low', 'normal', 'high', 'rush']; }\n  get value() { return this._value; }\n\n  higherThan(other) {\n    return Priority.legalValues().indexOf(this._value) >\n           Priority.legalValues().indexOf(other._value);\n  }\n}\n\n// Usage\nif (order.priority.higherThan(new Priority(\"normal\"))) { ... }\n```\n\n---\n\n### Replace Temp with Query\n\n**何时使用**：临时变量保存的是一个表达式结果\n\n**动机**：把表达式提取成函数，让代码更清晰。\n\n**步骤**：\n1. 确保变量只被赋值一次\n2. 把赋值右侧提取成一个方法\n3. 用方法调用替换临时变量引用\n4. 测试\n5. 删除临时变量声明和赋值\n\n**前：**\n```javascript\nconst basePrice = this._quantity * this._itemPrice;\nif (basePrice > 1000) {\n  return basePrice * 0.95;\n} else {\n  return basePrice * 0.98;\n}\n```\n\n**后：**\n```javascript\nget basePrice() {\n  return this._quantity * this._itemPrice;\n}\n\n// In the method\nif (this.basePrice > 1000) {\n  return this.basePrice * 0.95;\n} else {\n  return this.basePrice * 0.98;\n}\n```\n\n---\n\n## 简化条件逻辑\n\n### Decompose Conditional\n\n**何时使用**：复杂条件语句\n\n**动机**：把条件和分支动作分别提取出来，让意图更清楚。\n\n**步骤**：\n1. 对条件做 Extract Method\n2. 对 then 分支做 Extract Method\n3. 对 else 分支也做 Extract Method（如果有）\n\n**前：**\n```javascript\nif (!aDate.isBefore(plan.summerStart) && !aDate.isAfter(plan.summerEnd)) {\n  charge = quantity * plan.summerRate;\n} else {\n  charge = quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n**后：**\n```javascript\nif (isSummer(aDate, plan)) {\n  charge = summerCharge(quantity, plan);\n} else {\n  charge = regularCharge(quantity, plan);\n}\n\nfunction isSummer(date, plan) {\n  return !date.isBefore(plan.summerStart) && !date.isAfter(plan.summerEnd);\n}\n\nfunction summerCharge(quantity, plan) {\n  return quantity * plan.summerRate;\n}\n\nfunction regularCharge(quantity, plan) {\n  return quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n---\n\n### Consolidate Conditional Expression\n\n**何时使用**：多个条件最后都返回同一个结果\n\n**动机**：让人一眼看出这些条件其实是一道检查。\n\n**步骤**：\n1. 确认条件没有副作用\n2. 用 and / or 合并条件\n3. 视情况对合并后的条件做 Extract Method\n\n**前：**\n```javascript\nif (employee.seniority < 2) return 0;\nif (employee.monthsDisabled > 12) return 0;\nif (employee.isPartTime) return 0;\n```\n\n**后：**\n```javascript\nif (isNotEligibleForDisability(employee)) return 0;\n\nfunction isNotEligibleForDisability(employee) {\n  return employee.seniority < 2 ||\n         employee.monthsDisabled > 12 ||\n         employee.isPartTime;\n}\n```\n\n---\n\n### Replace Nested Conditional with Guard Clauses\n\n**何时使用**：深层嵌套条件让流程难以追踪\n\n**动机**：用 guard clause 提前返回，让正常流程更清楚。\n\n**步骤**：\n1. 找出特殊情况\n2. 用提前返回的 guard clause 替换它们\n3. 每改一步就测试\n\n**前：**\n```javascript\nfunction payAmount(employee) {\n  let result;\n  if (employee.isSeparated) {\n    result = { amount: 0, reasonCode: \"SEP\" };\n  } else {\n    if (employee.isRetired) {\n      result = { amount: 0, reasonCode: \"RET\" };\n    } else {\n      result = calculateNormalPay(employee);\n    }\n  }\n  return result;\n}\n```\n\n**后：**\n```javascript\nfunction payAmount(employee) {\n  if (employee.isSeparated) return { amount: 0, reasonCode: \"SEP\" };\n  if (employee.isRetired) return { amount: 0, reasonCode: \"RET\" };\n  return calculateNormalPay(employee);\n}\n```\n\n---\n\n### Replace Conditional with Polymorphism\n\n**何时使用**：按类型分支的 switch / 条件逻辑\n\n**动机**：让对象自己处理自己的行为。\n\n**步骤**：\n1. 创建类层次（如果还没有）\n2. 用 Factory Function 创建对象\n3. 把条件逻辑移到超类方法里\n4. 给每种情况创建子类方法\n5. 删除原条件\n\n**前：**\n```javascript\nfunction plumages(birds) {\n  return birds.map(b => plumage(b));\n}\n\nfunction plumage(bird) {\n  switch (bird.type) {\n    case 'EuropeanSwallow':\n      return \"average\";\n    case 'AfricanSwallow':\n      return (bird.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n    case 'NorwegianBlueParrot':\n      return (bird.voltage > 100) ? \"scorched\" : \"beautiful\";\n    default:\n      return \"unknown\";\n  }\n}\n```\n\n**后：**\n```javascript\nclass Bird {\n  get plumage() { return \"unknown\"; }\n}\n\nclass EuropeanSwallow extends Bird {\n  get plumage() { return \"average\"; }\n}\n\nclass AfricanSwallow extends Bird {\n  get plumage() {\n    return (this.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n  }\n}\n\nclass NorwegianBlueParrot extends Bird {\n  get plumage() {\n    return (this.voltage > 100) ? \"scorched\" : \"beautiful\";\n  }\n}\n\nfunction createBird(data) {\n  switch (data.type) {\n    case 'EuropeanSwallow': return new EuropeanSwallow(data);\n    case 'AfricanSwallow': return new AfricanSwallow(data);\n    case 'NorwegianBlueParrot': return new NorwegianBlueParrot(data);\n    default: return new Bird(data);\n  }\n}\n```\n\n---\n\n### Introduce Special Case (Null Object)\n\n**何时使用**：重复出现 null 检查\n\n**动机**：返回一个特殊对象来处理特殊情况。\n\n**步骤**：\n1. 创建一个具备预期接口的特殊情况类\n2. 增加 isSpecialCase 检查\n3. 引入工厂方法\n4. 用特殊对象替换 null 检查\n5. 测试\n\n**前：**\n```javascript\nconst customer = site.customer;\n// ... many places checking\nif (customer === \"unknown\") {\n  customerName = \"occupant\";\n} else {\n  customerName = customer.name;\n}\n```\n\n**后：**\n```javascript\nclass UnknownCustomer {\n  get name() { return \"occupant\"; }\n  get billingPlan() { return registry.defaultPlan; }\n}\n\n// Factory method\nfunction customer(site) {\n  return site.customer === \"unknown\"\n    ? new UnknownCustomer()\n    : site.customer;\n}\n\n// Usage - no null checks needed\nconst customerName = customer.name;\n```\n\n---\n\n## 重构 API\n\n### Separate Query from Modifier\n\n**何时使用**：函数既返回值又有副作用\n\n**动机**：明确哪些操作会产生副作用。\n\n**步骤**：\n1. 创建新的查询函数\n2. 复制原函数的返回逻辑\n3. 修改原函数，让它只负责副作用\n4. 替换依赖返回值的调用点\n5. 测试\n\n**前：**\n```javascript\nfunction alertForMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") {\n      setOffAlarms();\n      return \"Don\";\n    }\n    if (p === \"John\") {\n      setOffAlarms();\n      return \"John\";\n    }\n  }\n  return \"\";\n}\n```\n\n**后：**\n```javascript\nfunction findMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") return \"Don\";\n    if (p === \"John\") return \"John\";\n  }\n  return \"\";\n}\n\nfunction alertForMiscreant(people) {\n  if (findMiscreant(people) !== \"\") setOffAlarms();\n}\n```\n\n---\n\n### Parameterize Function\n\n**何时使用**：有多个做类似事情但数值不同的函数\n\n**动机**：通过参数化减少重复。\n\n**步骤**：\n1. 选择一个函数\n2. 为变化的字面值增加参数\n3. 修改函数体使用该参数\n4. 测试\n5. 让调用方改用参数化版本\n6. 删除不再使用的旧函数\n\n**前：**\n```javascript\nfunction tenPercentRaise(person) {\n  person.salary = person.salary * 1.10;\n}\n\nfunction fivePercentRaise(person) {\n  person.salary = person.salary * 1.05;\n}\n```\n\n**后：**\n```javascript\nfunction raise(person, factor) {\n  person.salary = person.salary * (1 + factor);\n}\n\n// Usage\nraise(person, 0.10);\nraise(person, 0.05);\n```\n\n---\n\n### Remove Flag Argument\n\n**何时使用**：布尔参数改变函数行为\n\n**动机**：通过拆分成明确函数，让行为更清楚。\n\n**步骤**：\n1. 针对不同旗标值创建显式函数\n2. 替换每个调用点\n3. 每次改动后测试\n4. 删除原函数\n\n**前：**\n```javascript\nfunction bookConcert(customer, isPremium) {\n  if (isPremium) {\n    // premium booking logic\n  } else {\n    // regular booking logic\n  }\n}\n\nbookConcert(customer, true);\nbookConcert(customer, false);\n```\n\n**后：**\n```javascript\nfunction bookPremiumConcert(customer) {\n  // premium booking logic\n}\n\nfunction bookRegularConcert(customer) {\n  // regular booking logic\n}\n\nbookPremiumConcert(customer);\nbookRegularConcert(customer);\n```\n\n---\n\n## 继承相关\n\n### Pull Up Method\n\n**何时使用**：多个子类里有相同方法\n\n**动机**：去掉类层次中的重复。\n\n**步骤**：\n1. 检查方法是否完全相同\n2. 确认签名一致\n3. 在超类中新建方法\n4. 从一个子类复制实现\n5. 删除一个子类中的方法并测试\n6. 删除其他子类中的方法并测试\n\n---\n\n### Push Down Method\n\n**何时使用**：某个行为只适用于部分子类\n\n**动机**：把方法放到真正使用它的地方。\n\n**步骤**：\n1. 把方法复制到需要它的子类\n2. 从超类删除方法\n3. 测试\n4. 删除不需要该方法的子类副本\n5. 测试\n\n---\n\n### Replace Subclass with Delegate\n\n**何时使用**：继承用得不对，需要更灵活\n\n**动机**：在合适的地方更偏向组合而不是继承。\n\n**步骤**：\n1. 创建一个空的委托类\n2. 在宿主类中加一个持有委托的字段\n3. 在宿主类构造委托\n4. 把功能迁移到委托类\n5. 每次迁移后测试\n6. 用委托替代继承\n\n---\n\n## Extract Class\n\n**何时使用**：大类里有多个职责\n\n**动机**：拆分类以维持单一职责。\n\n**步骤**：\n1. 决定如何拆分职责\n2. 创建新类\n3. 把字段从原类移到新类\n4. 测试\n5. 把方法从原类移到新类\n6. 每次移动后测试\n7. 重新检查并命名两个类\n8. 决定如何暴露新类\n\n**前：**\n```javascript\nclass Person {\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get officeAreaCode() { return this._officeAreaCode; }\n  set officeAreaCode(arg) { this._officeAreaCode = arg; }\n  get officeNumber() { return this._officeNumber; }\n  set officeNumber(arg) { this._officeNumber = arg; }\n\n  get telephoneNumber() {\n    return `(${this._officeAreaCode}) ${this._officeNumber}`;\n  }\n}\n```\n\n**后：**\n```javascript\nclass Person {\n  constructor() {\n    this._telephoneNumber = new TelephoneNumber();\n  }\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get telephoneNumber() { return this._telephoneNumber.toString(); }\n  get officeAreaCode() { return this._telephoneNumber.areaCode; }\n  set officeAreaCode(arg) { this._telephoneNumber.areaCode = arg; }\n}\n\nclass TelephoneNumber {\n  get areaCode() { return this._areaCode; }\n  set areaCode(arg) { this._areaCode = arg; }\n  get number() { return this._number; }\n  set number(arg) { this._number = arg; }\n  toString() { return `(${this._areaCode}) ${this._number}`; }\n}\n```\n\n---\n\n## 快速参考：异味到重构\n\n| 代码异味 | 主要重构 | 备选方案 |\n|----------|---------|---------|\n| 长函数 | Extract Method | Replace Temp with Query |\n| 重复代码 | Extract Method | Pull Up Method |\n| 大类 | Extract Class | Extract Subclass |\n| 长参数列表 | Introduce Parameter Object | Preserve Whole Object |\n| Feature Envy | Move Method | Extract Method + Move |\n| 数据泥团 | Extract Class | Introduce Parameter Object |\n| 基础类型沉迷 | Replace Primitive with Object | Replace Type Code |\n| switch 语句 | Replace Conditional with Polymorphism | Replace Type Code |\n| 临时字段 | Extract Class | Introduce Null Object |\n| 消息链 | Hide Delegate | Extract Method |\n| 中间人 | Remove Middle Man | Inline Method |\n| 发散式变化 | Extract Class | Split Phase |\n| 散弹式修改 | Move Method | Inline Class |\n| 死代码 | Remove Dead Code | - |\n| 臆想泛化 | Collapse Hierarchy | Inline Class |\n\n---\n\n## 延伸阅读\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (第 2 版)\n- 在线目录：https://refactoring.com/catalog/\n","isInternal":false,"tokens":6913,"sizeBytes":22807},{"name":"SKILL.md","path":"zh/03-skills/refactor/SKILL.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/zh/03-skills/refactor/SKILL.md","title":"refactor","category":"anthropic-skill","format":"markdown","content":"---\nname: refactor\ndescription: 基于 Martin Fowler 方法论的系统化代码重构 skill。适用于用户请求重构代码、改进代码结构、减少技术债、清理旧代码、消除 code smell 或提升可维护性时。这个 skill 采用分阶段、带研究与计划的安全增量实施方式。\n---\n\n# 代码重构 Skill\n\n这是一个基于 Martin Fowler《Refactoring: Improving the Design of Existing Code》（第 2 版）的系统化代码重构方法。这个 skill 强调安全、渐进的修改，并由测试提供保障。\n\n> “重构是在不改变软件外部行为的前提下，改进其内部结构的过程。” — Martin Fowler\n\n## 核心原则\n\n1. **保持行为不变**：外部行为必须保持一致\n2. **小步前进**：每次只做很小、可测试的改动\n3. **测试驱动**：测试是安全网\n4. **持续进行**：重构是长期过程，不是一次性任务\n5. **协作确认**：每个阶段都需要用户确认\n\n## 工作流程总览\n\n```\n阶段 1：研究与分析\n    ↓\n阶段 2：测试覆盖评估\n    ↓\n阶段 3：识别代码异味\n    ↓\n阶段 4：创建重构计划\n    ↓\n阶段 5：增量实施\n    ↓\n阶段 6：评审与迭代\n```\n\n---\n\n## 阶段 1：研究与分析\n\n### 目标\n- 理解代码库结构和用途\n- 确定重构范围\n- 收集业务需求背景\n\n### 先向用户确认的问题\n开始前先确认：\n\n1. **范围**：哪些文件 / 模块 / 函数需要重构？\n2. **目标**：你想解决什么问题？（可读性、性能、可维护性）\n3. **约束**：有哪些区域不能改？\n4. **时间压力**：这是否阻塞了其他工作？\n5. **测试状态**：是否已有测试？是否通过？\n\n### 行动\n- [ ] 阅读并理解目标代码\n- [ ] 识别依赖和集成点\n- [ ] 记录当前架构\n- [ ] 标记已有技术债迹象（TODO、FIXME）\n\n### 输出\n向用户汇报：\n- 代码结构总结\n- 识别出的问题区域\n- 初步建议\n- **请求继续执行的批准**\n\n---\n\n## 阶段 2：测试覆盖评估\n\n### 为什么测试重要\n> “没有测试的重构，就像没有安全带就开车。” — Martin Fowler\n\n测试是安全重构的**关键前提**。没有测试，很容易引入 bug。\n\n### 评估步骤\n\n1. **检查现有测试**\n   ```bash\n   # 查找测试文件\n   find . -name \"*test*\" -o -name \"*spec*\" | head -20\n   ```\n\n2. **运行现有测试**\n   ```bash\n   # JavaScript / TypeScript\n   npm test\n\n   # Python\n   pytest -v\n\n   # Java\n   mvn test\n   ```\n\n3. **检查覆盖率（如果可用）**\n   ```bash\n   # JavaScript\n   npm run test:coverage\n\n   # Python\n   pytest --cov=.\n   ```\n\n### 决策点：询问用户\n\n**如果测试存在且通过：**\n- 进入阶段 3\n\n**如果测试缺失或不完整：**\n给出选项：\n1. 先写测试（推荐）\n2. 在重构过程中逐步补测试\n3. 不写测试直接继续（有风险，需要用户确认）\n\n**如果测试失败：**\n- 停止。先修复失败测试再重构\n- 问用户：是否先修测试？\n\n### 测试编写建议（如需要）\n\n对每个要重构的函数，测试应覆盖：\n- 正常路径\n- 边界情况（空输入、null、边界值）\n- 错误场景（非法输入、异常）\n\n使用“红-绿-重构”循环：\n1. 写失败测试（红）\n2. 让它通过（绿）\n3. 再重构\n\n---\n\n## 阶段 3：识别代码异味\n\n### 什么是代码异味？\n代码深层问题的表面症状。它们不一定是 bug，但说明代码设计可能有问题。\n\n### 常见异味清单\n\n完整目录见 [references/code-smells.md](references/code-smells.md)。\n\n#### 快速参考\n\n| 异味 | 迹象 | 影响 |\n|-------|------|------|\n| **长函数** | 函数超过 30-50 行 | 难以理解、测试和维护 |\n| **重复代码** | 多处出现相同逻辑 | 修复需要改多处 |\n| **大类** | 类承担了太多职责 | 违反单一职责原则 |\n| **Feature Envy** | 一个方法更多依赖别的类的数据 | 封装性差 |\n| **基础类型沉迷** | 过度使用基础类型而不是对象 | 缺少领域概念 |\n| **长参数列表** | 方法参数超过 4 个 | 调用困难 |\n| **数据泥团** | 一组数据总是一起出现 | 缺少抽象 |\n| **switch 语句** | 复杂的 switch / if-else 链 | 难以扩展 |\n| **臆想泛化** | “以防未来需要”提前设计 | 不必要的复杂度 |\n| **死代码** | 未使用的代码 | 造成困惑和维护负担 |\n\n### 分析步骤\n\n1. **自动分析**（如果有脚本）\n   ```bash\n   python scripts/detect-smells.py <file>\n   ```\n\n2. **人工审查**\n   - 系统地走读代码\n   - 记录每个异味的位置和严重性\n   - 按影响分类（Critical / High / Medium / Low）\n\n3. **优先级排序**\n   优先关注会：\n   - 阻塞当前开发的异味\n   - 导致 bug 或混淆的异味\n   - 影响最常变更代码路径的异味\n\n### 输出：异味报告\n\n向用户呈现：\n- 识别出的异味及位置\n- 每项的严重性评估\n- 建议的优先级顺序\n- **请求用户确认优先级**\n\n---\n\n## 阶段 4：创建重构计划\n\n### 选择重构方式\n\n针对每个异味，从目录中选择合适的重构手法。\n\n完整列表见 [references/refactoring-catalog.md](references/refactoring-catalog.md)。\n\n#### 异味到重构的映射\n\n| 代码异味 | 推荐重构 |\n|----------|----------|\n| 长函数 | Extract Method、Replace Temp with Query |\n| 重复代码 | Extract Method、Pull Up Method、Form Template Method |\n| 大类 | Extract Class、Extract Subclass |\n| Feature Envy | Move Method、Move Field |\n| 基础类型沉迷 | Replace Primitive with Object、Replace Type Code with Class |\n| 长参数列表 | Introduce Parameter Object、Preserve Whole Object |\n| 数据泥团 | Extract Class、Introduce Parameter Object |\n| switch 语句 | Replace Conditional with Polymorphism |\n| 臆想泛化 | Collapse Hierarchy、Inline Class、Remove Dead Code |\n| 死代码 | Remove Dead Code |\n\n### 计划结构\n\n使用 [templates/refactoring-plan.md](templates/refactoring-plan.md) 里的模板。\n\n每项重构都要写明：\n1. **Target**：将修改哪些代码\n2. **Smell**：解决什么问题\n3. **Refactoring**：采用哪种手法\n4. **Steps**：详细微步骤\n5. **Risks**：可能出什么问题\n6. **Rollback**：如何回退\n\n### 分阶段方法\n\n**关键**：重构必须分阶段推进。\n\n**阶段 A：快速收益**（低风险，高价值）\n- 重命名变量以提升清晰度\n- 提取明显重复的代码\n- 删除死代码\n\n**阶段 B：结构改进**（中风险）\n- 从长函数中提取方法\n- 引入参数对象\n- 把方法移动到更合适的类\n\n**阶段 C：架构改动**（高风险）\n- 用多态替代条件分支\n- 提取类\n- 引入设计模式\n\n### 决策点：把计划展示给用户\n\n在开始实施前：\n- 展示完整重构计划\n- 解释每个阶段及其风险\n- 获得每个阶段的明确批准\n- **询问**：“是否继续执行阶段 A？”\n\n---\n\n## 阶段 5：增量实施\n\n### 黄金法则\n> “修改 → 测试 → 通过？→ 提交 → 下一步”\n\n### 实施节奏\n\n对每一步重构：\n\n1. **预检查**\n   - 测试通过（绿色）\n   - 代码能编译\n\n2. **只做一个小改动**\n   - 按目录中的具体操作进行\n   - 保持改动最小化\n\n3. **验证**\n   - 立刻运行测试\n   - 检查编译错误\n\n4. **如果测试通过（绿色）**\n   - 用描述清晰的提交信息提交\n   - 继续下一步\n\n5. **如果测试失败（红色）**\n   - 立刻停止\n   - 撤销改动\n   - 分析原因\n   - 如有疑问，询问用户\n\n### 提交策略\n\n每次提交都应当：\n- **原子性**：只包含一个逻辑改动\n- **可回滚**：容易撤销\n- **描述清楚**：提交信息明确\n\n示例提交信息：\n```\nrefactor: 从 processOrder() 中提取 calculateTotal()\nrefactor: 将 'x' 重命名为 'customerCount' 以提升清晰度\nrefactor: 删除未使用的 validateOldFormat() 方法\n```\n\n### 进度汇报\n\n每个子阶段完成后，向用户汇报：\n- 做了哪些改动\n- 测试是否仍通过\n- 遇到了什么问题\n- **询问**：“继续下一批吗？”\n\n---\n\n## 阶段 6：评审与迭代\n\n### 重构后检查清单\n\n- [ ] 所有测试通过\n- [ ] 没有新的警告 / 错误\n- [ ] 代码编译成功\n- [ ] 行为没有变化（手动验证）\n- [ ] 必要时已更新文档\n- [ ] 提交历史干净\n\n### 指标对比\n\n重构前后运行复杂度分析：\n```bash\npython scripts/analyze-complexity.py <file>\n```\n\n展示改进：\n- 代码行数变化\n- 圈复杂度变化\n- 可维护性指标变化\n\n### 用户评审\n\n向用户展示最终结果：\n- 所有变更摘要\n- 重构前后代码对比\n- 指标改善情况\n- 剩余技术债\n- **询问**：“你对这些改动满意吗？”\n\n### 下一步\n\n和用户讨论：\n- 还要处理哪些异味？\n- 是否安排下一次重构？\n- 是否把类似修改应用到其他地方？\n\n---\n\n## 重要指南\n\n### 何时暂停并询问\n\n遇到以下情况时，务必暂停并和用户确认：\n- 不确定业务逻辑\n- 改动可能影响外部 API\n- 测试覆盖不足\n- 需要做重大的架构决策\n- 风险上升\n- 遇到意外复杂性\n\n### 安全规则\n\n1. **没有测试不要重构**（除非用户明确确认风险）\n2. **不要做大改动**，拆成小步\n3. **每次改动后都不要跳过测试**\n4. **测试失败就不要继续**，先修复或回滚\n5. **不要臆测**，不确定就问\n\n### 不要做什么\n\n- 不要把重构和新功能混在一起\n- 不要在生产事故期间做重构\n- 不要重构你看不懂的代码\n- 不要过度设计，保持简单\n- 不要一次性重构所有内容\n\n---\n\n## 快速上手示例\n\n### 场景：长函数 + 重复逻辑\n\n**重构前：**\n```javascript\nfunction processOrder(order) {\n  // 150 行代码，包含：\n  // - 重复验证逻辑\n  // - 内联计算\n  // - 多种职责混杂\n}\n```\n\n**重构步骤：**\n\n1. **确认测试存在**，覆盖 `processOrder()`\n2. **提取** 验证逻辑为 `validateOrder()`\n3. **测试** - 应该通过\n4. **提取** 计算逻辑为 `calculateOrderTotal()`\n5. **测试** - 应该通过\n6. **提取** 通知逻辑为 `notifyCustomer()`\n7. **测试** - 应该通过\n8. **评审** - `processOrder()` 现在只负责串联 3 个清晰函数\n\n**重构后：**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const total = calculateOrderTotal(order);\n  notifyCustomer(order, total);\n  return { order, total };\n}\n```\n\n---\n\n## 参考资料\n\n- [代码异味目录](references/code-smells.md) - 代码异味完整清单\n- [重构目录](references/refactoring-catalog.md) - 重构手法\n- [重构计划模板](templates/refactoring-plan.md) - 计划模板\n\n## 脚本\n\n- `scripts/analyze-complexity.py` - 分析代码复杂度指标\n- `scripts/detect-smells.py` - 自动检测 code smell\n\n## 版本历史\n\n- v1.0.0 (2025-01-15)：首次发布，包含 Fowler 方法论、分阶段流程和用户确认点\n","frontmatter":{"name":"refactor","description":"基于 Martin Fowler 方法论的系统化代码重构 skill。适用于用户请求重构代码、改进代码结构、减少技术债、清理旧代码、消除 code smell 或提升可维护性时。这个 skill 采用分阶段、带研究与计划的安全增量实施方式。"},"isInternal":false,"tokens":3914,"sizeBytes":10861},{"name":"generate-readme.md","path":"07-plugins/documentation/commands/generate-readme.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/07-plugins/documentation/commands/generate-readme.md","title":"Command: /generate-readme","category":"command-prompt","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fdocumentation%2Fcommands%2Fgenerate-readme.md -->","frontmatter":{"description":"Create or update project README"},"isInternal":false,"tokens":157,"sizeBytes":582},{"name":"generate-readme.md","path":"ja/07-plugins/documentation/commands/generate-readme.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/ja/07-plugins/documentation/commands/generate-readme.md","title":"Command: /generate-readme","category":"command-prompt","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=ja%2F07-plugins%2Fdocumentation%2Fcommands%2Fgenerate-readme.md -->","isInternal":false,"tokens":229,"sizeBytes":681},{"name":"generate-readme.md","path":"uk/07-plugins/documentation/commands/generate-readme.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/uk/07-plugins/documentation/commands/generate-readme.md","title":"Command: /generate-readme","category":"command-prompt","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fdocumentation%2Fcommands%2Fgenerate-readme.md -->","frontmatter":{"description":"Створення або оновлення README проєкту"},"isInternal":false,"tokens":216,"sizeBytes":701},{"name":"generate-readme.md","path":"vi/07-plugins/documentation/commands/generate-readme.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/vi/07-plugins/documentation/commands/generate-readme.md","title":"Command: /generate-readme","category":"command-prompt","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fdocumentation%2Fcommands%2Fgenerate-readme.md -->","frontmatter":{"description":"Create or update project README"},"isInternal":false,"tokens":129,"sizeBytes":488},{"name":"generate-readme.md","path":"zh/07-plugins/documentation/commands/generate-readme.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/zh/07-plugins/documentation/commands/generate-readme.md","title":"Command: /generate-readme","category":"command-prompt","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=zh%2F07-plugins%2Fdocumentation%2Fcommands%2Fgenerate-readme.md -->","frontmatter":{"description":"创建或更新项目 README"},"isInternal":false,"tokens":141,"sizeBytes":406},{"name":"plugin.json","path":"07-plugins/devops-automation/.claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/07-plugins/devops-automation/.claude-plugin/plugin.json","title":"devops-automation","category":"plugin-manifest","format":"json","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fdevops-automation%2F.claude-plugin%2Fplugin.json -->","frontmatter":{"name":"devops-automation","version":"1.0.0","description":"Complete DevOps automation for deployment, monitoring, and incident response","author":{"name":"Community"},"license":"MIT"},"isInternal":false,"tokens":62,"sizeBytes":216},{"name":"README.md","path":"07-plugins/devops-automation/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/07-plugins/devops-automation/README.md","title":"devops-automation Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fdevops-automation%2FREADME.md -->","isInternal":false,"tokens":689,"sizeBytes":2570},{"name":"plugin.json","path":"07-plugins/documentation/.claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/07-plugins/documentation/.claude-plugin/plugin.json","title":"documentation","category":"plugin-manifest","format":"json","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fdocumentation%2F.claude-plugin%2Fplugin.json -->","frontmatter":{"name":"documentation","version":"1.0.0","description":"Comprehensive documentation generation and maintenance","author":{"name":"Community"},"license":"MIT"},"isInternal":false,"tokens":53,"sizeBytes":190},{"name":"README.md","path":"07-plugins/documentation/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/07-plugins/documentation/README.md","title":"documentation Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fdocumentation%2FREADME.md -->","isInternal":false,"tokens":748,"sizeBytes":3054},{"name":"plugin.json","path":"07-plugins/pr-review/.claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/07-plugins/pr-review/.claude-plugin/plugin.json","title":"pr-review","category":"plugin-manifest","format":"json","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fpr-review%2F.claude-plugin%2Fplugin.json -->","frontmatter":{"name":"pr-review","version":"1.0.0","description":"Complete PR review workflow with security, testing, and docs","author":{"name":"Anthropic"},"license":"MIT"},"isInternal":false,"tokens":60,"sizeBytes":192},{"name":"README.md","path":"07-plugins/pr-review/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/07-plugins/pr-review/README.md","title":"pr-review Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2Fpr-review%2FREADME.md -->","isInternal":false,"tokens":619,"sizeBytes":2373},{"name":"README.md","path":"07-plugins/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/07-plugins/README.md","title":"07-plugins Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=07-plugins%2FREADME.md -->","isInternal":false,"tokens":12450,"sizeBytes":50665},{"name":"README.md","path":"ja/07-plugins/devops-automation/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/ja/07-plugins/devops-automation/README.md","title":"devops-automation Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=ja%2F07-plugins%2Fdevops-automation%2FREADME.md -->","isInternal":false,"tokens":966,"sizeBytes":2853},{"name":"README.md","path":"ja/07-plugins/documentation/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/ja/07-plugins/documentation/README.md","title":"documentation Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=ja%2F07-plugins%2Fdocumentation%2FREADME.md -->","isInternal":false,"tokens":1101,"sizeBytes":3525},{"name":"README.md","path":"ja/07-plugins/pr-review/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/ja/07-plugins/pr-review/README.md","title":"pr-review Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=ja%2F07-plugins%2Fpr-review%2FREADME.md -->","isInternal":false,"tokens":869,"sizeBytes":2630},{"name":"README.md","path":"ja/07-plugins/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/ja/07-plugins/README.md","title":"07-plugins Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=ja%2F07-plugins%2FREADME.md -->","isInternal":false,"tokens":14815,"sizeBytes":46383},{"name":"plugin.json","path":"uk/07-plugins/devops-automation/.claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/uk/07-plugins/devops-automation/.claude-plugin/plugin.json","title":"devops-automation","category":"plugin-manifest","format":"json","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fdevops-automation%2F.claude-plugin%2Fplugin.json -->","frontmatter":{"name":"devops-automation","version":"1.0.0","description":"Complete DevOps automation for deployment, monitoring, and incident response","author":{"name":"Community"},"license":"MIT"},"isInternal":false,"tokens":62,"sizeBytes":216},{"name":"README.md","path":"uk/07-plugins/devops-automation/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/uk/07-plugins/devops-automation/README.md","title":"devops-automation Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fdevops-automation%2FREADME.md -->","isInternal":false,"tokens":1051,"sizeBytes":3304},{"name":"plugin.json","path":"uk/07-plugins/documentation/.claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/uk/07-plugins/documentation/.claude-plugin/plugin.json","title":"documentation","category":"plugin-manifest","format":"json","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fdocumentation%2F.claude-plugin%2Fplugin.json -->","frontmatter":{"name":"documentation","version":"1.0.0","description":"Comprehensive documentation generation and maintenance","author":{"name":"Community"},"license":"MIT"},"isInternal":false,"tokens":53,"sizeBytes":190},{"name":"README.md","path":"uk/07-plugins/documentation/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/uk/07-plugins/documentation/README.md","title":"documentation Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fdocumentation%2FREADME.md -->","isInternal":false,"tokens":1321,"sizeBytes":4224},{"name":"plugin.json","path":"uk/07-plugins/pr-review/.claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/uk/07-plugins/pr-review/.claude-plugin/plugin.json","title":"pr-review","category":"plugin-manifest","format":"json","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fpr-review%2F.claude-plugin%2Fplugin.json -->","frontmatter":{"name":"pr-review","version":"1.0.0","description":"Complete PR review workflow with security, testing, and docs","author":{"name":"Anthropic"},"license":"MIT"},"isInternal":false,"tokens":60,"sizeBytes":192},{"name":"README.md","path":"uk/07-plugins/pr-review/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/uk/07-plugins/pr-review/README.md","title":"pr-review Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2Fpr-review%2FREADME.md -->","isInternal":false,"tokens":955,"sizeBytes":2997},{"name":"README.md","path":"uk/07-plugins/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/uk/07-plugins/README.md","title":"07-plugins Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=uk%2F07-plugins%2FREADME.md -->","isInternal":false,"tokens":14827,"sizeBytes":49006},{"name":"plugin.json","path":"vi/07-plugins/devops-automation/.claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/vi/07-plugins/devops-automation/.claude-plugin/plugin.json","title":"devops-automation","category":"plugin-manifest","format":"json","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fdevops-automation%2F.claude-plugin%2Fplugin.json -->","frontmatter":{"name":"devops-automation","version":"1.0.0","description":"Complete DevOps automation for deployment, monitoring, and incident response","author":{"name":"Community"},"license":"MIT"},"isInternal":false,"tokens":62,"sizeBytes":216},{"name":"README.md","path":"vi/07-plugins/devops-automation/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/vi/07-plugins/devops-automation/README.md","title":"devops-automation Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fdevops-automation%2FREADME.md -->","isInternal":false,"tokens":592,"sizeBytes":2261},{"name":"plugin.json","path":"vi/07-plugins/documentation/.claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/vi/07-plugins/documentation/.claude-plugin/plugin.json","title":"documentation","category":"plugin-manifest","format":"json","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fdocumentation%2F.claude-plugin%2Fplugin.json -->","frontmatter":{"name":"documentation","version":"1.0.0","description":"Comprehensive documentation generation and maintenance","author":{"name":"Community"},"license":"MIT"},"isInternal":false,"tokens":53,"sizeBytes":190},{"name":"README.md","path":"vi/07-plugins/documentation/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/vi/07-plugins/documentation/README.md","title":"documentation Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fdocumentation%2FREADME.md -->","isInternal":false,"tokens":651,"sizeBytes":2745},{"name":"plugin.json","path":"vi/07-plugins/pr-review/.claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/vi/07-plugins/pr-review/.claude-plugin/plugin.json","title":"pr-review","category":"plugin-manifest","format":"json","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fpr-review%2F.claude-plugin%2Fplugin.json -->","frontmatter":{"name":"pr-review","version":"1.0.0","description":"Complete PR review workflow with security, testing, and docs","author":{"name":"Anthropic"},"license":"MIT"},"isInternal":false,"tokens":60,"sizeBytes":192},{"name":"README.md","path":"vi/07-plugins/pr-review/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/vi/07-plugins/pr-review/README.md","title":"pr-review Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2Fpr-review%2FREADME.md -->","isInternal":false,"tokens":522,"sizeBytes":2064},{"name":"README.md","path":"vi/07-plugins/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/vi/07-plugins/README.md","title":"07-plugins Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=vi%2F07-plugins%2FREADME.md -->","isInternal":false,"tokens":11932,"sizeBytes":38850},{"name":"README.md","path":"zh/07-plugins/devops-automation/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/zh/07-plugins/devops-automation/README.md","title":"DevOps 自动化插件","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=zh%2F07-plugins%2Fdevops-automation%2FREADME.md -->","frontmatter":{"name":"DevOps 自动化插件","description":"为部署、监控和故障处理提供自动化工作流","tags":"plugins, devops, automation"},"isInternal":false,"tokens":773,"sizeBytes":2053},{"name":"README.md","path":"zh/07-plugins/documentation/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/zh/07-plugins/documentation/README.md","title":"文档生成插件","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=zh%2F07-plugins%2Fdocumentation%2FREADME.md -->","frontmatter":{"name":"文档生成插件","description":"为文档编写、同步和校验提供完整工作流","tags":"plugins, documentation, automation"},"isInternal":false,"tokens":1032,"sizeBytes":3011},{"name":"README.md","path":"zh/07-plugins/pr-review/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/zh/07-plugins/pr-review/README.md","title":"PR 审查插件","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=zh%2F07-plugins%2Fpr-review%2FREADME.md -->","frontmatter":{"name":"PR 审查插件","description":"为 Pull Request 提供完整的代码审查工作流","tags":"plugins, code-review, pull-request"},"isInternal":false,"tokens":669,"sizeBytes":1850},{"name":"README.md","path":"zh/07-plugins/README.md","rawUrl":"https://raw.githubusercontent.com/luongnv89/claude-howto/HEAD/zh/07-plugins/README.md","title":"07-plugins Documentation","category":"plugin-manifest","format":"markdown","content":"<!-- Skill available on-demand via /api/skills/luongnv89/claude-howto?path=zh%2F07-plugins%2FREADME.md -->","isInternal":false,"tokens":10161,"sizeBytes":30810}],"systemPromptSnippet":"<yakaai_skills repo=\"luongnv89/claude-howto\">\n<!-- File: CLAUDE.md (Tokens: ~982 | Category: claude-rule) -->\n# CLAUDE.md\n\nTutorial repo. Output is markdown in numbered modules `01-` through `10-`, not an app. Scripts in `scripts/` exist only to validate docs and build the EPUB.\n\nSee also `.claude/CLAUDE.md` for stack/commands and `STYLE_GUIDE.md` for lesson structure.\n\n## Critical commands\n\n```bash\n# Quality gate (also runs on commit via pre-commit hooks)\npre-commit run --all-files\n\n# Tests\npytest scripts/tests/ -v\n\n# EPUB build (renders Mermaid with Pele — needs Node.js >= 20; the pinned bundle downloads once, then works offline)\nuv run scripts/build_epub.py\n\n# Python tooling\nruff check scripts/ && ruff format scripts/\nmypy scripts/ --ignore-missing-imports\nbandit -c scripts/pyproject.toml -r scripts/ --exclude scripts/tests/\n```\n\nPre-commit runs 5 doc checks on `.md` changes: markdown-lint, cross-references, mermaid-syntax, link-check, markdown-rendering. All must pass. The EPUB build is **not** a pre-commit hook — it runs in CI only (`build-epub` job in `.github/workflows/test.yml`), because it is a slow full-book build; the mermaid-syntax hook already renders every diagram with the same Pele bundle.\n\n## Architecture map\n\n- `01-` … `10-` — tutorial modules. **Numbered prefix = learning order**, not alphabetical. Do not reorganize.\n- Each module: `README.md` + copy-paste templates (`.md`, `.json`, `.sh`).\n- `scripts/` — utilities (EPUB builder, link/mermaid/cross-ref validators). Not the product.\n- `02-memory/*.md` — CLAUDE.md templates users copy into their own projects. Don't confuse with this file.\n- `openspec/` — spec-driven change proposals.\n\n## Hard rules\n\n- **YOU MUST NOT commit or push without explicit user request.**\n- **YOU MUST NOT add `Co-Authored-By: Claude`** to any commit message.\n- Always activate `.venv` before running Python scripts (check `venv/`, `.venv/`, `env/`).\n- Internal links use **relative paths** (e.g. `01-slash-commands/README.md`); anchors use `#heading-name`.\n- Code fences **must** declare a language (`bash`, `python`, `json`, …) — the cross-reference check fails otherwise.\n- External URLs must be reachable and stable. No ephemeral links.\n- Mermaid diagrams must render with Pele. The pre-commit mermaid hooks get Node.js 22 from pre-commit and run strict, so they fail instead of skipping; the first run needs network to download Node.js and the pinned Pele bundle (offline: `SKIP=mermaid,vietnamese-mermaid,japanese-mermaid`). Run by hand, `scripts/check_mermaid.py` only warns without Node.js >= 20, and fails under `--strict` or in CI. A broken EPUB build is usually invalid Mermaid, a missing Node.js >= 20, or a failed bundle download.\n- Commit format: `type(scope): subject` where `scope` matches the module folder (e.g. `feat(slash-commands):`, `docs(memory):`, `fix(README):`).\n- Do not reorganize the `01-`–`10-` numbering. The order is the curriculum.\n\n## Workflow preferences\n\n- For lesson edits, follow `STYLE_GUIDE.md` for structure/naming/diagrams.\n- Small fixes → minimal diff. Don't rewrite a section to fix a typo.\n- When adding a module page: README + templates first, then update root `README.md` index and `LEARNING-ROADMAP.md` if order/timing changes.\n- Tutorial > library: prioritize clear explanations and copy-paste examples over reusable abstractions.\n- If a quality check fails, fix the underlying issue. Don't bypass with `--no-verify`.\n\n## Token Efficiency\n- Never re-read files you just wrote or edited. You know the contents.\n- Never re-run commands to \"verify\" unless the outcome was uncertain.\n- Don't echo back large blocks of code or file contents unless asked.\n- Batch related edits into single operations. Don't make 5 edits when 1 handles it.\n- Skip confirmations like \"I'll continue...\" Just do it.\n- If a task needs 1 tool call, don't use 3. Plan before acting.\n- Do not summarize what you just did unless the result is ambiguous or you need additional input.\n\n<!-- File: ja/CLAUDE.md (Tokens: ~2794 | Category: claude-rule) -->\n<!-- i18n-source: CLAUDE.md -->\n<!-- i18n-source-sha: a70777e -->\n<!-- i18n-date: 2026-04-27 -->\n\n# CLAUDE.md\n\nこのファイルは、本リポジトリ内のコードを扱う際の Claude Code（claude.ai/code）向けガイドである。\n\n## プロジェクト概要\n\nClaude How To は Claude Code 機能のチュートリアルリポジトリである。これは **ドキュメント・アズ・コード** であり、主な成果物は実行可能アプリケーションではなく、番号付きの学習モジュールに整理された Markdown ファイルである。\n\n**アーキテクチャ：** 各モジュール（01〜10）は Claude Code の特定の機能を、コピー＆ペースト可能なテンプレート、Mermaid 図、サンプルとともに解説する。ビルドシステムはドキュメントの品質を検証し、EPUB 電子書籍を生成する。\n\n## よく使うコマンド\n\n### pre-commit 品質チェック\n\nすべてのドキュメントは、コミット前に 5 つの品質チェックを通過しなければならない（pre-commit フックで自動実行される）：\n\n```bash\n# pre-commit フックをインストール（毎コミットで実行）\npre-commit install\n\n# 全チェックを手動で実行\npre-commit run --all-files\n```\n\n5 つのチェックは以下のとおり：\n1. **markdown-lint** — `markdownlint` による Markdown 構造とフォーマット\n2. **cross-references** — 内部リンク、アンカー、コードフェンスの構文（Python スクリプト）\n3. **mermaid-syntax** — すべての Mermaid 図が正しくパースされるかを検証（Python スクリプト）\n4. **link-check** — 外部 URL が到達可能か（Python スクリプト）\n5. **markdown-rendering** — Markdown が壊れずにレンダリングされるか（Python スクリプト）\n\nEPUB ビルドは pre-commit フック **ではない** — CI のみで実行される（`.github/workflows/test.yml` の `build-epub` ジョブ）。本全体をビルドするため時間がかかるからである。mermaid-syntax フックが同じ Pele バンドルですべての図をすでにレンダリングしている。\n\n### 開発環境のセットアップ\n\n```bash\n# uv（Python パッケージマネージャ）をインストール\npip install uv\n\n# 仮想環境を作成して Python 依存関係をインストール\nuv venv\nsource .venv/bin/activate\nuv pip install -r scripts/requirements-dev.txt\n\n# Node.js ツール（Markdown リンタ）をインストール\nnpm install -g markdownlint-cli\n\n# Mermaid 図は Pele でレンダリングする（Node.js >= 20 が必要。グローバルインストールは不要）\nnode --version\n\n# pre-commit フックをインストール\nuv pip install pre-commit\npre-commit install\n```\n\n### テスト\n\n`scripts/` 内の Python スクリプトはユニットテストを持つ：\n\n```bash\n# 全テストを実行\npytest scripts/tests/ -v\n\n# カバレッジ付きで実行\npytest scripts/tests/ -v --cov=scripts --cov-report=html\n\n# 特定のテストを実行\npytest scripts/tests/test_build_epub.py -v\n```\n\n### コード品質\n\n```bash\n# Python コードをリント・整形\nruff check scripts/\nruff format scripts/\n\n# セキュリティスキャン\nbandit -c scripts/pyproject.toml -r scripts/ --exclude scripts/tests/\n\n# 型チェック\nmypy scripts/ --ignore-missing-imports\n```\n\n### EPUB ビルド\n\n```bash\n# 電子書籍を生成（Mermaid 図は Pele でレンダリング／Node.js >= 20 が必要。固定バンドルは初回のみダウンロード）\nuv run scripts/build_epub.py\n\n# オプション付き\nuv run scripts/build_epub.py --verbose --output custom-name.epub --lang ja\n```\n\n## ディレクトリ構造\n\n```\n├── 01-slash-commands/      # ユーザーが起動するショートカット\n├── 02-memory/              # 永続コンテキストの例\n├── 03-skills/              # 再利用可能な能力\n├── 04-subagents/           # 専門 AI アシスタント\n├── 05-mcp/                 # Model Context Protocol の例\n├── 06-hooks/               # イベント駆動の自動化\n├── 07-plugins/             # バンドル機能\n├── 08-checkpoints/         # セッションのスナップショット\n├── 09-advanced-features/   # プランニング、シンキング、バックグラウンド\n├── 10-cli/                 # CLI リファレンス\n├── scripts/\n│   ├── build_epub.py           # EPUB ジェネレータ（Mermaid を Pele でレンダリング）\n│   ├── check_cross_references.py   # 内部リンクを検証\n│   ├── check_links.py          # 外部 URL を検証\n│   ├── check_mermaid.py        # Mermaid 構文を検証\n│   └── tests/                  # スクリプトのユニットテスト\n├── .pre-commit-config.yaml    # 品質チェック定義\n└── README.md               # メインガイド（モジュール索引も兼ねる）\n```\n\n## コンテンツ作成ガイド\n\n### モジュール構造\n番号付きフォルダはいずれも以下のパターンに従う：\n- **README.md** — 機能の概要と例\n- **サンプルファイル** — コピー＆ペースト可能なテンプレート（コマンドは `.md`、設定は `.json`、フックは `.sh`）\n- ファイルは機能の複雑さと依存関係に従って整理されている\n\n### Mermaid 図\n- すべての図は正常にパースできること（pre-commit フックで検査）\n- EPUB ビルドは Pele で図をレンダリングする（Node.js >= 20 が必要。固定バンドルは初回のみダウンロードされ、以降はオフラインで動作する）\n- フローチャート、シーケンス図、アーキテクチャ可視化に Mermaid を使用する\n\n### 相互参照\n- 内部リンクは相対パスを使う（例：`(01-slash-commands/README.md)`）\n- コードフェンスは言語指定が必須（例：` ```bash `、` ```python `）\n- アンカーリンクは `#heading-name` 形式\n\n### リンク検証\n- 外部 URL は到達可能であること（pre-commit フックで検査）\n- 一時的なコンテンツへのリンクは避ける\n- 可能な限りパーマリンクを使用する\n\n## 主要なアーキテクチャ上のポイント\n\n1. **番号付きフォルダは学習順序を示す** — 01〜10 のプレフィックスは Claude Code 機能の推奨学習順序を表す。この番号付けは意図的なものなので、アルファベット順に並べ替えてはならない。\n\n2. **スクリプトはユーティリティであり製品ではない** — `scripts/` の Python スクリプトはドキュメント品質と EPUB 生成を支援するものである。実際のコンテンツは番号付きモジュールフォルダにある。\n\n3. **pre-commit がゲートキーパー** — PR が承認される前に 5 つの品質チェックがすべて通過しなければならない。CI パイプラインは同じチェックを 2 回目のパスとして実行する。\n\n4. **Mermaid のレンダリングには Node.js >= 20 が必要** — EPUB ビルドは固定バージョンの Pele バンドルを Node.js で実行して図をレンダリングする（バンドルは初回のみダウンロードされ、sha256 で検証してキャッシュされる）。ここでビルドが失敗する場合は、Node.js >= 20 が未インストールか、バンドルのダウンロード失敗か、Mermaid 構文エラーが典型的な原因である。pre-commit の mermaid フックは pre-commit が用意する Node.js 22 で厳格モードで実行され、スキップせずに失敗する。EPUB ビルド自体は pre-commit では実行されず、CI のみで実行される。\n\n5. **これはチュートリアルでありライブラリではない** — コンテンツを追加する際は、明快な解説、コピー＆ペースト可能な例、視覚的な図を重視する。価値は概念を教えることにあり、再利用可能なコードを提供することではない。\n\n## コミット規約\n\nConventional Commits 形式に従う：\n- `feat(slash-commands): Add API documentation generator`\n- `docs(memory): Improve personal preferences example`\n- `fix(README): Correct table of contents link`\n- `refactor(hooks): Simplify hook configuration examples`\n\nスコープは該当するフォルダ名に合わせる。\n\n<!-- File: uk/CLAUDE.md (Tokens: ~2879 | Category: claude-rule) -->\n<!-- i18n-source: CLAUDE.md -->\n<!-- i18n-source-sha: 63a1416 -->\n<!-- i18n-date: 2026-04-10 -->\n\n# CLAUDE.md\n\nЦей файл надає настанови для Claude Code (claude.ai/code) при роботі з кодом у цьому репозиторії.\n\n## Огляд проєкту\n\nClaude How To — це навчальний репозиторій з функцій Claude Code. Це **документація-як-код** — основний продукт — markdown-файли, організовані в пронумеровані навчальні модулі, а не виконуваний додаток.\n\n**Архітектура**: Кожен модуль (01-10) охоплює конкретну функцію Claude Code з готовими шаблонами для копіювання, Mermaid-діаграмами та прикладами. Система збірки валідує якість документації та генерує EPUB-книгу.\n\n## Типові команди\n\n### Перевірки якості pre-commit\n\nУся документація повинна пройти п'ять перевірок якості перед комітами (запускаються автоматично через pre-commit хуки):\n\n```bash\n# Install pre-commit hooks (runs on every commit)\npre-commit install\n\n# Run all checks manually\npre-commit run --all-files\n```\n\nП'ять перевірок:\n1. **markdown-lint** — Структура та форматування Markdown через `markdownlint`\n2. **cross-references** — Внутрішні посилання, якорі, синтаксис блоків коду (Python-скрипт)\n3. **mermaid-syntax** — Валідація коректного парсингу всіх Mermaid-діаграм (Python-скрипт)\n4. **link-check** — Доступність зовнішніх URL (Python-скрипт)\n5. **markdown-rendering** — Markdown рендериться без помилок (Python-скрипт)\n\nЗбірка EPUB **не є** pre-commit хуком — вона виконується лише в CI (джоб `build-epub` у `.github/workflows/test.yml`), бо це повільна збірка всієї книги; хук mermaid-syntax уже рендерить кожну діаграму тим самим бандлом Pele.\n\n### Налаштування середовища розробки\n\n```bash\n# Install uv (Python package manager)\npip install uv\n\n# Create virtual environment and install Python dependencies\nuv venv\nsource .venv/bin/activate\nuv pip install -r scripts/requirements-dev.txt\n\n# Install Node.js tools (markdown linter)\nnpm install -g markdownlint-cli\n\n# Mermaid diagrams render with Pele: needs Node.js >= 20, no global package\nnode --version\n\n# Install pre-commit hooks\nuv pip install pre-commit\npre-commit install\n```\n\n### Тестування\n\nPython-скрипти в `scripts/` мають юніт-тести:\n\n```bash\n# Run all tests\npytest scripts/tests/ -v\n\n# Run with coverage\npytest scripts/tests/ -v --cov=scripts --cov-report=html\n\n# Run specific test\npytest scripts/tests/test_build_epub.py -v\n```\n\n### Якість коду\n\n```bash\n# Lint and format Python code\nruff check scripts/\nruff format scripts/\n\n# Security scan\nbandit -c scripts/pyproject.toml -r scripts/ --exclude scripts/tests/\n\n# Type checking\nmypy scripts/ --ignore-missing-imports\n```\n\n### Збірка EPUB\n\n```bash\n# Generate ebook (renders Mermaid diagrams with Pele — needs Node.js >= 20; the pinned bundle downloads once)\nuv run scripts/build_epub.py\n\n# With options\nuv run scripts/build_epub.py --verbose --output custom-name.epub\n```\n\n## Структура каталогів\n\n```\n├── 01-slash-commands/      # Ярлики, ініційовані користувачем\n├── 02-memory/              # Приклади постійного контексту\n├── 03-skills/              # Повторно використовувані можливості\n├── 04-subagents/           # Спеціалізовані AI-асистенти\n├── 05-mcp/                 # Приклади Model Context Protocol\n├── 06-hooks/               # Автоматизація на основі подій\n├── 07-plugins/             # Пакетні функції\n├── 08-checkpoints/         # Знімки сесій\n├── 09-advanced-features/   # Планування, мислення, фони\n├── 10-cli/                 # Довідник CLI\n├── scripts/\n│   ├── build_epub.py           # Генератор EPUB (рендерить Mermaid через Pele)\n│   ├── check_cross_references.py   # Валідація внутрішніх посилань\n│   ├── check_links.py          # Перевірка зовнішніх URL\n│   ├── check_mermaid.py        # Валідація синтаксису Mermaid\n│   └── tests/                  # Юніт-тести для скриптів\n├── .pre-commit-config.yaml    # Визначення перевірок якості\n└── README.md               # Основний довідник (також індекс модулів)\n```\n\n## Настанови щодо контенту\n\n### Структура модуля\nКожна пронумерована папка дотримується патерну:\n- **README.md** — Огляд функції з прикладами\n- **Файли прикладів** — Готові шаблони для копіювання (`.md` для команд, `.json` для конфігурацій, `.sh` для хуків)\n- Файли організовані за складністю функцій та залежностями\n\n### Mermaid-діаграми\n- Усі діаграми повинні успішно парситися (перевіряється pre-commit хуком)\n- Збірка EPUB рендерить діаграми через Pele (потрібен Node.js >= 20; закріплений бандл завантажується лише під час першого запуску, далі все працює офлайн)\n- Використовуйте Mermaid для блок-схем, діаграм послідовностей та архітектурних візуалізацій\n\n### Перехресні посилання\n- Використовуйте відносні шляхи для внутрішніх посилань (напр., `(01-slash-commands/README.md)`)\n- Блоки коду повинні вказувати мову (напр., ` ```bash `, ` ```python `)\n- Якірні посилання використовують формат `#heading-name`\n\n### Валідація посилань\n- Зовнішні URL повинні бути доступні (перевіряється pre-commit хуком)\n- Уникайте посилань на тимчасовий контент\n- Використовуйте пермалінки де можливо\n\n## Ключові архітектурні рішення\n\n1. **Пронумеровані папки вказують порядок навчання** — Префікс 01-10 відображає рекомендовану послідовність вивчення функцій Claude Code. Ця нумерація навмисна; не реорганізовуйте за алфавітом.\n\n2. **Скрипти — утиліти, а не продукт** — Python-скрипти в `scripts/` підтримують якість документації та генерацію EPUB. Фактичний контент — у пронумерованих папках модулів.\n\n3. **Pre-commit — привратник** — Усі перевірки якості повинні пройти перед прийняттям PR. CI-конвеєр запускає ці ж перевірки як другий прохід.\n\n4. **Рендеринг Mermaid потребує Node.js >= 20** — Збірка EPUB запускає закріплений бандл Pele через Node.js для рендерингу діаграм (бандл завантажується лише під час першого запуску, перевіряється за sha256 і кешується). Помилки збірки тут зазвичай пов'язані з відсутнім Node.js >= 20, невдалим завантаженням бандла або невалідним синтаксисом Mermaid. Хуки mermaid у pre-commit працюють у суворому режимі з Node.js 22, який надає сам pre-commit, тож вони падають, а не пропускають перевірку. Сама збірка EPUB не виконується у pre-commit — лише в CI.\n\n5. **Це туторіал, а не бібліотека** — При додаванні контенту зосереджуйтесь на чітких поясненнях, готових прикладах та візуальних діаграмах. Цінність — у навчанні концепцій, а не у наданні повторно використовуваного коду.\n\n## Конвенції комітів\n\nДотримуйтесь формату conventional commits:\n- `feat(slash-commands): Add API documentation generator`\n- `docs(memory): Improve personal preferences example`\n- `fix(README): Correct table of contents link`\n- `refactor(hooks): Simplify hook configuration examples`\n\nСкоуп повинен відповідати назві папки де можливо.\n\n<!-- File: vi/CLAUDE.md (Tokens: ~2333 | Category: claude-rule) -->\n# CLAUDE.md\n\nFile này cung cấp hướng dẫn cho Claude Code (claude.ai/code) khi làm việc với code trong repository này.\n\n## Tổng Quan Dự Án\n\nClaude How To là một repository tutorial về các tính năng của Claude Code. Đây là **documentation-as-code** — sản phẩm chính là các file markdown được tổ chức thành các module học tập đánh số (01-10), không phải một ứng dụng thực thi.\n\n**Kiến trúc**: Mỗi module (01-10) bao phủ một tính năng cụ thể của Claude Code với các template copy-paste, sơ đồ Mermaid, và ví dụ. Hệ thống build xác thực chất lượng documentation và tạo ebook EPUB.\n\n## Các Lệnh Thường Dùng\n\n### Kiểm Tra Chất Lượng Pre-commit\n\nTất cả documentation phải vượt qua năm kiểm tra chất lượng trước khi commit (các kiểm tra này chạy tự động qua pre-commit hooks):\n\n```bash\n# Cài đặt pre-commit hooks (chạy trên mỗi commit)\npre-commit install\n\n# Chạy tất cả các kiểm tra thủ công\npre-commit run --all-files\n```\n\nNăm kiểm tra là:\n1. **markdown-lint** — Cấu trúc và định dạng Markdown qua `markdownlint`\n2. **cross-references** — Liên kết nội bộ, anchors, cú pháp code fence (Python script)\n3. **mermaid-syntax** — Xác thực tất cả sơ đồ Mermaid parse đúng (Python script)\n4. **link-check** — Các URL bên ngoài có thể truy cập được (Python script)\n5. **markdown-rendering** — Markdown render không lỗi (Python script)\n\nViệc build EPUB **không phải** là một pre-commit hook — nó chỉ chạy trong CI (job `build-epub` trong `.github/workflows/test.yml`), vì đây là bản build toàn bộ sách, chạy chậm; hook mermaid-syntax đã render mọi sơ đồ bằng cùng bundle Pele.\n\n### Thiết Lập Môi Trường Phát Triển\n\n```bash\n# Cài đặt uv (Python package manager)\npip install uv\n\n# Tạo virtual environment và cài đặt Python dependencies\nuv venv\nsource .venv/bin/activate\nuv pip install -r scripts/requirements-dev.txt\n\n# Cài đặt Node.js tools (markdown linter)\nnpm install -g markdownlint-cli\n\n# Sơ đồ Mermaid được render bằng Pele: cần Node.js >= 20, không cần cài package toàn cục\nnode --version\n\n# Cài đặt pre-commit hooks\nuv pip install pre-commit\npre-commit install\n```\n\n### Testing\n\nCác script Python trong `scripts/` có unit tests:\n\n```bash\n# Chạy tất cả tests\npytest scripts/tests/ -v\n\n# Chạy với coverage\npytest scripts/tests/ -v --cov=scripts --cov-report=html\n\n# Chạy test cụ thể\npytest scripts/tests/test_build_epub.py -v\n```\n\n### Chất Lượng Code\n\n```bash\n# Lint và format Python code\nruff check scripts/\nruff format scripts/\n\n# Security scan\nbandit -c scripts/pyproject.toml -r scripts/ --exclude scripts/tests/\n\n# Type checking\nmypy scripts/ --ignore-missing-imports\n```\n\n### Build EPUB\n\n```bash\n# Tạo ebook (render Mermaid diagrams bằng Pele — cần Node.js >= 20; bundle cố định chỉ tải về một lần)\nuv run scripts/build_epub.py\n\n# Với các tùy chọn\nuv run scripts/build_epub.py --verbose --output custom-name.epub --lang vi\n```\n\n## Cấu Trúc Thư Mục\n\n```\n├── 01-slash-commands/      # Các lối tắt do người dùng gọi\n├── 02-memory/              # Ví dụ về bối cảnh liên tục\n├── 03-skills/              # Các khả năng có thể tái sử dụng\n├── 04-subagents/           # Các tác nhân AI chuyên dụng\n├── 05-mcp/                 # Ví dụ Model Context Protocol\n├── 06-hooks/              # Tự động hóa dựa trên sự kiện\n├── 07-plugins/             # Các tính năng được đóng gói\n├── 08-checkpoints/         # Các snapshot của phiên\n├── 09-advanced-features/   # Lập kế hoạch, suy nghĩ, background tasks\n├── 10-cli/                 # Tham chiếu CLI\n├── scripts/\n│   ├── build_epub.py           # EPUB generator (render Mermaid bằng Pele)\n│   ├── check_cross_references.py   # Xác thực liên kết nội bộ\n│   ├── check_links.py          # Kiểm tra các URL bên ngoài\n│   ├── check_mermaid.py        # Xác thực cú pháp Mermaid\n│   └── tests/                  # Unit tests cho scripts\n├── .pre-commit-config.yaml    # Định nghĩa các kiểm tra chất lượng\n└── README.md               # Hướng dẫn chính (cũng là index của module)\n```\n\n## Hướng Dẫn Nội Dung\n\n### Cấu Trúc Module\n\nMỗi thư mục đánh số tuân theo pattern:\n- **README.md** — Tổng quan về tính năng với các ví dụ\n- **Các file ví dụ** — Template copy-paste (`.md` cho commands, `.json` cho configs, `.sh` cho hooks)\n- Các file được tổ chức theo độ phức tạp của tính năng và dependencies\n\n### Sơ Đồ Mermaid\n- Tất cả sơ đồ phải parse thành công (được kiểm tra bởi pre-commit hook)\n- EPUB build render sơ đồ bằng Pele (cần Node.js >= 20; bundle cố định chỉ tải về trong lần chạy đầu tiên, sau đó chạy offline)\n- Sử dụng Mermaid cho flowcharts, sequence diagrams, và architecture visuals\n\n### Cross-References\n- Sử dụng relative paths cho internal links (ví dụ: `(01-slash-commands/README.md)`)\n- Code fences phải chỉ định ngôn ngữ (ví dụ: ` ```bash `, ` ```python `)\n- Anchor links sử dụng format `#heading-name`\n\n### Link Validation\n- Các URL bên ngoài phải có thể truy cập được (được kiểm tra bởi pre-commit hook)\n- Tránh link đến nội dung tạm thời\n- Sử dụng permalinks nếu có thể\n\n## Các Điểm Kiến Trúc Quan Trọng\n\n1. **Các thư mục đánh số thể hiện thứ tự học tập** — Prefix 01-10 thể hiện thứ tự được khuyến nghị để học các tính năng của Claude Code. Đánh số này có chủ đích; không tổ chức lại theo bảng chữ cái.\n\n2. **Scripts là các tiện ích, không phải sản phẩm** — Các script Python trong `scripts/` hỗ trợ chất lượng documentation và tạo EPUB. Nội dung thực tế nằm trong các thư mục module đánh số.\n\n3. **Pre-commit là người gác cổng** — Tất cả năm kiểm tra chất lượng phải pass trước khi PR được chấp nhận. CI pipeline chạy các kiểm tra tương tự như lần thứ hai.\n\n4. **Mermaid rendering cần Node.js >= 20** — EPUB build chạy bundle Pele cố định bằng Node.js để render diagrams (bundle chỉ tải về trong lần chạy đầu tiên, được kiểm tra sha256 và lưu cache). Các lỗi build ở đây thường là do chưa cài Node.js >= 20, tải bundle thất bại, hoặc cú pháp Mermaid không hợp lệ. Các hook mermaid của pre-commit chạy ở chế độ strict với Node.js 22 do pre-commit cung cấp, nên chúng sẽ báo lỗi thay vì bỏ qua. Bản thân EPUB build không chạy trong pre-commit — nó chỉ chạy trong CI.\n\n5. **Đây là tutorial, không phải thư viện** — Khi thêm nội dung, tập trung vào giải thích rõ ràng, ví dụ copy-paste, và sơ đồ trực quan. Giá trị nằm ở việc dạy các khái niệm, không cung cấp code có thể tái sử dụng.\n\n## Commit Conventions\n\nTuân theo format conventional commit:\n- `feat(slash-commands): Add API documentation generator`\n- `docs(memory): Improve personal preferences example`\n- `fix(README): Correct table of contents link`\n- `refactor(hooks): Simplify hook configuration examples`\n\nScope nên khớp với tên thư mục khi áp dụng.\n\n<!-- File: .claude/skills/lesson-quiz/README.md (Tokens: ~519 | Category: anthropic-skill) -->\n# Lesson Quiz\n\n> Interactive quiz that tests your understanding of a specific Claude Code lesson with 10 questions, per-question feedback, and targeted review guidance.\n\n## Highlights\n\n- 10 questions per lesson mixing conceptual understanding and practical application\n- Covers all 10 lessons (01-Slash Commands through 10-CLI)\n- Three timing modes: pre-test, progress check, or mastery verification\n- Per-question feedback with correct answers and explanations\n- Targeted review recommendations pointing to specific lesson sections\n- 100-question bank across all lessons in `references/question-bank.md`\n\n## When to Use\n\n| Say this... | Skill will... |\n|---|---|\n| \"quiz me on hooks\" | Run a 10-question quiz on Lesson 06: Hooks |\n| \"lesson quiz 03\" | Test your knowledge of Lesson 03: Skills |\n| \"do I understand MCP\" | Assess your understanding of Lesson 05: MCP |\n| \"practice quiz\" | Let you pick a lesson, then quiz you |\n\n## How It Works\n\n```mermaid\ngraph TD\n    A[\"Select lesson\"] --> B[\"Choose timing: pre/during/after\"]\n    B --> C[\"Answer 10 questions in 5 rounds\"]\n    C --> D[\"Score and review feedback\"]\n    style A fill:#4CAF50,color:#fff\n    style D fill:#2196F3,color:#fff\n```\n\n## Usage\n\n```\n/lesson-quiz [lesson-name-or-number]\n```\n\nExamples:\n```\n/lesson-quiz hooks\n/lesson-quiz 03\n/lesson-quiz advanced-features\n/lesson-quiz           # (prompts for lesson selection)\n```\n\n## Output\n\n### Score Report\n- Total score out of 10 with grade (Mastered / Proficient / Developing / Beginning)\n- Breakdown by question category (conceptual vs. practical)\n\n### Per-Question Feedback\nFor each incorrect answer:\n- What you answered vs. the correct answer\n- Explanation of why the correct answer is right\n- Specific section of the lesson to review\n\n### Timing-Aware Guidance\n- **Pre-test**: Establishes baseline, highlights areas to focus on while studying\n- **During**: Identifies what you've grasped and what to revisit\n- **After**: Confirms mastery or pinpoints remaining gaps\n\n## Resources\n\n| Path | Description |\n|---|---|\n| `references/question-bank.md` | 100 pre-written questions (10 per lesson) with answers, explanations, and review pointers |\n\n<!-- File: .claude/skills/lesson-quiz/references/question-bank.md (Tokens: ~12386 | Category: anthropic-skill) -->\n# Lesson Quiz — Question Bank\n\n10 questions per lesson. Each question has: category, question text, options (3-4), correct answer, explanation, and review section.\n\n---\n\n## Lesson 01: Slash Commands\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the four types of slash commands in Claude Code?\n- **Options**: A) Built-in, skills, plugin commands, MCP prompts | B) Built-in, custom, hook commands, API prompts | C) System, user, plugin, terminal commands | D) Core, extension, macro, script commands\n- **Correct**: A\n- **Explanation**: Claude Code has built-in commands (like /help, /compact), skills (SKILL.md files), plugin commands (namespaced plugin-name:command), and MCP prompts (/mcp__server__prompt).\n- **Review**: Overview section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you pass all user-provided arguments to a skill?\n- **Options**: A) Use `${args}` | B) Use `$ARGUMENTS` | C) Use `$@` | D) Use `$INPUT`\n- **Correct**: B\n- **Explanation**: `$ARGUMENTS` captures all text after the command name. For positional args, use `$0`, `$1`, etc.\n- **Review**: Arguments\n\n### Q3\n- **Category**: conceptual\n- **Question**: When both a skill (.claude/skills/name/SKILL.md) and a legacy command (.claude/commands/name.md) exist with the same name, which takes priority?\n- **Options**: A) The legacy command | B) The skill | C) Whichever was created first | D) Claude asks the user to choose\n- **Correct**: B\n- **Explanation**: Skills take precedence over legacy commands with the same name. The skill system supersedes the older command system.\n- **Review**: Skill vs Command Conflict section\n\n### Q4\n- **Category**: practical\n- **Question**: How do you inject live shell output into a skill's prompt?\n- **Options**: A) Use `$(command)` syntax | B) Use `!`command`` (backtick with !) syntax | C) Use `@shell:command` syntax | D) Use `{command}` syntax\n- **Correct**: B\n- **Explanation**: The `!`command`` syntax runs a shell command and injects its output into the skill prompt before Claude sees it.\n- **Review**: Dynamic Context with Shell Commands\n\n### Q5\n- **Category**: conceptual\n- **Question**: What does `disable-model-invocation: true` do in a skill's frontmatter?\n- **Options**: A) Prevents the skill from running entirely | B) Allows only the user to invoke it (Claude cannot auto-invoke) | C) Hides it from the /help menu | D) Disables the skill's AI processing\n- **Correct**: B\n- **Explanation**: `disable-model-invocation: true` means only the user can trigger the command via `/command-name`. Claude will never auto-invoke it, useful for skills with side effects like deployments.\n- **Review**: Frontmatter Reference section\n\n### Q6\n- **Category**: practical\n- **Question**: You want to create a skill that only Claude can invoke automatically (hidden from the user's / menu). Which frontmatter field do you set?\n- **Options**: A) `disable-model-invocation: true` | B) `user-invocable: false` | C) `hidden: true` | D) `auto-only: true`\n- **Correct**: B\n- **Explanation**: `user-invocable: false` hides the skill from the user's slash menu but allows Claude to invoke it automatically based on context.\n- **Review**: Frontmatter Reference section\n\n### Q7\n- **Category**: practical\n- **Question**: What is the correct directory structure for a new custom skill called \"deploy\"?\n- **Options**: A) `.claude/commands/deploy.md` | B) `.claude/skills/deploy/SKILL.md` | C) `.claude/skills/deploy.md` | D) `.claude/deploy/SKILL.md`\n- **Correct**: B\n- **Explanation**: Skills live in a directory under `.claude/skills/` with a `SKILL.md` file inside. The directory name matches the command name.\n- **Review**: Creating a Custom Command as a Skill section\n\n### Q8\n- **Category**: conceptual\n- **Question**: How do plugin commands avoid name conflicts with user commands?\n- **Options**: A) They use a `plugin-name:command-name` namespace | B) They have a special .plugin extension | C) They are prefixed with `p/` | D) They override user commands automatically\n- **Correct**: A\n- **Explanation**: Plugin commands use a namespace like `pr-review:check-security` to avoid conflicts with standalone user commands.\n- **Review**: Plugin commands section\n\n### Q9\n- **Category**: practical\n- **Question**: You want a skill to use certain tools without asking for permission each time. Which frontmatter field do you add?\n- **Options**: A) `tools: [Read, Grep]` | B) `allowed-tools: [Read, Grep]` | C) `permissions: [Read, Grep]` | D) `restrict-tools: [Read, Grep]`\n- **Correct**: B\n- **Explanation**: `allowed-tools` pre-approves the listed tools during the turn that invokes the skill, so Claude can use them without a permission prompt; the grant clears when you send your next message. It does not restrict which tools are available — to remove tools while a skill is active, use `disallowed-tools`.\n- **Review**: Frontmatter Reference\n\n### Q10\n- **Category**: conceptual\n- **Question**: What is the `@file` syntax used for in a skill?\n- **Options**: A) Importing another skill | B) Referencing a file to include its content in the prompt | C) Creating a symlink | D) Setting file permissions\n- **Correct**: B\n- **Explanation**: The `@path/to/file` syntax in a skill includes the referenced file's content into the prompt, allowing skills to pull in templates or context files.\n- **Review**: File references section\n\n---\n\n## Lesson 02: Memory\n\n### Q1\n- **Category**: conceptual\n- **Question**: How do CLAUDE.md memory files relate to each other, and what has the highest authority?\n- **Options**: A) Higher tiers override lower tiers entirely | B) They are concatenated into context; Managed Policy loads first and cannot be excluded | C) The most recently modified file wins | D) Project Memory has the highest priority\n- **Correct**: B\n- **Explanation**: CLAUDE.md files are concatenated into context rather than overriding each other — load order sets position in context, not precedence. Managed Policy (admin-managed) loads first and cannot be excluded by individual settings. Auto memory is a separate mechanism.\n- **Review**: Memory hierarchy section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you quickly add a new rule to memory during a conversation?\n- **Options**: A) Use the `/memory` slash command or ask conversationally | B) Prefix your message with `#` (e.g., `# always use TypeScript`) | C) Type `/rule \"rule text\"` | D) Use `@add-memory \"rule text\"`\n- **Correct**: A\n- **Explanation**: Use `/memory` to open your CLAUDE.md and auto memory files in your editor, or ask Claude conversationally. Asking Claude to \"remember\" something (e.g., \"remember that we always use TypeScript strict mode\") saves it to auto memory; to put it in CLAUDE.md instead, say \"add this to CLAUDE.md\". The `#` prefix was discontinued and no longer works.\n- **Review**: Quick memory updates section in README\n\n### Q3\n- **Category**: conceptual\n- **Question**: What is the maximum depth for `@path/to/file` imports in CLAUDE.md?\n- **Options**: A) 3 levels deep | B) 4 levels deep | C) 10 levels deep | D) Unlimited\n- **Correct**: B\n- **Explanation**: The `@path` import syntax supports recursive imports up to a maximum depth of 4 hops to prevent infinite loops.\n- **Review**: The /memory Command section (Import features)\n\n### Q4\n- **Category**: practical\n- **Question**: How do you scope a rule file to only apply to files in `src/api/`?\n- **Options**: A) Put the rule in `src/api/CLAUDE.md` | B) Add `paths: src/api/**` YAML frontmatter to a `.claude/rules/*.md` file | C) Name the file `.claude/rules/api.md` | D) Use `@scope: src/api` in the rule file\n- **Correct**: B\n- **Explanation**: Files in `.claude/rules/` support a `paths:` frontmatter field with glob patterns to scope rules to specific directories.\n- **Review**: Path-specific rules section\n\n### Q5\n- **Category**: conceptual\n- **Question**: How many lines of Auto Memory's MEMORY.md are loaded at session start?\n- **Options**: A) All lines | B) First 100 lines | C) First 200 lines | D) First 500 lines\n- **Correct**: C\n- **Explanation**: The first 200 lines of MEMORY.md — or the first 25 KB, whichever comes first — are auto-loaded into context at session start. Topic files referenced from MEMORY.md are loaded on demand.\n- **Review**: Auto Memory section\n\n### Q6\n- **Category**: practical\n- **Question**: You want personal project preferences that are NOT committed to git. Which file should you use?\n- **Options**: A) `~/.claude/CLAUDE.md` | B) `CLAUDE.local.md` | C) `.claude/rules/personal.md` | D) `.claude/memory/personal.md`\n- **Correct**: B\n- **Explanation**: `CLAUDE.local.md` in the project root is for personal project-specific preferences. It should be git-ignored.\n- **Review**: Memory Locations Table\n\n### Q7\n- **Category**: conceptual\n- **Question**: What does the `/init` command do?\n- **Options**: A) Initializes a new Claude Code project from scratch | B) Generates a template CLAUDE.md based on your project structure | C) Resets all memory to defaults | D) Creates a new session\n- **Correct**: B\n- **Explanation**: `/init` analyzes your project and generates a template CLAUDE.md with suggested rules and standards. Re-running it on an existing CLAUDE.md suggests improvements.\n- **Review**: /init command section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you disable Auto Memory completely?\n- **Options**: A) Delete the ~/.claude/projects directory | B) Set `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1` | C) Add `auto-memory: false` to CLAUDE.md | D) Use `/memory disable auto`\n- **Correct**: B\n- **Explanation**: Setting `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1` disables auto memory. Value `0` forces it on. Unset = default on.\n- **Review**: Turning Auto Memory On or Off\n\n### Q9\n- **Category**: conceptual\n- **Question**: Can a lower-priority memory tier override rules from a higher-priority tier?\n- **Options**: A) Yes, the most recent rule always wins | B) No — CLAUDE.md files are concatenated into context, not overridden; load order sets position, not precedence | C) Yes, if the lower tier uses the `!important` flag | D) It depends on the rule type\n- **Correct**: B\n- **Explanation**: CLAUDE.md files (user, project, local, rules) are concatenated into context rather than overriding each other — later files appear later in context, not \"instead of\" earlier ones. Only Managed Policy is special: it loads first and cannot be excluded by individual settings. Auto memory is a separate mechanism, not part of the concatenation order.\n- **Review**: Memory hierarchy section\n\n### Q10\n- **Category**: practical\n- **Question**: You work across two repositories and want Claude to load CLAUDE.md from both. What flag do you use?\n- **Options**: A) `claude --multi-repo /path/to/other` | B) `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 claude --add-dir /path/to/other` | C) `claude --add-dir /path/to/other` on its own | D) `claude --include /path/to/other`\n- **Correct**: B\n- **Explanation**: `--add-dir` on its own only grants file access to the extra directory — its CLAUDE.md is not loaded by default. Setting `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1` makes Claude Code also load CLAUDE.md from directories added with `--add-dir`.\n- **Review**: Additional directories section\n\n---\n\n## Lesson 03: Skills\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the 3 levels of progressive disclosure in the skill system?\n- **Options**: A) Metadata, instructions, resources | B) Name, body, attachments | C) Header, content, scripts | D) Summary, details, data\n- **Correct**: A\n- **Explanation**: Level 1: Metadata (~100 tokens, always loaded), Level 2: SKILL.md body (<5k tokens, loaded on trigger), Level 3: Bundled resources (scripts/references/assets, loaded on demand).\n- **Review**: How Skills Work: Progressive Disclosure\n\n### Q2\n- **Category**: practical\n- **Question**: What is the most important factor for a skill to be auto-invoked by Claude?\n- **Options**: A) The skill's file name | B) The `description` field in frontmatter with when-to-use keywords | C) The skill's directory location | D) The `auto-invoke: true` frontmatter field\n- **Correct**: B\n- **Explanation**: Claude decides whether to auto-invoke a skill based on its `description` (plus optional `when_to_use`). It must include specific trigger phrases and scenarios.\n- **Review**: Controlling Skill Invocation section\n\n### Q3\n- **Category**: conceptual\n- **Question**: What is the maximum recommended length for a SKILL.md file?\n- **Options**: A) 100 lines | B) 250 lines | C) 500 lines | D) 1000 lines\n- **Correct**: C\n- **Explanation**: SKILL.md should be kept under 500 lines. Larger reference material belongs in `references/` subdirectory files.\n- **Review**: Keep SKILL.md Under 500 Lines section\n\n### Q4\n- **Category**: practical\n- **Question**: How do you make a skill run in an isolated subagent with its own context?\n- **Options**: A) Set `isolation: true` in frontmatter | B) Set `context: fork` with an `agent` field in frontmatter | C) Set `subagent: true` in frontmatter | D) Put the skill in `.claude/agents/`\n- **Correct**: B\n- **Explanation**: `context: fork` runs the skill in a separate context, and the `agent` field specifies which agent type (e.g., `Explore`, `Plan`, custom agent) to use.\n- **Review**: Running skills in subagents section\n\n### Q5\n- **Category**: conceptual\n- **Question**: What is the approximate context budget allocated to skill metadata (Level 1)?\n- **Options**: A) 0.5% of context window | B) 1% of context window | C) 5% of context window | D) 10% of context window\n- **Correct**: B\n- **Explanation**: Skill metadata occupies about 1% of the context window (fallback: 8,000 characters). This is configurable with `SLASH_COMMAND_TOOL_CHAR_BUDGET` or the `skillListingBudgetFraction` setting.\n- **Review**: the \"Description budget\" paragraph under Automatic Discovery\n\n### Q6\n- **Category**: practical\n- **Question**: A skill needs to reference a large API specification. Where should you put it?\n- **Options**: A) Inline in SKILL.md | B) In a `references/api-spec.md` file inside the skill directory | C) In the project's CLAUDE.md | D) In a separate `.claude/rules/` file\n- **Correct**: B\n- **Explanation**: Large reference material belongs in the `references/` subdirectory. Claude loads Level 3 resources on demand, keeping SKILL.md lean.\n- **Review**: Supporting files structure section\n\n### Q7\n- **Category**: conceptual\n- **Question**: What is the difference between Reference Content and Task Content in a skill?\n- **Options**: A) Reference is read-only, Task is read-write | B) Reference adds knowledge to context, Task provides step-by-step instructions | C) Reference is for documentation, Task is for code | D) There is no difference\n- **Correct**: B\n- **Explanation**: Reference Content adds domain knowledge to Claude's context (e.g., brand guidelines). Task Content provides actionable step-by-step instructions for a workflow.\n- **Review**: Skill content types section\n\n### Q8\n- **Category**: practical\n- **Question**: What characters are allowed in the `name` field of a skill's frontmatter for a skill you plan to share via claude.ai or the Skills API (Agent Skills spec)?\n- **Options**: A) Any characters | B) Lowercase letters, numbers, and hyphens only (max 64 chars) | C) Letters and underscores | D) Alphanumeric only\n- **Correct**: B\n- **Explanation**: The name must be kebab-case (lowercase, hyphens), max 64 characters. `name` is itself optional — if omitted it defaults to the skill's directory name — but when supplied it must follow these rules. In Claude Code, the `anthropic-skills` name and namespace are reserved for skills synced from claude.ai, so a skill with that name doesn't load; the broader ban on \"anthropic\" or \"claude\" applies to claude.ai skill uploads and the Skills API. Claude Code itself (v2.1.299) refuses only names that contain hidden, direction-changing or blank-like characters, `<` or `>`, or that are over 256 characters.\n- **Review**: SKILL.md format section\n\n### Q9\n- **Category**: conceptual\n- **Question**: In what order does Claude search for skills?\n- **Options**: A) User > Project > Enterprise | B) Enterprise > Personal > Project (plugin uses namespace) | C) Project > User > Enterprise | D) Alphabetical order\n- **Correct**: B\n- **Explanation**: Priority order is: Enterprise > Personal > Project. Plugin skills use a namespace (plugin-name:skill) so they don't conflict.\n- **Review**: Skill Types & Locations\n\n### Q10\n- **Category**: practical\n- **Question**: How do you prevent Claude from automatically invoking a skill while still allowing users to use it manually?\n- **Options**: A) Set `user-invocable: false` | B) Set `disable-model-invocation: true` | C) Remove the description field | D) Set `auto-invoke: false`\n- **Correct**: B\n- **Explanation**: `disable-model-invocation: true` prevents Claude from auto-invoking but keeps the skill available in the user's `/` menu for manual use.\n- **Review**: Controlling Skill Invocation\n\n---\n\n## Lesson 04: Subagents\n\n### Q1\n- **Category**: conceptual\n- **Question**: What is the main advantage of subagents over inline conversation?\n- **Options**: A) They are faster | B) They operate in a separate, clean context window preventing context pollution | C) They can use more tools | D) They have better error handling\n- **Correct**: B\n- **Explanation**: Subagents get a fresh context window, receiving only what the main agent passes. This prevents the main conversation from being polluted with task-specific details.\n- **Review**: Overview section\n\n### Q2\n- **Category**: practical\n- **Question**: What is the priority order for agent definitions?\n- **Options**: A) Project > User > CLI | B) CLI > Project > User | C) User > Project > CLI | D) They all have equal priority\n- **Correct**: B\n- **Explanation**: Full order is managed settings > `--agents` flag > project (`.claude/agents/`) > user (`~/.claude/agents/`) > plugin. Of the options listed, CLI > Project > User is the correct relative ordering.\n- **Review**: File locations section\n\n### Q3\n- **Category**: conceptual\n- **Question**: Which built-in subagent is optimized for read-only codebase exploration?\n- **Options**: A) general-purpose | B) Plan | C) Explore | D) Bash\n- **Correct**: C\n- **Explanation**: The Explore subagent is the read-only codebase search agent. Since v2.1.198 it inherits the session model, capped at Opus on the Claude API — `model: haiku` is opt-in, not the default. It supports three thoroughness levels: quick, medium, very thorough.\n- **Review**: Built-in subagents section\n\n### Q4\n- **Category**: practical\n- **Question**: How do you restrict which subagents a coordinator agent can spawn?\n- **Options**: A) Use `allowed-agents:` field | B) Use `Agent(agent_name)` syntax in the `tools` field | C) Set `spawn-limit: 2` | D) Use `restrict-agents: [name1, name2]`\n- **Correct**: B\n- **Explanation**: For an agent running as the main thread with `claude --agent`, `tools: Agent(worker, researcher)` creates an allowlist — it can only spawn subagents named \"worker\" or \"researcher\". `Task(...)` still works as an alias (the Task tool was renamed Agent in v2.1.63).\n- **Review**: Restrict spawnable subagents section\n\n### Q5\n- **Category**: conceptual\n- **Question**: What does `isolation: worktree` do for a subagent?\n- **Options**: A) Runs the agent in a Docker container | B) Gives the agent its own git worktree so changes don't affect the main tree | C) Prevents the agent from reading any files | D) Runs the agent in a sandbox\n- **Correct**: B\n- **Explanation**: Worktree isolation creates a separate git worktree. If the agent makes no changes, it auto-cleans up. If changes are made, the worktree path and branch are returned.\n- **Review**: Worktree isolation section\n\n### Q6\n- **Category**: practical\n- **Question**: How do you force a subagent to always run in the background (never inline)?\n- **Options**: A) Set `background: true` in the agent config | B) Use `async: true` in the agent config | C) Press Ctrl+D after starting it | D) Use `--background` CLI flag\n- **Correct**: A\n- **Explanation**: `background: true` in the agent configuration makes the subagent always run as a background task and prevents it from running inline. Subagents Claude spawns from the main conversation already run in the background by default (v2.1.198; always, in the desktop app and VS Code, since v2.1.302), but a subagent's own nested Agent calls run in the foreground by default in `claude -p`, the Agent SDK, the desktop app and VS Code. Users can also press Ctrl+B to send a running foreground task to the background.\n- **Review**: Background subagents section\n\n### Q7\n- **Category**: conceptual\n- **Question**: What does the `memory` field with scope `project` do for a subagent?\n- **Options**: A) Gives read access to the project CLAUDE.md | B) Creates a persistent memory directory scoped to the current project | C) Shares the main agent's conversation history | D) Loads the project's git history\n- **Correct**: B\n- **Explanation**: The `memory` field creates a persistent directory for the subagent. Scope `project` means the memory is tied to the current project. The first 200 lines or 25KB of the agent's MEMORY.md, whichever comes first, auto-load.\n- **Review**: Persistent memory section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you include a phrase in a subagent's description to encourage Claude to automatically delegate tasks to it?\n- **Options**: A) Add \"priority: high\" | B) Include \"use PROACTIVELY\" or \"MUST BE USED\" in the description | C) Set `auto-delegate: true` | D) Add \"trigger: always\"\n- **Correct**: B\n- **Explanation**: Including phrases like \"use PROACTIVELY\" or \"MUST BE USED\" in the description strongly encourages Claude to automatically delegate matching tasks.\n- **Review**: Automatic delegation section\n\n### Q9\n- **Category**: conceptual\n- **Question**: What are the valid `permissionMode` values for a subagent?\n- **Options**: A) read, write, admin | B) manual, acceptEdits, bypassPermissions, plan, dontAsk, auto | C) safe, normal, dangerous | D) restricted, standard, elevated\n- **Correct**: B\n- **Explanation**: Subagents support six permission modes: manual (runs reads without asking and prompts for everything else — shown as Manual; its config value is `default`, and manual is accepted as an alias since v2.1.200), acceptEdits (auto-accepts file edits), bypassPermissions (skips all), plan (read-only), dontAsk (auto-denies unless pre-approved), auto (background classifier decides).\n- **Review**: Configuration fields section\n\n### Q10\n- **Category**: practical\n- **Question**: How do you resume a subagent that returned an agentId from a previous run?\n- **Options**: A) Use `/resume agent-id` | B) Ask Claude to resume it — Claude messages the subagent with the SendMessage tool, using its agent ID or name | C) Use `claude -r agent-id` | D) Subagents cannot be resumed\n- **Correct**: B\n- **Explanation**: Each invocation starts a new instance. To continue earlier work, ask Claude to resume the subagent: Claude uses the SendMessage tool with the agent's ID or name, and the subagent resumes with its full conversation history. The built-in Explore and Plan agents are one-shot and can't be resumed.\n- **Review**: Resumable agents section\n\n---\n\n## Lesson 05: MCP\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the four MCP transport protocols, and which is recommended?\n- **Options**: A) HTTP (recommended), Stdio, SSE (deprecated), WebSocket (`ws`) | B) REST (recommended), GraphQL, gRPC, Thrift | C) TCP, UDP, HTTP | D) Stdio (recommended), HTTP, SSE\n- **Correct**: A\n- **Explanation**: HTTP is recommended for remote servers. Stdio is for local processes (most common currently). SSE is deprecated but still supported. WebSocket (`type: \"ws\"`) holds a persistent bidirectional connection for servers that push events unprompted; it is added with `claude mcp add-json` or `.mcp.json`, not with `--transport`, and supports header-only auth.\n- **Review**: MCP Installation Methods section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you add a GitHub MCP server via CLI?\n- **Options**: A) `claude mcp install github` | B) `claude mcp add --transport http github https://api.githubcopilot.com/mcp/` | C) `claude plugin add github-mcp` | D) `claude connect github`\n- **Correct**: B\n- **Explanation**: Use `claude mcp add` with the `--transport` flag, a name, and the server URL. GitHub's remote server also needs an auth header: `claude mcp add --transport http github https://api.githubcopilot.com/mcp/ --header \"Authorization: Bearer YOUR_GITHUB_PAT\"`.\n- **Review**: MCP configuration management section\n\n### Q3\n- **Category**: conceptual\n- **Question**: With `ENABLE_TOOL_SEARCH=auto`, what happens when MCP tool definitions reach 10% of the context window?\n- **Options**: A) They are truncated | B) Tool search kicks in: MCP tools are deferred and discovered on demand | C) Claude shows an error | D) Extra tools are disabled\n- **Correct**: B\n- **Explanation**: By default (`ENABLE_TOOL_SEARCH` unset) tool search is already on and all MCP tools are deferred. `auto` is threshold mode: tools load upfront until their definitions reach 10% of the context window, then all are deferred (`auto:N` sets a custom percentage). Tool search needs a model that supports `tool_reference` blocks: Opus 4, Sonnet 4, Haiku 4.5 and later.\n- **Review**: MCP Tool Search section\n\n### Q4\n- **Category**: practical\n- **Question**: How do you use environment variable fallbacks in MCP config?\n- **Options**: A) `${VAR || \"default\"}` | B) `${VAR:-default}` | C) `${VAR:default}` | D) `${VAR ? \"default\"}`\n- **Correct**: B\n- **Explanation**: `${VAR:-default}` provides a fallback value if the environment variable is not set. If `VAR` is unset and has no default, the server still loads with the literal `${VAR}` text, and `claude mcp list` and `/mcp` warn about the missing variable.\n- **Review**: Environment variable expansion section\n\n### Q5\n- **Category**: conceptual\n- **Question**: What is the difference between MCP and Memory for data access?\n- **Options**: A) MCP is faster, Memory is slower | B) MCP is for live/changing external data, Memory is for persistent/static preferences | C) MCP is for code, Memory is for text | D) They are interchangeable\n- **Correct**: B\n- **Explanation**: MCP connects to live, changing external data sources (APIs, databases). Memory stores persistent, static project context and preferences.\n- **Review**: MCP vs Memory section\n\n### Q6\n- **Category**: practical\n- **Question**: What happens when a team member first encounters a project-scoped `.mcp.json`?\n- **Options**: A) It loads automatically | B) They get an approval prompt to trust the project's MCP servers | C) It's ignored unless they opt in via settings | D) Claude asks the admin to approve\n- **Correct**: B\n- **Explanation**: Project-scoped `.mcp.json` triggers a security approval prompt on each team member's first use. This is intentional — it prevents untrusted MCP servers.\n- **Review**: MCP Scopes section\n\n### Q7\n- **Category**: conceptual\n- **Question**: What does `claude mcp serve` do?\n- **Options**: A) Starts an MCP server dashboard | B) Makes Claude Code itself act as an MCP server for other applications | C) Serves MCP documentation | D) Tests MCP server connections\n- **Correct**: B\n- **Explanation**: `claude mcp serve` turns Claude Code into an MCP server, enabling multi-agent orchestration where one Claude instance can be controlled by another.\n- **Review**: Claude as MCP Server section\n\n### Q8\n- **Category**: practical\n- **Question**: What is the default maximum output size for MCP tools?\n- **Options**: A) 5,000 tokens | B) 10,000 tokens | C) 25,000 tokens | D) 50,000 tokens\n- **Correct**: C\n- **Explanation**: Default max is 25,000 tokens (`MAX_MCP_OUTPUT_TOKENS`). A warning appears at 10k tokens. Text results over 50,000 characters are saved to a file.\n- **Review**: MCP Output Limits section\n\n### Q9\n- **Category**: conceptual\n- **Question**: When both `allowedMcpServers` and `deniedMcpServers` match a server in managed config, which wins?\n- **Options**: A) Allowed wins | B) Denied wins | C) The last one configured wins | D) Both are applied independently\n- **Correct**: B\n- **Explanation**: In managed MCP configuration, deny rules always take precedence over allow rules.\n- **Review**: Managed MCP Configuration section\n\n### Q10\n- **Category**: practical\n- **Question**: How do you reference an MCP resource in a conversation?\n- **Options**: A) Use `/mcp resource-name` | B) Use `@server-name:protocol://resource/path` mention syntax | C) Use `mcp.get(\"resource\")` | D) Resources are auto-loaded\n- **Correct**: B\n- **Explanation**: MCP resources are accessed via `@server-name:protocol://resource/path` mention syntax in conversation.\n- **Review**: MCP Resources section\n\n---\n\n## Lesson 06: Hooks\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the five types of hooks in Claude Code?\n- **Options**: A) Pre, Post, Error, Filter, and Transform hooks | B) Command, HTTP, MCP Tool, Prompt, and Agent hooks | C) Before, After, Around, Through, and Beside hooks | D) Input, Output, Filter, Transform, and Validate hooks\n- **Correct**: B\n- **Explanation**: Command hooks run shell scripts, HTTP hooks call webhook endpoints, MCP Tool hooks invoke an MCP tool, Prompt hooks use single-turn LLM evaluation, and Agent hooks use subagent-based verification. Agent hooks are experimental and may change.\n- **Review**: Hook types section\n\n### Q2\n- **Category**: practical\n- **Question**: A hook script exits with code 2. What happens?\n- **Options**: A) Non-blocking warning shown | B) Blocking error — stderr is shown as an error to Claude, tool use is prevented | C) Hook is retried | D) Session ends\n- **Correct**: B\n- **Explanation**: Exit code 0 = success/continue, exit code 2 = blocking error (stderr shown as error), any other non-zero = non-blocking error (a `<hook name> hook error` notice with the first line of stderr appears in the transcript, and the action goes ahead). Since v2.1.295, setting `\"onFailure\": \"block\"` on a command or HTTP hook makes such failures block like exit 2.\n- **Review**: Exit codes section\n\n### Q3\n- **Category**: conceptual\n- **Question**: What JSON fields does a PreToolUse hook receive on stdin?\n- **Options**: A) `tool_name` and `tool_output` | B) `session_id`, `tool_name`, `tool_input`, `hook_event_name`, `cwd`, and more | C) Only `tool_name` | D) The full conversation history\n- **Correct**: B\n- **Explanation**: Hooks receive a JSON object on stdin with: session_id, transcript_path, hook_event_name, tool_name, tool_input, tool_use_id, cwd, and permission_mode.\n- **Review**: JSON Input (via stdin)\n\n### Q4\n- **Category**: practical\n- **Question**: How can a PreToolUse hook modify the tool's input parameters before execution?\n- **Options**: A) Return modified JSON on stderr | B) Return JSON with `updatedInput` field on stdout (exit code 0) | C) Write to a temp file | D) Hooks cannot modify inputs\n- **Correct**: B\n- **Explanation**: A PreToolUse hook can output JSON with `\"updatedInput\": {...}` on stdout (with exit 0) to modify the tool's parameters before Claude uses them. `updatedInput` goes under `hookSpecificOutput` and replaces the whole input object; since v2.1.300 it is validated like Claude's own input, so unknown keys are dropped and input the tool rejects denies the call.\n- **Review**: PreToolUse section\n\n### Q5\n- **Category**: conceptual\n- **Question**: Which hook event supports `CLAUDE_ENV_FILE` for persisting environment variables into the session?\n- **Options**: A) PreToolUse | B) UserPromptSubmit | C) SessionStart | D) All events\n- **Correct**: C\n- **Explanation**: `CLAUDE_ENV_FILE` is available to SessionStart, Setup, CwdChanged, and FileChanged hooks, which use it to persist environment variables into the session. Of the options listed, SessionStart is the one that supports it — PreToolUse and UserPromptSubmit do not, and it is not available to all events.\n- **Review**: SessionStart section\n\n### Q6\n- **Category**: practical\n- **Question**: You want a hook that only runs once when a skill is first loaded, not on every tool call. What field do you add?\n- **Options**: A) `run-once: true` | B) `once: true` on a hook in the skill's frontmatter | C) `single: true` | D) `max-runs: 1`\n- **Correct**: B\n- **Explanation**: Hooks declared in a skill's frontmatter support `once: true` — Claude Code removes the hook after its first successful run (a run that fails, blocks, or times out leaves it in place). `once` is honored only in skill frontmatter.\n- **Review**: Component-scoped hooks section\n\n### Q7\n- **Category**: conceptual\n- **Question**: A Stop hook is defined in a subagent's frontmatter. What does it automatically convert to?\n- **Options**: A) A PostToolUse hook | B) A SubagentStop hook | C) A SessionEnd hook | D) It stays as a Stop hook\n- **Correct**: B\n- **Explanation**: When a Stop hook is placed in a subagent's frontmatter, it auto-converts to SubagentStop so it runs when that specific subagent finishes.\n- **Review**: Component-scoped hooks section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you match a hook to all MCP tools from a specific server?\n- **Options**: A) `matcher: \"mcp_github\"` | B) `matcher: \"mcp__github__.*\"` (regex pattern) | C) `matcher: \"mcp:github:*\"` | D) `matcher: \"github-mcp\"`\n- **Correct**: B\n- **Explanation**: Use regex patterns for matchers. MCP tools follow the `mcp__server__tool` naming convention, so `mcp__github__.*` matches all GitHub MCP tools.\n- **Review**: Matcher patterns section\n\n### Q9\n- **Category**: conceptual\n- **Question**: How many hook events does Claude Code support in total?\n- **Options**: A) 16 | B) 25 | C) 33 | D) 40\n- **Correct**: C\n- **Explanation**: Claude Code supports 33 hook events. They fall into four groups: session lifecycle (`SessionStart`, `Setup`, `SessionEnd`), prompt and message handling (`UserPromptSubmit`, `UserPromptExpansion`, `MessageDisplay`), tool use and permissions (`PreToolUse`, `PostToolUse`, `PermissionRequest`, …), and agent, task, and environment coordination (`SubagentStart`, `TaskCreated`, `CwdChanged`, `WorktreeCreate`, `PreModelSwitch`, `PostModelSwitch`, …).\n- **Review**: Hook events table\n\n### Q10\n- **Category**: practical\n- **Question**: You want to debug why a hook isn't firing. What's the best approach?\n- **Options**: A) Add print statements to the hook script | B) Use the `--debug` flag and `Ctrl+O` to open the transcript viewer | C) Check the system log | D) Hooks don't have debugging tools\n- **Correct**: B\n- **Explanation**: `claude --debug` (or `--debug-file <path>`, or `/debug` mid-session) logs hook runs to the debug log, including which hooks fire, their inputs, and outputs; `Ctrl+O` opens the transcript view to see hook outcomes.\n- **Review**: Debugging section\n\n---\n\n## Lesson 07: Plugins\n\n### Q1\n- **Category**: conceptual\n- **Question**: What is the core manifest file for a plugin and where does it live?\n- **Options**: A) `plugin.yaml` in the root directory | B) `.claude-plugin/plugin.json` | C) `package.json` with a \"claude\" key | D) `.claude/plugin.md`\n- **Correct**: B\n- **Explanation**: The plugin manifest lives at `.claude-plugin/plugin.json`. The manifest is optional; when present, `name` (kebab-case identifier) is its only required key; `description`, `version`, `author`, `homepage`, `repository` and `license` are optional metadata.\n- **Review**: Plugin definition structure section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you load a plugin from a local directory so you can try it in a session before publishing?\n- **Options**: A) Use `/plugin test ./my-plugin` | B) Use `claude --plugin-dir ./my-plugin` | C) Use `claude plugin validate ./my-plugin` | D) Copy it to ~/.claude/plugins/\n- **Correct**: B\n- **Explanation**: The `--plugin-dir` flag loads a plugin from a local directory for testing. It's repeatable for loading multiple plugins. `claude plugin validate ./my-plugin` checks the manifest and components but doesn't load the plugin into a session.\n- **Review**: Testing section\n\n### Q3\n- **Category**: conceptual\n- **Question**: What environment variable is available inside plugin hooks and MCP configs to reference the plugin's installation directory?\n- **Options**: A) `$PLUGIN_HOME` | B) `${CLAUDE_PLUGIN_ROOT}` | C) `$PLUGIN_DIR` | D) `${CLAUDE_PLUGIN_PATH}`\n- **Correct**: B\n- **Explanation**: `${CLAUDE_PLUGIN_ROOT}` resolves to the plugin's installed directory, enabling portable path references in hooks and MCP configs.\n- **Review**: Plugin-Provided MCP Servers section in Lesson 05 (MCP)\n\n### Q4\n- **Category**: practical\n- **Question**: A plugin has a command called \"check-security\" in the \"pr-review\" plugin. How does a user invoke it?\n- **Options**: A) `/check-security` | B) `/pr-review:check-security` | C) `/plugin pr-review check-security` | D) `/pr-review/check-security`\n- **Correct**: B\n- **Explanation**: Plugin commands use a `plugin-name:command-name` namespace to avoid conflicts with user commands and other plugins.\n- **Review**: Plugin Commands section in Lesson 01 (Slash Commands)\n\n### Q5\n- **Category**: conceptual\n- **Question**: Which components can a plugin bundle?\n- **Options**: A) Only commands and settings | B) Skills, agents, commands, hooks, MCP servers, LSP config, settings, templates, scripts | C) Only commands, hooks, and MCP servers | D) Only skills and agents\n- **Correct**: B\n- **Explanation**: Plugins can bundle: skills/, agents/, commands/, hooks/hooks.json, .mcp.json, .lsp.json, settings.json, templates/, scripts/, docs/, tests/. Note that `commands/` is legacy — official guidance is to use `skills/` for new plugins, though existing `commands/` directories keep working.\n- **Review**: Plugin Structure Example section\n\n### Q6\n- **Category**: practical\n- **Question**: How do you install a plugin from GitHub?\n- **Options**: A) `claude plugin add github:username/repo` | B) `/plugin marketplace add username/repo`, then `/plugin install plugin-name@marketplace-name` | C) `npm install @claude/username-repo` | D) `git clone` then `claude plugin register`\n- **Correct**: B\n- **Explanation**: Add the GitHub repo as a marketplace with `/plugin marketplace add username/repo`, then install with `/plugin install plugin-name@marketplace-name`. You can also do both in one step: `/plugin install plugin-name --marketplace username/repo` inside a session (v2.1.275+), or `claude plugin install plugin-name --marketplace username/repo` from your shell (v2.1.292+). There is no `github:` install form.\n- **Review**: Installation methods section\n\n### Q7\n- **Category**: conceptual\n- **Question**: What does the `settings.json` `agent` key do in a plugin?\n- **Options**: A) Specifies authentication credentials | B) Sets the main thread agent for the plugin | C) Lists available subagents | D) Configures agent permissions\n- **Correct**: B\n- **Explanation**: The `agent` key in a plugin's settings.json specifies which agent definition to use as the main thread agent when the plugin is active.\n- **Review**: Plugin Settings section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you manage plugin lifecycle (enable/disable/update)?\n- **Options**: A) Edit a config file manually | B) Use `/plugin enable`, `/plugin disable`, `claude plugin update <name>` | C) Use `claude plugin-manager` | D) Reinstall the plugin\n- **Correct**: B\n- **Explanation**: `/plugin enable` and `/plugin disable` are real slash commands. For updating an installed plugin, `claude plugin update <name>` is the form documented in the plugins reference, and the one Claude Code points you to when an update is available.\n- **Review**: Plugin CLI Commands section\n\n### Q9\n- **Category**: conceptual\n- **Question**: What is the main advantage of a plugin over standalone skills/hooks/MCP?\n- **Options**: A) Plugins are faster | B) Single-command install, versioned, marketplace distribution, bundles everything together | C) Plugins have more permissions | D) Plugins work offline\n- **Correct**: B\n- **Explanation**: Plugins package multiple components into one installable unit with versioning, marketplace distribution, and automatic updates — vs. manual setup of standalone components.\n- **Review**: Standalone vs Plugin Approach\n\n### Q10\n- **Category**: practical\n- **Question**: Where do plugin hooks configuration live within the plugin directory?\n- **Options**: A) `.claude-plugin/hooks.json` | B) `hooks/hooks.json` | C) `plugin.json` hooks section | D) `.claude/settings.json`\n- **Correct**: B\n- **Explanation**: Plugin hooks are configured in `hooks/hooks.json` within the plugin directory structure.\n- **Review**: Plugin Structure Example\n\n---\n\n## Lesson 08: Checkpoints\n\n### Q1\n- **Category**: conceptual\n- **Question**: What four things do checkpoints capture?\n- **Options**: A) Git commits, branches, tags, stashes | B) Messages, file modifications, tool usage history, session context | C) Code, tests, logs, configs | D) Inputs, outputs, errors, timing\n- **Correct**: B\n- **Explanation**: Checkpoints capture conversation messages, file modifications made by Claude's tools, tool usage history, and session context.\n- **Review**: Overview section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you access the checkpoint browser?\n- **Options**: A) Use `/restore` command | B) Press `Esc + Esc` (double-escape) or use `/rewind` | C) Use `/history` command | D) Press `Ctrl+Z`\n- **Correct**: B\n- **Explanation**: Double-escape (Esc+Esc) or the `/rewind` command opens the checkpoint browser to select a restore point.\n- **Review**: Accessing checkpoints section\n\n### Q3\n- **Category**: conceptual\n- **Question**: How many rewind options are available, and what are they?\n- **Options**: A) 3: Undo, Redo, Reset | B) 6: Restore code+conversation, Restore conversation, Restore code, Summarize from here, Summarize up to here, Never mind | C) 2: Full restore, Partial restore | D) 4: Code, Messages, Both, Cancel\n- **Correct**: B\n- **Explanation**: The 6 options are: Restore code and conversation (full rollback), Restore conversation only, Restore code only, Summarize from here (compress forward), Summarize up to here (compress backward), Never mind (cancel). The two summary options give bidirectional context compaction.\n- **Review**: Rewind options section\n\n### Q4\n- **Category**: practical\n- **Question**: You used `rm -rf temp/` via Bash in Claude Code, then want to rewind. Will the checkpoint restore those files?\n- **Options**: A) Yes, checkpoints capture everything | B) No, Bash filesystem operations (rm, mv, cp) are not tracked by checkpoints | C) Only if you used the Edit tool instead | D) Only if autoCheckpoint was enabled\n- **Correct**: B\n- **Explanation**: Checkpoints track file changes made by Claude's own Write/Edit tools in the main thread. Bash commands (rm, mv, cp), subagent edits (except a foreground `context: fork` skill), edits made outside Claude Code, and symlinked/hardlinked paths are all outside checkpoint tracking.\n- **Review**: Limitations section\n\n### Q5\n- **Category**: conceptual\n- **Question**: How long are checkpoints retained?\n- **Options**: A) Until session ends | B) 7 days | C) 30 days | D) Indefinitely\n- **Correct**: C\n- **Explanation**: Checkpoints are saved with the session, so `/rewind` works after you resume it; snapshots are deleted about 30 days after the session last saved one (`cleanupPeriodDays`); only the 100 most recent checkpoints keep file snapshots. The window is governed by `cleanupPeriodDays`.\n- **Review**: Checkpoint Retention section\n\n### Q6\n- **Category**: practical\n- **Question**: What does \"Summarize from here\" do when rewinding?\n- **Options**: A) Deletes the conversation from that point | B) Compresses the conversation into an AI-generated summary while preserving the original in the transcript | C) Creates a bullet-point list of changes | D) Exports the conversation to a file\n- **Correct**: B\n- **Explanation**: Summarize compresses the conversation into a shorter AI-generated summary. The original full text is preserved in the transcript file.\n- **Review**: Rewind Options section\n\n### Q7\n- **Category**: conceptual\n- **Question**: When are checkpoints created automatically?\n- **Options**: A) Every 5 minutes | B) On every user prompt | C) Only when you manually save | D) After every tool use\n- **Correct**: B\n- **Explanation**: Automatic checkpoints are created with every user prompt, capturing the state before Claude processes the request.\n- **Review**: Automatic checkpoints section\n\n### Q8\n- **Category**: practical\n- **Question**: How do you disable automatic checkpoint creation?\n- **Options**: A) Use `--no-checkpoints` flag | B) Set `fileCheckpointingEnabled: false` in settings | C) Delete the checkpoints directory | D) Checkpoints cannot be disabled\n- **Correct**: B\n- **Explanation**: Set `fileCheckpointingEnabled: false` in your configuration to disable automatic checkpoint creation (default is true; requires v2.1.119+). Env equivalent: `CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING`.\n- **Review**: Configuration section\n\n### Q9\n- **Category**: conceptual\n- **Question**: Are checkpoints a replacement for git commits?\n- **Options**: A) Yes, they're more powerful | B) No, they are complementary — checkpoints are session-scoped and expire, git is permanent and shareable | C) Yes, for small projects | D) Only in solo development\n- **Correct**: B\n- **Explanation**: Checkpoints are temporary (30-day retention), session-scoped, and cannot be shared. Git commits are permanent, auditable, and shareable. Use both together.\n- **Review**: Integration with git section\n\n### Q10\n- **Category**: practical\n- **Question**: You want to compare two different approaches. What's the recommended checkpoint workflow?\n- **Options**: A) Create two separate sessions | B) Checkpoint before approach A, try it, rewind to checkpoint, try approach B, compare results | C) Use git branches instead | D) There's no good way to compare approaches\n- **Correct**: B\n- **Explanation**: The branching strategy: checkpoint at clean state, try approach A, note results, rewind to the same checkpoint, try approach B. Compare both outcomes.\n- **Review**: Workflow patterns section\n\n---\n\n## Lesson 09: Advanced Features\n\n### Q1\n- **Category**: conceptual\n- **Question**: What are the six permission modes in Claude Code?\n- **Options**: A) read, write, execute, admin, root, sudo | B) manual, acceptEdits, plan, auto, dontAsk, bypassPermissions | C) safe, normal, elevated, admin, unrestricted, god | D) view, edit, run, deploy, full, bypass\n- **Correct**: B\n- **Explanation**: The six modes are: manual (runs reads without asking and prompts for everything else — shown as Manual; its config value is `default`, and manual is accepted as an alias since v2.1.200), acceptEdits (auto-accepts file edits), plan (read-only analysis), auto (background classifier decides), dontAsk (auto-denies unless pre-approved), bypassPermissions (skips all checks).\n- **Review**: Permission Modes section\n\n### Q2\n- **Category**: practical\n- **Question**: How do you activate planning mode?\n- **Options**: A) Only via `/plan` command | B) Via `/plan`, `Shift+Tab`/`Alt+M`, `--permission-mode plan` flag, or default config | C) Via `--planning` flag only | D) Planning is always on\n- **Correct**: B\n- **Explanation**: Planning mode can be activated multiple ways: /plan command, Shift+Tab/Alt+M keyboard shortcut, --permission-mode plan CLI flag, or as a default in config.\n- **Review**: Planning Mode section\n\n### Q3\n- **Category**: conceptual\n- **Question**: What does the `opusplan` model alias do?\n- **Options**: A) Uses only Opus for everything | B) Uses Opus for planning phase and Sonnet for implementation | C) Uses a special planning-optimized model | D) Enables plan mode automatically\n- **Correct**: B\n- **Explanation**: `opusplan` is a model alias that uses Opus for the planning phase (higher quality analysis) and Sonnet for the execution phase (faster implementation).\n- **Review**: Planning Mode section\n\n### Q4\n- **Category**: practical\n- **Question**: On a model where thinking can be turned off (for example Sonnet 5), how do you toggle extended thinking on or off during a session?\n- **Options**: A) Type `/effort max` | B) Press `Option+T` (macOS) or `Alt+T` | C) Include \"ultrathink\" in prompt | D) It's always enabled and cannot be toggled\n- **Correct**: B\n- **Explanation**: Option+T (macOS) or Alt+T toggles extended thinking on/off for the session. (`Ctrl+O` toggles verbose mode to show/hide the reasoning text.) On Opus 5.5 (the default model since v2.1.280), Sonnet 5.5 (what the `sonnet` alias resolves to on the Anthropic API since v2.1.284), Haiku 5.5 (what the `haiku` alias resolves to on the Anthropic API since v2.1.293), and the Fable models, thinking can't be turned off: the toggle, `alwaysThinkingEnabled` and `MAX_THINKING_TOKENS=0` have no effect there. For one-off deep reasoning, include \"ultrathink\" in your prompt; for session-level control, use the `/effort` command.\n- **Review**: Extended Thinking section\n\n### Q5\n- **Category**: conceptual\n- **Question**: Does the \"ultrathink\" keyword trigger deep reasoning?\n- **Options**: A) Yes, it triggers deep reasoning for one response without changing session settings | B) No, it's treated as regular prompt text | C) Yes, but only on Opus 4.6 | D) Yes, and it permanently changes the effort level\n- **Correct**: A\n- **Explanation**: Including \"ultrathink\" in your prompt adds an in-context instruction for the model to reason more on that turn. It does not change the effort level sent to the API—use `/effort max` for session-level deep reasoning.\n- **Review**: Extended Thinking section\n\n### Q6\n- **Category**: practical\n- **Question**: How do you run Claude in a CI/CD pipeline with structured JSON output and a turn limit?\n- **Options**: A) `claude --ci --json --limit 3` | B) `claude -p --output-format json --max-t\n\n<!-- [TRUNCATED AT 50KB] -->\n\n<!-- File: .claude/skills/lesson-quiz/references/results-template.md (Tokens: ~544 | Category: anthropic-skill) -->\n# Results Report Template\n\nThe output format for Step 5 (\"Score and Present Results\"). Fill the bracketed placeholders; keep the headings and table columns as shown.\n\n```markdown\n## Lesson Quiz Results: [Lesson Name]\n\n**Score: N/10** — [Grade label]\n**Quiz timing**: [Before / During / After] the lesson\n**Question breakdown**: N conceptual correct, N practical correct\n\n### Per-Question Results\n\n| # | Category | Question (short) | Your Answer | Result |\n|---|----------|-----------------|-------------|--------|\n| 1 | Conceptual | [abbreviated question] | [their answer] | [Correct / Incorrect] |\n| 2 | Practical | ... | ... | ... |\n| ... | ... | ... | ... | ... |\n\n### Incorrect Answers — Review These\n\n[For each incorrect answer, show:]\n\n**Q[N]: [Full question text]**\n- Your answer: [what they chose]\n- Correct answer: [correct option]\n- Explanation: [why it's correct]\n- Review: [specific section of the lesson README to re-read]\n\n### [Timing-specific message]\n\n[If pre-test]:\n**Pre-test score: N/10.** This gives you a baseline! Focus your study on the topics you missed. After completing the lesson, retake the quiz to measure your improvement.\n\n[If during]:\n**Progress check: N/10.** [If 7 or above: Great progress — keep going! If 5-6: Review the incorrect topics before continuing. If 0-4: Consider re-reading from the beginning.]\n\n[If after]:\n**Mastery check: N/10.** [If 9-10: You've mastered this lesson! Move on to the next. If 7-8: Almost there — review the missed topics and retake. If <7: Spend more time with the lesson, especially the sections marked above.]\n\n### Recommended Next Steps\n\n[Based on score and timing:]\n- [If mastered]: Proceed to the next lesson in the roadmap: [next lesson link]\n- [If proficient]: Review these specific sections, then retake: [list sections]\n- [If developing or below]: Re-read the full lesson: [lesson link]. Focus on: [list weak categories]\n- [Offer]: \"Would you like to retake this quiz, try a different lesson, or get help with a specific topic?\"\n```\n\n---\n\n**Last Updated**: September 2, 2026\n**Claude Code Version**: 2.1.257\n**Sources**:\n- https://code.claude.com/docs/en/overview\n\n<!-- File: .claude/skills/lesson-quiz/SKILL.md (Tokens: ~2237 | Category: anthropic-skill) -->\n---\nname: lesson-quiz\ndescription: \"Test a learner on a single Claude Code tutorial lesson (01-10) with 10 questions, scoring answers and flagging weak spots. Use before, during, or after a lesson. Don't use for whole-tutorial assessment or explaining a topic instead of testing it.\"\neffort: high\nmetadata:\n  version: 1.6.2\n  author: Luong NGUYEN\n---\n\n# Lesson Quiz\n\nInteractive quiz that tests understanding of a specific Claude Code lesson with 10 questions, provides per-question feedback, and identifies areas to review.\n\n## Prerequisites\n\nThis skill requires:\n\n- The tutorial repo checked out, so the lesson directories `01-slash-commands/` … `10-cli/` and each `README.md` are readable.\n- `references/question-bank.md` present in this skill (the source of all questions).\n\nBefore starting, confirm the target lesson's `README.md` exists. If it is missing, do not fabricate questions — warn the user and ask them to check the repository structure (see Error Handling).\n\n**Guardrails:**\n\n- **Never invent questions or answers.** Ask only questions drawn from `references/question-bank.md` for the selected lesson; if the bank lacks entries for a lesson, say so rather than making them up.\n- **Score accurately.** Track which shuffled position holds the correct answer for every question and validate each response against it — never guess a score.\n- **Confirm timing before scoring.** The pre/during/after choice changes how results are framed; do not skip it.\n\n## Instructions\n\n### Step 1: Determine the Lesson\n\nIf the user provided a lesson as an argument (e.g., `/lesson-quiz hooks` or `/lesson-quiz 03`), map it to the lesson directory:\n\n**Lesson mapping:**\n- `01`, `slash-commands`, `commands` → 01-slash-commands\n- `02`, `memory` → 02-memory\n- `03`, `skills` → 03-skills\n- `04`, `subagents`, `agents` → 04-subagents\n- `05`, `mcp` → 05-mcp\n- `06`, `hooks` → 06-hooks\n- `07`, `plugins` → 07-plugins\n- `08`, `checkpoints`, `checkpoint` → 08-checkpoints\n- `09`, `advanced`, `advanced-features` → 09-advanced-features\n- `10`, `cli` → 10-cli\n\nIf no argument was provided, present a selection prompt using AskUserQuestion:\n\n**Question 1** (header: \"Lesson\"):\n\"Which lesson do you want to quiz on?\"\nOptions:\n1. \"Slash Commands (01)\" — Custom commands, skills, frontmatter, arguments\n2. \"Memory (02)\" — CLAUDE.md, memory hierarchy, rules, auto memory\n3. \"Skills (03)\" — Progressive disclosure, auto-invocation, SKILL.md\n4. \"Subagents (04)\" — Task delegation, agent config, isolation\n\n**Question 2** (header: \"Lesson\"):\n\"Which lesson do you want to quiz on? (continued)\"\nOptions:\n1. \"MCP (05)\" — External integration, transport, servers, tool search\n2. \"Hooks (06)\" — Event automation, PreToolUse, exit codes, JSON I/O\n3. \"Plugins (07)\" — Bundled solutions, marketplace, plugin.json\n4. \"More lessons...\" — Checkpoints, Advanced Features, CLI\n\nIf \"More lessons...\" is selected, present:\n\n**Question 3** (header: \"Lesson\"):\n\"Select your lesson:\"\nOptions:\n1. \"Checkpoints (08)\" — Rewind, restore, safe experimentation\n2. \"Advanced Features (09)\" — Planning, permissions, print mode, thinking\n3. \"CLI Reference (10)\" — Flags, output formats, scripting, piping\n\n### Step 2: Read the Lesson Content\n\nRead the lesson README.md file to refresh context:\n- Read file: `<lesson-directory>/README.md`\n\nThen use the question bank from `references/question-bank.md` for that lesson (10 pre-written questions with answers and explanations). To stay within the context budget, read only the one selected lesson's README — not all ten.\n\n### Step 3: Present the Quiz\n\nAsk the user about quiz timing context:\n\nUse AskUserQuestion (header: \"Timing\"):\n\"When are you taking this quiz relative to the lesson?\"\nOptions:\n1. \"Before (pre-test)\" — I haven't read the lesson yet, testing my prior knowledge\n2. \"During (progress check)\" — I'm partway through the lesson\n3. \"After (mastery check)\" — I've completed the lesson and want to verify understanding\n\nThis context affects how the results are framed (see Step 5).\n\n### Step 4: Present Questions in Rounds\n\nPresent 10 questions from the question bank in rounds of 2 questions each (5 rounds total). Each question uses AskUserQuestion with the question text and 3-4 answer options.\n\n**IMPORTANT**: Use AskUserQuestion with max 4 options per question, 2 questions per round.\n\nFor each round, present 2 questions. After the user answers each round, immediately show per-question feedback: whether each answer was correct or incorrect, and if incorrect, show the correct answer and a brief explanation. Then proceed to the next round. After all 5 rounds, proceed to final scoring.\n\n**Question format per round:**\n\nEach question from the question bank has:\n- `question`: The question text\n- `options`: 3-4 answer choices (one correct, labeled in the bank)\n- `correct`: The correct answer label\n- `explanation`: Why the answer is correct\n- `category`: \"conceptual\" or \"practical\"\n\n**CRITICAL — Shuffle answer options**: For each question, you MUST randomize the order of the answer options before presenting them via AskUserQuestion. Do NOT present them in the order they appear in the question bank (A, B, C, D), and do NOT place the correct answer first. Use a different random permutation for each question. Track which shuffled position contains the correct answer so you can score accurately.\n\nExample: If the question bank lists options A (correct), B, C, D — you might present them as: C, A, D, B. The correct answer is now in position 2.\n\nPresent each question using AskUserQuestion. Record the user's answer for each.\n\n### Step 5: Score and Present Results\n\nAfter all rounds, calculate the score and present results.\n\n**Scoring:**\n- Each correct answer = 1 point\n- Total possible = 10 points\n\n**Grade scale:**\n- 9-10: Mastered — Excellent understanding\n- 7-8: Proficient — Good grasp, minor gaps\n- 5-6: Developing — Fundamentals understood, needs review\n- 3-4: Beginning — Significant gaps, review recommended\n- 0-2: Not yet — Start from the beginning of this lesson\n\n**Output format:** Follow the report template in `references/results-template.md`. It defines the score line, the per-question results table, the \"Incorrect Answers — Review These\" block, the timing-specific message (pre-test / during / after), and the \"Recommended Next Steps\" section. Fill its bracketed placeholders with this run's data.\n\n### Step 6: Offer Follow-up\n\nAfter presenting results, use AskUserQuestion:\n\n\"What would you like to do next?\"\nOptions:\n1. \"Retake this quiz\" — Try the same lesson quiz again\n2. \"Quiz another lesson\" — Switch to a different lesson\n3. \"Explain a topic I missed\" — Get a detailed explanation of an incorrect answer\n4. \"Done\" — End the quiz session\n\nIf **Retake**: Go back to Step 4 (skip timing question, use same timing).\nIf **Quiz another lesson**: Go back to Step 1.\nIf **Explain a topic**: Ask which question number, then read the relevant section from the lesson README.md and explain it with examples.\n\n## Acceptance Criteria\n\nA completed quiz run must satisfy all of these — verify each before presenting final results:\n\n- Exactly one lesson (01-10) was resolved before any question was asked.\n- The timing context (before / during / after) was captured via AskUserQuestion.\n- 10 questions from `references/question-bank.md` for that lesson were presented, in 5 rounds of 2, with answer options shuffled per question.\n- Every answer was scored against the tracked correct-position, producing an integer score in the range 0-10.\n- **Expected output**: a `## Lesson Quiz Results` report containing the score line (`Score: N/10` with a grade label), the per-question results table, an \"Incorrect Answers — Review These\" block for each miss, and a timing-specific message.\n- The follow-up prompt (retake / another lesson / explain / done) was offered.\n\nExample: for a 7/10 \"after\" run on Hooks, the report asserts `Score: 7/10 — Proficient`, lists all 10 rows in the results table, and expands the 3 incorrect questions with correct answer, explanation, and a review pointer.\n\n## Edge Cases & Error Handling\n\n### Invalid lesson argument\nIf the argument doesn't match any lesson, show the valid lesson list and ask the user to pick one.\n\n### User wants to quit mid-quiz\nIf the user indicates they want to stop during any round, present partial results for the questions answered so far (score out of the number attempted, not out of 10).\n\n### Lesson README not found\nIf the README.md file doesn't exist at the expected path, inform the user and suggest checking the repository structure. Do not proceed with fabricated content.\n\n### Question bank missing entries for a lesson\nIf `references/question-bank.md` has no questions for the resolved lesson, tell the user and stop — never invent questions to fill the gap.\n\n## Validation\n\n### Triggering test suite\n\n**Should trigger:**\n- \"quiz me on hooks\"\n- \"lesson quiz\"\n- \"test my knowledge of lesson 3\"\n- \"practice quiz for MCP\"\n- \"do I understand skills\"\n- \"quiz me on slash commands\"\n- \"lesson-quiz 06\"\n- \"test me on checkpoints\"\n- \"how well do I know the CLI\"\n- \"quiz me before I start the memory lesson\"\n\n**Should NOT trigger:**\n- \"assess my overall level\" (use /self-assessment)\n- \"explain hooks to me\"\n- \"create a hook\"\n- \"what is MCP\"\n- \"review my code\"\n\n<!-- File: .claude/skills/self-assessment/README.md (Tokens: ~617 | Category: anthropic-skill) -->\n# Self-Assessment & Learning Path Advisor\n\n> Comprehensive Claude Code proficiency assessment that evaluates 10 feature areas, identifies skill gaps, and generates a personalized learning path to level up.\n\n## Highlights\n\n- Two assessment modes: Quick (8 questions, 2 min) and Deep (5 rounds, 5 min)\n- Evaluates 10 feature areas: Slash Commands, Memory, Skills, Hooks, MCP, Subagents, Checkpoints, Advanced Features, Plugins, CLI\n- Per-topic scoring with mastery levels (None / Basic / Proficient)\n- Gap analysis with dependency-aware prioritization\n- Personalized learning path with specific exercises and success criteria\n- Follow-up actions: start learning, deep dive, practice project, or retake\n\n## When to Use\n\n| Say this... | Skill will... |\n|---|---|\n| \"assess my level\" | Run the assessment quiz and determine your level |\n| \"where should I start\" | Evaluate your experience and suggest a starting point |\n| \"check my skills\" | Produce a detailed skill profile across all 10 areas |\n| \"what should I learn next\" | Identify gaps and build a prioritized learning path |\n\n## How It Works\n\n```mermaid\ngraph TD\n    A[\"Choose assessment mode\"] --> B[\"Answer quiz questions\"]\n    B --> C[\"Score per-topic proficiency\"]\n    C --> D[\"Generate personalized learning path\"]\n    D --> E[\"Start learning or deep dive\"]\n    style A fill:#4CAF50,color:#fff\n    style E fill:#2196F3,color:#fff\n```\n\n## Assessment Modes\n\n### Quick Assessment (~2 min)\n- 8 yes/no experience questions across 2 rounds\n- Determines overall level: Beginner / Intermediate / Advanced\n- Lists specific gaps with tutorial links\n- Best for: first-time users, quick check-ins\n\n### Deep Assessment (~5 min)\n- 5 rounds of questions covering 10 feature areas (2 topics per round)\n- Per-topic scoring (0-2 points each, 20 points maximum — Checkpoints contributes 0-1, Advanced Features 0-3)\n- Mastery table with strength areas, priority gaps, and review items\n- Dependency-aware learning path with phases and time estimates\n- Recommended practice projects combining gap topics\n- Best for: experienced users wanting to level up, periodic skill reviews\n\n## Usage\n\n```text\n/self-assessment\n```\n\n## Output\n\n### Skill Profile Table\nShows per-topic score, mastery level, and status (Learn / Review / Mastered).\n\n### Personalized Learning Path\n- Organized into phases based on dependency order\n- Each topic includes: tutorial link, focus areas, key exercise, success criterion\n- Time estimate adjusted for topics already mastered\n- Practice projects combining multiple gap areas\n\n### Follow-up Actions\nAfter results, choose to:\n- Start the first gap tutorial with guided exercises\n- Deep dive into a specific gap area\n- Set up a practice project covering your gaps\n- Retake in a different assessment mode\n\n<!-- File: .claude/skills/self-assessment/references/deep-assessment-rounds.md (Tokens: ~1423 | Category: anthropic-skill) -->\n# Deep Assessment — Round Questions\n\nThe 5 rounds for Deep Assessment. Present one AskUserQuestion call per round (multi-select, max 4 options). Each round covers 2 feature areas with 2 options each. The scoring map for each round is duplicated in SKILL.md Step 2B so results can be computed without re-reading this file.\n\n---\n\n**Round 1 — Slash Commands & Memory** (header: \"Commands\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Created a custom slash command or skill\" — Written a SKILL.md file with frontmatter, or created .claude/commands/ files\n2. \"Used dynamic context in commands\" — Used `$ARGUMENTS`, `$0`/`$1`, backtick `!command` syntax, or `@file` references in skill/command files\n3. \"Set up project + personal memory\" — Created both a project CLAUDE.md and personal ~/.claude/CLAUDE.md (or CLAUDE.local.md)\n4. \"Used memory hierarchy features\" — Understand how the 7 memory locations are concatenated into context (loaded root-down, CLAUDE.local.md appended after CLAUDE.md at each level, subdirectory files loaded on demand), used .claude/rules/ directory, path-specific rules, or @import syntax\n\n**Scoring:** Options 1-2 → **Slash Commands** (0-2); Options 3-4 → **Memory** (0-2)\n\n---\n\n**Round 2 — Skills & Hooks** (header: \"Automation\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Installed and used an auto-invoked skill\" — A skill that triggers automatically based on its description, without manual /command invocation\n2. \"Controlled skill invocation behavior\" — Used `disable-model-invocation`, `user-invocable`, or `context: fork` with agent field in SKILL.md frontmatter\n3. \"Set up a PreToolUse or PostToolUse hook\" — Configured a hook that runs before/after tool execution (e.g., command validator, auto-formatter)\n4. \"Used advanced hook features\" — Configured prompt-type hooks, skill-frontmatter hooks, HTTP hooks, or hooks with custom JSON output (updatedInput, systemMessage)\n\n**Scoring:** Options 1-2 → **Skills** (0-2); Options 3-4 → **Hooks** (0-2)\n\n---\n\n**Round 3 — MCP & Subagents** (header: \"Integration\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Connected an MCP server and used its tools\" — e.g., GitHub MCP for PRs/issues, database MCP for queries, or any external data source\n2. \"Used advanced MCP features\" — Project-scope .mcp.json, OAuth authentication, MCP resources with @mentions, Tool Search, or `claude mcp serve`\n3. \"Created or configured custom subagents\" — Defined agents in .claude/agents/ with custom tools, model, or permissions\n4. \"Used advanced subagent features\" — Worktree isolation, persistent agent memory, background tasks with Ctrl+B, agent allowlists with `Agent(agent_type)` for an agent run as the main thread with `claude --agent` (the `Task(...)` form is a back-compat alias), or agent teams\n\n**Scoring:** Options 1-2 → **MCP** (0-2); Options 3-4 → **Subagents** (0-2)\n\n---\n\n**Round 4 — Checkpoints & Advanced Features** (header: \"Power User\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Used checkpoints for safe experimentation\" — Rewound to a checkpoint with Esc+Esc or /rewind, restored code and/or conversation, or used either Summarize option (summarize from here / summarize up to here)\n2. \"Used planning mode or extended thinking\" — Activated planning via /plan, Shift+Tab, or --permission-mode plan; toggled extended thinking with Alt+T/Option+T on a model that allows it, or set reasoning depth with `/effort`\n3. \"Configured permission modes\" — Used any of the six modes — manual (config value `default`; shown as Manual since v2.1.200), acceptEdits, plan, auto, dontAsk, or bypassPermissions — via CLI flags, keyboard shortcuts, or settings (just starting in the built-in auto default doesn't count)\n4. \"Used remote/desktop/web features\" — Used `claude --remote-control`, `claude --cloud`, `/teleport`, `/desktop`, or worktrees with `claude -w`\n\n**Scoring:** Option 1 → **Checkpoints** (0-1); Options 2-4 → **Advanced Features** (0-3)\n\n---\n\n**Round 5 — Plugins & CLI** (header: \"Mastery\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Installed or created a plugin\" — Used a bundled plugin from marketplace, or created a .claude-plugin/ directory with plugin.json manifest\n2. \"Used plugin advanced features\" — Plugin skills (`skills/` — the preferred form; namespaced `commands/` is legacy but still works), plugin hooks, plugin MCP servers, LSP configuration, or --plugin-dir flag for testing\n3. \"Used print mode in scripts or CI/CD\" — Used `claude -p` with --output-format json, --max-turns, piped input, or integrated into GitHub Actions / CI pipelines\n4. \"Used advanced CLI features\" — Session resumption (-c/-r), --agents flag, --json-schema for structured output, --fallback-model, --from-pr, or batch processing loops\n\n**Scoring:** Options 1-2 → **Plugins** (0-2); Options 3-4 → **CLI** (0-2)\n\n---\n\n**Last Updated**: October 18, 2026\n**Claude Code Version**: 2.1.302\n**Sources**:\n- https://code.claude.com/docs/en/memory\n- https://code.claude.com/docs/en/sub-agents\n- https://code.claude.com/docs/en/permission-modes\n- https://code.claude.com/docs/en/checkpointing\n- https://code.claude.com/docs/en/plugins-reference\n- https://code.claude.com/docs/en/permission-modes#which-mode-a-session-starts-in\n- https://code.claude.com/docs/en/hooks#hooks-in-skills-and-agents\n- https://code.claude.com/docs/en/model-config#extended-thinking\n\n<!-- File: .claude/skills/self-assessment/references/output-templates.md (Tokens: ~949 | Category: anthropic-skill) -->\n# Output Templates\n\nBlank markdown templates for the assessment results and learning path. The Step 3A/3B result templates and the Step 4 path-format template are duplicated verbatim in SKILL.md so results can be produced without re-reading this file.\n\n## Quick Assessment results (Step 3A)\n\n```markdown\n## Claude Code Skill Assessment Results\n\n### Your Level: [Level 1: Beginner / Level 2: Intermediate / Level 3: Advanced]\n\nYou checked **N/8** items.\n\n[One-line motivational summary based on level]\n\n### Your Skill Profile\n\n| Area | Status |\n|------|--------|\n| Basic CLI & Conversations | [Checked/Gap] |\n| CLAUDE.md & Memory | [Checked/Gap] |\n| Slash Commands (built-in) | [Checked/Gap] |\n| Custom Commands & Skills | [Checked/Gap] |\n| MCP Servers | [Checked/Gap] |\n| Hooks | [Checked/Gap] |\n| Subagents | [Checked/Gap] |\n| Print Mode & CI/CD | [Checked/Gap] |\n\n### Identified Gaps\n\n[For each unchecked item, provide a 1-line description of what to learn and a link to the tutorial]\n\n### Your Personalized Learning Path\n\n[Output the level-specific learning path — see Step 4]\n```\n\n## Deep Assessment results (Step 3B)\n\n```markdown\n## Claude Code Skill Assessment Results\n\n### Overall Level: [Level 1 / Level 2 / Level 3]\n\n**Total Score: N/20 points**\n\n[One-line motivational summary]\n\n### Your Skill Profile\n\n| Feature Area | Score | Mastery | Status |\n|-------------|-------|---------|--------|\n| Slash Commands | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Memory | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Skills | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Hooks | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| MCP | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Subagents | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Checkpoints | N/1 | [None/Proficient] | [Learn/Mastered] |\n| Advanced Features | N/3 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Plugins | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| CLI | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n\n**Mastery key:** 0 = None, 1 = Basic, 2 = Proficient\n\n### Strength Areas\n[List topics with score 2/2 — these are mastered]\n\n### Priority Gaps (Learn Next)\n[List topics with score 0 — these need attention first, ordered by dependency]\n\n### Review Areas\n[List topics with score 1/2 — basics known but advanced features not yet used]\n\n### Your Personalized Learning Path\n\n[Output gap-specific learning path — see Step 4]\n```\n\n## Learning Path (Step 4)\n\n```markdown\n### Your Personalized Learning Path\n\n**Estimated time**: ~N hours (adjusted for your current skills)\n\n#### Phase 1: [Phase Name] (~N hours)\n[Only if they have gaps in these areas]\n\n**[Topic Name]** — [Learn from scratch / Deep dive into advanced features]\n- Tutorial: [link to tutorial directory]\n- Focus on: [specific sections/concepts they need]\n- Key exercise: [one concrete exercise to do]\n- You'll know it's done when: [specific success criterion]\n\n**[Topic Name]** — ...\n\n---\n\n#### Phase 2: [Phase Name] (~N hours)\n...\n\n---\n\n### Recommended Practice Projects\n\nBased on your gaps, try these real-world exercises to solidify your learning:\n\n1. **[Project name]**: [1-line description combining 2-3 gap topics]\n2. **[Project name]**: [1-line description]\n3. **[Project name]**: [1-line description]\n```\n\n---\n\n**Last Updated**: September 2, 2026\n**Claude Code Version**: 2.1.257\n**Sources**:\n- https://code.claude.com/docs/en/overview\n\n<!-- File: .claude/skills/self-assessment/references/topic-recommendations.md (Tokens: ~2475 | Category: anthropic-skill) -->\n# Topic-Specific Recommendations\n\nUse these specific recommendations when a topic is a gap. Paths are relative to this reference file (`.claude/skills/self-assessment/references/`).\n\n**Slash Commands (score 0)**:\n- Tutorial: [01-slash-commands/](../../../../01-slash-commands/)\n- Focus on: Built-in commands reference, creating your first SKILL.md, `$ARGUMENTS` syntax\n- Key exercise: Create a `/optimize` command and test it\n- Done when: You can create a custom skill with arguments and dynamic context\n\n**Slash Commands (score 1 — review)**:\n- Focus on: Dynamic context with the ``!`command` `` syntax, `@file` references, `disable-model-invocation` vs `user-invocable` control\n- Done when: You can create a skill that injects live command output and controls its own invocation behavior\n\n**Memory (score 0)**:\n- Tutorial: [02-memory/](../../../../02-memory/)\n- Focus on: CLAUDE.md creation, `/init` and `/memory` commands, and the difference from auto memory (asking Claude to remember something saves it to auto memory; to put it in CLAUDE.md, say \"add this to CLAUDE.md\" or edit via `/memory` — the old `#` shortcut was removed)\n- Key exercise: Create a project CLAUDE.md with your coding standards\n- Done when: Claude remembers your preferences across sessions\n\n**Memory (score 1 — review)**:\n- Focus on: the 7 memory locations and how they are concatenated into context (loaded root-down, not overridden), .claude/rules/ directory with path-specific rules, `@import` syntax (max depth 4), Auto Memory MEMORY.md (Claude loads its first 200 lines or 25 KB, whichever comes first — a load cap, not a file-size limit)\n- Done when: You have modular rules for different directories and understand how every memory file is concatenated into context\n\n**Skills (score 0)**:\n- Tutorial: [03-skills/](../../../../03-skills/)\n- Focus on: SKILL.md format, auto-invocation via description field, progressive disclosure (3 loading levels)\n- Key exercise: Install `03-skills/code-review-specialist` and verify it auto-triggers\n- Done when: A skill automatically activates based on conversation context\n\n**Skills (score 1 — review)**:\n- Focus on: `context: fork` with `agent` field for subagent execution, `disable-model-invocation` vs `user-invocable`, the skill-listing budget (1% of the context window, fallback 8,000 characters; each entry's `description` + `when_to_use` capped at 1,536 characters by default via `skillListingMaxDescChars`), bundled resources (scripts/, references/, assets/)\n- Done when: You can create a skill that runs in a subagent with forked context\n\n**Hooks (score 0)**:\n- Tutorial: [06-hooks/](../../../../06-hooks/)\n- Focus on: Configuration structure (matcher + hooks array), PreToolUse/PostToolUse events, exit codes (0=success, 2=block), JSON input/output format\n- Key exercise: Create a PreToolUse hook that validates Bash commands\n- Done when: A hook blocks dangerous commands before execution\n\n**Hooks (score 1 — review)**:\n- Focus on: All 33 hook events (including PostToolUseFailure, StopFailure, TaskCreated, CwdChanged, FileChanged, PostCompact, Elicitation, ElicitationResult, Setup, UserPromptExpansion, MessageDisplay, PreModelSwitch, PostModelSwitch — the last two added in v2.1.251), 5 hook types (command, http, mcp_tool, prompt, agent — agent hooks are experimental and may change), hooks in SKILL.md frontmatter (they persist for the session after invocation; subagent-frontmatter hooks end with the subagent), HTTP hooks with allowedEnvVars, `onFailure: \"block\"` to block the action when a command or HTTP hook fails (v2.1.295+), `CLAUDE_ENV_FILE` for SessionStart, Setup, CwdChanged and FileChanged\n- Done when: You can create a prompt-based Stop hook and a hook in a skill's frontmatter (and you know it stays registered for the rest of the session)\n\n**MCP (score 0)**:\n- Tutorial: [05-mcp/](../../../../05-mcp/)\n- Focus on: `claude mcp add` command, transport types (`http` recommended, `stdio`, `ws` for push-style servers, and the deprecated `sse` — note `--transport` does not accept `ws`, so add WebSocket servers with `claude mcp add-json`), GitHub MCP setup, environment variable expansion\n- Key exercise: Add GitHub MCP server and query PRs\n- Done when: You can query live data from an external service via MCP\n\n**MCP (score 1 — review)**:\n- Focus on: Project-scope .mcp.json (each user approves it on first use; workspace trust applies), OAuth 2.0 auth, MCP resources with `@server:resource` mentions, Tool Search (ENABLE_TOOL_SEARCH), `claude mcp serve`, output limits (10,000 tokens warning; 25,000 tokens default max via `MAX_MCP_OUTPUT_TOKENS`; 50,000 characters disk-persistence threshold)\n- Done when: You have a project .mcp.json and understand how tool search defers MCP tools by default and what `ENABLE_TOOL_SEARCH=auto`/`false` change\n\n**Subagents (score 0)**:\n- Tutorial: [04-subagents/](../../../../04-subagents/)\n- Focus on: Agent file format (.claude/agents/*.md), built-in agents (Explore, Plan, general-purpose, claude, statusline-setup, claude-code-guide), tools/model/permissionMode config, spawn limits (depth default 3 since v2.1.219, concurrency default 20, and the 200-per-session spawn cap removed in v2.1.224)\n- Key exercise: Create a code-reviewer subagent and test delegation\n- Done when: Claude delegates code review to your custom agent\n\n**Subagents (score 1 — review)**:\n- Focus on: Worktree isolation (`isolation: worktree`), persistent agent memory (`memory` field with scopes), background agents (Ctrl+B to background; Ctrl+X Ctrl+K twice to stop them all), agent allowlists with `Agent(agent_type)` for a main-thread agent started with `claude --agent` (`Task(...)` remains a back-compat alias; in a subagent's own `tools` the type list is ignored), agent teams (`--teammate-mode`)\n- Done when: You have a subagent with persistent memory running in worktree isolation\n\n**Checkpoints (score 0)**:\n- Tutorial: [08-checkpoints/](../../../../08-checkpoints/)\n- Focus on: Esc+Esc and /rewind access, 6 rewind options (restore code and conversation, restore conversation, restore code, summarize from here, summarize up to here, never mind), limitations — bash filesystem ops, subagent edits (except a foreground `context: fork` skill), edits made outside Claude Code are untracked, and symlinked/hard-linked paths are skipped on restore\n- Key exercise: Make experimental changes, then rewind to restore\n- Done when: You can confidently experiment knowing you can rewind\n\n**Advanced Features (score 0)**:\n- Tutorial: [09-advanced-features/](../../../../09-advanced-features/)\n- Focus on: Planning mode (/plan or Shift+Tab), permission modes (6 types: manual — config value `default`, shown as Manual since v2.1.200 — acceptEdits, plan, auto, dontAsk, bypassPermissions), extended thinking (Alt+T/Option+T toggle — no effect on Opus 5.5 (the default model), Sonnet 5.5, Haiku 5.5, or the Fable models, where thinking stays on)\n- Key exercise: Use planning mode to design a feature, then implement it\n- Done when: You can switch between planning and implementation modes fluently\n\n**Advanced Features (score 1 — review)**:\n- Focus on: Remote control (`claude --remote-control`, alias `--rc`), web sessions (`claude --cloud`; `--remote` is a deprecated alias), desktop handoff (`/desktop`), worktrees (`claude -w`), task lists (Ctrl+T), managed settings for enterprise\n- Done when: You can hand off sessions between CLI, web, and desktop\n\n**Plugins (score 0)**:\n- Tutorial: [07-plugins/](../../../../07-plugins/)\n- Focus on: Plugin structure (.claude-plugin/plugin.json), what plugins bundle (skills, agents, MCP, hooks, settings — plus the legacy `commands/` directory, which still works but `skills/` is preferred for new plugins), installation from marketplace (`/plugin install`, or `claude plugin install <plugin> --marketplace <source>` from the shell)\n- Key exercise: Install a plugin and explore its components\n- Done when: You understand when to use a plugin vs standalone components\n\n**Plugins (score 1 — review)**:\n- Focus on: Creating plugin.json manifest, plugin hooks (hooks/hooks.json), LSP configuration (.lsp.json), `${CLAUDE_PLUGIN_ROOT}` variable, --plugin-dir for testing, marketplace publishing, mods (hooks modules shipped in a plugin that add panes, commands, and tool-call rules — v2.1.287+)\n- Done when: You can create and test a plugin for your team\n\n**CLI (score 0)**:\n- Tutorial: [10-cli/](../../../../10-cli/)\n- Focus on: Interactive vs print mode, `claude -p` with piping, `--output-format json`, session management (-c/-r)\n- Key exercise: Pipe a file to `claude -p` and get JSON output\n- Done when: You can use Claude non-interactively in a script\n\n**CLI (score 1 — review)**:\n- Focus on: --agents flag with JSON config, --json-schema for structured output, --fallback-model, --from-pr, --strict-mcp-config, batch processing with for loops, `claude mcp serve`\n- Done when: You have a CI/CD script that uses Claude with structured JSON output\n\n---\n\n**Last Updated**: October 18, 2026\n**Claude Code Version**: 2.1.302\n**Sources**:\n- https://code.claude.com/docs/en/hooks\n- https://code.claude.com/docs/en/memory\n- https://code.claude.com/docs/en/skills\n- https://code.claude.com/docs/en/mcp\n- https://code.claude.com/docs/en/sub-agents\n- https://code.claude.com/docs/en/checkpointing\n- https://code.claude.com/docs/en/permission-modes\n- https://code.claude.com/docs/en/plugins-reference\n- https://code.claude.com/docs/en/interactive-mode\n- https://code.claude.com/docs/en/model-config#extended-thinking\n- https://code.claude.com/docs/en/settings-reference\n- https://code.claude.com/docs/en/model-config\n- https://code.claude.com/docs/en/plugins/mods/overview\n- https://code.claude.com/docs/en/plugins/cli-reference\n- https://code.claude.com/docs/en/mcp#configure-tool-search\n- https://code.claude.com/docs/en/mcp#project-server-approvals-and-workspace-trust\n\n<!-- File: .claude/skills/self-assessment/SKILL.md (Tokens: ~5873 | Category: anthropic-skill) -->\n---\nname: self-assessment\nversion: 2.5.5\ndescription: Comprehensive Claude Code self-assessment and learning path advisor. Runs a multi-category quiz covering 10 feature areas, produces a detailed skill profile with per-topic scores, identifies specific gaps, and generates a personalized learning path with prioritized next steps. Use when asked to \"assess my level\", \"take the quiz\", \"find my level\", \"where should I start\", \"what should I learn next\", \"check my skills\", \"skill check\", or \"level up\".\n---\n\n# Self-Assessment & Learning Path Advisor\n\nComprehensive interactive assessment that evaluates Claude Code proficiency across 10 feature areas, identifies specific skill gaps, and generates a personalized learning path to level up.\n\n## Instructions\n\n### Step 1: Welcome & Choose Assessment Mode\n\nPresent the user with a choice of assessment depth:\n\nUse AskUserQuestion with these options:\n- **Quick Assessment** — \"2 multi-select questions (8 items), ~2 minutes. Determines your overall level (Beginner/Intermediate/Advanced) and gives a learning path.\"\n- **Deep Assessment** — \"5 categories with detailed questions, ~5 minutes. Gives per-topic skill scores, identifies specific gaps, and builds a prioritized learning path.\"\n\nIf user chooses **Quick Assessment**, go to Step 2A.\nIf user chooses **Deep Assessment**, go to Step 2B.\n\n---\n\n### Step 2A: Quick Assessment\n\nPresent TWO multi-select questions (AskUserQuestion supports max 4 options each):\n\n**Question 1** (header: \"Basics\"):\n\"Part 1/2: Which of these Claude Code skills do you already have?\"\nOptions:\n1. \"Start Claude Code and chat\" — I can run `claude` and interact with it\n2. \"Created/edited CLAUDE.md\" — I have set up project or user memory\n3. \"Used 3+ slash commands\" — e.g., /help, /compact, /model, /clear\n4. \"Created custom command/skill\" — Written a SKILL.md or custom command file\n\n**Question 2** (header: \"Advanced\"):\n\"Part 2/2: Which of these advanced skills do you have?\"\nOptions:\n1. \"Configured an MCP server\" — e.g., GitHub, database, or other external data source\n2. \"Set up hooks\" — Configured hooks in a settings file (e.g. ~/.claude/settings.json or .claude/settings.json)\n3. \"Created/used subagents\" — Used .claude/agents/ for task delegation\n4. \"Used print mode (claude -p)\" — Used `claude -p` for non-interactive or CI/CD use\n\n**Scoring:**\n- 0-2 total = Level 1: Beginner\n- 3-5 total = Level 2: Intermediate\n- 6-8 total = Level 3: Advanced\n\nGo to Step 3 with the level result, listing which specific items were NOT checked as gaps.\n\n---\n\n### Step 2B: Deep Assessment\n\nPresent 5 rounds of questions, one AskUserQuestion call per round. Each round covers 2 related feature areas. Use multi-select for all rounds.\n\n**IMPORTANT**: AskUserQuestion supports max 4 options per question. Each round has exactly 1 question with 4 options covering 2 topics (2 options per topic).\n\n---\n\n**Round 1 — Slash Commands & Memory** (header: \"Commands\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Created a custom slash command or skill\" — Written a SKILL.md file with frontmatter, or created .claude/commands/ files\n2. \"Used dynamic context in commands\" — Used `$ARGUMENTS`, `$0`/`$1`, backtick `!command` syntax, or `@file` references in skill/command files\n3. \"Set up project + personal memory\" — Created both a project CLAUDE.md and personal ~/.claude/CLAUDE.md (or CLAUDE.local.md)\n4. \"Used memory hierarchy features\" — Understand how the 7 memory locations are concatenated into context (loaded root-down, CLAUDE.local.md appended after CLAUDE.md at each level, subdirectory files loaded on demand), used .claude/rules/ directory, path-specific rules, or @import syntax\n\n**Scoring for Round 1:**\n- Options 1-2 map to **Slash Commands** (0-2 points)\n- Options 3-4 map to **Memory** (0-2 points)\n\n---\n\n**Round 2 — Skills & Hooks** (header: \"Automation\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Installed and used an auto-invoked skill\" — A skill that triggers automatically based on its description, without manual /command invocation\n2. \"Controlled skill invocation behavior\" — Used `disable-model-invocation`, `user-invocable`, or `context: fork` with agent field in SKILL.md frontmatter\n3. \"Set up a PreToolUse or PostToolUse hook\" — Configured a hook that runs before/after tool execution (e.g., command validator, auto-formatter)\n4. \"Used advanced hook features\" — Configured prompt-type hooks, skill-frontmatter hooks, HTTP hooks, or hooks with custom JSON output (updatedInput, systemMessage)\n\n**Scoring for Round 2:**\n- Options 1-2 map to **Skills** (0-2 points)\n- Options 3-4 map to **Hooks** (0-2 points)\n\n---\n\n**Round 3 — MCP & Subagents** (header: \"Integration\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Connected an MCP server and used its tools\" — e.g., GitHub MCP for PRs/issues, database MCP for queries, or any external data source\n2. \"Used advanced MCP features\" — Project-scope .mcp.json, OAuth authentication, MCP resources with @mentions, Tool Search, or `claude mcp serve`\n3. \"Created or configured custom subagents\" — Defined agents in .claude/agents/ with custom tools, model, or permissions\n4. \"Used advanced subagent features\" — Worktree isolation, persistent agent memory, background tasks with Ctrl+B, agent allowlists with `Agent(agent_type)` for an agent run as the main thread with `claude --agent` (the `Task(...)` form is a back-compat alias), or agent teams\n\n**Scoring for Round 3:**\n- Options 1-2 map to **MCP** (0-2 points)\n- Options 3-4 map to **Subagents** (0-2 points)\n\n---\n\n**Round 4 — Checkpoints & Advanced Features** (header: \"Power User\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Used checkpoints for safe experimentation\" — Rewound to a checkpoint with Esc+Esc or /rewind, restored code and/or conversation, or used either Summarize option (summarize from here / summarize up to here)\n2. \"Used planning mode or extended thinking\" — Activated planning via /plan, Shift+Tab, or --permission-mode plan; toggled extended thinking with Alt+T/Option+T on a model that allows it, or set reasoning depth with `/effort`\n3. \"Configured permission modes\" — Used any of the six modes — manual (config value `default`; shown as Manual since v2.1.200), acceptEdits, plan, auto, dontAsk, or bypassPermissions — via CLI flags, keyboard shortcuts, or settings (just starting in the built-in auto default doesn't count)\n4. \"Used remote/desktop/web features\" — Used `claude --remote-control`, `claude --cloud`, `/teleport`, `/desktop`, or worktrees with `claude -w`\n\n**Scoring for Round 4:**\n- Option 1 maps to **Checkpoints** (0-1 point)\n- Options 2-4 map to **Advanced Features** (0-3 points)\n\n---\n\n**Round 5 — Plugins & CLI** (header: \"Mastery\")\n\n\"Which of these have you done? Select all that apply.\"\nOptions:\n1. \"Installed or created a plugin\" — Used a bundled plugin from marketplace, or created a .claude-plugin/ directory with plugin.json manifest\n2. \"Used plugin advanced features\" — Plugin skills (`skills/` — the preferred form; namespaced `commands/` is legacy but still works), plugin hooks, plugin MCP servers, LSP configuration, or --plugin-dir flag for testing\n3. \"Used print mode in scripts or CI/CD\" — Used `claude -p` with --output-format json, --max-turns, piped input, or integrated into GitHub Actions / CI pipelines\n4. \"Used advanced CLI features\" — Session resumption (-c/-r), --agents flag, --json-schema for structured output, --fallback-model, --from-pr, or batch processing loops\n\n**Scoring for Round 5:**\n- Options 1-2 map to **Plugins** (0-2 points)\n- Options 3-4 map to **CLI** (0-2 points)\n\n---\n\n### Step 3: Calculate & Present Results\n\n#### 3A: For Quick Assessment\n\nCount total selections and determine level. Then present:\n\n```markdown\n## Claude Code Skill Assessment Results\n\n### Your Level: [Level 1: Beginner / Level 2: Intermediate / Level 3: Advanced]\n\nYou checked **N/8** items.\n\n[One-line motivational summary based on level]\n\n### Your Skill Profile\n\n| Area | Status |\n|------|--------|\n| Basic CLI & Conversations | [Checked/Gap] |\n| CLAUDE.md & Memory | [Checked/Gap] |\n| Slash Commands (built-in) | [Checked/Gap] |\n| Custom Commands & Skills | [Checked/Gap] |\n| MCP Servers | [Checked/Gap] |\n| Hooks | [Checked/Gap] |\n| Subagents | [Checked/Gap] |\n| Print Mode & CI/CD | [Checked/Gap] |\n\n### Identified Gaps\n\n[For each unchecked item, provide a 1-line description of what to learn and a link to the tutorial]\n\n### Your Personalized Learning Path\n\n[Output the level-specific learning path — see Step 4]\n```\n\n#### 3B: For Deep Assessment\n\nCalculate per-topic scores from the 5 rounds. Each topic gets 0-2 points, except Advanced Features (0-3) and Checkpoints (0-1). Then present:\n\n```markdown\n## Claude Code Skill Assessment Results\n\n### Overall Level: [Level 1 / Level 2 / Level 3]\n\n**Total Score: N/20 points**\n\n[One-line motivational summary]\n\n### Your Skill Profile\n\n| Feature Area | Score | Mastery | Status |\n|-------------|-------|---------|--------|\n| Slash Commands | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Memory | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Skills | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Hooks | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| MCP | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Subagents | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Checkpoints | N/1 | [None/Proficient] | [Learn/Mastered] |\n| Advanced Features | N/3 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| Plugins | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n| CLI | N/2 | [None/Basic/Proficient] | [Learn/Review/Mastered] |\n\n**Mastery key:** 0 = None, 1 = Basic, 2 = Proficient\n\n### Strength Areas\n[List topics with score 2/2 — these are mastered]\n\n### Priority Gaps (Learn Next)\n[List topics with score 0 — these need attention first, ordered by dependency]\n\n### Review Areas\n[List topics with score 1/2 — basics known but advanced features not yet used]\n\n### Your Personalized Learning Path\n\n[Output gap-specific learning path — see Step 4]\n```\n\n**Overall level calculation for Deep Assessment:**\n- 0-6 total points = Level 1: Beginner\n- 7-13 total points = Level 2: Intermediate\n- 14-20 total points = Level 3: Advanced\n\n---\n\n### Step 4: Generate Personalized Learning Path\n\nBased on the assessment results, generate a learning path that is specific to the user's gaps. Do NOT just repeat the generic level path — adapt it.\n\n#### Rules for Path Generation\n\n1. **Skip mastered topics**: If a topic scored 2/2, do not include it in the path.\n2. **Prioritize by dependency order**: Slash Commands before Skills, Memory before Subagents, etc. The dependency order is:\n   - Slash Commands (no deps) -> Skills (depends on Slash Commands)\n   - Memory (no deps) -> Subagents (depends on Memory)\n   - CLI Basics (no deps) -> CLI Mastery (depends on all)\n   - Checkpoints (no deps)\n   - Hooks (depends on Slash Commands)\n   - MCP (no deps) -> Plugins (depends on MCP, Skills, Hooks)\n   - Advanced Features (depends on all previous)\n3. **For score 1/2 topics**: Recommend the \"deep dive\" — link to the specific advanced section they're missing.\n4. **Estimate time**: Sum only the topics they need to learn/review.\n5. **Group into phases**: Organize remaining topics into logical phases of 2-3 topics each.\n\n#### Path Output Format\n\n```markdown\n### Your Personalized Learning Path\n\n**Estimated time**: ~N hours (adjusted for your current skills)\n\n#### Phase 1: [Phase Name] (~N hours)\n[Only if they have gaps in these areas]\n\n**[Topic Name]** — [Learn from scratch / Deep dive into advanced features]\n- Tutorial: [link to tutorial directory]\n- Focus on: [specific sections/concepts they need]\n- Key exercise: [one concrete exercise to do]\n- You'll know it's done when: [specific success criterion]\n\n**[Topic Name]** — ...\n\n---\n\n#### Phase 2: [Phase Name] (~N hours)\n...\n\n---\n\n### Recommended Practice Projects\n\nBased on your gaps, try these real-world exercises to solidify your learning:\n\n1. **[Project name]**: [1-line description combining 2-3 gap topics]\n2. **[Project name]**: [1-line description]\n3. **[Project name]**: [1-line description]\n```\n\n#### Topic-Specific Recommendations\n\nUse these specific recommendations when a topic is a gap:\n\n**Slash Commands (score 0)**:\n- Tutorial: [01-slash-commands/](../../../01-slash-commands/)\n- Focus on: Built-in commands reference, creating your first SKILL.md, `$ARGUMENTS` syntax\n- Key exercise: Create a `/optimize` command and test it\n- Done when: You can create a custom skill with arguments and dynamic context\n\n**Slash Commands (score 1 — review)**:\n- Focus on: Dynamic context with the ``!`command` `` syntax, `@file` references, `disable-model-invocation` vs `user-invocable` control\n- Done when: You can create a skill that injects live command output and controls its own invocation behavior\n\n**Memory (score 0)**:\n- Tutorial: [02-memory/](../../../02-memory/)\n- Focus on: CLAUDE.md creation, `/init` and `/memory` commands, and the difference from auto memory (asking Claude to remember something saves it to auto memory; to put it in CLAUDE.md, say \"add this to CLAUDE.md\" or edit via `/memory` — the old `#` shortcut was removed)\n- Key exercise: Create a project CLAUDE.md with your coding standards\n- Done when: Claude remembers your preferences across sessions\n\n**Memory (score 1 — review)**:\n- Focus on: the 7 memory locations and how they are concatenated into context (loaded root-down, not overridden), .claude/rules/ directory with path-specific rules, `@import` syntax (max depth 4), Auto Memory MEMORY.md (Claude loads its first 200 lines or 25 KB, whichever comes first — a load cap, not a file-size limit)\n- Done when: You have modular rules for different directories and understand how every memory file is concatenated into context\n\n**Skills (score 0)**:\n- Tutorial: [03-skills/](../../../03-skills/)\n- Focus on: SKILL.md format, auto-invocation via description field, progressive disclosure (3 loading levels)\n- Key exercise: Install `03-skills/code-review-specialist` and verify it auto-triggers\n- Done when: A skill automatically activates based on conversation context\n\n**Skills (score 1 — review)**:\n- Focus on: `context: fork` with `agent` field for subagent execution, `disable-model-invocation` vs `user-invocable`, the skill-listing budget (1% of the context window, fallback 8,000 characters; each entry's `description` + `when_to_use` capped at 1,536 characters by default via `skillListingMaxDescChars`), bundled resources (scripts/, references/, assets/)\n- Done when: You can create a skill that runs in a subagent with forked context\n\n**Hooks (score 0)**:\n- Tutorial: [06-hooks/](../../../06-hooks/)\n- Focus on: Configuration structure (matcher + hooks array), PreToolUse/PostToolUse events, exit codes (0=success, 2=block), JSON input/output format\n- Key exercise: Create a PreToolUse hook that validates Bash commands\n- Done when: A hook blocks dangerous commands before execution\n\n**Hooks (score 1 — review)**:\n- Focus on: All 33 hook events (including PostToolUseFailure, StopFailure, TaskCreated, CwdChanged, FileChanged, PostCompact, Elicitation, ElicitationResult, Setup, UserPromptExpansion, MessageDisplay, PreModelSwitch, PostModelSwitch — the last two added in v2.1.251), 5 hook types (command, http, mcp_tool, prompt, agent — agent hooks are experimental and may change), hooks in SKILL.md frontmatter (they persist for the session after invocation; subagent-frontmatter hooks end with the subagent), HTTP hooks with allowedEnvVars, `onFailure: \"block\"` to block the action when a command or HTTP hook fails (v2.1.295+), `CLAUDE_ENV_FILE` for SessionStart, Setup, CwdChanged and FileChanged\n- Done when: You can create a prompt-based Stop hook and a hook in a skill's frontmatter (and you know it stays registered for the rest of the session)\n\n**MCP (score 0)**:\n- Tutorial: [05-mcp/](../../../05-mcp/)\n- Focus on: `claude mcp add` command, transport types (`http` recommended, `stdio`, `ws` for push-style servers, and the deprecated `sse` — note `--transport` does not accept `ws`, so add WebSocket servers with `claude mcp add-json`), GitHub MCP setup, environment variable expansion\n- Key exercise: Add GitHub MCP server and query PRs\n- Done when: You can query live data from an external service via MCP\n\n**MCP (score 1 — review)**:\n- Focus on: Project-scope .mcp.json (each user approves it on first use; workspace trust applies), OAuth 2.0 auth, MCP resources with `@server:resource` mentions, Tool Search (ENABLE_TOOL_SEARCH), `claude mcp serve`, output limits (10,000 tokens warning; 25,000 tokens default max via `MAX_MCP_OUTPUT_TOKENS`; 50,000 characters disk-persistence threshold)\n- Done when: You have a project .mcp.json and understand how tool search defers MCP tools by default and what `ENABLE_TOOL_SEARCH=auto`/`false` change\n\n**Subagents (score 0)**:\n- Tutorial: [04-subagents/](../../../04-subagents/)\n- Focus on: Agent file format (.claude/agents/*.md), built-in agents (Explore, Plan, general-purpose, claude, statusline-setup, claude-code-guide), tools/model/permissionMode config, spawn limits (depth default 3 since v2.1.219, concurrency default 20, and the 200-per-session spawn cap removed in v2.1.224)\n- Key exercise: Create a code-reviewer subagent and test delegation\n- Done when: Claude delegates code review to your custom agent\n\n**Subagents (score 1 — review)**:\n- Focus on: Worktree isolation (`isolation: worktree`), persistent agent memory (`memory` field with scopes), background agents (Ctrl+B to background; Ctrl+X Ctrl+K twice to stop them all), agent allowlists with `Agent(agent_type)` for a main-thread agent started with `claude --agent` (`Task(...)` remains a back-compat alias; in a subagent's own `tools` the type list is ignored), agent teams (`--teammate-mode`)\n- Done when: You have a subagent with persistent memory running in worktree isolation\n\n**Checkpoints (score 0)**:\n- Tutorial: [08-checkpoints/](../../../08-checkpoints/)\n- Focus on: Esc+Esc and /rewind access, 6 rewind options (restore code and conversation, restore conversation, restore code, summarize from here, summarize up to here, never mind), limitations — bash filesystem ops, subagent edits (except a foreground `context: fork` skill), edits made outside Claude Code are untracked, and symlinked/hard-linked paths are skipped on restore\n- Key exercise: Make experimental changes, then rewind to restore\n- Done when: You can confidently experiment knowing you can rewind\n\n**Advanced Features (score 0)**:\n- Tutorial: [09-advanced-features/](../../../09-advanced-features/)\n- Focus on: Planning mode (/plan or Shift+Tab), permission modes (6 types: manual — config value `default`, shown as Manual since v2.1.200 — acceptEdits, plan, auto, dontAsk, bypassPermissions), extended thinking (Alt+T/Option+T toggle — no effect on Opus 5.5 (the default model), Sonnet 5.5, Haiku 5.5, or the Fable models, where thinking stays on)\n- Key exercise: Use planning mode to design a feature, then implement it\n- Done when: You can switch between planning and implementation modes fluently\n\n**Advanced Features (score 1 — review)**:\n- Focus on: Remote control (`claude --remote-control`, alias `--rc`), web sessions (`claude --cloud`; `--remote` is a deprecated alias), desktop handoff (`/desktop`), worktrees (`claude -w`), task lists (Ctrl+T), managed settings for enterprise\n- Done when: You can hand off sessions between CLI, web, and desktop\n\n**Plugins (score 0)**:\n- Tutorial: [07-plugins/](../../../07-plugins/)\n- Focus on: Plugin structure (.claude-plugin/plugin.json), what plugins bundle (skills, agents, MCP, hooks, settings — plus the legacy `commands/` directory, which still works but `skills/` is preferred for new plugins), installation from marketplace (`/plugin install`, or `claude plugin install <plugin> --marketplace <source>` from the shell)\n- Key exercise: Install a plugin and explore its components\n- Done when: You understand when to use a plugin vs standalone components\n\n**Plugins (score 1 — review)**:\n- Focus on: Creating plugin.json manifest, plugin hooks (hooks/hooks.json), LSP configuration (.lsp.json), `${CLAUDE_PLUGIN_ROOT}` variable, --plugin-dir for testing, marketplace publishing, mods (hooks modules shipped in a plugin that add panes, commands, and tool-call rules — v2.1.287+)\n- Done when: You can create and test a plugin for your team\n\n**CLI (score 0)**:\n- Tutorial: [10-cli/](../../../10-cli/)\n- Focus on: Interactive vs print mode, `claude -p` with piping, `--output-format json`, session management (-c/-r)\n- Key exercise: Pipe a file to `claude -p` and get JSON output\n- Done when: You can use Claude non-interactively in a script\n\n**CLI (score 1 — review)**:\n- Focus on: --agents flag with JSON config, --json-schema for structured output, --fallback-model, --from-pr, --strict-mcp-config, batch processing with for loops, `claude mcp serve`\n- Done when: You have a CI/CD script that uses Claude with structured JSON output\n\n---\n\n### Step 5: Offer Follow-up Actions\n\nAfter presenting results, ask the user what they'd like to do next:\n\nUse AskUserQuestion with these options:\n- **Start learning** — \"Help me begin the first topic in my learning path right now\"\n- **Deep dive on a gap** — \"Explain one of my gap areas in detail so I can learn it here\"\n- **Practice project** — \"Set up a practice project that covers my gap areas\"\n- **Retake assessment** — \"I want to retake the quiz (maybe the other mode)\"\n\nIf **Start learning**: Read the README.md of the first gap tutorial and walk the user through the first exercise.\nIf **Deep dive on a gap**: Ask which gap topic, then read the relevant tutorial README.md and explain the key concepts with examples.\nIf **Practice project**: Design a small project that combines 2-3 of their gap topics with concrete steps.\nIf **Retake assessment**: Go back to Step 1.\n\n## Error Handling\n\n### User selects no items in a round\nTreat as 0 points for that round's topics. Continue to next round.\n\n### User selects no items in any round\nAssign Level 1: Beginner. Encourage starting from the beginning. Output the full Level 1 path.\n\n### User wants to retake\nRe-run from Step 1 with a fresh assessment.\n\n### User disagrees with their level\nAcknowledge their preference. Ask which level they identify with. Present the path for their chosen level with a prerequisites check for topics they may have missed.\n\n### User asks about a specific topic\nIf the user says something like \"tell me about hooks\" or \"I want to learn MCP\" during the assessment, note it. After presenting results, highlight that topic in their learning path regardless of score.\n\n## Validation\n\n### Triggering test suite\n\n**Should trigger:**\n- \"assess my level\"\n- \"take the quiz\"\n- \"find my level\"\n- \"where should I start\"\n- \"what level am I\"\n- \"learning path quiz\"\n- \"self-assessment\"\n- \"what should I learn next\"\n- \"check my skills\"\n- \"skill check\"\n- \"level up\"\n- \"how good am I at Claude Code\"\n- \"evaluate my Claude Code knowledge\"\n\n**Should NOT trigger:**\n- \"review my code\"\n- \"create a skill\"\n- \"help me with MCP\"\n- \"explain slash commands\"\n- \"what is a checkpoint\"\n\n<!-- File: 03-skills/blog-draft/SKILL.md (Tokens: ~2136 | Category: anthropic-skill) -->\n---\nname: blog-draft\ndescription: Draft a blog post from ideas and resources. Use when users want to write a blog post, create content from research, or draft articles. Guides through research, brainstorming, outlining, and iterative drafting with version control.\n---\n\n## User Input\n\n```text\n$ARGUMENTS\n```\n\nYou **MUST** consider the user input before proceeding. User should provide:\n- **Idea/Topic**: The main concept or theme for the blog post\n- **Resources**: URLs, files, or references to research (optional but recommended)\n- **Target audience**: Who the blog post is for (optional)\n- **Tone/Style**: Formal, casual, technical, etc. (optional)\n\n**IMPORTANT**: If the user is requesting updates to an **existing blog post**, skip steps 0-8 and start directly at **Step 9**. Read the existing draft file(s) first, then proceed with the iteration process.\n\n## Execution Flow\n\nFollow these steps sequentially. **Do not skip steps or proceed without user approval where indicated.**\n\n### Step 0: Create Project Folder\n\n1. Generate a folder name using format: `YYYY-MM-DD-short-topic-name`\n   - Use today's date\n   - Create a short, URL-friendly slug from the topic (lowercase, hyphens, max 5 words)\n\n2. Create the folder structure:\n   ```\n   blog-posts/\n   └── YYYY-MM-DD-short-topic-name/\n       └── resources/\n   ```\n\n3. Confirm folder creation with user before proceeding.\n\n### Step 1: Research & Resource Collection\n\n1. Create `resources/` subfolder in the blog post directory\n\n2. For each provided resource:\n   - **URLs**: Fetch and save key information to `resources/` as markdown files\n   - **Files**: Read and summarize in `resources/`\n   - **Topics**: Use web search to gather up-to-date information\n\n3. For each resource, create a summary file in `resources/`:\n   - `resources/source-1-[short-name].md`\n   - `resources/source-2-[short-name].md`\n   - etc.\n\n4. Each summary should include:\n   ```markdown\n   # Source: [Title/URL]\n\n   ## Key Points\n   - Point 1\n   - Point 2\n\n   ## Relevant Quotes/Data\n   - Quote or statistic 1\n   - Quote or statistic 2\n\n   ## How This Relates to Topic\n   Brief explanation of relevance\n   ```\n\n5. Present research summary to user.\n\n### Step 2: Brainstorm & Clarify\n\n1. Based on the idea and researched resources, present:\n   - **Main themes** identified from research\n   - **Potential angles** for the blog post\n   - **Key points** that should be covered\n   - **Gaps** in information that need clarification\n\n2. Ask clarifying questions:\n   - What is the main takeaway you want readers to have?\n   - Are there specific points from the research you want to emphasize?\n   - What's the target length? (short: 500-800 words, medium: 1000-1500, long: 2000+)\n   - Any points you want to exclude?\n\n3. **Wait for user responses before proceeding.**\n\n### Step 3: Propose Outline\n\n1. Create a structured outline including:\n\n   ```markdown\n   # Blog Post Outline: [Title]\n\n   ## Meta Information\n   - **Target Audience**: [who]\n   - **Tone**: [style]\n   - **Target Length**: [word count]\n   - **Main Takeaway**: [key message]\n\n   ## Proposed Structure\n\n   ### Hook/Introduction\n   - Opening hook idea\n   - Context setting\n   - Thesis statement\n\n   ### Section 1: [Title]\n   - Key point A\n   - Key point B\n   - Supporting evidence from [source]\n\n   ### Section 2: [Title]\n   - Key point A\n   - Key point B\n\n   [Continue for all sections...]\n\n   ### Conclusion\n   - Summary of key points\n   - Call to action or final thought\n\n   ## Sources to Cite\n   - Source 1\n   - Source 2\n   ```\n\n2. Present outline to user and **ask for approval or modifications**.\n\n### Step 4: Save Approved Outline\n\n1. Once user approves the outline, save it to `OUTLINE.md` in the blog post folder.\n\n2. Confirm the outline has been saved.\n\n### Step 5: Commit Outline (if in git repo)\n\n1. Check if current directory is a git repository.\n\n2. If yes:\n   - Stage the new files: blog post folder, resources, and OUTLINE.md\n   - Create commit with message: `docs: Add outline for blog post - [topic-name]`\n   - Push to remote\n\n3. If not a git repo, skip this step and inform user.\n\n### Step 6: Write Draft\n\n1. Based on the approved outline, write the full blog post draft.\n\n2. Follow the structure from OUTLINE.md exactly.\n\n3. Include:\n   - Engaging introduction with hook\n   - Clear section headers\n   - Supporting evidence and examples from research\n   - Smooth transitions between sections\n   - Strong conclusion with takeaway\n   - **Citations**: All comparisons, statistics, data points, and factual claims MUST cite the original source\n\n4. Save the draft as `draft-v0.1.md` in the blog post folder.\n\n5. Format:\n   ```markdown\n   # [Blog Post Title]\n\n   *[Optional: subtitle or tagline]*\n\n   [Full content with inline citations...]\n\n   ---\n\n   ## References\n   - [1] Source 1 Title - URL or Citation\n   - [2] Source 2 Title - URL or Citation\n   - [3] Source 3 Title - URL or Citation\n   ```\n\n6. **Citation Requirements**:\n   - Every data point, statistic, or comparison MUST have an inline citation\n   - Use numbered references [1], [2], etc., or named citations [Source Name]\n   - Link citations to the References section at the end\n   - Example: \"Studies show that 65% of developers prefer TypeScript [1]\"\n   - Example: \"React outperforms Vue in rendering speed by 20% [React Benchmarks 2024]\"\n\n### Step 7: Commit Draft (if in git repo)\n\n1. Check if in git repository.\n\n2. If yes:\n   - Stage the draft file\n   - Create commit with message: `docs: Add draft v0.1 for blog post - [topic-name]`\n   - Push to remote\n\n3. If not a git repo, skip and inform user.\n\n### Step 8: Present Draft for Review\n\n1. Present the draft content to user.\n\n2. Ask for feedback:\n   - Overall impression?\n   - Sections that need expansion or reduction?\n   - Tone adjustments needed?\n   - Missing information?\n   - Specific edits or rewrites?\n\n3. **Wait for user response.**\n\n### Step 9: Iterate or Finalize\n\n**If user requests changes:**\n1. Note all requested modifications\n2. Return to Step 6 with the following adjustments:\n   - Increment version number (v0.2, v0.3, etc.)\n   - Incorporate all feedback\n   - Save as `draft-v[X.Y].md`\n   - Repeat Steps 7-8\n\n**If user approves:**\n1. Confirm the final draft version\n2. Optionally rename to `final.md` if user requests\n3. Summarize the blog post creation process:\n   - Total versions created\n   - Key changes between versions\n   - Final word count\n   - Files created\n\n## Version Tracking\n\nAll drafts are preserved with incremental versioning:\n- `draft-v0.1.md` - Initial draft\n- `draft-v0.2.md` - After first round of feedback\n- `draft-v0.3.md` - After second round of feedback\n- etc.\n\nThis allows tracking the evolution of the blog post and reverting if needed.\n\n## Output Files Structure\n\n```\nblog-posts/\n└── YYYY-MM-DD-topic-name/\n    ├── resources/\n    │   ├── source-1-name.md\n    │   ├── source-2-name.md\n    │   └── ...\n    ├── OUTLINE.md\n    ├── draft-v0.1.md\n    ├── draft-v0.2.md (if iterations)\n    └── draft-v0.3.md (if more iterations)\n```\n\n## Tips for Quality\n\n- **Hook**: Start with a question, surprising fact, or relatable scenario\n- **Flow**: Each paragraph should connect to the next\n- **Evidence**: Support claims with data from research\n- **Citations**: ALWAYS cite sources for:\n  - All statistics and data points (e.g., \"According to [Source], 75% of...\")\n  - Comparisons between products, services, or approaches (e.g., \"X performs 2x faster than Y [Source]\")\n  - Factual claims about market trends, research findings, or benchmarks\n  - Use inline citations with format: [Source Name] or [Author, Year]\n- **Voice**: Maintain consistent tone throughout\n- **Length**: Respect the target word count\n- **Readability**: Use short paragraphs, bullet points where appropriate\n- **CTA**: End with a clear call-to-action or thought-provoking question\n\n## Notes\n\n- Always wait for user approval at outlined checkpoints\n- Preserve all draft versions for history\n- Use web search for up-to-date information when URLs are provided\n- If resources are insufficient, ask user for more or suggest additional research\n- Adapt tone based on target audience (technical, general, business, etc.)\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n\n<!-- File: 03-skills/brand-voice/SKILL.md (Tokens: ~613 | Category: anthropic-skill) -->\n---\nname: brand-voice\ndescription: Ensure all communication matches brand voice and tone guidelines. Use when creating marketing copy, customer communications, public-facing content, or when users mention brand voice, tone, or writing style.\nuser-invocable: false\n---\n\n# Brand Voice Skill\n\n## Overview\nThis skill ensures all communications maintain consistent brand voice, tone, and messaging.\n\n## Brand Identity\n\n### Mission\nHelp teams automate their development workflows with AI\n\n### Values\n- **Simplicity**: Make complex things simple\n- **Reliability**: Rock-solid execution\n- **Empowerment**: Enable human creativity\n\n### Tone of Voice\n- **Friendly but professional** - approachable without being casual\n- **Clear and concise** - avoid jargon, explain technical concepts simply\n- **Confident** - we know what we're doing\n- **Empathetic** - understand user needs and pain points\n\n## Writing Guidelines\n\n### Do's ✅\n- Use \"you\" when addressing readers\n- Use active voice: \"Claude generates reports\" not \"Reports are generated by Claude\"\n- Start with value proposition\n- Use concrete examples\n- Keep sentences under 20 words\n- Use lists for clarity\n- Include calls-to-action\n\n### Don'ts ❌\n- Don't use corporate jargon\n- Don't patronize or oversimplify\n- Don't use \"we believe\" or \"we think\"\n- Don't use ALL CAPS except for emphasis\n- Don't create walls of text\n- Don't assume technical knowledge\n\n## Vocabulary\n\n### ✅ Preferred Terms\n- Claude (not \"the Claude AI\")\n- Code generation (not \"auto-coding\")\n- Agent (not \"bot\")\n- Streamline (not \"revolutionize\")\n- Integrate (not \"synergize\")\n\n### ❌ Avoid Terms\n- \"Cutting-edge\" (overused)\n- \"Game-changer\" (vague)\n- \"Leverage\" (corporate-speak)\n- \"Utilize\" (use \"use\")\n- \"Paradigm shift\" (unclear)\n\n## Examples\n\n### ✅ Good Example\n\"Claude automates your code review process. Instead of manually checking each PR, Claude reviews security, performance, and quality—saving your team hours every week.\"\n\nWhy it works: Clear value, specific benefits, action-oriented\n\n### ❌ Bad Example\n\"Claude leverages cutting-edge AI to provide comprehensive software development solutions.\"\n\nWhy it doesn't work: Vague, corporate jargon, no specific value\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n\n<!-- File: 03-skills/claude-md/SKILL.md (Tokens: ~1894 | Category: anthropic-skill) -->\n---\nname: claude-md\ndescription: Create or update CLAUDE.md files following best practices for optimal AI agent onboarding\n---\n\n## User Input\n\n```text\n$ARGUMENTS\n```\n\nYou **MUST** consider the user input before proceeding (if not empty). User may specify:\n- `create` - Create new CLAUDE.md from scratch\n- `update` - Improve existing CLAUDE.md\n- `audit` - Analyze and report on current CLAUDE.md quality\n- A specific path to create/update (e.g., `src/api/CLAUDE.md` for directory-specific instructions)\n\n## Core Principles\n\n**LLMs are stateless**: CLAUDE.md is the main project file loaded into every conversation (alongside auto memory and unscoped rules). It serves as the primary onboarding document for AI agents into your codebase.\n\n### The Golden Rules\n\n1. **Less is More**: Frontier LLMs can follow ~150-200 instructions. Claude Code's system prompt already uses ~50. Keep your CLAUDE.md focused and concise.\n\n2. **Universal Applicability**: Only include information relevant to EVERY session. Task-specific instructions belong in separate files.\n\n3. **Don't Use Claude as a Linter**: Style guidelines bloat context and degrade instruction-following. Use deterministic tools (prettier, eslint, etc.) instead.\n\n4. **Never Auto-Generate**: CLAUDE.md is the highest leverage point of the AI harness. Craft it manually with careful consideration.\n\n## Execution Flow\n\n### 1. Project Analysis\n\nFirst, analyze the current project state:\n\n1. Check for existing CLAUDE.md files:\n   - Root level: `./CLAUDE.md` or `.claude/CLAUDE.md`\n   - Directory-specific: `**/CLAUDE.md`\n   - Global user config: `~/.claude/CLAUDE.md`\n\n2. Identify the project structure:\n   - Technology stack (languages, frameworks)\n   - Project type (monorepo, single app, library)\n   - Development tools (package manager, build system, test runner)\n\n3. Review existing documentation:\n   - README.md\n   - CONTRIBUTING.md\n   - package.json, pyproject.toml, Cargo.toml, etc.\n\n### 2. Content Strategy (WHAT, WHY, HOW)\n\nStructure CLAUDE.md around three dimensions:\n\n#### WHAT - Technology & Structure\n- Technology stack overview\n- Project organization (especially important for monorepos)\n- Key directories and their purposes\n\n#### WHY - Purpose & Context\n- What the project does\n- Why certain architectural decisions were made\n- What each major component is responsible for\n\n#### HOW - Workflow & Conventions\n- Development workflow (bun vs node, pip vs uv, etc.)\n- Testing procedures and commands\n- Verification and build methods\n- Critical \"gotchas\" or non-obvious requirements\n\n### 3. Progressive Disclosure Strategy\n\nFor larger projects, recommend creating an `agent_docs/` folder:\n\n```\nagent_docs/\n  |- building_the_project.md\n  |- running_tests.md\n  |- code_conventions.md\n  |- architecture_decisions.md\n```\n\nIn CLAUDE.md, reference these files with instructions like:\n```markdown\nFor detailed build instructions, refer to `agent_docs/building_the_project.md`\n```\n\n**Important**: Use `file:line` references instead of code snippets to avoid outdated context.\n\n### 4. Quality Constraints\n\nWhen creating or updating CLAUDE.md:\n\n1. **Target Length**: Keep it under 200 lines; shorter is better\n2. **No Style Rules**: Remove any linting/formatting instructions\n3. **No Task-Specific Instructions**: Move to separate files\n4. **No Code Snippets**: Use file references instead\n5. **No Redundant Information**: Don't repeat what's in package.json or README\n\n### 5. Essential Sections\n\nA well-structured CLAUDE.md should include:\n\n```markdown\n# Project Name\n\nBrief one-line description.\n\n## Tech Stack\n- Primary language and version\n- Key frameworks/libraries\n- Database/storage (if any)\n\n## Project Structure\n[Only for monorepos or complex structures]\n- `apps/` - Application entry points\n- `packages/` - Shared libraries\n\n## Development Commands\n- Install: `command`\n- Test: `command`\n- Build: `command`\n\n## Critical Conventions\n[Only non-obvious, high-impact conventions]\n- Convention 1 with brief explanation\n- Convention 2 with brief explanation\n\n## Known Issues / Gotchas\n[Things that consistently trip up developers]\n- Issue 1\n- Issue 2\n```\n\n### 6. Anti-Patterns to Avoid\n\n**DO NOT include:**\n- Code style guidelines (use linters)\n- Documentation on how to use Claude\n- Long explanations of obvious patterns\n- Copy-pasted code examples\n- Generic best practices (\"write clean code\")\n- Instructions for specific tasks\n- Auto-generated content\n- Extensive TODO lists\n\n### 7. Validation Checklist\n\nBefore finalizing, verify:\n\n- [ ] Kept under 200 lines; shorter is better\n- [ ] Every line applies to ALL sessions\n- [ ] No style/formatting rules\n- [ ] No code snippets (use file references)\n- [ ] Commands are verified to work\n- [ ] Progressive disclosure used for complex projects\n- [ ] Critical gotchas are documented\n- [ ] No redundancy with README.md\n\n## Output Format\n\n### For `create` or default:\n\n1. Analyze the project\n2. Draft a CLAUDE.md following the structure above\n3. Present the draft for review\n4. Write to the appropriate location after approval\n\n### For `update`:\n\n1. Read existing CLAUDE.md\n2. Audit against best practices\n3. Identify:\n   - Content to remove (style rules, code snippets, task-specific)\n   - Content to condense\n   - Missing essential information\n4. Present changes for review\n5. Apply changes after approval\n\n### For `audit`:\n\n1. Read existing CLAUDE.md\n2. Generate a report with:\n   - Current line count vs target\n   - Percentage of universally-applicable content\n   - List of anti-patterns found\n   - Recommendations for improvement\n3. Do NOT modify the file, only report\n\n## AGENTS.md Handling\n\nIf the user requests AGENTS.md creation/update:\n\n**Since v2.1.277, Claude Code reads `AGENTS.md` directly as project instructions** — but only when the working directory and every directory above it contain no `CLAUDE.md`, `.claude/CLAUDE.md`, or `CLAUDE.local.md`. `~/.claude/CLAUDE.md`, managed CLAUDE.md, and `.claude/rules/` do not count for that check and keep loading alongside. Which files are read is controlled by **Project instructions** in `/config`: `claude-md-or-agents-md` (default), `claude-md-and-agents-md`, `claude-md`, or `managed-only`. Where direct reading is unavailable — versions before v2.1.277 (before v2.1.281 on Bedrock/Vertex/Foundry, LLM gateways, or with telemetry disabled), or the first session after upgrading — fall back to importing it from CLAUDE.md with `@AGENTS.md`, or symlinking `CLAUDE.md` to it.\n\nAGENTS.md is a cross-tool project-context file — the same *category* of document as CLAUDE.md, not an agent-definition format. It exists so several coding agents can share one set of project conventions:\n- Build, test, and lint commands\n- Code style and architectural conventions\n- Repository layout and where things live\n\nSubagents are defined separately, in `.claude/agents/*.md` — not in AGENTS.md.\n\nApply similar principles:\n- Keep focused and concise\n- Use progressive disclosure\n- Reference external docs instead of embedding content\n\n## Notes\n\n- Always verify commands work before including them\n- When in doubt, leave it out - less is more\n- The system reminder tells Claude that CLAUDE.md \"may or may not be relevant\" - the more noise, the more it gets ignored\n- Monorepos benefit most from clear WHAT/WHY/HOW structure\n- Directory-specific CLAUDE.md files should be even more focused\n\n---\n\n**Last Updated**: October 18, 2026\n**Claude Code Version**: 2.1.302\n**Sources**:\n- https://code.claude.com/docs/en/skills\n- https://code.claude.com/docs/en/memory#agents-md\n- https://code.claude.com/docs/en/memory#when-agents-md-support-is-unavailable\n- https://code.claude.com/docs/en/memory\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n\n<!-- File: 03-skills/code-review-specialist/SKILL.md (Tokens: ~668 | Category: anthropic-skill) -->\n---\nname: code-review-specialist\ndescription: Comprehensive code review with security, performance, and quality analysis. Use when users ask to review code, analyze code quality, evaluate pull requests, or mention code review, security analysis, or performance optimization.\n---\n\n# Code Review Skill\n\nThis skill provides comprehensive code review capabilities focusing on:\n\n1. **Security Analysis**\n   - Authentication/authorization issues\n   - Data exposure risks\n   - Injection vulnerabilities\n   - Cryptographic weaknesses\n   - Sensitive data logging\n\n2. **Performance Review**\n   - Algorithm efficiency (Big O analysis)\n   - Memory optimization\n   - Database query optimization\n   - Caching opportunities\n   - Concurrency issues\n\n3. **Code Quality**\n   - SOLID principles\n   - Design patterns\n   - Naming conventions\n   - Documentation\n   - Test coverage\n\n4. **Maintainability**\n   - Code readability\n   - Function size (should be < 50 lines)\n   - Cyclomatic complexity\n   - Dependency management\n   - Type safety\n\n## Reference Files\n\nThis skill includes supporting files that you should read when performing reviews:\n\n- **`templates/review-checklist.md`** — Structured checklist covering security, performance, quality, and testing. Read this file and use it as a guide to ensure no category is missed during review.\n- **`templates/finding-template.md`** — Standard template for documenting individual findings with severity, location, code examples, and impact analysis. Read this file and use its format when reporting issues.\n- **`scripts/analyze-metrics.py`** — Python script that calculates code metrics (function count, class count, average line length, complexity score). Run this on the file under review to gather quantitative data.\n- **`scripts/compare-complexity.py`** — Python script that compares cyclomatic and cognitive complexity between two versions of a file. Run this with the before and after versions when reviewing refactoring changes.\n\n## Review Template\n\nFor each piece of code reviewed, provide:\n\n### Summary\n- Overall quality assessment (1-5)\n- Key findings count\n- Recommended priority areas\n\n### Critical Issues (if any)\n- **Issue**: Clear description\n- **Location**: File and line number\n- **Impact**: Why this matters\n- **Severity**: Critical/High/Medium\n- **Fix**: Code example\n\n### Findings by Category\n\n#### Security (if issues found)\nList security vulnerabilities with examples\n\n#### Performance (if issues found)\nList performance problems with complexity analysis\n\n#### Quality (if issues found)\nList code quality issues with refactoring suggestions\n\n#### Maintainability (if issues found)\nList maintainability problems with improvements\n\n## Version History\n\n- v1.0.0 (2024-12-10): Initial release with security, performance, quality, and maintainability analysis\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n\n<!-- File: 03-skills/doc-generator/SKILL.md (Tokens: ~459 | Category: anthropic-skill) -->\n---\nname: doc-generator\ndescription: Generate comprehensive, accurate API documentation from source code. Use when creating or updating API documentation, generating OpenAPI specs, or when users mention API docs, endpoints, or documentation.\n---\n\n# API Documentation Generator Skill\n\n## Generates\n\n- OpenAPI/Swagger specifications\n- API endpoint documentation\n- SDK usage examples\n- Integration guides\n- Error code references\n- Authentication guides\n\n## Documentation Structure\n\n### For Each Endpoint\n\n````markdown\n## GET /api/v1/users/:id\n\n### Description\nBrief explanation of what this endpoint does\n\n### Parameters\n\n| Name | Type | Required | Description |\n|------|------|----------|-------------|\n| id | string | Yes | User ID |\n\n### Response\n\n**200 Success**\n```json\n{\n  \"id\": \"usr_123\",\n  \"name\": \"John Doe\",\n  \"email\": \"john@example.com\",\n  \"created_at\": \"2025-01-15T10:30:00Z\"\n}\n```\n\n**404 Not Found**\n```json\n{\n  \"error\": \"USER_NOT_FOUND\",\n  \"message\": \"User does not exist\"\n}\n```\n\n### Examples\n\n**cURL**\n```bash\ncurl -X GET \"https://api.example.com/api/v1/users/usr_123\" \\\n  -H \"Authorization: Bearer YOUR_TOKEN\"\n```\n\n**JavaScript**\n```javascript\nconst user = await fetch('/api/v1/users/usr_123', {\n  headers: { 'Authorization': 'Bearer token' }\n}).then(r => r.json());\n```\n\n**Python**\n```python\nresponse = requests.get(\n    'https://api.example.com/api/v1/users/usr_123',\n    headers={'Authorization': 'Bearer token'}\n)\nuser = response.json()\n```\n````\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n\n<!-- File: 03-skills/refactor/references/code-smells.md (Tokens: ~3406 | Category: anthropic-skill) -->\n# Code Smells Catalog\n\nA comprehensive reference of code smells based on Martin Fowler's *Refactoring* (2nd Edition). Code smells are symptoms of deeper problems—they indicate that something might be wrong with your code's design.\n\n> \"A code smell is a surface indication that usually corresponds to a deeper problem in the system.\" — Martin Fowler\n\n---\n\n## Bloaters\n\nCode smells representing something that has grown too large to be handled effectively.\n\n### Long Method\n\n**Signs:**\n- Method exceeds 30-50 lines\n- Need to scroll to see the whole method\n- Multiple levels of nesting\n- Comments explaining what sections do\n\n**Why it's bad:**\n- Hard to understand\n- Difficult to test in isolation\n- Changes have unintended consequences\n- Duplicate logic hides inside\n\n**Refactorings:**\n- Extract Method\n- Replace Temp with Query\n- Introduce Parameter Object\n- Replace Method with Method Object\n- Decompose Conditional\n\n**Example (Before):**\n```javascript\nfunction processOrder(order) {\n  // Validate order (20 lines)\n  if (!order.items) throw new Error('No items');\n  if (order.items.length === 0) throw new Error('Empty order');\n  // ... more validation\n\n  // Calculate totals (30 lines)\n  let subtotal = 0;\n  for (const item of order.items) {\n    subtotal += item.price * item.quantity;\n  }\n  // ... tax, shipping, discounts\n\n  // Send notifications (20 lines)\n  // ... email logic\n}\n```\n\n**Example (After):**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const totals = calculateOrderTotals(order);\n  sendOrderNotifications(order, totals);\n  return { order, totals };\n}\n```\n\n---\n\n### Large Class\n\n**Signs:**\n- Class has many instance variables (>7-10)\n- Class has many methods (>15-20)\n- Class name is vague (Manager, Handler, Processor)\n- Methods don't use all instance variables\n\n**Why it's bad:**\n- Violates Single Responsibility Principle\n- Hard to test\n- Changes ripple through unrelated features\n- Difficult to reuse parts\n\n**Refactorings:**\n- Extract Class\n- Extract Subclass\n- Extract Interface\n\n**Detection:**\n```\nLines of code > 300\nNumber of methods > 15\nNumber of fields > 10\n```\n\n---\n\n### Primitive Obsession\n\n**Signs:**\n- Using primitives for domain concepts (string for email, int for money)\n- Arrays of primitives instead of objects\n- String constants for type codes\n- Magic numbers/strings\n\n**Why it's bad:**\n- No validation at type level\n- Logic scattered across codebase\n- Easy to pass wrong values\n- Missing domain concepts\n\n**Refactorings:**\n- Replace Primitive with Object\n- Replace Type Code with Class\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**Example (Before):**\n```javascript\nconst user = {\n  email: 'john@example.com',     // Just a string\n  phone: '1234567890',           // Just a string\n  status: 'active',              // Magic string\n  balance: 10050                 // Cents as integer\n};\n```\n\n**Example (After):**\n```javascript\nconst user = {\n  email: new Email('john@example.com'),\n  phone: new PhoneNumber('1234567890'),\n  status: UserStatus.ACTIVE,\n  balance: Money.cents(10050)\n};\n```\n\n---\n\n### Long Parameter List\n\n**Signs:**\n- Methods with 4+ parameters\n- Parameters that always appear together\n- Boolean flags changing method behavior\n- Null/undefined passed frequently\n\n**Why it's bad:**\n- Hard to call correctly\n- Parameter order confusion\n- Indicates method doing too much\n- Hard to add new parameters\n\n**Refactorings:**\n- Introduce Parameter Object\n- Preserve Whole Object\n- Replace Parameter with Method Call\n- Remove Flag Argument\n\n**Example (Before):**\n```javascript\nfunction createUser(firstName, lastName, email, phone,\n                    street, city, state, zip,\n                    isAdmin, isActive, createdBy) {\n  // ...\n}\n```\n\n**Example (After):**\n```javascript\nfunction createUser(personalInfo, address, options) {\n  // personalInfo: { firstName, lastName, email, phone }\n  // address: { street, city, state, zip }\n  // options: { isAdmin, isActive, createdBy }\n}\n```\n\n---\n\n### Data Clumps\n\n**Signs:**\n- Same 3+ fields appear together repeatedly\n- Parameters that always travel together\n- Classes with field subsets belonging together\n\n**Why it's bad:**\n- Duplicate handling logic\n- Missing abstraction\n- Harder to extend\n- Indicates hidden class\n\n**Refactorings:**\n- Extract Class\n- Introduce Parameter Object\n- Preserve Whole Object\n\n**Example:**\n```javascript\n// Data clump: (x, y, z) coordinates\nfunction movePoint(x, y, z, dx, dy, dz) { }\nfunction scalePoint(x, y, z, factor) { }\nfunction distanceBetween(x1, y1, z1, x2, y2, z2) { }\n\n// Extract Point3D class\nclass Point3D {\n  constructor(x, y, z) { }\n  move(delta) { }\n  scale(factor) { }\n  distanceTo(other) { }\n}\n```\n\n---\n\n## Object-Orientation Abusers\n\nSmells indicating incomplete or incorrect use of OOP principles.\n\n### Switch Statements\n\n**Signs:**\n- Long switch/case or if/else chains\n- Same switch in multiple places\n- Switch on type codes\n- Adding new cases requires changes everywhere\n\n**Why it's bad:**\n- Violates Open/Closed Principle\n- Changes ripple to all switch locations\n- Hard to extend\n- Often indicates missing polymorphism\n\n**Refactorings:**\n- Replace Conditional with Polymorphism\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**Example (Before):**\n```javascript\nfunction calculatePay(employee) {\n  switch (employee.type) {\n    case 'hourly':\n      return employee.hours * employee.rate;\n    case 'salaried':\n      return employee.salary / 12;\n    case 'commissioned':\n      return employee.sales * employee.commission;\n  }\n}\n```\n\n**Example (After):**\n```javascript\nclass HourlyEmployee {\n  calculatePay() {\n    return this.hours * this.rate;\n  }\n}\n\nclass SalariedEmployee {\n  calculatePay() {\n    return this.salary / 12;\n  }\n}\n```\n\n---\n\n### Temporary Field\n\n**Signs:**\n- Instance variables only used in some methods\n- Fields set conditionally\n- Complex initialization for certain cases\n\n**Why it's bad:**\n- Confusing—field exists but might be null\n- Hard to understand object state\n- Indicates conditional logic hiding\n\n**Refactorings:**\n- Extract Class\n- Introduce Null Object\n- Replace Temp Field with Local\n\n---\n\n### Refused Bequest\n\n**Signs:**\n- Subclass doesn't use inherited methods/data\n- Subclass overrides to do nothing\n- Inheritance used for code reuse, not IS-A relationship\n\n**Why it's bad:**\n- Wrong abstraction\n- Violates Liskov Substitution Principle\n- Misleading hierarchy\n\n**Refactorings:**\n- Push Down Method/Field\n- Replace Subclass with Delegate\n- Replace Inheritance with Delegation\n\n---\n\n### Alternative Classes with Different Interfaces\n\n**Signs:**\n- Two classes that do similar things\n- Different method names for same concept\n- Could be used interchangeably\n\n**Why it's bad:**\n- Duplicate implementations\n- No common interface\n- Hard to switch between\n\n**Refactorings:**\n- Rename Method\n- Move Method\n- Extract Superclass\n- Extract Interface\n\n---\n\n## Change Preventers\n\nSmells that make changes difficult—changing one thing requires changing many others.\n\n### Divergent Change\n\n**Signs:**\n- One class changed for multiple different reasons\n- Changes in different areas trigger same class edits\n- Class is a \"God class\"\n\n**Why it's bad:**\n- Violates Single Responsibility\n- High change frequency\n- Merge conflicts\n\n**Refactorings:**\n- Extract Class\n- Extract Superclass\n- Extract Subclass\n\n**Example:**\nA `User` class changes for:\n- Authentication changes\n- Profile changes\n- Billing changes\n- Notification changes\n\n→ Extract: `AuthService`, `ProfileService`, `BillingService`, `NotificationService`\n\n---\n\n### Shotgun Surgery\n\n**Signs:**\n- One change requires edits in many classes\n- Small feature needs touching 10+ files\n- Changes are scattered, hard to find all\n\n**Why it's bad:**\n- Easy to miss a spot\n- High coupling\n- Changes are error-prone\n\n**Refactorings:**\n- Move Method\n- Move Field\n- Inline Class\n\n**Detection:**\nLook for: adding one field requires changes in >5 files.\n\n---\n\n### Parallel Inheritance Hierarchies\n\n**Signs:**\n- Creating subclass in one hierarchy requires subclass in another\n- Class prefixes match (e.g., `DatabaseOrder`, `DatabaseProduct`)\n\n**Why it's bad:**\n- Double the maintenance\n- Coupling between hierarchies\n- Easy to forget one side\n\n**Refactorings:**\n- Move Method\n- Move Field\n- Eliminate one hierarchy\n\n---\n\n## Dispensables\n\nSomething unnecessary that should be removed.\n\n### Comments (Excessive)\n\n**Signs:**\n- Comments explaining what code does\n- Commented-out code\n- TODO/FIXME that linger forever\n- Apologies in comments\n\n**Why it's bad:**\n- Comments lie (get out of sync)\n- Code should be self-documenting\n- Dead code causes confusion\n\n**Refactorings:**\n- Extract Method (name explains what)\n- Rename (clarity without comments)\n- Remove commented code\n- Introduce Assertion\n\n**Good vs Bad Comments:**\n```javascript\n// BAD: Explaining what\n// Loop through users and check if active\nfor (const user of users) {\n  if (user.status === 'active') { }\n}\n\n// GOOD: Explaining why\n// Active users only - inactive are handled by cleanup job\nconst activeUsers = users.filter(u => u.isActive);\n```\n\n---\n\n### Duplicate Code\n\n**Signs:**\n- Same code in multiple places\n- Similar code with small variations\n- Copy-paste patterns\n\n**Why it's bad:**\n- Bug fixes needed in multiple places\n- Inconsistency risk\n- Bloated codebase\n\n**Refactorings:**\n- Extract Method\n- Extract Class\n- Pull Up Method (in hierarchies)\n- Form Template Method\n\n**Detection Rule:**\nAny code duplicated 3+ times should be extracted.\n\n---\n\n### Lazy Class\n\n**Signs:**\n- Class doesn't do enough to justify existence\n- Wrapper with no added value\n- Result of over-engineering\n\n**Why it's bad:**\n- Maintenance overhead\n- Unnecessary indirection\n- Complexity without benefit\n\n**Refactorings:**\n- Inline Class\n- Collapse Hierarchy\n\n---\n\n### Dead Code\n\n**Signs:**\n- Unreachable code\n- Unused variables/methods/classes\n- Commented-out code\n- Code behind impossible conditions\n\n**Why it's bad:**\n- Confusion\n- Maintenance burden\n- Slows down understanding\n\n**Refactorings:**\n- Remove Dead Code\n- Safe Delete\n\n**Detection:**\n```bash\n# Look for unused exports\n# Look for unreferenced functions\n# IDE \"unused\" warnings\n```\n\n---\n\n### Speculative Generality\n\n**Signs:**\n- Abstract classes with one subclass\n- Unused parameters \"for future use\"\n- Methods that only delegate\n- \"Framework\" for one use case\n\n**Why it's bad:**\n- Complexity without benefit\n- YAGNI (You Ain't Gonna Need It)\n- Harder to understand\n\n**Refactorings:**\n- Collapse Hierarchy\n- Inline Class\n- Remove Parameter\n- Rename Method\n\n---\n\n## Couplers\n\nSmells that represent excessive coupling between classes.\n\n### Feature Envy\n\n**Signs:**\n- Method uses more data from another class than its own\n- Many getter calls to another object\n- Data and behavior are separated\n\n**Why it's bad:**\n- Wrong location for behavior\n- Poor encapsulation\n- Hard to maintain\n\n**Refactorings:**\n- Move Method\n- Move Field\n- Extract Method (then move)\n\n**Example (Before):**\n```javascript\nclass Order {\n  getDiscountedPrice(customer) {\n    // Uses customer data heavily\n    if (customer.loyaltyYears > 5) {\n      return this.price * customer.discountRate;\n    }\n    return this.price;\n  }\n}\n```\n\n**Example (After):**\n```javascript\nclass Customer {\n  getDiscountedPriceFor(price) {\n    if (this.loyaltyYears > 5) {\n      return price * this.discountRate;\n    }\n    return price;\n  }\n}\n```\n\n---\n\n### Inappropriate Intimacy\n\n**Signs:**\n- Classes access each other's private parts\n- Bidirectional references\n- Subclasses know too much about parents\n\n**Why it's bad:**\n- High coupling\n- Changes cascade\n- Hard to modify one without other\n\n**Refactorings:**\n- Move Method\n- Move Field\n- Change Bidirectional to Unidirectional\n- Extract Class\n- Hide Delegate\n\n---\n\n### Message Chains\n\n**Signs:**\n- Long chains of method calls: `a.getB().getC().getD().getValue()`\n- Client depends on navigation structure\n- \"Train wreck\" code\n\n**Why it's bad:**\n- Fragile—any change breaks chain\n- Violates Law of Demeter\n- Coupling to structure\n\n**Refactorings:**\n- Hide Delegate\n- Extract Method\n- Move Method\n\n**Example:**\n```javascript\n// Bad: Message chain\nconst managerName = employee.getDepartment().getManager().getName();\n\n// Better: Hide delegation\nconst managerName = employee.getManagerName();\n```\n\n---\n\n### Middle Man\n\n**Signs:**\n- Class that only delegates to another\n- Half the methods are delegations\n- No added value\n\n**Why it's bad:**\n- Unnecessary indirection\n- Maintenance overhead\n- Confusing architecture\n\n**Refactorings:**\n- Remove Middle Man\n- Inline Method\n\n---\n\n## Smell Severity Guide\n\n| Severity | Description | Action |\n|----------|-------------|--------|\n| **Critical** | Blocks development, causes bugs | Fix immediately |\n| **High** | Significant maintenance burden | Fix in current sprint |\n| **Medium** | Noticeable but manageable | Plan for near future |\n| **Low** | Minor inconvenience | Fix opportunistically |\n\n---\n\n## Quick Detection Checklist\n\nUse this checklist when scanning code:\n\n- [ ] Any method > 30 lines?\n- [ ] Any class > 300 lines?\n- [ ] Any method with > 4 parameters?\n- [ ] Any duplicated code blocks?\n- [ ] Any switch/case on type codes?\n- [ ] Any unused code?\n- [ ] Any methods using another class's data heavily?\n- [ ] Any long chains of method calls?\n- [ ] Any comments explaining \"what\" not \"why\"?\n- [ ] Any primitives that should be objects?\n\n---\n\n## Further Reading\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Kerievsky, J. (2004). *Refactoring to Patterns*\n- Feathers, M. (2004). *Working Effectively with Legacy Code*\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n\n<!-- File: 03-skills/refactor/references/refactoring-catalog.md (Tokens: ~5933 | Category: anthropic-skill) -->\n# Refactoring Catalog\n\nA curated catalog of refactoring techniques from Martin Fowler's *Refactoring* (2nd Edition). Each refactoring includes motivation, step-by-step mechanics, and examples.\n\n> \"A refactoring is defined by its mechanics—the precise sequence of steps that you follow to carry out the change.\" — Martin Fowler\n\n---\n\n## How to Use This Catalog\n\n1. **Identify the smell** using the code smells reference\n2. **Find the matching refactoring** in this catalog\n3. **Follow the mechanics** step by step\n4. **Test after each step** to ensure behavior is preserved\n\n**Golden Rule**: If any step takes more than 10 minutes, break it into smaller steps.\n\n---\n\n## Most Common Refactorings\n\n### Extract Method\n\n**When to use**: Long method, duplicate code, need to name a concept\n\n**Motivation**: Turn a code fragment into a method whose name explains the purpose.\n\n**Mechanics**:\n1. Create a new method named for what it does (not how)\n2. Copy the code fragment into the new method\n3. Scan for local variables used in the fragment\n4. Pass local variables as parameters (or declare in method)\n5. Handle return values appropriately\n6. Replace the original fragment with a call to the new method\n7. Test\n\n**Before**:\n```javascript\nfunction printOwing(invoice) {\n  let outstanding = 0;\n\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n\n  // Calculate outstanding\n  for (const order of invoice.orders) {\n    outstanding += order.amount;\n  }\n\n  // Print details\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n**After**:\n```javascript\nfunction printOwing(invoice) {\n  printBanner();\n  const outstanding = calculateOutstanding(invoice);\n  printDetails(invoice, outstanding);\n}\n\nfunction printBanner() {\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n}\n\nfunction calculateOutstanding(invoice) {\n  return invoice.orders.reduce((sum, order) => sum + order.amount, 0);\n}\n\nfunction printDetails(invoice, outstanding) {\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n---\n\n### Inline Method\n\n**When to use**: Method body is as clear as its name, excessive delegation\n\n**Motivation**: Remove needless indirection when the method doesn't add value.\n\n**Mechanics**:\n1. Check that the method isn't polymorphic\n2. Find all calls to the method\n3. Replace each call with the method body\n4. Test after each replacement\n5. Remove the method definition\n\n**Before**:\n```javascript\nfunction getRating(driver) {\n  return moreThanFiveLateDeliveries(driver) ? 2 : 1;\n}\n\nfunction moreThanFiveLateDeliveries(driver) {\n  return driver.numberOfLateDeliveries > 5;\n}\n```\n\n**After**:\n```javascript\nfunction getRating(driver) {\n  return driver.numberOfLateDeliveries > 5 ? 2 : 1;\n}\n```\n\n---\n\n### Extract Variable\n\n**When to use**: Complex expression that is hard to understand\n\n**Motivation**: Give a name to a piece of a complex expression.\n\n**Mechanics**:\n1. Ensure the expression has no side effects\n2. Declare an immutable variable\n3. Set it to the result of the expression (or part)\n4. Replace the original expression with the variable\n5. Test\n\n**Before**:\n```javascript\nreturn order.quantity * order.itemPrice -\n  Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +\n  Math.min(order.quantity * order.itemPrice * 0.1, 100);\n```\n\n**After**:\n```javascript\nconst basePrice = order.quantity * order.itemPrice;\nconst quantityDiscount = Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;\nconst shipping = Math.min(basePrice * 0.1, 100);\nreturn basePrice - quantityDiscount + shipping;\n```\n\n---\n\n### Inline Variable\n\n**When to use**: Variable name doesn't communicate more than the expression\n\n**Motivation**: Remove unnecessary indirection.\n\n**Mechanics**:\n1. Check that the right-hand side has no side effects\n2. If variable isn't immutable, make it so and test\n3. Find the first reference and replace with the expression\n4. Test\n5. Repeat for all references\n6. Remove the declaration and assignment\n7. Test\n\n---\n\n### Rename Variable\n\n**When to use**: Name doesn't clearly communicate purpose\n\n**Motivation**: Good names are crucial for clean code.\n\n**Mechanics**:\n1. If variable is widely used, consider encapsulating\n2. Find all references\n3. Change each reference\n4. Test\n\n**Tips**:\n- Use intention-revealing names\n- Avoid abbreviations\n- Use domain terminology\n\n```javascript\n// Bad\nconst d = 30;\nconst x = users.filter(u => u.a);\n\n// Good\nconst daysSinceLastLogin = 30;\nconst activeUsers = users.filter(user => user.isActive);\n```\n\n---\n\n### Change Function Declaration\n\n**When to use**: Function name doesn't explain purpose, parameters need change\n\n**Motivation**: Good function names make code self-documenting.\n\n**Mechanics (Simple)**:\n1. Remove parameters not needed\n2. Change the name\n3. Add parameters needed\n4. Test\n\n**Mechanics (Migration - for complex changes)**:\n1. If removing parameter, make sure it's not used\n2. Create new function with desired declaration\n3. Have old function call new function\n4. Test\n5. Change callers to use new function\n6. Test after each\n7. Remove old function\n\n**Before**:\n```javascript\nfunction circum(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n**After**:\n```javascript\nfunction circumference(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n---\n\n### Encapsulate Variable\n\n**When to use**: Direct access to data from multiple places\n\n**Motivation**: Provide a clear access point for data manipulation.\n\n**Mechanics**:\n1. Create getter and setter functions\n2. Find all references\n3. Replace reads with getter\n4. Replace writes with setter\n5. Test after each change\n6. Restrict visibility of the variable\n\n**Before**:\n```javascript\nlet defaultOwner = { firstName: \"Martin\", lastName: \"Fowler\" };\n\n// Used in many places\nspaceship.owner = defaultOwner;\n```\n\n**After**:\n```javascript\nlet defaultOwnerData = { firstName: \"Martin\", lastName: \"Fowler\" };\n\nfunction defaultOwner() { return defaultOwnerData; }\nfunction setDefaultOwner(arg) { defaultOwnerData = arg; }\n\nspaceship.owner = defaultOwner();\n```\n\n---\n\n### Introduce Parameter Object\n\n**When to use**: Several parameters that frequently go together\n\n**Motivation**: Group data that naturally belongs together.\n\n**Mechanics**:\n1. Create a new class/structure for the grouped parameters\n2. Test\n3. Use Change Function Declaration to add the new object\n4. Test\n5. For each parameter in the group, remove it from the function and use the new object\n6. Test after each\n\n**Before**:\n```javascript\nfunction amountInvoiced(startDate, endDate) { ... }\nfunction amountReceived(startDate, endDate) { ... }\nfunction amountOverdue(startDate, endDate) { ... }\n```\n\n**After**:\n```javascript\nclass DateRange {\n  constructor(start, end) {\n    this.start = start;\n    this.end = end;\n  }\n}\n\nfunction amountInvoiced(dateRange) { ... }\nfunction amountReceived(dateRange) { ... }\nfunction amountOverdue(dateRange) { ... }\n```\n\n---\n\n### Combine Functions into Class\n\n**When to use**: Several functions operate on the same data\n\n**Motivation**: Group functions with the data they operate on.\n\n**Mechanics**:\n1. Apply Encapsulate Record to the common data\n2. Move each function into the class\n3. Test after each move\n4. Replace data arguments with uses of class fields\n\n**Before**:\n```javascript\nfunction base(reading) { ... }\nfunction taxableCharge(reading) { ... }\nfunction calculateBaseCharge(reading) { ... }\n```\n\n**After**:\n```javascript\nclass Reading {\n  constructor(data) { this._data = data; }\n\n  get base() { ... }\n  get taxableCharge() { ... }\n  get calculateBaseCharge() { ... }\n}\n```\n\n---\n\n### Split Phase\n\n**When to use**: Code deals with two different things\n\n**Motivation**: Separate code into distinct phases with clear boundaries.\n\n**Mechanics**:\n1. Create a second function for the second phase\n2. Test\n3. Introduce an intermediate data structure between phases\n4. Test\n5. Extract first phase into its own function\n6. Test\n\n**Before**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  const shippingPerCase = (basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = quantity * shippingPerCase;\n  return basePrice - discount + shippingCost;\n}\n```\n\n**After**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const priceData = calculatePricingData(product, quantity);\n  return applyShipping(priceData, shippingMethod);\n}\n\nfunction calculatePricingData(product, quantity) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  return { basePrice, quantity, discount };\n}\n\nfunction applyShipping(priceData, shippingMethod) {\n  const shippingPerCase = (priceData.basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = priceData.quantity * shippingPerCase;\n  return priceData.basePrice - priceData.discount + shippingCost;\n}\n```\n\n---\n\n## Moving Features\n\n### Move Method\n\n**When to use**: Method uses more features of another class than its own\n\n**Motivation**: Put functions with the data they use most.\n\n**Mechanics**:\n1. Examine all program elements used by method in its class\n2. Check if method is polymorphic\n3. Copy method to target class\n4. Adjust for new context\n5. Make original method delegate to target\n6. Test\n7. Consider removing original method\n\n---\n\n### Move Field\n\n**When to use**: Field is used more by another class\n\n**Motivation**: Keep data with the functions that use it.\n\n**Mechanics**:\n1. Encapsulate the field if not already\n2. Test\n3. Create field in target\n4. Update references to use target field\n5. Test\n6. Remove original field\n\n---\n\n### Move Statements into Function\n\n**When to use**: Same code always appears with a function call\n\n**Motivation**: Remove duplication by moving repeated code into the function.\n\n**Mechanics**:\n1. Extract the repeated code into a function if not already\n2. Move statements into that function\n3. Test\n4. If callers no longer need standalone statements, remove them\n\n---\n\n### Move Statements to Callers\n\n**When to use**: Common behavior varies between callers\n\n**Motivation**: When behavior needs to differ, move it out of the function.\n\n**Mechanics**:\n1. Use Extract Method on the code to move\n2. Use Inline Method on the original function\n3. Remove the now-inlined call\n4. Move extracted code to each caller\n5. Test\n\n---\n\n## Organizing Data\n\n### Replace Primitive with Object\n\n**When to use**: Data item needs more behavior than simple value\n\n**Motivation**: Encapsulate data with its behavior.\n\n**Mechanics**:\n1. Apply Encapsulate Variable\n2. Create a simple value class\n3. Change the setter to create a new instance\n4. Change the getter to return the value\n5. Test\n6. Add richer behavior to the new class\n\n**Before**:\n```javascript\nclass Order {\n  constructor(data) {\n    this.priority = data.priority; // string: \"high\", \"rush\", etc.\n  }\n}\n\n// Usage\nif (order.priority === \"high\" || order.priority === \"rush\") { ... }\n```\n\n**After**:\n```javascript\nclass Priority {\n  constructor(value) {\n    if (!Priority.legalValues().includes(value))\n      throw new Error(`Invalid priority: ${value}`);\n    this._value = value;\n  }\n\n  static legalValues() { return ['low', 'normal', 'high', 'rush']; }\n  get value() { return this._value; }\n\n  higherThan(other) {\n    return Priority.legalValues().indexOf(this._value) >\n           Priority.legalValues().indexOf(other._value);\n  }\n}\n\n// Usage\nif (order.priority.higherThan(new Priority(\"normal\"))) { ... }\n```\n\n---\n\n### Replace Temp with Query\n\n**When to use**: Temporary variable holds result of an expression\n\n**Motivation**: Make the code clearer by extracting the expression into a function.\n\n**Mechanics**:\n1. Check that the variable is assigned only once\n2. Extract the assignment's right-hand side into a method\n3. Replace references to the temp with the method call\n4. Test\n5. Remove the temp declaration and assignment\n\n**Before**:\n```javascript\nconst basePrice = this._quantity * this._itemPrice;\nif (basePrice > 1000) {\n  return basePrice * 0.95;\n} else {\n  return basePrice * 0.98;\n}\n```\n\n**After**:\n```javascript\nget basePrice() {\n  return this._quantity * this._itemPrice;\n}\n\n// In the method\nif (this.basePrice > 1000) {\n  return this.basePrice * 0.95;\n} else {\n  return this.basePrice * 0.98;\n}\n```\n\n---\n\n## Simplifying Conditional Logic\n\n### Decompose Conditional\n\n**When to use**: Complex conditional (if-then-else) statement\n\n**Motivation**: Make the intention clear by extracting conditions and actions.\n\n**Mechanics**:\n1. Apply Extract Method on the condition\n2. Apply Extract Method on the then-branch\n3. Apply Extract Method on the else-branch (if present)\n\n**Before**:\n```javascript\nif (!aDate.isBefore(plan.summerStart) && !aDate.isAfter(plan.summerEnd)) {\n  charge = quantity * plan.summerRate;\n} else {\n  charge = quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n**After**:\n```javascript\nif (isSummer(aDate, plan)) {\n  charge = summerCharge(quantity, plan);\n} else {\n  charge = regularCharge(quantity, plan);\n}\n\nfunction isSummer(date, plan) {\n  return !date.isBefore(plan.summerStart) && !date.isAfter(plan.summerEnd);\n}\n\nfunction summerCharge(quantity, plan) {\n  return quantity * plan.summerRate;\n}\n\nfunction regularCharge(quantity, plan) {\n  return quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n---\n\n### Consolidate Conditional Expression\n\n**When to use**: Multiple conditions with the same result\n\n**Motivation**: Make it clear that conditions are a single check.\n\n**Mechanics**:\n1. Verify no side effects in conditions\n2. Combine conditions using `and` or `or`\n3. Consider Extract Method on the combined condition\n\n**Before**:\n```javascript\nif (employee.seniority < 2) return 0;\nif (employee.monthsDisabled > 12) return 0;\nif (employee.isPartTime) return 0;\n```\n\n**After**:\n```javascript\nif (isNotEligibleForDisability(employee)) return 0;\n\nfunction isNotEligibleForDisability(employee) {\n  return employee.seniority < 2 ||\n         employee.monthsDisabled > 12 ||\n         employee.isPartTime;\n}\n```\n\n---\n\n### Replace Nested Conditional with Guard Clauses\n\n**When to use**: Deeply nested conditionals making flow hard to follow\n\n**Motivation**: Use guard clauses for special cases, keeping normal flow clear.\n\n**Mechanics**:\n1. Find the special case conditions\n2. Replace them with guard clauses that return early\n3. Test after each change\n\n**Before**:\n```javascript\nfunction payAmount(employee) {\n  let result;\n  if (employee.isSeparated) {\n    result = { amount: 0, reasonCode: \"SEP\" };\n  } else {\n    if (employee.isRetired) {\n      result = { amount: 0, reasonCode: \"RET\" };\n    } else {\n      result = calculateNormalPay(employee);\n    }\n  }\n  return result;\n}\n```\n\n**After**:\n```javascript\nfunction payAmount(employee) {\n  if (employee.isSeparated) return { amount: 0, reasonCode: \"SEP\" };\n  if (employee.isRetired) return { amount: 0, reasonCode: \"RET\" };\n  return calculateNormalPay(employee);\n}\n```\n\n---\n\n### Replace Conditional with Polymorphism\n\n**When to use**: Switch/case based on type, conditional logic varying by type\n\n**Motivation**: Let objects handle their own behavior.\n\n**Mechanics**:\n1. Create class hierarchy (if not exists)\n2. Use Factory Function for object creation\n3. Move conditional logic into superclass method\n4. Create subclass method for each case\n5. Remove original conditional\n\n**Before**:\n```javascript\nfunction plumages(birds) {\n  return birds.map(b => plumage(b));\n}\n\nfunction plumage(bird) {\n  switch (bird.type) {\n    case 'EuropeanSwallow':\n      return \"average\";\n    case 'AfricanSwallow':\n      return (bird.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n    case 'NorwegianBlueParrot':\n      return (bird.voltage > 100) ? \"scorched\" : \"beautiful\";\n    default:\n      return \"unknown\";\n  }\n}\n```\n\n**After**:\n```javascript\nclass Bird {\n  get plumage() { return \"unknown\"; }\n}\n\nclass EuropeanSwallow extends Bird {\n  get plumage() { return \"average\"; }\n}\n\nclass AfricanSwallow extends Bird {\n  get plumage() {\n    return (this.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n  }\n}\n\nclass NorwegianBlueParrot extends Bird {\n  get plumage() {\n    return (this.voltage > 100) ? \"scorched\" : \"beautiful\";\n  }\n}\n\nfunction createBird(data) {\n  switch (data.type) {\n    case 'EuropeanSwallow': return new EuropeanSwallow(data);\n    case 'AfricanSwallow': return new AfricanSwallow(data);\n    case 'NorwegianBlueParrot': return new NorwegianBlueParrot(data);\n    default: return new Bird(data);\n  }\n}\n```\n\n---\n\n### Introduce Special Case (Null Object)\n\n**When to use**: Repeated null checks for special cases\n\n**Motivation**: Return a special object that handles the special case.\n\n**Mechanics**:\n1. Create special case class with expected interface\n2. Add isSpecialCase check\n3. Introduce factory method\n4. Replace null checks with special case object usage\n5. Test\n\n**Before**:\n```javascript\nconst customer = site.customer;\n// ... many places checking\nif (customer === \"unknown\") {\n  customerName = \"occupant\";\n} else {\n  customerName = customer.name;\n}\n```\n\n**After**:\n```javascript\nclass UnknownCustomer {\n  get name() { return \"occupant\"; }\n  get billingPlan() { return registry.defaultPlan; }\n}\n\n// Factory method\nfunction customer(site) {\n  return site.customer === \"unknown\"\n    ? new UnknownCustomer()\n    : site.customer;\n}\n\n// Usage - no null checks needed\nconst customerName = customer.name;\n```\n\n---\n\n## Refactoring APIs\n\n### Separate Query from Modifier\n\n**When to use**: Function both returns a value and has side effects\n\n**Motivation**: Make it clear which operations have side effects.\n\n**Mechanics**:\n1. Create a new query function\n2. Copy original function's return logic\n3. Modify original to return void\n4. Replace calls that use return value\n5. Test\n\n**Before**:\n```javascript\nfunction alertForMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") {\n      setOffAlarms();\n      return \"Don\";\n    }\n    if (p === \"John\") {\n      setOffAlarms();\n      return \"John\";\n    }\n  }\n  return \"\";\n}\n```\n\n**After**:\n```javascript\nfunction findMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") return \"Don\";\n    if (p === \"John\") return \"John\";\n  }\n  return \"\";\n}\n\nfunction alertForMiscreant(people) {\n  if (findMiscreant(people) !== \"\") setOffAlarms();\n}\n```\n\n---\n\n### Parameterize Function\n\n**When to use**: Several functions doing similar things with different values\n\n**Motivation**: Remove duplication by adding a parameter.\n\n**Mechanics**:\n1. Select one function\n2. Add parameter for the varying literal\n3. Change body to use the parameter\n4. Test\n5. Change callers to use the parameterized version\n6. Remove now-unused functions\n\n**Before**:\n```javascript\nfunction tenPercentRaise(person) {\n  person.salary = person.salary * 1.10;\n}\n\nfunction fivePercentRaise(person) {\n  person.salary = person.salary * 1.05;\n}\n```\n\n**After**:\n```javascript\nfunction raise(person, factor) {\n  person.salary = person.salary * (1 + factor);\n}\n\n// Usage\nraise(person, 0.10);\nraise(person, 0.05);\n```\n\n---\n\n### Remove Flag Argument\n\n**When to use**: Boolean parameter that changes function behavior\n\n**Motivation**: Make the behavior explicit through separate functions.\n\n**Mechanics**:\n1. Create explicit function for each flag value\n2. Replace each call with appropriate new function\n3. Test after each change\n4. Remove original function\n\n**Before**:\n```javascript\nfunction bookConcert(customer, isPremium) {\n  if (isPremium) {\n    // premium booking logic\n  } else {\n    // regular booking logic\n  }\n}\n\nbookConcert(customer, true);\nbookConcert(customer, false);\n```\n\n**After**:\n```javascript\nfunction bookPremiumConcert(customer) {\n  // premium booking logic\n}\n\nfunction bookRegularConcert(customer) {\n  // regular booking logic\n}\n\nbookPremiumConcert(customer);\nbookRegularConcert(customer);\n```\n\n---\n\n## Dealing with Inheritance\n\n### Pull Up Method\n\n**When to use**: Same method in multiple subclasses\n\n**Motivation**: Remove duplication in class hierarchy.\n\n**Mechanics**:\n1. Inspect methods to ensure they are identical\n2. Check signatures are the same\n3. Create new method in superclass\n4. Copy body from one subclass\n5. Delete one subclass method, test\n6. Delete other subclass methods, test each\n\n---\n\n### Push Down Method\n\n**When to use**: Behavior relevant only to a subset of subclasses\n\n**Motivation**: Put method where it's used.\n\n**Mechanics**:\n1. Copy method to each subclass that needs it\n2. Remove method from superclass\n3. Test\n4. Remove from subclasses that don't need it\n5. Test\n\n---\n\n### Replace Subclass with Delegate\n\n**When to use**: Inheritance is being used incorrectly, need more flexibility\n\n**Motivation**: Prefer composition over inheritance when appropriate.\n\n**Mechanics**:\n1. Create empty class for delegate\n2. Add field to host class holding delegate\n3. Create constructor for delegate, called from host\n4. Move features to delegate\n5. Test after each move\n6. Replace inheritance with delegation\n\n---\n\n## Extract Class\n\n**When to use**: Large class with multiple responsibilities\n\n**Motivation**: Split class to maintain single responsibility.\n\n**Mechanics**:\n1. Decide how to split responsibilities\n2. Create new class\n3. Move field from original to new class\n4. Test\n5. Move methods from original to new class\n6. Test after each move\n7. Review and rename both classes\n8. Decide how to expose new class\n\n**Before**:\n```javascript\nclass Person {\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get officeAreaCode() { return this._officeAreaCode; }\n  set officeAreaCode(arg) { this._officeAreaCode = arg; }\n  get officeNumber() { return this._officeNumber; }\n  set officeNumber(arg) { this._officeNumber = arg; }\n\n  get telephoneNumber() {\n    return `(${this._officeAreaCode}) ${this._officeNumber}`;\n  }\n}\n```\n\n**After**:\n```javascript\nclass Person {\n  constructor() {\n    this._telephoneNumber = new TelephoneNumber();\n  }\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get telephoneNumber() { return this._telephoneNumber.toString(); }\n  get officeAreaCode() { return this._telephoneNumber.areaCode; }\n  set officeAreaCode(arg) { this._telephoneNumber.areaCode = arg; }\n}\n\nclass TelephoneNumber {\n  get areaCode() { return this._areaCode; }\n  set areaCode(arg) { this._areaCode = arg; }\n  get number() { return this._number; }\n  set number(arg) { this._number = arg; }\n  toString() { return `(${this._areaCode}) ${this._number}`; }\n}\n```\n\n---\n\n## Quick Reference: Smell to Refactoring\n\n| Code Smell | Primary Refactoring | Alternative |\n|------------|-------------------|-------------|\n| Long Method | Extract Method | Replace Temp with Query |\n| Duplicate Code | Extract Method | Pull Up Method |\n| Large Class | Extract Class | Extract Subclass |\n| Long Parameter List | Introduce Parameter Object | Preserve Whole Object |\n| Feature Envy | Move Method | Extract Method + Move |\n| Data Clumps | Extract Class | Introduce Parameter Object |\n| Primitive Obsession | Replace Primitive with Object | Replace Type Code |\n| Switch Statements | Replace Conditional with Polymorphism | Replace Type Code |\n| Temporary Field | Extract Class | Introduce Null Object |\n| Message Chains | Hide Delegate | Extract Method |\n| Middle Man | Remove Middle Man | Inline Method |\n| Divergent Change | Extract Class | Split Phase |\n| Shotgun Surgery | Move Method | Inline Class |\n| Dead Code | Remove Dead Code | - |\n| Speculative Generality | Collapse Hierarchy | Inline Class |\n\n---\n\n## Further Reading\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Online catalog: https://refactoring.com/catalog/\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n\n<!-- File: 03-skills/refactor/SKILL.md (Tokens: ~2770 | Category: anthropic-skill) -->\n---\nname: refactor\ndescription: Systematic code refactoring based on Martin Fowler's methodology. Use when users ask to refactor code, improve code structure, reduce technical debt, clean up legacy code, eliminate code smells, or improve code maintainability. This skill guides through a phased approach with research, planning, and safe incremental implementation.\n---\n\n# Code Refactoring Skill\n\nA systematic approach to refactoring code based on Martin Fowler's *Refactoring: Improving the Design of Existing Code* (2nd Edition). This skill emphasizes safe, incremental changes backed by tests.\n\n> \"Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure.\" — Martin Fowler\n\n## Core Principles\n\n1. **Behavior Preservation**: External behavior must remain unchanged\n2. **Small Steps**: Make tiny, testable changes\n3. **Test-Driven**: Tests are the safety net\n4. **Continuous**: Refactoring is ongoing, not a one-time event\n5. **Collaborative**: User approval required at each phase\n\n## Workflow Overview\n\n```\nPhase 1: Research & Analysis\n    ↓\nPhase 2: Test Coverage Assessment\n    ↓\nPhase 3: Code Smell Identification\n    ↓\nPhase 4: Refactoring Plan Creation\n    ↓\nPhase 5: Incremental Implementation\n    ↓\nPhase 6: Review & Iteration\n```\n\n---\n\n## Phase 1: Research & Analysis\n\n### Objectives\n- Understand the codebase structure and purpose\n- Identify the scope of refactoring\n- Gather context about business requirements\n\n### Questions to Ask User\nBefore starting, clarify:\n\n1. **Scope**: Which files/modules/functions need refactoring?\n2. **Goals**: What problems are you trying to solve? (readability, performance, maintainability)\n3. **Constraints**: Are there any areas that should NOT be changed?\n4. **Timeline pressure**: Is this blocking other work?\n5. **Test status**: Do tests exist? Are they passing?\n\n### Actions\n- [ ] Read and understand the target code\n- [ ] Identify dependencies and integrations\n- [ ] Document current architecture\n- [ ] Note any existing technical debt markers (TODOs, FIXMEs)\n\n### Output\nPresent findings to user:\n- Code structure summary\n- Identified problem areas\n- Initial recommendations\n- **Request approval to proceed**\n\n---\n\n## Phase 2: Test Coverage Assessment\n\n### Why Tests Matter\n> \"Refactoring without tests is like driving without a seatbelt.\" — Martin Fowler\n\nTests are the **key enabler** of safe refactoring. Without them, you risk introducing bugs.\n\n### Assessment Steps\n\n1. **Check for existing tests**\n   ```bash\n   # Look for test files\n   find . -name \"*test*\" -o -name \"*spec*\" | head -20\n   ```\n\n2. **Run existing tests**\n   ```bash\n   # JavaScript/TypeScript\n   npm test\n\n   # Python\n   pytest -v\n\n   # Java\n   mvn test\n   ```\n\n3. **Check coverage (if available)**\n   ```bash\n   # JavaScript\n   npm run test:coverage\n\n   # Python\n   pytest --cov=.\n   ```\n\n### Decision Point: Ask User\n\n**If tests exist and pass:**\n- Proceed to Phase 3\n\n**If tests are missing or incomplete:**\nPresent options:\n1. Write tests first (recommended)\n2. Add tests incrementally during refactoring\n3. Proceed without tests (risky - requires user acknowledgment)\n\n**If tests are failing:**\n- STOP. Fix failing tests before refactoring\n- Ask user: Should we fix tests first?\n\n### Test Writing Guidelines (if needed)\n\nFor each function being refactored, ensure tests cover:\n- Happy path (normal operation)\n- Edge cases (empty inputs, null, boundaries)\n- Error scenarios (invalid inputs, exceptions)\n\nUse the \"red-green-refactor\" cycle:\n1. Write failing test (red)\n2. Make it pass (green)\n3. Refactor\n\n---\n\n## Phase 3: Code Smell Identification\n\n### What Are Code Smells?\nSymptoms of deeper problems in code. They're not bugs, but indicators that the code could be improved.\n\n### Common Code Smells to Check\n\nSee [references/code-smells.md](references/code-smells.md) for the complete catalog.\n\n#### Quick Reference\n\n| Smell | Signs | Impact |\n|-------|-------|--------|\n| **Long Method** | Methods > 30-50 lines | Hard to understand, test, maintain |\n| **Duplicated Code** | Same logic in multiple places | Bug fixes needed in multiple places |\n| **Large Class** | Class with too many responsibilities | Violates Single Responsibility |\n| **Feature Envy** | Method uses another class's data more | Poor encapsulation |\n| **Primitive Obsession** | Overuse of primitives instead of objects | Missing domain concepts |\n| **Long Parameter List** | Methods with 4+ parameters | Hard to call correctly |\n| **Data Clumps** | Same data items appearing together | Missing abstraction |\n| **Switch Statements** | Complex switch/if-else chains | Hard to extend |\n| **Speculative Generality** | Code \"just in case\" | Unnecessary complexity |\n| **Dead Code** | Unused code | Confusion, maintenance burden |\n\n### Analysis Steps\n\n1. **Automated Analysis** (if scripts available)\n   ```bash\n   python scripts/detect-smells.py <file>\n   ```\n\n2. **Manual Review**\n   - Walk through code systematically\n   - Note each smell with location and severity\n   - Categorize by impact (Critical/High/Medium/Low)\n\n3. **Prioritization**\n   Focus on smells that:\n   - Block current development\n   - Cause bugs or confusion\n   - Affect most-changed code paths\n\n### Output: Smell Report\n\nPresent to user:\n- List of identified smells with locations\n- Severity assessment for each\n- Recommended priority order\n- **Request approval on priorities**\n\n---\n\n## Phase 4: Refactoring Plan Creation\n\n### Selecting Refactorings\n\nFor each smell, select an appropriate refactoring from the catalog.\n\nSee [references/refactoring-catalog.md](references/refactoring-catalog.md) for the complete list.\n\n#### Smell-to-Refactoring Mapping\n\n| Code Smell | Recommended Refactoring(s) |\n|------------|---------------------------|\n| Long Method | Extract Method, Replace Temp with Query |\n| Duplicated Code | Extract Method, Pull Up Method, Form Template Method |\n| Large Class | Extract Class, Extract Subclass |\n| Feature Envy | Move Method, Move Field |\n| Primitive Obsession | Replace Primitive with Object, Replace Type Code with Class |\n| Long Parameter List | Introduce Parameter Object, Preserve Whole Object |\n| Data Clumps | Extract Class, Introduce Parameter Object |\n| Switch Statements | Replace Conditional with Polymorphism |\n| Speculative Generality | Collapse Hierarchy, Inline Class, Remove Dead Code |\n| Dead Code | Remove Dead Code |\n\n### Plan Structure\n\nUse the template at [templates/refactoring-plan.md](templates/refactoring-plan.md).\n\nFor each refactoring:\n1. **Target**: What code will change\n2. **Smell**: What problem it addresses\n3. **Refactoring**: Which technique to apply\n4. **Steps**: Detailed micro-steps\n5. **Risks**: What could go wrong\n6. **Rollback**: How to undo if needed\n\n### Phased Approach\n\n**CRITICAL**: Introduce refactoring gradually in phases.\n\n**Phase A: Quick Wins** (Low risk, high value)\n- Rename variables for clarity\n- Extract obvious duplicate code\n- Remove dead code\n\n**Phase B: Structural Improvements** (Medium risk)\n- Extract methods from long functions\n- Introduce parameter objects\n- Move methods to appropriate classes\n\n**Phase C: Architectural Changes** (Higher risk)\n- Replace conditionals with polymorphism\n- Extract classes\n- Introduce design patterns\n\n### Decision Point: Present Plan to User\n\nBefore implementation:\n- Show complete refactoring plan\n- Explain each phase and its risks\n- Get explicit approval for each phase\n- **Ask**: \"Should I proceed with Phase A?\"\n\n---\n\n## Phase 5: Incremental Implementation\n\n### The Golden Rule\n> \"Change → Test → Green? → Commit → Next step\"\n\n### Implementation Rhythm\n\nFor each refactoring step:\n\n1. **Pre-check**\n   - Tests are passing (green)\n   - Code compiles\n\n2. **Make ONE small change**\n   - Follow the mechanics from the catalog\n   - Keep changes minimal\n\n3. **Verify**\n   - Run tests immediately\n   - Check for compilation errors\n\n4. **If tests pass (green)**\n   - Commit with descriptive message\n   - Move to next step\n\n5. **If tests fail (red)**\n   - STOP immediately\n   - Undo the change\n   - Analyze what went wrong\n   - Ask user if unclear\n\n### Commit Strategy\n\nEach commit should be:\n- **Atomic**: One logical change\n- **Reversible**: Easy to revert\n- **Descriptive**: Clear commit message\n\nExample commit messages:\n```\nrefactor: Extract calculateTotal() from processOrder()\nrefactor: Rename 'x' to 'customerCount' for clarity\nrefactor: Remove unused validateOldFormat() method\n```\n\n### Progress Reporting\n\nAfter each sub-phase, report to user:\n- Changes made\n- Tests still passing?\n- Any issues encountered\n- **Ask**: \"Continue with next batch?\"\n\n---\n\n## Phase 6: Review & Iteration\n\n### Post-Refactoring Checklist\n\n- [ ] All tests passing\n- [ ] No new warnings/errors\n- [ ] Code compiles successfully\n- [ ] Behavior unchanged (manual verification)\n- [ ] Documentation updated if needed\n- [ ] Commit history is clean\n\n### Metrics Comparison\n\nRun complexity analysis before and after:\n```bash\npython scripts/analyze-complexity.py <file>\n```\n\nPresent improvements:\n- Lines of code change\n- Cyclomatic complexity change\n- Maintainability index change\n\n### User Review\n\nPresent final results:\n- Summary of all changes\n- Before/after code comparison\n- Metrics improvements\n- Remaining technical debt\n- **Ask**: \"Are you satisfied with these changes?\"\n\n### Next Steps\n\nDiscuss with user:\n- Additional smells to address?\n- Schedule follow-up refactoring?\n- Apply similar changes elsewhere?\n\n---\n\n## Important Guidelines\n\n### When to STOP and Ask\n\nAlways pause and consult user when:\n- Unsure about business logic\n- Change might affect external APIs\n- Test coverage is inadequate\n- Significant architectural decision needed\n- Risk level increases\n- You encounter unexpected complexity\n\n### Safety Rules\n\n1. **Never refactor without tests** (unless user explicitly acknowledges risk)\n2. **Never make big changes** - break into tiny steps\n3. **Never skip the test run** after each change\n4. **Never continue if tests fail** - fix or rollback first\n5. **Never assume** - when in doubt, ask\n\n### What NOT to Do\n\n- Don't combine refactoring with feature additions\n- Don't refactor during production emergencies\n- Don't refactor code you don't understand\n- Don't over-engineer - keep it simple\n- Don't refactor everything at once\n\n---\n\n## Quick Start Example\n\n### Scenario: Long Method with Duplication\n\n**Before:**\n```javascript\nfunction processOrder(order) {\n  // 150 lines of code with:\n  // - Duplicated validation logic\n  // - Inline calculations\n  // - Mixed responsibilities\n}\n```\n\n**Refactoring Steps:**\n\n1. **Ensure tests exist** for processOrder()\n2. **Extract** validation into validateOrder()\n3. **Test** - should pass\n4. **Extract** calculation into calculateOrderTotal()\n5. **Test** - should pass\n6. **Extract** notification into notifyCustomer()\n7. **Test** - should pass\n8. **Review** - processOrder() now orchestrates 3 clear functions\n\n**After:**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const total = calculateOrderTotal(order);\n  notifyCustomer(order, total);\n  return { order, total };\n}\n```\n\n---\n\n## References\n\n- [Code Smells Catalog](references/code-smells.md) - Complete list of code smells\n- [Refactoring Catalog](references/refactoring-catalog.md) - Refactoring techniques\n- [Refactoring Plan Template](templates/refactoring-plan.md) - Planning template\n\n## Scripts\n\n- `scripts/analyze-complexity.py` - Analyze code complexity metrics\n- `scripts/detect-smells.py` - Automated smell detection\n\n## Version History\n\n- v1.0.0 (2025-01-15): Initial release with Fowler methodology, phased approach, user consultation points\n\n---\n\n**Last Updated**: August 4, 2026\n**Claude Code Version**: 2.1.220\n**Sources**:\n- https://code.claude.com/docs/en/skills\n**Compatible Models**: Claude Fable 5, Claude Opus 5, Claude Sonnet 5, Claude Sonnet 4.6, Claude Opus 4.8, Claude Haiku 4.5\n\n<!-- File: ja/03-skills/blog-draft/SKILL.md (Tokens: ~3653 | Category: anthropic-skill) -->\n<!-- i18n-source: 03-skills/blog-draft/SKILL.md -->\n<!-- i18n-source-sha: f396788 -->\n<!-- i18n-date: 2026-04-27 -->\n\n---\nname: blog-draft\ndescription: アイデアとリソースからブログ記事の下書きを作成する。ブログ記事の執筆、リサーチからのコンテンツ作成、記事の下書き作成時に使用する。リサーチ、ブレインストーミング、アウトライン作成、バージョン管理付きの反復的な下書き作成を案内する。\n---\n\n## ユーザー入力\n\n```text\n$ARGUMENTS\n```\n\n進める前にユーザー入力を**必ず**考慮する。ユーザーは以下を提供すべきである。\n- **Idea/Topic**: ブログ記事の主要なコンセプトやテーマ\n- **Resources**: URL、ファイル、リサーチ用の参考情報（任意だが推奨）\n- **Target audience**: ブログ記事の対象読者（任意）\n- **Tone/Style**: フォーマル、カジュアル、技術的、など（任意）\n\n**重要**: ユーザーが**既存のブログ記事**の更新を要求している場合、ステップ 0-8 をスキップして直接**ステップ 9**から開始する。まず既存の下書きファイルを読み、その後で反復プロセスを進める。\n\n## 実行フロー\n\n以下のステップを順次実行する。**ステップをスキップしたり、指示された箇所でユーザー承認なしに進めたりしてはならない。**\n\n### Step 0: プロジェクトフォルダの作成\n\n1. 次の形式でフォルダ名を生成する: `YYYY-MM-DD-short-topic-name`\n   - 今日の日付を使用\n   - トピックから短く URL フレンドリーなスラッグを作成（小文字、ハイフン、最大 5 単語）\n\n2. フォルダ構造を作成:\n   ```\n   blog-posts/\n   └── YYYY-MM-DD-short-topic-name/\n       └── resources/\n   ```\n\n3. 進める前にフォルダ作成をユーザーに確認する。\n\n### Step 1: リサーチとリソース収集\n\n1. ブログ記事ディレクトリ内に `resources/` サブフォルダを作成\n\n2. 提供された各リソースに対して:\n   - **URLs**: 取得して主要情報を `resources/` にマークダウンファイルとして保存\n   - **Files**: 読み込んで `resources/` に要約\n   - **Topics**: ウェブ検索を使用して最新情報を収集\n\n3. 各リソースについて、`resources/` に要約ファイルを作成:\n   - `resources/source-1-[short-name].md`\n   - `resources/source-2-[short-name].md`\n   - など\n\n4. 各要約には以下を含める:\n   ```markdown\n   # Source: [Title/URL]\n\n   ## Key Points\n   - Point 1\n   - Point 2\n\n   ## Relevant Quotes/Data\n   - Quote or statistic 1\n   - Quote or statistic 2\n\n   ## How This Relates to Topic\n   関連性の簡潔な説明\n   ```\n\n5. リサーチの要約をユーザーに提示する。\n\n### Step 2: ブレインストーミングと明確化\n\n1. アイデアとリサーチしたリソースに基づき、以下を提示:\n   - リサーチから特定された**主要テーマ**\n   - ブログ記事の**取りうる切り口**\n   - カバーすべき**重要ポイント**\n   - 明確化が必要な情報の**ギャップ**\n\n2. 明確化のための質問:\n   - 読者に持って帰ってほしい主要なテイクアウェイは何か？\n   - リサーチの中で特に強調したい点はあるか？\n   - 目標の長さは？（short: 500-800 words、medium: 1000-1500、long: 2000+）\n   - 除外したい点はあるか？\n\n3. **進める前にユーザー応答を待つ。**\n\n### Step 3: アウトライン提案\n\n1. 以下を含む構造化されたアウトラインを作成:\n\n   ```markdown\n   # Blog Post Outline: [Title]\n\n   ## Meta Information\n   - **Target Audience**: [who]\n   - **Tone**: [style]\n   - **Target Length**: [word count]\n   - **Main Takeaway**: [key message]\n\n   ## Proposed Structure\n\n   ### Hook/Introduction\n   - Opening hook idea\n   - Context setting\n   - Thesis statement\n\n   ### Section 1: [Title]\n   - Key point A\n   - Key point B\n   - Supporting evidence from [source]\n\n   ### Section 2: [Title]\n   - Key point A\n   - Key point B\n\n   [全セクションについて続ける...]\n\n   ### Conclusion\n   - Summary of key points\n   - Call to action or final thought\n\n   ## Sources to Cite\n   - Source 1\n   - Source 2\n   ```\n\n2. アウトラインをユーザーに提示し、**承認または修正を求める**。\n\n### Step 4: 承認されたアウトラインの保存\n\n1. ユーザーがアウトラインを承認したら、ブログ記事フォルダ内の `OUTLINE.md` に保存する。\n\n2. アウトラインが保存されたことを確認する。\n\n### Step 5: アウトラインのコミット（git リポジトリの場合）\n\n1. カレントディレクトリが git リポジトリかどうか確認する。\n\n2. はいの場合:\n   - 新しいファイル（ブログ記事フォルダ、resources、OUTLINE.md）をステージング\n   - 次のメッセージでコミットを作成: `docs: Add outline for blog post - [topic-name]`\n   - リモートへプッシュ\n\n3. git リポジトリでない場合は、このステップをスキップしユーザーに伝える。\n\n### Step 6: 下書き作成\n\n1. 承認されたアウトラインに基づき、ブログ記事の下書き全文を作成する。\n\n2. OUTLINE.md の構造に厳密に従う。\n\n3. 含めるもの:\n   - フック付きの魅力的な導入\n   - 明確なセクション見出し\n   - リサーチからの裏付けとなる証拠と例\n   - セクション間の滑らかな遷移\n   - テイクアウェイのある力強い結論\n   - **Citations**: すべての比較、統計、データポイント、事実主張は元のソースを必ず引用すること\n\n4. 下書きをブログ記事フォルダ内に `draft-v0.1.md` として保存する。\n\n5. フォーマット:\n   ```markdown\n   # [Blog Post Title]\n\n   *[Optional: subtitle or tagline]*\n\n   [インライン引用付きの本文...]\n\n   ---\n\n   ## References\n   - [1] Source 1 Title - URL or Citation\n   - [2] Source 2 Title - URL or Citation\n   - [3] Source 3 Title - URL or Citation\n   ```\n\n6. **引用要件**:\n   - すべてのデータポイント、統計、比較にはインライン引用を必ず付ける\n   - [1]、[2] などの番号引用、または [Source Name] のような名前付き引用を使用\n   - 引用を末尾の References セクションへリンクする\n   - 例: \"Studies show that 65% of developers prefer TypeScript [1]\"\n   - 例: \"React outperforms Vue in rendering speed by 20% [React Benchmarks 2024]\"\n\n### Step 7: 下書きのコミット（git リポジトリの場合）\n\n1. git リポジトリかどうか確認する。\n\n2. はいの場合:\n   - 下書きファイルをステージング\n   - 次のメッセージでコミットを作成: `docs: Add draft v0.1 for blog post - [topic-name]`\n   - リモートへプッシュ\n\n3. git リポジトリでない場合は、スキップしてユーザーに伝える。\n\n### Step 8: レビュー用に下書きを提示\n\n1. 下書きの内容をユーザーに提示する。\n\n2. フィードバックを求める:\n   - 全体の印象は？\n   - 拡張または削減が必要なセクションは？\n   - トーン調整は必要か？\n   - 不足している情報は？\n   - 具体的な編集や書き直しは？\n\n3. **ユーザー応答を待つ。**\n\n### Step 9: 反復または最終化\n\n**ユーザーが変更を要求した場合:**\n1. すべての要望を記録する\n2. 以下の調整を加えてステップ 6 へ戻る:\n   - バージョン番号を増加（v0.2、v0.3 など）\n   - すべてのフィードバックを反映\n   - `draft-v[X.Y].md` として保存\n   - ステップ 7-8 を繰り返す\n\n**ユーザーが承認した場合:**\n1. 最終下書きのバージョンを確認\n2. ユーザーが要求すれば任意で `final.md` にリネーム\n3. ブログ記事作成プロセスを要約:\n   - 作成したバージョンの総数\n   - バージョン間の主要な変更\n   - 最終ワード数\n   - 作成したファイル\n\n## バージョン追跡\n\nすべての下書きは段階的なバージョン番号付きで保持する:\n- `draft-v0.1.md` - 初回下書き\n- `draft-v0.2.md` - 1 回目のフィードバック反映後\n- `draft-v0.3.md` - 2 回目のフィードバック反映後\n- など\n\nこれによりブログ記事の進化を追跡し、必要に応じて差し戻すことができる。\n\n## 出力ファイル構造\n\n```\nblog-posts/\n└── YYYY-MM-DD-topic-name/\n    ├── resources/\n    │   ├── source-1-name.md\n    │   ├── source-2-name.md\n    │   └── ...\n    ├── OUTLINE.md\n    ├── draft-v0.1.md\n    ├── draft-v0.2.md (反復した場合)\n    └── draft-v0.3.md (さらに反復した場合)\n```\n\n## 品質のためのヒント\n\n- **Hook**: 質問、意外な事実、共感できるシナリオで始める\n- **Flow**: 各段落は次の段落と接続させる\n- **Evidence**: リサーチデータで主張を裏付ける\n- **Citations**: 以下については必ずソースを引用する:\n  - すべての統計とデータポイント（例: \"According to [Source], 75% of...\"）\n  - 製品、サービス、アプローチ間の比較（例: \"X performs 2x faster than Y [Source]\"）\n  - 市場トレンド、リサーチ結果、ベンチマークについての事実主張\n  - 形式: [Source Name] または [Author, Year] のインライン引用を使用\n- **Voice**: 全体を通じて一貫したトーンを保つ\n- **Length**: 目標ワード数を尊重\n- **Readability**: 短い段落、適切な箇所での箇条書きを使用\n- **CTA**: 明確な CTA または考えさせる問いで終える\n\n## 注意事項\n\n- 指定されたチェックポイントでは必ずユーザー承認を待つ\n- 履歴のためすべての下書きバージョンを保持する\n- URL が提供された場合は最新情報のためウェブ検索を使用する\n- リソースが不十分な場合はユーザーに追加を求めるか、追加リサーチを提案する\n- 対象読者（技術系、一般、ビジネスなど）に応じてトーンを適応させる\n\n<!-- File: ja/03-skills/brand-voice/SKILL.md (Tokens: ~1085 | Category: anthropic-skill) -->\n<!-- i18n-source: 03-skills/brand-voice/SKILL.md -->\n<!-- i18n-source-sha: a6380d8 -->\n<!-- i18n-date: 2026-04-27 -->\n\n---\nname: brand-voice\ndescription: すべてのコミュニケーションがブランドボイスとトーンのガイドラインに沿うことを保証する。マーケティングコピー、顧客向け連絡、公開コンテンツの作成時、またはブランドボイス、トーン、文体について言及がある場合に使用する。\nuser-invocable: false\n---\n\n# ブランドボイス・スキル\n\n## 概要\nこのスキルは、すべてのコミュニケーションにおいて一貫したブランドボイス、トーン、メッセージングを維持する。\n\n## ブランドアイデンティティ\n\n### ミッション\nチームが AI で開発ワークフローを自動化することを支援する\n\n### バリュー\n- **シンプリシティ**: 複雑なものをシンプルにする\n- **信頼性**: 揺るぎない実行\n- **エンパワーメント**: 人間の創造性を引き出す\n\n### トーン・オブ・ボイス\n- **フレンドリーかつプロフェッショナル** - カジュアルにならず、親しみやすい\n- **明快で簡潔** - 専門用語を避け、技術的な概念をわかりやすく説明する\n- **自信を持って** - 自分たちが何をしているかを理解している\n- **共感的** - ユーザーのニーズと痛みを理解する\n\n## 執筆ガイドライン\n\n### やるべきこと ✅\n- 読者を指す際には「you」を使用\n- 能動態を使用: 「Claude generates reports」とし、「Reports are generated by Claude」としない\n- 価値提案から始める\n- 具体例を用いる\n- 1 文を 20 語未満に保つ\n- 明確化のためリストを使用\n- CTA（行動喚起）を含める\n\n### 避けるべきこと ❌\n- 企業ジャーゴンを使わない\n- 見下したり過度に単純化したりしない\n- 「we believe」や「we think」を使わない\n- 強調以外で全大文字を使わない\n- 文章の壁を作らない\n- 技術的な前提知識を仮定しない\n\n## ボキャブラリー\n\n### ✅ 推奨用語\n- Claude（「the Claude AI」ではなく）\n- Code generation（「auto-coding」ではなく）\n- Agent（「bot」ではなく）\n- Streamline（「revolutionize」ではなく）\n- Integrate（「synergize」ではなく）\n\n### ❌ 避ける用語\n- 「Cutting-edge」（使い古されている）\n- 「Game-changer」（曖昧）\n- 「Leverage」（企業用語的）\n- 「Utilize」（「use」を使う）\n- 「Paradigm shift」（不明瞭）\n\n## 例\n\n### ✅ 良い例\n\"Claude automates your code review process. Instead of manually checking each PR, Claude reviews security, performance, and quality—saving your team hours every week.\"\n\nなぜ機能するか: 明確な価値、具体的なメリット、行動志向\n\n### ❌ 悪い例\n\"Claude leverages cutting-edge AI to provide comprehensive software development solutions.\"\n\nなぜ機能しないか: 曖昧、企業ジャーゴン、具体的な価値がない\n\n<!-- File: ja/03-skills/claude-md/SKILL.md (Tokens: ~3486 | Category: anthropic-skill) -->\n<!-- i18n-source: 03-skills/claude-md/SKILL.md -->\n<!-- i18n-source-sha: f78c094 -->\n<!-- i18n-date: 2026-04-27 -->\n---\nname: claude-md\ndescription: Create or update CLAUDE.md files following best practices for optimal AI agent onboarding\n---\n\n## ユーザー入力\n\n```text\n$ARGUMENTS\n```\n\nユーザー入力が空でない場合、進める前に **必ず** 内容を考慮すること。ユーザーは以下を指定する場合がある:\n- `create` - 新しい CLAUDE.md をゼロから作成\n- `update` - 既存 CLAUDE.md を改善\n- `audit` - 現在の CLAUDE.md の品質を分析しレポート\n- 作成・更新する具体的なパス（例: ディレクトリ固有命令向けの `src/api/CLAUDE.md`）\n\n## 基本原則\n\n**LLM はステートレス**: CLAUDE.md は、すべての会話に読み込まれる主要なプロジェクトファイルである（自動メモリやスコープなしのルールと並んで読み込まれる）。コードベースに対する AI エージェントの主要なオンボーディングドキュメントとして機能する。\n\n### ゴールデンルール\n\n1. **少ないほど良い**: フロンティア LLM は約 150〜200 個の命令に従える。Claude Code のシステムプロンプトはすでに約 50 個を使用している。CLAUDE.md は焦点を絞り簡潔に保つこと。\n\n2. **普遍的な適用性**: あらゆるセッションに関係する情報のみを含める。タスク固有の命令は別ファイルに置く。\n\n3. **Claude をリンターとして使わない**: スタイルガイドラインはコンテキストを膨張させ命令の遵守を低下させる。代わりに決定論的なツール（prettier, eslint など）を使う。\n\n4. **絶対に自動生成しない**: CLAUDE.md は AI ハーネスにおける最も影響力の高いポイントである。慎重に手作業で作り上げること。\n\n## 実行フロー\n\n### 1. プロジェクト分析\n\nまず現在のプロジェクト状態を分析する:\n\n1. 既存の CLAUDE.md ファイルを確認:\n   - ルートレベル: `./CLAUDE.md` または `.claude/CLAUDE.md`\n   - ディレクトリ固有: `**/CLAUDE.md`\n   - グローバルユーザー設定: `~/.claude/CLAUDE.md`\n\n2. プロジェクト構造を特定:\n   - 技術スタック（言語、フレームワーク）\n   - プロジェクト種別（モノレポ、単一アプリ、ライブラリ）\n   - 開発ツール（パッケージマネージャー、ビルドシステム、テストランナー）\n\n3. 既存ドキュメントをレビュー:\n   - README.md\n   - CONTRIBUTING.md\n   - package.json, pyproject.toml, Cargo.toml など\n\n### 2. コンテンツ戦略（WHAT, WHY, HOW）\n\nCLAUDE.md を 3 つの観点で構成する:\n\n#### WHAT - 技術と構造\n- 技術スタックの概要\n- プロジェクトの編成（モノレポでは特に重要）\n- 主要ディレクトリとその目的\n\n#### WHY - 目的と背景\n- プロジェクトが何をするか\n- なぜ特定の設計判断が下されたのか\n- 各主要コンポーネントが何を担当するか\n\n#### HOW - ワークフローと規約\n- 開発ワークフロー（bun と node、pip と uv など）\n- テスト手順とコマンド\n- 検証およびビルド手段\n- 重要な「ハマりどころ」や明示されない要件\n\n### 3. プログレッシブディスクロージャ戦略\n\n大規模プロジェクトでは `agent_docs/` フォルダの作成を推奨する:\n\n```\nagent_docs/\n  |- building_the_project.md\n  |- running_tests.md\n  |- code_conventions.md\n  |- architecture_decisions.md\n```\n\nCLAUDE.md からは以下のような命令でこれらのファイルを参照する:\n```markdown\nFor detailed build instructions, refer to `agent_docs/building_the_project.md`\n```\n\n**重要**: 古くなるコンテキストを避けるため、コードスニペットではなく `file:line` 参照を用いる。\n\n### 4. 品質制約\n\nCLAUDE.md を作成・更新する際:\n\n1. **目標の長さ**: 200 行未満\n2. **スタイルルールなし**: lint やフォーマットの命令は除く\n3. **タスク固有命令なし**: 別ファイルへ移す\n4. **コードスニペットなし**: ファイル参照を用いる\n5. **冗長情報なし**: package.json や README にあるものを繰り返さない\n\n### 5. 必須セクション\n\n良く構成された CLAUDE.md には以下を含めるべきである:\n\n```markdown\n# Project Name\n\nBrief one-line description.\n\n## Tech Stack\n- Primary language and version\n- Key frameworks/libraries\n- Database/storage (if any)\n\n## Project Structure\n[Only for monorepos or complex structures]\n- `apps/` - Application entry points\n- `packages/` - Shared libraries\n\n## Development Commands\n- Install: `command`\n- Test: `command`\n- Build: `command`\n\n## Critical Conventions\n[Only non-obvious, high-impact conventions]\n- Convention 1 with brief explanation\n- Convention 2 with brief explanation\n\n## Known Issues / Gotchas\n[Things that consistently trip up developers]\n- Issue 1\n- Issue 2\n```\n\n### 6. 避けるべきアンチパターン\n\n**含めてはいけないもの:**\n- コードスタイルガイドライン（リンターを使う）\n- Claude の使い方に関するドキュメント\n- 自明なパターンへの長い説明\n- コピー＆ペーストされたコード例\n- 一般的なベストプラクティス（\"write clean code\"）\n- 特定タスク向けの命令\n- 自動生成された内容\n- 大量の TODO リスト\n\n### 7. 検証チェックリスト\n\n最終化前に確認:\n\n- [ ] 200 行未満\n- [ ] すべての行があらゆるセッションに適用される\n- [ ] スタイルやフォーマットのルールがない\n- [ ] コードスニペットがない（ファイル参照を使う）\n- [ ] コマンドが動作することを検証済み\n- [ ] 複雑なプロジェクトでプログレッシブディスクロージャを利用\n- [ ] 重要なハマりどころがドキュメント化されている\n- [ ] README.md と内容が重複していない\n\n## 出力形式\n\n### `create` または既定の場合:\n\n1. プロジェクトを分析する\n2. 上記の構造に従って CLAUDE.md の草案を作る\n3. 草案をレビュー用に提示する\n4. 承認後、適切な場所へ書き込む\n\n### `update` の場合:\n\n1. 既存 CLAUDE.md を読む\n2. ベストプラクティスに照らして監査する\n3. 以下を特定する:\n   - 削除する内容（スタイルルール、コードスニペット、タスク固有）\n   - 凝縮する内容\n   - 不足している必須情報\n4. 変更内容をレビュー用に提示する\n5. 承認後、変更を適用する\n\n### `audit` の場合:\n\n1. 既存 CLAUDE.md を読む\n2. 以下を含むレポートを生成する:\n   - 現在の行数と目標値\n   - 普遍的に適用可能なコンテンツの割合\n   - 検出されたアンチパターンの一覧\n   - 改善のための推奨\n3. ファイルを変更しない、レポートのみを行う\n\n## AGENTS.md の取り扱い\n\nユーザーが AGENTS.md の作成・更新を求めた場合:\n\n**v2.1.277 以降、Claude Code は `AGENTS.md` をプロジェクト指示として直接読み込む。** ただし、作業ディレクトリとその上位すべてのディレクトリに `CLAUDE.md`、`.claude/CLAUDE.md`、`CLAUDE.local.md` のいずれも存在しない場合に限る。`~/.claude/CLAUDE.md`、管理 CLAUDE.md、`.claude/rules/` はこの判定の対象外であり、引き続き併せて読み込まれる。この挙動は `/config` の **Project instructions** で制御する: `claude-md-or-agents-md`（デフォルト）、`claude-md-and-agents-md`、`claude-md`、`managed-only`。直接読み込みが利用できない環境 — v2.1.277 より前のバージョン（Bedrock/Vertex/Foundry、LLM ゲートウェイ、テレメトリ無効の場合は v2.1.281 より前）、またはアップグレード後の最初のセッション — では、CLAUDE.md から `@AGENTS.md` でインポートするか、`CLAUDE.md` をこのファイルへのシンボリックリンクにするフォールバックを使う。\n\nAGENTS.md はツール横断のプロジェクトコンテキストファイルであり、CLAUDE.md と同じ *種類* のドキュメントである。エージェント定義フォーマットではない。複数のコーディングエージェントが 1 つのプロジェクト規約を共有できるようにするために存在する:\n- ビルド、テスト、リントのコマンド\n- コードスタイルとアーキテクチャ上の規約\n- リポジトリの構成と各要素の所在\n\nサブエージェントは AGENTS.md ではなく、`.claude/agents/*.md` で別途定義する。\n\n同様の原則を適用する:\n- 焦点を絞り簡潔に保つ\n- プログレッシブディスクロージャを用いる\n- 内容を埋め込むのではなく外部ドキュメントを参照する\n\n## 注意事項\n\n- コマンドを含める前に必ず動作確認する\n- 迷ったら省略する。少ないほど良い\n- システムリマインダーは Claude に対して CLAUDE.md は「関係があるかどうかわからない」と告げている。ノイズが多いほど無視されやすい\n- モノレポは明確な WHAT/WHY/HOW 構造の恩恵が最も大きい\n- ディレクトリ固有の CLAUDE.md ファイルはさらに焦点を絞るべきである\n\n---\n\n**最終更新**: 2026 年 10 月 18 日\n**Claude Code バージョン**: 2.1.302\n**Sources**:\n- https://code.claude.com/docs/en/memory\n\n<!-- File: ja/03-skills/code-review-specialist/SKILL.md (Tokens: ~937 | Category: anthropic-skill) -->\n<!-- i18n-source: 03-skills/code-review-specialist/SKILL.md -->\n<!-- i18n-source-sha: e978c49 -->\n<!-- i18n-date: 2026-04-27 -->\n\n---\nname: code-review-specialist\ndescription: セキュリティ、パフォーマンス、品質分析を含む包括的なコードレビュー。コードレビュー、コード品質分析、プルリクエスト評価の依頼があった場合、またはコードレビュー、セキュリティ分析、パフォーマンス最適化について言及がある場合に使用する。\n---\n\n# コードレビュー・スキル\n\nこのスキルは、以下に焦点を当てた包括的なコードレビュー機能を提供する。\n\n1. **セキュリティ分析**\n   - 認証・認可の問題\n   - データ漏洩リスク\n   - インジェクション脆弱性\n   - 暗号の弱点\n   - 機密データのロギング\n\n2. **パフォーマンス・レビュー**\n   - アルゴリズム効率（Big O 分析）\n   - メモリ最適化\n   - データベースクエリ最適化\n   - キャッシュ機会\n   - 並行性の問題\n\n3. **コード品質**\n   - SOLID 原則\n   - デザインパターン\n   - 命名規則\n   - ドキュメント\n   - テストカバレッジ\n\n4. **保守性**\n   - コードの可読性\n   - 関数サイズ（50 行未満が望ましい）\n   - 循環的複雑度\n   - 依存関係管理\n   - 型安全性\n\n## レビュー・テンプレート\n\nレビューしたコードごとに、以下を提供する。\n\n### サマリー\n- 全体品質評価（1-5）\n- 主要な指摘件数\n- 推奨される優先領域\n\n### クリティカルな問題（あれば）\n- **Issue**: 明確な説明\n- **Location**: ファイルと行番号\n- **Impact**: なぜ重要か\n- **Severity**: Critical/High/Medium\n- **Fix**: コード例\n\n### カテゴリ別の指摘事項\n\n#### セキュリティ（問題が見つかった場合）\nセキュリティ脆弱性を例示しながら列挙\n\n#### パフォーマンス（問題が見つかった場合）\n複雑度分析を含めパフォーマンス問題を列挙\n\n#### 品質（問題が見つかった場合）\nリファクタリング提案を含めコード品質の問題を列挙\n\n#### 保守性（問題が見つかった場合）\n改善案を含め保守性の問題を列挙\n\n## バージョン履歴\n\n- v1.0.0 (2024-12-10): セキュリティ、パフォーマンス、品質、保守性分析を含む初回リリース\n\n<!-- File: ja/03-skills/doc-generator/SKILL.md (Tokens: ~541 | Category: anthropic-skill) -->\n<!-- i18n-source: 03-skills/doc-generator/SKILL.md -->\n<!-- i18n-source-sha: a6380d8 -->\n<!-- i18n-date: 2026-04-27 -->\n\n---\nname: doc-generator\ndescription: ソースコードから包括的かつ正確な API ドキュメントを生成する。API ドキュメントの作成・更新、OpenAPI 仕様の生成時、または API ドキュメント、エンドポイント、ドキュメントについて言及がある場合に使用する。\n---\n\n# API ドキュメント生成スキル\n\n## 生成するもの\n\n- OpenAPI/Swagger 仕様\n- API エンドポイントのドキュメント\n- SDK 利用例\n- 統合ガイド\n- エラーコード・リファレンス\n- 認証ガイド\n\n## ドキュメント構造\n\n### 各エンドポイントごと\n\n````markdown\n## GET /api/v1/users/:id\n\n### Description\nこのエンドポイントの動作を簡潔に説明\n\n### Parameters\n\n| Name | Type | Required | Description |\n|------|------|----------|-------------|\n| id | string | Yes | User ID |\n\n### Response\n\n**200 Success**\n```json\n{\n  \"id\": \"usr_123\",\n  \"name\": \"John Doe\",\n  \"email\": \"john@example.com\",\n  \"created_at\": \"2025-01-15T10:30:00Z\"\n}\n```\n\n**404 Not Found**\n```json\n{\n  \"error\": \"USER_NOT_FOUND\",\n  \"message\": \"User does not exist\"\n}\n```\n\n### Examples\n\n**cURL**\n```bash\ncurl -X GET \"https://api.example.com/api/v1/users/usr_123\" \\\n  -H \"Authorization: Bearer YOUR_TOKEN\"\n```\n\n**JavaScript**\n```javascript\nconst user = await fetch('/api/v1/users/usr_123', {\n  headers: { 'Authorization': 'Bearer token' }\n}).then(r => r.json());\n```\n\n**Python**\n```python\nresponse = requests.get(\n    'https://api.example.com/api/v1/users/usr_123',\n    headers={'Authorization': 'Bearer token'}\n)\nuser = response.json()\n```\n````\n\n<!-- File: ja/03-skills/refactor/references/code-smells.md (Tokens: ~6263 | Category: anthropic-skill) -->\n<!-- i18n-source: 03-skills/refactor/references/code-smells.md -->\n<!-- i18n-source-sha: 245272f -->\n<!-- i18n-date: 2026-04-27 -->\n# コードスメルカタログ\n\nMartin Fowler 著『Refactoring』(第 2 版) に基づく、コードスメルの包括的なリファレンスである。コードスメルはより深い問題の症状であり、コード設計に何か問題がある可能性を示す指標となる。\n\n> \"A code smell is a surface indication that usually corresponds to a deeper problem in the system.\" — Martin Fowler\n\n---\n\n## Bloaters（肥満児）\n\n効果的に扱うには大きくなりすぎたものを表すコードスメル群である。\n\n### Long Method（長すぎる関数）\n\n**兆候:**\n- メソッドが 30〜50 行を超える\n- メソッド全体を見るのにスクロールが必要\n- ネストが多重になっている\n- セクションごとに何をしているかを説明するコメントがある\n\n**なぜ悪いか:**\n- 理解しづらい\n- 単独でテストするのが難しい\n- 変更が予期しない影響を及ぼす\n- 内部に重複ロジックが隠れる\n\n**リファクタリング:**\n- メソッドの抽出\n- Replace Temp with Query\n- パラメータオブジェクトの導入\n- Replace Method with Method Object\n- 条件記述の分解\n\n**例（Before）:**\n```javascript\nfunction processOrder(order) {\n  // 注文の検証 (20 行)\n  if (!order.items) throw new Error('No items');\n  if (order.items.length === 0) throw new Error('Empty order');\n  // ... さらに検証\n\n  // 合計金額の計算 (30 行)\n  let subtotal = 0;\n  for (const item of order.items) {\n    subtotal += item.price * item.quantity;\n  }\n  // ... 税、送料、割引\n\n  // 通知の送信 (20 行)\n  // ... メール送信ロジック\n}\n```\n\n**例（After）:**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const totals = calculateOrderTotals(order);\n  sendOrderNotifications(order, totals);\n  return { order, totals };\n}\n```\n\n---\n\n### Large Class（巨大なクラス）\n\n**兆候:**\n- クラスのインスタンス変数が多い(7〜10 個超)\n- クラスのメソッドが多い(15〜20 個超)\n- クラス名が漠然としている(Manager、Handler、Processor)\n- 全インスタンス変数を使わないメソッドがある\n\n**なぜ悪いか:**\n- 単一責任原則に違反する\n- テストが困難\n- 変更が無関係な機能にも波及する\n- 部分的な再利用が難しい\n\n**リファクタリング:**\n- クラスの抽出\n- Extract Subclass\n- Extract Interface\n\n**検出基準:**\n```\nコード行数 > 300\nメソッド数 > 15\nフィールド数 > 10\n```\n\n---\n\n### Primitive Obsession（プリミティブ型への執着）\n\n**兆候:**\n- ドメイン概念にプリミティブを使う(メールに string、金額に int)\n- オブジェクトでなくプリミティブの配列を使う\n- タイプコードに文字列定数を使う\n- マジックナンバーやマジックストリング\n\n**なぜ悪いか:**\n- 型レベルでの検証ができない\n- ロジックがコードベース全体に散らばる\n- 誤った値を渡しやすい\n- ドメイン概念が欠落する\n\n**リファクタリング:**\n- Replace Primitive with Object\n- Replace Type Code with Class\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**例（Before）:**\n```javascript\nconst user = {\n  email: 'john@example.com',     // 単なる文字列\n  phone: '1234567890',           // 単なる文字列\n  status: 'active',              // マジックストリング\n  balance: 10050                 // セント単位の整数\n};\n```\n\n**例（After）:**\n```javascript\nconst user = {\n  email: new Email('john@example.com'),\n  phone: new PhoneNumber('1234567890'),\n  status: UserStatus.ACTIVE,\n  balance: Money.cents(10050)\n};\n```\n\n---\n\n### Long Parameter List（長すぎるパラメータリスト）\n\n**兆候:**\n- パラメータが 4 個以上のメソッド\n- 常に一緒に現れるパラメータ\n- メソッドの振る舞いを切り替える真偽値フラグ\n- null/undefined が頻繁に渡される\n\n**なぜ悪いか:**\n- 正しく呼び出すのが難しい\n- 引数順序の混乱を招く\n- メソッドが多くを抱え込んでいるサイン\n- パラメータの追加が難しい\n\n**リファクタリング:**\n- パラメータオブジェクトの導入\n- Preserve Whole Object\n- Replace Parameter with Method Call\n- Remove Flag Argument\n\n**例（Before）:**\n```javascript\nfunction createUser(firstName, lastName, email, phone,\n                    street, city, state, zip,\n                    isAdmin, isActive, createdBy) {\n  // ...\n}\n```\n\n**例（After）:**\n```javascript\nfunction createUser(personalInfo, address, options) {\n  // personalInfo: { firstName, lastName, email, phone }\n  // address: { street, city, state, zip }\n  // options: { isAdmin, isActive, createdBy }\n}\n```\n\n---\n\n### Data Clumps（データの群れ）\n\n**兆候:**\n- 同じ 3 個以上のフィールドが繰り返し一緒に現れる\n- 常に一緒に渡されるパラメータ群\n- 一塊として属するべきフィールド集合を持つクラス\n\n**なぜ悪いか:**\n- 取り扱いロジックが重複する\n- 抽象化が欠けている\n- 拡張しづらい\n- 隠れたクラスの存在を示す\n\n**リファクタリング:**\n- クラスの抽出\n- パラメータオブジェクトの導入\n- Preserve Whole Object\n\n**例:**\n```javascript\n// データの群れ: (x, y, z) 座標\nfunction movePoint(x, y, z, dx, dy, dz) { }\nfunction scalePoint(x, y, z, factor) { }\nfunction distanceBetween(x1, y1, z1, x2, y2, z2) { }\n\n// Point3D クラスを抽出\nclass Point3D {\n  constructor(x, y, z) { }\n  move(delta) { }\n  scale(factor) { }\n  distanceTo(other) { }\n}\n```\n\n---\n\n## Object-Orientation Abusers（オブジェクト指向の濫用者）\n\nオブジェクト指向の原則を不完全または誤って使っていることを示すスメル群である。\n\n### Switch Statements（スイッチ文）\n\n**兆候:**\n- 長い switch/case や if/else の連鎖\n- 同じ switch が複数箇所に存在\n- タイプコードに対する switch\n- 新ケース追加で各所を変更する必要がある\n\n**なぜ悪いか:**\n- 開放閉鎖原則に違反する\n- 全ての switch 箇所に変更が波及する\n- 拡張が困難\n- ポリモーフィズム不在のサインであることが多い\n\n**リファクタリング:**\n- ポリモーフィズムによる条件記述の置き換え\n- Replace Type Code with Subclasses\n- Replace Type Code with State/Strategy\n\n**例（Before）:**\n```javascript\nfunction calculatePay(employee) {\n  switch (employee.type) {\n    case 'hourly':\n      return employee.hours * employee.rate;\n    case 'salaried':\n      return employee.salary / 12;\n    case 'commissioned':\n      return employee.sales * employee.commission;\n  }\n}\n```\n\n**例（After）:**\n```javascript\nclass HourlyEmployee {\n  calculatePay() {\n    return this.hours * this.rate;\n  }\n}\n\nclass SalariedEmployee {\n  calculatePay() {\n    return this.salary / 12;\n  }\n}\n```\n\n---\n\n### Temporary Field（一時的フィールド）\n\n**兆候:**\n- 一部のメソッドでのみ使用されるインスタンス変数\n- 条件付きで設定されるフィールド\n- 特定ケースのために複雑な初期化を要する\n\n**なぜ悪いか:**\n- 紛らわしい - フィールドが存在するが null の場合がある\n- オブジェクトの状態が理解しづらい\n- 隠れた条件分岐ロジックを示す\n\n**リファクタリング:**\n- クラスの抽出\n- Introduce Null Object\n- Replace Temp Field with Local\n\n---\n\n### Refused Bequest（相続拒否）\n\n**兆候:**\n- サブクラスが継承したメソッド/データを使わない\n- サブクラスがオーバーライドして何もしない\n- IS-A 関係ではなくコード再利用目的の継承\n\n**なぜ悪いか:**\n- 抽象化が誤っている\n- リスコフの置換原則に違反する\n- 階層が誤解を招く\n\n**リファクタリング:**\n- Push Down Method/Field\n- Replace Subclass with Delegate\n- Replace Inheritance with Delegation\n\n---\n\n### Alternative Classes with Different Interfaces（異なるインターフェイスの代替クラス）\n\n**兆候:**\n- 似たことをする 2 つのクラス\n- 同じ概念に異なるメソッド名を使っている\n- 互いに置換可能だが共通インターフェイスがない\n\n**なぜ悪いか:**\n- 実装が重複する\n- 共通インターフェイスがない\n- 切り替えが難しい\n\n**リファクタリング:**\n- Rename Method\n- Move Method\n- Extract Superclass\n- Extract Interface\n\n---\n\n## Change Preventers（変更の妨げ）\n\n変更を困難にするスメル群 - ある変更のために他の多くを変える必要が生じる。\n\n### Divergent Change（変更の発散）\n\n**兆候:**\n- 1 つのクラスが異なる複数の理由で変更される\n- 異なる領域の変更が同じクラスへの編集を引き起こす\n- そのクラスは「神クラス」化している\n\n**なぜ悪いか:**\n- 単一責任原則に違反する\n- 変更頻度が高くなる\n- マージコンフリクトを招く\n\n**リファクタリング:**\n- クラスの抽出\n- Extract Superclass\n- Extract Subclass\n\n**例:**\n`User` クラスが次の理由で変更される:\n- 認証の変更\n- プロフィールの変更\n- 課金の変更\n- 通知の変更\n\n→ 抽出: `AuthService`、`ProfileService`、`BillingService`、`NotificationService`\n\n---\n\n### Shotgun Surgery（散弾銃手術）\n\n**兆候:**\n- 1 つの変更で多くのクラスへの編集が必要\n- 小さな機能でも 10 ファイル以上に手を入れる\n- 変更箇所が散在し、すべてを見つけにくい\n\n**なぜ悪いか:**\n- 修正漏れが起きやすい\n- 結合度が高い\n- 変更がエラーを誘発しやすい\n\n**リファクタリング:**\n- Move Method\n- Move Field\n- Inline Class\n\n**検出基準:**\n1 フィールドの追加で 5 ファイル以上の変更が必要かを確認する。\n\n---\n\n### Parallel Inheritance Hierarchies（並行継承階層）\n\n**兆候:**\n- 一方の階層にサブクラスを作ると、もう一方にも作る必要がある\n- クラス名のプレフィックスが揃っている(例: `DatabaseOrder`、`DatabaseProduct`)\n\n**なぜ悪いか:**\n- 保守コストが倍になる\n- 階層間の結合度が高い\n- 片側を忘れやすい\n\n**リファクタリング:**\n- Move Method\n- Move Field\n- 一方の階層を削除する\n\n---\n\n## Dispensables（不要物）\n\n不要であり削除すべきものを表すスメル群である。\n\n### Comments（過剰なコメント）\n\n**兆候:**\n- コードが何をしているかを説明するコメント\n- コメントアウトされたコード\n- 永遠に残る TODO/FIXME\n- 言い訳のコメント\n\n**なぜ悪いか:**\n- コメントは嘘をつく(コードと乖離する)\n- コードは自己文書化されているべき\n- 死んだコードは混乱を生む\n\n**リファクタリング:**\n- メソッドの抽出(名前で「何」を表す)\n- Rename(コメントなしで明確化)\n- コメントアウトされたコードの削除\n- Introduce Assertion\n\n**良いコメントと悪いコメント:**\n```javascript\n// 悪い: 「何」を説明している\n// users をループしてアクティブかどうか確認\nfor (const user of users) {\n  if (user.status === 'active') { }\n}\n\n// 良い: 「なぜ」を説明している\n// アクティブなユーザーのみ。非アクティブはクリーンアップジョブで処理される\nconst activeUsers = users.filter(u => u.isActive);\n```\n\n---\n\n### Duplicate Code（重複したコード）\n\n**兆候:**\n- 同じコードが複数箇所にある\n- わずかな違いだけの似たコード\n- コピペのパターン\n\n**なぜ悪いか:**\n- バグ修正を複数箇所で行う必要がある\n- 不整合のリスク\n- コードベースが肥大化する\n\n**リファクタリング:**\n- メソッドの抽出\n- クラスの抽出\n- Pull Up Method(階層内)\n- Form Template Method\n\n**検出ルール:**\n3 回以上重複するコードは抽出すべきである。\n\n---\n\n### Lazy Class（怠け者のクラス）\n\n**兆候:**\n- クラスが存在を正当化できるほど働いていない\n- 付加価値のないラッパー\n- 過剰設計の結果\n\n**なぜ悪いか:**\n- 保守オーバーヘッド\n- 不要な間接参照\n- メリットなき複雑さ\n\n**リファクタリング:**\n- Inline Class\n- Collapse Hierarchy\n\n---\n\n### Dead Code（デッドコード）\n\n**兆候:**\n- 到達不能なコード\n- 使われていない変数/メソッド/クラス\n- コメントアウトされたコード\n- 起こり得ない条件下にあるコード\n\n**なぜ悪いか:**\n- 混乱を招く\n- 保守の負担\n- 理解の速度を落とす\n\n**リファクタリング:**\n- デッドコードの削除\n- Safe Delete\n\n**検出基準:**\n```bash\n# 未使用のエクスポートを探す\n# 参照されない関数を探す\n# IDE の「未使用」警告を確認\n```\n\n---\n\n### Speculative Generality（投機的一般化）\n\n**兆候:**\n- サブクラスが 1 つしかない抽象クラス\n- 「将来のため」の未使用パラメータ\n- 委譲のみのメソッド\n- 1 用途しかない「フレームワーク」\n\n**なぜ悪いか:**\n- メリットなき複雑さ\n- YAGNI(You Ain't Gonna Need It)\n- 理解しづらい\n\n**リファクタリング:**\n- Collapse Hierarchy\n- Inline Class\n- Remove Parameter\n- Rename Method\n\n---\n\n## Couplers（結合の問題）\n\nクラス間の過剰な結合を表すスメル群である。\n\n### Feature Envy（機能の横恋慕）\n\n**兆候:**\n- メソッドが自クラスより他クラスのデータを多く使う\n- 他オブジェクトへの getter 呼び出しが多い\n- データと振る舞いが分離している\n\n**なぜ悪いか:**\n- 振る舞いの置き場所が誤っている\n- カプセル化が不十分\n- 保守が難しい\n\n**リファクタリング:**\n- Move Method\n- Move Field\n- メソッドの抽出(その後 move)\n\n**例（Before）:**\n```javascript\nclass Order {\n  getDiscountedPrice(customer) {\n    // customer のデータを多く使っている\n    if (customer.loyaltyYears > 5) {\n      return this.price * customer.discountRate;\n    }\n    return this.price;\n  }\n}\n```\n\n**例（After）:**\n```javascript\nclass Customer {\n  getDiscountedPriceFor(price) {\n    if (this.loyaltyYears > 5) {\n      return price * this.discountRate;\n    }\n    return price;\n  }\n}\n```\n\n---\n\n### Inappropriate Intimacy（不適切な親密さ）\n\n**兆候:**\n- クラスが互いのプライベート部分にアクセスする\n- 双方向の参照\n- サブクラスが親について詳しすぎる\n\n**なぜ悪いか:**\n- 結合度が高い\n- 変更が連鎖する\n- 一方を変えると他方も変える必要がある\n\n**リファクタリング:**\n- Move Method\n- Move Field\n- Change Bidirectional to Unidirectional\n- クラスの抽出\n- Hide Delegate\n\n---\n\n### Message Chains（メッセージの連鎖）\n\n**兆候:**\n- メソッド呼び出しの長い連鎖: `a.getB().getC().getD().getValue()`\n- クライアントがナビゲーション構造に依存している\n- 「列車事故」コード\n\n**なぜ悪いか:**\n- 脆弱 - 連鎖中のいずれかが変わると壊れる\n- デメテルの法則に違反する\n- 構造への結合\n\n**リファクタリング:**\n- Hide Delegate\n- メソッドの抽出\n- Move Method\n\n**例:**\n```javascript\n// 悪い: メッセージの連鎖\nconst managerName = employee.getDepartment().getManager().getName();\n\n// 良い: 委譲を隠す\nconst managerName = employee.getManagerName();\n```\n\n---\n\n### Middle Man（仲介人）\n\n**兆候:**\n- 他クラスへ委譲するだけのクラス\n- メソッドの半数が委譲\n- 付加価値がない\n\n**なぜ悪いか:**\n- 不要な間接参照\n- 保守オーバーヘッド\n- アーキテクチャが分かりにくい\n\n**リファクタリング:**\n- Remove Middle Man\n- メソッドのインライン化\n\n---\n\n## スメル深刻度ガイド\n\n| 深刻度 | 説明 | 対応 |\n|----------|-------------|--------|\n| **Critical** | 開発をブロックし、バグの原因となる | 直ちに修正 |\n| **High** | 保守負担が大きい | 当該スプリント中に修正 |\n| **Medium** | 目に付くが許容範囲 | 近い将来に計画 |\n| **Low** | 軽微な不便 | 機会があれば修正 |\n\n---\n\n## 簡易検出チェックリスト\n\nコードをスキャンする際に使うチェックリストである。\n\n- [ ] 30 行を超えるメソッドはあるか?\n- [ ] 300 行を超えるクラスはあるか?\n- [ ] 4 個を超えるパラメータを持つメソッドはあるか?\n- [ ] 重複したコードブロックはあるか?\n- [ ] タイプコードに対する switch/case はあるか?\n- [ ] 使われていないコードはあるか?\n- [ ] 他クラスのデータを多く使っているメソッドはあるか?\n- [ ] メソッド呼び出しの長い連鎖はあるか?\n- [ ] 「なぜ」ではなく「何」を説明しているコメントはあるか?\n- [ ] オブジェクト化すべきプリミティブはあるか?\n\n---\n\n## 参考文献\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- Kerievsky, J. (2004). *Refactoring to Patterns*\n- Feathers, M. (2004). *Working Effectively with Legacy Code*\n\n<!-- File: ja/03-skills/refactor/references/refactoring-catalog.md (Tokens: ~9860 | Category: anthropic-skill) -->\n<!-- i18n-source: 03-skills/refactor/references/refactoring-catalog.md -->\n<!-- i18n-source-sha: 245272f -->\n<!-- i18n-date: 2026-04-27 -->\n\n# リファクタリングカタログ\n\nMartin Fowler 著『Refactoring』(第 2 版) から厳選したリファクタリング技法のカタログである。各リファクタリングには動機、手順、例を掲載している。\n\n> 「リファクタリングは、その手順、すなわち変更を実施するための正確なステップ列によって定義される。」 — Martin Fowler\n\n---\n\n## このカタログの使い方\n\n1. コードスメルのリファレンスを使って **コードスメルを特定する**\n2. このカタログから **対応するリファクタリングを探す**\n3. **手順に沿って一段ずつ進める**\n4. **各ステップごとにテスト** を実行し、振る舞いが保たれていることを確認する\n\n**鉄則**: ある手順に 10 分以上かかるのであれば、もっと小さなステップに分割すること。\n\n---\n\n## 最も頻出するリファクタリング\n\n### メソッドの抽出 (Extract Method)\n\n**使う場面**: 長いメソッド、重複コード、概念に名前を付けたいとき\n\n**動機**: コード片を、目的を表す名前を持つメソッドに切り出す。\n\n**手順**:\n1. やっていること(どうやってではなく)にちなんだ名前で新しいメソッドを作成する\n2. コード片を新しいメソッドへコピーする\n3. コード片で使われているローカル変数を洗い出す\n4. ローカル変数をパラメータとして渡す(あるいはメソッド内で宣言する)\n5. 戻り値を適切に処理する\n6. 元のコード片を新しいメソッドの呼び出しに置き換える\n7. テストする\n\n**Before**:\n```javascript\nfunction printOwing(invoice) {\n  let outstanding = 0;\n\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n\n  // 未払額の計算\n  for (const order of invoice.orders) {\n    outstanding += order.amount;\n  }\n\n  // 詳細の出力\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n**After**:\n```javascript\nfunction printOwing(invoice) {\n  printBanner();\n  const outstanding = calculateOutstanding(invoice);\n  printDetails(invoice, outstanding);\n}\n\nfunction printBanner() {\n  console.log(\"***********************\");\n  console.log(\"**** Customer Owes ****\");\n  console.log(\"***********************\");\n}\n\nfunction calculateOutstanding(invoice) {\n  return invoice.orders.reduce((sum, order) => sum + order.amount, 0);\n}\n\nfunction printDetails(invoice, outstanding) {\n  console.log(`name: ${invoice.customer}`);\n  console.log(`amount: ${outstanding}`);\n}\n```\n\n---\n\n### メソッドのインライン化 (Inline Method)\n\n**使う場面**: メソッド本体が名前と同じくらい明快な場合、過度な委譲が見られる場合\n\n**動機**: メソッドが価値を加えていない場合、不要な間接参照を取り除く。\n\n**手順**:\n1. メソッドがポリモーフィックでないことを確認する\n2. メソッドの呼び出し箇所をすべて見つける\n3. 各呼び出しをメソッド本体で置き換える\n4. 置き換えるたびにテストする\n5. メソッド定義を削除する\n\n**Before**:\n```javascript\nfunction getRating(driver) {\n  return moreThanFiveLateDeliveries(driver) ? 2 : 1;\n}\n\nfunction moreThanFiveLateDeliveries(driver) {\n  return driver.numberOfLateDeliveries > 5;\n}\n```\n\n**After**:\n```javascript\nfunction getRating(driver) {\n  return driver.numberOfLateDeliveries > 5 ? 2 : 1;\n}\n```\n\n---\n\n### 変数の抽出 (Extract Variable)\n\n**使う場面**: 複雑で理解しづらい式があるとき\n\n**動機**: 複雑な式の一部に名前を付ける。\n\n**手順**:\n1. 式に副作用がないことを確認する\n2. イミュータブルな変数を宣言する\n3. 式(または式の一部)の結果をその変数に代入する\n4. 元の式を変数で置き換える\n5. テストする\n\n**Before**:\n```javascript\nreturn order.quantity * order.itemPrice -\n  Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +\n  Math.min(order.quantity * order.itemPrice * 0.1, 100);\n```\n\n**After**:\n```javascript\nconst basePrice = order.quantity * order.itemPrice;\nconst quantityDiscount = Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;\nconst shipping = Math.min(basePrice * 0.1, 100);\nreturn basePrice - quantityDiscount + shipping;\n```\n\n---\n\n### 変数のインライン化 (Inline Variable)\n\n**使う場面**: 変数名が式以上の情報を伝えていないとき\n\n**動機**: 不要な間接参照を取り除く。\n\n**手順**:\n1. 右辺に副作用がないことを確認する\n2. 変数がイミュータブルでなければイミュータブルにし、テストする\n3. 最初の参照箇所を見つけて式で置き換える\n4. テストする\n5. すべての参照箇所について繰り返す\n6. 宣言と代入を削除する\n7. テストする\n\n---\n\n### 変数名の変更 (Rename Variable)\n\n**使う場面**: 名前が目的を明確に伝えていないとき\n\n**動機**: クリーンなコードには良い名前が不可欠である。\n\n**手順**:\n1. 変数が広く使われている場合は、カプセル化を検討する\n2. すべての参照箇所を見つける\n3. 各参照箇所を変更する\n4. テストする\n\n**Tips**:\n- 意図を明らかにする名前を使う\n- 略語を避ける\n- ドメイン用語を用いる\n\n```javascript\n// 悪い例\nconst d = 30;\nconst x = users.filter(u => u.a);\n\n// 良い例\nconst daysSinceLastLogin = 30;\nconst activeUsers = users.filter(user => user.isActive);\n```\n\n---\n\n### 関数宣言の変更 (Change Function Declaration)\n\n**使う場面**: 関数名が目的を表していない、パラメータの変更が必要な場合\n\n**動機**: 良い関数名はコードを自己説明的にする。\n\n**手順 (シンプル版)**:\n1. 不要なパラメータを削除する\n2. 名前を変更する\n3. 必要なパラメータを追加する\n4. テストする\n\n**手順 (マイグレーション版 — 複雑な変更向け)**:\n1. パラメータを削除する場合、それが使われていないことを確認する\n2. 望ましい宣言の新しい関数を作成する\n3. 古い関数から新しい関数を呼び出すようにする\n4. テストする\n5. 呼び出し側を新しい関数を使うように変更する\n6. 各変更後にテストする\n7. 古い関数を削除する\n\n**Before**:\n```javascript\nfunction circum(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n**After**:\n```javascript\nfunction circumference(radius) {\n  return 2 * Math.PI * radius;\n}\n```\n\n---\n\n### 変数のカプセル化 (Encapsulate Variable)\n\n**使う場面**: データに複数箇所から直接アクセスしているとき\n\n**動機**: データ操作のための明確なアクセスポイントを提供する。\n\n**手順**:\n1. getter と setter 関数を作成する\n2. すべての参照箇所を見つける\n3. 読み取りを getter で置き換える\n4. 書き込みを setter で置き換える\n5. 各変更後にテストする\n6. 変数の可視性を制限する\n\n**Before**:\n```javascript\nlet defaultOwner = { firstName: \"Martin\", lastName: \"Fowler\" };\n\n// 多くの場所で利用される\nspaceship.owner = defaultOwner;\n```\n\n**After**:\n```javascript\nlet defaultOwnerData = { firstName: \"Martin\", lastName: \"Fowler\" };\n\nfunction defaultOwner() { return defaultOwnerData; }\nfunction setDefaultOwner(arg) { defaultOwnerData = arg; }\n\nspaceship.owner = defaultOwner();\n```\n\n---\n\n### パラメータオブジェクトの導入 (Introduce Parameter Object)\n\n**使う場面**: いくつかのパラメータがしばしばまとまって登場する場合\n\n**動機**: 自然にまとまるべきデータをグループ化する。\n\n**手順**:\n1. グループ化したパラメータ用の新しいクラス/構造体を作成する\n2. テストする\n3. 「関数宣言の変更」で新しいオブジェクトを追加する\n4. テストする\n5. グループ内の各パラメータについて、関数から取り除き新しいオブジェクトを使うようにする\n6. 各変更後にテストする\n\n**Before**:\n```javascript\nfunction amountInvoiced(startDate, endDate) { ... }\nfunction amountReceived(startDate, endDate) { ... }\nfunction amountOverdue(startDate, endDate) { ... }\n```\n\n**After**:\n```javascript\nclass DateRange {\n  constructor(start, end) {\n    this.start = start;\n    this.end = end;\n  }\n}\n\nfunction amountInvoiced(dateRange) { ... }\nfunction amountReceived(dateRange) { ... }\nfunction amountOverdue(dateRange) { ... }\n```\n\n---\n\n### 関数群のクラス化 (Combine Functions into Class)\n\n**使う場面**: 複数の関数が同じデータを操作している場合\n\n**動機**: 関数を、それらが操作するデータと共にまとめる。\n\n**手順**:\n1. 共通データに「レコードのカプセル化 (Encapsulate Record)」を適用する\n2. 各関数をクラス内に移動する\n3. 移動するたびにテストする\n4. データ引数をクラスのフィールド利用に置き換える\n\n**Before**:\n```javascript\nfunction base(reading) { ... }\nfunction taxableCharge(reading) { ... }\nfunction calculateBaseCharge(reading) { ... }\n```\n\n**After**:\n```javascript\nclass Reading {\n  constructor(data) { this._data = data; }\n\n  get base() { ... }\n  get taxableCharge() { ... }\n  get calculateBaseCharge() { ... }\n}\n```\n\n---\n\n### 段階の分割 (Split Phase)\n\n**使う場面**: コードが 2 つの異なる事柄を扱っている場合\n\n**動機**: コードを明確な境界を持つ別々のフェーズに分離する。\n\n**手順**:\n1. 第 2 フェーズ用の関数を作成する\n2. テストする\n3. フェーズ間の中間データ構造を導入する\n4. テストする\n5. 第 1 フェーズを独立した関数として抽出する\n6. テストする\n\n**Before**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  const shippingPerCase = (basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = quantity * shippingPerCase;\n  return basePrice - discount + shippingCost;\n}\n```\n\n**After**:\n```javascript\nfunction priceOrder(product, quantity, shippingMethod) {\n  const priceData = calculatePricingData(product, quantity);\n  return applyShipping(priceData, shippingMethod);\n}\n\nfunction calculatePricingData(product, quantity) {\n  const basePrice = product.basePrice * quantity;\n  const discount = Math.max(quantity - product.discountThreshold, 0)\n    * product.basePrice * product.discountRate;\n  return { basePrice, quantity, discount };\n}\n\nfunction applyShipping(priceData, shippingMethod) {\n  const shippingPerCase = (priceData.basePrice > shippingMethod.discountThreshold)\n    ? shippingMethod.discountedFee : shippingMethod.feePerCase;\n  const shippingCost = priceData.quantity * shippingPerCase;\n  return priceData.basePrice - priceData.discount + shippingCost;\n}\n```\n\n---\n\n## 機能の移動\n\n### メソッドの移動 (Move Method)\n\n**使う場面**: メソッドが自分のクラスより他のクラスの機能を多く使っている場合\n\n**動機**: 関数を、最もよく利用するデータの近くに置く。\n\n**手順**:\n1. 自クラス内でメソッドが利用しているプログラム要素をすべて調べる\n2. メソッドがポリモーフィックかどうか確認する\n3. 移動先クラスにメソッドをコピーする\n4. 新しいコンテキストに合わせて調整する\n5. 元のメソッドが移動先に委譲するようにする\n6. テストする\n7. 元のメソッドの削除を検討する\n\n---\n\n### フィールドの移動 (Move Field)\n\n**使う場面**: フィールドが他のクラスでより多く使われている場合\n\n**動機**: データを、それを使う関数と共に保持する。\n\n**手順**:\n1. まだの場合はフィールドをカプセル化する\n2. テストする\n3. 移動先にフィールドを作成する\n4. 参照箇所を移動先のフィールドを使うように更新する\n5. テストする\n6. 元のフィールドを削除する\n\n---\n\n### 関数への文の移動 (Move Statements into Function)\n\n**使う場面**: 同じコードが必ずある関数呼び出しと一緒に現れる場合\n\n**動機**: 繰り返しコードを関数内に移動して重複を取り除く。\n\n**手順**:\n1. まだの場合は繰り返しコードを関数として抽出する\n2. その関数の中に文を移動する\n3. テストする\n4. 呼び出し側で単独の文が不要になったら削除する\n\n---\n\n### 呼び出し側への文の移動 (Move Statements to Callers)\n\n**使う場面**: 共通の振る舞いが呼び出し側ごとに異なる場合\n\n**動機**: 振る舞いを変える必要があるなら、関数の外に移す。\n\n**手順**:\n1. 移動するコードに「メソッドの抽出」を適用する\n2. 元の関数に「メソッドのインライン化」を適用する\n3. インライン化された呼び出しを削除する\n4. 抽出したコードを各呼び出し側に移動する\n5. テストする\n\n---\n\n## データの再編成\n\n### プリミティブをオブジェクトで置き換える (Replace Primitive with Object)\n\n**使う場面**: データ項目に単純な値以上の振る舞いが必要な場合\n\n**動機**: データを振る舞いと共にカプセル化する。\n\n**手順**:\n1. 「変数のカプセル化」を適用する\n2. シンプルな値クラスを作成する\n3. setter を新しいインスタンス生成に変更する\n4. getter を値の返却に変更する\n5. テストする\n6. 新しいクラスにより豊かな振る舞いを追加する\n\n**Before**:\n```javascript\nclass Order {\n  constructor(data) {\n    this.priority = data.priority; // 文字列: \"high\"、\"rush\" など\n  }\n}\n\n// 利用箇所\nif (order.priority === \"high\" || order.priority === \"rush\") { ... }\n```\n\n**After**:\n```javascript\nclass Priority {\n  constructor(value) {\n    if (!Priority.legalValues().includes(value))\n      throw new Error(`Invalid priority: ${value}`);\n    this._value = value;\n  }\n\n  static legalValues() { return ['low', 'normal', 'high', 'rush']; }\n  get value() { return this._value; }\n\n  higherThan(other) {\n    return Priority.legalValues().indexOf(this._value) >\n           Priority.legalValues().indexOf(other._value);\n  }\n}\n\n// 利用箇所\nif (order.priority.higherThan(new Priority(\"normal\"))) { ... }\n```\n\n---\n\n### 一時変数を問い合わせで置き換える (Replace Temp with Query)\n\n**使う場面**: 一時変数が式の結果を保持している場合\n\n**動機**: 式を関数として切り出すことでコードを明快にする。\n\n**手順**:\n1. 変数が一度だけ代入されていることを確認する\n2. 代入の右辺をメソッドとして抽出する\n3. 一時変数の参照箇所をメソッド呼び出しで置き換える\n4. テストする\n5. 一時変数の宣言と代入を削除する\n\n**Before**:\n```javascript\nconst basePrice = this._quantity * this._itemPrice;\nif (basePrice > 1000) {\n  return basePrice * 0.95;\n} else {\n  return basePrice * 0.98;\n}\n```\n\n**After**:\n```javascript\nget basePrice() {\n  return this._quantity * this._itemPrice;\n}\n\n// メソッド内\nif (this.basePrice > 1000) {\n  return this.basePrice * 0.95;\n} else {\n  return this.basePrice * 0.98;\n}\n```\n\n---\n\n## 条件記述の単純化\n\n### 条件記述の分解 (Decompose Conditional)\n\n**使う場面**: 複雑な条件分岐 (if-then-else) があるとき\n\n**動機**: 条件と動作を抽出して意図を明確にする。\n\n**手順**:\n1. 条件部分に「メソッドの抽出」を適用する\n2. then 節に「メソッドの抽出」を適用する\n3. else 節 (もしあれば) に「メソッドの抽出」を適用する\n\n**Before**:\n```javascript\nif (!aDate.isBefore(plan.summerStart) && !aDate.isAfter(plan.summerEnd)) {\n  charge = quantity * plan.summerRate;\n} else {\n  charge = quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n**After**:\n```javascript\nif (isSummer(aDate, plan)) {\n  charge = summerCharge(quantity, plan);\n} else {\n  charge = regularCharge(quantity, plan);\n}\n\nfunction isSummer(date, plan) {\n  return !date.isBefore(plan.summerStart) && !date.isAfter(plan.summerEnd);\n}\n\nfunction summerCharge(quantity, plan) {\n  return quantity * plan.summerRate;\n}\n\nfunction regularCharge(quantity, plan) {\n  return quantity * plan.regularRate + plan.regularServiceCharge;\n}\n```\n\n---\n\n### 条件式の統合 (Consolidate Conditional Expression)\n\n**使う場面**: 同じ結果を返す条件が複数あるとき\n\n**動機**: それらの条件が単一のチェックであることを明らかにする。\n\n**手順**:\n1. 条件に副作用がないことを確認する\n2. 条件を `and` または `or` で結合する\n3. 結合した条件に「メソッドの抽出」を検討する\n\n**Before**:\n```javascript\nif (employee.seniority < 2) return 0;\nif (employee.monthsDisabled > 12) return 0;\nif (employee.isPartTime) return 0;\n```\n\n**After**:\n```javascript\nif (isNotEligibleForDisability(employee)) return 0;\n\nfunction isNotEligibleForDisability(employee) {\n  return employee.seniority < 2 ||\n         employee.monthsDisabled > 12 ||\n         employee.isPartTime;\n}\n```\n\n---\n\n### ガード節による入れ子の条件記述の置き換え (Replace Nested Conditional with Guard Clauses)\n\n**使う場面**: 入れ子の条件分岐が深く、流れを追いにくいとき\n\n**動機**: 特殊ケースにガード節を使い、通常フローを明確に保つ。\n\n**手順**:\n1. 特殊ケースの条件を見つける\n2. それらを早期 return するガード節で置き換える\n3. 各変更後にテストする\n\n**Before**:\n```javascript\nfunction payAmount(employee) {\n  let result;\n  if (employee.isSeparated) {\n    result = { amount: 0, reasonCode: \"SEP\" };\n  } else {\n    if (employee.isRetired) {\n      result = { amount: 0, reasonCode: \"RET\" };\n    } else {\n      result = calculateNormalPay(employee);\n    }\n  }\n  return result;\n}\n```\n\n**After**:\n```javascript\nfunction payAmount(employee) {\n  if (employee.isSeparated) return { amount: 0, reasonCode: \"SEP\" };\n  if (employee.isRetired) return { amount: 0, reasonCode: \"RET\" };\n  return calculateNormalPay(employee);\n}\n```\n\n---\n\n### ポリモーフィズムによる条件記述の置き換え (Replace Conditional with Polymorphism)\n\n**使う場面**: 型に基づく switch/case、型ごとに変化する条件ロジック\n\n**動機**: オブジェクト自身に振る舞いを担わせる。\n\n**手順**:\n1. クラス階層を作成する (なければ)\n2. オブジェクト生成にファクトリ関数を使う\n3. 条件ロジックをスーパークラスのメソッドに移す\n4. ケースごとにサブクラスのメソッドを作成する\n5. 元の条件記述を削除する\n\n**Before**:\n```javascript\nfunction plumages(birds) {\n  return birds.map(b => plumage(b));\n}\n\nfunction plumage(bird) {\n  switch (bird.type) {\n    case 'EuropeanSwallow':\n      return \"average\";\n    case 'AfricanSwallow':\n      return (bird.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n    case 'NorwegianBlueParrot':\n      return (bird.voltage > 100) ? \"scorched\" : \"beautiful\";\n    default:\n      return \"unknown\";\n  }\n}\n```\n\n**After**:\n```javascript\nclass Bird {\n  get plumage() { return \"unknown\"; }\n}\n\nclass EuropeanSwallow extends Bird {\n  get plumage() { return \"average\"; }\n}\n\nclass AfricanSwallow extends Bird {\n  get plumage() {\n    return (this.numberOfCoconuts > 2) ? \"tired\" : \"average\";\n  }\n}\n\nclass NorwegianBlueParrot extends Bird {\n  get plumage() {\n    return (this.voltage > 100) ? \"scorched\" : \"beautiful\";\n  }\n}\n\nfunction createBird(data) {\n  switch (data.type) {\n    case 'EuropeanSwallow': return new EuropeanSwallow(data);\n    case 'AfricanSwallow': return new AfricanSwallow(data);\n    case 'NorwegianBlueParrot': return new NorwegianBlueParrot(data);\n    default: return new Bird(data);\n  }\n}\n```\n\n---\n\n### 特殊ケースの導入 (Introduce Special Case / Null Object)\n\n**使う場面**: 特殊ケースに対する null チェックが繰り返される場合\n\n**動機**: 特殊ケースを処理する特殊オブジェクトを返す。\n\n**手順**:\n1. 期待されるインターフェースを持つ特殊ケースクラスを作成する\n2. isSpecialCase チェックを追加する\n3. ファクトリメソッドを導入する\n4. null チェックを特殊ケースオブジェクトの利用で置き換える\n5. テストする\n\n**Before**:\n```javascript\nconst customer = site.customer;\n// ... 多数の箇所でチェック\nif (customer === \"unknown\") {\n  customerName = \"occupant\";\n} else {\n  customerName = customer.name;\n}\n```\n\n**After**:\n```javascript\nclass UnknownCustomer {\n  get name() { return \"occupant\"; }\n  get billingPlan() { return registry.defaultPlan; }\n}\n\n// ファクトリメソッド\nfunction customer(site) {\n  return site.customer === \"unknown\"\n    ? new UnknownCustomer()\n    : site.customer;\n}\n\n// 利用箇所 — null チェック不要\nconst customerName = customer.name;\n```\n\n---\n\n## API のリファクタリング\n\n### 問い合わせと変更の分離 (Separate Query from Modifier)\n\n**使う場面**: 関数が値を返すと同時に副作用も持つ場合\n\n**動機**: どの操作に副作用があるのかを明確にする。\n\n**手順**:\n1. 新しい問い合わせ関数を作成する\n2. 元の関数の戻り値ロジックをコピーする\n3. 元の関数を void を返すように変更する\n4. 戻り値を使っていた呼び出しを置き換える\n5. テストする\n\n**Before**:\n```javascript\nfunction alertForMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") {\n      setOffAlarms();\n      return \"Don\";\n    }\n    if (p === \"John\") {\n      setOffAlarms();\n      return \"John\";\n    }\n  }\n  return \"\";\n}\n```\n\n**After**:\n```javascript\nfunction findMiscreant(people) {\n  for (const p of people) {\n    if (p === \"Don\") return \"Don\";\n    if (p === \"John\") return \"John\";\n  }\n  return \"\";\n}\n\nfunction alertForMiscreant(people) {\n  if (findMiscreant(people) !== \"\") setOffAlarms();\n}\n```\n\n---\n\n### 関数のパラメータ化 (Parameterize Function)\n\n**使う場面**: 似たような処理を異なる値で行う関数が複数あるとき\n\n**動機**: パラメータを追加することで重複を取り除く。\n\n**手順**:\n1. 一つの関数を選ぶ\n2. 変動するリテラル用のパラメータを追加する\n3. 本体をそのパラメータを使うように変更する\n4. テストする\n5. 呼び出し側をパラメータ化された版を使うように変更する\n6. 不要になった関数を削除する\n\n**Before**:\n```javascript\nfunction tenPercentRaise(person) {\n  person.salary = person.salary * 1.10;\n}\n\nfunction fivePercentRaise(person) {\n  person.salary = person.salary * 1.05;\n}\n```\n\n**After**:\n```javascript\nfunction raise(person, factor) {\n  person.salary = person.salary * (1 + factor);\n}\n\n// 利用箇所\nraise(person, 0.10);\nraise(person, 0.05);\n```\n\n---\n\n### フラグ引数の削除 (Remove Flag Argument)\n\n**使う場面**: 関数の振る舞いを切り替えるブール型パラメータがある場合\n\n**動機**: 別々の関数を通して振る舞いを明示的にする。\n\n**手順**:\n1. フラグの値ごとに明示的な関数を作成する\n2. 各呼び出しを適切な新しい関数で置き換える\n3. 各変更後にテストする\n4. 元の関数を削除する\n\n**Before**:\n```javascript\nfunction bookConcert(customer, isPremium) {\n  if (isPremium) {\n    // プレミアム予約のロジック\n  } else {\n    // 通常予約のロジック\n  }\n}\n\nbookConcert(customer, true);\nbookConcert(customer, false);\n```\n\n**After**:\n```javascript\nfunction bookPremiumConcert(customer) {\n  // プレミアム予約のロジック\n}\n\nfunction bookRegularConcert(customer) {\n  // 通常予約のロジック\n}\n\nbookPremiumConcert(customer);\nbookRegularConcert(customer);\n```\n\n---\n\n## 継承の取り扱い\n\n### メソッドの引き上げ (Pull Up Method)\n\n**使う場面**: 同じメソッドが複数のサブクラスにあるとき\n\n**動機**: クラス階層内の重複を取り除く。\n\n**手順**:\n1. メソッド同士が同一であることを確認する\n2. シグネチャが同じであることを確認する\n3. スーパークラスに新しいメソッドを作成する\n4. 一つのサブクラスから本体をコピーする\n5. 一つのサブクラスからメソッドを削除し、テストする\n6. 他のサブクラスのメソッドも順次削除し、その都度テストする\n\n---\n\n### メソッドの押し下げ (Push Down Method)\n\n**使う場面**: サブクラスの一部のみに関係する振る舞いがあるとき\n\n**動機**: メソッドを使われる場所に置く。\n\n**手順**:\n1. メソッドを必要とする各サブクラスにコピーする\n2. スーパークラスからメソッドを削除する\n3. テストする\n4. 必要としないサブクラスからは削除する\n5. テストする\n\n---\n\n### サブクラスを委譲で置き換える (Replace Subclass with Delegate)\n\n**使う場面**: 継承が誤って使われている、もしくはより柔軟性が必要な場合\n\n**動機**: 適切な場面では継承よりコンポジションを優先する。\n\n**手順**:\n1. 委譲先用の空クラスを作成する\n2. 委譲先を保持するフィールドをホストクラスに追加する\n3. ホストから呼ばれる委譲先のコンストラクタを作成する\n4. 機能を委譲先へ移動する\n5. 移動するたびにテストする\n6. 継承を委譲で置き換える\n\n---\n\n## クラスの抽出 (Extract Class)\n\n**使う場面**: 複数の責務を持つ大きなクラスがあるとき\n\n**動機**: クラスを分割して単一責務を保つ。\n\n**手順**:\n1. 責務をどう分けるか決める\n2. 新しいクラスを作成する\n3. フィールドを元のクラスから新しいクラスへ移動する\n4. テストする\n5. メソッドを元のクラスから新しいクラスへ移動する\n6. 移動するたびにテストする\n7. 両クラスを見直して必要なら名前を変更する\n8. 新しいクラスをどう公開するかを決める\n\n**Before**:\n```javascript\nclass Person {\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get officeAreaCode() { return this._officeAreaCode; }\n  set officeAreaCode(arg) { this._officeAreaCode = arg; }\n  get officeNumber() { return this._officeNumber; }\n  set officeNumber(arg) { this._officeNumber = arg; }\n\n  get telephoneNumber() {\n    return `(${this._officeAreaCode}) ${this._officeNumber}`;\n  }\n}\n```\n\n**After**:\n```javascript\nclass Person {\n  constructor() {\n    this._telephoneNumber = new TelephoneNumber();\n  }\n  get name() { return this._name; }\n  set name(arg) { this._name = arg; }\n  get telephoneNumber() { return this._telephoneNumber.toString(); }\n  get officeAreaCode() { return this._telephoneNumber.areaCode; }\n  set officeAreaCode(arg) { this._telephoneNumber.areaCode = arg; }\n}\n\nclass TelephoneNumber {\n  get areaCode() { return this._areaCode; }\n  set areaCode(arg) { this._areaCode = arg; }\n  get number() { return this._number; }\n  set number(arg) { this._number = arg; }\n  toString() { return `(${this._areaCode}) ${this._number}`; }\n}\n```\n\n---\n\n## クイックリファレンス: スメルからリファクタリングへ\n\n| コードスメル | 主なリファクタリング | 代替 |\n|------------|-------------------|-------------|\n| 長すぎるメソッド (Long Method) | メソッドの抽出 | 一時変数を問い合わせで置き換える |\n| 重複コード (Duplicate Code) | メソッドの抽出 | メソッドの引き上げ |\n| 大きすぎるクラス (Large Class) | クラスの抽出 | サブクラスの抽出 |\n| 長すぎるパラメータリスト (Long Parameter List) | パラメータオブジェクトの導入 | オブジェクトそのものの受け渡し |\n| 機能の横恋慕 (Feature Envy) | メソッドの移動 | メソッドの抽出 + 移動 |\n| データのかたまり (Data Clumps) | クラスの抽出 | パラメータオブジェクトの導入 |\n| プリミティブ依存症 (Primitive Obsession) | プリミティブをオブジェクトで置き換える | タイプコードの置き換え |\n| switch 文 (Switch Statements) | ポリモーフィズムによる条件記述の置き換え | タイプコードの置き換え |\n| 一時的属性 (Temporary Field) | クラスの抽出 | Null オブジェクトの導入 |\n| メッセージの連鎖 (Message Chains) | 委譲の隠蔽 | メソッドの抽出 |\n| 仲介人 (Middle Man) | 中間者の除去 | メソッドのインライン化 |\n| 変更の分散 (Divergent Change) | クラスの抽出 | 段階の分割 |\n| 散弾銃手術 (Shotgun Surgery) | メソッドの移動 | クラスのインライン化 |\n| 死せるコード (Dead Code) | 死せるコードの除去 | - |\n| 投機的一般性 (Speculative Generality) | 階層の平坦化 | クラスのインライン化 |\n\n---\n\n## 参考文献\n\n- Fowler, M. (2018). *Refactoring: Improving the Design of Existing Code* (2nd ed.)\n- オンラインカタログ: https://refactoring.com/catalog/\n\n<!-- File: ja/03-skills/refactor/SKILL.md (Tokens: ~5617 | Category: anthropic-skill) -->\n<!-- i18n-source: 03-skills/refactor/SKILL.md -->\n<!-- i18n-source-sha: 245272f -->\n<!-- i18n-date: 2026-04-27 -->\n---\nname: refactor\ndescription: Martin Fowler の方法論に基づく体系的なコードリファクタリング。ユーザーがコードのリファクタリング、コード構造の改善、技術的負債の削減、レガシーコードのクリーンアップ、コードスメルの解消、コード保守性の向上を求めた際に使用する。本スキルは、リサーチ・計画・安全な段階的実装からなる段階的アプローチを案内する。\n---\n\n# コードリファクタリングスキル\n\nMartin Fowler 著『Refactoring: Improving the Design of Existing Code』(第 2 版) に基づくコードリファクタリングへの体系的アプローチ。本スキルは、テストに支えられた安全で段階的な変更を重視する。\n\n> \"Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure.\" — Martin Fowler\n\n## 中核となる原則\n\n1. **振る舞いの保全**: 外部から見える振る舞いは変えてはならない\n2. **小さなステップ**: テスト可能な微小な変更を積み重ねる\n3. **テスト駆動**: テストはセーフティネットである\n4. **継続的**: リファクタリングは一度きりの作業ではなく継続的に行う\n5. **協調的**: 各フェーズでユーザーの承認が必要\n\n## ワークフロー概要\n\n```\nPhase 1: Research & Analysis\n    ↓\nPhase 2: Test Coverage Assessment\n    ↓\nPhase 3: Code Smell Identification\n    ↓\nPhase 4: Refactoring Plan Creation\n    ↓\nPhase 5: Incremental Implementation\n    ↓\nPhase 6: Review & Iteration\n```\n\n---\n\n## フェーズ 1: リサーチと分析\n\n### 目的\n- コードベースの構造と目的を把握する\n- リファクタリングの範囲を特定する\n- ビジネス要件に関するコンテキストを収集する\n\n### ユーザーへの確認事項\n開始前に次の点を明確化する。\n\n1. **範囲**: どのファイル/モジュール/関数をリファクタリングするのか?\n2. **目標**: 何を解決したいのか?(可読性、性能、保守性)\n3. **制約**: 変更してはいけない領域はあるか?\n4. **時間的圧力**: 他作業のブロッカーになっているか?\n5. **テスト状況**: テストは存在するか?パスしているか?\n\n### アクション\n- [ ] 対象コードを読み、理解する\n- [ ] 依存関係と統合箇所を洗い出す\n- [ ] 現行アーキテクチャを文書化する\n- [ ] 既存の技術的負債マーカー(TODO、FIXME)を控える\n\n### 出力\nユーザーへの提示内容:\n- コード構造のサマリー\n- 検出された問題箇所\n- 初期推奨事項\n- **着手の承認を依頼する**\n\n---\n\n## フェーズ 2: テストカバレッジの評価\n\n### なぜテストが重要か\n> \"Refactoring without tests is like driving without a seatbelt.\" — Martin Fowler\n\nテストは安全なリファクタリングを可能にする**鍵となる要素**である。テストがなければ、バグを混入させるリスクがある。\n\n### 評価ステップ\n\n1. **既存テストの確認**\n   ```bash\n   # テストファイルを探す\n   find . -name \"*test*\" -o -name \"*spec*\" | head -20\n   ```\n\n2. **既存テストの実行**\n   ```bash\n   # JavaScript/TypeScript\n   npm test\n\n   # Python\n   pytest -v\n\n   # Java\n   mvn test\n   ```\n\n3. **カバレッジの確認(可能な場合)**\n   ```bash\n   # JavaScript\n   npm run test:coverage\n\n   # Python\n   pytest --cov=.\n   ```\n\n### 判断ポイント: ユーザーへの確認\n\n**テストが存在し、かつパスしている場合:**\n- フェーズ 3 へ進む\n\n**テストが不足、または不完全な場合:**\n次の選択肢を提示する。\n1. 先にテストを書く(推奨)\n2. リファクタリング中に段階的にテストを追加する\n3. テストなしで進める(リスクあり、ユーザーの明示的同意が必要)\n\n**テストが失敗している場合:**\n- STOP。リファクタリング前に失敗テストを修正する\n- ユーザーに確認: 先にテストを直すべきか?\n\n### テスト作成のガイドライン(必要時)\n\nリファクタリング対象の各関数について、以下をテストでカバーする。\n- ハッピーパス(通常動作)\n- エッジケース(空入力、null、境界値)\n- エラーシナリオ(無効入力、例外)\n\n「red-green-refactor」サイクルを用いる。\n1. 失敗するテストを書く(red)\n2. パスさせる(green)\n3. リファクタリングする\n\n---\n\n## フェーズ 3: コードスメルの特定\n\n### コードスメルとは?\nコードに潜むより深い問題の症状である。バグそのものではないが、コード改善の余地を示す指標となる。\n\n### よくチェックすべきコードスメル\n\n完全なカタログは [references/code-smells.md](references/code-smells.md) を参照。\n\n#### クイックリファレンス\n\n| スメル | 兆候 | 影響 |\n|-------|-------|--------|\n| **Long Method（長すぎる関数）** | メソッドが 30〜50 行を超える | 理解、テスト、保守が困難 |\n| **Duplicated Code（重複したコード）** | 同じロジックが複数箇所に存在 | バグ修正を複数箇所で行う必要がある |\n| **Large Class（巨大なクラス）** | 責務が多すぎるクラス | 単一責任原則に違反 |\n| **Feature Envy（機能の横恋慕）** | 他クラスのデータを多く使用するメソッド | カプセル化が不十分 |\n| **Primitive Obsession（プリミティブ型への執着）** | オブジェクト化すべき所をプリミティブで多用 | ドメイン概念が欠落 |\n| **Long Parameter List（長すぎるパラメータリスト）** | パラメータが 4 個以上 | 正しく呼び出すのが困難 |\n| **Data Clumps（データの群れ）** | 同じデータ項目が常に一緒に現れる | 抽象化が欠落 |\n| **Switch Statements（スイッチ文)** | 複雑な switch / if-else の連鎖 | 拡張が困難 |\n| **Speculative Generality（投機的一般化）** | 「念のため」のコード | 不要な複雑さ |\n| **Dead Code（デッドコード）** | 使われていないコード | 混乱と保守負担 |\n\n### 分析ステップ\n\n1. **自動分析**(スクリプトが利用可能な場合)\n   ```bash\n   python scripts/detect-smells.py <file>\n   ```\n\n2. **手動レビュー**\n   - コードを体系的に読み進める\n   - 各スメルを場所と深刻度とともに記録する\n   - 影響度別に分類する(Critical / High / Medium / Low)\n\n3. **優先順位付け**\n   次のようなスメルに注力する。\n   - 現在の開発をブロックしているもの\n   - バグや混乱を引き起こしているもの\n   - 変更頻度が高いコードパスに影響するもの\n\n### 出力: スメルレポート\n\nユーザーへの提示内容:\n- 検出されたスメルの一覧と場所\n- 各スメルの深刻度評価\n- 推奨される優先順位\n- **優先順位の承認を依頼する**\n\n---\n\n## フェーズ 4: リファクタリング計画の作成\n\n### リファクタリング技法の選定\n\n各スメルに対して、カタログから適切なリファクタリング技法を選ぶ。\n\n完全な一覧は [references/refactoring-catalog.md](references/refactoring-catalog.md) を参照。\n\n#### スメル別の推奨リファクタリング\n\n| コードスメル | 推奨リファクタリング |\n|------------|---------------------------|\n| Long Method（長すぎる関数） | メソッドの抽出、Replace Temp with Query |\n| Duplicated Code（重複したコード） | メソッドの抽出、Pull Up Method、Form Template Method |\n| Large Class（巨大なクラス） | クラスの抽出、Extract Subclass |\n| Feature Envy（機能の横恋慕） | Move Method、Move Field |\n| Primitive Obsession（プリミティブ型への執着） | Replace Primitive with Object、Replace Type Code with Class |\n| Long Parameter List（長すぎるパラメータリスト） | パラメータオブジェクトの導入、Preserve Whole Object |\n| Data Clumps（データの群れ） | クラスの抽出、パラメータオブジェクトの導入 |\n| Switch Statements（スイッチ文） | ポリモーフィズムによる条件記述の置き換え |\n| Speculative Generality（投機的一般化） | Collapse Hierarchy、Inline Class、デッドコードの削除 |\n| Dead Code（デッドコード） | デッドコードの削除 |\n\n### 計画の構成\n\n[templates/refactoring-plan.md](templates/refactoring-plan.md) のテンプレートを使用する。\n\n各リファクタリングごとに次の項目を埋める。\n1. **対象**: 何を変更するか\n2. **スメル**: どの問題に対処するか\n3. **リファクタリング**: どの技法を適用するか\n4. **手順**: 細かいマイクロステップ\n5. **リスク**: 何が失敗しうるか\n6. **ロールバック**: 取り消す方法\n\n### 段階的アプローチ\n\n**重要**: リファクタリングはフェーズに分けて段階的に導入する。\n\n**フェーズ A: クイックウィン**(低リスク、高価値)\n- 明確化のための変数名変更\n- 明らかな重複コードの抽出\n- デッドコードの削除\n\n**フェーズ B: 構造改善**(中リスク)\n- 長すぎる関数からのメソッド抽出\n- パラメータオブジェクトの導入\n- メソッドを適切なクラスへ移動\n\n**フェーズ C: アーキテクチャ変更**(高リスク)\n- 条件分岐をポリモーフィズムで置換\n- クラスの抽出\n- デザインパターンの導入\n\n### 判断ポイント: ユーザーへの計画提示\n\n実装前に:\n- 完全なリファクタリング計画を提示する\n- 各フェーズの内容とリスクを説明する\n- 各フェーズについて明示的な承認を得る\n- **質問**: 「フェーズ A を進めてもよいか?」\n\n---\n\n## フェーズ 5: 段階的な実装\n\n### ゴールデンルール\n> \"Change → Test → Green? → Commit → Next step\"\n\n### 実装のリズム\n\n各リファクタリングステップで:\n\n1. **事前チェック**\n   - テストがパスしている(green)\n   - コードがコンパイルできる\n\n2. **小さな変更を 1 つだけ行う**\n   - カタログのメカニクスに従う\n   - 変更は最小限に保つ\n\n3. **検証**\n   - 直ちにテストを実行\n   - コンパイルエラーがないか確認\n\n4. **テストがパス(green)した場合**\n   - 説明的なコミットメッセージでコミット\n   - 次のステップへ進む\n\n5. **テストが失敗(red)した場合**\n   - 直ちに STOP\n   - 変更を取り消す\n   - 何が起きたかを分析する\n   - 不明な場合はユーザーに確認する\n\n### コミット戦略\n\n各コミットは次の性質を満たすこと。\n- **アトミック**: 論理的に 1 つの変更\n- **可逆**: 容易に revert できる\n- **説明的**: 明確なコミットメッセージ\n\nコミットメッセージ例:\n```\nrefactor: Extract calculateTotal() from processOrder()\nrefactor: Rename 'x' to 'customerCount' for clarity\nrefactor: Remove unused validateOldFormat() method\n```\n\n### 進捗報告\n\nサブフェーズごとに、ユーザーへ次を報告する。\n- 行った変更\n- テストはまだパスしているか\n- 発生した問題\n- **質問**: 「次のバッチへ進めてもよいか?」\n\n---\n\n## フェーズ 6: レビューと反復\n\n### リファクタリング後チェックリスト\n\n- [ ] 全テストがパスする\n- [ ] 新たな警告/エラーが出ていない\n- [ ] コードが正常にコンパイルできる\n- [ ] 振る舞いが変わっていない(手動検証)\n- [ ] 必要に応じてドキュメントが更新されている\n- [ ] コミット履歴が整理されている\n\n### メトリクス比較\n\nリファクタリング前後で複雑度解析を実施する。\n```bash\npython scripts/analyze-complexity.py <file>\n```\n\n改善点を提示する。\n- コード行数の変化\n- 循環的複雑度の変化\n- 保守性指数の変化\n\n### ユーザーレビュー\n\n最終結果を提示する。\n- 全変更のサマリー\n- Before / After のコード比較\n- メトリクスの改善\n- 残る技術的負債\n- **質問**: 「この変更内容で問題ないか?」\n\n### 次のステップ\n\nユーザーと議論する。\n- 追加で対処すべきスメルはあるか?\n- フォローアップのリファクタリングを計画するか?\n- 同様の変更を他箇所にも適用するか?\n\n---\n\n## 重要なガイドライン\n\n### STOP してユーザーに相談すべきタイミング\n\n次の場合、必ず一旦止まりユーザーに相談する。\n- ビジネスロジックに不確実性がある\n- 外部 API に影響しうる変更\n- テストカバレッジが不十分\n- 重大なアーキテクチャ判断が必要\n- リスクレベルが上昇する\n- 想定外の複雑さに遭遇した\n\n### 安全のためのルール\n\n1. **テストなしでリファクタリングしない**(ユーザーが明示的にリスクを受容しない限り)\n2. **大きな変更を一度にしない** - 微小なステップに分割する\n3. **各変更後のテスト実行を省略しない**\n4. **テスト失敗時は続行しない** - 修正かロールバックを先に行う\n5. **思い込みで進めない** - 疑問があれば確認する\n\n### やってはいけないこと\n\n- リファクタリングと機能追加を同時に行わない\n- 本番障害対応中にリファクタリングしない\n- 理解していないコードをリファクタリングしない\n- 過剰設計をしない - シンプルに保つ\n- 全てを一度にリファクタリングしない\n\n---\n\n## クイックスタート例\n\n### シナリオ: 重複を含む長い関数\n\n**Before:**\n```javascript\nfunction processOrder(order) {\n  // 150 行のコードに以下が混在:\n  // - 重複したバリデーションロジック\n  // - インラインの計算処理\n  // - 複数の責務\n}\n```\n\n**リファクタリング手順:**\n\n1. processOrder() に対する**テストの存在を確認**\n2. バリデーションを validateOrder() に**抽出**\n3. **テスト** - パスすること\n4. 計算を calculateOrderTotal() に**抽出**\n5. **テスト** - パスすること\n6. 通知を notifyCustomer() に**抽出**\n7. **テスト** - パスすること\n8. **レビュー** - processOrder() は明確な 3 関数の調整役となる\n\n**After:**\n```javascript\nfunction processOrder(order) {\n  validateOrder(order);\n  const total = calculateOrderTotal(order);\n  notifyCustomer(order, total);\n  return { order, total };\n}\n```\n\n---\n\n## 参考文献\n\n- [Code Smells Catalog](references/code-smells.md) - コードスメルの完全な一覧\n- [Refactoring Catalog](references/refactoring-catalog.md) - リファクタリング技法\n- [Refactoring Plan Template](templates/refactoring-plan.md) - 計画用テンプレート\n\n## スクリプト\n\n- `scripts/analyze-complexity.py` - コード複雑度メトリクスの分析\n- `scripts/detect-smells.py` - スメルの自動検出\n\n## バージョン履歴\n\n- v1.0.0 (2025-01-15): Fowler の方法論、段階的アプローチ、ユーザー相談ポイントを備えた初版リリース\n\n<!-- File: uk/03-skills/blog-draft/SKILL.md (Tokens: ~4730 | Category: anthropic-skill) -->\n---\nname: blog-draft\ndescription: Створення чернетки блог-посту з ідей та ресурсів. Використовуйте, коли користувачі хочуть написати блог-пост, створити контент з дослідження або підготувати статтю. Проводить через дослідження, мозковий штурм, складання плану та ітеративне написання з контролем версій.\n---\n\n## Введення користувача\n\n```text\n$ARGUMENTS\n```\n\nВи **ПОВИННІ** врахувати введення користувача перед продовженням. Користувач має надати:\n- **Ідея/Тема**: Основна концепція або тематика блог-посту\n- **Ресурси**: URL, файли або посилання на дослідження (необовʼязково, але рекомендовано)\n- **Цільова аудиторія**: Для кого блог-пост (необовʼязково)\n- **Тон/Стиль**: Формальний, невимушений, технічний тощо (необовʼязково)\n\n**ВАЖЛИВО**: Якщо користувач запитує оновлення **існуючого блог-посту**, пропустіть кроки 0-8 і починайте безпосередньо з **Кроку 9**. Спочатку прочитайте існуючий файл(и) чернетки, потім продовжуйте з процесом ітерації.\n\n## Потік виконання\n\nВиконуйте ці кроки послідовно. **Не пропускайте кроки та не продовжуйте без затвердження користувача, де це зазначено.**\n\n### Крок 0: Створення папки проєкту\n\n1. Згенерувати назву папки у форматі: `YYYY-MM-DD-short-topic-name`\n   - Використати сьогоднішню дату\n   - Створити короткий, URL-дружній slug з теми (малі літери, дефіси, макс. 5 слів)\n\n2. Створити структуру папок:\n   ```\n   blog-posts/\n   └── YYYY-MM-DD-short-topic-name/\n       └── resources/\n   ```\n\n3. Підтвердити створення папки з користувачем перед продовженням.\n\n### Крок 1: Дослідження та збір ресурсів\n\n1. Створити підпапку `resources/` у каталозі блог-посту\n\n2. Для кожного наданого ресурсу:\n   - **URL-адреси**: Отримати та зберегти ключову інформацію до `resources/` як markdown-файли\n   - **Файли**: Прочитати та підсумувати в `resources/`\n   - **Теми**: Використати веб-пошук для збору актуальної інформації\n\n3. Для кожного ресурсу створити файл резюме в `resources/`:\n   - `resources/source-1-[short-name].md`\n   - `resources/source-2-[short-name].md`\n   - тощо\n\n4. Кожне резюме має включати:\n   ```markdown\n   # Джерело: [Назва/URL]\n\n   ## Ключові тези\n   - Теза 1\n   - Теза 2\n\n   ## Релевантні цитати/дані\n   - Цитата або статистика 1\n   - Цитата або статистика 2\n\n   ## Як це стосується теми\n   Короткий опис релевантності\n   ```\n\n5. Представити резюме дослідження користувачу.\n\n### Крок 2: Мозковий штурм та уточнення\n\n1. На основі ідеї та досліджених ресурсів представити:\n   - **Основні теми**, виявлені з дослідження\n   - **Потенційні ракурси** для блог-посту\n   - **Ключові тези**, які слід розкрити\n   - **Прогалини** в інформації, що потребують уточнення\n\n2. Поставити уточнюючі запитання:\n   - Який головний висновок ви хочете донести до читачів?\n   - Чи є конкретні тези з дослідження, які хочете виділити?\n   - Яка цільова довжина? (коротка: 500-800 слів, середня: 1000-1500, довга: 2000+)\n   - Щось хочете виключити?\n\n3. **Чекати відповідей користувача перед продовженням.**\n\n### Крок 3: Запропонувати план\n\n1. Створити структурований план, що включає:\n\n   ```markdown\n   # План блог-посту: [Назва]\n\n   ## Метаінформація\n   - **Цільова аудиторія**: [хто]\n   - **Тон**: [стиль]\n   - **Цільова довжина**: [кількість слів]\n   - **Головний висновок**: [ключове повідомлення]\n\n   ## Запропонована структура\n\n   ### Зачіпка/Вступ\n   - Ідея вступної зачіпки\n   - Встановлення контексту\n   - Теза\n\n   ### Розділ 1: [Назва]\n   - Ключова теза A\n   - Ключова теза B\n   - Підтверджуючі докази з [джерела]\n\n   ### Розділ 2: [Назва]\n   - Ключова теза A\n   - Ключова теза B\n\n   [Продовжити для всіх розділів...]\n\n   ### Висновок\n   - Резюме ключових тез\n   - Заклик до дії або завершальна думка\n\n   ## Джерела для цитування\n   - Джерело 1\n   - Джерело 2\n   ```\n\n2. Представити план користувачу та **запитати затвердження або модифікації**.\n\n### Крок 4: Зберегти затверджений план\n\n1. Після затвердження плану користувачем зберегти його як `OUTLINE.md` у папці блог-посту.\n\n2. Підтвердити збереження плану.\n\n### Крок 5: Закомітити план (якщо в git-репо)\n\n1. Перевірити, чи поточний каталог є git-репозиторієм.\n\n2. Якщо так:\n   - Додати нові файли до індексу: папку блог-посту, ресурси та OUTLINE.md\n   - Створити коміт з повідомленням: `docs: Add outline for blog post - [topic-name]`\n   - Відправити на віддалений сервер\n\n3. Якщо не git-репо, пропустити цей крок та повідомити користувача.\n\n### Крок 6: Написати чернетку\n\n1. На основі затвердженого плану написати повну чернетку блог-посту.\n\n2. Точно дотримуватися структури з OUTLINE.md.\n\n3. Включити:\n   - Захопливий вступ із зачіпкою\n   - Чіткі заголовки розділів\n   - Підтверджуючі докази та приклади з дослідження\n   - Плавні переходи між розділами\n   - Сильний висновок з головною тезою\n   - **Цитування**: Усі порівняння, статистика, дані та фактичні твердження ПОВИННІ цитувати оригінальне джерело\n\n4. Зберегти чернетку як `draft-v0.1.md` у папці блог-посту.\n\n5. Формат:\n   ```markdown\n   # [Назва блог-посту]\n\n   *[Необовʼязково: підзаголовок або слоган]*\n\n   [Повний вміст з інлайн-цитатами...]\n\n   ---\n\n   ## Список джерел\n   - [1] Назва джерела 1 - URL або цитата\n   - [2] Назва джерела 2 - URL або цитата\n   - [3] Назва джерела 3 - URL або цитата\n   ```\n\n6. **Вимоги до цитування**:\n   - Кожна точка даних, статистика або порівняння ПОВИННІ мати інлайн-цитату\n   - Використовуйте нумеровані посилання [1], [2] тощо, або іменовані цитати [Назва джерела]\n   - Звʼязуйте цитати з розділом Список джерел наприкінці\n   - Приклад: «Дослідження показують, що 65% розробників віддають перевагу TypeScript [1]»\n   - Приклад: «React перевершує Vue за швидкістю рендерингу на 20% [React Benchmarks 2024]»\n\n### Крок 7: Закомітити чернетку (якщо в git-репо)\n\n1. Перевірити, чи в git-репозиторії.\n\n2. Якщо так:\n   - Додати файл чернетки до індексу\n   - Створити коміт з повідомленням: `docs: Add draft v0.1 for blog post - [topic-name]`\n   - Відправити на віддалений сервер\n\n3. Якщо не git-репо, пропустити та повідомити користувача.\n\n### Крок 8: Представити чернетку для перегляду\n\n1. Представити вміст чернетки користувачу.\n\n2. Запитати зворотний звʼязок:\n   - Загальне враження?\n   - Розділи, що потребують розширення або скорочення?\n   - Потрібні корекції тону?\n   - Відсутня інформація?\n   - Конкретні правки або переписування?\n\n3. **Чекати відповіді користувача.**\n\n### Крок 9: Ітерація або фіналізація\n\n**Якщо користувач запитує зміни:**\n1. Зафіксувати всі запитані модифікації\n2. Повернутися до Кроку 6 з такими змінами:\n   - Збільшити номер версії (v0.2, v0.3 тощо)\n   - Врахувати всі зауваження\n   - Зберегти як `draft-v[X.Y].md`\n   - Повторити Кроки 7-8\n\n**Якщо користувач затверджує:**\n1. Підтвердити фінальну версію чернетки\n2. За бажанням перейменувати на `final.md`\n3. Підсумувати процес створення блог-посту:\n   - Загальна кількість створених версій\n   - Ключові зміни між версіями\n   - Фінальна кількість слів\n   - Створені файли\n\n## Відстеження версій\n\nУсі чернетки зберігаються з інкрементальним версіонуванням:\n- `draft-v0.1.md` — початкова чернетка\n- `draft-v0.2.md` — після першого раунду зауважень\n- `draft-v0.3.md` — після другого раунду зауважень\n- тощо\n\nЦе дозволяє відстежувати еволюцію блог-посту та повертатися до попередніх версій за потреби.\n\n## Структура вихідних файлів\n\n```\nblog-posts/\n└── YYYY-MM-DD-topic-name/\n    ├── resources/\n    │   ├── source-1-name.md\n    │   ├── source-2-name.md\n    │   └── ...\n    ├── OUTLINE.md\n    ├── draft-v0.1.md\n    ├── draft-v0.2.md (якщо ітерації)\n    └── draft-v0.3.md (якщо більше ітерацій)\n```\n\n## Поради щодо якості\n\n- **Зачіпка**: Починайте з питання, дивовижного факту або знайомого сценарію\n- **Потік**: Кожен абзац має зʼєднуватися з наступним\n- **Докази**: Підтверджуйте твердження даними з дослідження\n- **Цитування**: ЗАВЖДИ цитуйте джерела для:\n  - Усіх статистик та даних (напр., «За даними [Джерело], 75%...»)\n  - Порівнянь між продуктами, сервісами або підходами (напр., «X працює у 2 рази швидше за Y [Джерело]»)\n  - Фактичних тверджень про ринкові тенденції, результати досліджень або бенчмарки\n  - Використовуйте інлайн-цитати у форматі: [Назва джерела] або [Автор, Рік]\n- **Голос**: Підтримуйте послідовний тон протягом усього тексту\n- **Довжина**: Дотримуйтесь цільової кількості слів\n- **Читабельність**: Використовуйте короткі абзаци, маркери де доречно\n- **CTA**: Завершуйте чітким закликом до дії або питанням, що провокує думки\n\n## Примітки\n\n- Завжди чекайте затвердження користувача у зазначених контрольних точках\n- Зберігайте всі версії чернеток для історії\n- Використовуйте веб-пошук для актуальної інформації, коли надані URL\n- Якщо ресурсів недостатньо, попросіть користувача надати більше або запропонуйте додаткове дослідження\n- Адаптуйте тон відповідно до цільової аудиторії (технічна, загальна, бізнес тощо)\n\n<!-- ... +54 more modular skills available via /api/skills/luongnv89/claude-howto?path={path} -->\n</yakaai_skills>"}