These docs track the main branch and may describe unreleased features. The stable documentation lives at docs.docker.com.

Custom Commands

Define slash commands that send prompts, open URLs, or switch agents.

What Slash Commands Are

A slash command is a named shortcut a user types in the TUI (/df, /deploy, /plan) or on the CLI (docker agent run agent.yaml /df) instead of typing out a full prompt. Every agent can declare its own commands under commands:, and top-level commands: groups let multiple agents share the same set without duplicating them.

Unlike regular chat messages — which are queued while the agent is busy — slash commands (both built-in and named) execute immediately, even mid-response.

Commands come in three shapes:

Shape What it does
Prompt command Sends a prompt to the current agent
URL command Opens a link in the user's browser (full TUI only)
Agent-switching command Switches the active agent, optionally with a prompt (full TUI and CLI)
Behavior differs by frontend

url and agent are only fully honored in the full TUI, which checks url before agent (a URL command opens the browser and stops there; an agent-switching command switches before sending any instruction). The lean TUI doesn't special-case either field — it only resolves a command's expanded text and sends it as a chat message, so a URL-only command silently sends whatever trailing text followed the slash (often nothing, opening no browser) and an agent-switching command sends its instruction to the current agent instead of the target. The CLI (docker agent run agent.yaml /command) switches agents like the full TUI, but has no browser to open, so url has no effect there. The HTTP API (POST /api/sessions/:id/agent/:agent) resolves agent-switching commands server-side: if the message content starts with a slash command whose agent field is set, the active agent is switched and the message is rewritten before the turn runs. Prompt-only and URL commands are not resolved server-side and pass through to the model unchanged.

Prompt Commands

The simplest form: a string value that becomes the instruction sent to the current agent.

agents:
  root:
    model: anthropic/claude-sonnet-4-5
    description: A system administrator assistant.
    instruction: You are a system administrator.
    commands:
      df: "Check how much free space I have on my disk"
      logs: "Show me the last 50 lines of system logs"
      greet: "Say hello to ${env.USER}"

For more control, use the object form with an instruction: field, plus an optional description: shown in completion dialogs and help text:

commands:
  deploy:
    description: "Deploy the application to staging"
    instruction: "Deploy ${env.PROJECT_NAME || 'app'} to ${env.ENV || 'staging'}"

Commands support JavaScript template literal syntax (${env.VAR}) for environment variable interpolation, with optional || defaults and ternary expressions — the same syntax as agent instruction and description. Undefined variables expand to the empty string. See Variable Expansion in Config Fields for the full picture.

Prompt commands can also reference the text typed after the slash and call tools, using the same ${...} expansion engine as ${env.VAR}:

If instruction uses none of the ${args...} placeholders, any text typed after the slash is appended to the resolved instruction automatically.

commands:
  fix:
    description: "Fix a file, with optional extra options"
    instruction: "Fix the file ${args[0]} with options ${args[1]}"
  run:
    description: "Run a command with all the typed arguments"
    instruction: 'Run command with args: ${args.join(" ")}'
  lint:
    description: "Show the current lint output"
    instruction: 'Lint: ${shell({cmd: "task lint"})}'
# Run commands from the CLI too
$ docker agent run agent.yaml /df
$ docker agent run agent.yaml /greet
$ docker agent run agent.yaml /fix main.go --verbose
$ PROJECT_NAME=myapp ENV=production docker agent run agent.yaml /deploy

URL Commands

A command with a url field opens that URL in the user's default browser instead of sending a prompt to the agent. Any URI scheme the OS knows how to dispatch works — standard web URLs and custom schemes such as docker-desktop:// for deep links.

agents:
  root:
    model: anthropic/claude-sonnet-4-5
    description: An agent with handy URL shortcuts.
    instruction: You are a helpful assistant.
    commands:
      feedback:
        description: "Open the feedback site for this session"
        url: https://example.com/feedback?session={{session_id}}
      docs:
        description: "Open the documentation"
        url: https://docs.docker.com/
      desktop:
        description: "Open this session in Docker Desktop"
        url: docker-desktop://dashboard/session/{{session_id}}

The {{session_id}} token is replaced at invocation time with the current session ID (URL-query-escaped so it can't break the URL or inject extra query parameters), letting a command deep-link to something scoped to the conversation. This token deliberately uses {{...}} rather than the ${...} JS-expansion syntax, since the session ID is only known at dispatch time.

URLs are validated before being handed to the OS opener: a parseable URL with a non-empty scheme is required, and flag-like inputs (those starting with -) are rejected to prevent argument injection.

Full TUI only

URL commands only open a browser in the full TUI. The CLI and lean TUI don't check the url field at all, so docker agent run agent.yaml /docs never opens a browser there — but the command is still dispatched: its resolved text (usually empty, for a URL-only command) is sent as a prompt and can trigger a model turn.

See examples/url_commands.yaml for a complete example.

Agent-Switching Commands

A command with an agent field switches the active agent for the rest of the conversation. This is useful for building workflow shortcuts where /plan, /review, /deploy each route the user to the right specialist.

agents:
  root:
    model: anthropic/claude-sonnet-4-5
    description: Main assistant
    instruction: You are a project coordinator.
    sub_agents: [planner, reviewer]
    commands:
      # Switch to planner with a pre-filled prompt
      plan:
        agent: planner
        instruction: "Create a detailed plan for: ${args.join(' ')}"
      # Switch to reviewer; any text after /review is forwarded
      review:
        agent: reviewer

  planner:
    model: anthropic/claude-sonnet-4-5
    description: Planning specialist
    instruction: You create detailed project plans.

  reviewer:
    model: anthropic/claude-sonnet-4-5
    description: Code review specialist
    instruction: You review code and suggest improvements.

When agent is set without instruction, any text typed after the slash command (e.g. /review fix the auth bug) is forwarded as a prompt to the target agent. When both are set, the agent is switched first, then the instruction is sent to the new agent. Either way, the target can be any agent defined in the team, not just one of the current agent's own sub_agentssub_agents above is shown because planner and reviewer also happen to be delegation targets, not because agent: requires it.

Agent switching stays in the same session — the target agent sees the full conversation history, and the user must explicitly switch back (there's no automatic return). This is different from the two other ways agents hand off work:

Agent-switching command handoff tool transfer_task
Trigger User runs /command Model calls handoff() Model calls transfer_task()
Session Stays in the same session Stays in the same session Launches an isolated sub-session
History Target agent sees full conversation Target agent sees full conversation Child runs in isolation; only the result returns
Control User must explicitly switch back Target agent can chain to another agent Root agent stays in control

Use transfer_task (via sub_agents) when you want delegation with a clean result; use agent-switching commands when you want to become a different agent for the rest of the conversation.

See examples/agent_switching_commands.yaml for a complete example.

Reusable Command Groups

Repeated command sets across agents can be hoisted into the top-level commands: section and pulled in by name with use_commands: — the same reuse pattern as mcps: for MCP servers and toolsets: for shared toolsets.

commands:
  ci:
    deploy: "Deploy the application"
    test: "Run the test suite"

agents:
  root:
    model: anthropic/claude-sonnet-4-5
    description: Lead developer
    instruction: You are the lead developer. Coordinate the team.
    use_commands: [ci]      # reuse the "ci" command group
    commands:
      lint: "Run the linter"  # inline command, merged in (wins on conflict)

  docs-writer:
    model: anthropic/claude-sonnet-4-5
    description: Documentation writer
    instruction: You write and maintain the project documentation.
    use_commands: [ci]      # same group, reused without duplication

An agent's own inline commands: entries take precedence over merged use_commands: entries on name conflicts. See examples/shared-commands-skills.yaml for a complete example that also covers the equivalent skills: / use_skills: pattern.

Hiding Commands

Use --disable-commands to hide and disable specific slash commands in the TUI — built-in ones (/cost, /eval, /model, …) or your own named ones. Accepts a comma-separated list; the leading slash is optional and matching is case-insensitive.

$ docker agent run agent.yaml --disable-commands="/cost,/eval,/model"

This is useful for shipping a distributed agent with a narrower command surface — for example, hiding /model so a published agent always runs its intended model.

Built-in Commands

The TUI ships its own slash commands (/new, /compact, /sessions, /settings, …) alongside whatever an agent defines. See Slash Commands in the TUI reference for the full list.

Command Configuration Reference

Property Type Description
description string Shown in completion dialogs and help text.
instruction string The prompt sent to the agent. Supports argument expansion (${args[0]}, ${args.join(" ")}, …), tool calls (${tool_name({...})}), and the legacy bang syntax !tool_name(...).
agent string Name of an agent in the team to switch to when this command is invoked — any agent in the team's agents: map, not just one of the current agent's sub_agents. When set without instruction, any text typed after the slash command is forwarded as a prompt to the target agent.
url string URL to open in the user's default browser when this command is invoked, instead of sending a prompt to the agent (full TUI only — see URL Commands). The token {{session_id}} is replaced at invocation time with the current session ID (URL-query-escaped).

instruction and agent can be combined (the agent is switched first, then the instruction is sent to the new agent). In the full TUI, if url is set, it takes precedence over agent and instruction — the command only opens the browser; the lean TUI and CLI don't check url at all, so a URL-only command instead sends its (usually empty) resolved text as a prompt. See Behavior differs by frontend above. The simple string form is shorthand for { instruction: "..." }.