|
Download docs/cli/custom-commands.md from SaylorTwift/gemini-cli: direct link, hf CLI and curl.
- Browser
- Download file 12.1 kB
-
https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/docs/cli/custom-commands.md
- Command line
-
hf download hf://SaylorTwift/gemini-cli/docs/cli/custom-commands.md
-
curl -L -o custom-commands.md https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/docs/cli/custom-commands.md
12.1 kB
| # Custom commands | |
| Custom commands let you save and reuse your favorite or most frequently used | |
| prompts as personal shortcuts within Gemini CLI. You can create commands that | |
| are specific to a single project or commands that are available globally across | |
| all your projects, streamlining your workflow and ensuring consistency. | |
| ## File locations and precedence | |
| Gemini CLI discovers commands from two locations, loaded in a specific order: | |
| 1. **User commands (global):** Located in `~/.gemini/commands/`. These commands | |
| are available in any project you are working on. | |
| 2. **Project commands (local):** Located in | |
| `<your-project-root>/.gemini/commands/`. These commands are specific to the | |
| current project and can be checked into version control to be shared with | |
| your team. | |
| If a command in the project directory has the same name as a command in the user | |
| directory, the **project command will always be used.** This allows projects to | |
| override global commands with project-specific versions. | |
| ## Naming and namespacing | |
| The name of a command is determined by its file path relative to its `commands` | |
| directory. Subdirectories are used to create namespaced commands, with the path | |
| separator (`/` or `\`) being converted to a colon (`:`). | |
| - A file at `~/.gemini/commands/test.toml` becomes the command `/test`. | |
| - A file at `<project>/.gemini/commands/git/commit.toml` becomes the namespaced | |
| command `/git:commit`. | |
| <!-- prettier-ignore --> | |
| > [!TIP] | |
| > After creating or modifying `.toml` command files, run | |
| > `/commands reload` to pick up your changes without restarting the CLI. | |
| > To see all available command files, run `/commands list`. | |
| ## TOML file format (v1) | |
| Your command definition files must be written in the TOML format and use the | |
| `.toml` file extension. | |
| ### Required fields | |
| - `prompt` (String): The prompt that will be sent to the Gemini model when the | |
| command is executed. This can be a single-line or multi-line string. | |
| ### Optional fields | |
| - `description` (String): A brief, one-line description of what the command | |
| does. This text will be displayed next to your command in the `/help` menu. | |
| **If you omit this field, a generic description will be generated from the | |
| filename.** | |
| ## Handling arguments | |
| Custom commands support two powerful methods for handling arguments. The CLI | |
| automatically chooses the correct method based on the content of your command's | |
| `prompt`. | |
| ### 1. Context-aware injection with `{{args}}` | |
| If your `prompt` contains the special placeholder `{{args}}`, the CLI will | |
| replace that placeholder with the text the user typed after the command name. | |
| The behavior of this injection depends on where it is used: | |
| **A. Raw injection (outside shell commands)** | |
| When used in the main body of the prompt, the arguments are injected exactly as | |
| the user typed them. | |
| **Example (`git/fix.toml`):** | |
| ```toml | |
| # Invoked via: /git:fix "Button is misaligned" | |
| description = "Generates a fix for a given issue." | |
| prompt = "Please provide a code fix for the issue described here: {{args}}." | |
| ``` | |
| The model receives: | |
| `Please provide a code fix for the issue described here: "Button is misaligned".` | |
| **B. Using arguments in shell commands (inside `!{...}` blocks)** | |
| When you use `{{args}}` inside a shell injection block (`!{...}`), the arguments | |
| are automatically **shell-escaped** before replacement. This lets you safely | |
| pass arguments to shell commands, ensuring the resulting command is | |
| syntactically correct and secure while preventing command injection | |
| vulnerabilities. | |
| **Example (`/grep-code.toml`):** | |
| ```toml | |
| prompt = """ | |
| Please summarize the findings for the pattern `{{args}}`. | |
| Search Results: | |
| !{grep -r {{args}} .} | |
| """ | |
| ``` | |
| When you run `/grep-code It's complicated`: | |
| 1. The CLI sees `{{args}}` used both outside and inside `!{...}`. | |
| 2. Outside: The first `{{args}}` is replaced raw with `It's complicated`. | |
| 3. Inside: The second `{{args}}` is replaced with the escaped version (for | |
| example, on Linux: `"It\'s complicated"`). | |
| 4. The command executed is `grep -r "It's complicated" .`. | |
| 5. The CLI prompts you to confirm this exact, secure command before execution. | |
| 6. The final prompt is sent. | |
| ### 2. Default argument handling | |
| If your `prompt` does **not** contain the special placeholder `{{args}}`, the | |
| CLI uses a default behavior for handling arguments. | |
| If you provide arguments to the command (for example, `/mycommand arg1`), the | |
| CLI will append the full command you typed to the end of the prompt, separated | |
| by two newlines. This allows the model to see both the original instructions and | |
| the specific arguments you just provided. | |
| If you do **not** provide any arguments (for example, `/mycommand`), the prompt | |
| is sent to the model exactly as it is, with nothing appended. | |
| **Example (`changelog.toml`):** | |
| This example shows how to create a robust command by defining a role for the | |
| model, explaining where to find the user's input, and specifying the expected | |
| format and behavior. | |
| ```toml | |
| # In: <project>/.gemini/commands/changelog.toml | |
| # Invoked via: /changelog 1.2.0 added "Support for default argument parsing." | |
| description = "Adds a new entry to the project's CHANGELOG.md file." | |
| prompt = """ | |
| # Task: Update Changelog | |
| You are an expert maintainer of this software project. A user has invoked a command to add a new entry to the changelog. | |
| **The user's raw command is appended below your instructions.** | |
| Your task is to parse the `<version>`, `<change_type>`, and `<message>` from their input and use the `write_file` tool to correctly update the `CHANGELOG.md` file. | |
| ## Expected Format | |
| The command follows this format: `/changelog <version> <type> <message>` | |
| - `<type>` must be one of: "added", "changed", "fixed", "removed". | |
| ## Behavior | |
| 1. Read the `CHANGELOG.md` file. | |
| 2. Find the section for the specified `<version>`. | |
| 3. Add the `<message>` under the correct `<type>` heading. | |
| 4. If the version or type section doesn't exist, create it. | |
| 5. Adhere strictly to the "Keep a Changelog" format. | |
| """ | |
| ``` | |
| When you run `/changelog 1.2.0 added "New feature"`, the final text sent to the | |
| model will be the original prompt followed by two newlines and the command you | |
| typed. | |
| ### 3. Executing shell commands with `!{...}` | |
| You can make your commands dynamic by executing shell commands directly within | |
| your `prompt` and injecting their output. This is ideal for gathering context | |
| from your local environment, like reading file content or checking the status of | |
| Git. | |
| When a custom command attempts to execute a shell command, Gemini CLI will now | |
| prompt you for confirmation before proceeding. This is a security measure to | |
| ensure that only intended commands can be run. | |
| **How it works:** | |
| 1. **Inject commands:** Use the `!{...}` syntax. | |
| 2. **Argument substitution:** If `{{args}}` is present inside the block, it is | |
| automatically shell-escaped (see | |
| [Context-Aware Injection](#1-context-aware-injection-with-args) above). | |
| 3. **Robust parsing:** The parser correctly handles complex shell commands that | |
| include nested braces, such as JSON payloads. The content inside `!{...}` | |
| must have balanced braces (`{` and `}`). If you need to execute a command | |
| containing unbalanced braces, consider wrapping it in an external script | |
| file and calling the script within the `!{...}` block. | |
| 4. **Security check and confirmation:** The CLI performs a security check on | |
| the final, resolved command (after arguments are escaped and substituted). A | |
| dialog will appear showing the exact command(s) to be executed. | |
| 5. **Execution and error reporting:** The command is executed. If the command | |
| fails, the output injected into the prompt will include the error messages | |
| (stderr) followed by a status line, for example, | |
| `[Shell command exited with code 1]`. This helps the model understand the | |
| context of the failure. | |
| **Example (`git/commit.toml`):** | |
| This command gets the staged git diff and uses it to ask the model to write a | |
| commit message. | |
| ````toml | |
| # In: <project>/.gemini/commands/git/commit.toml | |
| # Invoked via: /git:commit | |
| description = "Generates a Git commit message based on staged changes." | |
| # The prompt uses !{...} to execute the command and inject its output. | |
| prompt = """ | |
| Please generate a Conventional Commit message based on the following git diff: | |
| ```diff | |
| !{git diff --staged} | |
| ``` | |
| """ | |
| ```` | |
| When you run `/git:commit`, the CLI first executes `git diff --staged`, then | |
| replaces `!{git diff --staged}` with the output of that command before sending | |
| the final, complete prompt to the model. | |
| ### 4. Injecting file content with `@{...}` | |
| You can directly embed the content of a file or a directory listing into your | |
| prompt using the `@{...}` syntax. This is useful for creating commands that | |
| operate on specific files. | |
| **How it works:** | |
| - **File injection**: `@{path/to/file.txt}` is replaced by the content of | |
| `file.txt`. | |
| - **Multimodal support**: If the path points to a supported image (for example, | |
| PNG, JPEG), PDF, audio, or video file, it will be correctly encoded and | |
| injected as multimodal input. Other binary files are handled gracefully and | |
| skipped. | |
| - **Directory listing**: `@{path/to/dir}` is traversed and each file present | |
| within the directory and all subdirectories is inserted into the prompt. This | |
| respects `.gitignore` and `.geminiignore` if enabled. | |
| - **Workspace-aware**: The command searches for the path in the current | |
| directory and any other workspace directories. Absolute paths are allowed if | |
| they are within the workspace. | |
| - **Processing order**: File content injection with `@{...}` is processed | |
| _before_ shell commands (`!{...}`) and argument substitution (`{{args}}`). | |
| - **Parsing**: The parser requires the content inside `@{...}` (the path) to | |
| have balanced braces (`{` and `}`). | |
| **Example (`review.toml`):** | |
| This command injects the content of a _fixed_ best practices file | |
| (`docs/best-practices.md`) and uses the user's arguments to provide context for | |
| the review. | |
| ```toml | |
| # In: <project>/.gemini/commands/review.toml | |
| # Invoked via: /review FileCommandLoader.ts | |
| description = "Reviews the provided context using a best practice guide." | |
| prompt = """ | |
| You are an expert code reviewer. | |
| Your task is to review {{args}}. | |
| Use the following best practices when providing your review: | |
| @{docs/best-practices.md} | |
| """ | |
| ``` | |
| When you run `/review FileCommandLoader.ts`, the `@{docs/best-practices.md}` | |
| placeholder is replaced by the content of that file, and `{{args}}` is replaced | |
| by the text you provided, before the final prompt is sent to the model. | |
| --- | |
| ## Example: A "Pure Function" refactoring command | |
| Let's create a global command that asks the model to refactor a piece of code. | |
| **1. Create the file and directories:** | |
| First, ensure the user commands directory exists, then create a `refactor` | |
| subdirectory for organization and the final TOML file. | |
| **macOS/Linux** | |
| ```bash | |
| mkdir -p ~/.gemini/commands/refactor | |
| touch ~/.gemini/commands/refactor/pure.toml | |
| ``` | |
| **Windows (PowerShell)** | |
| ```powershell | |
| New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.gemini\commands\refactor" | |
| New-Item -ItemType File -Force -Path "$env:USERPROFILE\.gemini\commands\refactor\pure.toml" | |
| ``` | |
| **2. Add the content to the file:** | |
| Open `~/.gemini/commands/refactor/pure.toml` in your editor and add the | |
| following content. We are including the optional `description` for best | |
| practice. | |
| ```toml | |
| # In: ~/.gemini/commands/refactor/pure.toml | |
| # This command will be invoked via: /refactor:pure | |
| description = "Asks the model to refactor the current context into a pure function." | |
| prompt = """ | |
| Please analyze the code I've provided in the current context. | |
| Refactor it into a pure function. | |
| Your response should include: | |
| 1. The refactored, pure function code block. | |
| 2. A brief explanation of the key changes you made and why they contribute to purity. | |
| """ | |
| ``` | |
| **3. Run the command:** | |
| That's it! You can now run your command in the CLI. First, you might add a file | |
| to the context, and then invoke your command: | |
| ``` | |
| > @my-messy-function.js | |
| > /refactor:pure | |
| ``` | |
| Gemini CLI will then execute the multi-line prompt defined in your TOML file. | |