The Clever Use of Gemini CLI Custom Commands

Share:

1. Introduction

Gemini CLI is a command-line tool launched by Google that allows you to interact with Gemini models through the command line.

Nowadays, I use Gemini CLI for many programming scenarios. When using Gemini CLI, I always feel a bit constrained—each project can only configure one gemini.md. Switching scenarios requires constant modifications, which is too troublesome!

Unlike Cursor, which can configure multiple cursor rules, Gemini CLI can only configure one system prompt per project. To set multiple scenarios, you have to write them all into a single prompt. This degrades prompt effectiveness.

Persistence pays off. After scouring the official Gemini CLI documentation, I finally found a perfect solution—custom commands!

2. Meet "Custom Commands"

Gemini CLI provides a series of built-in commands to help users manage sessions, customize interfaces, and control behavior. These commands start with a forward slash /.

Gemini CLI comes with built-in commands like /help, /clear, /copy, etc.

As the official documentation says 📝: Custom commands allow users to save and reuse their most commonly used prompts as personal shortcuts in Gemini CLI. You can create commands specific to a single project, or commands that apply globally to all projects, streamlining workflows and ensuring consistency.

We can notice that using custom commands can manage our prompts, which aligns perfectly with my needs. So I decided to use custom commands to implement flexible system prompts.

3. Three Steps to Create Your First Command

Gemini CLI discovers commands from two locations and loads them in a specific order:

  1. User commands (global): Located in ~/.gemini/commands/. These commands are available in any project the user is working on.
  2. Project commands (local): Located in /.gemini/commands/. These commands are specific to the current project and can be checked into version control for team sharing.

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.

The command name is determined by its file path relative to the commands directory. Subdirectories are used to create namespaced commands, and path separators (/ or \) are converted to colons (:).

  • Files in ~/.gemini/commands/test.toml become the command /test.
  • Files in <project>/.gemini/commands/git/commit.toml become the namespaced command /git:commit.

Custom command definition files must be written in TOML format and use the .toml file extension.

  • 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.
  • description (string): A brief one-line description of the command's functionality. This text will be displayed next to the command in the /help menu. If this field is omitted, a generic description will be generated based on the filename.

Here's a simple example:

description = "Requirement Breakdown Assistant"

prompt = "Please help me break down this requirement: {{args}} "

After adding this file, you can call the /prdspliter command in Gemini to break down requirements.

{{args}} is a Gemini CLI placeholder representing all content the user enters after the command. For simple prompt management, this is already sufficient.

But what if you want to implement more complex logic, such as integrating with command-line tools?

4. Ultimate Play: Making Custom Commands Work with Shell

You can make commands dynamic by executing shell commands directly in the prompt and injecting their output. This is perfect for gathering context from the local environment, such as reading file contents or checking Git status.

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 only intended commands are run.

How it works:

  1. Inject Command: Use the !{...} syntax in the prompt to specify where the command should run and where to inject its output.
  2. Confirm Execution: When you run the command, a dialog will appear listing the shell commands the prompt wants to execute.
  3. Grant Permission: You can choose:
  • Allow Once: The command will run only this time.
  • Always Allow in This Session: The command will be added to the current CLI session's temporary allowlist, no further confirmation needed.
  • No: Cancel the shell command execution.

The CLI still follows global excludeTools and coreTools settings.

Example (git/commit.toml):

This command gets the staged Git diff and uses it to ask the model to write a commit message.

# File path: <project>/.gemini/commands/git/commit.toml
# Call with: /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 the user runs /git:commit, the CLI first executes git diff --staged, then replaces !{git diff --staged} with that command's output, and finally sends the complete prompt to the model.

Summary

In short, Gemini CLI's custom commands are definitely a feature worth exploring deeply. They can greatly improve our workflow efficiency.

For your convenience, I've organized the git:commit command mentioned in this article and several other practical commands from my personal collection into a GitHub repository.

gemini-cli-commands

Welcome to "treasure hunt"—and don't forget to give me a Star/Fork/Issue combo! Every piece of feedback is motivation for me to keep exploring~

References

Gemini CLI Commands