# Type Generation

The `promptly generate` CLI command fetches all your prompts and composers from the API and generates a TypeScript declaration file with typed template variables for every prompt and composer ID.

## Run codegen

```bash
bunx promptly generate
```
```bash
npx promptly generate
```
```bash
yarn dlx promptly generate
```
```bash
pnpm dlx promptly generate
```
This generates a `promptly-env.d.ts` declaration file. The CLI automatically places it in `src/types/` or `types/` if either directory exists in your project, otherwise it falls back to the project root.

## Generated output

The generated file uses [declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html) to augment the `PromptVariableMap` interface. When composers are present, it also augments `ComposerVariableMap` (input variables) and `ComposerPromptMap` (named prompt keys):

```typescript title="promptly-env.d.ts"
// Auto-generated by @promptlycms/prompts - do not edit
import '@promptlycms/prompts';

declare module '@promptlycms/prompts' {
  interface PromptVariableMap {
    'review-prompt': {
      [V in 'latest' | '2.0.0' | '1.0.0']: {
        pickupLocation: string;
        items: string;
      };
    };
    'welcome-email': {
      [V in 'latest' | '1.0.0']: {
        email: string;
        subject: string;
      };
    };
  }
  interface ComposerVariableMap {
    'translation-pipeline': {
      [V in 'latest' | '1.0.0']: {
        text: string;
        targetLang: string;
      };
    };
  }
  interface ComposerPromptMap {
    'translation-pipeline': 'translatePrompt' | 'reviewPrompt';
  }
}
```

## What this gives you

With the generated file present, you get:

- **Prompt ID autocomplete** - `getPrompt('` suggests all known prompt IDs
- **Composer ID autocomplete** - `getComposer('` suggests all known composer IDs
- **Typed template variables** - `result.userMessage({ ... })` only accepts the correct variable keys
- **Typed composer inputs** - `getComposer('id', { input: { ... } })` only accepts the correct input keys
- **Typed prompt names** - destructured prompt names on `ComposerResult` are checked at compile time
- **Version-aware types** - different versions can have different variables, and the types track this
- **Strict composer IDs** - generated composer types narrow `getComposer()` and `getComposers()` to known composer IDs
- **Fallback for unknown prompts** - untyped prompt IDs fall back to `Record<string, unknown>`

### Before codegen

```typescript
// No autocomplete, no type checking on variables
const result = await promptly.getPrompt('review-prompt');
result.userMessage({ anything: 'goes' }); // No error
```

### After codegen

```typescript
// Autocomplete for prompt ID and variables
const result = await promptly.getPrompt('review-prompt');

result.userMessage({
  pickupLocation: 'London', // Typed
  items: 'sofa',            // Typed
});

result.userMessage({
  wrong: 'key', // Type error
});
```

## Output location

By default, the CLI auto-detects the best location for the generated file:

| Priority | Directory | Output path |
|----------|-----------|-------------|
| 1 | `src/types/` exists | `src/types/promptly-env.d.ts` |
| 2 | `types/` exists | `types/promptly-env.d.ts` |
| 3 | Fallback | `./promptly-env.d.ts` |

To override, use the `--output` (`-o`) flag:

```bash
npx promptly generate --output ./custom/path/promptly-env.d.ts
```

## Pass API key directly

If you don't have `PROMPTLY_API_KEY` set in your environment:

```bash
npx promptly generate --api-key pk_live_...
```

## Best practices

**Tip:** Commit `promptly-env.d.ts` to version control. This ensures types are available in CI and for teammates without needing to run codegen.

- **Re-run codegen** whenever you add, remove, or rename template variables in the CMS
- **Commit the generated file** so types are available without running codegen
- **Add to your build script** if you want to always regenerate on deploy

## How it works

Under the hood, `promptly generate`:

1. Reads `PROMPTLY_API_KEY` from the environment (or `--api-key` flag)
2. Calls `GET /prompts?include_versions=true` and `GET /composers?include_versions=true` in parallel
3. Extracts `${variable}` template patterns from each prompt's `userMessage` and each composer's prompt segments
4. Extracts prompt names from composer segments and converts them to camelCase keys
5. Groups versions with identical variables together
6. Sorts versions (latest first, then semver descending)
7. Writes a `declare module '@promptlycms/prompts'` augmentation file
8. Warns about any missing AI provider packages

The `PromptVariableMap`, `ComposerVariableMap`, and `ComposerPromptMap` interfaces are intentionally empty in the source package - they exist only as declaration merging targets. This is the same pattern used by Prisma and GraphQL Code Generator.

## Next steps

- Learn about [fetching prompts](https://docs.promptlycms.com/guides/fetching-prompts/) with typed results
- See the full [CLI reference](https://docs.promptlycms.com/reference/cli/) for all flags