Skip to main content

motif

Generate a drop-in animated mascot for any app or game, from the command line.

One description plus an action becomes a sprite sheet with the background removed, frames sliced and normalized, and export bundles for iOS, Android, Web, Unity and Godot. The work happens on trymotif.app and spends credits from your account, so this tool needs neither an image-model key nor ffmpeg on your machine.

Two tiers: the sprite sheet above, and Motion AI (--mode motion), which animates a picture of your character with a video model instead of drawing one.

Install

pipx install motifkit

No dependencies beyond Python 3.10+. Nothing is compiled, nothing is downloaded at runtime.

Set up

  1. Create an account at trymotif.app.
  2. Click the link in the confirmation email. This is the step people skip. Until your address is confirmed, creating an API key is refused, and the CLI reports it as an auth failure without much of a clue why.
  3. Create a key at trymotif.app/settings/api-keys, or from the ⚙ in the top bar of the app. It is shown once.
  4. Give it to the CLI:
motif configure

It is stored in ~/.config/motif/credentials.json, readable only by you. In CI, skip that and set the key from your secret store instead - the environment always wins:

export MOTIF_API_KEY="motif_sk_..."

What it costs

A new account starts with 10 credits and a sprite sheet costs 10, so the first generation is on the house and the next one needs a pack. Free accounts can make one generation a day; every account can have three jobs running at once. Credits are bought from the web app - there is no motif buy, on purpose, because payment belongs in a browser.

Prices come from the server rather than from this page, so ask it:

motif account                                # balance, and the price of each tier
motif gen "..." --action "..." --dry-run     # what this exact run would cost

Use

# The whole thing: generate, wait, and write the bundle.
motif gen "a happy robot mascot" --action "jumping for joy"

# With a reference image, a grid, and somewhere to put it.
motif gen "a fox knight" \
  --action "waving hello" \
  --ref ./concept.png \
  --rows 2 --cols 4 --fps 12 \
  --out ./assets/fox

# What would this cost? Creates nothing.
motif gen "..." --action "..." --dry-run
motif account

Motion AI (--mode motion)

The other tier. Instead of drawing a sprite sheet, Motion AI films your character's own artwork with a video model, so it needs a picture of the character and costs more (ask the server: motif account, which also says whether this deployment offers the tier through the API at all).

motif motions                       # the motions this server ships

motif gen --mode motion --action wave --ref ./capy.png --out ./assets/capy

--action is either one of those preset keys or your own description of the movement (--action "sips from a mug and smiles").

The cutout comes first. A clip is generated from one exact cut-out image, and whatever that image looks like is what the mascot IS for the whole clip - a matte that ate an ear produces a clip of a one-eared mascot, and nothing downstream can put it back. So the first run cuts the character out, writes the PNG next to your work, and stops:

Cutout written to ./motif-cutout-8f21ba03.png (512x512).
Nobody has approved this cutout yet. Open it, and if the character survived the
cut, run the same command again with --approve-cutout.

Look at it, then:

motif gen --mode motion --action wave --ref ./capy.png --approve-cutout

Nothing is charged until that point. The approval belongs to the mascot rather than to each animation, so later clips of the same character reuse it:

motif gen --mode motion --action nod --project <project_id>

The project id is printed with the job; --cutout-out PATH chooses where the PNG lands. Replacing the reference image retires the approval, on purpose.

--cut whole exports the entire take, matching the Studio; --cut loop gives you one cycle that repeats seamlessly. The recovery command printed on failure always spells --cut out in full, so a captured command reproduces its own request whatever the default is.

Option Default Meaning
--mode motion sprite Use Motion AI instead of a sprite sheet
--duration N 5 Seconds of footage to buy (priced per length)
--cut whole|loop whole whole: the entire take, played once - it steps where it wraps. loop: one cycle, about a second, repeating seamlessly
--whole-clip off Deprecated alias for --cut whole
--approve-cutout off Approve the written cutout without being asked
--cutout-out PATH ./motif-cutout-<id>.png Where to write the cutout for review
--project ID - Reuse a mascot's approved cutout

motif gen covers upload, create, poll and download, so you never have to handle a job id - until something goes wrong, and then it prints the command to recover with:

motif status <job_id> --wait     # keep waiting, then download
motif status <job_id>            # just look
motif export <job_id> --out ./x  # download again
motif cancel <job_id>            # ask the server to stop
motif cut <job_id> --cut loop    # re-cut the clip - costs nothing
motif jobs                       # list recent jobs, newest first

motif jobs is the answer to "I lost the id". A generation is paid for the moment it is admitted, so a job id that went missing is money already spent; this lists what is still there to poll or download.

motif cancel stops a job that has not started spending. Once the work has been sent to the model it is paid for, so that job finishes and keeps its credits - motif status says which happened.

motif cut changes a finished clip between the whole take and the loop. The footage is already bought, so switching is free and unlimited - you never have to regenerate to see the other cut. Add --out ./x to download the re-cut bundle in the same step.

Pressing Ctrl-C stops the CLI, not the job. The generation is already paid for and keeps running, so the CLI tells you the id to resume with rather than silently throwing the work away.

Waiting rides out a bad connection. A clip can take several minutes and is checked every few seconds, so the CLI retries a dropped read with a backoff rather than abandoning a job you have already paid for, and it obeys the server's Retry-After when it is asked to slow down. It gives up only after five failures in a row.

In a script

motif gen "a happy robot" --action idle --json > result.json
case $? in
  0) jq -r '.output_dir' result.json ;;
  4) echo "out of credits"; exit 1 ;;
  6) sleep 60 ;;   # rate limited
esac

In motion mode a script (or an agent) has one extra step, and it is deliberate: run once, look at the cutout the CLI wrote, then re-run with --approve-cutout.

motif gen --mode motion --action wave --ref ./capy.png --cutout-out ./cut.png
if [ $? -eq 10 ]; then
  # ./cut.png is on disk. Check the character survived the cut, then:
  motif gen --mode motion --action wave --ref ./capy.png --approve-cutout --json
fi

--json prints the machine-readable result on stdout; progress and errors go to stderr, so redirecting one does not lose the other. The output never contains your API key.

Exit codes are part of the contract, grouped by what you have to do about them:

Code Meaning
0 success
1 something unexpected
2 bad arguments or local config, or a tier this deployment does not sell
3 no key, wrong key, revoked key, or an unconfirmed email address
4 out of credits, the free daily limit, or a pack is needed to download
5 idempotency conflict, or too late to cancel
6 rate limited, or too many jobs running at once
7 the generation itself failed or was cancelled
8 connection lost or interrupted - the job may still be running
9 this build of the CLI is older than the server accepts
10 the cutout needs looking at before a clip can be made

About retrying

Each invocation carries one idempotency key, so a retry inside that invocation - after a dropped connection, say - returns the job that already exists instead of creating a second one.

Running the command again is a new request and is charged again. That is deliberate: two motif gen commands usually mean you want two animations. If you are retrying rather than asking for another one, resume the job you already paid for:

motif status <job_id> --wait

Exit code 8 always means "the job may still be running", and it always prints that command.

Metadata

Release files for motifkit 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for motifkit 0.1.1
File Size Uploaded
motifkit-0.1.1.tar.gz 27.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for motifkit 0.1.1
File Interpreter ABI Platform
motifkit-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 51.9 kB

Release files / motifkit-0.1.1.tar.gz

Download URL motifkit-0.1.1.tar.gz
Size 27.1 kB
Tags Source
SHA-256 checksum
How to use checksums
716aea81e2ebd07f9a3d5402e13848d252982a2082b2e83a7242ce7c2766b335
BLAKE2b-256 checksum
How to use checksums
1d2e686fab386e169bae6abc4ad0e2e617185edc7d2acffb0197afb80a9dabab
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.3

Release files / motifkit-0.1.1-py3-none-any.whl

Download URL motifkit-0.1.1-py3-none-any.whl
Size 24.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2165a8ba9e493d21826098cdc2ad36e8727b6888a5c3b2b1b55aab02f8aa6a85
BLAKE2b-256 checksum
How to use checksums
88a5a800d97d145f2b5353d3a9e448dbe6598b22b328cd16eda842dd4d694236
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.3

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page