Files
valknar f24d138ab4 feat: initial Freepik AI CLI
Sophisticated Python CLI for generating and manipulating images and
video via the Freepik API, built with typer + rich.

Commands:
- generate-image: text-to-image with 8 models (flux-2-pro, mystic, seedream, etc.)
- generate-video: image-to-video with 7 models (kling, minimax, runway, etc.)
- generate-icon: text-to-icon in solid/outline/color/flat/sticker styles
- upscale-image: 3 modes (precision-v2, precision, creative) + 2x/4x scale
- upscale-video: standard/turbo modes
- expand-image: outpainting with per-side pixel offsets
- relight: AI-controlled relighting (Premium)
- style-transfer: artistic style application (Premium)
- describe-image: reverse-engineer an image into a prompt
- config set/get/show/reset: configuration management

Features: Rich Live polling panel, exponential backoff, --wait/--no-wait,
auto-timestamped output filenames, streaming download with progress bar,
FREEPIK_API_KEY env var support, venv-based setup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 10:56:45 +02:00

124 lines
4.0 KiB
Python

"""Root typer application — command registration and banner."""
from __future__ import annotations
from typing import Annotated, Optional
import typer
from freepik_cli import __version__
from freepik_cli.commands import config as config_cmd
from freepik_cli.commands.analyze import describe_image
from freepik_cli.commands.edit import expand_image, relight_image, style_transfer
from freepik_cli.commands.generate import generate_icon, generate_image, generate_video
from freepik_cli.commands.upscale import upscale_image, upscale_video
from freepik_cli.utils.console import console, print_banner
from freepik_cli.utils.config import FreepikConfig
app = typer.Typer(
name="freepik",
help=(
"[bold magenta]Freepik AI[/bold magenta] — generate images, videos, and more "
"from the command line.\n\n"
"[dim]Set your API key:[/dim] [cyan]export FREEPIK_API_KEY=your_key[/cyan]\n"
"[dim]Get an API key:[/dim] https://www.freepik.com/api"
),
rich_markup_mode="rich",
no_args_is_help=True,
pretty_exceptions_enable=True,
pretty_exceptions_show_locals=False,
pretty_exceptions_short=True,
add_completion=True,
)
# ── Flat commands ──────────────────────────────────────────────────────────────
app.command(
"generate-image",
help="[bold]Generate an image[/bold] from a text prompt using AI models.",
rich_help_panel="Generation",
)(generate_image)
app.command(
"generate-video",
help="[bold]Generate a video[/bold] by animating a source image using AI.",
rich_help_panel="Generation",
)(generate_video)
app.command(
"generate-icon",
help="[bold]Generate an icon[/bold] from a text prompt in various styles.",
rich_help_panel="Generation",
)(generate_icon)
app.command(
"upscale-image",
help="[bold]Upscale and enhance[/bold] an image using AI.",
rich_help_panel="Enhancement",
)(upscale_image)
app.command(
"upscale-video",
help="[bold]Upscale a video[/bold] to higher resolution using AI.",
rich_help_panel="Enhancement",
)(upscale_video)
app.command(
"expand-image",
help="[bold]Expand an image[/bold] by adding new content around its edges (outpainting).",
rich_help_panel="Editing",
)(expand_image)
app.command(
"relight",
help="[bold]Relight an image[/bold] using AI-controlled lighting. [dim](Premium)[/dim]",
rich_help_panel="Editing",
)(relight_image)
app.command(
"style-transfer",
help="[bold]Apply an artistic style[/bold] from one image onto another. [dim](Premium)[/dim]",
rich_help_panel="Editing",
)(style_transfer)
app.command(
"describe-image",
help="[bold]Describe an image[/bold] and generate a text prompt from it.",
rich_help_panel="Analysis",
)(describe_image)
# ── Nested config sub-app ──────────────────────────────────────────────────────
app.add_typer(
config_cmd.app,
rich_help_panel="Settings",
)
# ── Root callback ──────────────────────────────────────────────────────────────
@app.callback(invoke_without_command=True)
def main(
ctx: typer.Context,
version: Annotated[
bool,
typer.Option("--version", "-v", help="Show version and exit", is_eager=True),
] = False,
) -> None:
"""
[bold magenta]Freepik AI[/bold magenta] — generate images, videos, icons, and more.
"""
cfg = FreepikConfig.load()
if version:
print_banner()
console.print(f"[dim]Version:[/dim] [bold]{__version__}[/bold]\n")
raise typer.Exit()
if ctx.invoked_subcommand is None:
if cfg.show_banner:
print_banner()
console.print(ctx.get_help())
elif cfg.show_banner and ctx.invoked_subcommand not in ("config",):
print_banner()