Type ;review, ;tests, ;plan and friends in a prompt and they expand to full instructions. Add your own via the extraSnippets option. /snippets lists them.

Type ;review or ;tests and it expands into a full instruction.
Short ;name shortcuts in a prompt expand to reusable instructions before Claude sees them. Ships with ;review ;tests ;plan ;explain ;short ;fix, and you can add your own.
/plugin marketplace add cloudcruncher/claude-mod-garage
/plugin install prompt-snippets@mod-garage
Run /reload-plugins (or restart Claude Code) afterwards. To try it from a local clone without installing: claude --plugin-dir ./dev-mods/prompt-snippets
;name anywhere at the start of a word in a prompt./snippets lists everything available.extraSnippets option (a JSON object).Illustrative output.
You type
refactor the parser ;plan ;short
Claude receives
refactor the parser Before editing anything, outline a short plan: the goal, the files you will touch and how you will verify it. Then proceed. Keep the answer under 5 lines. Results first, no preamble.
/snippets
;review Review the current changes for correctness bugs, security issues and missed…
;tests Write focused tests for the behaviour above, run them, and report the result…
;plan Before editing anything, outline a short plan: the goal, the files you will touc…
| Option | Default | What it does |
|---|---|---|
extraSnippets | (empty) | JSON object of name -> text, e.g. {"ship":"Run the checks, then commit and push."} |
Set options when installing, or later in /plugin → the mod → configure.
;foo are left untouched.hooks/register.ts 21 lines1import type { Register } from 'claude-code'
2import { DEFAULTS, expand, parseExtra } from './lib'
3
4export const register: Register = (on, options) => {
5 const snippets = { ...DEFAULTS, ...parseExtra(options?.extraSnippets) }
6
7 on('session.start', async ($, e, next) => {
8 await $.command.register({ name: 'snippets', description: 'List the ;snippet shortcuts you can type in a prompt' })
9 return next(e)
10 })
11
12 on('command.run', { command: 'snippets' }, () => ({
13 text: Object.entries(snippets).map(([k, v]) => `;${k} ${v.length > 70 ? v.slice(0, 69) + '…' : v}`).join('\n'),
14 }))
15
16 on('prompt.submit', (_$, e, next) => {
17 const text = expand(String(e.text ?? ''), snippets)
18 return next(text === e.text ? e : { ...e, text })
19 }).catch(($, e, next) => next(e))
20}
21hooks/lib.ts 26 lines1export const DEFAULTS: Record<string, string> = {
2 review: 'Review the current changes for correctness bugs, security issues and missed edge cases. Report findings most severe first, each with file and line.',
3 tests: 'Write focused tests for the behaviour above, run them, and report the result honestly. Do not change production code unless a test exposes a real bug.',
4 plan: 'Before editing anything, outline a short plan: the goal, the files you will touch and how you will verify it. Then proceed.',
5 explain: 'Explain this simply: what it does, why it is built this way, and one thing that could trip me up.',
6 short: 'Keep the answer under 5 lines. Results first, no preamble.',
7 fix: 'Find the root cause before changing anything. Show the evidence, make the smallest fix, and verify it with a command.',
8}
9
10/** Parses the extraSnippets option; a bad value is ignored so the defaults still work. */
11export function parseExtra(raw: unknown): Record<string, string> {
12 if (typeof raw !== 'string' || !raw.trim()) return {}
13 try {
14 const obj = JSON.parse(raw)
15 const out: Record<string, string> = {}
16 if (obj && typeof obj === 'object') for (const [k, v] of Object.entries(obj)) if (typeof v === 'string' && /^[\w-]+$/.test(k)) out[k] = v
17 return out
18 } catch { return {} }
19}
20
21/** Replaces `;name` (at a word start) with its snippet text; unknown names are left alone. */
22export function expand(text: string, snippets: Record<string, string>): string {
23 return text.replace(/(^|\s);([\w-]+)\b/g, (m, lead: string, name: string) =>
24 Object.prototype.hasOwnProperty.call(snippets, name) ? lead + snippets[name] : m)
25}
26