Created
April 10, 2026 13:10
-
-
Save jahands/f65b09d17836c51c050a03d3a6842c16 to your computer and use it in GitHub Desktop.
opencode prompt shortcuts plugin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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