# How Gemini CLI Commands Are Structured Using TOML: A Complete Guide

> Learn how Gemini CLI commands structure TOML files in .gemini/commands/, featuring prompt and description fields with runtime placeholders like {{args}}.

- Repository: [Every/compound-engineering-plugin](https://github.com/everyinc/compound-engineering-plugin)
- Tags: how-to-guide
- Published: 2026-02-16

---

**Gemini CLI commands are structured as individual TOML files placed in the `.gemini/commands/` directory, with each file containing a `description` field and a multiline `prompt` field that supports runtime placeholders like `{{args}}`.**

The EveryInc/compound-engineering-plugin repository provides a complete implementation for converting Claude Code commands into Gemini CLI's TOML-based format. Understanding this structure is essential for developers migrating existing AI-assisted workflows or building custom command suites for Google's Gemini CLI.

## Understanding the TOML File Structure for Gemini CLI Commands

### Required Fields

Each Gemini CLI command TOML file must contain two specific fields according to the specification in [`docs/specs/gemini.md`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/docs/specs/gemini.md) (lines 30-38):

- **`description`**: A concise, one-line string summary displayed when users run `/help`
- **`prompt`**: A multiline string (using TOML's triple-quote syntax) containing the actual instructions sent to the model

The `prompt` field supports template variables that expand at runtime. The most common placeholder is `{{args}}`, which injects user-provided arguments into the prompt context.

### File Path Conventions and Namespaces

The physical location of each TOML file determines its invocation syntax. Files reside under `.gemini/commands/` and use directory nesting to create command namespaces:

```

.gemini/commands/git/commit.toml    →  /git:commit
.gemini/commands/workflows/plan.toml → /workflows:plan

```

As implemented in [`src/converters/claude-to-gemini.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-gemini.ts) (lines 36-38), the `resolveCommandPath` function converts colon-separated command names into directory paths by splitting on the delimiter and joining with forward slashes.

## How Commands Are Converted from Claude Code to Gemini TOML

The conversion pipeline in [`src/converters/claude-to-gemini.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-gemini.ts) handles the transformation of Claude Code command definitions into Gemini-compatible TOML files through three key functions:

### Name Resolution and Path Mapping

The `resolveCommandPath` function normalizes command names to filesystem-safe paths. It processes colon-separated identifiers (e.g., `git:commit`) into array segments (`["git", "commit"]`), then joins them for the final file location.

### TOML Serialization

The `toToml` function (lines 44-53) constructs the final TOML content:

```typescript
function toToml(description: string, prompt: string): string {
  // Escapes backslashes and quotes for TOML safety
  const escapedPrompt = prompt
    .replace(/\\/g, '\\\\')
    .replace(/"/g, '\\"')
  
  return `description = "${description}"
prompt = """
${escapedPrompt}
"""
`
}

```

This implementation uses TOML's triple-quoted literal strings for the prompt field to preserve formatting and newlines while escaping internal quotes and backslashes to prevent parsing errors.

### File System Writing

The `writeGeminiBundle` function in [`src/targets/gemini.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/gemini.ts) (lines 21-24) persists each command to disk:

```typescript
if (bundle.commands.length > 0) {
  for (const command of bundle.commands) {
    await writeText(
      path.join(paths.commandsDir, `${command.name}.toml`),
      command.content + "\n"
    )
  }
}

```

This ensures each command receives a `.toml` extension and resides in the correct subdirectory based on its namespace.

## Practical Examples of Gemini CLI TOML Commands

### Example TOML Command File

Here is a complete example of a generated command file located at [`.gemini/commands/git/commit.toml`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/.gemini/commands/git/commit.toml):

```toml
description = "Create a git commit with a good message"
prompt = """
Look at the current git diff and create a commit with a descriptive message.

User request: {{args}}
"""

```

The `description` appears when users list available commands, while the `prompt` contains the full instructions sent to the Gemini model, including the `{{args}}` placeholder that injects user input.

### Conversion Implementation Example

The following TypeScript demonstrates how the plugin converts a Claude Code command definition into the Gemini TOML structure:

```typescript
// src/converters/claude-to-gemini.ts
function convertCommand(command: ClaudeCommand, usedNames: Set<string>): GeminiCommand {
  const commandPath = resolveCommandPath(command.name)   // ["git","commit"]
  const pathKey = commandPath.join("/")                // "git/commit"
  uniqueName(pathKey, usedNames)                       // track for deduplication

  const description = command.description ?? `Converted from Claude command ${command.name}`
  const prompt = command.argumentHint
    ? `${transformContentForGemini(command.body.trim())}\n\nUser request: {{args}}`
    : transformContentForGemini(command.body.trim())

  const content = toToml(description, prompt)          // serialises to TOML
  return { name: pathKey, content }
}

```

This function handles name resolution, description fallback logic, prompt transformation with optional argument injection, and final TOML serialization.

## Summary

- **Gemini CLI commands use TOML files** stored in `.gemini/commands/` with a `description` string and multiline `prompt` field.
- **File paths define command namespaces**: subdirectories create colon-separated command names (e.g., [`git/commit.toml`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/git/commit.toml) becomes `/git:commit`).
- **The conversion pipeline** in [`src/converters/claude-to-gemini.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-gemini.ts) uses `resolveCommandPath` for name mapping and `toToml` for serialization.
- **Runtime placeholders** like `{{args}}` in the `prompt` field allow dynamic user input injection when commands execute.

## Frequently Asked Questions

### What fields are required in a Gemini CLI TOML command file?

Every TOML command file must contain exactly two top-level fields: `description`, which is a single-line string displayed in help menus, and `prompt`, which is a multiline string containing the instructions sent to the Gemini model. According to the specification in [`docs/specs/gemini.md`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/docs/specs/gemini.md), these fields are mandatory for the CLI to recognize and execute the command.

### How does the file path determine the command name?

The Gemini CLI derives the invocation syntax from the relative path under `.gemini/commands/`. Directory separators become namespace colons, and the filename (minus extension) becomes the final command segment. As implemented in [`src/converters/claude-to-gemini.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-gemini.ts), the `resolveCommandPath` function splits colon-separated names and joins them with forward slashes, meaning `git:commit` maps to [`.gemini/commands/git/commit.toml`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/.gemini/commands/git/commit.toml).

### Can I use variables or placeholders in the prompt field?

Yes, the `prompt` field supports template variables that expand at runtime. The most common placeholder is `{{args}}`, which injects any arguments the user provides after the command invocation. During conversion in [`src/converters/claude-to-gemini.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-gemini.ts), the pipeline appends `\n\nUser request: {{args}}` to prompts when the original Claude command accepts arguments, ensuring user input reaches the model context.