josippapez/ai-setup/tree/main/claude/plugins/dev-core
この mod について
dev-core
Claude Code の日常デフォルトです。リポジトリの根拠、常時有効のルール、コアスキル、専門 agent をまとめた、OpenCode `interactive-mcp⟧ の Claude 互換ミラーです。
リポジトリ情報は別の repo-docs⟧ プラグインが担当します。find_docs⟧、list_docs⟧、read_doc⟧、find_libs⟧、get_blast_radius⟧、get_file_dependents⟧ は claude/plugins/repo-docs⟧ にあり、orchestrate⟧ と MCP server と mcp__plugin_repo-docs_repo-docs__*⟧ を共有します。claude/install.sh⟧ が自動で導入し、呼び出せないときは claude plugin install repo-docs@ai-setup⟧ を実行します。.mcp.json⟧ には interactive⟧(@rawwee/interactive-mcp⟧、--disable-tools message_complete_notification,intensive_chat⟧、request_user_input⟧)、context7⟧、chrome-devtools⟧、computer-use⟧ が登録されます。プロジェクト固有の server は `~/.claude.json⟧ に置きます。
WCAG は MCP ではなく @rawwee/wcag-cli⟧ CLI で調べ、Bash と accessibility⟧ skill を使います。常時登録された MCP は毎セッション subprocess を起動するため、状態を持つ repo-docs⟧ や chrome-devtools⟧ のような場合だけ使います。`skills/⟧ は OpenCode skills のミラーです。
ルールは三層です。常時有効のカーネルは rules/⟧(evidence-first⟧、external-facts⟧、proactive-execution⟧)にあり、hooks/link-rules.cjs⟧ が SessionStart⟧ で rules/*.md⟧ を更新し、~/.claude/rules/dev-core⟧ から ${CLAUDE_PLUGIN_DATA}/rules/⟧ を参照させます。main agent と subagent は /context⟧ の Memory files で読み、コンパクション後も再ロードします。
公開リンクを作ったセッションにはネイティブコピーがないため、SessionStart⟧ と SubagentStart⟧ で分割注入します。上限は 10,000 文字で、first-session⟧ と session_id⟧ がキーです。claude plugin disable⟧ 後も ~/.claude/rules/⟧ から ~/.claude/plugins/data/*/rules⟧ へのリンクを調べ、claude plugin list --json⟧ が 0.3 s で無効または一覧外としたものを削除します。rules-index⟧ が同一バイトのコピーを保ち、ユーザーの実ディレクトリは残します。hooks.json⟧ はイベントごとに 3 スロット(使用 2)を登録し、`hooks/inject-rules.cjs⟧ を置き換えます。
第二層は rules-digest.md⟧。hooks/inject-rules-digest.cjs⟧ が UserPromptSubmit⟧ ごとに約 250-token の要約を出します。カーネルは約 2.5k token なので毎回の再送を避け、完全なルールを参照します。concise-output⟧ も同じ仕組みを持つため `[rules-reminder]⟧ は 2 つ表示されます。
第三層は rule-cards/⟧ です。hooks/rule-cards.ts⟧ がツール結果へカードを添付し、rule-cards/triggers.json⟧ と rule-cards/triggers.test.cjs⟧ がトリガーを確認します。PreToolUse⟧ の代わりに、カードごとに Node を起動するコスト(0.05~0.06 s、git mv⟧ ガード付き Bash では 5 枚)を避けます。カーネルは turn 0、カードはアクションの隣に届きます。
| カード | 発火 | スキップ |
| --- | --- | --- |
| writing-code⟧ | Edit⟧、Write⟧、NotebookEdit⟧、Bash の sed -i⟧、tee⟧、リダイレクト | — |
| reading-libraries⟧ | node_modules/⟧ を触るツールまたは Bash | -not -path⟧、--exclude-dir⟧、-g '!node_modules'⟧、-prune⟧ の除外だけ |
| git-commit⟧ | Bash の git commit⟧ | — |
パスを名前にしただけでは作業とはみなしません。find . -type f -not -path "./node_modules/*"⟧ は監査で opensrc を発火し、skip⟧ が抑制します。5 プロンプトの fixture 測定では 39 呼び出し中、Edit⟧、Write⟧、Read⟧、Grep⟧、Glob⟧ はゼロでした。Bash パターンを足すと 4 枚が発火します。カードは agent ごとに 2 分でデバウンスされ、8 回の注入は 4 種類、14,240 文字でした。requires: <path>⟧ と `/reload-plugins⟧ も使えます。コストは 30.5 KB(7.6k token)から 9.9 KB(2.5k token)、カード全体は 6.9 KB です。
git mv⟧ は強制です。hooks/mv-guard.ts⟧ は Bash の tool.call⟧ hook で、引用符なしの &&⟧、||⟧、;⟧、|⟧ と改行で区切った各区間を検査します。追跡済み source の通常の mv⟧ を拒否し、glob、複数 source、未追跡、無視、temp、非 git ディレクトリは通します。最初のコマンドは mv src/utils.js src/helpers.js && sed -i '' ... && echo ...⟧、修正後は git mv⟧ で R100 src/utils.js -> src/helpers.js⟧ になりました。git add -A⟧ の rename 検出に頼らず決定的です。
テスト
node --test claude/plugins/dev-core/hooks/*.test.cjs
Mod
hooks/screenshots.tsx⟧ は chrome-devtools の take_screenshot⟧ をターミナル記録の画像として描画します(PNG のみ)。JPEG/WebP と他のサーフェスはデフォルトの行です。
インストール
まず作者の README で marketplace とプラグイン名を確認してください。コマンドはリポジトリの構成によって変わる場合があります。
claude plugin marketplace add josippapez/ai-setup claude plugin install dev-core
原文 / README
dev-core
Everyday defaults for Claude Code: repo grounding, the always-on engineering rules, core skills, and the specialist agents. Claude-compatible mirror of the OpenCode interactive-mcp custom plugin, which keeps the older name.
-
Repo grounding comes from the separate
repo-docsplugin, not from this one.find_docs/list_docs/read_doc/find_libs/get_blast_radius/get_file_dependentslive inclaude/plugins/repo-docs, shared withorchestrateso both use one MCP server and one tool namespace (mcp__plugin_repo-docs_repo-docs__*) instead of each bundling an identical copy.claude/install.shinstallsrepo-docsautomatically alongside this plugin; if its tools are not callable, tell the user to runclaude plugin install repo-docs@ai-setup. Seeclaude/plugins/repo-docs/README.md. -
.mcp.jsonregistersinteractive(@rawwee/interactive-mcp, a question tool subagents can reach since Claude Code withholdsAskUserQuestionfrom them;--disable-tools message_complete_notification,intensive_chatleaves onlyrequest_user_input, since the main agent is told to useAskUserQuestionand nothing here uses intensive chat, so the other tools were roster weight nobody could call), plus bundled third-party MCP servers that should be available by default in every project:context7(@upstash/context7-mcp),chrome-devtools(chrome-devtools-mcp) andcomputer-use(computer-use-mcp, mouse/keyboard/screenshot control of the real desktop for anything with no API and no DOM behind it: native app UI, OS dialogs, browser chrome outside the page, and seeing what actually rendered; it also rescues achrome-devtoolscall stuck on the native remote-debugging dialog, which no timeout cuts short). Documented by thecomputer-useskill. These ship enabled with the plugin so they need no per-machine MCP config. Project- or secret-specific servers (e.g. Figma, a local Storybook endpoint) are intentionally kept out of the plugin and live at user scope in~/.claude.json. -
WCAG lookups are a CLI, not an MCP. Accessibility criteria/techniques/failures come from
@rawwee/wcag-cli, invoked over Bash and documented by the bundledaccessibilityskill. A skill + on-demand CLI costs nothing until used, whereas an always-registered MCP spawns a subprocess every session — the same pattern asopensrcandrtk. Prefer this shape for any stateless reference lookup; keep an MCP only where the server holds real state (a warm index, a browser session), asrepo-docsandchrome-devtoolsdo. -
skills/mirrors the OpenCode skills. -
Rules come in three layers: an always-on kernel, a per-prompt digest, and tool-triggered cards. Claude Code has no native plugin "rules" loader and nothing a plugin ships reaches the system prompt except an output style, so a hook publishes the kernel as user-scope rules and the other two layers arrive as hook-injected
additionalContext.rules/is the kernel:evidence-first,external-facts,proactive-execution. Only what applies to every turn regardless of which tool runs.hooks/link-rules.cjsruns onSessionStart, refreshes everyrules/*.mdin the plugin's data dir file by file through a rename (emptying the directory first made a concurrently starting session report every rule missing) (${CLAUDE_PLUGIN_DATA}/rules/) and points~/.claude/rules/dev-coreat the copy. From the next launch Claude Code loads them natively: into the main agent and every subagent (measured with a no-tools probe subagent), listed under Memory files in/context, reloaded after compaction. The data dir is the one path Claude Code deletes on uninstall, so the rules leave with the plugin; the dangling link is skipped silently (measured).Two gaps, both measured, both closed by the same script. Rules load before
SessionStarthooks run, so the session that publishes the link has no native copy and neither do its subagents (measured: a subagent spawned after the link appeared still reported nothing): in that one session the script emits the rules asadditionalContexton bothSessionStartandSubagentStart, sharded under the 10,000-character cap, keyed on afirst-sessionmarker in the data dir that holds the publishingsession_id. Andclaude plugin disableruns nothing of the disabled plugin, so the script also sweeps~/.claude/rules/for links into~/.claude/plugins/data/*/ruleswhose pluginclaude plugin list --json(0.3 s) reports disabled or no longer lists, and removes them;rules-indexcarries a byte-identical copy so the sweep still runs when dev-core itself is the one disabled. If the user has their own real directory at~/.claude/rules/dev-core, it is left alone and the rules keep arriving as context every session.hooks.jsonregisters 3 shard slots per event (2 in use). This replacedhooks/inject-rules.cjs, which emitted the kernel as sharded context on every session and every subagent spawn.rules-digest.mdis the second layer: a ~250-token restatement of the kernel, emitted on everyUserPromptSubmitbyhooks/inject-rules-digest.cjs. The kernel is ~2.5k tokens and sits in the launch context, so repeating it every prompt is unaffordable and leaving it alone lets its pull fade. The digest carries no rule text of its own; it points at the copy already in context and says the full rules govern where the two differ.concise-outputships the identical script against its own digest, which is why a session shows two[rules-reminder]blocks.rule-cards/is the third layer: guidance that only matters next to a specific tool, delivered by the mod inhooks/rule-cards.ts, which attaches the card to the tool call's result. Its triggers (tools, afireregex, askipregex) live inrule-cards/triggers.json, checked byrule-cards/triggers.test.cjs. It replaced aPreToolUsecommand hook that started a Node process per card on every matching call (0.05 to 0.06 s each, five per Bash call with thegit mvguard). The kernel lands at turn 0 and is far from the work by turn 40; a card arrives adjacent to the action instead.| Card | Fires on | Skips when | | --- | --- | --- | |
writing-code— simplicity, surgical scope, root cause, what a reviewer checks |Edit/Write/NotebookEdit, or a Bashsed -i,tee, or redirect into a file | — | |reading-libraries—opensrcover assumption | any tool call or Bash command touching anode_modules/path | the path appears only in an exclusion (-not -path,--exclude-dir,-g '!node_modules',-prune) | |git-commit— what has to be true before it lands | a Bashgit commit| — |Naming a path is not working on it. The skip column came from this plugin's own audit, where
find . -type f -not -path "./node_modules/*"fired the opensrc card. The trigger'sskipregex suppresses it; a false skip costs nothing, a false fire costs context every two minutes, so the skip pattern wins over the fire pattern.Every card has a Bash trigger as well as a tool-name one, and that is not optional. Benchmarked 2026-09-14 over five prompts in a fixture repo: across 39 tool calls the model made zero
Edit,Write,Read,Grep, andGlobcalls. Every file read, write, search, and move went through Bash (cat -n,cat >> f <<EOF,sed -i,grep -rn,find,mv). With tool-name matchers alone exactly one card fired; with the Bash patterns added, all four fired in the same run.Each card is debounced: it reappears at most once every two minutes, per card, per agent. Injected context does not leave the conversation, it only moves further back, so re-injecting on every user prompt just piles up duplicate copies. Measured over the five-prompt bench run under the original per-prompt keying: 8 injections carrying only 4 distinct bodies, 14,240 characters, half of it a repeat of text already in context. A card may declare
requires: <path>to skip itself unless that path exists under the session cwd. The debounce is kept in the mod's memory, so/reload-pluginsre-arms every card.Cost: the always-on bundle went from 30.5 KB (~7.6k tokens) to 9.9 KB (~2.5k tokens), loaded natively at launch for the main agent and each subagent. The cards total 6.9 KB, and only the one matching the tool is ever sent.
-
git mvis enforced, not suggested.hooks/mv-guard.tsis a modtool.callhook on Bash that denies a plainmvwhose source is tracked by git, and names thegit mvto run instead. Guidance alone did not hold: the rule is read at session start and forgotten at the moment it matters, and a plainmvplusgit addrecords the move as a delete and an add. It splits the command on unquoted&&,||,;,|, and newlines and checks every segment, because the whole-command version never fired once: asked to rename a tracked file, the model wrotemv src/utils.js src/helpers.js && sed -i '' ... && echo ...on the first try. Within a segment it denies only a two-argumentmv, optional short flags, source tracked in the git work tree at the session cwd. Globs, multi-source moves, untracked or ignored sources, temp paths, and non-git directories all run untouched, because a false deny costs the user a blocked command.Verified live: the model hit the deny, read the reason, and re-ran with
git mv, landing the change asR100 src/utils.js -> src/helpers.js. Worth knowing thatgit add -Aplus git's own rename detection often recovers a plainmvanyway — in the control arm it did. The guard makes the rename deterministic rather than dependent on similarity detection.
Tests
node --test claude/plugins/dev-core/hooks/*.test.cjs
Mod
hooks/screenshots.tsx draws a chrome-devtools take_screenshot result as the picture itself in the terminal transcript (PNG only, inline or saved to a file). JPEG/WebP results and other surfaces keep the default row.
