How Custom Commands Work in Forge: A Complete Guide to Prompt Shortcuts
Forge treats custom commands as reusable prompt templates stored in Markdown files that you can invoke via CLI shortcuts instead of typing repetitive prompts.
Custom commands in Forge allow you to define named shortcuts for frequently used AI prompts. According to the antinomyhq/forgecode source code, these commands are auto-discovered at runtime from specific directories, parsed using front-matter metadata, and executed through a dedicated CLI interface.
How the Command Loading System Works
The CommandLoaderService in crates/forge_services/src/command.rs handles the discovery and initialization of custom commands. This service runs automatically when Forge starts, scanning for *.md files in two specific locations.
Directory Structure and Discovery
Forge searches for command definitions in the following order of priority:
- Global directory:
$HOME/.forge/commands(user-wide commands) - Local directory:
.forge/commandsinside the current working directory (project-specific commands)
The loader's init() method first loads built-in commands via init_default(), then reads the global directory using infra.get_environment().command_path(), followed by the local directory via command_path_local(). Each file is processed through parse_command_file using gray-matter for front-matter parsing and deserialization.
Parsing and Conflict Resolution
When multiple commands share the same name, Forge resolves conflicts using a last-write-wins strategy. Local commands override global commands, which in turn override built-ins. This hierarchy ensures that project-specific definitions take precedence while maintaining fallback options.
The parsed data constructs a UserCommand struct defined in crates/forge_domain/src/event.rs. This struct contains:
- A unique command name
- A
Template<Value>for the prompt body - Optional parameter placeholders for dynamic injection
Creating Your First Custom Command
To define a custom command, create a Markdown file with YAML front-matter in either the global or local commands directory.
---
name: summarize-pr
description: Summarize a Pull Request with context
---
You are a helpful code reviewer.
Summarize the following PR description in a concise bullet list:
{{ .prompt }}
The front-matter fields name and description become the command's metadata in the CLI. The body acts as a template engine, where {{ .prompt }} serves as a placeholder that gets replaced by arguments passed during invocation. You can define multiple parameter placeholders depending on your template requirements.
Invoking Custom Commands from the CLI
The Cmd sub-command group in crates/forge_main/src/cli.rs exposes two primary actions for managing custom commands: listing available commands and executing them.
Listing Available Commands
View all loaded custom commands using:
forge cmd list --custom
Internally, this triggers on_show_custom_commands in crates/forge_main/src/ui.rs, which fetches commands via self.command_manager.list_custom() and renders a formatted table displaying each command's name and description.
Executing Custom Commands
Invoke a custom command by passing its name and arguments:
forge cmd execute summarize-pr "Add feature X: fixes Y, improves Z."
The CLI handler joins supplied arguments, ensures the string starts with a slash, and parses it into a SlashCommand::Custom variant. The event.name identifies the command while event.parameters inject values into the stored template. The final rendered prompt is then sent to your configured LLM provider.
Keyboard Shortcuts and ZSH Integration
Forge includes ZSH integration for displaying keyboard shortcuts via run_zsh_keyboard() in crates/forge_main/src/zsh/plugin.rs. When you run forge keyboard or use bound key sequences, the system streams the keyboard.zsh script and prints available shortcuts.
The shortcut table is generated by Info::from(&ForgeCommandManager) in crates/forge_main/src/info.rs, which adds a "KEYBOARD SHORTCUTS" section with platform-specific bindings such as <ALT+ENTER> on Linux/Windows and <OPT+ENTER> on macOS for multiline input.
Summary
- Custom commands are Markdown files with YAML front-matter stored in
$HOME/.forge/commands(global) or.forge/commands(local). - The
CommandLoaderServiceauto-discovers and parses commands at startup using gray-matter, with local commands overriding global ones. - The
UserCommandstruct represents commands in memory, holding templates that support parameter injection via{{ .parameter }}syntax. - Use
forge cmd list --customto view available commands andforge cmd execute <name> <args>to run them. - ZSH integration provides keyboard shortcut discovery through
forge keyboardand platform-specific key bindings.
Frequently Asked Questions
Where should I store custom commands in Forge?
Store global commands in $HOME/.forge/commands and project-specific commands in .forge/commands within your working directory. The local directory takes precedence if command names conflict.
How do I pass arguments to a custom command?
Arguments passed to forge cmd execute are injected into template placeholders like {{ .prompt }} or custom named parameters you define in the Markdown body. The event.parameters field handles the runtime substitution before sending to the LLM.
Can local commands override global commands?
Yes. The loading mechanism in crates/forge_services/src/command.rs resolves conflicts by keeping the last command found, meaning local (CWD) commands override global ($HOME) commands, which override built-in defaults.
How do I view available keyboard shortcuts?
Run forge keyboard to display the shortcut table, or check the "KEYBOARD SHORTCUTS" section in the interactive UI generated by Info::from(&ForgeCommandManager). Shortcuts include multiline input triggers like <ALT+ENTER> on Linux/Windows and <OPT+ENTER> on macOS.
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 →