npm package: @neochief/geppetto
Description: Declarative prompt runner for OpenAI, Claude, and Grok models. Define prompts, context, output paths, and post-processing in files, then run them from the CLI.
Author: Alexander Shvets
Latest version: 1.6.0

# Geppetto: Declarative prompt runner

Geppetto is a declarative prompt runner for OpenAI, Claude, and Grok models. You define prompts, context, output paths, and post-processing in files. Geppetto compiles them into a prompt, sends it to the selected model, and saves the result where you want it.

## Installation

```bash
pnpm add -g @neochief/geppetto
```

## Usage

### 1. Setup your API key

Set the environment variable for the provider you want to use. You only need the key for the model you plan to run:

- `OPENAI_API_KEY` for OpenAI models
- `ANTHROPIC_API_KEY` for Anthropic models
- `XAI_API_KEY` for Grok models

Example:

```bash
export OPENAI_API_KEY="sk-..."
```


### 2. Define your prompt file

A prompt file must be a YAML file. Example:

**prompt.yml**
```yaml
messages:
  - file: prompt_style.yml
  - text: Don't forget that you're a Roman Emperor.
    role: system
include:
  - ps.txt
outputDir: results
content: |
  What is the meaning of life?
```

**ps.txt**
```text
P.S. I'm writing from XXI century.
```

**prompt_style.yml**
```yaml
role: system
text: |
  Imagine that you are Marcus Aurelius and you are writing a letter to your friend. You are in a good mood and you want to share your thoughts about the meaning of life.
```

This will result in a prompt consisting of two messages:

```
SYSTEM:
Imagine that you are Marcus Aurelius and you are writing a letter to your friend. You are in a good mood and you want to share your thoughts about the meaning of life.

SYSTEM:
Don't forget that you're a Roman Emperor.

USER:
What is the meaning of life?

P.S. I'm writing from XXI century.
``` 

### 3. Run Geppetto (with `gep` for convenience)

```bash
gep prompt.yml
```

## Arguments

1. Task file.
2. (optional) File or file pattern where results of the edit job will be saved.

## Options

### `-m`: LLM model to use

You can use different LLM models by specifying the `-m` option. The default is `claude-opus-4-6`.

```bash
gep prompt.yml -m gpt-5.4
```

Supported models:

- claude-opus-4-6 (`--claude`) ← the default
- claude-sonnet-4-6
- gpt-5.4 (`--gpt`)
- gpt-5.4-mini
- grok-4 (`--grok`)

Instead of passing the `-m` parameter, you can also use `--gpt`, `--grok`, or `--claude` for the current shorthand aliases.

### `--serial`: Run requests one by one

Run API calls sequentially instead of in parallel.

```bash
gep prompt.yml --serial
```

Claude requests are run serially automatically.

### `-s`: Silent mode

By default, Geppetto prints the full prompt and the results to the console. You can disable this behavior by using the `-s` option.

### `--dry-run`: Dry run

Do not send the prompt to LLM, just print the prompt to the console.

```bash
gep prompt.yml --dry-run
```

### `--thinking`: Override thinking level from CLI

Set thinking level directly from the command line.

```bash
gep prompt.yml --thinking off
gep prompt.yml --thinking medium
gep prompt.yml --thinking max
```

Supported values:

- `off`
- `medium`
- `max`

When both CLI and task file specify `thinking`, the CLI value wins.

## Prompt file options

- `text`: text string that will be used as a message.
- `include`: array of file paths that will be used as part of the message. If `text` is also passed, the included content is added after it.
- `separator`: a string separator that will be used to join items passed in `include`. By default, the separator is "\n\n". Don't specify when using `editInPlace` or `includesAsFiles`.
- `editInPlace`: will treat each passed include as a basis for modification according to the prompt. Will save the results in the same files. Don't use `includesAsFiles` and any of the output options with this mode.
- `includesAsFiles`: if true, each include will be wrapped in a special template that also includes the file name and the file path. This is useful when the exact files are important for the context. It is useful in conjunction with `outputAsFiles`.
- `role`: the default role that will be used for all messages, unless overridden in a message sub-file. Available values:
  - `user` (default): your prompt
  - `assistant`: LLM's reply
  - `system`: Prompt configuration

- `messages`: array of messages submitted before the main message
  - `file`: pathname to a YAML message sub-file, this can be a file with its own sub-messages.
  - `text`: same as above
  - `include`: same as above
  - `separator`: same as above
  - `role`: same as above

- `outputDir`: the output directory where the results will be saved. The results will be saved in a new sub-folder each time the script is launched. This sub-folder will also include a file with the prompt. This helps to iterate the changes to the source files, while having the original prompt close to the results. If this option is not defined, the results will only be printed to the console.
- `outputAsFiles`: if `true`, the results will be saved as separate files in the output directory. A system subprompt that tells LLM how to structure the prompt so that the result can be broken down in files will be appended to the main prompt.
- `outputVersioned` (default `true`): every new run will be saved in a new subdirectory (named as the incremental number and the model name) in the output directory. If `false`, the result will be saved in the output directory directly. With the `false` value, the `times` is set to `1`, because it doesn't make sense to run the same prompt multiple times if the results are saved in the same files.
- `times`: number of different runs for the same prompt. Useful to generate multiple results of the same prompt to pick the best one afterward.
- `thinking`: shared reasoning level for GPT and Claude models. Supported values: `off`, `medium`, `max`. This is a Geppetto abstraction over provider-specific settings. It is not supported for Grok models.

Thinking mapping:

- `off`: GPT uses `reasoning.effort: none`. Claude uses `thinking: disabled`.
- `medium`: GPT uses `reasoning.effort: medium`. Claude uses `thinking.budget_tokens: 2048`.
- `max`: GPT uses `reasoning.effort: xhigh`. Claude uses `thinking.budget_tokens: 8192`.

When Claude thinking is enabled, Geppetto keeps the final text output and omits the returned thinking blocks.

### Thinking examples

Turn thinking off:

```yaml
thinking: off
text: |
  Explain this code briefly.
```

Use the balanced setting:

```yaml
thinking: medium
text: |
  Review this design and list the main risks.
```

Use the highest built-in setting:

```yaml
thinking: max
text: |
  Solve this step by step and check edge cases carefully.
```

## Development

Build the CLI locally:

```bash
pnpm install
pnpm build
```

Smoke test the supported providers:

```bash
pnpm test-gpt
pnpm test-claude
pnpm test-grok
```