Custom Commands

June 9, 2026 · View on GitHub

A custom command is one kind of skill member. This page covers command-specific details — frontmatter parameters, auto-injection, aliases, namespacing. For the broader picture (bundling a command with a subagent and tools, or adding a cron / file.changed subscription), see Skills.

If you find yourself typing the same kind of prompt repeatedly — "review this file for bugs", "write tests following our conventions", "check for security issues" — custom commands let you save those prompts as markdown files and invoke them as slash commands.

Each command becomes a /command you can run during any session, with support for parameters, aliases, auto-injection based on keywords, and namespace organization.

Quick Start

# Create a command with AI assistance
/commands create review-code

# Or create the file manually
mkdir -p .nanocoder/commands

.nanocoder/commands/review-code.md:

---
description: Review code for issues and improvements
aliases: [review]
parameters: [filename]
---

Review {{filename}} for:
- Bugs and edge cases
- Performance issues
- Code style and readability

Then invoke it:

/review-code src/app.ts

File Structure

Commands live in .nanocoder/commands/ in your project root. Each .md file becomes a command named after the file.

.nanocoder/commands/
  test.md              -> /test
  review.md            -> /review
  refactor/
    dry.md             -> /refactor:dry
    solid.md           -> /refactor:solid

Subdirectories create namespaced commands using colon syntax (e.g., refactor/dry.md becomes /refactor:dry).

Frontmatter Reference

All fields are optional except that every command should have a description. Frontmatter uses standard YAML between --- delimiters.

---
description: What this command does
aliases: [alt-name, shortcut]
parameters: [filename, target]
tags: [testing, quality]
triggers: [write tests, unit test]
estimated-tokens: 2000
category: testing
version: 1.0.0
author: your-name
examples:
  - /my-command src/utils.ts
  - /my-command lib/parser.ts
references: [docs/guide.md]
dependencies: [other-command]
---

Field Details

FieldTypeDescription
descriptionstringShown in /commands list and /commands show
aliasesstring[]Alternative names to invoke the command
parametersstring[]Positional placeholder names, usable as {{param}} in the body. name=default makes one optional (see Optional arguments)
tagsstring[]Keywords for auto-injection when the user's message matches
triggersstring[]Phrases that auto-inject this command into context
estimated-tokensnumberToken budget hint, shown in /commands list for auto-injectable commands
categorystringOrganizational grouping, shown in /commands show
versionstringVersion string, shown in /commands show
authorstringAuthor name, shown in /commands show
examplesstring[]Usage examples, shown in /commands show
referencesstring[]Related files or URLs, shown in /commands show
dependenciesstring[]Other commands this one depends on

Array Syntax

Arrays can be written in either JSON-style or YAML dash syntax:

# JSON-style (inline)
aliases: [review, code-review]

# YAML dash syntax (multiline)
aliases:
  - review
  - code-review

Parameters

Parameters defined in frontmatter become {{param}} placeholders in the command body. When the user invokes the command, positional arguments fill in the placeholders.

---
parameters: [filename, style]
---

Review {{filename}} using {{style}} conventions.
/review src/app.ts airbnb
# Becomes: Review src/app.ts using airbnb conventions.

Built-in variables are always available:

  • {{cwd}} - Current working directory
  • {{command}} - The command name
  • {{args}} - All arguments as a single string

Optional arguments

Every positional argument is optional - if the user omits one, its placeholder substitutes an empty string. Two features make that clean:

Default values. Add =default to a parameter name; an omitted argument substitutes the default instead of empty. Quote the entry in YAML when the value contains = or /.

---
parameters: [pr_number, "base=origin/main"]
---

Diff PR #{{pr_number}} against {{base}}.
/diff 123            # Diff PR #123 against origin/main.
/diff 123 develop    # Diff PR #123 against develop.

Conditional sections. Use {{# name }}…{{/ name }} to include a block only when the argument was provided, and {{^ name }}…{{/ name }} for the inverse. This drops a whole clause for an omitted argument instead of leaving a dangling fragment.

---
parameters: [pr_number, "issue_number="]
---

Review PR #{{pr_number}}{{# issue_number }}, linked to issue #{{issue_number}}{{/ issue_number }}.
{{^ issue_number }}No linked issue was given - review the diff on its own merits.{{/ issue_number }}

In /commands help, defaulted parameters show as [name=default] and the rest as <name>.

Auto-Injection

Commands with tags or triggers can be automatically injected into the system prompt when the user's message matches. This lets you add context-specific instructions without the user needing to invoke the command explicitly.

  • tags: Matched as keywords against the user's message
  • triggers: Matched as phrases against the user's message
---
description: Testing conventions for this project
tags: [testing, test, spec]
triggers: [write tests, add tests]
estimated-tokens: 1500
---

When writing tests for this project, follow these conventions:
- Use AVA as the test framework
- Place spec files alongside source files
- ...

Resources

When using the directory-as-command pattern, files in a resources/ subdirectory are automatically loaded and passed as additional context. This is useful for bundling templates, configs, or reference documents alongside the command.

.nanocoder/commands/
  api-gen/
    api-gen.md            -> The command (must match directory name)
    resources/
      template.yaml       -> Loaded as a resource
      examples.json       -> Loaded as a resource

Commands

CommandDescription
/commandsList all custom commands
/commands show <name>Show detailed info about a command
/commands create <name>Create a new command file with AI assistance

Custom commands are loaded at boot. To pick up new or edited command files, restart Nanocoder. (Bundle-skill commands declared in .nanocoder/skills/<name>/commands/ also load at boot; there is no hot-reload.)

/commands create

Creates a new command file in .nanocoder/commands/ and starts an AI-assisted session to write its content. The AI will ask what you want the command to do, then write the markdown file for you.

/commands create lint-fix

The .md extension is added automatically.

Examples

Test Generator

---
description: Generate comprehensive unit tests
aliases: [unittest, test-gen]
parameters: [filename]
---

Generate comprehensive unit tests for the file {{filename}}.

Consider the following:

1. Test all public functions and methods
2. Include edge cases and error scenarios
3. Use appropriate mocking where needed
4. Follow the existing test framework conventions in this project
5. Ensure good test coverage

If {{filename}} is not provided, analyze the most recently modified files and suggest which ones need tests.

DRY Refactoring

---
description: Apply DRY principle to reduce code duplication
aliases: [dedupe]
parameters: [target]
---

Analyze {{target}} for code duplication and apply the DRY (Don't Repeat Yourself) principle.

Steps:

1. Identify repeated code patterns
2. Extract common functionality into reusable functions/components
3. Update all instances to use the new abstraction
4. Ensure no functionality is broken
5. Run tests if available

Git Issue Checker

---
description: Fetch and list open GitHub issues
aliases: [issues, open-issues]
category: git
---

List all open GitHub issues for this repository. Show the issue number, title, labels, and assignee for each.

Tips

  • Start with /commands create: Let the AI help you write your first commands
  • Keep prompts focused: Commands work best with clear, specific instructions
  • Use parameters for flexibility: Instead of hardcoding paths, use {{filename}} or {{target}}
  • Organize with directories: Group related commands under a namespace (e.g., refactor/)
  • Use aliases for convenience: Add short aliases for commands you use frequently