TODO: one line

Personal Claude Code mods (function-hook plugins).
Start work on a GitHub issue without leaving the prompt. Needs the gh CLI, logged in, and a session started inside the repo.
/issue 33 fetches issue #33 and puts a prompt in the input box: Work on GitHub issue #33: <title>. Commit with "Closes #33" in the message. Press Enter to send it, or edit it first.gh issue view itself. This only happens when the next prompt you send still mentions #33 (not #330 or other/repo#33); otherwise the issue is dropped. Messages from peer sessions, schedules or other plugins don't count as your next prompt./issue with no number opens a pane listing up to 50 open issues. Press 1–9 or select an issue to load it the same way. Refresh (r) reloads the list, and Close closes the pane./push pushes the current branch to its upstream, the same as git push.
Each mod lives in mods/<name>/, laid out like template/: a working mod named mod-template that bin/mods new copies and renames, and that bin/mods check checks along with the mods, so it can't fall out of date. Change the layout there, not here.
A mod that keeps $.state adds its contract as types/index.d.ts and points "types" in .claude-plugin/plugin.json at it, as mods/issue does.
bin/mods install # all mods
bin/mods install issue # just one (added to what's already installed)
bin/mods uninstall push
bin/mods list
Install doesn't copy anything. It points CLAUDE_CODE_PLUGIN_DIRS in ~/.claude/settings.json at the folders in this repo (keeping any unrelated entries, and backing the file up to settings.json.mods-bak). So:
git pull. Interactive sessions watch these folders and hot-reload a mod when its files are saved.bin/mods keeps it and warns about it, and list shows it as missing, until you run bin/mods uninstall <old-name>.The words used here (installed set, repo entry, foreign entry, dead entry) are defined in CONTEXT.md. tests/bin-mods.sh tests this against a throwaway settings file. The pre-commit hook runs it when bin/ or tests/ changes.
bin/mods new <name> "description" to scaffold from template/. Its one test checks the template's placeholder behaviour, so it fails once you replace that behaviour.plugin-authoring skill first: it has the API types and examples.bin/mods check <name> runs claude plugin validate, tsc and claude plugin test. tsc is skipped until the engine has loaded the mod once, because that load writes .claude-plugin/types/ (gitignored).bin/mods try <name> starts a one-off claude --plugin-dir session with only that mod, without installing it.claude --debug gives more)..githooks/, enabled with git config core.hooksPath .githooks) runs bin/mods check on every mod the commit touches, and on the template when it changes.Because installed mods load straight from the working tree, a half-finished edit reaches your real sessions as soon as you save it. For risky changes, use a branch plus bin/mods try, or a worktree.
hooks/register.tsx 9 lines1import type { Register } from 'claude-code'
2
3export const register: Register = (on) => {
4 on('session.start', async ($, e, next) => {
5 $.ui.status('mod-template loaded')
6 return next(e)
7 })
8}
9