diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index 32c72e23e1..43bb737075 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -1504,6 +1504,9 @@ export namespace SessionPrompt { }) export type CommandInput = z.infer const bashRegex = /!`([^`]+)`/g + const argsRegex = /(?:[^\s"']+|"[^"]*"|'[^']*')+/g + const placeholderRegex = /\$(\d+)/g + const quoteTrimRegex = /^["']|["']$/g /** * Regular expression to match @ file references in text * Matches @ followed by file paths, excluding commas, periods at end of sentences, and backticks @@ -1515,7 +1518,25 @@ export namespace SessionPrompt { const command = await Command.get(input.command) const agentName = command.agent ?? input.agent ?? "build" - let template = command.template.replaceAll("$ARGUMENTS", input.arguments) + const raw = input.arguments.match(argsRegex) ?? [] + const args = raw.map((arg) => arg.replace(quoteTrimRegex, "")) + + const placeholders = command.template.match(placeholderRegex) ?? [] + let last = 0 + for (const item of placeholders) { + const value = Number(item.slice(1)) + if (value > last) last = value + } + + // Let the final placeholder swallow any extra arguments so prompts read naturally + const withArgs = command.template.replaceAll(placeholderRegex, (_, index) => { + const position = Number(index) + const argIndex = position - 1 + if (argIndex >= args.length) return "" + if (position === last) return args.slice(argIndex).join(" ") + return args[argIndex] + }) + let template = withArgs.replaceAll("$ARGUMENTS", input.arguments) const shell = ConfigMarkdown.shell(template) if (shell.length > 0) { diff --git a/packages/web/src/content/docs/commands.mdx b/packages/web/src/content/docs/commands.mdx index adfa3fbf3d..463ad9e498 100644 --- a/packages/web/src/content/docs/commands.mdx +++ b/packages/web/src/content/docs/commands.mdx @@ -129,6 +129,36 @@ Run the command with arguments: And `$ARGUMENTS` will be replaced with `Button`. +You can also access individual arguments using positional parameters: + +- `$1` - First argument +- `$2` - Second argument +- `$3` - Third argument +- And so on... + +For example: + +```md title=".opencode/command/create-file.md" +--- +description: Create a new file with content +--- + +Create a file named $1 in the directory $2 +with the following content: $3 +``` + +Run the command: + +```bash frame="none" +/create-file config.json src "{ \"key\": \"value\" }" +``` + +This replaces: + +- `$1` with `config.json` +- `$2` with `src` +- `$3` with `{ "key": "value" }` + --- ### Shell output