How Slash Commands and Custom Command Directories Work in DeepSeek-Reasonix

DeepSeek-Reasonix implements slash commands as Markdown-based prompt templates stored in configurable directories, loading them at startup with priority-based overrides and exposing them to the model through a dedicated tool interface.

DeepSeek-Reasonix treats slash commands as reusable prompt templates that transform user inputs into structured instructions for the AI. These commands are defined in Markdown files scattered across multiple custom command directories, which the application scans recursively on startup according to a strict priority hierarchy. Understanding this architecture allows you to extend the tool with custom workflows by simply creating text files in the right locations.

Directory Discovery and Priority Hierarchy

The function CommandDirs() in internal/config/paths.go builds a prioritized list of directories to scan, with later directories overriding earlier ones when filenames conflict. The search order follows five distinct priority levels:

  1. Global legacy OS support – System-wide legacy paths like <legacy-support>/commands
  2. XDG config fallback – Standard XDG directories such as <xdg-config>/commands
  3. User home convention – Dot-directories in the home folder: ~/.reasonix/commands, ~/.agents/commands, and similar variants
  4. User config/support directories – XDG-compliant paths: $XDG_CONFIG_HOME/reasonix/commands, $XDG_DATA_HOME/reasonix/commands
  5. Project-relative convention – Local directories in the current working tree: ./.reasonix/commands, ./.agents/commands

This hierarchy ensures that project-specific commands take precedence over user defaults, while system-wide fallbacks remain available. When two files resolve to the same command name, the higher-priority directory wins, as documented in the Load function comments in internal/command/command.go.

Loading and Parsing Command Files

The Load(dirs ...string) function in internal/command/command.go walks each directory recursively via walkCommands and processes every *.md file through parseFile. This pipeline extracts three critical components from each Markdown file:

Path-to-name mapping converts the relative filepath into a command identifier by removing the .md extension and converting subdirectory separators into colon namespaces. For example, git/commit.md becomes the command git:commit.

Front-matter parsing extracts a minimal header using frontmatter.Split (lines 45-48). The system recognizes two fields:

  • description – A human-readable explanation of the command's purpose
  • argument-hint – Placeholder text showing expected arguments

Body extraction treats the remainder of the file as a template string containing substitution tokens.

The resulting data populates a Command struct defined in internal/command/command.go:

type Command struct {
    Name        string // e.g. "review" or "git:commit"
    Description string // from front-matter
    ArgHint     string // from front-matter
    Body        string // template containing $ARGUMENTS, $1…$N, $$
    Source      string // original file path (for diagnostics)
}

Template Rendering and Variable Substitution

When invoked, the Command.Render(args []string) method (lines 32-48) processes the template body using the regex substRe to replace tokens:

  • $ARGUMENTS – Expands to all arguments joined by spaces
  • $1, $2, etc. – Positional arguments (empty string if missing)
  • $$ – Escapes to a literal dollar sign

This simple substitution engine allows commands to accept flexible input without requiring complex scripting syntax.

Runtime Execution and Tool Integration

Custom slash commands are exposed to the AI model through slashCommandTool in internal/command/slashtool.go. The implementation follows this flow:

NewSlashCommandTool receives a slice of SlashEntry wrappers containing the loaded Command objects. When the model calls this tool, it provides JSON with command and arguments fields. The Execute method handles three scenarios:

  • Empty or "list" command – Returns a formatted list of available commands via the list method
  • Specific command lookup – Renders the template with supplied arguments and returns the expanded text
  • Management commands – Direct handling of built-ins like /model, /provider, and /reload-cmd occurs in managementNotice within internal/control/slash.go (lines 62-84)

For custom commands, the tool returns a message formatted as:


Expanded /review — follow these instructions now:

<rendered text>

The model treats this output as a standard user turn, effectively injecting the expanded prompt into the conversation context.

UI Completion and Autocomplete

Both the CLI and TUI interfaces share completion logic defined in internal/control/slash.go. The SlashArgItems function (lines 44-86) dispatches to command-specific helpers (e.g., mcpArgItems, skillArgItems) to generate relevant suggestions.

When typing in the CLI, internal/cli/complete.go calls SlashArgItems to provide live autocomplete. The TUI implementation in internal/cli/chat_tui.go renders these as interactive menus. The filterSlash utility hides already-completed suggestions to streamline the interface.

Creating and Using Custom Commands

To create a custom slash command, place a Markdown file in any scanned directory. For example, create ~/.reasonix/commands/review.md:

description: Summarize the provided code
argument-hint: <files...>

Review the following files:
$ARGUMENTS

Provide a concise summary.

After saving, trigger a reload by running /reload-cmd in the Reasonix interface. This calls ReloadCommands, which re-executes command.Load(CommandDirs()) to pick up the new file.

To invoke the command from the model via the tool interface:

{
  "command": "review",
  "arguments": "main.go utils.go"
}

The slashCommandTool expands this to:


Expanded /review — follow these instructions now:

Review the following files:
main.go utils.go

Provide a concise summary.

To list available commands, send an empty command field:

{ "command": "", "arguments": "" }

Summary

  • DeepSeek-Reasonix loads slash commands from Markdown files in prioritized directories defined by CommandDirs() in internal/config/paths.go
  • Priority overrides follow a five-level hierarchy from global legacy paths to project-local directories
  • Command names derive from file paths, with subdirectories becoming colon-separated namespaces (e.g., git/commit.md → git:commit)
  • Template rendering supports $ARGUMENTS, positional $1…$N, and escaped $$ tokens via the Render method in internal/command/command.go
  • Runtime execution flows through slashCommandTool in internal/command/slashtool.go, distinguishing management commands from custom templates
  • Live reload is available via the /reload-cmd management command without requiring application restart

Frequently Asked Questions

Where should I place custom slash command files?

Place Markdown files in any directory returned by CommandDirs() in internal/config/paths.go. The most common locations are ~/.reasonix/commands/ for user-global commands or ./.reasonix/commands/ for project-specific commands. The scanner recursively searches subdirectories, turning folder structures into command namespaces.

How do I reload commands without restarting the application?

Execute the /reload-cmd management command in the CLI or TUI interface. This triggers ReloadCommands in the controller, which re-executes command.Load(CommandDirs()) to refresh the command registry from disk. This only reloads custom commands; management commands are baked into the binary.

What variables can I use in command templates?

Templates support three substitution tokens processed by Command.Render(): $ARGUMENTS expands to all arguments joined by spaces, $1 through $N access specific positional arguments (returning empty strings for missing positions), and $$ produces a literal dollar sign. These are replaced via regex matching defined in internal/command/command.go.

How are conflicting command names resolved?

When identical filenames exist across multiple directories, later directories override earlier ones according to the priority order in CommandDirs(). Project-relative directories (priority 5) take precedence over user home directories (priority 3), allowing repository-specific commands to shadow global defaults. The Source field in the Command struct tracks the originating file path for debugging conflicts.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →