CLI
Drive Media Moana from your terminal — folders, uploads, presets, AI jobs, and automations, all scriptable
moana is the official command-line interface for Media Moana. It exposes every action you can take in the web app — uploading media, managing folders, running AI jobs, wiring up automations — as a scriptable command you can call from any shell, CI pipeline, or cron job.
If you can do it in the UI, you can do it from the terminal.
Install
npm install -g @moana/cliThis installs a single binary, moana, available globally on your $PATH.
To verify:
moana --version
moana --helpAuthenticate
The CLI authenticates against your Media Moana account using a browser-based OAuth flow. Run:
moana loginWhat happens:
- The CLI starts a temporary callback server on
localhost:3456. - Your default browser opens to the Media Moana login page.
- After you sign in, an API key is issued and posted back to the CLI.
- The key is saved to
~/.moana/config.yml. You're done.
You only need to run login once per machine. The token persists across sessions.
Commands at a glance
| Group | What it manages |
|---|---|
folder | Folder hierarchy — create, list, move, delete |
media | Media files — upload, list, get, rename, move, favorite, publish, trash, restore, purge, clone |
preset | Processing presets (resize, compress, format conversion pipelines) |
ai-presets | AI presets (model + prompt + schema bundles for chat and image generation) |
models | Browse available chat and image AI models |
jobs | Submit and monitor async AI / processing jobs |
automations | Cron and event-triggered pipelines |
Run moana <group> --help for the full list of subcommands, or moana <group> <command> --help for option details.
Folders
Folders are paths like /products/2024/spring. The CLI works with absolute paths, not folder IDs, so commands stay readable.
# Create a nested folder (parents are created automatically)
moana folder create /products/2024/spring
# List the entire folder tree
moana folder list
# Rename or move
moana folder move /products/2024/spring /products/2024/summer
# Delete (trashes all media within — irreversible without restore)
moana folder delete /products/2024 --yesfolder list defaults to a visual tree. Use -o json|yaml|table to switch formats.
Media
Upload
Upload accepts files, folders, or wildcards. When you pass a folder, the local directory structure is preserved under the target.
# Single file into the default upload folder
moana media upload ./photo.jpg
# Whole folder into a target path (preserves nested structure)
moana media upload ./shoot-2024/ -f /products/2024
# Wildcards with concurrency tuning and a MIME filter
moana media upload ./raw/*.{jpg,png} \
-f /inbox \
--concurrency 8 \
--mime-type jpeg png| Option | Purpose |
|---|---|
-f, --folder <path> | Target folder. Defaults to /upload-{timestamp} if omitted. |
-c, --concurrency <n> | Parallel uploads (default 3). Tune up for large batches and fast networks. |
-m, --mime-type <types...> | Skip files whose MIME type isn't in the list. Case-insensitive, accepts both image/jpeg and jpeg. |
The CLI hashes each file, dedupes against your library, stages uploads, and reports a per-file table with timing breakdowns at the end.
List, get, rename
# List with pagination and filtering
moana media list --type all --page 0 --per-page 20
moana media list --type favorite
moana media list --type folder --value <folder-id>
moana media list --type search --value "sunset beach"
# Inspect one
moana media get <media-id>
# Rename
moana media rename <media-id> -n "New Name.jpg"--type accepts all, folder, trash, favorite, published, or search. The --value flag carries the query (folder ID for folder, text for search).
Organize and curate
All bulk commands take one or more media IDs and accept -o json|yaml|table.
# Move into a folder
moana media move <id1> <id2> -f /products/featured
# Favorite / unfavorite
moana media favorite <id1> <id2>
moana media favorite <id1> --off
# Publish to a public URL / unpublish
moana media publish <id1>
moana media publish <id1> --off
# Clone (creates new media with new IDs)
moana media clone <id1> <id2>Delete, restore, purge
The CLI distinguishes between soft delete (move to trash, recoverable) and purge (permanent, irreversible).
# Move to trash
moana media delete <id1> <id2>
# Bring back from trash
moana media restore <id1>
# Permanent delete (asks for confirmation)
moana media purge <id1> <id2>
moana media purge <id1> --yes # skip confirmation
# Empty the trash entirely
moana media purge --empty-trash --yesProcessing presets
Processing presets are deterministic image pipelines — resize, compress, format-convert, and so on. They're the same presets used by the web app's batch flows and by automations.
# List
moana preset list # all
moana preset list -f user # only your custom presets
moana preset list -f builtin # only built-in presets
# Inspect a preset's pipeline
moana preset get builtin-social-instagram-square -o yaml
# Create from inline JSON
moana preset create \
-n "Web Optimize" \
-p '[{"operation":"resize","params":{"width":1600}},{"operation":"webp","params":{"quality":82}}]'
# Or from a file (the -p flag accepts JSON strings or file paths)
moana preset create -n "Web Optimize" -p ./pipelines/web-optimize.json
# Update / clone / delete
moana preset update <slug> -n "Web Optimize v2" -p ./pipelines/web-optimize-v2.json
moana preset clone builtin-social-instagram-square
moana preset delete <slug> --yes
# Bulk
moana preset batch-delete <slug-1> <slug-2>
moana preset import ./presets-export.jsonA pipeline is just an array of { operation, params } objects — see any built-in preset with preset get … -o yaml for a working template.
AI presets
AI presets bundle a model + prompt + parameters + optional JSON schema into a reusable handle. They power both chat and image-generation flows.
# List, filter, inspect
moana ai-presets list -m chat
moana ai-presets list -m ai_image -f user
moana ai-presets get my-product-describer -o yaml
# Create a chat preset with a structured-output schema
moana ai-presets create \
-t "Product Describer" \
--mode chat \
-m google/gemini-2.5-flash \
-p @./prompts/product-describer.md \
--schema ./schemas/product.json \
--tags "ecommerce,seo" \
--description "Generates SEO-friendly product copy from a single image"
# Create an image preset
moana ai-presets create \
-t "Studio Product Shot" \
--mode ai_image \
-m openai/gpt-image-1 \
--params '{"size":"1024x1024","quality":"high"}'
# Update, clone, delete
moana ai-presets update my-product-describer -t "Product Describer v2"
moana ai-presets clone builtin-tagger
moana ai-presets delete my-product-describer --yes
# Import a JSON export from another workspace
moana ai-presets import ./ai-presets-export.jsonLoading prompts and JSON from files
Two conventions worth remembering:
-p, --promptaccepts either a literal string or a file path prefixed with@(e.g.@./prompt.md).--schema,--params,--variablesaccept either a JSON string or a path to a.jsonfile. The CLI auto-detects which.
This makes it easy to keep prompts and schemas under source control and reference them by path.
AI models
Browse the catalogue of models available to your account.
# Chat models (default mode)
moana models list
# Image-generation models, with full pricing details
moana models list -m ai_image
# Pipe to jq for ad-hoc filtering
moana models list -m chat -o json | jq '.[] | select(.support_structured_output)'The table view shows series, ID, modality, context length, supported parameters, and per-million-token (or per-image) pricing.
Jobs
Jobs are the async execution layer behind every AI run. Use them when you want to script work that the UI would normally fire off in the background.
There are four job types:
| Type | What it does |
|---|---|
ai-generate | Text-to-image generation. Outputs N new media items. |
ai-edit | AI edit on existing media (background removal, upscale, style transfer, etc.) |
parse | Run a chat AI preset over media — typically for tagging, captioning, or metadata extraction. |
process | Run a deterministic processing preset (resize, compress, convert) at scale. |
Estimate before submitting
Every job has an estimable credit cost. Always estimate before running large batches.
moana jobs estimate \
--type ai-edit \
--media-ids id1,id2,id3 \
--preset-id builtin-remove-backgroundSubmit
# Generate 4 images from a prompt
moana jobs submit \
--type ai-generate \
--preset-id my-product-shot \
--count 4 \
--target-folder-id <folder-id>
# Process a folder of media through a preset, replacing originals
moana jobs submit \
--type process \
--media-ids id1,id2,id3 \
--preset-id builtin-preset-util-web-optimize \
--mode REPLACE_MEDIA
# Override a preset on the fly with an inline model and prompt
moana jobs submit \
--type parse \
--media-ids id1,id2 \
--model google/gemini-2.5-flash \
--prompt @./prompts/tagger.md--mode controls whether output media replace originals (REPLACE_MEDIA) or land as new files (NEW_MEDIA).
Track and recover
# List jobs (paginated, filterable)
moana jobs list --status PROCESSING
moana jobs list --type ai-generate --trigger-type cron
moana jobs list --automation-id <slug>
# Drill into one job (per-item results)
moana jobs get <job-id> -o yaml
# Cancel a running job
moana jobs cancel <job-id>
# Resume a failed job — only the unfinished items re-run, linked via rootJobId
moana jobs resume <job-id>
# Clean up
moana jobs delete <job-id> --yes
moana jobs batch-delete <id1> <id2> <id3> --yesjobs resume is the right tool when a batch fails halfway through. It creates a new attempt that picks up only the items that didn't settle, so you don't pay twice for already-finished work.
Automations
Automations chain triggers (cron, upload events, generic events) to actions (run a processing preset, run an AI preset, …). Once enabled, they fire on their own.
Because the trigger and action shapes are nested JSON, automations create and update take a single --data payload — either inline JSON or a file path.
# List, inspect
moana automations list
moana automations list -f user
moana automations get builtin-web-optimize -o yaml
# Create from a file
moana automations create -d ./automations/auto-tag.json
# Toggle on / off
moana automations enable my-auto-tag
moana automations disable my-auto-tag
# Manually fire a cron automation right now (creates a job)
moana automations trigger my-nightly-rebuild
# Clone (always disabled by default — review before enabling)
moana automations clone builtin-web-optimize
# Delete
moana automations delete my-auto-tag --yes
moana automations batch-delete slug-1 slug-2 --yesA minimal automation looks like this:
{
"name": "Auto-tag on upload",
"enabled": true,
"trigger": {
"type": "event",
"eventType": "media.upload"
},
"action": {
"type": "chat_ai_preset",
"presetId": "my-product-describer"
}
}For the full schema and trigger/action catalogue, see the Automations guide.
Output formats
Every command that returns data accepts -o json|yaml|table. Most reads default to table; most writes default to json. Folder list also supports tree.
moana media list -o json
moana preset get my-preset -o yaml
moana folder list -o treeJSON output is colorized for terminals and machine-readable when piped, so you can chain commands with tools like jq:
# Trash every media item over 50 MB in /raw
moana media list --type folder --value <raw-folder-id> -o json |
jq -r '.data[] | select(.basicInfo.size > 50000000) | .mediaId' |
xargs moana media deleteConfiguration
State lives at ~/.moana/config.yml:
env: prod
token: mk_live_…You can edit it by hand, but moana login is usually the easier path.
Conventions cheat-sheet
| Convention | Where it applies |
|---|---|
--yes / -y | Skip confirmation on destructive commands |
-o, --output <fmt> | json (default for reads of one item), yaml, table (default for lists), tree (folder list only) |
-p, --prompt @file | Prompt option reads file contents when prefixed with @ |
--schema, --params, --variables, -p (presets) | Accept inline JSON or a file path — auto-detected |
--tags "a,b,c" | Comma-separated lists |
--media-ids id1,id2 | Job options take comma-separated IDs |
| Multiple positional IDs | Most batch commands take space-separated IDs as positional args |
What's next
- Run
moana --helpto explore the full command tree. - Pair the CLI with Automations to remove the human from repeatable workflows.
- Use the same actions over HTTP — see the API Reference for the underlying endpoints.
Last updated: July 7, 2026