OpenCode Nested Commands: $1 Solution, -102 Lines
Here's what tripped me up: I tried to make a slash command call another slash command.
I had two commands doing basically the same thing. One was my 4-agent blog review system—495 lines of voice validation, completeness checking, structure editing, and technical validation. The other was a wrapper that auto-selects the next post needing review, then calls the first command. 239 lines of tracking and selection logic.
What I Tried (and Why It Failed)
The wrapper command was supposed to be simple: /review-next-blog-post. This wrapper then called the custom slash command /review-blog-post-multi-agent @content/posts/specific-post on the "next" post to be reviewed in my list of posts, based on criteria I defined.
I tried different variations. Maybe the slash command syntax was wrong? Maybe I needed quotes or a different calling pattern? Still nothing. I spent way too long wondering why OpenCode was just... ignoring my nested command call.
Turns out OpenCode slash commands can't call other slash commands. Each command is like a separate executable. You can't have command-a trigger command-b from within command-a's definition.
The Realization
This actually makes sense—predictable behavior, no infinite loops, no command calling itself. But I didn't know that going in, and the lack of error feedback made the confusion worse.
I thought about a few options:
- Could I work around this somehow with some intermediate command?
- Maybe use the CLI tool to trigger commands?
- Wait—what if I just made one command do both?
The last option felt right. Instead of trying to make commands nested, I needed a single command that could operate in two different modes.
The Solution: One Command, Two Modes OpenCode's $1 argument system handles this perfectly:
**Auto-Selection Mode (no arguments):**
`/review-blog-post-multi-agent`
**Direct Review Mode (specific post):**
`/review-blog-post-multi-agent @content/posts/blog-post-slug.md` or `path/to/blog-post.md`
**Mode Selection Logic:**
- If `$1` is provided AND not empty → Direct Review Mode
- If `$1` is empty or missing → Auto-Selection Mode
If $1 is provided, use the file directly. If it's missing, run auto-selection. The command now does both modes in one place—finds the next post OR reviews the one you specify.
The Result
The consolidation was a net improvement: from 2 commands totaling 734 lines to 1 command with 632 lines. That's -102 lines while adding more functionality.
Here's what changed:
- Tracking logic: Moved from the wrapper command into
project_docs/blog-review-tracking.jsonas reusable content - Auto-selection logic: Now part of the main command instead of a separate wrapper
- Architecture: No nested dependencies—just one command that can operate in two modes
- Usage: I can run
/review-blog-post-multi-agentfor auto-selection OR/review-blog-post-multi-agent @content/posts/specific-post.mdfor direct review