{"id":20519,"plugin_id":"plugins_6aa518f7d9608191aa8b89c668c2fbe1","kind":"skill","collection_source":null,"comparison_source":null,"observed_at":"2026-09-30T23:16:18.907Z","digest":"53dbeceb9055c65222609407ed197239a0f88f2703fc1e7108c878c18467e814","against":null,"payload":{"name":"astria-api","description":"Use when making API calls to Astria for tunes, prompts, packs, image/video generation (Gemini/Seedream), inspecting or variating videos, handing an external agent session into Astria, or estimating generation and pack pricing. The reference for the `astria` CLI.","included_files":[],"skill_md_contents":"---\nname: astria-api\ndescription: Use when making API calls to Astria for tunes, prompts, packs, image/video generation (Gemini/Seedream), inspecting or variating videos, handing an external agent session into Astria, or estimating generation and pack pricing. The reference for the `astria` CLI.\nallowed-tools: Bash(astria:*)\n---\n\n# Astria CLI Reference\n\nAll Astria operations go through the bundled **`astria`** command-line tool. It\nhandles authentication, the API base URL, and workspace scoping for you — never\nbuild raw `curl` calls and never read API tokens from environment variables.\n\nOutput is JSON on stdout, so you can parse ids and image URLs directly.\n\n## Authentication\n\n`astria` resolves credentials automatically:\n1. Environment variables, if present (the Astria web app injects these).\n2. `~/.astria/config.json`, written by `astria login`.\n\nIf a command fails with *\"not authenticated\"*, tell the user to run:\n\n```bash\nastria login          # prompts for an API key (astria.ai/users/edit/api)\n```\n\nCheck the active account any time with `astria whoami`.\n\n## Profiles\n\nProfiles work like the AWS CLI — keep separate credentials, base URL and\nworkspace per profile (e.g. production vs a local dev server):\n\n```bash\nastria --profile localhost login --base-url http://localhost:3000\nastria --profile localhost generate --text \"...\"\nASTRIA_PROFILE=localhost astria tunes list       # env-var form\n```\n\n`--profile <name>` (before the subcommand) or the `ASTRIA_PROFILE` env var\nselects it. Each profile is its own file — `~/.astria/config.<name>.json`; the\ndefault profile stays at `~/.astria/config.json`.\n\n## Tune reference syntax\n\nThe core concept. A **tune** is a fine-tuned model trained on user images —\n\"tune\" and \"reference\" mean the same thing. Reference a tune inside prompt text\nwith `<model_type:id:1> name`:\n\n- `model_type` and `id` come from the tune JSON (`astria tunes get <id>`)\n- `name` is the tune's class name and MUST appear right after the `<...>` token\n- the trailing `:1` is a fixed part of the token syntax — it is NOT a weight or strength. Always write `:1`; never vary it and never suggest changing it.\n- Combine freely: `<faceid:123:1> woman wearing <faceid:456:1> dress, white studio background`\n\n`<faceid:123:1> woman` is correct; `John` (a bare name the model never trained on) is wrong.\n\n## Workspace scoping\n\nAdd `-w/--workspace` to any command:\n- `-w <id>` — target a specific workspace\n- `-w all` — query across every workspace\n- omit it — uses `WORKSPACE_ID`/config default, or personal scope\n\n## Models\n\n`--model` accepts a model name or a raw tune id. **Don't hardcode model\nnames — discover the current catalog at runtime:**\n\n```bash\nastria models              # image + video models — name, title, tune id, resolutions\nastria models --refresh    # force-refresh (otherwise cached for a day)\n```\n\nThe catalog is fetched from the Astria server, so it stays current as models\nare added or retired and the tune ids never go stale. The output marks the\n`default` model (used when `--model` is omitted) and lists each model's\nsupported `--resolution` values — a model with no resolutions listed doesn't\naccept `--resolution`. It also lists the `video_models` catalog and the\n`default_video_model` used by `astria video`.\n\n`astria generate` / `astria video` `--help` print the current model,\nresolution and video-model names inline — they read the same cached catalog.\n\n---\n\n## Tunes / references\n\n```bash\nastria tunes list                              # all tunes\nastria tunes list --title \"brown dress\"        # by title / product name / SKU\nastria tunes list --name shoes --name sandals  # by class name (repeatable)\nastria tunes list --gallery --model-type faceid --limit 200   # public gallery\nastria tunes get 123\nastria tunes create --title \"Brown dress\" --name dress \\\n  --description \"satin brown dress\" \\\n  --image-url https://example.com/a.jpg --image-url https://example.com/b.jpg\nastria tunes create --title \"Studio shot\" --name woman --image ./face1.jpg --image ./face2.jpg\nastria tunes update 123 --name ring --title \"Gold ring\"\n```\n\n`tunes create` takes `--image-url` (remote) and/or `--image` (local file),\nboth repeatable. `--name` is the subject class (man, woman, dress, shoes,\nsandals, pose, …). `--model-type` defaults to `faceid`.\n\n## Prompts\n\n```bash\nastria prompts list                            # recent prompts\nastria prompts list --pack-id 88               # a pack's template prompts\nastria prompts list --tune-id 123              # prompts for one tune\nastria prompts list --liked --is-video         # liked video prompts\nastria prompts list --today --limit 100        # prompts created today\nastria prompts list --text \"white background\" --limit 100 --offset 0\nastria prompts get 555 --model nano-banana-pro       # one prompt (needs its tune/model)\nastria prompts update 555 --model nano-banana-pro --pack-id 88   # assign a prompt to a pack\nastria prompts update 555 --model nano-banana-pro --base-pack-id 88   # bind as a pack one-off (board frame)\n```\n\n- `prompts list` filters: `--pack-id`, `--base-pack-id`, `--tune-id`,\n  `--user-id`, `--orig-prompt-id`, `--text`, and the flags `--liked`,\n  `--today`, `--is-video`, `--is-api`.\n\n## Generate images\n\n```bash\nastria generate --text \"<faceid:123:1> woman, clean white studio background\"\nastria generate --model nano-banana-pro --text \"...\" --num-images 4 --aspect-ratio 3:4 --resolution 2K\nastria generate --model seedream --text \"product photo of headphones on marble\" --num-images 2\nastria generate --text \"cinematic portrait\" --film-grain\nastria generate --text \"recreate this in 4K\" --input-image https://example.com/photo.jpg\nastria generate --text \"<faceid:123:1> woman, white bg\" --pack-id 88 --wait   # author a pack template prompt\nastria generate --text \"...\" --base-pack-id 88       # one-off bound to pack 88 — lands in its board frame\n```\n\n- `--input-image` accepts a URL or a local file path (used for image editing/upscaling).\n- `--film-grain` sends film grain as a separate prompt attribute and leaves\n  `--text` unchanged. `--film_grain` is an alias; `--no-film-grain` explicitly\n  disables it.\n- `--pack-id` authors the prompt as a pack **template** prompt; `--base-pack-id`\n  records pack provenance only (a one-off). On the board, `--base-pack-id`\n  generations appear as free rows inside that pack's frame.\n- A `--pack-id` template prompt must **reference a fine-tuned tune** — embed a\n  `<faceid:ID:1>` (or `<lora:ID:1>` …) token in `--text`. A plain foundation-model\n  prompt with no reference is rejected (HTTP 422, \"Prompt is not using a fine-tuned\n  model\"). `--base-pack-id` one-offs have no such requirement.\n- `--wait` polls until the images are ready and prints the finished prompt JSON.\n  Without it, the command returns immediately — images render asynchronously.\n- `aspect_ratio` values: `1:1 16:9 9:16 21:9 9:21 3:2 2:3 5:4 4:5 4:3`.\n- `--seed` sets the generation seed. Astria dedups prompts by `(text, seed)`\n  within a tune, so the same prompt text reused on different input images\n  collapses onto one prompt — pass a distinct `--seed` per call to keep them\n  separate without altering the prompt text.\n\n## Generate video\n\nVideo runs through the same prompt: the image stage renders the first frame\nfrom `--text`, then the video model animates it from `--video-prompt`.\n\n```bash\n# Existing reference: use the same token + tune-name syntax as image generation.\n# Put Seedance 2 references in --video-prompt so their images condition the video.\nastria video --video-model seedance2_fast_720p \\\n  --video-prompt \"<faceid:1234:1> woman walks down a runway as the camera tracks her\" \\\n  --duration 5 --aspect-ratio 16:9 --wait\n\n# New references: create them from local files or URLs and use them immediately.\nastria video --video-model seedance2_fast_720p \\\n  --video-prompt \"woman wearing a dress walks down a runway\" \\\n  --reference woman=./model.jpg --reference dress=https://example.com/dress.jpg \\\n  --duration 5 --aspect-ratio 16:9 --wait\n\n# Ordered raw references: attach the images directly without creating tunes.\nastria video --video-model seedance2_fast_720p \\\n  --video-prompt \"transition through these looks in order\" \\\n  --image-reference ./look-1.jpg --image-reference ./look-2.jpg \\\n  --duration 15 --aspect-ratio 16:9 --wait\n\nastria video --text \"zwx man <faceid:123:1> in a dance arena\" \\\n  --video-model kling30_motion_control_pro --video-prompt \"match the dance moves\" \\\n  --duration 10 --input-video ./reference.mp4\n```\n\n- Seedance 2 references use `<faceid:TUNE_ID:1> TUNE_NAME`, exactly like image\n  prompts. The tune's class name must immediately follow the token. A bare\n  `<faceid:1234:1>` token is incomplete.\n- Put existing reference mentions in `--video-prompt`; Seedance 2 resolves the\n  referenced tunes' images and sends them as video reference images.\n- `--reference NAME=PATH_OR_URL` creates an instant `faceid` reference and\n  prepends `<faceid:NEW_ID:1> NAME` to both `--text` (when present) and\n  `--video-prompt`. Repeat it for multiple references. `--images` is an alias.\n- `--image-reference PATH_OR_URL` attaches a raw image directly to the video\n  prompt without creating a tune. Repeat it in storyboard order. Use either\n  all local files or all URLs in one request so that ordering remains exact.\n- `--first-frame` / `--last-frame` / `--input-video` accept a URL or local file.\n- Motion-control models (`*_motion_control*`, `wan_animate_*`, `dreamactor_m2`,\n  `happyhorse_motion_control`) require `--input-video`.\n\n### `video_model` values and cost\n\nCosts are per 5-second base (per 10s for motion-control / fixed-duration\nmodels) and scale linearly with duration. `_audio` models include a soundtrack.\n\n| video_model                     | cost (¢)    | duration options |\n|----------------------------------|------------:|------------------|\n| seedance_480p                    |          10 | 2–12             |\n| seedance_v15_720p                |          14 | 4–12             |\n| seedance_v15_audio_720p          |          29 | 4–12             |\n| cinematic_video                  |          84 | 5, 10, 15        |\n| wan25_720p                       |          53 | 5, 10            |\n| wan26_720p / wan26_1080p         |       53/79 | 5, 10, 15        |\n| wan27_720p / wan27_1080p         |       55/83 | 5, 10, 15        |\n| wan_animate_720p                 |          44 | 10               |\n| ltx23_720p / ltx23_1080p         |       17/22 | 5, 10, 15, 20    |\n| happyhorse_720p / _1080p         |      77/132 | 3–10             |\n| happyhorse_motion_control        |         154 | 10               |\n| dreamactor_m2                    |          29 | 10               |\n| seedance2_fast_480p / _720p      |      60/140 | 4–15             |\n| seedance2_480p / _720p / _1080p  | 120/280/450 | 4–15             |\n| veo31_fast_720p / _1080p         |          85 | 4, 6, 8          |\n| veo31_fast_4k                    |         264 | 8                |\n| veo31_lite_720p / _1080p         |       44/71 | 4, 6, 8          |\n| kling30_standard / _pro          |      92/123 | 3–15             |\n| kling30_4k                       |         263 | 3–15             |\n| kling30_motion_control / _pro    |     277/370 | 10               |\n\nVideo output is delivered in the prompt's `images[]` with `content_type=video/mp4`.\n\n## Inspect video\n\nTurn a local video or public HTTPS video URL into timestamped text-to-video\nprompt text. Local files are direct-uploaded to Astria automatically; do not\nupload them separately or build raw API requests.\n\n```bash\nastria inspect-video ./clip.mp4\nastria inspect-video https://example.com/clip.mp4\nastria inspect-video ./clip.mp4 --tune-id 123 --tune-id 456\n```\n\nThe output uses one `SS-SS - description` line per cut for videos up to 30\nseconds. `--tune-id` is repeatable: use it when the resulting generation will\ncarry those references, so inspection removes their appearance details and\ninserts the exact Astria reference tokens. There is intentionally no custom\nprompt option; use the returned `description` as the video prompt.\n\n## Variate video\n\nUse `astria variate` when the user wants to preserve a source video's timing,\nperformance, camera, transitions, and audio while changing its content. The\ncommand runs the Variate mini-app workflow end to end: source inspection,\nreplacement-reference creation, structured prompt writing, and fixed-model\nSeedance 2.5 generation.\n\n```bash\n# Edit from a written brief\nastria variate ./source.mp4 \\\n  --brief 'Change the text on the final card to say \"Astria\"' --wait\n\n# Mix existing references with new local or remote images\nastria variate ./source.mp4 \\\n  --tune-id 123 \\\n  --reference ./dress.jpg \\\n  --reference woman=https://example.com/model.jpg \\\n  --brief 'Replace the presenter and wardrobe' --wait\n\n# Reuse an existing source description and avoid another inspection charge\nastria variate https://example.com/source.mp4 \\\n  --description-file ./source-description.txt \\\n  --brief 'Use a warmer end-card treatment'\n```\n\n- `SOURCE` is a local MP4/MOV or public HTTPS URL.\n- Repeat `--tune-id ID` for existing replacement references.\n- Repeat `--reference [NAME=]PATH_OR_URL` to create replacement references.\n  Without `NAME=`, the CLI detects the image class. With it, detection is\n  skipped. References preserve command order within the existing/new groups.\n- At least one reference or a non-empty `--brief` is required.\n- `--description` / `--description-file` bypass source inspection.\n- The command intentionally fixes `video_model=seedance25_720p`, enables\n  generated audio, and omits duration/aspect ratio so the source drives them.\n- Local source and reference files are direct-uploaded in one parallel batch.\n- The JSON result contains `description`, `references`, `video_prompt`, and\n  `prompt`; add `--wait` to receive the settled generation in `prompt`.\n\n## Download\n\n`astria download` saves a prompt's rendered assets (images, or `video/mp4`) to a\nlocal directory. It works from a **prompt id alone** — no tune id needed — and\nfetches each prompt fresh from the API, so newly rendered assets are included.\n\n```bash\nastria download 555 556 557                       # ids as arguments\nastria download 555 --out ./shoot                  # custom target directory\nastria download --prompts-file ids.txt             # one id per line (or whitespace)\nastria prompts list --pack-id 88 | \\\n  python3 -c 'import sys,json; [print(p[\"id\"]) for p in json.load(sys.stdin)]' | \\\n  astria download                                  # ids piped on stdin\n```\n\n- Prompt ids come from positional args, `--prompts-file`, and/or stdin; they are\n  deduped with original order preserved.\n- `--out` defaults to `./astria-downloads` and is created if missing.\n- Each asset is saved as `prompt-<id>-<NN><ext>` — `<NN>` is a zero-padded\n  index, `<ext>` is derived from the URL (`.jpg`/`.png`/`.webp`/`.mp4`/…).\n- Downloads run in parallel (~6 at a time).\n- A prompt that 404s, errors, or has no images yet is reported in the JSON\n  output (`error` field) and does not abort the run.\n- The JSON summary lists per prompt `{id, images, saved[], error?}` plus\n  `totals {prompts, downloaded, failed}`.\n\n## Packs\n\nPacks are surfaced in the Astria GUI as **Templates** — \"pack\" and \"template\" are interchangeable terms for the same object.\n\n```bash\nastria packs list\nastria packs get spring-lookbook\nastria packs create --title \"Spring Lookbook\"\nastria prompts update 555 --model nano-banana-pro --pack-id 88   # add a prompt to the pack\n```\n\n## Pricing\n\n`cost_mc` is an integer number of **millicents** (one thousandth of a US cent):\n\n- 1,000 `cost_mc` = $0.01\n- 100,000 `cost_mc` = $1.00\n- Convert to dollars with `cost_mc / 100_000`.\n\nA prompt's `cost_mc` already includes its `num_images`; never multiply by\n`num_images` again. Sum `cost_mc` across prompt records to price a prompt batch.\nFor example, prompts priced at 12,500 and 25,000 `cost_mc` total 37,500\nmillicents, or **$0.375**.\n\nUse `astria packs get <slug|id>` before running a pack:\n\n- `template_prompts[].cost_mc` is each stored template prompt's baseline. Sum\n  all entries for the full stored baseline, or selected entries for a\n  `--prompt-ids` subset.\n- `costs.<class>.cost_mc` estimates a fresh reference tune of that class plus\n  that class's prompt group. For multi-class packs it is not necessarily the\n  cost of the entire pack.\n\nThese are estimates, not personalized quotes. Generated prompts recalculate\ncost after prompt overrides; creator discounts, the payer's ecommerce pricing,\nworkspace rules, and Cartesian tune variants can change the result.\n\nAfter `astria packs run`, use `order.total_cost_mc` as the authoritative amount\ncharged when an order is returned. If no order is returned, the generated\nprompts' `cost_mc` values describe their individual base costs.\n\n### Run a pack\n\n`astria packs run <slug|id>` fires a pack's template prompts —\n`POST /p/:slug/tunes`. This is the canonical \"run a template\": the pack\ngenerates its whole prompt set, either against **tunes you already have** or\nagainst a **fresh tune trained from photos**. The positional accepts either the\npack **slug** or its numeric **id** — `astria packs run zara-pants …` and\n`astria packs run 3893 …` are equivalent.\n\n```bash\n# multi packs — run against existing tunes (tune_ids), with overrides\nastria packs run spring-lookbook --tune-id 123 --tune-id 456 \\\n  --brief \"golden hour, Lisbon\" --aspect-ratio 3:4 --inpaint-faces\n\n# only a subset of the pack's template prompts\nastria packs run spring-lookbook --tune-id 123 --prompt-ids 501,502\n\n# regular packs — train a fresh tune from photos, then generate\nastria packs run my-pack --title Jane --name woman \\\n  --image ./a.jpg --image ./b.jpg          # or --image-url https://…\n```\n\n- **Who the pack runs on** — pass either `--tune-id ID` (repeatable, or a\n  comma-separated list) to reuse existing tunes, **or** a training set\n  (`--title` + `--name` + `--image`/`--image-url`) to train a new tune first.\n  **Multi packs require at least one `--tune-id`** (the server routes tune_ids\n  to its multi handler; omitting them on a multi pack is a 422).\n- `--prompt-ids 501,502` runs only that subset of the pack's template prompts;\n  omit it to run them all.\n- `--brief` is an art-direction brief applied to the generated prompts.\n- **Overrides** ride along as `prompt_attributes`: `--num-images`,\n  `--aspect-ratio`, `--resolution`, `--inpaint-faces/--no-inpaint-faces`, and\n  `--attr KEY=VALUE` (repeatable) for any other prompt attribute, e.g.\n  `--attr super_resolution=true`.\n- The positional is the pack **slug or numeric id** — both resolve to the same\n  `/p/:slug/tunes` endpoint. On a multi pack the JSON response includes the new\n  `order` and its `prompt_ids` — feed those to `astria prompts wait` and\n  `astria download` to fetch the images.\n\n#### Worked example — a multi pack, step by step\n\n`zara-boot-test` (id `4001`) is a **multi pack** that composes two references —\na `dress` and a `shoes` (Footwear) — into one shoot. Create a reference per\ngarment, then run the pack against both by id. Scope every step to a workspace\nwith `-w` (find yours with `astria workspaces list`).\n\n```bash\n# 1. Create a reference for the dress (Gemini branch — instant, no training wait)\nastria tunes create -w 679 --name dress --title \"Zara dress\" --image ./dress.jpg\n# → { \"id\": 5234832, \"branch\": \"gemini-2\", \"trained_at\": \"...\" }\n\n# 2. Create a SEPARATE reference for the boots.\n#    Use a class the pack's slot recognizes: 'boots' (like 'shoes'/'sandals')\n#    resolves to the Footwear cube, so it fills the pack's shoes slot.\nastria tunes create -w 679 --name boots --title \"Zara boots\" --image ./boot.jpg\n# → { \"id\": 5234834, \"branch\": \"gemini-2\", \"trained_at\": \"...\" }\n\n# 3. Run the pack against both references — one --tune-id each.\n#    'zara-boot-test' or its id '4001' are interchangeable here.\nastria packs run zara-boot-test -w 679 \\\n  --tune-id 5234832 --tune-id 5234834 --num-images 1 --aspect-ratio 3:4\n# → { \"status\": 201, \"order\": { \"id\": 37345, \"tune_ids\": [5234834, 5234832] },\n#     \"prompt_ids\": [45042524, 45042523] }\n\n# 4. Fetch the results (the order hands back the prompt ids)\nastria prompts wait -w 679 45042524 45042523              # block until rendered (or user_error)\nastria download 45042524 45042523 --out ./zara-boot-shoot\n```\n\nThe pack swaps each reference into the matching template slot by lookbook cube,\nso the generated prompts come back with both tokens recorded, e.g.\n`a model wearing <faceid:5234832:1> dress and <faceid:5234834:1> boots, …`\n(and the shoes-only template gets just the boots token). The overrides land as\nprompt attributes (`aspect_ratio: 3:4`, `num_images: 1`).\n\nGemini-branch references (step 1–2) are ready instantly; a pack built on trained\ntunes queues its prompts and renders them once the tunes finish training. Pass\none `--tune-id` per reference slot the pack defines — a multi pack needs at\nleast one, and rejects the run (422) if you send none.\n\n## Board (infinite canvas)\n\nThe board (`/boards/:id` in the GUI) organizes work as **frames** (a pack-bound working context), **order rows** (one Order = a line of prompts sharing one reference set) and **reference cards** (tunes with lookbook roles: Pose, Face, Accessories, Jacket, Top, Bags & Belts, Footwear, Bottom, Background). There is no board API and no `board` verb — you act on the regular domain objects with the verbs above, and the canvas updates live (new rows land via the `order.created` broadcast, cells re-render as prompts finish).\n\n```bash\nastria packs run 88 --tune-id 123 --tune-id 456 \\\n    --prompt-ids 501,502 --brief \"golden hour, Lisbon\"  # new row: clone the pack's templates with swapped refs\nastria prompts wait 7001 7002 && astria download 7001 7002   # wait for the row's cells, fetch images\nastria generate --text \"...\" --base-pack-id 88       # one-off into pack 88's frame (free row, not a template)\n# variant with edited text (stacks as a version on its cell; order_id from `astria prompts get`):\nastria api POST /prompts/7001/duplicate --query view=board --data '{\"prompt\":{\"text\":\"...\",\"order_id\":901}}'\n# promote a prompt into the pack template / demote a template back out (confirm with the user first):\nastria api PATCH /prompts/7001 --query view=board --data '{\"prompt\":{\"pack_id\":88,\"base_pack_id\":null,\"orig_prompt_id\":null}}'\nastria api PATCH /prompts/7001 --query view=board --data '{\"prompt\":{\"pack_id\":null,\"base_pack_id\":88}}'\n```\n\nFor an ordered raw-image video, pass the selected images directly with repeated\n`astria video --image-reference PATH_OR_URL` options. Do not create temporary\ntunes for those images.\n\n## Workspaces & landing pages\n\n```bash\nastria workspaces list\nastria workspaces create --title \"Acme Store\"   # new workspace → returns its id/slug\nastria landing get -w 42                        # workspace JSON incl. landing_page_html\nastria landing set -w 42 --html-file ./edited.html\n```\n\n## Hand work into Astria’s embedded agent\n\nWhen the user asks to continue the current ChatGPT, Codex, Claude, or Cursor\nsession in Astria, write a concise UTF-8 `HANDOFF.md` containing the objective,\ncompleted work, important decisions, artifact paths, unresolved issues, and the\nrecommended next action. Do not include credentials or hidden reasoning.\n\nAttach only files needed to continue. Include a custom skill only when it was\nactually used or is needed for the remaining work; never export credential\nfiles or an entire agent configuration directory.\n\n```bash\nastria agent handoff -w 42 \\\n  --handoff ./HANDOFF.md \\\n  --attach ./deliverables \\\n  --skill ~/.claude/skills/relevant-skill \\\n  --source claude-code \\\n  --open\n```\n\n`--attach` and `--skill` are repeatable. A skill path must be a directory with\n`SKILL.md`. The command uploads the versioned bundle, creates a dedicated chat\nsession, prints its HTTPS deep link, and opens it with `--open`. Imported skills\nare reviewable session-scoped references; Astria does not silently install them\ninto the shared workspace skill directory.\n\n## Raw API escape hatch\n\nFor anything without a dedicated verb:\n\n```bash\nastria api GET /prompts --query limit=5 --query offset=0\nastria api POST /tunes --form 'tune[title]=Hat' --form 'tune[images][]=@./hat.jpg'\n```\n\n## Pagination\n\nList commands accept `--limit N` and `--offset Y`. Default sort is id\ndescending, so `--offset` walks backwards through history.\n\n## Errors\n\nA non-zero exit prints `astria: <METHOD> <PATH> → HTTP <code>: <message>` on\nstderr. Surface the message to the user and suggest a fix. HTTP 422 means a\nvalidation error (missing/invalid fields).\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}