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.
- package/.bunli/commands.gen.ts +171 -0
- package/.bunli/release-state.json +26 -0
- package/README.md +165 -43
- package/ai-img.schema.json +142 -0
- package/dist/highlights-eq9cgrbb.scm +604 -0
- package/dist/highlights-ghv9g403.scm +205 -0
- package/dist/highlights-hk7bwhj4.scm +284 -0
- package/dist/highlights-r812a2qc.scm +150 -0
- package/dist/highlights-x6tmsnaa.scm +115 -0
- package/dist/index.js +1290 -163
- package/dist/index.js.map +80 -24
- package/dist/injections-73j83es3.scm +27 -0
- package/dist/tree-sitter-javascript-nd0q4pe9.wasm +0 -0
- package/dist/tree-sitter-markdown-411r6y9b.wasm +0 -0
- package/dist/tree-sitter-markdown_inline-j5349f42.wasm +0 -0
- package/dist/tree-sitter-typescript-zxjzwt75.wasm +0 -0
- package/dist/tree-sitter-zig-e78zbjpm.wasm +0 -0
- package/package.json +19 -10
|
@@ -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
|
|
3
|
+
AI image generation CLI built with Bun + Bunli + AI SDK.
|
|
4
4
|
|
|
5
|
-
## Install
|
|
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
|
-
|
|
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
|
-
##
|
|
20
|
+
## Install as Agent Skill
|
|
19
21
|
|
|
20
|
-
|
|
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
|
-
|
|
47
|
-
|
|
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
|
-
##
|
|
79
|
+
## Shell Completions
|
|
51
80
|
|
|
52
|
-
|
|
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
|
-
|
|
57
|
-
ai-img generate -p "a sunset" -P google -o sunset.png
|
|
83
|
+
Quick install patterns:
|
|
58
84
|
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
#
|
|
63
|
-
ai-img
|
|
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
|
-
|
|
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
|
|
107
|
+
- Google: `GOOGLE_API_KEY`, `GEMINI_API_KEY`, `GOOGLE_GENERATIVE_AI_API_KEY`
|
|
71
108
|
- Fal: `FAL_API_KEY`
|
|
72
109
|
|
|
73
|
-
##
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
-
|
|
77
|
-
-
|
|
78
|
-
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
-
|
|
91
|
-
|
|
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
|
+
}
|