# pi-subscription-image

[English](./README.md) | [简体中文](./README.zh-CN.md)

A [Pi](https://github.com/earendil-works/pi-mono) extension that generates and edits images with your OpenAI Codex or xAI Grok subscription quota via the `generate_image_with_subscription` tool and `/img`.

`/subscription-image status` output:

```text
Image Generation: Codex ready; Grok ready
```

`/img` command:

```text
/img a flat vector icon of a red panda
```

## Supported Providers

To sign in, run `/login`, pick `Sign in with an account` (Account below), then pick the name shown in the table.

| Provider | `/login` option | Capabilities | Default model | Output format |
| --- | --- | --- | --- | --- |
| OpenAI Codex (`codex`) | Account → `OpenAI Codex (legacy)` | Text-to-image, reference-image editing (up to 5 images) | `gpt-5.6-sol` (`gpt-image-2` backend) | `png` (default), `jpeg`, `webp` |
| xAI Grok (`grok`) | Account → `xAI` | Text-to-image, `1k` / `2k` resolution, `low` / `medium` quality | `grok-imagine-image-2.0` | Selected by Grok (`png`, `jpeg`, or `webp`) |

### Provider Notes

#### OpenAI Codex

Sign in with a ChatGPT Plus or Pro account (Account → `OpenAI Codex (legacy)`). Reference-image editing accepts up to 5 local images (`png`, `jpeg`, or `webp`, up to 20 MB each) or recent images from the current conversation. When `aspectRatio` is set, it is appended to the prompt as a composition constraint.

#### xAI Grok

Sign in with your X Premium or SuperGrok account (Account → `xAI`). Grok Imagine accepts `aspectRatio` (defaults to `1:1`), `resolution` (`1k` default or `2k`), and `quality` (`low` or `medium`, supported on `grok-imagine-image-2.0` models only) as native request parameters.

## Installation

Requires Node.js >= 22.19.0.

From npm:

```bash
pi install npm:@specode/pi-subscription-image
```

From GitHub:

```bash
pi install git:github.com/specode/pi-subscription-image
```

From a local directory for development:

```bash
pi install /path/to/pi-subscription-image
```

Run `/reload` or restart Pi after installing.

## Usage

Sign in through `/login` as described above, then ask Pi in natural language or run `/img <prompt>`:

- Generated images are shown inline in the conversation and saved to `~/.pi/agent/generated-images/` by default.
- Run `/subscription-image status` to check whether Codex and Grok credentials are available in Pi.
- Multi-image requests (`n` from `1` to `4`) run sequentially and save each image as soon as it finishes. If a later image fails or the request is cancelled, already-generated images are still returned and kept on disk.

### Provider Selection

When `provider` is omitted or set to `"auto"`, the extension chooses a backend in this order:

1. Reference images are provided (`referencedImagePaths` or `numLastImagesToInclude`) → `codex`
2. Active session model is under `openai-codex` → `codex`
3. Active session model is under `xai` → `grok`
4. `defaultProvider` is configured → configured provider
5. Otherwise, the tool asks you to pass `provider="codex"` or `provider="grok"` (or configure `defaultProvider`).

### Tool Parameters (`generate_image_with_subscription`)

| Parameter | Description |
| --- | --- |
| `prompt` | Required. Image description or edit instruction |
| `provider` | `auto` (default), `codex` (aliases: `openai`, `openai-codex`), or `grok` (aliases: `xai`, `grok-cli`) |
| `model` | Model override (Codex routing model or Grok Imagine model) |
| `aspectRatio` | `1:1`, `3:4`, `4:3`, `9:16`, `16:9`, `2:3`, `3:2`, `9:19.5`, or `19.5:9` (alias: `aspect_ratio`) |
| `n` | Number of images to generate sequentially (`1`–`4`, default `1`) |
| `outputFormat` | Codex only: `png` (default), `jpeg`, or `webp` |
| `referencedImagePaths` | Codex only: up to 5 local image paths (`png`, `jpeg`, `webp`) |
| `numLastImagesToInclude` | Codex only: include the most recent `1`–`5` conversation images |
| `resolution` | Grok only: `1k` (default) or `2k` |
| `quality` | Grok Imagine 2.0 only: `low` or `medium` (omitted by default) |
| `save` | `global` (default, `~/.pi/agent/generated-images/`), `project` (`<cwd>/.pi/generated-images/`), `custom`, or `none` |
| `saveDir` | Target directory when `save="custom"` |

## Configuration

Create `~/.pi/agent/extensions/subscription-image.json` (global) or `.pi/extensions/subscription-image.json` (trusted project override):

```json
{
  "defaultProvider": "codex",
  "save": "global",
  "saveDir": "~/Pictures/generated",
  "providers": {
    "codex": {
      "routingModel": "gpt-5.6-sol",
      "outputFormat": "png"
    },
    "grok": {
      "imageModel": "grok-imagine-image-2.0",
      "resolution": "1k"
    }
  }
}
```

Optional: set `providers.grok.quality` to `"low"` or `"medium"`. Legacy top-level keys (`codexRoutingModel`, `grokImageModel`) are also accepted.

### Environment Variables

| Variable | Description |
| --- | --- |
| `PI_SUBSCRIPTION_IMAGE_PROVIDER` | Default provider (`codex` or `grok`) |
| `PI_SUBSCRIPTION_IMAGE_SAVE_MODE` | Save mode (`global`, `project`, `custom`, or `none`; fallback: `PI_IMAGE_SAVE_MODE`) |
| `PI_SUBSCRIPTION_IMAGE_SAVE_DIR` | Directory for `save="custom"` (fallback: `PI_IMAGE_SAVE_DIR`) |
| `PI_SUBSCRIPTION_IMAGE_CODEX_MODEL` | Default Codex routing model |
| `PI_SUBSCRIPTION_IMAGE_CODEX_OUTPUT_FORMAT` | Default Codex output format (`png`, `jpeg`, or `webp`) |
| `PI_SUBSCRIPTION_IMAGE_GROK_MODEL` | Default Grok image model |
| `PI_SUBSCRIPTION_IMAGE_GROK_RESOLUTION` | Default Grok resolution (`1k` or `2k`) |
| `PI_SUBSCRIPTION_IMAGE_GROK_QUALITY` | Default Grok quality (`low` or `medium`) |
| `PI_SUBSCRIPTION_IMAGE_GROK_BASE_URL` | Custom Grok API base URL (default: `https://api.x.ai/v1`) |

## Privacy and Safety

- Credentials come only from Pi's own login (provider registry) in memory and are never written to disk by this extension.
- Requests go to `https://chatgpt.com/backend-api/codex/responses` for Codex and `https://api.x.ai/v1/images/generations` (or `PI_SUBSCRIPTION_IMAGE_GROK_BASE_URL` when set) for Grok.
- Save settings and provider parameters are validated before sending generation requests so invalid configuration does not spend quota.
- Prompts are sent as provided (with an explicit aspect-ratio line appended only on Codex when `aspectRatio` is set).

## Development

```bash
# Run tests
npm test

# Run typecheck, tests, extension smoke check, and package check
npm run check

# Load the extension directly in Pi without installing
pi --no-extensions --offline -e ./src/index.ts --list-models
```

### Calling from Codemode Scripts

On Pi versions with tool `outputSchema` and `structuredContent` support, Codemode scripts can call `tools.generate_image_with_subscription` directly:

```js
const result = await tools.generate_image_with_subscription({
  prompt: "A red panda in watercolor",
});
for (const block of result.output) {
  if (block.type === "image") image(block);
  else text(block.text);
}
```

`result` has the shape `{ provider, model, output, generationErrors, savedPaths, saveWarnings }`. Pass image blocks to `image(block)` rather than `text()`, `console.log`, or `return` so base64 image data does not hit Codemode's 16 MiB script output limit. For multiple Codex images in one script, prefer `outputFormat: "webp"` or `"jpeg"`.

## License

[MIT](./LICENSE). See [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md) for adapted sources and licenses.
