summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorrienkim <[email protected]>2025-10-30 04:54:24 +0900
committerGitHub <[email protected]>2025-10-29 14:54:24 -0500
commita9cae7b33563cb23c3aab88884d6e9b215fc0ba7 (patch)
tree61c0903596a2214a87ebf7ecf48d426641858296
parent972c0893dd7596f13f74f25a822029183013a210 (diff)
downloadopencode-a9cae7b33563cb23c3aab88884d6e9b215fc0ba7.tar.gz
opencode-a9cae7b33563cb23c3aab88884d6e9b215fc0ba7.zip
feat: add positional argument support to slash commands (#3456)
Co-authored-by: Aiden Cline <[email protected]>
-rw-r--r--packages/opencode/src/session/prompt.ts23
-rw-r--r--packages/web/src/content/docs/commands.mdx30
2 files changed, 52 insertions, 1 deletions
diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts
index 32c72e23e..43bb73707 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<typeof CommandInput>
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 adfa3fbf3..463ad9e49 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