Agent Skill
2/7/2026

knowledge-architecture

Knowledge management for Claude Code projects. Use when: creating skills or agents, deciding where to put new knowledge (skill vs CLAUDE.md vs reference-data vs memory vs agent), routing information, CLAUDE.md hygiene, editing/modifying CLAUDE.md or skills or agents or memory files, extracting content from bloated files, or any discussion about knowledge architecture, documentation structure, or SOP placement. MUST be invoked BEFORE proposing any edits to CLAUDE.md, skills, agents, or memory - no exceptions.

A
artymclabin
4GitHub Stars
1Views
npx skills add ArtyMcLabin/ClaudeCode-global-config

SKILL.md

Nameknowledge-architecture
DescriptionKnowledge management for Claude Code projects. Use when: creating skills or agents, deciding where to put new knowledge (skill vs CLAUDE.md vs reference-data vs memory vs agent), routing information, CLAUDE.md hygiene, editing/modifying CLAUDE.md or skills or agents or memory files, extracting content from bloated files, or any discussion about knowledge architecture, documentation structure, or SOP placement. MUST be invoked BEFORE proposing any edits to CLAUDE.md, skills, agents, or memory - no exceptions.

name: knowledge-architecture description: Knowledge management for Claude Code projects. Use when: creating skills or agents, deciding where to put new knowledge (skill vs CLAUDE.md vs reference-data vs memory vs agent), routing information, CLAUDE.md hygiene, editing/modifying CLAUDE.md or skills or agents or memory files, extracting content from bloated files, or any discussion about knowledge architecture, documentation structure, or SOP placement. MUST be invoked BEFORE proposing any edits to CLAUDE.md, skills, agents, or memory - no exceptions. user-invocable: false

Claude Code Knowledge Management

Part 1: Where Does Knowledge Go?

Evaluate in order. First match wins.

0. BEHAVIORAL FIX FOR EXISTING AGENT/SKILL (agent outputs bad data, skill misses a check):
   โ†’ Update the agent/skill definition directly โ€” it owns its own behavior rules
   โ†’ SSoT: don't scatter fixes across CLAUDE.md, memory, or caller prompts
   โ†’ Poka-yoke: fix at the source so ALL callers benefit, not just the one who hit the bug

1. TABULAR/REGISTRY DATA (URLs, IDs, contacts, rosters):
   โ†’ Used by ONE skill: .claude/skills/{skill}/references/*.md
   โ†’ Used repo-wide: reference-data/*.md

2. SITUATIONAL PERSONAL DATA (address, ID, rarely-needed info):
   โ†’ Create pointer registry (reference-data/personal-data-sources.md)
   โ†’ Registry contains POINTERS to sources (Keep notes, sheets), not data
   โ†’ CLAUDE.md has one-liner: "check registry for personal info"
   โ†’ PA looks up dynamically when needed, doesn't cache in context
   โ†’ Pattern: reference-data/{type}-sources.md with table of pointers

3. NEEDS ISOLATED CONTEXT (heavy processing, browser automation):
   โ†’ Propose agent to user, await approval
   โ†’ If rejected: create skill instead

4. DOMAIN KNOWLEDGE (procedures, workflows, explanations):
   โ†’ .claude/skills/{name}/SKILL.md
   โ†’ This is the default for most content

5. SESSION-LEARNED LESSON (mistake pattern, environment quirk, workaround):
   โ†’ Auto memory: ~/.claude/projects/{project}/memory/MEMORY.md (or topic files in same dir)
   โ†’ MEMORY.md is always loaded into system prompt โ€” keep under 200 lines
   โ†’ Use for: lessons that DON'T belong to any skill/agent but affect behavior across sessions
   โ†’ Do NOT use for: behavioral fixes to existing skills/agents (rule 0), procedures (rule 4), or data (rule 1)
   โ†’ Anti-pattern: duplicating a rule that already exists in a skill/hook/CLAUDE.md โ€” memory is NOT for reinforcement of existing rules

6. ONE-LINER CROSS-CUTTING RULE:
   โ†’ CLAUDE.md (only if truly 1-2 lines)

7. UNCLEAR:
   โ†’ Ask user

Pointer Registry Pattern (for situational data): When user provides info that PA needs occasionally but shouldn't bloat every session:

  1. Ask: "Should I add this to a source registry for future lookup?"
  2. Create/update reference-data/{domain}-sources.md
  3. Store POINTER (source location), not actual data
  4. Add one-liner to CLAUDE.md: "For X, check reference-data/{domain}-sources.md"
  5. PA dynamically looks up only when needed

Part 2: CLAUDE.md Hygiene

CLAUDE.md bloats fast. Rules:

  • One-liners only - >2-3 lines = extract to skill
  • Pointers not content - "See skill X" not the procedure
  • No procedures - All procedures โ†’ skills
  • Skills are default - When in doubt, create skill
  • Minimal edits - Modify existing or remove violations OK; adding = max 1 line
  • Agents need approval - Never auto-create

Part 3: Skill Structure

.claude/skills/{name}/
โ”œโ”€โ”€ SKILL.md              โ† Required (exact filename)
โ”‚   โ”œโ”€โ”€ YAML frontmatter  โ† Required: name + description
โ”‚   โ””โ”€โ”€ Markdown body     โ† Instructions
โ”œโ”€โ”€ references/           โ† Docs loaded on demand
โ”œโ”€โ”€ scripts/              โ† Executable code
โ””โ”€โ”€ assets/               โ† Templates, files for output

Critical:

  • Path must be .claude/skills/{name}/SKILL.md
  • Frontmatter description determines when skill triggers - be comprehensive
  • Body only loads AFTER skill triggers
  • .claude/ must NOT be gitignored

Part 4: Frontmatter

Official reference: https://code.claude.com/docs/en/skills

Standard template (use for ALL skills):

---
name: skill-name
description: What it does AND when to use it. This is critical - Claude uses it to decide when to apply the skill.
user-invocable: false
---

Complete field reference

FieldRequiredDefaultDescription
nameNodirectory nameDisplay name. Lowercase, numbers, hyphens only (max 64 chars).
descriptionRecommendedfirst paragraph of bodyWHAT + WHEN. Claude uses this to decide when to apply the skill.
user-invocableYes (our standard)trueSet to false on ALL skills. Our skills are background knowledge, not user-invocable commands.
disable-model-invocationNofalseSet true to prevent Claude from auto-loading. Use for side-effect workflows user must trigger manually.
allowed-toolsNoconversation permissionsTools Claude can use without per-use approval when skill is active. String or array.
modelNoinheritsModel override (sonnet, opus, haiku).
contextNoinlineSet to fork to run in a forked subagent context (isolated context window).
agentNogeneral-purposeWhich subagent type when context: fork is set. Built-in: Explore, Plan, general-purpose, or custom from .claude/agents/.
argument-hintNononeHint for autocomplete, e.g. [issue-number].
hooksNononeHooks scoped to this skill's lifecycle.

Invocation matrix (how fields interact):

FrontmatterUser can /invokeClaude auto-loadsContext loading
(default)YesYesDescription always in context, body loads on invoke
disable-model-invocation: trueYesNoDescription NOT in context
user-invocable: falseNoYesDescription always in context, body loads on invoke

String substitutions available in skill body:

  • $ARGUMENTS โ€” all arguments passed on invocation
  • $ARGUMENTS[N] or $N โ€” specific argument by 0-based index
  • ${CLAUDE_SESSION_ID} โ€” current session ID
  • !`command` โ€” dynamic context injection (shell command runs before skill content is sent)

Our standard: user-invocable: false

ALL skills MUST include user-invocable: false. Our skills are model-invoked background knowledge (Claude decides when to load them based on description). Only slash commands in .claude/commands/ are user-invocable. Omitting this field defaults to true, which pollutes the / menu with non-actionable entries.

When to propose context: fork

context: fork runs the skill in an isolated subagent context. The skill body becomes the subagent's task prompt โ€” it won't have conversation history.

Propose context: fork when:

  • Skill involves heavy browser automation or screenshot processing
  • Skill processes large data (parsing spreadsheets, logs, transcripts)
  • Skill runs multi-step workflows that could bloat parent context
  • Skill is frequently delegated to Task tool subagents anyway
  • Skill has explicit task instructions (not just guidelines/conventions)

Do NOT use when:

  • Skill is lightweight (lookup, simple procedure, reference)
  • Skill needs to read/write parent conversation state
  • Skill is a quick decision tree or routing logic
  • Skill contains conventions/guidelines without an actionable task (subagent gets guidelines but no task = useless)

Workflow: When creating/editing a skill and context: fork seems beneficial, propose to user: "This skill involves [heavy processing/browser automation/etc.] โ€” recommend adding context: fork so it runs in an isolated context. Approve?" Do NOT add silently. If proposing fork, also suggest an appropriate agent: value.

Troubleshooting Misbehaving Skills

If a skill is not triggering, triggers too often, or behaves unexpectedly, fetch the troubleshooting section from https://code.claude.com/docs/en/skills for current diagnostic steps. Key issues:

SymptomLikely CauseFix
Skill not triggeringDescription missing keywords users naturally sayRephrase description with concrete trigger phrases
Skill triggers too oftenDescription too broadNarrow description; consider disable-model-invocation: true
Claude doesn't see all skillsToo many skill descriptions exceed character budget (default 15k)Run /context to check; set SLASH_COMMAND_TOOL_CHAR_BUDGET env var to increase
Fork skill returns emptySkill has guidelines but no actionable taskcontext: fork needs explicit task instructions, not just conventions

Always fetch the live URL โ€” troubleshooting guidance may be updated upstream.

Part 5: Writing Guidelines

  1. Imperative form - "Create documents" not "This skill creates"
  2. Description is trigger - Include all contexts when skill should activate
  3. Don't repeat - Info in SKILL.md OR references, not both
  4. Concise - Claude is smart; only add context it lacks
  5. Compliance reporting - After creating/editing a skill, just say "โœ… Compliant with knowledge-architecture" โ€” don't enumerate every rule that was followed
  6. Deterministic output format - When a skill or SOP produces user-facing output (reports, tables, status updates), define the EXACT format in the skill body. Include:
    • A template/example showing the structure
    • Emoji legends for visual scanning (e.g., ๐Ÿ’ป = code, ๐Ÿ“„ = docs, โœ… = done, โš ๏ธ = attention)
    • Column names, row ordering, section order
    • This ensures identical formatting across sessions โ€” user builds muscle memory for scanning output. Ad-hoc formatting = cognitive overhead every time.

Part 5b: Reference Doc Types & Three-Level Hierarchy

references/ files serve two distinct purposes. Never mix them in one file.

TypePurposeSSoT rule
OperationalRegistry data, design rationale for runtime choicesSupplements the skill; skill body is SSoT for behavior
Re-engineeringChange impact, contracts, extension checklists for modifying the frameworkMust NOT re-describe what skills already define โ€” only meta-guidance for maintainers

If a re-engineering guide drifts from the skills, the skills win. The guide is a convenience layer, never a source of truth for behavior.

Three Levels of Context Engineering

When skills form a framework (e.g., autonomous issue dispatch with 5+ interconnected skills):

Level 1: Operational skills (SKILL.md)        โ€” SSoT for behavior
Level 2: Re-engineering guides (references/)   โ€” how to safely modify Level 1; must not duplicate it
Level 3: This skill (knowledge-architecture)   โ€” governs how Levels 1 and 2 are structured

When creating a re-engineering guide: It must add value beyond reading the skills sequentially โ€” change impact analysis, interface contracts, extension checklists. Content that's already true by reading the skills doesn't belong in the guide.

Part 6: Size Management

ComponentGuidelineLoaded
SKILL.md body~500 linesWhen skill triggers
references/UnlimitedOn demand
scripts/UnlimitedExecuted, not loaded

If >500 lines: keep core workflow in SKILL.md, move details to references/.

Part 7: Global vs Local

LocationScope
~/.claude/skills/All projects
.claude/skills/ (repo)This project only

Part 8: Post-Creation

  1. Frontmatter has name:, description:, and user-invocable: false
  2. Description explains WHAT + WHEN comprehensively
  3. Located at .claude/skills/{name}/SKILL.md
  4. Add to .claude/settings.json: "Skill(name)" in permissions.allow
  5. Register in CLAUDE.md skills index (local skills only)
  6. Evaluate whether context: fork is appropriate โ€” if yes, propose to user
  7. ๐Ÿงช Evaluate whether a reminder hook is appropriate (see Part 12) โ€” if Claude repeatedly forgets to follow this skill and it maps to a matchable action, create a PostToolUse hook and log it on the tracking issue

Part 9: No Subagent Delegation for Context Engineering

NEVER delegate context engineering changes to subagents (developer, general-purpose, etc.). This includes edits to CLAUDE.md, skills, agents, and memory files.

Why: Context engineering changes encode the owner's intent and philosophy from the current conversation. Subagents lack conversation history and can only work from the prompt given โ€” nuances discussed with the owner are silently lost. A broken SOP degrades all future sessions, making this higher-stakes than application code.

Do it yourself, even when it's slow. PreToolUse hooks that block SKILL.md edits require retries โ€” that's annoying but the cost is mechanical (extra tool calls), not intellectual. The alternative (subagent) risks semantic drift.

Exception: None. If the edit volume is too high for one session, split across sessions rather than delegate.


Part 10: Agents (Require Approval)

Never auto-create agents. Protocol:

  1. Identify candidate (needs isolated context, heavy processing)
  2. Propose: "This could be an agent because [X]. Create agent?"
  3. User approves โ†’ .claude/agents/*.md
  4. User rejects โ†’ Create skill instead

Part 11: Search Both Locations

When searching for agents or skills, ALWAYS check both:

TypeLocal (project)Global (user home)
Skills.claude/skills/~/.claude/skills/
Agents.claude/agents/~/.claude/agents/

Never assume "not found" after checking only one location.

Part 12: Auto-Fix Rule

When this skill is invoked to review an edit that already happened (post-hoc), do NOT ask the user whether to fix violations. Fix them immediately, then report:

  1. What was violated
  2. What was fixed
  3. What was learned

Asking "want me to fix this?" after reading a skill that clearly states the rules wastes the user's time. The rules are unambiguous โ€” just apply them.

Pre-Edit Root Cause Check

๐Ÿšจ Before editing any skill, ask: "Did I actually invoke/follow this skill during the task that revealed the gap?"

  • If NO โ€” the edit alone won't prevent recurrence. The root cause is that the skill wasn't loaded, not that it was incomplete. After making the edit, also evaluate:
    1. Why wasn't the skill triggered? (description too narrow? no hook? wrong trigger phrases?)
    2. What would have caught it? (add hook per Part 12? broaden description? add trigger to CLAUDE.md skill index?)
    3. Implement the prevention โ€” don't just fix content and move on
  • If YES โ€” the skill was loaded but insufficient. Content edit is the correct fix.

Part 13: Skill Reminder Hooks (๐Ÿงช Experimental)

Tracking issue: https://github.com/<GITHUB_USER>/PersonalAssistant-ClaudeCode/issues/23 Status: Evaluating until 2026-02-02. When implementing this pattern, comment on the issue with where you applied it (repo, skill name, hook matcher) so we can track all implementations and roll back if needed.

Problem

Claude frequently forgets to load relevant skills before/during actions. CLAUDE.md instructions are suggestions; hooks are deterministic guarantees.

Pattern: PostToolUse Reminder Hook

A PostToolUse hook fires after every tool call matching a pattern. By exiting with code 2 and writing to stderr, the message is fed directly to Claude as feedback (not just shown to the user). This forces Claude to acknowledge and follow the skill.

How It Works

Claude edits file โ†’ PostToolUse hook fires โ†’ script checks file type โ†’
  If match: exit 2 + stderr reminder โ†’ Claude receives feedback, loads skill
  If no match: exit 0 โ†’ silent, no overhead

Implementation Steps

When creating or modifying a skill that Claude frequently forgets to follow:

  1. Create the hook script in the skill's scripts/ folder:
#!/usr/bin/env python3
"""PostToolUse reminder hook for {skill-name}."""
import json, sys

try:
    data = json.load(sys.stdin)
except (json.JSONDecodeError, EOFError):
    sys.exit(0)  # exit 0 = silent pass-through (no input, not our concern)

file_path = data.get("tool_input", {}).get("file_path", "")

# Adjust condition to match the skill's domain
if not file_path.lower().endswith(".md"):
    sys.exit(0)  # exit 0 = not a match, pass silently

content = (
    "You modified a file relevant to {skill-name}. "
    "Follow the {skill-name} skill (~/.claude/skills/{name}/SKILL.md)."
)

# ASCII-only border (Unicode crashes on Windows cp1252)
border = "=" * 70
msg = f"\n+{border}\n| HOOK OUTPUT\n+{border}\n\n{content}\n\n+{border}\n"
print(msg, file=sys.stderr)
sys.exit(2)  # exit 2 = feedback to Claude (MUST be 2, not 0)
  1. Register the hook in ~/.claude/settings.json (global) or .claude/settings.json (project):

๐Ÿšจ Cross-platform compatibility: Use python -c with os.path.expanduser('~') to resolve the home directory. $HOME doesn't expand on Windows, and hardcoded paths aren't portable. Only $CLAUDE_PROJECT_DIR is reliably injected by Claude Code (for project-scoped hooks only).

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write|MultiEdit",
        "hooks": [{
          "type": "command",
          "command": "python -c \"import os;exec(open(os.path.expanduser('~/.claude/skills/{name}/scripts/postToolUse-reminder.py')).read())\"",
          "timeout": 5
        }]
      }
    ]
  }
}
  1. Comment on the tracking issue (https://github.com/<GITHUB_USER>/PersonalAssistant-ClaudeCode/issues/23) with:
    • Skill name and path
    • Hook matcher used
    • File type / condition that triggers the reminder

Hook Event Reference

EventWhenUse For
PostToolUseAfter tool succeedsRemind after file edits (most common)
PreToolUseBefore tool runsBlock/warn before dangerous actions
StopClaude finishes respondingVerify all rules were followed
SubagentStopSubagent finishesValidate subagent output quality
SessionStartSession beginsInject context (schedule, state)

Matchers: Tool name patterns โ€” Edit|Write|MultiEdit, Bash, mcp__gmail__send_email, * (all), etc.

Exit codes: 0 = silent, 2 = feedback to Claude (stderr), other = non-blocking error.

๐Ÿšจ Hook stdin input varies by event type:

Eventstdin fieldsHow to get transcript data
PreToolUsetool_name, tool_inputN/A
PostToolUsetool_name, tool_input, tool_outputN/A
Stopsession_id, transcript_path, cwd, stop_hook_activeParse JSONL file at transcript_path

Stop hooks do NOT receive transcript_summary or tools_used. Must read and parse transcript_path (JSONL, one JSON object per line, entries have type: "assistant" with content blocks containing tool_use and text).

Official docs: https://code.claude.com/docs/en/hooks

Pattern: PreToolUse Blocking Hook

A PreToolUse hook fires before tool execution. Exit code 2 blocks the tool call entirely and feeds the stderr message to Claude. Use this to permanently blacklist dangerous/faulty tool variants.

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "mcp__dangerous__tool_name",
        "hooks": [{
          "type": "command",
          "command": "echo 'BLOCKED: Use mcp__safe__tool_name instead. Reason: [why].' && exit 2",
          "timeout": 5
        }]
      }
    ]
  }
}

When to use blocking hooks:

  • Two MCP tools overlap in function but one is broken/unsafe
  • A tool silently fails (no error, wrong behavior) โ€” worse than crashing
  • The correct alternative is known and deterministic

When NOT to use:

  • Tool works but needs guardrails โ†’ use reminder hook instead
  • Tool is the only option โ†’ fix the tool, don't block it

Pattern: Poka-Yoke Blocking Hook (Block + Bypass Flag)

A poka-yoke (mistake-proofing) hook blocks a dangerous action by default but provides a bypass flag that Claude can use after verifying the action is genuinely correct. This creates a two-step flow:

  1. Claude attempts the action โ†’ hook blocks it with rejection reason + bypass instructions
  2. Claude evaluates: is there a better approach (API, ORM, etc.)?
    • Yes โ†’ use the proper approach (hook achieved its goal)
    • No (direct action is genuinely required) โ†’ retry with bypass flag in the command

Key design principles:

  • Block is the default โ€” unsafe action never runs without conscious acknowledgment
  • Bypass flag is embedded in the command โ€” Claude must modify the command to include it, forcing deliberate intent
  • Rejection message teaches โ€” explains WHY it's blocked and WHAT the preferred alternative is
  • No user interaction needed โ€” Claude self-corrects without bothering the user

Implementation:

# In the hook script:
BYPASS_FLAG = "--confirmed-reason"

# Check for bypass flag in command
if BYPASS_FLAG in command:
    sys.exit(0)  # Allow through

# Block with instructions
content = (
    "BLOCKED: [dangerous action] detected.\n"
    "PREFERRED: Use [safe alternative] instead.\n"
    f"IF [safe alternative] is unavailable: re-run with {BYPASS_FLAG} flag.\n"
    "Example: command /* {BYPASS_FLAG} */ args..."
)
print(content, file=sys.stderr)
sys.exit(2)

When to use poka-yoke (vs hard block vs reminder):

PatternWhenClaude can proceed?
Hard blockAction is NEVER correct (e.g., drizzle-kit push)No โ€” must use alternative
Poka-yokeAction is usually wrong but sometimes correct (e.g., raw SQL when API unavailable)Yes โ€” with bypass flag
ReminderAction is correct but needs guardrails (e.g., check skill before editing)Yes โ€” always proceeds

Existing implementations:

HookBypass FlagBlocksPreferred Alternative
preToolUse-block-raw-sql-writes.py--sql-write-confirmedpsql UPDATE/INSERT/DELETE/ALTER/DROP/TRUNCATEAdmin API endpoints

Testing Hooks (Subprocess Verification)

๐Ÿšจ Hook changes in settings.json only apply to NEW Claude Code sessions. The current session uses the settings loaded at startup.

To verify a hook works without restarting your session:

# Safe test โ€” spawns a fresh CC instance that loads new settings
# Use --print flag to run non-interactively (prints output, exits)
claude --print "Try calling mcp__google-workspace__gmail_send to <YOUR_EMAIL> with subject 'Hook verification test' and body 'This should be blocked by PreToolUse hook.'" --allowedTools "mcp__google-workspace__gmail_send,mcp__google-workspace__gmail_*"

Safety rules for subprocess hook testing:

  • ONLY test blocking hooks โ€” never test reminder hooks this way (they don't block, so the action executes)
  • ONLY use self-targeted test data โ€” send to user's own email, use test subjects
  • NEVER test hooks that involve destructive actions โ€” if the hook fails, the action runs
  • Expected result: The subprocess should report the hook blocked the tool. If the tool executes, the hook is misconfigured.
  • If test fails (tool executes): Check matcher pattern, exit code (must be 2), and that settings.json is valid JSON

Hook Pitfalls (MANDATORY checklist)

Before deploying any hook script:

  1. Exit codes โ€” sys.exit(0) = silent pass, sys.exit(2) = feedback to Claude. The FINAL exit must be 2 for the hook to actually work. Using 0 makes the hook a silent no-op.
  2. ASCII only in .py source โ€” exec(open(...).read()) on Windows uses cp1252 encoding. Unicode box-drawing (โ•โ•”โ•—โ• โ•ฃโ•šโ•) and emojis crash the script silently before any code executes. Use ASCII borders only: =, +, |.
  3. QA in fresh instance โ€” After creating or modifying any hook, test in a fresh claude --print instance (see "Testing Hooks" section). Current session caches settings at startup. Never consider a hook change done without end-to-end verification. Test ALL tool variants in the matcher โ€” if matcher covers 5 tools, test all 5, not just one.

When to Add a Reminder Hook

Add a hook when ALL of these are true:

  • Claude repeatedly forgets to follow the skill (proven pattern, not hypothetical)
  • The skill applies to a matchable action (file type, tool name, MCP call)
  • The skill is corrective/preventive (rules to enforce, not just reference info)

Do NOT add hooks for:

  • Informational skills (lookup, reference data)
  • Skills that already trigger reliably via description
  • One-off workflows the user explicitly invokes

Existing Implementations

SkillMatcherConditionScript
knowledge-architecture (reminder)Edit|Write|MultiEdit*.md files OR files inside .claude/skills//.claude/agents/ dirs (PostToolUse)~/.claude/skills/knowledge-architecture/scripts/postToolUse-reminder.py
knowledge-architecture (blocker)Edit|Write|MultiEditBLOCKS CLAUDE.MD and SKILL.MD (PreToolUse)~/.claude/skills/knowledge-architecture/scripts/preToolUse-block-knowledge-files.py
message-draftingmcp__google-workspace__gmail_send|..gmail_createDraft|..gmail_sendDraft|mcp__gmail__send_email|..draft_emailAny gmail send/draft call.claude/skills/message-drafting/scripts/preToolUse-reminder.py
email-verificationBash|mcp__google-workspace__gmail_send|..gmail_createDraft|..gmail_sendDraft|mcp__gmail__send_email|..draft_emailBash with mail.google.com/mailto: + all gmail send/draft.claude/skills/message-drafting/scripts/preToolUse-email-verification.py
gmail-send-blockermcp__google-workspace__gmail_send|mcp__google-workspace__gmail_sendDraftDENY LIST โ€” tools don't exist in current MCP but denied as insurance. Real protection: gmail-agent definition enforces mcp__gmail__send_email + from paramdeny list in ~/.claude/settings.json
db-safety (prod bypass)WriteBLOCKS writing .ts/.js with prod DB hostname + raw DB client~/.claude/skills/db-safety/scripts/preToolUse-block-prod-bypass.py
db-safety (raw SQL writes)BashPOKA-YOKE โ€” blocks psql write ops, bypass: --sql-write-confirmed~/.claude/skills/db-safety/scripts/preToolUse-block-raw-sql-writes.py

Part 16: Skill Inheritance (OOP Pattern)

Skills can inherit from a base skill, like OOP class inheritance. The child inherits all principles from the base and declares only its additions and overrides.

Pattern:

base-skill (defines shared principles)
โ”œโ”€โ”€ child-skill-A (inherits + overrides item naming)
โ”œโ”€โ”€ child-skill-B (inherits + adds domain sections)
โ””โ”€โ”€ [future children]

How to declare inheritance:

In the child skill's output format section, add:

> **Inherits:** {base-skill-name}

**Overrides:**
- {base section}: {what changes}

**Additions:**
- {new section not in base}

Rules:

  • Child MUST NOT duplicate base content โ€” reference it, don't copy it
  • If child doesn't mention a base principle, it applies as-is (implicit inheritance)
  • Overrides MUST be explicit โ€” state what you're replacing and why
  • Base skill is the SSoT โ€” if child contradicts base without declaring an override, base wins
  • When loading a child skill, Claude SHOULD also load the base to understand the full contract

Current inheritance tree:

report-format (base)
โ”œโ”€โ”€ audit-common (overrides: C1/W3/I5 IDs; adds: registry logging, drift protocol)
โ””โ”€โ”€ task-triage (overrides: adds confidence %, incident registry; adds: platform-specific sections)

Common Mistakes

MistakeFix
Flat file skills/foo.mdMove to .claude/skills/foo/SKILL.md
Missing frontmatterAdd name:, description:, and user-invocable: false
Missing user-invocable: falseAdd it โ€” skills are never user-invocable
Vague descriptionDescribe WHAT + WHEN comprehensively
Body >500 linesMove details to references/
Procedure in CLAUDE.mdExtract to skill
Multi-paragraph in CLAUDE.mdExtract to skill
Searched only local for agent/skillCheck both local .claude/ AND global ~/.claude/
Asked user "should I fix?" after skill showed clear violationJust fix it and report what was done
Created reminder hook without logging on tracking issueComment on https://github.com/<GITHUB_USER>/PersonalAssistant-ClaudeCode/issues/23 with skill name, matcher, and condition
Added hook for skill that triggers reliably alreadyOnly add hooks for skills Claude repeatedly forgets โ€” don't over-hook

Part 14: Stop Hook Self-Documentation (๐Ÿงช Experimental)

Status: Experimental. Only verified by code review, not real-world usage. Evaluate before relying on this pattern.

Problem

When Stop hooks fire for edge cases (temp scripts, non-project files), Claude often wastes user attention by explaining why the hook is irrelevant. The user already knows โ€” they don't need commentary.

Solution: Self-Explanatory Hook Messages

Stop hooks should include instructions for Claude on how to handle the feedback:

msg = (
    f"VIOLATION โ€” {details}\n\n"
    "---\n"
    "[STOP HOOK] This is a safety reminder, not a blocker. If obviously not applicable "
    "(e.g., temp scripts, non-project files, user explicitly waived), ignore silently "
    "without comment โ€” user already knows."
)
print(msg, file=sys.stderr)
sys.exit(2)

Hook Writing Guidelines for Stop Hooks

  1. Add temp path detection โ€” Exit silently (code 0) if all edited files are in temp directories:

    TEMP_PATH_PATTERNS = ("/temp/", "\\temp\\", "/tmp/", "\\tmp\\", "n:\\temp\\")
    all_files_in_temp = all(
        any(pat in fp.lower() for pat in TEMP_PATH_PATTERNS)
        for fp in edited_file_paths
    )
    if all_files_in_temp:
        sys.exit(0)
    
  2. End message with [STOP HOOK] instruction โ€” Tells Claude:

    • This is a reminder, not a blocker
    • When to ignore silently (temp scripts, non-project, user waived)
    • Don't comment when ignoring โ€” user already knows
  3. Fire-once guard โ€” Prevent infinite loops if Claude's response triggers another stop:

    marker_file = os.path.join(tempfile.gettempdir(), f"hook-fired-{session_hash}")
    if os.path.exists(marker_file):
        sys.exit(0)
    

When Claude Receives Stop Hook Feedback

Claude MUST follow the [STOP HOOK] instruction at the end:

  • If applicable: Address the feedback, follow the SOP
  • If not applicable: Ignore silently, no comment, continue with task

Anti-pattern: Saying "Hook feedback irrelevant because..." โ€” this wastes user attention. Just ignore and continue.

Part 15: Post-Action Verification ("Trust but Verify")

Principle: MCP/API success response โ‰  actual success. Side-effect operations MUST include independent verification.

The Problem

MCP tools and APIs return success in cases where the action silently failed:

  • Gmail says "sent" but email stuck in drafts or had wrong recipient
  • Sheets says "updated" but wrong cell modified or value coerced (number โ†’ string)
  • Slack API returns 200 but reaction not applied (wrong channel, missing permissions)
  • Deployment exits 0 but process crashed on startup
  • Database write succeeds but constraint silently truncated data

Subagents are especially vulnerable โ€” they report "done" to the parent based on tool response alone, with no way to retroactively verify.

Rule

Every agent spec and skill that performs side-effect operations MUST include a verification step after each critical action. The verification must use an independent read/query โ€” not the write response.

Verification Patterns

OperationVerificationExample
Send emailRead sent folder, confirm recipient + subjectsearch_emails("in:sent subject:X to:Y newer_than:1m")
Modify spreadsheetRead back modified cells, compare valuesget_sheet_data(range) after update_cells
Slack messageFetch channel history, confirm message existsconversations.history after chat.postMessage
Slack reactionFetch message reactions, confirm emoji presentreactions.get after reactions.add
File writeRead file back, verify content/sizeRead after Write for critical files
API mutationFollow-up GET to confirm state changeGET /resource/:id after PUT /resource/:id
Database writeSELECT to verify row exists with expected valuesQuery after INSERT/UPDATE
DeploymentHealth check endpoint or process listcurl /health or docker ps after deploy
Git pushVerify remote ref matches localgit ls-remote after git push

Where to Encode Verification Steps

LocationHow
Agent specs (agents/*.md)Section: "Post-Action Verification" listing verify-after patterns per operation type the agent performs
Skills (skills/*/SKILL.md)Inline after each side-effect step: "Verify: [what to check]"
CLAUDE.md delegation rulesWhen mandating delegation ("always use X agent"), note: "Agent verifies actions per knowledge-architecture Part 15"

Writing Verification Steps

Good verification: Independent observation that confirms the intended outcome.

Step 3: Send the email via mcp__gmail__send_email
Step 4: VERIFY โ€” Search sent folder for subject "X" to "Y" within last 2 minutes.
         If not found: retry send. If found but wrong content: flag to user.

Bad verification: Trusting the tool response.

Step 3: Send the email via mcp__gmail__send_email
Step 4: If no error returned, report success.  โ† WRONG: silent failures return no error

Scope โ€” What Needs Verification

Not every operation needs it. Apply to side effects that are hard to undo or whose failure has consequences:

Needs VerificationDoesn't Need
Sending emails/messagesReading files
Modifying shared data (sheets, DB)Searching/querying
Deploying codeLocal file edits (editor shows result)
Applying permissions/settingsListing/enumerating
Financial/billing operationsFormatting/transforming data
Slack reactions used as state trackingInformational API calls

Anti-Patterns

Anti-PatternWhy It Fails
"MCP returned success, reporting done"MCP success = HTTP 200, not business logic success
"No error thrown, must have worked"Many APIs return 200 with error in body or silently no-op
"Verified by checking the tool response fields"Response is the CLAIM, not independent evidence
"Will verify in the next step anyway"Next step may depend on this step and cascade-fail silently
Skills Info
Original Name:knowledge-architectureAuthor:artymclabin