ai-img 0.1.2 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,171 @@
1
+ // This file was automatically generated by Bunli.
2
+ // You should NOT make any changes in this file as it will be overwritten.
3
+
4
+ import type { Command, CLI, GeneratedOptionMeta, RegisteredCommands, CommandOptions, GeneratedCommandMeta } from '@bunli/core'
5
+ import { createGeneratedHelpers, registerGeneratedStore } from '@bunli/core'
6
+
7
+ import Batch from '../src/commands/batch.js'
8
+ import Config from '../src/commands/config/index.js'
9
+ import Edit from '../src/commands/edit.js'
10
+ import Generate from '../src/commands/generate.js'
11
+ import Status from '../src/commands/status.js'
12
+
13
+ // Narrow list of command names to avoid typeof-cycles in types
14
+ const names = ['batch', 'config', 'edit', 'generate', 'status'] as const
15
+ type GeneratedNames = typeof names[number]
16
+
17
+ const modules: Record<GeneratedNames, Command<any>> = {
18
+ 'batch': Batch,
19
+ 'config': Config,
20
+ 'edit': Edit,
21
+ 'generate': Generate,
22
+ 'status': Status
23
+ } as const
24
+
25
+ const metadata: Record<GeneratedNames, GeneratedCommandMeta> = {
26
+ 'batch': {
27
+ name: 'batch',
28
+ description: 'Batch generate images from a JSONL file',
29
+ options: {
30
+ 'input': { type: 'z.string.min', required: true, hasDefault: false, description: 'Input JSONL file path (one job per line)', short: 'i', min: 1, minLength: 1, fileType: 'file', schema: {"type":"zod","method":"min","args":[{"type":"unknown","raw":{"type":"NumericLiteral","start":729,"end":730,"loc":{"start":{"line":29,"column":33,"index":729},"end":{"line":29,"column":34,"index":730}},"extra":{"rawValue":1,"raw":"1"},"value":1}}]}, validator: '(val) => true' },
31
+ 'outDir': { type: 'z.string.optional', required: false, hasDefault: false, description: 'Output directory', short: 'o', fileType: 'directory', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
32
+ 'concurrency': { type: 'z.coerce.number.min.max.optional', required: false, hasDefault: false, description: 'Concurrent API calls', short: 'c', min: 1, max: 25, minLength: 1, maxLength: 25, schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
33
+ 'model': { type: 'z.string.optional', required: false, hasDefault: false, description: 'Model ID to use (default varies by provider)', short: 'm', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
34
+ 'provider': { type: 'z.string.optional', required: false, hasDefault: false, description: 'AI provider: openai, google, fal (auto-detected if omitted)', short: 'P', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
35
+ 'maxAttempts': { type: 'z.coerce.number.min.max.optional', required: false, hasDefault: false, description: 'Max retry attempts for failed jobs', min: 1, max: 10, minLength: 1, maxLength: 10, schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' }
36
+ },
37
+ path: './src/commands/batch'
38
+ },
39
+ 'config': {
40
+ name: 'config',
41
+ description: 'Manage ai-img runtime configuration',
42
+ commands: [
43
+ {
44
+ name: 'init',
45
+ description: 'Create an ai-img config file',
46
+ options: {
47
+ 'target': { type: 'z.enum.default', required: true, hasDefault: true, default: "user", description: 'Config target: user or project', short: 't', enumValues: ["user","project"], schema: {"type":"zod","method":"default","args":[{"type":"literal","value":"user"}]}, validator: '(val) => true' },
48
+ 'file': { type: 'z.string.optional', required: false, hasDefault: false, description: 'Custom config file path', fileType: 'file', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
49
+ 'force': { type: 'z.coerce.boolean.default', required: true, hasDefault: true, default: false, description: 'Overwrite target file if it already exists', short: 'f', schema: {"type":"zod","method":"default","args":[{"type":"unknown","raw":{"type":"BooleanLiteral","start":380,"end":385,"loc":{"start":{"line":13,"column":61,"index":380},"end":{"line":13,"column":66,"index":385}},"value":false}}]}, validator: '(val) => true' }
50
+ },
51
+ path: './src/commands/config/init'
52
+ },
53
+ {
54
+ name: 'show',
55
+ description: 'Show effective merged configuration (secrets redacted)',
56
+ path: './src/commands/config/show'
57
+ },
58
+ {
59
+ name: 'set',
60
+ description: 'Set a config key (supports dotted paths)',
61
+ options: {
62
+ 'target': { type: 'z.enum.default', required: true, hasDefault: true, default: "user", description: 'Config target: user or project', short: 't', enumValues: ["user","project"], schema: {"type":"zod","method":"default","args":[{"type":"literal","value":"user"}]}, validator: '(val) => true' },
63
+ 'file': { type: 'z.string.optional', required: false, hasDefault: false, description: 'Custom config file path', fileType: 'file', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
64
+ 'secret': { type: 'z.coerce.boolean.default', required: true, hasDefault: true, default: false, description: 'Treat the value as a secret (prompts securely when omitted)', schema: {"type":"zod","method":"default","args":[{"type":"unknown","raw":{"type":"BooleanLiteral","start":532,"end":537,"loc":{"start":{"line":18,"column":62,"index":532},"end":{"line":18,"column":67,"index":537}},"value":false}}]}, validator: '(val) => true' }
65
+ },
66
+ path: './src/commands/config/set'
67
+ },
68
+ {
69
+ name: 'unset',
70
+ description: 'Unset a config key (supports dotted paths)',
71
+ options: {
72
+ 'target': { type: 'z.enum.default', required: true, hasDefault: true, default: "user", description: 'Config target: user or project', short: 't', enumValues: ["user","project"], schema: {"type":"zod","method":"default","args":[{"type":"literal","value":"user"}]}, validator: '(val) => true' },
73
+ 'file': { type: 'z.string.optional', required: false, hasDefault: false, description: 'Custom config file path', fileType: 'file', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' }
74
+ },
75
+ path: './src/commands/config/unset'
76
+ }
77
+ ],
78
+ path: './src/commands/config/index'
79
+ },
80
+ 'edit': {
81
+ name: 'edit',
82
+ description: 'Edit an existing image with AI',
83
+ options: {
84
+ 'prompt': { type: 'z.string.min', required: true, hasDefault: false, description: 'Text prompt for editing', short: 'p', min: 1, minLength: 1, schema: {"type":"zod","method":"min","args":[{"type":"unknown","raw":{"type":"NumericLiteral","start":712,"end":713,"loc":{"start":{"line":24,"column":34,"index":712},"end":{"line":24,"column":35,"index":713}},"extra":{"rawValue":1,"raw":"1"},"value":1}}]}, validator: '(val) => true' },
85
+ 'input': { type: 'z.string.min', required: true, hasDefault: false, description: 'Input image path(s) - first image is primary', short: 'i', min: 1, minLength: 1, fileType: 'path', schema: {"type":"zod","method":"min","args":[{"type":"unknown","raw":{"type":"NumericLiteral","start":823,"end":824,"loc":{"start":{"line":28,"column":33,"index":823},"end":{"line":28,"column":34,"index":824}},"extra":{"rawValue":1,"raw":"1"},"value":1}}]}, validator: '(val) => true' },
86
+ 'mask': { type: 'z.string.optional', required: false, hasDefault: false, description: 'Mask image path (for partial edits)', short: 'm', fileType: 'path', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
87
+ 'model': { type: 'z.string.optional', required: false, hasDefault: false, description: 'Model ID to use (default varies by provider)', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
88
+ 'provider': { type: 'z.string.optional', required: false, hasDefault: false, description: 'AI provider: openai, google, fal (auto-detected if omitted)', short: 'P', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
89
+ 'size': { type: 'z.string.optional', required: false, hasDefault: false, description: 'Image size', short: 's', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
90
+ 'count': { type: 'z.coerce.number.min.max.optional', required: false, hasDefault: false, description: 'Number of images to generate', short: 'c', min: 1, max: 10, minLength: 1, maxLength: 10, schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
91
+ 'output': { type: 'z.string.optional', required: false, hasDefault: false, description: 'Output file path', short: 'o', fileType: 'file', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
92
+ 'outDir': { type: 'z.string.optional', required: false, hasDefault: false, description: 'Output directory', fileType: 'directory', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
93
+ 'image-mode': { type: 'z.enum.optional', required: false, hasDefault: false, description: 'Terminal image preview mode (off, auto, on)', enumValues: ["off","auto","on"], schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' }
94
+ },
95
+ path: './src/commands/edit'
96
+ },
97
+ 'generate': {
98
+ name: 'generate',
99
+ description: 'Generate new images from a text prompt',
100
+ options: {
101
+ 'prompt': { type: 'z.string.min', required: true, hasDefault: false, description: 'Text prompt for image generation', short: 'p', min: 1, minLength: 1, schema: {"type":"zod","method":"min","args":[{"type":"unknown","raw":{"type":"NumericLiteral","start":718,"end":719,"loc":{"start":{"line":24,"column":34,"index":718},"end":{"line":24,"column":35,"index":719}},"extra":{"rawValue":1,"raw":"1"},"value":1}}]}, validator: '(val) => true' },
102
+ 'model': { type: 'z.string.optional', required: false, hasDefault: false, description: 'Model ID to use (default varies by provider)', short: 'm', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
103
+ 'provider': { type: 'z.string.optional', required: false, hasDefault: false, description: 'AI provider: openai, google, fal (auto-detected if omitted)', short: 'P', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
104
+ 'size': { type: 'z.string.optional', required: false, hasDefault: false, description: 'Image size (e.g., 1024x1024, 1536x1024)', short: 's', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
105
+ 'aspectRatio': { type: 'z.string.optional', required: false, hasDefault: false, description: 'Aspect ratio (e.g., 16:9, 4:3, 1:1) - for Gemini models', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
106
+ 'count': { type: 'z.coerce.number.min.max.optional', required: false, hasDefault: false, description: 'Number of images to generate', short: 'c', min: 1, max: 10, minLength: 1, maxLength: 10, schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
107
+ 'seed': { type: 'z.coerce.number.optional', required: false, hasDefault: false, description: 'Random seed for reproducibility', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
108
+ 'quality': { type: 'z.enum.optional', required: false, hasDefault: false, description: 'Quality setting (provider-specific)', enumValues: ["low","medium","high","auto"], schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
109
+ 'output': { type: 'z.string.optional', required: false, hasDefault: false, description: 'Output file path', short: 'o', fileType: 'file', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
110
+ 'outDir': { type: 'z.string.optional', required: false, hasDefault: false, description: 'Output directory', fileType: 'directory', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
111
+ 'image-mode': { type: 'z.enum.optional', required: false, hasDefault: false, description: 'Terminal image preview mode (off, auto, on)', enumValues: ["off","auto","on"], schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' }
112
+ },
113
+ path: './src/commands/generate'
114
+ },
115
+ 'status': {
116
+ name: 'status',
117
+ description: 'Show detected providers and default model resolution',
118
+ options: {
119
+ 'provider': { type: 'z.string.optional', required: false, hasDefault: false, description: 'Provider to inspect (openai, google, fal)', short: 'P', schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' },
120
+ 'image-mode': { type: 'z.enum.optional', required: false, hasDefault: false, description: 'Terminal image preview mode (off, auto, on)', enumValues: ["off","auto","on"], schema: {"type":"zod","method":"optional","args":[]}, validator: '(val) => true' }
121
+ },
122
+ path: './src/commands/status'
123
+ }
124
+ } as const
125
+
126
+ export const generated = registerGeneratedStore(createGeneratedHelpers(modules, metadata))
127
+
128
+ export const commands = generated.commands
129
+ export const commandMeta = generated.metadata
130
+
131
+ export interface GeneratedCLI {
132
+ register(cli?: CLI<any>): GeneratedCLI
133
+ list(): Array<{
134
+ name: GeneratedNames
135
+ command: (typeof modules)[GeneratedNames]
136
+ metadata: (typeof metadata)[GeneratedNames]
137
+ }>
138
+ get<Name extends GeneratedNames>(name: Name): (typeof modules)[Name]
139
+ getMetadata<Name extends GeneratedNames>(name: Name): (typeof metadata)[Name]
140
+ getFlags<Name extends keyof RegisteredCommands & string>(name: Name): CommandOptions<Name>
141
+ getFlagsMeta<Name extends GeneratedNames>(name: Name): Record<string, GeneratedOptionMeta>
142
+ withCLI(cli: CLI<any>): { execute(name: string, options: unknown): Promise<void> }
143
+ }
144
+
145
+ export const cli: GeneratedCLI = {
146
+ register: (cliInstance?: CLI<any>) => { generated.register(cliInstance); return cli },
147
+ list: () => generated.list(),
148
+ get: <Name extends GeneratedNames>(name: Name) => generated.get(name),
149
+ getMetadata: <Name extends GeneratedNames>(name: Name) => generated.getMetadata(name),
150
+ getFlags: <Name extends keyof RegisteredCommands & string>(name: Name) => generated.getFlags(name) as CommandOptions<Name>,
151
+ getFlagsMeta: <Name extends GeneratedNames>(name: Name) => generated.getFlagsMeta(name),
152
+ withCLI: (cliInstance) => generated.withCLI(cliInstance)
153
+ }
154
+
155
+ // Enhanced helper functions
156
+ export const listCommands = () => generated.list().map(c => c.name)
157
+ export const getCommandApi = <Name extends GeneratedNames>(name: Name) => generated.getMetadata(name)
158
+ export const getTypedFlags = <Name extends GeneratedNames>(name: Name) => generated.getFlags(name) as CommandOptions<Name>
159
+ export const validateCommand = <Name extends GeneratedNames>(name: Name, flags: Record<string, unknown>) => generated.validateCommand(name, flags)
160
+ export const findCommandByName = <Name extends GeneratedNames>(name: Name) => generated.findByName(name)
161
+ export const findCommandsByDescription = (searchTerm: string) => generated.findByDescription(searchTerm)
162
+ export const getCommandNames = () => generated.getCommandNames()
163
+
164
+ // Auto-register on import for zero-config usage
165
+ export default cli
166
+
167
+ // Ensure module augmentation happens on import
168
+ declare module '@bunli/core' {
169
+ // Precise key mapping without typeof cycles
170
+ interface RegisteredCommands extends Record<GeneratedNames, Command<any>> {}
171
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "packageName": "ai-img",
3
+ "targetVersion": "0.2.1",
4
+ "tag": "v0.2.1",
5
+ "options": {
6
+ "publishNpm": true,
7
+ "publishGitHub": true,
8
+ "binaryEnabled": false,
9
+ "platforms": []
10
+ },
11
+ "status": "in_progress",
12
+ "completedSteps": [
13
+ "run-tests",
14
+ "update-version",
15
+ "build-project",
16
+ "create-git-tag"
17
+ ],
18
+ "createdAt": "2026-03-06T08:17:38.158Z",
19
+ "updatedAt": "2026-03-06T08:21:06.876Z",
20
+ "currentStep": "publish-npm",
21
+ "lastError": {
22
+ "step": "publish-npm",
23
+ "message": "npm publish failed (exit code 1)",
24
+ "at": "2026-03-06T08:19:51.285Z"
25
+ }
26
+ }
package/README.md CHANGED
@@ -1,27 +1,25 @@
1
1
  # ai-img
2
2
 
3
- AI Image Generation CLI with bunli + AI SDK. Supports OpenAI, Google (Gemini), and Fal AI.
3
+ AI image generation CLI built with Bun + Bunli + AI SDK.
4
4
 
5
- ## Install CLI
5
+ ## Install
6
6
 
7
7
  ```bash
8
- # Install globally with Bun (recommended)
9
8
  bun add -g ai-img
9
+ ```
10
+
11
+ Or local development:
10
12
 
11
- # Or clone and install locally
13
+ ```bash
12
14
  git clone https://github.com/aryasaatvik/ai-img
13
15
  cd ai-img
14
16
  bun install
15
17
  bun run build
16
18
  ```
17
19
 
18
- ## Usage
20
+ ## Install as Agent Skill
19
21
 
20
- ```bash
21
- # Generate an image
22
- ai-img generate -p "a cat sitting on a chair" -o cat.png
23
-
24
- Add to your AI agent skills:
22
+ Add to your AI agent:
25
23
 
26
24
  ```bash
27
25
  # For Claude Code
@@ -42,50 +40,174 @@ npx skills add ./skills/ai-image-gen
42
40
 
43
41
  See [skills/ai-image-gen](./skills/ai-image-gen/) for full skill documentation.
44
42
 
43
+ ## Commands
44
+
45
45
  ```bash
46
- bun install
47
- bun run build
46
+ # Generate images
47
+ ai-img generate -p "a cat wearing sunglasses" -o cat.png
48
+
49
+ # Edit images
50
+ ai-img edit -p "make it blue" -i input.png -o output.png
51
+
52
+ # Batch jobs from JSONL
53
+ ai-img batch -i jobs.jsonl -o ./output
54
+
55
+ # Provider/config status
56
+ ai-img status
57
+
58
+ # Force strict preview rendering (supported on generate/edit)
59
+ ai-img generate -p "a cat wearing sunglasses" --image-mode on
60
+ ai-img edit -p "make it blue" -i input.png --image-mode on
61
+
62
+ # Inspect preview mode resolution with explicit flag
63
+ ai-img status --image-mode on
64
+
65
+ # Manage runtime config
66
+ ai-img config init
67
+ ai-img config init --target project
68
+ ai-img config show
69
+ ai-img config set aiImg.defaults.provider openai
70
+ ai-img config set aiImg.preview.mode auto
71
+ ai-img config unset aiImg.defaults.provider
72
+
73
+ # Generate shell completions
74
+ ai-img completions bash
75
+ ai-img completions zsh
76
+ ai-img completions fish
48
77
  ```
49
78
 
50
- ## Usage
79
+ ## Shell Completions
51
80
 
52
- ```bash
53
- # Generate an image
54
- ai-img generate -p "a cat sitting on a chair" -o cat.png
81
+ The completions plugin adds a `completions` command for Bash/Zsh/Fish.
55
82
 
56
- # Generate with specific provider
57
- ai-img generate -p "a sunset" -P google -o sunset.png
83
+ Quick install patterns:
58
84
 
59
- # Edit an image
60
- ai-img edit -p "make it blue" -i input.png -o output.png
85
+ ```bash
86
+ # Bash (current session)
87
+ source <(ai-img completions bash)
88
+
89
+ # Zsh (save file)
90
+ mkdir -p ~/.zsh/completions
91
+ ai-img completions zsh > ~/.zsh/completions/_ai-img
61
92
 
62
- # Batch process from JSONL
63
- ai-img batch -i jobs.jsonl -o output/
93
+ # Fish (save file)
94
+ ai-img completions fish > ~/.config/fish/completions/ai-img.fish
64
95
  ```
65
96
 
66
97
  ## Providers
67
98
 
68
- Set your API key via environment variable:
99
+ Supported providers: `openai`, `google`, `fal`.
100
+
101
+ Credential resolution order is:
102
+ 1. Environment variables
103
+ 2. Config secrets (`aiImg.secrets.<provider>`)
104
+
105
+ Environment variable names:
69
106
  - OpenAI: `OPENAI_API_KEY`
70
- - Google: `GEMINI_API_KEY` or `GOOGLE_API_KEY`
107
+ - Google: `GOOGLE_API_KEY`, `GEMINI_API_KEY`, `GOOGLE_GENERATIVE_AI_API_KEY`
71
108
  - Fal: `FAL_API_KEY`
72
109
 
73
- ## Options
74
-
75
- ### generate
76
- - `-p, --prompt` - Text prompt (required)
77
- - `-P, --provider` - AI provider (openai, google, fal)
78
- - `-m, --model` - Model ID
79
- - `-s, --size` - Image size (e.g., 1024x1024)
80
- - `-c, --count` - Number of images
81
- - `-o, --output` - Output file path
82
-
83
- ### edit
84
- - `-p, --prompt` - Edit prompt (required)
85
- - `-i, --input` - Input image path (required)
86
- - `-m, --mask` - Mask image for partial edits
87
-
88
- ### batch
89
- - `-i, --input` - JSONL file with one job per line
90
- - `-o, --outDir` - Output directory
91
- - `-c, --concurrency` - Concurrent API calls
110
+ ## Runtime Config
111
+
112
+ Config is loaded from these sources (deep merged, later overrides earlier):
113
+ 1. `~/.config/ai-img/config.json`
114
+ 2. `.ai-imgrc`
115
+ 3. `.ai-imgrc.json`
116
+ 4. `.ai-imgrc.local.json`
117
+
118
+ Runtime precedence is:
119
+ 1. CLI flags
120
+ 2. Project config
121
+ 3. User config
122
+ 4. Built-in defaults
123
+
124
+ `config init/set/unset` defaults to `--target user`. Use `--target project` to write local project config.
125
+
126
+ For preview mode specifically, precedence is:
127
+ 1. `--image-mode` flag
128
+ 2. `aiImg.preview.mode` config
129
+ 3. default `auto`
130
+
131
+ ### Config Schema
132
+
133
+ ```json
134
+ {
135
+ "aiImg": {
136
+ "schemaVersion": 1,
137
+ "defaults": {
138
+ "provider": "openai",
139
+ "model": "gpt-image-1.5",
140
+ "size": "1024x1024",
141
+ "output": "output.png",
142
+ "outDir": "./output"
143
+ },
144
+ "generate": {
145
+ "quality": "auto",
146
+ "count": 1
147
+ },
148
+ "edit": {
149
+ "count": 1
150
+ },
151
+ "batch": {
152
+ "concurrency": 5,
153
+ "maxAttempts": 3
154
+ },
155
+ "preview": {
156
+ "mode": "auto",
157
+ "protocol": "auto",
158
+ "width": 32
159
+ },
160
+ "secrets": {
161
+ "openai": "...",
162
+ "google": "...",
163
+ "fal": "..."
164
+ }
165
+ }
166
+ }
167
+ ```
168
+
169
+ ### Terminal Preview Notes
170
+
171
+ - Preview mode values: `off`, `auto`, `on`
172
+ - `auto` is best-effort and non-fatal when rendering is unavailable
173
+ - `on` is strict and fails fast before provider API calls when preview is unsupported
174
+ - Default thumbnail width is `32` columns; only width is set so aspect ratio is preserved
175
+ - Current protocol support is Kitty-compatible terminals (for example Kitty, Ghostty)
176
+ - `aiImg.schemaVersion` defaults to `1` during config load when omitted
177
+
178
+ ## IDE Autocomplete via JSON Schema
179
+
180
+ The config schema is generated from Zod and published as `ai-img.schema.json`.
181
+
182
+ Generate/update it:
183
+
184
+ ```bash
185
+ bun run generate:schema
186
+ ```
187
+
188
+ Check for drift:
189
+
190
+ ```bash
191
+ bun run generate:schema:check
192
+ ```
193
+
194
+ Use it in your config file:
195
+
196
+ ```json
197
+ {
198
+ "$schema": "./ai-img.schema.json",
199
+ "aiImg": {
200
+ "schemaVersion": 1
201
+ }
202
+ }
203
+ ```
204
+
205
+ ## Scripts
206
+
207
+ ```bash
208
+ bun run dev
209
+ bun run build
210
+ bun run typecheck
211
+ bun run generate:schema
212
+ bun run generate:schema:check
213
+ ```
@@ -0,0 +1,142 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "type": "object",
4
+ "properties": {
5
+ "aiImg": {
6
+ "type": "object",
7
+ "properties": {
8
+ "defaults": {
9
+ "type": "object",
10
+ "properties": {
11
+ "provider": {
12
+ "type": "string",
13
+ "enum": [
14
+ "openai",
15
+ "google",
16
+ "fal"
17
+ ]
18
+ },
19
+ "model": {
20
+ "type": "string",
21
+ "minLength": 1
22
+ },
23
+ "size": {
24
+ "type": "string",
25
+ "pattern": "^\\d+x\\d+$"
26
+ },
27
+ "output": {
28
+ "type": "string",
29
+ "minLength": 1
30
+ },
31
+ "outDir": {
32
+ "type": "string",
33
+ "minLength": 1
34
+ }
35
+ },
36
+ "additionalProperties": false
37
+ },
38
+ "generate": {
39
+ "type": "object",
40
+ "properties": {
41
+ "quality": {
42
+ "type": "string",
43
+ "enum": [
44
+ "low",
45
+ "medium",
46
+ "high",
47
+ "auto"
48
+ ]
49
+ },
50
+ "count": {
51
+ "type": "integer",
52
+ "minimum": 1,
53
+ "maximum": 10
54
+ }
55
+ },
56
+ "additionalProperties": false
57
+ },
58
+ "edit": {
59
+ "type": "object",
60
+ "properties": {
61
+ "count": {
62
+ "type": "integer",
63
+ "minimum": 1,
64
+ "maximum": 10
65
+ }
66
+ },
67
+ "additionalProperties": false
68
+ },
69
+ "batch": {
70
+ "type": "object",
71
+ "properties": {
72
+ "concurrency": {
73
+ "type": "integer",
74
+ "minimum": 1,
75
+ "maximum": 25
76
+ },
77
+ "maxAttempts": {
78
+ "type": "integer",
79
+ "minimum": 1,
80
+ "maximum": 10
81
+ }
82
+ },
83
+ "additionalProperties": false
84
+ },
85
+ "preview": {
86
+ "type": "object",
87
+ "properties": {
88
+ "mode": {
89
+ "type": "string",
90
+ "enum": [
91
+ "off",
92
+ "auto",
93
+ "on"
94
+ ]
95
+ },
96
+ "protocol": {
97
+ "type": "string",
98
+ "enum": [
99
+ "auto",
100
+ "kitty"
101
+ ]
102
+ },
103
+ "width": {
104
+ "type": "integer",
105
+ "minimum": 1,
106
+ "maximum": 9007199254740991
107
+ }
108
+ },
109
+ "additionalProperties": false
110
+ },
111
+ "secrets": {
112
+ "type": "object",
113
+ "properties": {
114
+ "openai": {
115
+ "type": "string",
116
+ "minLength": 1
117
+ },
118
+ "google": {
119
+ "type": "string",
120
+ "minLength": 1
121
+ },
122
+ "fal": {
123
+ "type": "string",
124
+ "minLength": 1
125
+ }
126
+ },
127
+ "additionalProperties": false
128
+ },
129
+ "schemaVersion": {
130
+ "type": "number",
131
+ "const": 1
132
+ }
133
+ },
134
+ "additionalProperties": false
135
+ }
136
+ },
137
+ "required": [
138
+ "aiImg"
139
+ ],
140
+ "additionalProperties": false,
141
+ "$id": "https://ai-img.dev/schemas/ai-img.schema.json"
142
+ }