# How to Configure Custom Output Directories for Each Target Platform in Compound Engineering Plugin

> Learn how to configure custom output directories for each target platform in the Compound Engineering Plugin. Use flags like --output and --codex-home to manage your builds efficiently.

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

---

**Use the `--output` flag to set a base directory for all targets, and override specific platforms with `--codex-home`, `--pi-home`, or target-specific path resolution logic in [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts).**

The **compound-engineering-plugin** from EveryInc is a CLI tool that converts plugin definitions into agent-compatible bundles for multiple AI platforms. When you need to customize where these generated files land—whether to a global config directory, a project-local folder, or a CI artifact path—the plugin provides granular control through CLI flags and intelligent path resolution.

## CLI Flags for Custom Output Directories

The conversion command in [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts) accepts several flags that determine the final write location for each target platform.

### The --output Flag (Base Directory)

The `--output` flag defines the project-relative root for conversion output. When omitted, the CLI defaults to the current working directory.

```bash
npx compound-engineering-plugin convert ./my-plugin --output ./build/agents

```

In [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts), this value is processed by `resolveOutputRoot(args.output)` to establish the base path for most targets.

### Target-Specific Override Flags

For platforms that typically reside in global config directories, you can override the base directory with dedicated flags:

| Flag | Target | Purpose |
|------|--------|---------|
| `--codex-home` | Codex | Absolute path to a `.codex` directory (e.g., `~/.codex`). |
| `--pi-home` | Pi | Absolute path to a `.pi/agent` directory (e.g., `~/.pi/agent`). |

These flags are resolved in [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts) using `resolveTargetHome`, which expands tildes and applies sensible defaults:

```typescript
// src/commands/convert.ts
const codexHome = resolveTargetHome(
  args.codexHome,
  path.join(os.homedir(), ".codex")
);
const piHome = resolveTargetHome(
  args.piHome,
  path.join(os.homedir(), ".pi", "agent")
);

```

## How Output Paths Are Resolved Internally

After parsing CLI arguments, the `resolveTargetOutputRoot` function in [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts) maps each target name to its final directory. This function implements the precedence logic that determines whether to use a global home directory, a nested subfolder, or the base output root.

```typescript
// src/commands/convert.ts
function resolveTargetOutputRoot(targetName, outputRoot, codexHome, piHome) {
  if (targetName === "codex")  return codexHome;
  if (targetName === "pi")     return piHome;
  if (targetName === "droid")  return path.join(os.homedir(), ".factory");
  if (targetName === "cursor") return path.join(outputRoot, ".cursor");
  if (targetName === "gemini") return path.join(outputRoot, ".gemini");
  return outputRoot; // OpenCode and others
}

```

**Key behaviors:**
- **Codex** and **Pi** respect their respective `--*-home` flags exclusively.
- **Droid** defaults to `~/.factory` unless overridden by environment logic.
- **Cursor** and **Gemini** nest under the base `--output` directory inside hidden folders (`.cursor`, `.gemini`).
- **OpenCode** uses the base `outputRoot` directly, with nesting logic handled at the writer level.

## Target-Specific Resolver Behavior

Each target platform implements a resolver function that finalizes the directory structure under the root provided by `resolveTargetOutputRoot`. These resolvers live in `src/targets/<target>.ts` and handle platform-specific conventions.

### OpenCode (opencode.ts)

The `resolveOpenCodePaths` function in [`src/targets/opencode.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/opencode.ts) determines nesting based on the basename of the output root:

```typescript
// src/targets/opencode.ts
function resolveOpenCodePaths(outputRoot: string) {
  const base = path.basename(outputRoot);
  
  // If already pointing to .opencode or opencode, use directly
  if (base === ".opencode" || base === "opencode") {
    return { root: outputRoot, /* ... */ };
  }
  
  // Otherwise nest under hidden .opencode folder
  return {
    root: path.join(outputRoot, ".opencode"),
    // ...
  };
}

```

### Codex (codex.ts)

The `resolveCodexRoot` function in [`src/targets/codex.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/codex.ts) ensures the `.codex` extension is present:

```typescript
// src/targets/codex.ts
function resolveCodexRoot(outputRoot: string) {
  if (path.basename(outputRoot).endsWith(".codex")) {
    return outputRoot; // Use as-is
  }
  // Create .codex subdirectory
  return path.join(outputRoot, ".codex");
}

```

### Pi (pi.ts)

The `resolvePiPaths` function in [`src/targets/pi.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/pi.ts) handles three distinct installation patterns:

```typescript
// src/targets/pi.ts
function resolvePiPaths(outputRoot: string) {
  const base = path.basename(outputRoot);
  
  // Case 1: Global install at ~/.pi/agent
  if (base === "agent") {
    return {
      skillsDir: path.join(outputRoot, "skills"),
      promptsDir: path.join(outputRoot, "prompts"),
      extensionsDir: path.join(outputRoot, "extensions"),
      mcporterConfigPath: path.join(outputRoot, "compound-engineering", "mcporter.json"),
      agentsPath: path.join(outputRoot, "AGENTS.md"),
    };
  }
  
  // Case 2: Project-local .pi directory
  if (base === ".pi") {
    return { /* same layout, no extra nesting */ };
  }
  
  // Case 3: Custom output root → auto-prefix with .pi
  return {
    skillsDir: path.join(outputRoot, ".pi", "skills"),
    promptsDir: path.join(outputRoot, ".pi", "prompts"),
    extensionsDir: path.join(outputRoot, ".pi", "extensions"),
    mcporterConfigPath: path.join(outputRoot, ".pi", "compound-engineering", "mcporter.json"),
    agentsPath: path.join(outputRoot, "AGENTS.md"),
  };
}

```

### Other Targets (Cursor, Gemini, Droid)

- **Cursor** ([`src/targets/cursor.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/cursor.ts)): Uses `resolveCursorPaths` to write directly to `.cursor` directories or nest accordingly.
- **Gemini** ([`src/targets/gemini.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/gemini.ts)): Uses `resolveGeminiPaths` with identical logic to Cursor, ensuring `.gemini` folder structure.
- **Droid** ([`src/targets/droid.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/droid.ts)): Uses `resolveDroidPaths` to handle `~/.factory` global installs or local `.factory` nesting.

## Practical Examples

### Basic Conversion with Default OpenCode Output

```bash
npx compound-engineering-plugin convert ./my-plugin

# Files appear under $(pwd)/.opencode

```

### Explicit OpenCode Destination

```bash
npx compound-engineering-plugin convert ./my-plugin \
  --output ~/.config/opencode

# Writes directly to ~/.config/opencode (no .opencode nesting)

```

### Custom Codex and Pi Outputs

```bash
npx compound-engineering-plugin convert ./my-plugin \
  --codex-home ~/.codex \
  --pi-home ./.pi \
  --also codex

# Results:

#   OpenCode → $(pwd)/.opencode

#   Codex    → ~/.codex (direct)

#   Pi       → ./.pi (direct)

```

### Custom Root for Cursor Files

To place Cursor files under `build/agent-files`:

```bash
npx compound-engineering-plugin convert ./my-plugin \
  --output build/agent-files \
  --also cursor

```

The `resolveTargetOutputRoot` function maps `cursor` to `build/agent-files/.cursor`, and the Cursor writer creates the necessary subdirectories.

## Summary

- Use **`--output`** to set the base directory for all target platforms.
- Override specific platforms with **`--codex-home`** and **`--pi-home`** for global configuration directories.
- The **`resolveTargetOutputRoot`** function in [`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts) implements the precedence logic for mapping targets to directories.
- Each target implements a resolver (e.g., `resolveOpenCodePaths`, `resolvePiPaths`) that handles platform-specific nesting conventions.
- Codex and Pi support absolute paths to home directories, while Cursor, Gemini, and Droid nest under the base output root by default.

## Frequently Asked Questions

### What is the difference between --output and --codex-home?

The **`--output`** flag sets the base directory for most targets, including OpenCode, Cursor, and Gemini. The **`--codex-home`** flag specifically overrides the output location for the Codex target, allowing you to point directly to a global configuration directory like `~/.codex` regardless of the base output setting.

### How do I prevent the plugin from creating nested .opencode or .cursor folders?

Pass a path that already ends with the target's expected directory name. For OpenCode, use `--output ~/.config/opencode` (basename `opencode`). For Cursor, the resolver checks if the basename is `.cursor` and uses it directly. If the basename does not match, the plugin automatically nests files under the appropriate hidden folder to maintain platform conventions.

### Can I write Pi files to the global agent directory while keeping other targets local?

Yes. Use the **`--pi-home`** flag to specify the global path while omitting or using `--output` for local targets. For example: `npx compound-engineering-plugin convert ./my-plugin --pi-home ~/.pi/agent --output ./local-agents`. This writes Pi files to the global `~/.pi/agent` directory while placing OpenCode and other local targets under `./local-agents`.

### Where is the logic that decides which directory each target uses?

The primary logic resides in **[`src/commands/convert.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/commands/convert.ts)** inside the `resolveTargetOutputRoot` function. This function takes the target name, base output root, and any home directory overrides, then returns the final path. Each target also has its own resolver function (e.g., `resolvePiPaths` in [`src/targets/pi.ts`](https://github.com/EveryInc/compound-engineering-plugin/blob/main/src/targets/pi.ts)) that handles platform-specific directory layout and nesting conventions.