Skip to content

run: --command removed in v2 and slash commands are not expanded — no CLI path for headless command invocation #49903

Open

Description

@markuswondrak

Description

OpenCode 2.0.8 removed --command from opencode run, and run does not expand slash commands in the message, so there is no CLI way to invoke a command headlessly.

--command was the supported headless path in v1 — see #7345, where the response was "use the --command mycmd ... we expect the flag". The migrate-v1 guide also says command definitions in .opencode/ "should continue to work without changes", and that supported behavior stopping in V2 is a compatibility bug.

This is a hard break for consumers, not an edge case. Spec Kit builds the invocation in its opencode integration (src/specify_cli/integrations/opencode/__init__.py): it synthesizes a /speckit.<name> prompt internally and then appends --command <name> to opencode run. The flag is not user-supplied, so affected users cannot work around it, and every Spec Kit workflow command step fails immediately on v2.

Observations from the same environment (2.0.8):

  • GET /api/command returns data: [] even though the command above exists.
  • POST /api/session/{sessionID}/command with {"name":"zzprobe","text":""} returns 204, so the server can execute the command — run just exposes no way to invoke it.

AI disclosure: this report was drafted with an AI assistant (OpenCode agent, model: DeepSeek V4.1 Flash) from commands and logs reproduced on the affected machine, and reviewed by the reporter before posting.

Plugins

None

OpenCode version

2.0.8

Steps to reproduce

  1. Add a file-based command .opencode/commands/zzprobe.md:


    description: probe

    Reply with exactly the token PROBE_7391 and nothing else. Do not use any tools.

  2. opencode run --command zzprobe "x"
    Actual: ERROR: Unrecognized flag: --command in command opencode run (exit 1)

  3. opencode run "/zzprobe"
    Actual: the command is not expanded. The model receives the literal text /zzprobe and replies that it does not recognize the command.

  4. opencode run --help
    Flags listed: --standalone --server --continue/-c --session/-s --fork --model/-m --agent --format --file/-f --title --thinking --auto (no --command)

Screenshot and/or share link

N/A (headless)

Operating System

Ubuntu 24.04.5 LTS (Linux 6.17.0-1032-oem, x86_64)

Terminal

Non-interactive / headless (spawned by a workflow runner, no TTY)

Activity

  1. tslator commented on Oct 26, 2026

    @tslator

    Still present in 2.0.32 and 2.1.4. Wire-level confirmation (local OpenAI-compatible provider recording POST bodies; two model ids so selection is provable from recorded requests):

    • opencode run --standalone '/summarize' with the command present in ~/.config/opencode/commands/summarize.md: provider receives the raw text /summarize as user input; the template body never appears in the request.
    • Same via OPENCODE_CONFIG_DIR (commands/rk3-cmd.md): raw /rk3-cmd sent on both versions.
    • opencode run --help on 2.1.4 has no --command-style flag.

    Your POST /api/session/{id}/command observation matches: the registry is populated server-side, expansion happens TUI-client-side.

    Helpful triage data point: the GET /api/command → [] in your repro is (at least partly) a lazy-load artifact, not necessarily missing commands — on a live background service the first call for a given location[directory] returns [], and a second call seconds later returns the full set (plain serve without --service returns [] for everything, so use service mode to probe). The registry is therefore available headlessly; only the run-boundary expansion is missing.

    For context: orgs shipping shared command sets via OPENCODE_CONFIG_DIR additionally lose user-level commands to the replace-vs-additive bug in #32825 — separate issue, same blast radius for headless command workflows.

  2. opencodejr commented on Oct 28, 2026

    @opencodejr

    Thanks for the detailed report. I can confirm this on 2.0.8, and it still happens on the latest dev (d6867f2).

    I used a project with .opencode/commands/zzprobe.md and a mock provider that logs what the model receives:

    • opencode run --command zzprobe x fails with Unrecognized flag: --command in command opencode run (exit 1), and run --help lists no command flag.
    • opencode run "/zzprobe" sends the literal text /zzprobe to the model. The command template is never expanded.
    • On dev, GET /api/command also returned data: [] for that project, as you saw.

    The v1 docs list run --command, and the migration guide says command definitions should keep working, so this looks like a v2 compatibility regression. #48365 (item 2) describes the same gap for commands registered by plugins.

    The script below reproduces it with opencode from PATH. Maintainers will take it from here.

    Reproduction script (repro.sh)
    #!/usr/bin/env bash
    # Reproduces #49903: `opencode run` has no --command flag and does not expand "/cmd".
    # Usage: OC="opencode" ./repro.sh   (or OC="bun ... packages/cli/src/index.ts")
    set -u
    OC=${OC:-opencode}
    HERE=$(cd "$(dirname "$0")" && pwd)
    P=$(mktemp -d /tmp/opencode/proj.XXXX); cd "$P"; git init -q
    export MOCK_LOG=$P/mock.log MOCK_PORT=4599
    bun "$HERE/mock.ts" & MOCK=$!; sleep 1
    mkdir -p .opencode/commands
    printf -- '---\ndescription: probe\n---\nReply with exactly the token PROBE_7391 and nothing else.\n' > .opencode/commands/zzprobe.md
    cat > opencode.json <<J
    { "provider": { "mock": { "npm": "@ai-sdk/openai-compatible", "name": "Mock",
      "options": { "baseURL": "http://127.0.0.1:4599/v1", "apiKey": "x" }, "models": { "m": { "name": "m" } } } },
      "model": "mock/m" }
    J
    export XDG_DATA_HOME=$P/.data XDG_CONFIG_HOME=$P/.cfg XDG_STATE_HOME=$P/.state XDG_CACHE_HOME=$P/.cache
    echo "== version: $($OC --version)"
    echo "== 1) run --command zzprobe x"; $OC run --standalone --command zzprobe "x"; echo "exit=$?"
    echo "== 2) run \"/zzprobe\""; timeout 120 $OC run --standalone --model mock/m "/zzprobe"; echo "exit=$?"
    echo "== user text received by the model:"; cat "$MOCK_LOG"
    echo "== run --help flags:"; $OC run --help 2>&1 | grep -E '^\s+--' 
    kill $MOCK

    Run it: bash repro.sh

  3. smartneighbor commented on Oct 31, 2026

    @smartneighbor

    Still reproducible on v2.2.4: --command is rejected. This also affects skills: V1 automatically registered them as commands, allowing opencode run --command <skill-id>. Scheduled jobs depend on this. Related proposed fix: #50430.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions