# How Namespaced Commands Create Directory Hierarchies in Conversion

> Learn how namespaced commands create directory hierarchies in conversion. Discover how colons transform into forward slashes for automatic nested folder generation.

- Repository: [Every/compound-engineering-plugin](https://github.com/everyinc/compound-engineering-plugin)
- Tags: internals
- Published: 2026-02-19

---

**Namespaced commands create directory hierarchies during conversion by splitting command names on colons, joining the segments with forward slashes, and passing the resulting path key to the file writer, which automatically generates nested folders that mirror the original namespace structure.**

In the `EveryInc/compound-engineering-plugin` repository, converting Claude Code plugins to target formats requires handling command namespaces like `workflows:plan`. When targeting hierarchical formats such as Gemini, the conversion pipeline transforms these colon-separated identifiers into file-system paths, producing organized directory structures that reflect the logical command groupings.

## The Namespace-to-Directory Pipeline

The conversion process follows a strict pipeline to transform flat command names into hierarchical directory trees. This logic lives exclusively in the Gemini converter, as other target formats deliberately flatten the namespace.

### Parsing and Segmenting Namespaced Commands

The process begins in [`src/converters/claude-to-gemini.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-gemini.ts) within the `resolveCommandPath` function. This utility splits the raw command name on the colon character (`:`) and normalizes each segment to ensure file-system compatibility.

```typescript
// src/converters/claude-to-gemini.ts
function resolveCommandPath(name: string): string[] {
  // "workflows:plan" → ["workflows", "plan"]
  return name.split(":").map((segment) => normalizeName(segment))
}

```

For a command named `workflows:plan`, this returns an array `["workflows", "plan"]`. If the command includes multiple namespaces, such as `category:subcategory:task`, the function returns a correspondingly deeper array.

### Generating Hierarchical Path Keys

The `convertCommand` function receives these segments and joins them with forward slashes to create a `pathKey`. This key serves as the relative path for the output file.

```typescript
// src/converters/claude-to-gemini.ts
function convertCommand(command: ClaudeCommand, usedNames: Set<string>): GeminiCommand {
  // Preserve namespace → "workflows:plan" becomes "workflows/plan"
  const commandPath = resolveCommandPath(command.name)   // ["workflows", "plan"]
  const pathKey = commandPath.join("/")                 // "workflows/plan"
  uniqueName(pathKey, usedNames)                       // ensure uniqueness

  const description = command.description ?? `Converted from Claude command ${command.name}`
  const transformedBody = transformContentForGemini(command.body.trim())
  const content = toToml(description, transformedBody)

  return { name: pathKey, content }                     // name contains the slash
}

```

The `uniqueName` function registers this key to prevent collisions when different namespaces contain identically named commands.

### Writing Nested Directory Structures

The final step occurs in [`src/targets/gemini.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/gemini.ts) within `writeGeminiBundle`. When the writer constructs the file path using `path.join`, the forward slashes embedded in `command.name` trigger automatic directory creation.

```typescript
// src/targets/gemini.ts
await writeText(
  path.join(paths.commandsDir, `${command.name}.toml`), // e.g. ".../.gemini/commands/workflows/plan.toml"
  command.content + "\n"
);

```

Because `command.name` contains `workflows/plan`, the operating system creates the `workflows` directory and places [`plan.toml`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/plan.toml) inside it, resulting in a structure like:

```

output/.gemini/
├─ commands/
│  ├─ workflows/
│  │  └─ plan.toml
│  └─ another/
│     └─ task.toml

```

## Contrast with Flat-Structure Targets

Other target writers—specifically Droid, Cursor, Codex, and Pi—do not preserve hierarchical namespaces. Instead, they use `flattenCommandName` to strip the namespace prefix, ensuring compatibility with their flat file layouts.

In [`src/converters/claude-to-droid.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-droid.ts), the implementation extracts only the segment after the final colon:

```typescript
// src/converters/claude-to-droid.ts
function flattenCommandName(name: string): string {
  const colonIndex = name.lastIndexOf(":")
  const base = colonIndex >= 0 ? name.slice(colonIndex + 1) : name
  return normalizeName(base) // "workflows:plan" → "plan"
}

```

The Droid writer then writes [`plan.md`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/plan.md) directly under the `commands` directory, losing the `workflows` hierarchy. Similar logic exists in [`src/converters/claude-to-cursor.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/converters/claude-to-cursor.ts) for Cursor-compatible output.

## Summary

- **Namespace parsing** in `resolveCommandPath` splits command names on colons and normalizes each segment.
- **Path generation** joins segments with forward slashes to create file-system-compatible keys like `workflows/plan`.
- **Automatic directory creation** occurs in `writeGeminiBundle` when `path.join` processes keys containing slashes, creating nested folders under the `.gemini/commands` directory.
- **Format-specific behavior** means only Gemini retains hierarchies; other targets flatten namespaces using `flattenCommandName` to match their flat file requirements.

## Frequently Asked Questions

### How does the converter handle duplicate command names across different namespaces?

The `uniqueName` utility registers each generated `pathKey` in a `Set` to track used names. If a collision occurs—for example, both `workflows:plan` and `tasks:plan` resolving to the same flattened key—the function disambiguates the names to ensure unique file outputs.

### Why does only the Gemini target support hierarchical directories?

Gemini's specification supports nested command structures organized by category, making it the only target format that benefits from preserved namespaces. According to the source code, Droid, Cursor, Codex, and Pi implement `flattenCommandName` specifically because their formats expect flat command listings without subdirectories.

### What happens if a command name contains multiple colons?

The `resolveCommandPath` function splits on **all** colon characters, creating arbitrarily deep nesting. A command named `project:workflows:plan` generates the path key `project/workflows/plan`, resulting in three levels of directory hierarchy under the output directory.

### Where is the directory creation logic located?

The actual directory creation happens implicitly in [`src/targets/gemini.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/gemini.ts) within the `writeGeminiBundle` function. When Node.js's `path.join` combines `paths.commandsDir` with a `command.name` containing forward slashes, and `writeText` attempts to write the file, the operating system automatically creates the necessary parent directories to accommodate the path.