Expand description
Read-side access to Claude Code’s on-disk custom slash command definitions.
Claude Code resolves custom slash commands from *.md files at:
~/.claude/commands/<name>.md– user-level<project>/.claude/commands/<name>.md– project-level
Plus plugin-provided commands under
~/.claude/plugins/<plugin>/commands/, which this module does
not enumerate (the plugin feature surfaces those separately).
§What’s NOT covered
Built-in slash commands like /help, /clear, /config,
/init are hardcoded in the claude binary. They have no disk
representation, are not listed by claude --help, and aren’t
introspectable from the CLI. Consumers learn about them from
Claude Code’s own UX. We deliberately do not attempt to mirror
a built-in list here – doing so would silently rot every time
Claude Code adds or renames one.
Skills also surface as slash commands (/recall,
/draft-pr-first, etc.) but they’re a separate on-disk artifact
type and are not loaded by this module. A consumer that wants
“the full slash command universe at this moment” combines this
list with a separate skills enumeration (and accepts that
built-ins aren’t represented).
§Two levels of granularity
CommandsRoot::list– enumerate every*.mdcommand at the root with summary metadata.CommandsRoot::get– read one command’s full record including the prompt body and any unknown frontmatter keys.
§Frontmatter format
Real-world commands look like:
---
description: Open a PR for the current branch
argument-hint: <pr title>
allowed-tools: Bash(git *), Bash(gh *)
model: sonnet
---
Open a pull request titled "$ARGUMENTS" ...The parser is permissive: only description, argument-hint,
allowed-tools, model, and disable-model-invocation are
typed. Any other key: value pairs land in Command::extra.
Frontmatter is optional – a body-only file parses fine, with
description left None.
Note the dashes in argument-hint / allowed-tools /
disable-model-invocation: that’s how Claude Code spells the
keys on disk. The typed fields use Rust-friendly snake_case
names.
§Example
use claude_wrapper::commands::CommandsRoot;
let root = CommandsRoot::user()?;
for summary in root.list()? {
println!("/{}: {}", summary.file_stem,
summary.description.as_deref().unwrap_or(""));
}Structs§
- Command
- Full command record returned by
CommandsRoot::get. - Command
Summary - Lightweight metadata for one slash command, returned by
CommandsRoot::list. - Commands
Root - Root directory of one set of slash command definitions
(
<root>/<stem>.md). UseSelf::userfor the user-level root at~/.claude/commands,Self::projectfor a project’s<dir>/.claude/commands, orSelf::atto point at an arbitrary directory for tests.