@flatkey-ai/cli 0.1.5 → 0.1.6
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/README.md +27 -1
- package/package.json +5 -1
- package/src/api.js +20 -1
- package/src/cli.js +43 -1
- package/src/config.js +3 -3
- package/src/help.js +144 -3
- package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -50
- package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -34
- package/.github/pull_request_template.md +0 -13
- package/.github/workflows/npm-publish.yml +0 -36
- package/CONTRIBUTING.md +0 -37
- package/SECURITY.md +0 -13
- package/docs/superpowers/plans/2026-07-17-flatkey-cli.md +0 -90
- package/docs/superpowers/specs/2026-07-17-flatkey-cli-design.md +0 -209
- package/flatkey-output/audio-01.mp3 +0 -1
- package/release/deb/README.md +0 -16
- package/release/homebrew/flatkey.rb +0 -16
- package/release/msi/README.md +0 -15
- package/test/animation.test.js +0 -30
- package/test/api.test.js +0 -282
- package/test/artifacts.test.js +0 -108
- package/test/cli.test.js +0 -143
- package/test/config.test.js +0 -62
- package/test/help.test.js +0 -33
- package/test/integration.test.js +0 -274
- package/test/live-flatkey.test.js +0 -121
- package/test/models.test.js +0 -56
- package/test/package.test.js +0 -29
package/README.md
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
Creative generation from the terminal for media teams and AI agents. Generate images, videos, audio, and text through one Flatkey credit balance.
|
|
9
9
|
|
|
10
|
+
Languages: [English](README.md) | [简体中文](docs/readme/README.zh-CN.md) | [日本語](docs/readme/README.ja-JP.md)
|
|
11
|
+
|
|
10
12
|
Website: [flatkey.ai](https://flatkey.ai/?utm_source=github&utm_medium=readme&utm_campaign=flatkey_cli)
|
|
11
13
|
|
|
12
14
|
```bash
|
|
@@ -29,6 +31,21 @@ flatkey credits --json
|
|
|
29
31
|
- Cross-platform npm package for macOS, Linux, and Windows.
|
|
30
32
|
- Cool terminal progress animation for human runs; disabled in `--json` mode.
|
|
31
33
|
|
|
34
|
+
## Product Comparison
|
|
35
|
+
|
|
36
|
+
Flatkey is built for media teams that want programmatic generation without paying a premium for a closed creative suite or waiting in long queues. Higgsfield is strong for creator-facing workflows, and Dreamina/Jimeng has good ByteDance video models, but both can become expensive or slow once the workflow moves from manual creation to repeated AI-agent testing. In our testing, Dreamina/Jimeng video generation can wait up to 5 hours during peak time, which makes one-by-one prompt iteration impractical.
|
|
37
|
+
|
|
38
|
+
| Need | Flatkey | Higgsfield | Dreamina / Jimeng |
|
|
39
|
+
| --- | --- | --- | --- |
|
|
40
|
+
| Cost for repeat testing | Flatkey token pricing is at least ~20% lower than comparable retail routes, and some modalities such as image can be ~40% lower. | Credit packages can be expensive once premium video/image models are used heavily. | Subscription credits can be cheaper in some local workflows, but API-style automation usually has plan and region constraints. |
|
|
41
|
+
| Programmatic access | First-class CLI and API-router workflow. Designed for agents, scripts, and batch testing. | Strong product UI for creators; CLI-style automation is not the primary product promise. | CLI/API access is gated behind higher-tier setup in many workflows, not the default creator entry path. |
|
|
42
|
+
| Queue / iteration speed | Built for fast CLI retries, `--dry-run`, local outputs, and unified model routing. | Good for polished creator workflows, but heavy credit usage makes broad testing costly. | Peak-time queues can block video iteration; we have observed waits up to 5 hours for a single video generation test. |
|
|
43
|
+
| Modalities | Image, video, TTS, SFX, music, text, credits, status, and model discovery behind one Flatkey key. | Strong image/video creator stack and media tooling. | Strong ByteDance image/video models, especially Seedance/Dreamina-style workflows. |
|
|
44
|
+
| Agent ergonomics | `--json`, `--output/-o`, `--dry-run`, `models`, `audio voices`, and predictable stdout/stderr. | More oriented around human creative workflows. | More oriented around app/product workflow than simple agent protocol. |
|
|
45
|
+
| Best fit | Media teams building repeatable generation pipelines and AI-agent workflows. | Creators who want a polished visual production suite. | Teams already deep in CapCut/Dreamina/Jimeng ecosystem and willing to accept plan/queue tradeoffs. |
|
|
46
|
+
|
|
47
|
+
In short: use Flatkey when the job is repeated media generation, cost-sensitive testing, and AI-agent automation. Use creator suites when you want their native editing UI more than a programmable router.
|
|
48
|
+
|
|
32
49
|
## Install
|
|
33
50
|
|
|
34
51
|
```bash
|
|
@@ -62,7 +79,7 @@ Or save it locally:
|
|
|
62
79
|
flatkey onboard --api-key <key>
|
|
63
80
|
```
|
|
64
81
|
|
|
65
|
-
|
|
82
|
+
Create a key at [console.flatkey.ai/keys](https://console.flatkey.ai/keys), then pass it with `--api-key`.
|
|
66
83
|
|
|
67
84
|
## Commands
|
|
68
85
|
|
|
@@ -81,9 +98,14 @@ flatkey image generate \
|
|
|
81
98
|
flatkey video generate \
|
|
82
99
|
--prompt "8 second cinematic product reveal, glossy black background" \
|
|
83
100
|
--model seedance2 \
|
|
101
|
+
--ratio 16:9 \
|
|
102
|
+
--resolution 720p \
|
|
84
103
|
-o launch.mp4
|
|
85
104
|
```
|
|
86
105
|
|
|
106
|
+
Video ratios: `16:9`, `9:16`, `4:3`, `3:4`, `21:9`, `1:1`.
|
|
107
|
+
Video resolutions: `480p`, `720p`, `1080p`.
|
|
108
|
+
|
|
87
109
|
### Generate Audio
|
|
88
110
|
|
|
89
111
|
Text to speech:
|
|
@@ -222,6 +244,10 @@ npm test
|
|
|
222
244
|
node bin/flatkey.js --version
|
|
223
245
|
```
|
|
224
246
|
|
|
247
|
+
## Star History
|
|
248
|
+
|
|
249
|
+
[](https://www.star-history.com/#flatkey-ai/flatkey-cli&Date)
|
|
250
|
+
|
|
225
251
|
## Links
|
|
226
252
|
|
|
227
253
|
- Website: [flatkey.ai](https://flatkey.ai/?utm_source=github&utm_medium=readme&utm_campaign=flatkey_cli_links)
|
package/package.json
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flatkey-ai/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Flatkey media generation CLI for image, video, audio, credits, status, and models.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"flatkey": "bin/flatkey.js"
|
|
8
8
|
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"src"
|
|
12
|
+
],
|
|
9
13
|
"scripts": {
|
|
10
14
|
"test": "node --test"
|
|
11
15
|
},
|
package/src/api.js
CHANGED
|
@@ -43,11 +43,24 @@ export function generateVideo(options) {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
export function planVideoRequest(options) {
|
|
46
|
+
const ratio = validateOptionalValue(
|
|
47
|
+
optionValue(options, "ratio", "aspect"),
|
|
48
|
+
["16:9", "9:16", "4:3", "3:4", "21:9", "1:1"],
|
|
49
|
+
"ratio",
|
|
50
|
+
);
|
|
51
|
+
const resolution = validateOptionalValue(
|
|
52
|
+
options.resolution,
|
|
53
|
+
["480p", "720p", "1080p"],
|
|
54
|
+
"resolution",
|
|
55
|
+
);
|
|
46
56
|
return planJsonPost(options, "/v1/video/generations", cleanObject({
|
|
47
57
|
model: options.model ?? "veo-3",
|
|
48
58
|
prompt: options.prompt,
|
|
49
59
|
duration: parseOptionalInteger(options.duration),
|
|
50
|
-
aspect:
|
|
60
|
+
aspect: ratio,
|
|
61
|
+
ratio,
|
|
62
|
+
resolution,
|
|
63
|
+
quality: resolution,
|
|
51
64
|
fps: parseOptionalInteger(options.fps),
|
|
52
65
|
}));
|
|
53
66
|
}
|
|
@@ -223,6 +236,12 @@ function optionValue(options, ...keys) {
|
|
|
223
236
|
return undefined;
|
|
224
237
|
}
|
|
225
238
|
|
|
239
|
+
function validateOptionalValue(value, allowed, name) {
|
|
240
|
+
if (value === undefined) return undefined;
|
|
241
|
+
if (allowed.includes(value)) return value;
|
|
242
|
+
throw new Error(`Invalid ${name}: ${value}. Allowed values: ${allowed.join(", ")}`);
|
|
243
|
+
}
|
|
244
|
+
|
|
226
245
|
function cleanObject(value) {
|
|
227
246
|
return Object.fromEntries(
|
|
228
247
|
Object.entries(value).filter(([, entry]) => entry !== undefined),
|
package/src/cli.js
CHANGED
|
@@ -18,16 +18,44 @@ export function parseArgv(argv) {
|
|
|
18
18
|
if (!group) {
|
|
19
19
|
return { group: "help", action: undefined, options: {} };
|
|
20
20
|
}
|
|
21
|
+
if (group === "--help" || group === "-h") {
|
|
22
|
+
return { group: "help", action: undefined, options: {} };
|
|
23
|
+
}
|
|
21
24
|
if (group === "--version" || group === "-v") {
|
|
22
25
|
return { group: "version", action: undefined, options: {} };
|
|
23
26
|
}
|
|
24
27
|
if (!COMMANDS.has(group)) {
|
|
25
28
|
throw new Error(`Unknown command: ${group}`);
|
|
26
29
|
}
|
|
30
|
+
if (group === "help" && maybeAction && !maybeAction.startsWith("--")) {
|
|
31
|
+
return {
|
|
32
|
+
group: "help",
|
|
33
|
+
action: undefined,
|
|
34
|
+
options: { command: maybeAction, ...parseOptions(rest) },
|
|
35
|
+
};
|
|
36
|
+
}
|
|
27
37
|
|
|
28
38
|
const hasAction = GROUP_ACTIONS.has(group);
|
|
39
|
+
if (hasAction && isHelpToken(maybeAction)) {
|
|
40
|
+
return { group, action: undefined, options: { help: true } };
|
|
41
|
+
}
|
|
42
|
+
if (!hasAction && isHelpToken(maybeAction)) {
|
|
43
|
+
return { group, action: undefined, options: { help: true } };
|
|
44
|
+
}
|
|
29
45
|
const action = hasAction ? maybeAction : undefined;
|
|
30
46
|
const optionTokens = hasAction ? rest : argv.slice(1);
|
|
47
|
+
const hasHelpOption = optionTokens.some((token) => token === "--help" || token === "-h")
|
|
48
|
+
|| (optionTokens.length === 1 && optionTokens[0] === "help");
|
|
49
|
+
if (hasHelpOption) {
|
|
50
|
+
return {
|
|
51
|
+
group,
|
|
52
|
+
action,
|
|
53
|
+
options: {
|
|
54
|
+
...parseOptions(optionTokens.filter((token) => token !== "help" && token !== "--help" && token !== "-h")),
|
|
55
|
+
help: true,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
31
59
|
|
|
32
60
|
return {
|
|
33
61
|
group,
|
|
@@ -36,6 +64,10 @@ export function parseArgv(argv) {
|
|
|
36
64
|
};
|
|
37
65
|
}
|
|
38
66
|
|
|
67
|
+
function isHelpToken(token) {
|
|
68
|
+
return token === "help" || token === "--help" || token === "-h";
|
|
69
|
+
}
|
|
70
|
+
|
|
39
71
|
function parseOptions(tokens) {
|
|
40
72
|
const options = {};
|
|
41
73
|
for (let index = 0; index < tokens.length; index += 1) {
|
|
@@ -66,6 +98,11 @@ function parseOptions(tokens) {
|
|
|
66
98
|
|
|
67
99
|
export async function main(argv) {
|
|
68
100
|
const command = parseArgv(argv);
|
|
101
|
+
if (command.options.help) {
|
|
102
|
+
const result = await runCommand(command);
|
|
103
|
+
process.stdout.write(`${formatHuman(result)}\n`);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
69
106
|
if (command.group === "onboard") {
|
|
70
107
|
const { writeConfig } = await import("./config.js");
|
|
71
108
|
const configPath = await writeConfig({ apiKey: command.options.api_key });
|
|
@@ -86,9 +123,14 @@ export async function runCommand(command, deps = {}) {
|
|
|
86
123
|
const stderr = deps.stderr ?? process.stderr;
|
|
87
124
|
|
|
88
125
|
if (command.group === "help") {
|
|
89
|
-
const { getAiHelp, getHumanHelp } = await import("./help.js");
|
|
126
|
+
const { getAiHelp, getCommandHelp, getHumanHelp } = await import("./help.js");
|
|
127
|
+
if (command.options.command) return getCommandHelp(command.options.command);
|
|
90
128
|
return command.options.ai ? getAiHelp() : getHumanHelp();
|
|
91
129
|
}
|
|
130
|
+
if (command.options.help) {
|
|
131
|
+
const { getCommandHelp } = await import("./help.js");
|
|
132
|
+
return getCommandHelp(command.group, command.action);
|
|
133
|
+
}
|
|
92
134
|
if (command.group === "version") {
|
|
93
135
|
const version = await readPackageVersion();
|
|
94
136
|
return command.options.json ? { version } : version;
|
package/src/config.js
CHANGED
|
@@ -22,13 +22,13 @@ export async function resolveApiKey({
|
|
|
22
22
|
if (saved?.apiKey) return saved.apiKey;
|
|
23
23
|
|
|
24
24
|
throw new Error(
|
|
25
|
-
"Missing Flatkey API key.
|
|
25
|
+
"Missing Flatkey API key. Create one at https://console.flatkey.ai/keys, then run `flatkey onboard --api-key <key>` or set FLATKEY_API_KEY.",
|
|
26
26
|
);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export async function writeConfig({ apiKey, configDir = getDefaultConfigDir() }) {
|
|
30
|
-
if (
|
|
31
|
-
throw new Error("Missing --api-key value.");
|
|
30
|
+
if (typeof apiKey !== "string" || apiKey.trim() === "") {
|
|
31
|
+
throw new Error("Missing --api-key value. Create a key at https://console.flatkey.ai/keys, then run `flatkey onboard --api-key <key>`.");
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
await mkdir(configDir, { recursive: true });
|
package/src/help.js
CHANGED
|
@@ -3,6 +3,7 @@ export function getAiHelp() {
|
|
|
3
3
|
|
|
4
4
|
Setup:
|
|
5
5
|
- Prefer env: FLATKEY_API_KEY=<key>
|
|
6
|
+
- Create a key at https://console.flatkey.ai/keys
|
|
6
7
|
- Or save key: flatkey onboard --api-key <key>
|
|
7
8
|
- Use --json for machine-readable output.
|
|
8
9
|
|
|
@@ -13,7 +14,7 @@ JSON mode:
|
|
|
13
14
|
|
|
14
15
|
Commands:
|
|
15
16
|
- flatkey image generate --prompt "<prompt>" --json [--model <model>] [--output image.png]
|
|
16
|
-
- flatkey video generate --prompt "<prompt>" --json [--model seedance2] [--output video.mp4]
|
|
17
|
+
- flatkey video generate --prompt "<prompt>" --json [--model seedance2] [--ratio 16:9] [--resolution 720p] [--output video.mp4]
|
|
17
18
|
- flatkey audio generate --prompt "<text>" --json [--voice-id <voice_id>] [--model eleven_multilingual_v2] [--output speech.mp3]
|
|
18
19
|
- flatkey audio sfx --prompt "<sound>" --json [--duration <seconds>] [--output sfx.mp3]
|
|
19
20
|
- flatkey audio music --prompt "<music prompt>" --json [--music-length-ms <ms>] [--output music.mp3]
|
|
@@ -29,7 +30,7 @@ Environment:
|
|
|
29
30
|
- Default router: https://router.flatkey.ai
|
|
30
31
|
|
|
31
32
|
Recovery:
|
|
32
|
-
- Missing key: run flatkey onboard --api-key <key> or set FLATKEY_API_KEY.
|
|
33
|
+
- Missing key: create one at https://console.flatkey.ai/keys, then run flatkey onboard --api-key <key> or set FLATKEY_API_KEY.
|
|
33
34
|
- Unknown model: run flatkey models --json, then retry with a listed model id.
|
|
34
35
|
- Unknown voice: run flatkey audio voices --json, then retry with a listed voice_id.
|
|
35
36
|
- API failure: inspect stderr JSON or HTTP message, then retry only after fixing request or credits.
|
|
@@ -40,7 +41,7 @@ export function getHumanHelp() {
|
|
|
40
41
|
return `Usage: flatkey <command> [options]
|
|
41
42
|
|
|
42
43
|
Commands:
|
|
43
|
-
onboard --api-key <key> Save Flatkey API key
|
|
44
|
+
onboard --api-key <key> Save Flatkey API key from https://console.flatkey.ai/keys
|
|
44
45
|
image generate --prompt <txt> Generate image
|
|
45
46
|
video generate --prompt <txt> Generate video
|
|
46
47
|
audio generate --prompt <txt> Generate speech with ElevenLabs voices
|
|
@@ -57,5 +58,145 @@ Global options:
|
|
|
57
58
|
--json Print machine-readable JSON
|
|
58
59
|
--output, -o <file> Write generated output to a local file
|
|
59
60
|
--base-url <url> Override Flatkey router URL
|
|
61
|
+
|
|
62
|
+
Video options:
|
|
63
|
+
--ratio <value> 16:9, 9:16, 4:3, 3:4, 21:9, or 1:1
|
|
64
|
+
--resolution <value> 480p, 720p, or 1080p
|
|
60
65
|
`;
|
|
61
66
|
}
|
|
67
|
+
|
|
68
|
+
const COMMAND_HELP = {
|
|
69
|
+
audio: `Usage: flatkey audio <action> [options]
|
|
70
|
+
|
|
71
|
+
Actions:
|
|
72
|
+
generate --prompt <txt> Generate speech
|
|
73
|
+
sfx --prompt <txt> Generate sound effects
|
|
74
|
+
music --prompt <txt> Generate music
|
|
75
|
+
voices List available voices
|
|
76
|
+
|
|
77
|
+
Options:
|
|
78
|
+
--json Print machine-readable JSON
|
|
79
|
+
--output, -o <file> Write generated output to a local file
|
|
80
|
+
--model <model> Override model id
|
|
81
|
+
--voice-id <voice_id> Voice id for speech generation
|
|
82
|
+
--duration <seconds> Duration for sound effects
|
|
83
|
+
--music-length-ms <ms> Music length in milliseconds
|
|
84
|
+
--help Show audio help`,
|
|
85
|
+
"audio generate": `Usage: flatkey audio generate --prompt <txt> [options]
|
|
86
|
+
|
|
87
|
+
Options:
|
|
88
|
+
--voice-id <voice_id> Voice id
|
|
89
|
+
--model <model> Model id, default eleven_multilingual_v2
|
|
90
|
+
--stability <0..1> Voice stability
|
|
91
|
+
--similarity-boost <0..1> Voice similarity boost
|
|
92
|
+
--style <0..1> Voice style
|
|
93
|
+
--output, -o <file> Write speech file
|
|
94
|
+
--json Print machine-readable JSON`,
|
|
95
|
+
"audio music": `Usage: flatkey audio music --prompt <txt> [options]
|
|
96
|
+
|
|
97
|
+
Options:
|
|
98
|
+
--music-length-ms <ms> Music length in milliseconds
|
|
99
|
+
--output, -o <file> Write music file
|
|
100
|
+
--json Print machine-readable JSON`,
|
|
101
|
+
"audio sfx": `Usage: flatkey audio sfx --prompt <txt> [options]
|
|
102
|
+
|
|
103
|
+
Options:
|
|
104
|
+
--duration <seconds> Sound effect duration
|
|
105
|
+
--output, -o <file> Write sound effect file
|
|
106
|
+
--json Print machine-readable JSON`,
|
|
107
|
+
"audio voices": `Usage: flatkey audio voices [options]
|
|
108
|
+
|
|
109
|
+
Options:
|
|
110
|
+
--json Print machine-readable JSON`,
|
|
111
|
+
credits: `Usage: flatkey credits [options]
|
|
112
|
+
|
|
113
|
+
Options:
|
|
114
|
+
--json Print machine-readable JSON`,
|
|
115
|
+
help: `Usage: flatkey help [command] [options]
|
|
116
|
+
|
|
117
|
+
Options:
|
|
118
|
+
--ai Print agent-focused usage guide`,
|
|
119
|
+
image: `Usage: flatkey image generate --prompt <txt> [options]
|
|
120
|
+
|
|
121
|
+
Options:
|
|
122
|
+
--model <model> Model id
|
|
123
|
+
--size <size> Image size for OpenAI-style image models
|
|
124
|
+
--quality <quality> Image quality for supported models
|
|
125
|
+
--n <count> Number of images for supported models
|
|
126
|
+
--output, -o <file> Write image file
|
|
127
|
+
--json Print machine-readable JSON`,
|
|
128
|
+
"image generate": `Usage: flatkey image generate --prompt <txt> [options]
|
|
129
|
+
|
|
130
|
+
Options:
|
|
131
|
+
--model <model> Model id
|
|
132
|
+
--size <size> Image size for OpenAI-style image models
|
|
133
|
+
--quality <quality> Image quality for supported models
|
|
134
|
+
--n <count> Number of images for supported models
|
|
135
|
+
--output, -o <file> Write image file
|
|
136
|
+
--json Print machine-readable JSON`,
|
|
137
|
+
models: `Usage: flatkey models [options]
|
|
138
|
+
|
|
139
|
+
Options:
|
|
140
|
+
--type <type> Filter: image, video, audio, or text
|
|
141
|
+
--json Print machine-readable JSON`,
|
|
142
|
+
onboard: `Usage: flatkey onboard --api-key <key>
|
|
143
|
+
|
|
144
|
+
Create a Flatkey API key first:
|
|
145
|
+
https://console.flatkey.ai/keys
|
|
146
|
+
|
|
147
|
+
Options:
|
|
148
|
+
--api-key <key> Flatkey API key to save`,
|
|
149
|
+
status: `Usage: flatkey status [options]
|
|
150
|
+
|
|
151
|
+
Options:
|
|
152
|
+
--json Print machine-readable JSON`,
|
|
153
|
+
text: `Usage: flatkey text generate --prompt <txt> [options]
|
|
154
|
+
|
|
155
|
+
Options:
|
|
156
|
+
--model <model> Model id, default gpt-5.5
|
|
157
|
+
--output, -o <file> Write text file
|
|
158
|
+
--json Print machine-readable JSON`,
|
|
159
|
+
"text generate": `Usage: flatkey text generate --prompt <txt> [options]
|
|
160
|
+
|
|
161
|
+
Options:
|
|
162
|
+
--model <model> Model id, default gpt-5.5
|
|
163
|
+
--output, -o <file> Write text file
|
|
164
|
+
--json Print machine-readable JSON`,
|
|
165
|
+
version: `Usage: flatkey version [options]
|
|
166
|
+
|
|
167
|
+
Aliases:
|
|
168
|
+
flatkey --version
|
|
169
|
+
flatkey -v
|
|
170
|
+
|
|
171
|
+
Options:
|
|
172
|
+
--json Print machine-readable JSON`,
|
|
173
|
+
video: `Usage: flatkey video generate --prompt <txt> [options]
|
|
174
|
+
|
|
175
|
+
Options:
|
|
176
|
+
--model <model> Model id, default veo-3
|
|
177
|
+
--duration <seconds> Video duration
|
|
178
|
+
--ratio <value> 16:9, 9:16, 4:3, 3:4, 21:9, or 1:1
|
|
179
|
+
--resolution <value> 480p, 720p, or 1080p
|
|
180
|
+
--fps <fps> Frames per second
|
|
181
|
+
--output, -o <file> Write video file
|
|
182
|
+
--json Print machine-readable JSON`,
|
|
183
|
+
"video generate": `Usage: flatkey video generate --prompt <txt> [options]
|
|
184
|
+
|
|
185
|
+
Options:
|
|
186
|
+
--model <model> Model id, default veo-3
|
|
187
|
+
--duration <seconds> Video duration
|
|
188
|
+
--ratio <value> 16:9, 9:16, 4:3, 3:4, 21:9, or 1:1
|
|
189
|
+
--resolution <value> 480p, 720p, or 1080p
|
|
190
|
+
--fps <fps> Frames per second
|
|
191
|
+
--output, -o <file> Write video file
|
|
192
|
+
--json Print machine-readable JSON`,
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
export function getCommandHelp(group, action) {
|
|
196
|
+
const key = action ? `${group} ${action}` : group;
|
|
197
|
+
const help = COMMAND_HELP[key];
|
|
198
|
+
if (!help) {
|
|
199
|
+
throw new Error(`Unknown help topic: ${key}`);
|
|
200
|
+
}
|
|
201
|
+
return help;
|
|
202
|
+
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
name: Bug report
|
|
2
|
-
description: Report a Flatkey CLI bug.
|
|
3
|
-
title: "[Bug]: "
|
|
4
|
-
labels: ["bug"]
|
|
5
|
-
body:
|
|
6
|
-
- type: textarea
|
|
7
|
-
id: summary
|
|
8
|
-
attributes:
|
|
9
|
-
label: Summary
|
|
10
|
-
description: What happened?
|
|
11
|
-
validations:
|
|
12
|
-
required: true
|
|
13
|
-
- type: textarea
|
|
14
|
-
id: command
|
|
15
|
-
attributes:
|
|
16
|
-
label: Command
|
|
17
|
-
description: Paste the command. Redact API keys.
|
|
18
|
-
render: bash
|
|
19
|
-
validations:
|
|
20
|
-
required: true
|
|
21
|
-
- type: textarea
|
|
22
|
-
id: output
|
|
23
|
-
attributes:
|
|
24
|
-
label: Output
|
|
25
|
-
description: Paste relevant stdout/stderr. Redact secrets.
|
|
26
|
-
render: text
|
|
27
|
-
- type: input
|
|
28
|
-
id: version
|
|
29
|
-
attributes:
|
|
30
|
-
label: Version
|
|
31
|
-
description: Run `flatkey --version`.
|
|
32
|
-
placeholder: "0.1.4"
|
|
33
|
-
- type: dropdown
|
|
34
|
-
id: os
|
|
35
|
-
attributes:
|
|
36
|
-
label: OS
|
|
37
|
-
options:
|
|
38
|
-
- macOS
|
|
39
|
-
- Linux
|
|
40
|
-
- Windows
|
|
41
|
-
- Other
|
|
42
|
-
- type: checkboxes
|
|
43
|
-
id: checks
|
|
44
|
-
attributes:
|
|
45
|
-
label: Checks
|
|
46
|
-
options:
|
|
47
|
-
- label: I removed API keys and secrets from this report.
|
|
48
|
-
required: true
|
|
49
|
-
- label: I tried the command again with `--dry-run` when applicable.
|
|
50
|
-
required: false
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
name: Feature request
|
|
2
|
-
description: Request a Flatkey CLI feature.
|
|
3
|
-
title: "[Feature]: "
|
|
4
|
-
labels: ["enhancement"]
|
|
5
|
-
body:
|
|
6
|
-
- type: textarea
|
|
7
|
-
id: problem
|
|
8
|
-
attributes:
|
|
9
|
-
label: Problem
|
|
10
|
-
description: What workflow should be easier?
|
|
11
|
-
validations:
|
|
12
|
-
required: true
|
|
13
|
-
- type: textarea
|
|
14
|
-
id: proposal
|
|
15
|
-
attributes:
|
|
16
|
-
label: Proposal
|
|
17
|
-
description: What command or behavior do you want?
|
|
18
|
-
render: bash
|
|
19
|
-
validations:
|
|
20
|
-
required: true
|
|
21
|
-
- type: dropdown
|
|
22
|
-
id: area
|
|
23
|
-
attributes:
|
|
24
|
-
label: Area
|
|
25
|
-
options:
|
|
26
|
-
- image
|
|
27
|
-
- video
|
|
28
|
-
- audio
|
|
29
|
-
- text
|
|
30
|
-
- models
|
|
31
|
-
- credits/status
|
|
32
|
-
- packaging
|
|
33
|
-
- docs
|
|
34
|
-
- other
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
name: Publish npm
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_dispatch:
|
|
5
|
-
push:
|
|
6
|
-
tags:
|
|
7
|
-
- "v*"
|
|
8
|
-
|
|
9
|
-
permissions:
|
|
10
|
-
contents: read
|
|
11
|
-
|
|
12
|
-
jobs:
|
|
13
|
-
publish:
|
|
14
|
-
name: Publish @flatkey-ai/cli
|
|
15
|
-
runs-on: ubuntu-latest
|
|
16
|
-
|
|
17
|
-
steps:
|
|
18
|
-
- name: Checkout
|
|
19
|
-
uses: actions/checkout@v4
|
|
20
|
-
|
|
21
|
-
- name: Setup Node
|
|
22
|
-
uses: actions/setup-node@v4
|
|
23
|
-
with:
|
|
24
|
-
node-version: 22
|
|
25
|
-
registry-url: "https://registry.npmjs.org"
|
|
26
|
-
|
|
27
|
-
- name: Install dependencies
|
|
28
|
-
run: npm install
|
|
29
|
-
|
|
30
|
-
- name: Test
|
|
31
|
-
run: npm test
|
|
32
|
-
|
|
33
|
-
- name: Publish
|
|
34
|
-
run: npm publish --access public
|
|
35
|
-
env:
|
|
36
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/CONTRIBUTING.md
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# Contributing
|
|
2
|
-
|
|
3
|
-
Thanks for improving Flatkey CLI.
|
|
4
|
-
|
|
5
|
-
## Setup
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
git clone https://github.com/flatkey-ai/flatkey-cli.git
|
|
9
|
-
cd flatkey-cli
|
|
10
|
-
npm install
|
|
11
|
-
npm test
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
## Local CLI
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
node bin/flatkey.js --version
|
|
18
|
-
node bin/flatkey.js help --ai
|
|
19
|
-
node bin/flatkey.js image generate --prompt "test" --dry-run --json
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## Tests
|
|
23
|
-
|
|
24
|
-
Run all tests before opening a PR:
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
npm test
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
Live tests require `FLATKEY_API_KEY` and can spend credits. Keep routine tests mocked or `--dry-run`.
|
|
31
|
-
|
|
32
|
-
## Pull Requests
|
|
33
|
-
|
|
34
|
-
- Keep changes small and focused.
|
|
35
|
-
- Add or update tests for behavior changes.
|
|
36
|
-
- Do not commit API keys, generated media, or local config.
|
|
37
|
-
- Use `--dry-run` examples when possible.
|
package/SECURITY.md
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# Security
|
|
2
|
-
|
|
3
|
-
## Reporting
|
|
4
|
-
|
|
5
|
-
Please do not open public issues for security vulnerabilities.
|
|
6
|
-
|
|
7
|
-
Report security concerns through Flatkey support at [flatkey.ai](https://flatkey.ai/?utm_source=github&utm_medium=security&utm_campaign=flatkey_cli).
|
|
8
|
-
|
|
9
|
-
## API Keys
|
|
10
|
-
|
|
11
|
-
- Prefer `FLATKEY_API_KEY` for automation.
|
|
12
|
-
- Never commit API keys.
|
|
13
|
-
- Rotate keys if they appear in logs, screenshots, shell history, or public CI.
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
# Flatkey CLI Implementation Plan
|
|
2
|
-
|
|
3
|
-
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
-
|
|
5
|
-
**Goal:** Build `@flatkey-ai/cli`, a Node.js CLI for Flatkey image, video, audio, credits, status, models, onboarding, and AI-first help.
|
|
6
|
-
|
|
7
|
-
**Architecture:** Use small ESM modules with dependency-injected `fetch`, filesystem paths, and streams so behavior can be tested without real Flatkey calls. The CLI parser converts argv into command objects, command handlers call provider functions, and output helpers keep human logs off stdout in JSON mode.
|
|
8
|
-
|
|
9
|
-
**Tech Stack:** Node.js ESM, npm package bin, built-in `node:test`, `assert/strict`, `fs/promises`, `child_process`, and global `fetch`.
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## File Structure
|
|
14
|
-
|
|
15
|
-
- `package.json`: npm metadata, bin mapping, scripts, engines.
|
|
16
|
-
- `bin/flatkey.js`: executable entrypoint.
|
|
17
|
-
- `src/cli.js`: argv parsing, command dispatch, exit handling.
|
|
18
|
-
- `src/config.js`: API key/config resolution and onboarding writes.
|
|
19
|
-
- `src/api.js`: Flatkey HTTP requests and route selection.
|
|
20
|
-
- `src/artifacts.js`: save base64/data URL/url artifacts.
|
|
21
|
-
- `src/help.js`: human and AI help text.
|
|
22
|
-
- `src/models.js`: bundled fallback model list and remote normalization.
|
|
23
|
-
- `src/animation.js`: ASCII animation lifecycle.
|
|
24
|
-
- `test/*.test.js`: focused tests for each module and CLI subprocess behavior.
|
|
25
|
-
|
|
26
|
-
## Task 1: Package and Parser
|
|
27
|
-
|
|
28
|
-
- [ ] Write failing tests in `test/cli.test.js` for `parseArgv`, including `flatkey image generate --prompt x --json`, `flatkey credits --json`, unknown command, and `flatkey help --ai`.
|
|
29
|
-
- [ ] Run `npm test -- test/cli.test.js`; expect module-not-found or function-not-found failure.
|
|
30
|
-
- [ ] Create `package.json`, `bin/flatkey.js`, and `src/cli.js` with minimal parser and dispatch stubs.
|
|
31
|
-
- [ ] Run `npm test -- test/cli.test.js`; expect parser tests pass.
|
|
32
|
-
- [ ] Commit: `feat: add cli parser`
|
|
33
|
-
|
|
34
|
-
## Task 2: Config and Onboarding
|
|
35
|
-
|
|
36
|
-
- [ ] Write failing tests in `test/config.test.js` for API key precedence: option, `FLATKEY_API_KEY`, saved config, and missing key error.
|
|
37
|
-
- [ ] Write failing test for `writeConfig` creating config JSON with `apiKey`.
|
|
38
|
-
- [ ] Run `npm test -- test/config.test.js`; expect missing module failure.
|
|
39
|
-
- [ ] Create `src/config.js` and wire `onboard` command to write config.
|
|
40
|
-
- [ ] Run `npm test -- test/config.test.js test/cli.test.js`; expect pass.
|
|
41
|
-
- [ ] Commit: `feat: add flatkey config`
|
|
42
|
-
|
|
43
|
-
## Task 3: API Requests
|
|
44
|
-
|
|
45
|
-
- [ ] Write failing tests in `test/api.test.js` for Nano image route, OpenAI image route, video route, audio route, credits route, status route, and models route using injected fetch.
|
|
46
|
-
- [ ] Run `npm test -- test/api.test.js`; expect missing module failure.
|
|
47
|
-
- [ ] Create `src/api.js` with `FlatkeyError`, `generateImage`, `generateVideo`, `generateAudio`, `getCredits`, `getStatus`, and `getModels`.
|
|
48
|
-
- [ ] Run `npm test -- test/api.test.js`; expect pass.
|
|
49
|
-
- [ ] Commit: `feat: add flatkey api client`
|
|
50
|
-
|
|
51
|
-
## Task 4: Artifacts and Model Fallback
|
|
52
|
-
|
|
53
|
-
- [ ] Write failing tests in `test/artifacts.test.js` for saving base64, data URL, and preserving URL outputs.
|
|
54
|
-
- [ ] Write failing tests in `test/models.test.js` for bundled fallback shape and type filtering.
|
|
55
|
-
- [ ] Run targeted tests; expect missing module failures.
|
|
56
|
-
- [ ] Create `src/artifacts.js` and `src/models.js`.
|
|
57
|
-
- [ ] Run targeted tests; expect pass.
|
|
58
|
-
- [ ] Commit: `feat: add artifact and model helpers`
|
|
59
|
-
|
|
60
|
-
## Task 5: Help and Animation
|
|
61
|
-
|
|
62
|
-
- [ ] Write failing tests in `test/help.test.js` checking `help --ai` includes setup, JSON contract, image/video/audio examples, credits, status, and models.
|
|
63
|
-
- [ ] Write failing tests in `test/animation.test.js` checking no animation when JSON mode or non-TTY.
|
|
64
|
-
- [ ] Run targeted tests; expect missing module failures.
|
|
65
|
-
- [ ] Create `src/help.js` and `src/animation.js`.
|
|
66
|
-
- [ ] Run targeted tests; expect pass.
|
|
67
|
-
- [ ] Commit: `feat: add help and animation`
|
|
68
|
-
|
|
69
|
-
## Task 6: Command Integration
|
|
70
|
-
|
|
71
|
-
- [ ] Write failing subprocess tests in `test/integration.test.js` with a local HTTP server for `image generate --json`, `video generate --json`, `audio generate --json`, `credits --json`, `status --json`, and `models --json`.
|
|
72
|
-
- [ ] Run `npm test -- test/integration.test.js`; expect command behavior missing.
|
|
73
|
-
- [ ] Wire command handlers in `src/cli.js` to config, API, artifacts, models, help, and animation.
|
|
74
|
-
- [ ] Run `npm test`; expect pass.
|
|
75
|
-
- [ ] Commit: `feat: wire flatkey cli commands`
|
|
76
|
-
|
|
77
|
-
## Task 7: Release Metadata
|
|
78
|
-
|
|
79
|
-
- [ ] Write failing tests or static checks for package name `@flatkey-ai/cli`, bin `flatkey`, and executable bin file.
|
|
80
|
-
- [ ] Add `README.md` with install, auth, commands, and release channel notes.
|
|
81
|
-
- [ ] Add `release/homebrew/flatkey.rb`, `release/deb/README.md`, and `release/msi/README.md` as packaging stubs that wrap npm package release.
|
|
82
|
-
- [ ] Run `npm test`.
|
|
83
|
-
- [ ] Commit: `docs: add release notes`
|
|
84
|
-
|
|
85
|
-
## Final Verification
|
|
86
|
-
|
|
87
|
-
- [ ] Run `npm test`.
|
|
88
|
-
- [ ] Run `node bin/flatkey.js help --ai`.
|
|
89
|
-
- [ ] Run `node bin/flatkey.js models --json` without network key and confirm bundled fallback.
|
|
90
|
-
- [ ] Run `git status --short`.
|