Creating with Magic Art
Magic Art is itself an agent with human checkpoints: it asks clarifying questions,
recommends templates, confirms how many images to make, and can stop mid-generation to ask
for more. Your job is to decide who answers at each checkpoint — answer from the
conversation yourself where you can, and go back to the user only when the judgment is
genuinely theirs.
Preflight
magic --version
- Command not found, or lower than this skill's
version (see frontmatter):
npm i -g @magic-art/cli@latest && magic skill install. The skill files ship inside
the CLI package, so a copy installed from a hub can be older than the binary that
implements it; re-installing writes the matching copy to ~/.agents/skills/magic-art
and relinks every agent on the machine.
magic auth status --json
- Exit code 20 → tell the user to run
magic login, and relay the URL and pairing code
the CLI prints verbatim. The user authorizes in their own browser.
Never enter a code, password or any credential on their behalf.
- Quote before spending anything:
magic billing quote --op image -n <count> --json
- Exit code 21 (
canAfford=false, or requiredPlanId non-empty) → give the user the
point price and the top-up link, then stop. Never buy or upgrade for them.
Picking a mode (details in references/modes.md)
| What the user is describing |
mode |
| A poster, promo image, cover, single hero visual |
poster |
| A Xiaohongshu note, multi-page deck, recommendation post |
social-card |
| One theme, several images that belong together |
image-series |
| A portrait shoot, "turn my photo into…" (needs the user's own photo) |
portrait / portrait-series |
| A scene, a story, recurring characters across several shots |
film (see "Film Studio" below) |
| A logo, brand mark, symbol, app icon |
logo (see "Logo Studio" below) |
| Can't articulate it, wants free rein |
free |
Unsure? Run magic styles list --kind <mode> --json to see what styles exist in that mode,
or magic search --json to pull every available facet in one call.
The standard flow
magic project create --mode poster --text "<the user's idea, verbatim>" [--ref image]... # → prints a work id
magic clarify open <id> --json # modes that need clarifying
magic clarify send <id> -m "<your answer>" --json # loop until ready_for_plan
magic generate <id> --count 4 --wait --json # submit and follow to the end
magic assets download <id> --out ./out # results land locally
- Create:
magic project create --mode <mode> --text "<the user's idea, verbatim>".
If the user supplied reference images, pass --ref <file> (repeatable) and use
--ref-prompt to say what those images are for (a style reference, or a product/person
that must be preserved). Resolution can only be set here (--resolution 1k|2k|4k) and
cannot be changed afterwards.
- Clarify (
social-card, image-series and other modes that require it):
magic clarify open <id> --json returns the opening question; then loop
clarify send / clarify select until it returns ready_for_plan: true.
- To pick templates and set the count, use
magic clarify select <id> --template <id> --template <id> --count 4
(no model call — fast and deterministic).
- For when to answer yourself, see "Who answers" below.
- Generate:
magic generate <id> --count <N> --wait --json.
- Without
--wait it only submits and prints a jobId; follow it later with
magic job wait <id> --json.
- Exit code 30 (
awaiting_human): read the question on stdout. If you can answer it,
magic job answer <id> --job <jobId> -m "<answer>" (keeps waiting by default);
otherwise relay it to the user.
- Exit code 40:
magic job list <id> --json for the error and the replayable params,
then magic job resume <id>, or adjust parameters and generate again.
- Deliver:
magic assets download <id> --out <dir>, then hand the user the local paths.
- Edit:
magic edit <id> --parent <assetId> --prompt "<what to change>" (returns the new
image synchronously), then download. When the change is hard to describe for the whole
image and only one area is wrong, switch to regional annotation (next section).
Regional (annotated) edits
When the user says "just this bit is off", don't write "change the icon in the top-left" into
--prompt and let the model hunt for it — point at the place directly:
magic assets download "$ID" --asset <assetId> --out ./out # get the image locally and look at it first
magic edit "$ID" --parent <assetId> \
--mark "0.62,0.08,0.3,0.12=replace this headline with 'Flash sale - 20% off'" \
--mark "0.1,0.75=this corner is empty, add a small icon" --json
- Coordinates are fractions of 0–1 with the origin at the top-left:
x,y,w,h=note boxes
an area, x,y=note points at a spot. Pixels (1200,800,...) are rejected outright, never
silently reinterpreted as fractions and applied to the wrong place.
- At most 10 marks per call, each note ≤300 characters. Multiple marks reach the model
numbered ①②③ in the order you give them.
- With
--mark present, --prompt is optional; giving both means "overall requirement plus
per-area requirements".
- For many marks, put them in a file:
--marks-file marks.json (a JSON array of objects with
x,y,w,h,note).
Hard rule: never give coordinates for an image you haven't looked at. With only an asset
id in hand, every coordinate is a guess — magic assets download it first, read the image,
see where things actually are, then mark. Even when the user describes the location ("the QR
code in the bottom-right"), look at the image and confirm the QR code is really there.
Changing one coordinate or one word is a new render and a new charge; only re-running the
exact same command reuses the previous operation_id.
Let the user draw the boxes (--mark-ui)
The user cannot see whether coordinates on a command line are right — by the time they find
out the box was wrong, the points are spent. If there is any doubt about a position, hand
the boxing to the user by adding --mark-ui:
magic edit "$ID" --parent <assetId> \
--mark "0.62,0.08,0.3,0.12=replace this headline with 'Flash sale - 20% off'" \
--mark-ui --json
The CLI serves a page bound to 127.0.0.1 only and opens a browser, showing the user the
original image with the boxes you gave already drawn on it. They can drag, add and delete
boxes and write a note on each; the CLI continues only after they click "submit and
generate". On submit, the browser-composed ①②③-annotated preview goes to the model along
with the boxes — exactly like annotated editing on the website.
--mark is optional: when you are unsure of everything, pass --mark-ui alone and let
the user box from scratch.
- "Cancel" or closing the page = exit code 10, nothing generated, nothing charged. Do not
fall back to blind coordinates on your own initiative — ask the user what they want changed.
- On a server with no browser: add
--no-open and the CLI prints the URL for the user to open
themselves (they must be able to reach 127.0.0.1 on that machine; if they can't, fall back
to --mark with coordinates).
- No submission within 15 minutes times out, handled the same as a cancel.
Film Studio (--mode film)
For work where the same character or place has to look the same in more than one image —
a scene, a short story, a comic, a shot list. The other modes render each image on its own;
film gives you cards that other shots reference, so consistency is structural instead of
something you re-describe in every prompt.
magic project create --mode film --text "<the user's idea>" # → a work id
magic film plan "$ID" --seed "深夜天台,老陈和年轻警察对峙" --apply --json # seed → benches (free)
magic film cand "$ID" bn_chen --count 3 --wait --json # candidate bases (charged)
magic film sheet create "$ID" --from bn_chen --views front,profile --wait --json # → fs_… (charged)
magic film anchor "$ID" fs_chen --name 老陈 --handle laochen # exit 30 → ask the user
magic film anchor "$ID" fs_chen --name 老陈 --handle laochen --yes # → aa_… in the library
magic film shot create "$ID" --title 天台对峙 \
--card "aa_laochen:front:subject@0.3,0.6" --cam "A:lens=35" --action "老陈抬手" --json
magic film generate "$ID" fsh_1 --count 2 --dry-run --json # price + composed prompt
magic film generate "$ID" fsh_1 --count 2 --wait --json # charged
magic film out "$ID" <assetId> --show-prompt --json # what this frame was made of
magic film save "$ID" <assetId> # keep it in the strip
magic film list <id> --json returns the whole film — benches, view cards, shots and any
running jobs — and is how you re-orient after an interruption instead of re-planning.
- Pass ids and structured fields, never prompt prose. The sentence the image model reads is
composed server-side from the card ids, the camera and the action. To see it, read it back
with
--dry-run / --show-prompt; to change it, change the structure. --prompt-edit "A=…"
exists for the rare full override, and --auto-prompt puts composition back.
- A view is a free label, not an enum:
--views front,profile,俯拍=俯拍 is fine. Omitting
--views uses the type's default set.
- Only five things cost points:
film cand, film sheet create, film sheet update (when it
adds or re-shoots a view), film generate, film swap. Everything else — planning, listing,
editing shots, reordering, saving, the whole library — is free.
- Never compute a film price yourself.
magic film generate --dry-run --json returns the
server's quote and the composed prompt in one call; quote from that.
- One click renders
cameras × --count images, capped at 12.
Anchoring is the user's decision
magic film anchor promotes a view card into the account-level library: it outlives this
work, and every shot referencing that identity is rebound onto it. Which take is the
character is taste, so without --yes the CLI prints the candidate views and their image URLs
and exits 30. Show the user the images, get an answer, then re-run with --yes.
magic library list|show|add|set|rm is that library's own surface — the cards are pointers, so
deleting a work does not delete its cards, and magic library rm --hard on a card another film
still references is refused rather than quietly breaking that film.
Logo Studio (magic logo)
For a brand mark: a logo, a symbol, an app icon. One brief goes in, a board of distinct
directions comes back as transparent PNGs, and the user picks the one that is theirs.
magic logo generate --name "Nimbus" --about "weather app for sailors" \
--palette "#0f4c81,#e8b04b" --directions 3 --count 2 --dry-run --json # price + the plan, free
magic logo generate --name "Nimbus" --about "weather app for sailors" \
--directions 3 --count 2 --out ./logos --yes --json # charged; waits; downloads
magic logo generate --name "Nimbus" --about "weather app for sailors" \
--mark-types mascot,emblem --count 2 --out ./logos --yes --json # exactly these two directions
magic logo generate --name "Nimbus" --about "weather app for sailors" \
--mark-types mascot,auto --count 2 --out ./logos --yes --json # mascot + one the planner surprises you with
ls -la ./logos # d1-c1.png d1-c2.png d2-c1.png … — show the user the FILES, not the ids
magic logo list <id> --out ./logos --json # the board again, free
magic logo pack <id> --cand d1-c2 --out ./logos # anchor + delivery zip, free
magic logo generate creates the work itself when you don't pass --project <id> — including
with --dry-run, because the planner and the price both live on the work. That dry-run work is
empty and costs nothing, but it is real: reuse it with --project <id> instead of letting the next
call mint a second one. The id is the first thing on stdout — project_id\t<id> (with --json, a
{"event":"project_created",…} line) printed before anything is charged, so a run that dies
mid-flight is recoverable with --project <id>. magic logo list <id> is how you re-orient after
an interruption instead of generating a second board.
--mark-types names which kinds of mark to explore, out of abstract / lettermark /
mascot / emblem / pictorial (comma-separated, at most five). One type = one direction, in the
order given, so it sets the direction count and --directions is ignored (with a notice) when both
are passed. A sixth value, auto, is "you pick": that ONE slot's type is chosen server-side by the
planner, which is asked for a surprising angle the brief does not spell out — and it may pick a type
already named in the same list. At most one auto, but it combines with all five concrete types
(abstract,lettermark,mascot,emblem,pictorial,auto = six directions). --mark-types mascot,auto is
therefore two directions — a mascot, plus whatever the planner wants to surprise you with.
Leave it off and the planner picks the types from the brief, which is the default. It is
the same choice the 简报 card offers on the canvas, and it rides on the brief — so a board planned
with it keeps the selection.
The table both commands print is id / direction / mark type / status / transparent ratio / local file. status is ready (downloaded), opaque (the model returned a background instead of
transparency — already refunded, nothing to pay or fix, offer a re-roll) or failed.
- The brand name never enters the image prompt. Models cannot spell reliably, so the mark is
drawn wordless and the wordmark is built from real font outlines later. Don't try to route the
name in through
--about; describe what the brand is instead.
- Which mark is the brand is the user's decision, made by looking. After
generate, give the
user the local file paths so they can open the PNGs. Never pick for them.
- How big the batch is:
--directions defaults to 3 (1–5) and --count to 2 (1–4),
so a bare generate renders 3 × 2 = 6 marks. The server clamps both, and the canvas's 简报 card
stores the same two numbers — passing neither on a work that already has a brief reuses what the
user chose there.
- Only
generate costs points — directions × count images, priced per 2K image; list and
pack are free. Quote from --dry-run --json's quote, never by arithmetic. Over 300 points
without --yes, the CLI prints the quote and exits 30: relay it, then re-run with
--project <id> --yes so it uses the work it already created. Exit 30 with
"reason":"no_quote" means the server priced nothing and the CLI refused to dispatch blind —
retry. Not enough points is exit 21 (only the user can fix it); nothing was dispatched in
either case.
- Exit 50 after a paid
generate means "still running", not "broken" — the points were spent
and the jobs are alive server-side, so the move is magic logo list <id> --out ./logos, never a
second generate. A candidate that actually failed shows as exit 40, once nothing is in
flight.
pack always succeeds, and always tries for the SVG. The zip holds transparent PNGs in six
sizes, two mono versions, the wordmark lockups, a README — and vector/mark.svg, which the export
job traces on the spot when the mark has none. Tracing needs the deployed logo-lab service, so
where it is missing the archive ships without that one file and says so: --json carries
"vector": false and the plain output prints a line. Never tell the user the SVG is in there
without checking that field.
Who answers (checkpoint policy)
| Cloud checkpoint |
Your strategy |
| clarify opening / follow-ups |
Answer yourself first: distil it from the outer conversation; ask only when the information genuinely isn't there |
Template recommendation (selecting_templates) |
Choose for them, using recommended_templates reasons plus the taste the user has already expressed; relay the options only if they asked to pick from a few directions |
Count confirmation (selecting_count) |
Answer yourself: the number they said, or the mode default if they said none |
awaiting_human during generation |
Answer yourself first; purely subjective preference with nothing in context → ask |
| Whether a regional box is accurate |
Hand it over when it isn't: any doubt about position → --mark-ui so the user confirms or fixes the box on the image. Don't spend points on guessed coordinates |
magic film anchor (exit 30) |
Always ask: the card outlives this work and rebinds every shot that uses it. Relay the candidate views and their image URLs, then re-run with --yes |
| Which bench candidate / which take to build on |
Ask when it is taste, decide when it is craft: "which of these three faces is 老陈" is the user's; "this one failed, re-roll it" is yours |
| Insufficient balance / upgrade needed |
Always ask: quote plus top-up URL, never purchase |
| Publishing / permanent deletion |
Always ask (outward-facing, irreversible) |
| Login |
Relay the URL and pairing code only, never enter any credential |
Hard rules
- Use the
magic CLI only; never curl the site API directly. Auth headers, idempotent
operation_ids, poll cadence and exit-code semantics all live in the CLI. Going around it
breaks, and it will trip rate limits.
- Quote before spending: generation burns magic points, so
billing quote comes first.
Exit code 21 always means stop and ask.
- Publishing and permanent deletion (
magic project delete --yes): ask the user first.
- Never hand-roll a sleep/poll loop: wait with
magic job wait, which polls at the
cadence the site expects.
- Resuming after an interruption:
magic job list <id> --json first — an active job means
job wait, a failed one means job resume. Do not just run generate again (that is
buying it a second time).
- Look at the image before giving coordinates:
--mark coordinates may only come from an
image you actually viewed, never inferred from an asset id.
- In film, pass ids — never a hand-written prompt. Prompts are composed server-side from
the cards, camera and action; read one back with
--dry-run / --show-prompt instead of
writing one, and never total up points yourself when the server returns a quote.
- Never
magic film anchor --yes on your own judgment: exit 30 is a question for the user.
- Always get images down with
magic assets download (the CLI resolves CDN or signed
private-bucket URLs). Don't try to pull bytes out of the API.
- Look up each command's full set of flags with
magic <command> --help rather than
assembling arguments from memory.
Reference
references/modes.md — what each mode is for, count bounds, input requirements, routing calls,
and the film chain (bench → view card → anchor → shot) with its charged commands
references/recipes.md — end-to-end recipes (command sequences plus expected output),
including a full film and the second film that reuses its cards
references/troubleshooting.md — exit-code handbook, rate limits, expired tokens,
awaiting_human reply templates, the job resume decision tree
1---2name: magic-art3description: Turn an idea into a finished visual with Magic Art (magic-design.art): AI posters, Xiaohongshu-style multi-page card decks, portrait shoots, image series — and download the results locally. Use when the user wants a poster, cover, social card deck, portrait or a set of on-theme images, or mentions Magic Art / magic-design.art. Everything runs through the `magic` CLI.4---56# Creating with Magic Art78Magic Art is itself an agent with human checkpoints: it asks clarifying questions,9recommends templates, confirms how many images to make, and can stop mid-generation to ask10for more. Your job is to **decide who answers at each checkpoint** — answer from the11conversation yourself where you can, and go back to the user only when the judgment is12genuinely theirs.1314## Preflight15161. `magic --version`17 - Command not found, or lower than this skill's `version` (see frontmatter):18 `npm i -g @magic-art/cli@latest && magic skill install`. The skill files ship inside19 the CLI package, so a copy installed from a hub can be older than the binary that20 implements it; re-installing writes the matching copy to `~/.agents/skills/magic-art`21 and relinks every agent on the machine.222. `magic auth status --json`23 - Exit code 20 → tell the user to run `magic login`, and relay the URL and pairing code24 the CLI prints **verbatim**. The user authorizes in their own browser.25 **Never enter a code, password or any credential on their behalf.**263. Quote before spending anything:27 `magic billing quote --op image -n <count> --json`28 - Exit code 21 (`canAfford=false`, or `requiredPlanId` non-empty) → give the user the29 point price and the top-up link, then stop. **Never buy or upgrade for them.**3031## Picking a mode (details in references/modes.md)3233| What the user is describing | mode |34|---|---|35| A poster, promo image, cover, single hero visual | `poster` |36| A Xiaohongshu note, multi-page deck, recommendation post | `social-card` |37| One theme, several images that belong together | `image-series` |38| A portrait shoot, "turn my photo into…" (needs the user's own photo) | `portrait` / `portrait-series` |39| A scene, a story, recurring characters across several shots | `film` (see "Film Studio" below) |40| A logo, brand mark, symbol, app icon | `logo` (see "Logo Studio" below) |41| Can't articulate it, wants free rein | `free` |4243Unsure? Run `magic styles list --kind <mode> --json` to see what styles exist in that mode,44or `magic search --json` to pull every available facet in one call.4546## The standard flow4748```bash49magic project create --mode poster --text "<the user's idea, verbatim>" [--ref image]... # → prints a work id50magic clarify open <id> --json # modes that need clarifying51magic clarify send <id> -m "<your answer>" --json # loop until ready_for_plan52magic generate <id> --count 4 --wait --json # submit and follow to the end53magic assets download <id> --out ./out # results land locally54```55561. **Create**: `magic project create --mode <mode> --text "<the user's idea, verbatim>"`.57 If the user supplied reference images, pass `--ref <file>` (repeatable) and use58 `--ref-prompt` to say what those images are for (a style reference, or a product/person59 that must be preserved). Resolution can only be set here (`--resolution 1k|2k|4k`) and60 cannot be changed afterwards.612. **Clarify** (`social-card`, `image-series` and other modes that require it):62 `magic clarify open <id> --json` returns the opening question; then loop63 `clarify send` / `clarify select` until it returns `ready_for_plan: true`.64 - To pick templates and set the count, use65 `magic clarify select <id> --template <id> --template <id> --count 4`66 (no model call — fast and deterministic).67 - For when to answer yourself, see "Who answers" below.683. **Generate**: `magic generate <id> --count <N> --wait --json`.69 - Without `--wait` it only submits and prints a jobId; follow it later with70 `magic job wait <id> --json`.71 - Exit code 30 (`awaiting_human`): read the question on stdout. If you can answer it,72 `magic job answer <id> --job <jobId> -m "<answer>"` (keeps waiting by default);73 otherwise relay it to the user.74 - Exit code 40: `magic job list <id> --json` for the error and the replayable params,75 then `magic job resume <id>`, or adjust parameters and generate again.764. **Deliver**: `magic assets download <id> --out <dir>`, then hand the user the local paths.775. **Edit**: `magic edit <id> --parent <assetId> --prompt "<what to change>"` (returns the new78 image synchronously), then download. When the change is hard to describe for the whole79 image and only one area is wrong, switch to **regional annotation** (next section).8081## Regional (annotated) edits8283When the user says "just this bit is off", don't write "change the icon in the top-left" into84`--prompt` and let the model hunt for it — point at the place directly:8586```bash87magic assets download "$ID" --asset <assetId> --out ./out # get the image locally and look at it first88magic edit "$ID" --parent <assetId> \89 --mark "0.62,0.08,0.3,0.12=replace this headline with 'Flash sale - 20% off'" \90 --mark "0.1,0.75=this corner is empty, add a small icon" --json91```9293- Coordinates are **fractions of 0–1** with the origin at the top-left: `x,y,w,h=note` boxes94 an area, `x,y=note` points at a spot. Pixels (`1200,800,...`) are rejected outright, never95 silently reinterpreted as fractions and applied to the wrong place.96- At most 10 marks per call, each note ≤300 characters. Multiple marks reach the model97 numbered ①②③ in the order you give them.98- With `--mark` present, `--prompt` is optional; giving both means "overall requirement plus99 per-area requirements".100- For many marks, put them in a file: `--marks-file marks.json` (a JSON array of objects with101 `x,y,w,h,note`).102103**Hard rule: never give coordinates for an image you haven't looked at.** With only an asset104id in hand, every coordinate is a guess — `magic assets download` it first, read the image,105see where things actually are, then mark. Even when the user describes the location ("the QR106code in the bottom-right"), look at the image and confirm the QR code is really there.107108Changing one coordinate or one word is a new render and a new charge; only re-running the109exact same command reuses the previous `operation_id`.110111### Let the user draw the boxes (`--mark-ui`)112113The user cannot see whether coordinates on a command line are right — by the time they find114out the box was wrong, the points are spent. **If there is any doubt about a position, hand115the boxing to the user** by adding `--mark-ui`:116117```bash118magic edit "$ID" --parent <assetId> \119 --mark "0.62,0.08,0.3,0.12=replace this headline with 'Flash sale - 20% off'" \120 --mark-ui --json121```122123The CLI serves a page bound to 127.0.0.1 only and opens a browser, showing the user the124original image with the boxes you gave **already drawn** on it. They can drag, add and delete125boxes and write a note on each; the CLI continues only after they click "submit and126generate". On submit, the browser-composed **①②③-annotated preview** goes to the model along127with the boxes — exactly like annotated editing on the website.128129- **`--mark` is optional**: when you are unsure of everything, pass `--mark-ui` alone and let130 the user box from scratch.131- **"Cancel" or closing the page = exit code 10, nothing generated, nothing charged.** Do not132 fall back to blind coordinates on your own initiative — ask the user what they want changed.133- On a server with no browser: add `--no-open` and the CLI prints the URL for the user to open134 themselves (they must be able to reach 127.0.0.1 on that machine; if they can't, fall back135 to `--mark` with coordinates).136- No submission within 15 minutes times out, handled the same as a cancel.137138## Film Studio (`--mode film`)139140For work where **the same character or place has to look the same in more than one image** —141a scene, a short story, a comic, a shot list. The other modes render each image on its own;142film gives you cards that other shots reference, so consistency is structural instead of143something you re-describe in every prompt.144145```bash146magic project create --mode film --text "<the user's idea>" # → a work id147magic film plan "$ID" --seed "深夜天台,老陈和年轻警察对峙" --apply --json # seed → benches (free)148magic film cand "$ID" bn_chen --count 3 --wait --json # candidate bases (charged)149magic film sheet create "$ID" --from bn_chen --views front,profile --wait --json # → fs_… (charged)150magic film anchor "$ID" fs_chen --name 老陈 --handle laochen # exit 30 → ask the user151magic film anchor "$ID" fs_chen --name 老陈 --handle laochen --yes # → aa_… in the library152magic film shot create "$ID" --title 天台对峙 \153 --card "aa_laochen:front:subject@0.3,0.6" --cam "A:lens=35" --action "老陈抬手" --json154magic film generate "$ID" fsh_1 --count 2 --dry-run --json # price + composed prompt155magic film generate "$ID" fsh_1 --count 2 --wait --json # charged156magic film out "$ID" <assetId> --show-prompt --json # what this frame was made of157magic film save "$ID" <assetId> # keep it in the strip158```159160`magic film list <id> --json` returns the whole film — benches, view cards, shots and any161running jobs — and is how you re-orient after an interruption instead of re-planning.162163- **Pass ids and structured fields, never prompt prose.** The sentence the image model reads is164 composed server-side from the card ids, the camera and the action. To see it, read it back165 with `--dry-run` / `--show-prompt`; to change it, change the structure. `--prompt-edit "A=…"`166 exists for the rare full override, and `--auto-prompt` puts composition back.167- **A view is a free label**, not an enum: `--views front,profile,俯拍=俯拍` is fine. Omitting168 `--views` uses the type's default set.169- **Only five things cost points**: `film cand`, `film sheet create`, `film sheet update` (when it170 adds or re-shoots a view), `film generate`, `film swap`. Everything else — planning, listing,171 editing shots, reordering, saving, the whole library — is free.172- **Never compute a film price yourself.** `magic film generate --dry-run --json` returns the173 server's `quote` and the composed prompt in one call; quote from that.174- One click renders `cameras × --count` images, capped at 12.175176### Anchoring is the user's decision177178`magic film anchor` promotes a view card into the **account-level library**: it outlives this179work, and every shot referencing that identity is rebound onto it. Which take *is* the180character is taste, so without `--yes` the CLI prints the candidate views and their image URLs181and exits **30**. Show the user the images, get an answer, then re-run with `--yes`.182183`magic library list|show|add|set|rm` is that library's own surface — the cards are pointers, so184deleting a work does not delete its cards, and `magic library rm --hard` on a card another film185still references is refused rather than quietly breaking that film.186187## Logo Studio (`magic logo`)188189For a **brand mark**: a logo, a symbol, an app icon. One brief goes in, a board of distinct190directions comes back as transparent PNGs, and the user picks the one that is theirs.191192```bash193magic logo generate --name "Nimbus" --about "weather app for sailors" \194 --palette "#0f4c81,#e8b04b" --directions 3 --count 2 --dry-run --json # price + the plan, free195magic logo generate --name "Nimbus" --about "weather app for sailors" \196 --directions 3 --count 2 --out ./logos --yes --json # charged; waits; downloads197magic logo generate --name "Nimbus" --about "weather app for sailors" \198 --mark-types mascot,emblem --count 2 --out ./logos --yes --json # exactly these two directions199magic logo generate --name "Nimbus" --about "weather app for sailors" \200 --mark-types mascot,auto --count 2 --out ./logos --yes --json # mascot + one the planner surprises you with201ls -la ./logos # d1-c1.png d1-c2.png d2-c1.png … — show the user the FILES, not the ids202magic logo list <id> --out ./logos --json # the board again, free203magic logo pack <id> --cand d1-c2 --out ./logos # anchor + delivery zip, free204```205206`magic logo generate` creates the work itself when you don't pass `--project <id>` — **including207with `--dry-run`**, because the planner and the price both live on the work. That dry-run work is208empty and costs nothing, but it is real: reuse it with `--project <id>` instead of letting the next209call mint a second one. The id is the first thing on stdout — `project_id\t<id>` (with `--json`, a210`{"event":"project_created",…}` line) printed **before** anything is charged, so a run that dies211mid-flight is recoverable with `--project <id>`. `magic logo list <id>` is how you re-orient after212an interruption instead of generating a second board.213214`--mark-types` names **which** kinds of mark to explore, out of `abstract` / `lettermark` /215`mascot` / `emblem` / `pictorial` (comma-separated, at most five). One type = one direction, in the216order given, so it sets the direction count and `--directions` is ignored (with a notice) when both217are passed. A sixth value, `auto`, is "you pick": that ONE slot's type is chosen server-side by the218planner, which is asked for a surprising angle the brief does not spell out — and it may pick a type219already named in the same list. At most one `auto`, but it combines with all five concrete types220(`abstract,lettermark,mascot,emblem,pictorial,auto` = six directions). `--mark-types mascot,auto` is221therefore two directions — a mascot, plus whatever the planner wants to surprise you with.222Leave it off and the planner picks the types from the brief, which is the default. It is223the same choice the 简报 card offers on the canvas, and it rides on the brief — so a board planned224with it keeps the selection.225226The table both commands print is `id / direction / mark type / status / transparent ratio / local227file`. `status` is `ready` (downloaded), `opaque` (the model returned a background instead of228transparency — **already refunded**, nothing to pay or fix, offer a re-roll) or `failed`.229230- **The brand name never enters the image prompt.** Models cannot spell reliably, so the mark is231 drawn wordless and the wordmark is built from real font outlines later. Don't try to route the232 name in through `--about`; describe what the brand *is* instead.233- **Which mark is the brand is the user's decision, made by looking.** After `generate`, give the234 user the local file paths so they can open the PNGs. Never pick for them.235- **How big the batch is**: `--directions` defaults to **3** (1–5) and `--count` to **2** (1–4),236 so a bare `generate` renders 3 × 2 = 6 marks. The server clamps both, and the canvas's 简报 card237 stores the same two numbers — passing neither on a work that already has a brief reuses what the238 user chose there.239- **Only `generate` costs points** — directions × count images, priced per 2K image; `list` and240 `pack` are free. Quote from `--dry-run --json`'s `quote`, never by arithmetic. Over 300 points241 without `--yes`, the CLI prints the quote and exits **30**: relay it, then re-run with242 `--project <id> --yes` so it uses the work it already created. Exit **30** with243 `"reason":"no_quote"` means the server priced nothing and the CLI refused to dispatch blind —244 retry. Not enough points is exit **21** (only the user can fix it); nothing was dispatched in245 either case.246- **Exit 50 after a paid `generate` means "still running", not "broken"** — the points were spent247 and the jobs are alive server-side, so the move is `magic logo list <id> --out ./logos`, never a248 second `generate`. A candidate that actually failed shows as exit **40**, once nothing is in249 flight.250- **`pack` always succeeds, and always tries for the SVG.** The zip holds transparent PNGs in six251 sizes, two mono versions, the wordmark lockups, a README — and `vector/mark.svg`, which the export252 job traces on the spot when the mark has none. Tracing needs the deployed logo-lab service, so253 where it is missing the archive ships without that one file and says so: `--json` carries254 `"vector": false` and the plain output prints a line. Never tell the user the SVG is in there255 without checking that field.256257## Who answers (checkpoint policy)258259| Cloud checkpoint | Your strategy |260|---|---|261| clarify opening / follow-ups | **Answer yourself first**: distil it from the outer conversation; ask only when the information genuinely isn't there |262| Template recommendation (`selecting_templates`) | Choose for them, using `recommended_templates` reasons plus the taste the user has already expressed; relay the options only if they asked to pick from a few directions |263| Count confirmation (`selecting_count`) | Answer yourself: the number they said, or the mode default if they said none |264| `awaiting_human` during generation | Answer yourself first; purely subjective preference with nothing in context → ask |265| Whether a regional box is accurate | **Hand it over when it isn't**: any doubt about position → `--mark-ui` so the user confirms or fixes the box on the image. Don't spend points on guessed coordinates |266| `magic film anchor` (exit 30) | **Always ask**: the card outlives this work and rebinds every shot that uses it. Relay the candidate views and their image URLs, then re-run with `--yes` |267| Which bench candidate / which take to build on | **Ask when it is taste, decide when it is craft**: "which of these three faces is 老陈" is the user's; "this one failed, re-roll it" is yours |268| Insufficient balance / upgrade needed | **Always ask**: quote plus top-up URL, never purchase |269| Publishing / permanent deletion | **Always ask** (outward-facing, irreversible) |270| Login | Relay the URL and pairing code only, **never enter any credential** |271272## Hard rules273274- **Use the `magic` CLI only**; never curl the site API directly. Auth headers, idempotent275 `operation_id`s, poll cadence and exit-code semantics all live in the CLI. Going around it276 breaks, and it will trip rate limits.277- **Quote before spending**: generation burns magic points, so `billing quote` comes first.278 Exit code 21 always means stop and ask.279- **Publishing and permanent deletion** (`magic project delete --yes`): ask the user first.280- **Never hand-roll a sleep/poll loop**: wait with `magic job wait`, which polls at the281 cadence the site expects.282- **Resuming after an interruption**: `magic job list <id> --json` first — an active job means283 `job wait`, a failed one means `job resume`. **Do not just run `generate` again** (that is284 buying it a second time).285- **Look at the image before giving coordinates**: `--mark` coordinates may only come from an286 image you actually viewed, never inferred from an asset id.287- **In film, pass ids — never a hand-written prompt.** Prompts are composed server-side from288 the cards, camera and action; read one back with `--dry-run` / `--show-prompt` instead of289 writing one, and never total up points yourself when the server returns a `quote`.290- **Never `magic film anchor --yes` on your own judgment**: exit 30 is a question for the user.291- **Always get images down with `magic assets download`** (the CLI resolves CDN or signed292 private-bucket URLs). Don't try to pull bytes out of the API.293- Look up each command's full set of flags with `magic <command> --help` rather than294 assembling arguments from memory.295296## Reference297298- `references/modes.md` — what each mode is for, count bounds, input requirements, routing calls,299 and the `film` chain (bench → view card → anchor → shot) with its charged commands300- `references/recipes.md` — end-to-end recipes (command sequences plus expected output),301 including a full film and the second film that reuses its cards302- `references/troubleshooting.md` — exit-code handbook, rate limits, expired tokens,303 `awaiting_human` reply templates, the `job resume` decision tree