CLI for sending a prompt + image to an OpenRouter vision model.
Named after the Ancient Greek word “eikōn” (εἰκών), meaning “image,” “likeness,” or “icon.”
- Bun
- OpenRouter API key via one of:
OPENROUTER_API_KEY(env)--api-key-file <path>--api-key-stdin- config file (
eikon config init)
- OpenRouter provisioning key for admin endpoints:
OPENROUTER_PROVISIONING_KEY(env)eikon openrouter <subcommand> --api-key <key>
Published package:
bunx @vforsh/eikon --help
npx @vforsh/eikon --helpGlobal install:
bun add -g @vforsh/eikon
npm install -g @vforsh/eikoneikon is a Bun CLI. bunx works directly. npx also works, but Bun still must be installed and available on PATH because the package binary uses #!/usr/bin/env bun.
The npm package is scoped as @vforsh/eikon. The installed executable is still eikon.
bun install
bun linkeikon <command> [options]
Commands:
analyze Analyze an image with a prompt/preset (default command)
analyze:local Show local image information (no LLM)
upscale:local Upscale an image locally via sharp
save Save an image from piped dataURL or --input file
placeholder Generate a placeholder image with background and text
compose Layer images in order with opacity and blend modes
presets List/show prompt presets
config Manage config (init/show/path)
openrouter OpenRouter provisioning endpoints
atlas Sprite atlas operations
transform Image transformation operations
fx Visual effects (shadow, inner-shadow, outline, glow, blur, tint)
adjust Image adjustments (brightness, contrast, saturation, vibrance)
inpaint-mask Generate an inpainting mask (white=inpaint, black=keep)
describe Describe a command as machine-readable JSON
help Show help for a command# Help
eikon --help
eikon help analyze
eikon help analyze --json
eikon describe atlas split
# Analyze (explicit)
eikon analyze ./image.png "Describe the UI"
# Analyze (default command; same as `eikon analyze`)
eikon ./image.png --preset web-ui
# Use the built-in layout-only web UI preset (no prompt required)
eikon ./image.png --preset web-ui-layout
# Use a different model
eikon ./image.png "Summarize" --model google/gemini-2.5-flash
# Write output to a file (still prints to stdout; add --quiet to suppress stdout)
eikon ./image.png "List objects" --output result.txt
eikon ./image.png "List objects" --output result.txt --quiet
# JSON output
eikon ./image.png "Extract labels" --json
# Downsize image before upload (defaults to max 2048x2048)
eikon ./image.png --preset web-ui --downsize
# Downsize by max width/height in pixels (preserves aspect ratio, no upscaling)
eikon ./image.png --preset web-ui --max-width 1600 --max-height 1200
# Downsize by multiplier (relative to original dimensions)
eikon ./image.png --preset web-ui --max-width x0.5
# API key via file/stdin
eikon ./image.png --preset web-ui --api-key-file ./openrouter.key
cat ./openrouter.key | eikon ./image.png --preset web-ui --api-key-stdin
# Prompt via stdin
cat prompt.txt | eikon ./image.png --preset web-ui --prompt-stdin
# Get local image info (no LLM)
eikon analyze:local ./image.png
eikon analyze:local ./image.png --plain
eikon analyze:local ./image.png --json
# Upscale locally via sharp
eikon upscale:local ./image.png --out ./image@2x.png
eikon upscale:local ./image.png --out ./image@2x.png --height 2400 --plain
# Create a placeholder image
eikon placeholder --w 1200 --h 630 --bg-color "#111827" --out placeholder.png
# Compose layers
eikon compose --layer base.png --layer overlay.png:0.5:multiply --out result.png
# Atlas operations
eikon atlas split spritesheet.png --out ./sprites/
eikon atlas split spritesheet.png --atlas-json sprites.json --out ./sprites/
eikon atlas create ./sprites/ --out atlas.png
# Transform images
eikon transform rotate ./image.png --angle 90 --out rotated.png
eikon transform pad ./image.png --all 32 --out padded.png
# Add local image effects
eikon fx shadow ./sprite.png --out ./sprite-shadow.png
eikon fx inner-shadow ./button.png --color "#5b3413" --blur 6 --dy 3 --opacity 0.6 --out ./button-inset.png
eikon fx glow ./icon.png --color "#ffd54a" --blur 12 --out ./icon-glow.png
# Adjust images
eikon adjust brightness ./photo.png --factor 1.2 --out ./bright.png
eikon adjust vibrance ./photo.png --amount 0.8 --out ./vibrant.png
# Generate inpainting masks
eikon inpaint-mask ./photo.png --region "left:48" --out ./mask.png
# Save an image from piped Argus/Playwright/etc dataURL output
# This extracts the base64 payload, decodes it, and writes the bytes to a file.
# Useful for saving screenshots from CI/E2E tools that output dataURLs.
argus eval ... | eikon save --out screenshot.png
eikon save --input dataurl.txt --out screenshot.png
eikon save --input dataurl.txt --out screenshot.png --force
eikon save --input dataurl.txt --out screenshot.png --json
# OpenRouter provisioning endpoints (requires provisioning key)
eikon openrouter keys --api-key "$OPENROUTER_PROVISIONING_KEY"
eikon openrouter guardrails --json- stdout: primary output (result)
- stderr: diagnostics/errors (never required to parse for success)
Output modes are mutually exclusive:
- Default (human): prints a human-readable response (for
analyze, this is the model response text) --plain: stable, line-oriented output--json: stable JSON object
If --output <file> is provided, the result is written to the file and also printed to stdout (unless --quiet is set).
{
"ok": true,
"command": "analyze",
"text": "…model response…",
"meta": {
"model": "google/gemini-3-flash-preview",
"preset": "web-ui",
"image": {
"path": "/abs/path.png",
"mime": "image/png",
"original": { "width": 3168, "height": 2774 },
"processed": { "width": 2048, "height": 1793, "resized": true }
},
"timingMs": { "total": 1234, "uploadPrep": 120, "request": 1010 }
}
}Every JSON success response includes:
ok: truecommand: canonical command path, such asanalyze,atlas split, orconfig show- command-specific fields alongside
okandcommand
Every JSON error response uses:
{
"ok": false,
"error": {
"type": "usage",
"code": 2,
"message": "Human-readable error message",
"hints": []
}
}# Machine-readable help for the whole CLI
eikon help --json
# Machine-readable help for a specific command
eikon help analyze --json
eikon help atlas split --json
# Structured command description for agents
eikon describe analyze
eikon describe atlas splithelp --json and describe return command metadata including:
- positional arguments
- options and whether they require values
- aliases
- subcommands
- the canonical JSON success/error envelope shape
--downsize: downsizes to fit within 2048x2048 before upload.--max-width/--max-height: downsizes to fit within the given limits. Each accepts either:- pixels (e.g.
1600) - multipliers (e.g.
x0.5,x0.25)
- pixels (e.g.
- If the image is already within limits, no resize/re-encode is performed.
eikon upscale:local: resize images locally via Sharpeikon placeholder: generate placeholder images with text, gradients, and maskseikon compose: layer multiple images with opacity, blend modes, and offsetseikon atlas split|extract|create: split sprite sheets, extract frames, and build atlasesatlas split --atlas-json <file>: use TexturePacker JSON as inputatlas extract --atlas-json <file>: use TexturePacker JSON as inputatlas create --no-metadata: skip sidecar TexturePacker JSON generation
eikon transform rotate|flip|crop|pad|trim|mask|shift: geometry and canvas operationseikon fx shadow|inner-shadow|outline|glow|blur|tint: visual effectseikon adjust brightness|contrast|saturation|vibrance: image adjustmentseikon inpaint-mask: generate black/white masks for inpainting workflows
0: success1: external API error (OpenRouter admin endpoints)2: usage / validation error3: configuration error4: authentication error (missing/invalid API key)5: filesystem error (missing/unreadable image)6: dependency error (optional dependency missing)7: network/API error8: unexpected internal error
bun test
bun run test:e2eOPENROUTER_API_KEY: API key (can be overridden by--api-key-file/--api-key-stdin)OPENROUTER_PROVISIONING_KEY: provisioning key foropenroutersubcommandsOPENROUTER_MODEL: default model if--modelis not setEIKON_TIMEOUT_MS: default timeout (ms)NO_COLOR: disable color output
Run:
eikon config initThis creates ~/.config/eikon/config.toml.
Supported keys:
apiKey = "sk-or-v1-..."
model = "google/gemini-3-flash-preview"
analyzeModel = "google/gemini-3-flash-preview"
timeoutMs = 30000Precedence: flags > env > config.
Notes:
analyzeModeloverridesmodelforanalyze.