modscode / コード参考書 / Claude が呼べるツールを足す
Claude が呼べるツールを足す($.tool.register)
session.start で $.tool.register({ name, description, inputSchema }) すると、Claude は mcp__プラグイン名__name というツールを呼べるようになります。呼ばれたら tool.call をその名前で受けて { result } を返します。サーバーを立てる必要はありません。
最小の形
// a plugin named my-mod: Claude sees the tool as mcp__my-mod__word_count
export function register(on) {
on('session.start', async ($, e, next) => {
await $.tool.register({
name: 'word_count',
description: 'Count the words in a text',
inputSchema: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'] },
})
return next(e)
})
on('tool.call', { tool: 'mcp__my-mod__word_count' }, async ($, e) => {
return { result: String(e.text.trim().split(/\s+/).filter(Boolean).length) }
})
}
modscode が公式ドキュメントの API で書いた最小の例です。自由に使えます。
実際の Mod のコード(6 本)
GitHub の公開 Mod から、図鑑が読んだコミットの該当行をそのまま引いています。見出しから Mod のページ(何をするか・良いところ・画面・コードが触るもの)へ、ファイル名から GitHub の該当行へ移れます。
写す前・入れる前に、必ず自分でコードを確かめてください。Mod はサンドボックスなしで、あなたの権限で動きます。modscode は中身の安全を保証しません。
assumption-ledger Danny McAteer · ターミナル+デスクトップ · ★ 536
Gives Claude a register_assumption tool and shows the turn's assumptions, decisions and considered-but-not-done items above the prompt
on('session.start', async ($, e, next) => {
const stored = await quiet($, 'store read', $.store.get('isOff'))
await quiet($, 'state write', update($, isOff, () => stored === true))
await quiet($, 'tool register', $.tool.register({ name: 'register_assumption', description: DESCRIPTION, inputSchema: SCHEMA }))
await quiet(
$,
'command register',
$.command.register({
name: COMMAND,
description: "This session's assumptions, decisions and skipped fixes",
argumentHint: '[write [path] | off | on]',
}),
)
return next(e)
})MIT ライセンス。写すときは著作権表示を残してください。 この Mod のコードと画面
ライセンスの全文(MIT)
MIT License Copyright (c) 2026 Dan McAteer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
context-level Tobias Hagemann · フックだけ · ★ 406
Gives Claude a tool that reads how much of the context window remains.
on('session.start', async ($, e, next) => {
await $.tool.register({
name: 'read',
description: "Reads how much of this session's context window remains.",
})
return next(e)
})MIT ライセンス。写すときは著作権表示を残してください。 この Mod のコードと画面
ライセンスの全文(MIT)
MIT License Copyright (c) 2026 Tobias Hagemann Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
terminal-browser zenbu-labs · ターミナル+デスクトップ · ★ 3671
A browser running directly inside claude code. Preview websites, view HTML documents, and let your agent control the built in browser.
on('session.start', async ($, e, next) => {
const r = await next(e)
let surfaces: readonly string[] = []
try {
surfaces = await $.session.surfaces()
} catch {}
if (!surfaces.includes('terminal')) return r
await $.command.register({
name: 'browser',
description: 'Open a browser to the right',
argumentHint: '[url]',
immediate: true,
}).catch(err => $.ui.log(`terminal-browser: /browser not registered: ${err}`))
if (agentToolEnabled) {
await $.tool.register({
name: 'open',
description: 'Open terminal-browser directly inside claude code. Control the open page with the terminal-browser action CLI.',
inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'The page to open, as a full url or a host name' } } },
}).catch(err => $.ui.log(`terminal-browser: open tool not registered: ${err}`))
await $.tool.register({ name: 'close', description: 'Close the terminal-browser pane.' }).catch(err => $.ui.log(`terminal-browser: close tool not registered: ${err}`))
}
return r
})MIT ライセンス。写すときは著作権表示を残してください。 この Mod のコードと画面
ライセンスの全文(MIT)
Copyright 2026 Zenbu Labs, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
clodfarm clodfarm · フックだけ · ★ 147
The farm's messaging inside Claude Code: wakes an idle conversation for its mail, gates and logs SendMessage, and gives the model a msg tool
on('session.start', async ($, e, next) => {
const task = await $.env.get('FARM_TASK_ID')
my.flag = task === 'usage' ? undefined : await $.env.get('FARM_MAIL_FLAG')
if (!my.flag) return next(e)
await $.env.set('FARM_MOD_LIVE', '1')
await $.tool.register({
name: MSG,
description:
'Send a message to another Claude on this farm (by its name) or to a sub-agent (by its id), the same as ' +
'`clodfarm msg`. A Claude\'s conversations get it at their next tool call or prompt, and one active in the ' +
'last 10 minutes is woken for it; a running sub-agent gets it at its next tool call. `urgent` interrupts a ' +
'running sub-agent now; `wake` starts someone to handle it if nobody has read it in a while.',
inputSchema: {
type: 'object',
properties: {
to: { type: 'string', description: 'A Claude\'s name, or a sub-agent\'s id' },
text: { type: 'string', description: 'The message' },
urgent: { type: 'boolean', description: 'Interrupt that running sub-agent with it now' },
wake: { type: 'boolean', description: 'If nobody reads it in time, start someone to handle it' },
},
required: ['to', 'text'],
},
})
if (!task) $.clock.every(POLL_MS, () => void wake($)) // a conversation: a sub-agent's run ends with its turn
return next(e)
})MIT ライセンス。写すときは著作権表示を残してください。 この Mod のコードと画面
ライセンスの全文(MIT)
MIT License Copyright (c) 2026 Duke Security, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
kindex-modern Wander · ターミナル+デスクトップ · ★ 34
Repo-local Kindex memory and durable tasks for Claude function hooks (Claude Code mod, 2.1.287+)
on("session.start", async ($, e, next) => {
// The registration can outlive a host session. Retire its window and fence
// callbacks still awaiting an inner hook or an RPC from that session.
activeState.current = false;
const state = newSession();
activeState = state;
try {
const [project_path, session_id] = await Promise.all([$.session.cwd(), $.session.id()]);
if (!state.current) return next(e);
state.scope = {project_path, session_id, agent: "claude"};
// Registering is idempotent on reload. Host assigns the actual full names.
const task = await $.tool.register({name: "task", description: "Kindex durable repo task service: tasks live in this worktree's .kin/local store and survive compaction and new sessions (the native Task/TodoWrite tools route here too). " +
"get and list read (list takes status, limit, cursor). create, update, complete, cancel, claim, release and reconcile write and need args.operation_id: resending an ID with the same arguments returns the committed result (replayed: true) instead of applying it twice, and reusing it with different arguments is refused. " +
"Pass expected_version on update/complete/cancel/claim/release to refuse the write if the task changed; another session's live claim refuses the write unless force is true. " +
"reconcile syncs this session's list of items (keyed by external_id) into a namespace, default \"todos\"; cancel_missing cancels open items absent from the list.",
inputSchema: {type: "object", properties: {operation: {type: "string", enum: ["create", "get", "list", "update", "complete", "cancel", "claim", "release", "reconcile"]}, args: taskArguments}, required: ["operation", "args"], additionalProperties: false}});
if (!state.current) return next(e);
state.taskTool = task.tool;
const memory = await $.tool.register({name: "memory", description: "Search this repository's Kindex memory or capture evidence for later review. " +
"action=search: full-text search on up to 16 words (3+ characters) taken from text; returns up to 5 matching non-task nodes (id, title, first 500 characters) plus up to 10 open durable tasks, as evidence rather than instructions. Personal memory is not searched. " +
"action=capture: stores text (at least 20 characters; truncated near 3,900) as a quarantined capture candidate and returns its candidate_id. Nothing becomes durable knowledge, a directive or a permission until someone reviews and accepts it.",
inputSchema: {type: "object", properties: {action: {type: "string", enum: ["search", "capture"]}, text: {type: "string", maxLength: 16000}}, required: ["action", "text"], additionalProperties: false}});
if (!state.current) return next(e);
state.memoryTool = memory.tool;
const description = await rpc($, state, {action: "describe"});
if (!description.ok || !["kindex", "signet-eval"].includes(description.policy_owner ?? "")) throw new Error("Unavailable");
state.expectedOwner = description.policy_owner;
state.qualified = true;
$.ui.status(`Kindex .kin/ · policy: ${state.expectedOwner} · host redaction not guaranteed`);
} catch { if (state.current) degraded($); }
return next(e);
});MIT ライセンス。写すときは著作権表示を残してください。 この Mod のコードと画面
ライセンスの全文(MIT)
MIT License Copyright (c) 2026 Wander Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
crit-tui Tomasz Tomczyk · ターミナル+デスクトップ · ★ 1178
Early: crit inside Claude Code. Comment on the conversation, your diff or a file in a pane, send the review to Claude, and read Claude's replies in threads.
await $.tool.register({
name: 'reply',
description:
'Reply to a crit review comment the user left (on the conversation, the diff or a file). Pass the comment id from the review and a short reply. The user resolves threads, not you.',
inputSchema: {
type: 'object',
properties: {
id: { type: 'string', description: 'The comment id, as given in the review.' },
body: { type: 'string', description: 'Your reply.' },
},
required: ['id', 'body'],
},
})
MIT ライセンス。写すときは著作権表示を残してください。 この Mod のコードと画面
ライセンスの全文(MIT)
MIT License Copyright (c) 2026 Tomasz Tomczyk Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
作り始める
フォルダーに .claude-plugin/plugin.json({"name": "my-mod"})と hooks/hooks.json({"modules": ["register.js"]})を置き、上のコードを hooks/register.js に保存して、claude --plugin-dir . で 1 セッションだけ読み込みます。claude plugin validate . で、フックするイベントと呼ぶ API の一覧が出ます。