How to Create Slash Commands with Argument Placeholders and @file References in Claudian
Claudian lets you define slash commands as Markdown files with YAML front-matter, supporting $ARGUMENTS, $1, $2 placeholders for dynamic input and @file references that automatically attach file contents to your prompts.
The Claudian SDK is an open-source Obsidian plugin that integrates Claude directly into your vault. Creating parameterized slash commands allows you to build reusable prompts that dynamically pull in arguments and file contents before sending requests to the agent.
Understanding the Three Token Types
Claudian expands three distinct token types when processing slash commands. According to the source code in src/features/settings/ui/SlashCommandSettings.ts at line 185, these placeholders are officially documented as:
- Argument placeholders: Use
$ARGUMENTSfor the entire input string, or$1,$2, etc., for positional arguments. The runtime substitutes these with user-supplied values at invocation time. - File references: The
@<path>syntax triggers theFileContextManagerto resolve the path, read the file, and attach its contents to the query. This happens insrc/features/chat/controllers/InputController.tsviafileContextManager.transformContextMentions. - Shell snippets: The
!followed by a back-ticked command (e.g.,!`bash git status`) executes in the agent's sandboxed runtime, injecting the command output directly into the prompt.
Creating Your First Slash Command
Slash commands live as Markdown files in your vault with a YAML front-matter block followed by the prompt body. The parsing logic resides in src/utils/slashCommand.ts, which normalizes the argument-hint field and serializes commands back to Markdown.
Here is a minimal command file that uses both positional arguments and file references:
---
name: summarize-file
description: Summarise a file with optional extra notes
argument-hint: "[file] [notes]"
allowed-tools:
- Read
---
Summarise @{{ $1 }}.
Additional notes: $2
When invoked as /summarize-file docs/api.md "Focus on auth methods", the following expansion occurs:
$1resolves todocs/api.md.@{{ $1 }}triggers file resolution—the referenced file is read and attached to the query context.$2resolves toFocus on auth methods.
Using $ARGUMENTS for Free-Form Input
For commands that accept unstructured text, use the $ARGUMENTS placeholder to capture everything after the command name. This pattern is processed in src/features/chat/controllers/InputController.ts around lines 200-207, where the controller prepares the promptToSend string.
---
name: review-code
description: Review code and suggest improvements
argument-hint: "[code]"
allowed-tools:
- Read
---
Please review the following code:
$ARGUMENTS
Invoking /review-code console.log('test'); replaces $ARGUMENTS with the complete argument string console.log('test');.
Combining Placeholders with Shell Snippets
Advanced commands can mix all three token types. The ! syntax delegates execution to the agent's runtime, while @file references ensure the agent receives the file context.
---
name: lint-and-run
description: Lint a file then run a test command
argument-hint: "[file] [test-cmd]"
allowed-tools:
- Bash
---
!`bash eslint @{{ $1 }}`
Run test: $2
In this example:
@{{ $1 }}expands to the file path provided as the first argument.- The
!`bash ...`snippet executeseslinton that file path within the sandbox. $2receives the test command string.
Where the Magic Happens: Core Implementation Files
The lifecycle of slash command expansion spans several key files in the YishenTu/claudian repository:
src/utils/slashCommand.ts – Handles front-matter parsing and serialization. The serializeSlashCommandMarkdown function ensures kebab-case output for fields like argument-hint and allowed-tools, which the parser expects.
src/features/chat/controllers/InputController.ts – Orchestrates the expansion pipeline. At lines 200-207, the controller:
- Appends editor context and selections.
- Calls
fileContextManager.transformContextMentions(promptToSend)to expand@filereferences into absolute paths and attach contents. - Sends the expanded string to the agent runtime, which then substitutes
$ARGUMENTSand positional placeholders.
src/core/prompts/mainAgent.ts – Documents the @filename.md syntax at line 131, establishing the convention used throughout the prompt language.
Programmatic Command Creation
You can generate command files dynamically using the SDK's utility functions:
import {
serializeSlashCommandMarkdown,
validateCommandName,
} from '@/utils/slashCommand';
const cmd = {
name: 'summarize-file',
description: 'Summarise a file with optional notes',
argumentHint: '[file] [notes]',
allowedTools: ['Read'],
};
const body = `Summarise @{{ $1 }}.\nAdditional notes: $2`;
const markdown = serializeSlashCommandMarkdown(cmd, body);
// Write `markdown` to your vault's commands directory
The validateCommandName function ensures your command name follows SDK constraints before serialization.
Summary
- Slash commands in Claudian are Markdown files with YAML front-matter defining
name,description,argument-hint, andallowed-tools. - Argument placeholders (
$ARGUMENTS,$1,$2) are substituted at runtime by the agent after@fileexpansion occurs. - @file references are resolved by
FileContextManager.transformContextMentionsinInputController.ts, automatically attaching file contents to queries. - Shell snippets (
!`bash ...`) execute in the agent's sandboxed environment and inject output into prompts. - Use
src/utils/slashCommand.tsfunctions likeserializeSlashCommandMarkdownto programmatically generate valid command files.
Frequently Asked Questions
What happens if I use $1 but don't provide any arguments when invoking the command?
If no arguments are provided, $1 resolves to an empty string. The @{{ $1 }} reference would then attempt to resolve @ with no path, which typically fails silently or resolves to an invalid path depending on your FileContextManager configuration. Always validate inputs or provide default logic in your prompt body.
Can I use @file references outside of slash commands?
Yes. The @filename.md syntax is part of the broader prompt language documented in src/core/prompts/mainAgent.ts. The InputController processes these mentions for any chat input, not just slash command invocations, allowing you to reference files in regular chat messages.
How are shell snippets (!) different from regular commands?
Shell snippets marked with !` are executed by the agent's runtime in a sandboxed environment, not by your local system. This means they have access to the agent's file system view and tools, whereas local shell commands would run on your host machine. According to the implementation, these snippets are processed after file references but before the final prompt is sent to Claude.
Where should I store my slash command Markdown files?
Store them in your Obsidian vault's designated commands directory (typically configured in Claudian's settings). The SDK scans these locations and parses them using the logic in src/utils/slashCommand.ts to populate the command palette. Ensure each file has valid YAML front-matter separated from the body by --- delimiters.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →