1# Slash commands /opsx:* routing to tools23## Summary45Implement the upstream OpenSpec `/opsx:*` command set (core + expanded profiles) as Hermes plugin slash commands. 11 commands route to the plugin's existing tool handlers via `ctx.dispatch_tool()`, providing power-user shortcuts for common spec-driven workflows.67## Motivation89The plugin registers 19 agent tools but no slash commands. Users who know what they want must either type a natural language prompt and let the agent select the right tool, or manually construct tool arguments. The upstream OpenSpec CLI defines a standard `/opsx:*` command set (`docs/commands.md`) that provides a canonical command surface. Implementing these as Hermes plugin slash commands gives users a familiar, fast shortcut.1011## Design1213### Command set1415**Core profile (default):**16| Command | Routes to |17|---|---|18| `/opsx:propose` | `openspec_change_create` + `openspec_instructions(proposal)` |19| `/opsx:explore` | `openspec_idea_create` |20| `/opsx:apply` | `openspec_task_list` + `openspec_instructions(apply)` |21| `/opsx:archive` | `openspec_validate` → `openspec_change_archive` |2223**Expanded workflow:**24| Command | Routes to |25|---|---|26| `/opsx:new` | `openspec_change_create` |27| `/opsx:continue` | `openspec_status` + `openspec_instructions(next_artifact)` |28| `/opsx:ff` | `openspec_change_create` → `openspec_change_promote` |29| `/opsx:verify` | `openspec_validate` + `openspec_status` + `openspec_task_list` |30| `/opsx:sync` | `openspec_spec_list` + `openspec_spec_diff` per spec |31| `/opsx:bulk-archive` | `openspec_change_archive` × N |32| `/opsx:onboard` | Static help text (no tool calls) |3334All commands accept `--workdir <path>` or `--project <name>` flags to target a repo. Without flags, the current working directory is used.3536### Implementation3738Create `commands.py` with:39- `_parse_target(raw_args)` — extracts `--workdir`/`--project` flags, returns `(tool_args, positional_text)`40- `_dispatch(ctx, tool_name, args)` — calls `ctx.dispatch_tool()` and parses JSON result41- `_fmt_result(result, ok_label, error_label)` — formats tool result for display42- Per-command handlers that orchestrate 1-3 tool calls each43- `register_commands(ctx)` — loops over the command table and calls `ctx.register_command()`4445Wire in `__init__.py` `register()` by calling `_commands.register_commands(ctx)` after tool registration.4647### Confirmed API4849- `ctx.register_command(name, handler, description, args_hint)` — accepts colon-delimited names (e.g. `"opsx:propose"`). The name is cleaned via `.lower().strip().lstrip("/")` — colons pass through.50- Command lookup in `cli.py` and `gateway/run.py` uses the full name including colon.51- `ctx.dispatch_tool(tool_name, args)` routes through the normal approval/redaction pipeline.52- No conflicts with built-in commands (checked via `resolve_command()`).5354## Alternatives considered5556- **Inject as user messages for the agent to handle.** Rejected — that's just a shortcut to typing the tool name. Direct routing is faster and doesn't consume tokens.57- **Call tools.py handlers directly (bypass dispatch_tool).** Rejected — `dispatch_tool` is the documented pattern and routes through approvals/redaction. Direct calls would bypass safety pipelines.