name: Dev10x:diag-friction
description: >
Diagnose permission friction. Guide the agent toward pre-approved
commands, simplify complex command chains, and (when no safe local
rule fits) file an upstream issue to improve the permission
friction hooks. Replaces the former Dev10x:skill-reinforcement
skill — reinforcement of skill usage is still part of the job,
but the broader goal is reducing the friction supervisors see.
Reads conversation context to identify the offending command,
matches it against a command-to-skill map, audits local + global
settings for simpler pre-approved forms, and outputs a firm
reinforcement message pointing to the correct skill or pre-approved
command.
TRIGGER when: user sees agent using CLI instead of a skill, user
rejects a command that should have been a skill, supervisor is
bothered by repeated permission prompts, or user says "use the
skills" / "diag friction" / "skill reinforcement".
DO NOT TRIGGER when: agent is already using skills correctly,
or the CLI command has no skill equivalent and no friction is
observed.
user-invocable: true
invocation-name: Dev10x:diag-friction
allowed-tools:
- AskUserQuestion
- Read(/.claude/SKILLS.md)
- Read(/.claude/settings.json)
- Read(~/.claude/settings.local.json)
- Read(.claude/settings.json)
- Read(.claude/settings.local.json)
- Read(${CLAUDE_PLUGIN_ROOT}/skills/diag-friction/references/*)
- Read(${CLAUDE_PLUGIN_ROOT}/src/dev10x/validators/command-skill-map.yaml)
Dev10x:diag-friction
Diagnose and reduce permission friction. Guides the agent toward pre-approved commands, simplifies command chains that defeat allow-rule matching, and points to upstream issue filing when the friction is structural (the hook itself needs updating).
Formerly
Dev10x:skill-reinforcement. The skill-reinforcement behavior (firm nudge toward the right Dev10x skill or MCP tool) is still core to this skill — it is one slice of the broader job of diagnosing why the supervisor saw a permission prompt in the first place. If you're looking for the oldskill-reinforcementinvocation, you're in the right place.
When to Use
Invoke this skill when:
- The agent ran a CLI command that a skill already handles
- You rejected a command and want the agent to use a skill instead
- You approved a command but want to reinforce the skill habit
- You want to say "use the skills" with a structured response
Orchestration
REQUIRED: Create a task at invocation. Execute at startup:
TaskCreate(subject="Reinforce skill usage", activeForm="Reinforcing")
Mark completed when done: TaskUpdate(taskId, status="completed")
Instructions
Step 1: Identify the offending command
Scan the recent conversation for the CLI command that triggered this invocation. Look for:
- The most recent
Bashtool call that was rejected or approved - Any command the user flagged as wrong
- If the user provided arguments (e.g.,
/Dev10x:diag-friction kubectl), use that as the command identifier
Store the command string for matching.
Step 2: Match against command-skill map
REQUIRED — Read the canonical map first (GH-181 F9). Do
NOT inline knowledge from the parent skill's SKILL.md or
recall mappings from training. The hook's YAML is authoritative
and ships updates ahead of skill docs; skipping the Read is a
documented Step 2 violation.
Read(file_path="${CLAUDE_PLUGIN_ROOT}/src/dev10x/validators/command-skill-map.yaml")
The YAML in skills/diag-friction/references/command-skill-map.yaml
is a legacy copy — prefer the hook's YAML which is the single
source of truth.
Match the identified command against the patterns list in each
mapping entry. Use prefix matching — if the command starts with
any pattern in the list, it matches that entry.
If no match is found in the map, fall back to Step 3.
Step 2b: Check workflow context
If a pattern match is found but the command appears to be a valid part of the currently active skill's documented workflow, check whether the skill says to delegate for this case:
- Read the active skill's SKILL.md (if identifiable from context)
- Check if the command matches a delegation point marked with
REQUIRED: Skill()— a command can be valid syntax within a skill but still a violation if the skill mandates delegation to a sub-skill for that operation - Example:
gh api --method POST .../repliesis documented ingh-pr-respondbut the skill requires VALID comments to go throughDev10x:gh-pr-fixup— using the raw API is a violation
If the command is a delegation bypass, treat it as a match and output the reinforcement pointing to the correct sub-skill.
Step 3: Fall back to SKILLS.md
If no direct mapping exists, read ~/.claude/SKILLS.md and scan
skill descriptions from the system-reminder context to find the
best match based on the command's purpose.
Step 3b: Permission friction audit
Audit project + user settings for a simpler, pre-approved alternative to the offending command. Most rejections happen because chaining shifts the effective prefix away from any allow-rule.
See references/audit-procedure.md
for sources, allow-rule shapes, and the four-step audit procedure.
The audit output feeds Step 4 — surface findings even when a
skill match was also found.
Step 3c-pre: Inline-code structured-alternatives (GH-282)
When the offending command starts with an inline-code prefix
(python -c, python3 -c, sh -c, bash -c, perl -e,
ruby -e, node -e, deno eval), the right recommendation is
almost never "extract to ~/.claude/tools/" — it's the canonical
structured tool that already exists for the use case (jq, yq,
yamllint, actionlint, curl, etc.).
Procedure:
Read(file_path="${CLAUDE_PLUGIN_ROOT}/skills/diag-friction/references/structured-alternatives.yaml")- Check the offending command against
inline_code_prefixes. If no prefix matches, skip this step and proceed to Step 3c. - Extract the inline code body (text between the quotes after the
-c/-eflag). - Match the body against each entry's
detection_keywords(substring match; first hit wins). - Surface the matched
toolandexampleas the primary recommendation in the "Use instead" section of Step 4. - Fall back to the "Multi-step logic (fallback)" entry only when no keyword matches across all other entries.
Example match for python -c "import yaml; yaml.safe_load(...)":
the yaml.safe_load keyword hits the YAML-parsing entry, so the
reinforcement names yq as the canonical alternative — not a
tools-directory extraction.
Step 3c: Detect structural friction (file upstream)
When the hook itself is too aggressive, the command-skill map is missing an entry, or no safe targeted allow-rule fits, point the user at the upstream issue tracker so the hooks can be improved for everyone — not patched locally over and over.
See references/upstream-friction.md
for the signals that suggest structural friction and the
"Upstream issue" section template (problem statement, suggested
resolution, pre-filled gh issue create invocation). Do NOT
auto-file — the user approves first.
Step 3d: Generalize the suggested rule shape (GH-597)
When the audit (Step 3b) or upstream path (Step 3c) lands on
proposing a targeted allow-rule, do not echo the harness's
suggested shape — it is wrong in one of three directions. Surface
the generalized shape produced by
dev10x.skills.permission.generalize.generalize_rule_shape:
| Failure mode | Harness suggests | Generalized shape |
|---|---|---|
| over-broad (verb-blind) | Bash(ip route *) |
Bash(ip route get:*) |
| over-narrow (session arg) | Bash(persist.sh <id> *) |
Bash(persist.sh:*) |
| too-literal (no wildcard) | Bash(yarn build:x) |
Bash(yarn build:*) |
Apply the generalized rule in the "Pre-approved alternatives" /
"Upstream issue" sections so the rule the user accepts is reusable
and safe — never the dead-on-arrival or over-granting default.
Only Bash command rules are generalized; mcp__*, WebFetch(...),
and Read(...) rules pass through unchanged.
Step 3e: Background-dispatch pre-seed over auto-mode (GH-610)
When the friction arose inside a background subagent (workflow /
monitor / loop / fanout child) — or the only "fix" on offer is the
harness's "switch to auto mode" / disable-prompts nudge (the GH-310
footgun) — do NOT recommend blanket bypassPermissions. The correct
remedy is to fix the dispatcher, not to silence prompts:
- Prepend the canonical friction-avoidance preamble to the subagent
prompt (fetch via
mcp__plugin_Dev10x_cli__background_preamble). - Pre-seed the subagent's
allowed_toolswith the wrappers it needs (Read,Grep,Glob,mktmp,push_safe,create_pr, …) so the preferred tool surface is actually available.
Surface this as the primary recommendation whenever the offending
command came from a background dispatch path. See
references/orchestration/background-preamble.md and
references/orchestration/subagent-dispatch.md § Background Friction
Preamble.
Step 4: Output reinforcement message
Output a firm, concise reinforcement message with seven sections: command detected, use instead, why, how to invoke, pre-approved alternatives (from Step 3b), upstream issue (from Step 3c when friction is structural), related skills.
See references/audit-output.md
for the per-section schema, MCP invocation example, and ranking
rules when multiple skills apply.
Step 4b: Respect user rejection
If the user explicitly rejected the command (denied the Bash tool call), do NOT conclude "no violation found" and resume the rejected workflow. A user rejection overrides documentation matching — even if the command appears valid within the skill, the user's denial takes precedence. Instead, ask the user what they expected if no skill match is found.
Step 5: Reinforce the general principle
End with a brief reminder:
Always check if a skill or MCP tool exists before reaching for CLI commands. Skills provide consistent behavior, proper tool declarations, and avoid permission friction.
Prefer pre-approved commands. Keep each Bash call to one simple command — no
&&/;chaining, no env-var prefixes, no leading subshells. Packing multiple steps into one call shifts the effective prefix and breaks allow-rule matching, which is the main reason supervisors see avoidable permission prompts. When no pre-approved form fits, propose a narrow targeted allow-rule rather than crafting a more elaborate command.
Step 6: Offer follow-up action (REQUIRED when command was rejected)
If the triggering command was rejected by the user (denied the Bash tool call), the reinforcement must actively offer to retry the intended action via the recommended skill. Plain text offers ("Want me to invoke X?") do NOT block execution and break the structured decision flow used across Dev10x skills.
REQUIRED: Call AskUserQuestion (do NOT use plain text).
AskUserQuestion(questions=[{question: "Invoke <recommended-skill> now to complete the intended action?", header: "Retry", options: [{label: "Yes, invoke <skill> now (Recommended)", description: "Re-run the intended action via the correct skill"}, {label: "I'll invoke it manually later", description: "Skip for now — user will handle"}, {label: "Cancel — discard the attempted operation", description: "Do not retry"}], multiSelect: false}])
Substitute <recommended-skill> with the skill identified in
Step 2 (e.g., Dev10x:gh-pr-monitor, Dev10x:k8s,
Dev10x:git).
Skip this gate when:
- The user invoked the skill informationally (not after a rejection) and no follow-up action is implied
- No recommended skill was identified (Step 3 fallback with no clear match) — ask the user what they expected instead
- The triggering command was approved, not rejected — the intended action has already run
On approval, invoke the recommended skill immediately. On cancellation, acknowledge and stop — do NOT resume the rejected workflow.
Examples
See references/examples.md for five
walkthroughs:
- kubectl usage — direct CLI match (
Dev10x:k8s) - direct git push — bypassed safety skill (
Dev10x:git) - friction from chaining — Step 3b audit surfaces a pre-approved alternative
- no match found — fallback to SKILLS.md scan
- structural friction — no safe local rule fits, file an upstream issue