Skip to content

Instantly share code, notes, and snippets.

@jahands
Created April 10, 2026 13:10
Show Gist options
  • Select an option

  • Save jahands/f65b09d17836c51c050a03d3a6842c16 to your computer and use it in GitHub Desktop.

Select an option

Save jahands/f65b09d17836c51c050a03d3a6842c16 to your computer and use it in GitHub Desktop.
opencode prompt shortcuts plugin
import { fmt } from 'llm-tools'
import type { Plugin } from '@opencode-ai/plugin'
const PROMPT_SHORTCUTS = {
'#explore': fmt.oneLine(`
Use explore agents to get a better understanding of
relevant systems before you dive into the details yourself.
`),
'#plan': fmt.oneLine(`
Make a plan and then ask me to review before you make any changes.
`),
} as const satisfies Record<string, string>
function escapeForRegExp(text: string): string {
return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
}
function endsSentence(text: string): boolean {
const trimmed = text.trimEnd()
if (!trimmed) return true
return ['.', '!', '?'].includes(trimmed.at(-1) ?? '')
}
function replaceShortcut(text: string, trigger: string, replacement: string): string {
const pattern = new RegExp(`(\\s*)${escapeForRegExp(trigger)}`, 'g')
return text.replace(pattern, (_match, whitespace: string, offset: number, source: string) => {
const prefix = source.slice(0, offset)
if (endsSentence(prefix)) return `${whitespace}${replacement}`
return `.${whitespace || ' '}${replacement}`
})
}
export function replacePromptShortcuts(text: string): string {
let nextText = text
for (const [trigger, replacement] of Object.entries(PROMPT_SHORTCUTS)) {
nextText = replaceShortcut(nextText, trigger, replacement)
}
return nextText
}
export const PromptShortcutsPlugin: Plugin = async () => {
return {
'chat.message': async (_input, output) => {
for (const part of output.parts) {
// Synthetic parts are OpenCode-generated context, not literal user input.
if (part.type !== 'text' || part.synthetic) continue
const replaced = replacePromptShortcuts(part.text)
if (replaced === part.text) continue
part.text = replaced
}
},
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment