{
  "schemaVersion": "6.0",
  "registryVersion": 2,
  "lastUpdated": "2026-10-15T07:27:57Z",
  "registryUrl": "https://cartridges.machinefabric.com/v2/manifest",
  "fabricRegistryUrl": "https://fabric.capdag.com",
  "channels": {
    "release": {
      "cartridges": {
        "pdfcartridge": {
          "name": "pdfcartridge",
          "description": "PDF page renderer, page-text disbinder, and PDF content inspector",
          "author": "https://github.com/machinefabric",
          "pageUrl": "https://github.com/machinefabric/pdfcartridge",
          "teamId": "P336JK947M",
          "minAppVersion": "1.0.0",
          "categories": [],
          "tags": [],
          "cap_groups": [
            {
              "name": "pdf-formats",
              "caps": [
                {
                  "urn": "cap:effect=none",
                  "title": "Identity",
                  "aliases": [
                    "identity"
                  ],
                  "cap_description": "The categorical identity morphism. Echoes input as output unchanged. Mandatory in every capability set.",
                  "args": [
                    {
                      "media_urn": "media:",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:"
                        }
                      ]
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:",
                      "name": "output",
                      "output_description": "The input data, unchanged",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:in=\"media:document;ext=pdf\";out=\"media:ext=png;image\";render-page-image",
                  "version": 3,
                  "title": "Render PDF Page Images",
                  "aliases": [
                    "render-page-image-pdf",
                    "pdf2png"
                  ],
                  "cap_description": "Render PNG page images for one or more PDF pages",
                  "documentation": "## Purpose\n\nRenders one or more pages of a PDF as PNG images. Each page becomes a separate PNG output. Use this to feed PDF content into vision models, generate thumbnails, or produce visual previews.\n\n## Inputs\n\n- A PDF file (path or stdin).\n- Page image width in pixels (default 800).\n- Page image height in pixels (default 1200).\n- An optional index range (default: `1-`, all pages). Format: `1` (single page), `1-5` (pages 1-5), `3-` (page 3 to end). Ranges are 1-based.\n\n## Outputs\n\nA sequence of PNG images, one per rendered page.\n\n## Notes\n\n- Index ranges support comma lists ('1,3,5-7'); ranges past the end clamp to the document. Encrypted PDFs need `--password` (the error names the flag when it is missing or wrong).\n\n- Higher resolution (larger width/height) produces more readable images at the cost of larger file sizes.\n- Feed the PNG output into [Describe Image (MLX)](https://capdag.com/browse/cap:describe-image;in=\"media:ext=png;image\";ml-model;mlx;out=\"media:enc=utf-8;ext=txt;image-description;plain-text\";vision) or [Generate Image Embeddings (Candle)](https://capdag.com/browse/cap:generate-image-embeddings;candle;in=\"media:ext=png;image\";ml-model;out=\"media:embedding-vector;enc=utf-8;record\") for vision-based PDF analysis.\n- For plain text extraction, use [Disbind PDF Into Pages](https://capdag.com/browse/cap:disbind;in=\"media:document;ext=pdf\";out=\"media:enc=utf-8;ext=txt;page;plain-text\") instead.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:document;ext=pdf"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the document file to process"
                    },
                    {
                      "media_urn": "media:numeric;page-image-width",
                      "name": "width",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--width"
                        }
                      ],
                      "arg_description": "Width of the page image in pixels",
                      "default_value": 800
                    },
                    {
                      "media_urn": "media:numeric;page-image-height",
                      "name": "height",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--height"
                        }
                      ],
                      "arg_description": "Height of the page image in pixels",
                      "default_value": 1200
                    },
                    {
                      "media_urn": "media:enc=utf-8;index-range",
                      "name": "index-range",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--index-range"
                        }
                      ],
                      "arg_description": "Pages to select (1-based). Grammar: '2', '1-5', '3-', '1,3,5-7'. Ranges past the end clamp to the document.",
                      "default_value": "1-"
                    },
                    {
                      "media_urn": "media:enc=utf-8;pdf-password;secret",
                      "name": "password",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--password"
                        }
                      ],
                      "arg_description": "Password for encrypted PDFs. Without it, an encrypted PDF fails with an error naming this flag; a wrong password fails saying so."
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:ext=png;image",
                      "name": "output",
                      "output_description": "PNG page images, one per rendered page",
                      "optional": false,
                      "is_sequence": true,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:disbind;in=\"media:document;ext=pdf\";out=\"media:enc=utf-8;ext=txt;page;plain-text\"",
                  "version": 3,
                  "title": "Disbind PDF Into Pages",
                  "aliases": [
                    "disbind-pdf"
                  ],
                  "cap_description": "Extract plain text content from each PDF page",
                  "documentation": "## Purpose\n\nSplits a PDF into its individual pages and extracts the plain text content from each page. The output is a sequence of text items, one per page. Use this as the first step in any PDF processing pipeline — text extraction, summarization, search indexing, or embedding.\n\n## Inputs\n\n- A PDF file (path or stdin).\n- An optional index range (default: `1-`, meaning all pages). Format: `1` (single page), `1-5` (pages 1 to 5), `3-` (page 3 to end).\n\n## Outputs\n\nA sequence of plain text values, one item per extracted page.\n\n## Notes\n\n- A page whose text extraction fails emits an empty-text item with a warning (same shape as a scanned page) — one bad page never aborts the rest of the document. Encrypted PDFs need `--password`.\n\n- Text extraction works on digitally-created PDFs. Scanned PDFs (image-only) will produce empty or near-empty pages. Run an OCR step first for scanned documents.\n- For visual rendering of pages as images (e.g. to feed into vision models), use [Render PDF Page Images](https://capdag.com/browse/cap:render-page-image;in=\"media:document;ext=pdf\";out=\"media:ext=png;image\").\n- Page numbers in the index range are 1-based.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:document;ext=pdf"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the document file to process"
                    },
                    {
                      "media_urn": "media:enc=utf-8;index-range",
                      "name": "index-range",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--index-range"
                        }
                      ],
                      "arg_description": "Pages to select (1-based). Grammar: '2', '1-5', '3-', '1,3,5-7'. Ranges past the end clamp to the document.",
                      "default_value": "1-"
                    },
                    {
                      "media_urn": "media:enc=utf-8;pdf-password;secret",
                      "name": "password",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--password"
                        }
                      ],
                      "arg_description": "Password for encrypted PDFs. Without it, an encrypted PDF fails with an error naming this flag; a wrong password fails saying so."
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:enc=utf-8;ext=txt;page;plain-text",
                      "name": "output",
                      "output_description": "Plain text pages, one per page in the document; each page is persistable as a `.txt` file",
                      "optional": false,
                      "is_sequence": true,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:disbind-to-pdf;in=\"media:document;ext=pdf\";out=\"media:document;ext=pdf\"",
                  "version": 3,
                  "title": "Disbind PDF Into Per-Page PDFs",
                  "aliases": [
                    "disbind-to-pdf"
                  ],
                  "cap_description": "Split a PDF into a sequence of one-page PDFs",
                  "documentation": "## Purpose\n\nSplits a PDF into a sequence of one-page PDFs — one item per page. Distinct from [Disbind PDF Into Page Text](https://capdag.com/browse/cap:disbind;in=\"media:document;ext=pdf\";out=\"media:enc=utf-8;ext=txt;page;plain-text\") in that the output items are *PDF documents*, not page text. Use this when downstream caps want to operate on individual pages while keeping the PDF structure intact (e.g. per-page rendering with different parameters, per-page redaction, per-page binding back into a different order).\n\n## Inputs\n\n- A PDF file (path or stdin).\n- An optional index range (default: `1-`, every page). Format: `1` (single page), `1-5` (pages 1-5), `3-` (page 3 to end).\n\n## Outputs\n\nA sequence of `media:document;ext=pdf` items, one valid one-page PDF per emitted page.\n\n## Notes\n\n- Index ranges support comma lists ('1,3,5-7'); ranges past the end clamp to the document. Encrypted PDFs need `--password`.\n\n- Each emitted item is a complete standalone PDF with the page tree, resources, and metadata pdfium produces from the source page; downstream caps that load PDFs work on the items unchanged.\n- An index range that matches no pages is a hard error — silently emitting an empty sequence would let downstream pipelines run on nothing without surfacing the empty-range mistake.\n- For text-only extraction, use [Disbind PDF Into Page Text](https://capdag.com/browse/cap:disbind;in=\"media:document;ext=pdf\";out=\"media:enc=utf-8;ext=txt;page;plain-text\").\n- For the inverse (concatenating per-page PDFs back into one), use [Bind PDFs](https://capdag.com/browse/cap:bind;in=\"media:document;ext=pdf\";out=\"media:document;ext=pdf\").",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:document;ext=pdf"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the PDF file to process"
                    },
                    {
                      "media_urn": "media:enc=utf-8;index-range",
                      "name": "index-range",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--index-range"
                        }
                      ],
                      "arg_description": "Pages to select (1-based). Grammar: '2', '1-5', '3-', '1,3,5-7'. Ranges past the end clamp to the document.",
                      "default_value": "1-"
                    },
                    {
                      "media_urn": "media:enc=utf-8;pdf-password;secret",
                      "name": "password",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--password"
                        }
                      ],
                      "arg_description": "Password for encrypted PDFs. Without it, an encrypted PDF fails with an error naming this flag; a wrong password fails saying so."
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:document;ext=pdf",
                      "name": "output",
                      "output_description": "Per-page PDFs, one item per page",
                      "optional": false,
                      "is_sequence": true,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:bind;in=\"media:document;ext=pdf\";out=\"media:document;ext=pdf\"",
                  "version": 3,
                  "title": "Bind PDFs",
                  "aliases": [
                    "bind-pdf"
                  ],
                  "cap_description": "Concatenate a sequence of PDFs into a single multi-page PDF",
                  "documentation": "## Purpose\n\nStitches a sequence of PDFs into a single multi-page PDF. Each input PDF's pages are appended to the output in arrival order — the first input's pages first, then the second's, and so on. Page contents, resources, and metadata are copied verbatim via pdfium's import-pages path; no re-rendering, no font subsetting, no recompression.\n\n## Inputs\n\n- A sequence of `media:document;ext=pdf` items.\n\n## Outputs\n\nA single `media:document;ext=pdf` whose page count is the sum of all input PDFs' page counts.\n\n## Notes\n\n- Encrypted inputs need `--password`; one password applies to every encrypted input (unencrypted inputs ignore it).\n\n- An empty input sequence is a hard error; an input PDF with zero pages is also a hard error. Both surface the upstream issue rather than silently producing an empty output.\n- Each input is loaded as its own pdfium document and its pages are imported into the destination at the running insertion index. Memory usage scales with the size of the largest individual input PDF (loaded one at a time), not with the sum.\n- For the inverse (splitting one PDF into per-page PDFs), use [Disbind PDF Into Per-Page PDFs](https://capdag.com/browse/cap:disbind-to-pdf;in=\"media:document;ext=pdf\";out=\"media:document;ext=pdf\").",
                  "args": [
                    {
                      "media_urn": "media:document;ext=pdf",
                      "name": "input",
                      "required": true,
                      "is_sequence": true,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:document;ext=pdf"
                        }
                      ],
                      "arg_description": "Sequence of PDF files to concatenate"
                    },
                    {
                      "media_urn": "media:enc=utf-8;pdf-password;secret",
                      "name": "password",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--password"
                        }
                      ],
                      "arg_description": "Password for encrypted PDFs. Without it, an encrypted PDF fails with an error naming this flag; a wrong password fails saying so."
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:document;ext=pdf",
                      "name": "output",
                      "output_description": "Single concatenated PDF",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                }
              ],
              "adapter_urns": [
                "media:document;ext=pdf"
              ]
            }
          ],
          "latestVersion": "1.368.920",
          "versions": {
            "1.368.920": {
              "releaseDate": "2026-10-15T07:23:50Z",
              "changelog": [
                "Initial release"
              ],
              "minAppVersion": "1.0.0",
              "builds": [
                {
                  "platform": "darwin-arm64",
                  "package": {
                    "name": "pdfcartridge-1.368.920-darwin-arm64.pkg",
                    "url": "https://cartridges.machinefabric.com/release/pdfcartridge/1.368.920/pdfcartridge-1.368.920-darwin-arm64.pkg",
                    "sha256": "45a025d528ccdd174ced7444e27c1ab43357e6865a457e143838b28f3704ad53",
                    "size": 6795859
                  },
                  "packages": [
                    {
                      "name": "pdfcartridge-1.368.920-darwin-arm64.pkg",
                      "url": "https://cartridges.machinefabric.com/release/pdfcartridge/1.368.920/pdfcartridge-1.368.920-darwin-arm64.pkg",
                      "sha256": "45a025d528ccdd174ced7444e27c1ab43357e6865a457e143838b28f3704ad53",
                      "size": 6795859,
                      "format": "pkg"
                    }
                  ],
                  "binary": {
                    "name": "pdfcartridge-1.368.920-darwin-arm64.bin",
                    "url": "https://cartridges.machinefabric.com/release/pdfcartridge/1.368.920/pdfcartridge-1.368.920-darwin-arm64.bin",
                    "sha256": "cfbbd82575449e368f74e72e008d753227214550df1d1225d72ccfed0dbf27d7",
                    "size": 17775840,
                    "signature": "untrusted comment: signature from rsign secret key\nRUTbeBdFkW9D4tNkQ9yjCcVQ24jHaY0AF266jGoLIeUe2aYuupNZA6DZrryGh/AZvgp4plFHEks6tHFTI2qXI9NZvqF9+Tvxzww=\ntrusted comment: file:pdfcartridge-1.368.920-darwin-arm64.bin sha256=cfbbd82575449e368f74e72e008d753227214550df1d1225d72ccfed0dbf27d7\n0Xoi47Et63pUngVRnaf5hoK14CFxsBWwY74OpMoNtVFsouUM/j+OggD5ZnRoKoyIGh16QvVnGNwZlFmBBfy4Cw==\n"
                  }
                }
              ]
            }
          }
        },
        "candlecartridge": {
          "name": "candlecartridge",
          "description": "Candle ML inference cartridge for CapDAG",
          "author": "https://github.com/machinefabric",
          "pageUrl": "https://github.com/machinefabric/candlecartridge",
          "teamId": "P336JK947M",
          "minAppVersion": "1.0.0",
          "categories": [],
          "tags": [],
          "cap_groups": [
            {
              "name": "candle-inference",
              "caps": [
                {
                  "urn": "cap:effect=none",
                  "title": "Identity",
                  "aliases": [
                    "identity"
                  ],
                  "cap_description": "The categorical identity morphism. Echoes input as output unchanged. Mandatory in every capability set.",
                  "args": [
                    {
                      "media_urn": "media:",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:"
                        }
                      ]
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:",
                      "name": "output",
                      "output_description": "The input data, unchanged",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:candle;in=\"media:audio;ext=wav\";ml-model;out=\"media:enc=utf-8;record;transcription\";transcribe",
                  "version": 5,
                  "title": "Transcribe Audio (Candle) (Candle (Rust safetensors), ML Model)",
                  "aliases": [
                    "audio-transcription-candle",
                    "transcribe-candle"
                  ],
                  "cap_description": "Transcribe audio files to text using Whisper models with Candle ML framework",
                  "documentation": "## Purpose\n\nConverts spoken audio into text using OpenAI Whisper models running locally via the Candle ML framework. Runs on CPU or GPU without a network dependency after the model is downloaded.\n\n## Inputs\n\n- A WAV audio stream (mono or stereo, any sample rate Whisper supports) — a bounded file, or the UNBOUNDED streaming WAV a live microphone machine produces via `encode-audio-frames-wav`. Speech-tagged sources (`media:audio;ext=wav;speech`) conform as before; the `speech` tag is no longer required, and non-speech audio simply yields little or no text.\n- An optional language code (e.g. `en`, `fr`, `zh`). Omit to let Whisper auto-detect the language.\n- Every emitted record carries its window start/end times (window-level boundaries, not token-level timestamps) — there is no timestamps flag to forget.\n- An optional model spec pointing to a HuggingFace Whisper checkpoint. Defaults to `openai/whisper-base`, the offline-travel-kit transcription model.\n\n## Outputs\n\nA SEQUENCE of JSON transcription records, one per 30-second Whisper window, each carrying the window's text, its start/end times, the detected language, and the model name. Over a live microphone the records stream out as each window fills — live transcription — and the sequence ends when the feed stops. Over a bounded file the same per-window records arrive as they are transcribed.\n\n## Notes\n\n- Larger Whisper models (`whisper-small`, `whisper-medium`, `whisper-large-v3`) produce more accurate transcripts at the cost of memory and latency.\n- Input must be WAV. Convert other audio formats upstream before passing to this cap; live microphone capture arrives via `encode-audio-frames-wav` (the planner inserts it automatically for `media:audio;live;microphone` sources).\n- Audio of any length is transcribed in full: it is processed in Whisper's native 30-second windows and the window transcripts are concatenated in order. Nothing is truncated.\n- See also: [Generate Vector Embeddings (Candle)](https://capdag.com/browse/cap:generate-embeddings;candle;in=\"media:enc=utf-8\";ml-model;out=\"media:embedding-vector;enc=utf-8;record\") to embed the resulting transcript.\n\n## Backend\nThe inference framework or runtime that loads and executes a model. Backend choice\ndetermines weight format, hardware acceleration, and runtime characteristics. A media\nURN that omits the backend tag is backend-agnostic — it accepts any backend.\n\nCandle is a lightweight Rust-based ML framework. Loads models in safetensors format\ndirectly on CPU, Metal, or CUDA. Embeddable in Rust applications without Python\nruntime overhead.\n\n## ML model\nMarker indicating the cap invokes a machine-learning model. Inputs typically\ninclude a model spec or model artifact; the cap is subject to model-resolution\nand hardware-pressure policies.\n\nThe cap invokes a machine-learning model.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": true,
                      "sources": [
                        {
                          "stdin": "media:audio;ext=wav"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the audio file (WAV format)"
                    },
                    {
                      "media_urn": "media:enc=utf-8;language",
                      "name": "language",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--language"
                        }
                      ],
                      "arg_description": "Language code for transcription (e.g. en, fr, zh). Omit to auto-detect on multilingual models; English-only checkpoints accept only en."
                    },
                    {
                      "media_urn": "media:candle;enc=utf-8;model-spec;repo-safetensors;tokenizer-unified;transcription",
                      "name": "model",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model"
                        }
                      ],
                      "arg_description": "Whisper model name from HuggingFace",
                      "default_value": "hf:openai/whisper-base?include=*.json,*.safetensors"
                    },
                    {
                      "media_urn": "media:enc=utf-8;inference;model;model-loading;operator;policy",
                      "name": "model-loading",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-loading"
                        }
                      ],
                      "arg_description": "How the model's files are brought into memory: `map` memory-maps them, `read` reads them whole, `auto` maps from a local disk and reads from a network filesystem.",
                      "default_value": "auto"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:enc=utf-8;record;transcription",
                      "name": "output",
                      "output_description": "Transcribed text with optional timestamps and metadata",
                      "optional": false,
                      "is_sequence": true,
                      "streaming": true
                    }
                  ]
                },
                {
                  "urn": "cap:candle;embeddings-dimensions;in=\"media:candle;embeddings;enc=utf-8;model-spec;repo-safetensors;tokenizer-unified\";ml-model;out=\"media:integer;model-dim;numeric\"",
                  "version": 3,
                  "title": "Get Embeddings Dimensions (Candle) (Candle (Rust safetensors), ML Model)",
                  "aliases": [
                    "embeddings-dimensions-candle",
                    "embedding-dims-candle"
                  ],
                  "cap_description": "Query the dimensionality of embeddings for a given Candle model",
                  "documentation": "## Purpose\n\nReports the vector size that a Candle-based embedding model produces. Use this before creating a vector index so you know how many dimensions to allocate.\n\n## Inputs\n\n- A model spec pointing to a HuggingFace BERT-architecture embedding model. Defaults to `sentence-transformers/all-MiniLM-L6-v2`, the Candle embeddings model in the offline travel kit.\n\n## Outputs\n\nA single integer: the number of dimensions in each embedding vector this model produces.\n\n## Notes\n\n- The result is read from the model's saved configuration, not from running inference, so it is fast and requires no GPU memory.\n- Use at pipeline setup time to parameterize downstream vector store caps.\n- See also: [Generate Vector Embeddings (Candle)](https://capdag.com/browse/cap:generate-embeddings;candle;in=\"media:enc=utf-8\";ml-model;out=\"media:embedding-vector;enc=utf-8;record\")\n\n## Backend\nThe inference framework or runtime that loads and executes a model. Backend choice\ndetermines weight format, hardware acceleration, and runtime characteristics. A media\nURN that omits the backend tag is backend-agnostic — it accepts any backend.\n\nCandle is a lightweight Rust-based ML framework. Loads models in safetensors format\ndirectly on CPU, Metal, or CUDA. Embeddable in Rust applications without Python\nruntime overhead.\n\n## ML model\nMarker indicating the cap invokes a machine-learning model. Inputs typically\ninclude a model spec or model artifact; the cap is subject to model-resolution\nand hardware-pressure policies.\n\nThe cap invokes a machine-learning model.",
                  "args": [
                    {
                      "media_urn": "media:candle;embeddings;enc=utf-8;model-spec;repo-safetensors;tokenizer-unified",
                      "name": "input",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model"
                        },
                        {
                          "stdin": "media:candle;embeddings;enc=utf-8;model-spec;repo-safetensors;tokenizer-unified"
                        }
                      ],
                      "arg_description": "HuggingFace model name to query dimensions for",
                      "default_value": "hf:sentence-transformers/all-MiniLM-L6-v2?include=*.json,*.safetensors"
                    },
                    {
                      "media_urn": "media:enc=utf-8;inference;model;model-loading;operator;policy",
                      "name": "model-loading",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-loading"
                        }
                      ],
                      "arg_description": "How the model's files are brought into memory: `map` memory-maps them, `read` reads them whole, `auto` maps from a local disk and reads from a network filesystem.",
                      "default_value": "auto"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:integer;model-dim;numeric",
                      "name": "output",
                      "output_description": "Dimensionality of the embeddings (positive integer)",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:candle;generate-embeddings;in=\"media:enc=utf-8\";ml-model;out=\"media:embedding-vector;enc=utf-8;record\"",
                  "version": 4,
                  "title": "Generate Vector Embeddings (Candle) (Candle (Rust safetensors), ML Model)",
                  "aliases": [
                    "embeddings-generation-candle",
                    "embeddings-candle"
                  ],
                  "cap_description": "Generate vector embeddings from text using Candle ML framework on CPU/GPU",
                  "documentation": "## Purpose\n\nEncodes text into dense floating-point vectors suitable for semantic search, clustering, classification, and retrieval-augmented generation (RAG). Uses sentence-transformers models running locally via Candle on CPU or GPU. Long documents are automatically split into overlapping chunks; each chunk gets its own vector.\n\n## Inputs\n\n- A text file to embed.\n- A model spec (HuggingFace BERT-architecture repo). Defaults to `sentence-transformers/all-MiniLM-L6-v2`, the Candle embeddings model in the offline travel kit.\n- Chunk size in words (default 400) and chunk overlap in words (default 50). Adjust to match your retrieval granularity.\n\n## Outputs\n\nA JSON record containing an array of embedding objects. Each object includes the chunk text, its position in the document, the embedding vector (array of floats), and model metadata (model name, dimensions).\n\n## Notes\n\n- Choose chunk size based on context: smaller chunks (100-200 words) give precise retrieval; larger chunks (500-800 words) give more context per match.\n- Overlap prevents important content from being cut across chunk boundaries.\n- A chunk whose tokenization exceeds the model's positional capacity (512 tokens for MiniLM-class models) is embedded window-by-window and the window embeddings are mean-pooled weighted by token count, then L2-normalized — the whole chunk always contributes; nothing is rejected or silently truncated.\n- Candle supports both CPU and CUDA GPU. GPU significantly reduces latency for large documents.\n- Use [Get Embeddings Dimensions (Candle)](https://capdag.com/browse/cap:embeddings-dimensions;candle;in=\"media:candle;embeddings;enc=utf-8;model-spec;repo-safetensors;tokenizer-unified\";ml-model;out=\"media:integer;model-dim;numeric\") to check the vector size before building an index.\n- For GGUF-quantized models, see [Generate Vector Embeddings (GGUF)](https://capdag.com/browse/cap:generate-embeddings;gguf;in=\"media:enc=utf-8\";ml-model;out=\"media:embedding-vector;enc=utf-8;record\").\n\n## Backend\nThe inference framework or runtime that loads and executes a model. Backend choice\ndetermines weight format, hardware acceleration, and runtime characteristics. A media\nURN that omits the backend tag is backend-agnostic — it accepts any backend.\n\nCandle is a lightweight Rust-based ML framework. Loads models in safetensors format\ndirectly on CPU, Metal, or CUDA. Embeddable in Rust applications without Python\nruntime overhead.\n\n## ML model\nMarker indicating the cap invokes a machine-learning model. Inputs typically\ninclude a model spec or model artifact; the cap is subject to model-resolution\nand hardware-pressure policies.\n\nThe cap invokes a machine-learning model.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:enc=utf-8"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to text file to generate embeddings from"
                    },
                    {
                      "media_urn": "media:candle;embeddings;enc=utf-8;model-spec;repo-safetensors;tokenizer-unified",
                      "name": "model",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model"
                        }
                      ],
                      "arg_description": "HuggingFace model name for embeddings",
                      "default_value": "hf:sentence-transformers/all-MiniLM-L6-v2?include=*.json,*.safetensors"
                    },
                    {
                      "media_urn": "media:chunk-size;numeric",
                      "name": "chunk-size",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--chunk-size"
                        }
                      ],
                      "arg_description": "Chunk size in words for splitting input text",
                      "default_value": 400
                    },
                    {
                      "media_urn": "media:chunk-overlap;numeric",
                      "name": "chunk-overlap",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--chunk-overlap"
                        }
                      ],
                      "arg_description": "Chunk overlap in words when splitting input text",
                      "default_value": 50
                    },
                    {
                      "media_urn": "media:enc=utf-8;inference;model;model-loading;operator;policy",
                      "name": "model-loading",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-loading"
                        }
                      ],
                      "arg_description": "How the model's files are brought into memory: `map` memory-maps them, `read` reads them whole, `auto` maps from a local disk and reads from a network filesystem.",
                      "default_value": "auto"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:embedding-vector;enc=utf-8;record",
                      "name": "output",
                      "output_description": "JSON containing embeddings, chunk metadata and model information",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:candle;generate-image-embeddings;in=\"media:ext=png;image\";ml-model;out=\"media:embedding-vector;enc=utf-8;record\"",
                  "version": 4,
                  "title": "Generate Image Embeddings (Candle) (Candle (Rust safetensors), ML Model)",
                  "aliases": [
                    "embeddings-generation-image",
                    "image-embeddings-candle"
                  ],
                  "cap_description": "Generate image embeddings using CLIP models with Candle ML framework",
                  "documentation": "## Purpose\n\nEncodes a PNG image into a dense floating-point vector using CLIP (Contrastive Language-Image Pretraining). The resulting vector lives in the same semantic space as CLIP text embeddings, enabling cross-modal similarity search — find images by text queries and vice versa.\n\n## Inputs\n\n- A PNG image file.\n- A CLIP-architecture model spec from HuggingFace. Defaults to `openai/clip-vit-base-patch32`, the image-embeddings model in the offline travel kit.\n\n## Outputs\n\nA JSON record containing the image embedding vector and model metadata.\n\n## Notes\n\n- CLIP image and text vectors are compatible: you can compare an image embedding to text embeddings generated by a CLIP text encoder in the same vector space.\n- Input must be PNG. An image in another format is converted first with [Convert Image Format](https://capdag.com/browse/cap:convert-image;in=media:image;out=media:image); a machine planned from a JPEG or WebP source takes that step by itself.\n- For describing image content in natural language rather than embedding it, use [Describe Image (Candle)](https://capdag.com/browse/cap:describe-image;candle;in=\"media:ext=png;image\";ml-model;out=\"media:enc=utf-8;ext=txt;image-description;plain-text\").\n\n## Backend\nThe inference framework or runtime that loads and executes a model. Backend choice\ndetermines weight format, hardware acceleration, and runtime characteristics. A media\nURN that omits the backend tag is backend-agnostic — it accepts any backend.\n\nCandle is a lightweight Rust-based ML framework. Loads models in safetensors format\ndirectly on CPU, Metal, or CUDA. Embeddable in Rust applications without Python\nruntime overhead.\n\n## ML model\nMarker indicating the cap invokes a machine-learning model. Inputs typically\ninclude a model spec or model artifact; the cap is subject to model-resolution\nand hardware-pressure policies.\n\nThe cap invokes a machine-learning model.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=png;image"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the image file to embed"
                    },
                    {
                      "media_urn": "media:candle;enc=utf-8;image-embeddings;model-spec",
                      "name": "model",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model"
                        }
                      ],
                      "arg_description": "CLIP-architecture model name from HuggingFace",
                      "default_value": "hf:openai/clip-vit-base-patch32?include=*.json,*.safetensors,pytorch_model.bin"
                    },
                    {
                      "media_urn": "media:enc=utf-8;inference;model;model-loading;operator;policy",
                      "name": "model-loading",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-loading"
                        }
                      ],
                      "arg_description": "How the model's files are brought into memory: `map` memory-maps them, `read` reads them whole, `auto` maps from a local disk and reads from a network filesystem.",
                      "default_value": "auto"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:embedding-vector;enc=utf-8;record",
                      "name": "output",
                      "output_description": "Image embedding vector with model metadata",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:candle;in=\"media:fmt=json;llm-generation-request;record\";llm;llm-inference;ml-model;out=\"media:fmt=ndjson;llm-text-stream\"",
                  "version": 3,
                  "title": "LLM Text Generation (Candle) (Candle (Rust safetensors), LLM, ML Model)",
                  "aliases": [
                    "llm-inference-candle"
                  ],
                  "cap_description": "Generate text using Candle transformer models. Output is NDJSON streaming tokens.",
                  "documentation": "## Purpose\n\nRuns autoregressive text generation using Candle transformer models (safetensors format). Accepts a fully-structured generation request and streams output as NDJSON tokens. This is the low-level inference cap used by higher-level caps like Summarize and Generate Code.\n\n## Inputs\n\nA single JSON generation request record containing: the prompt, model spec (HuggingFace safetensors repo), sampling parameters (temperature, top-p, max tokens, seed), and an optional system prompt.\n\nOptional HuggingFace bearer token (`hf_token`) for gated repositories — required for `gemma`, `gemma2`, `gemma3` and any other licence-protected model.\n\n## Outputs\n\nAn NDJSON stream. Each line is a JSON object. Lines carry token text, status events (`started`, `complete`), and a final summary with total tokens and timing.\n\n## Notes\n\n- Every execution is streaming — there is no non-streaming mode.\n- Candle runs on CPU, Metal, or CUDA. GPU is strongly recommended for models larger than 3B parameters.\n- Architectures supported: mistral, llama, qwen2, qwen3, phi, phi3, gemma, gemma2, gemma3, falcon, olmo, olmo2. The architecture is detected from the model's `config.json` `model_type` — pickers driven by `supported_model_types` will reject any model whose architecture is outside this list. Yi is unsupported in this cap because `candle-transformers` 0.9.2 ships a non-deserialisable `yi::Config`; use the GGUF or MLX backends for Yi.\n- For higher-level tasks (summarization, code generation, creative writing), use the task-specific inference caps rather than this one directly.\n- For constrained output (JSON schema, regex), use [Constrained LLM Generation (GGUF)](https://capdag.com/browse/cap:llm-inference-constrained;constrained;gguf;in=\"media:fmt=json;llm-generation-request;record\";llm;ml-model;out=\"media:fmt=ndjson;llm-text-stream\").\n\n## Backend\nThe inference framework or runtime that loads and executes a model. Backend choice\ndetermines weight format, hardware acceleration, and runtime characteristics. A media\nURN that omits the backend tag is backend-agnostic — it accepts any backend.\n\nCandle is a lightweight Rust-based ML framework. Loads models in safetensors format\ndirectly on CPU, Metal, or CUDA. Embeddable in Rust applications without Python\nruntime overhead.\n\n## Model task\nThe inference modality of a model. Model-task narrows what kind of inference cap a\nmodel spec is suitable for: an LLM cannot serve transcription, a transcription model\ncannot serve text generation. The task tag is part of the model-spec URN; it is set\nby the cap declaring its model-spec input slot, not derived from the model file.\n\nCausal language model for text generation and instruction following. Accepts a text\nprompt and produces a text continuation, typically token-by-token via streaming.\n\n## ML model\nMarker indicating the cap invokes a machine-learning model. Inputs typically\ninclude a model spec or model artifact; the cap is subject to model-resolution\nand hardware-pressure policies.\n\nThe cap invokes a machine-learning model.",
                  "args": [
                    {
                      "media_urn": "media:fmt=json;llm-generation-request;record",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:fmt=json;llm-generation-request;record"
                        }
                      ],
                      "arg_description": "The generation request containing prompt, model spec, and parameters"
                    },
                    {
                      "media_urn": "media:enc=utf-8;hf-token;secret",
                      "name": "hf-token",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--hf-token"
                        }
                      ],
                      "arg_description": "HuggingFace bearer token. Required when targeting a gated repository (license-protected models). Without it, gated downloads fail with a clear authentication error."
                    },
                    {
                      "media_urn": "media:enc=utf-8;inference;model;model-loading;operator;policy",
                      "name": "model-loading",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-loading"
                        }
                      ],
                      "arg_description": "How the model's files are brought into memory: `map` memory-maps them, `read` reads them whole, `auto` maps from a local disk and reads from a network filesystem.",
                      "default_value": "auto"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:fmt=ndjson;llm-text-stream",
                      "name": "output",
                      "output_description": "NDJSON stream of tokens, status updates, and completion message",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:candle;generate-text;in=\"media:enc=utf-8\";llm;ml-model;out=\"media:enc=utf-8;ext=txt;plain-text\"",
                  "version": 3,
                  "title": "Generate Text with LLM (Candle) (Candle (Rust safetensors), LLM, ML Model)",
                  "aliases": [
                    "llm-text-generation-candle",
                    "generate-text-candle"
                  ],
                  "cap_description": "Generate text using Candle transformer models (multi-architecture safetensors).",
                  "documentation": "## Purpose\n\nAccepts a raw text prompt and generates a text continuation using a Candle safetensors LLM. This is a simpler, prompt-in / text-out interface compared to the structured request used by the llm-inference caps. Suitable for quick text generation without building a full generation request object.\n\n## Inputs\n\n- A text prompt (plain text, passed via stdin or positional arg).\n- A model spec (HuggingFace safetensors repo). Defaults to `Qwen/Qwen2.5-0.5B-Instruct`, the Candle LLM in the offline travel kit.\n- Sampling parameters: max tokens (512), temperature (0.7), top-p (0.9), seed (42).\n- Optional HuggingFace bearer token (`hf_token`) for gated repositories — required for `gemma`, `gemma2`, `gemma3` and any other licence-protected model.\n\n## Outputs\n\nGenerated text streamed as raw text chunks (not NDJSON).\n\n## Notes\n\n- Architectures supported: mistral, llama, qwen2, qwen3, phi, phi3, gemma, gemma2, gemma3, falcon, olmo, olmo2. The architecture is detected from the model's `config.json` `model_type` — pickers driven by `supported_model_types` will reject any model whose architecture is outside this list. Yi is unsupported in this cap because `candle-transformers` 0.9.2 ships a non-deserialisable `yi::Config`; use the GGUF or MLX backends for Yi.\n- For structured output, system prompts, or streaming JSON events, use [LLM Text Generation (Candle)](https://capdag.com/browse/cap:llm-inference;candle;in=\"media:fmt=json;llm-generation-request;record\";llm;ml-model;out=\"media:fmt=ndjson;llm-text-stream\") instead.\n- Requires safetensors model weights (not GGUF).\n- Gated repositories require `hf_token`. Without one, the call fails hard with a clear authentication error rather than silently downgrading.\n\n## Backend\nThe inference framework or runtime that loads and executes a model. Backend choice\ndetermines weight format, hardware acceleration, and runtime characteristics. A media\nURN that omits the backend tag is backend-agnostic — it accepts any backend.\n\nCandle is a lightweight Rust-based ML framework. Loads models in safetensors format\ndirectly on CPU, Metal, or CUDA. Embeddable in Rust applications without Python\nruntime overhead.\n\n## Model task\nThe inference modality of a model. Model-task narrows what kind of inference cap a\nmodel spec is suitable for: an LLM cannot serve transcription, a transcription model\ncannot serve text generation. The task tag is part of the model-spec URN; it is set\nby the cap declaring its model-spec input slot, not derived from the model file.\n\nCausal language model for text generation and instruction following. Accepts a text\nprompt and produces a text continuation, typically token-by-token via streaming.\n\n## ML model\nMarker indicating the cap invokes a machine-learning model. Inputs typically\ninclude a model spec or model artifact; the cap is subject to model-resolution\nand hardware-pressure policies.\n\nThe cap invokes a machine-learning model.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:enc=utf-8"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Input text prompt for generation"
                    },
                    {
                      "media_urn": "media:enc=utf-8;system-prompt",
                      "name": "system-prompt",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--system-prompt"
                        }
                      ],
                      "arg_description": "System prompt that frames the model's behaviour for the request. Applied via the model's chat template when the downloaded model carries one (chat-template-jinja or chat-template-short); ignored for base/completion models. Default is a generic helpful-assistant frame that works for arbitrary user input — task-specific prompts (summarise, translate, explain) belong in the user-message slot.",
                      "default_value": "You are a helpful assistant. Respond to the user's input with a useful, accurate, and concise reply. If the input is a document or excerpt, treat it as the subject of the user's request and respond about it."
                    },
                    {
                      "media_urn": "media:candle;enc=utf-8;llm;model-spec;repo-safetensors;tokenizer-unified",
                      "name": "model-spec",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-spec"
                        }
                      ],
                      "arg_description": "Candle model specification (HuggingFace repo with safetensors weights and a unified tokenizer.json)",
                      "default_value": "hf:Qwen/Qwen2.5-0.5B-Instruct?include=*.json,*.safetensors"
                    },
                    {
                      "media_urn": "media:enc=utf-8;hf-token;secret",
                      "name": "hf-token",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--hf-token"
                        }
                      ],
                      "arg_description": "HuggingFace bearer token. Required when targeting a gated repository (license-protected models). Without it, gated downloads fail with a clear authentication error."
                    },
                    {
                      "media_urn": "media:inference;limit;max-tokens;numeric;task;user",
                      "name": "max-tokens",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--max-tokens"
                        }
                      ],
                      "arg_description": "Maximum number of tokens to generate",
                      "default_value": 512
                    },
                    {
                      "media_urn": "media:inference;numeric;sampling;task;temperature;user",
                      "name": "temperature",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--temperature"
                        }
                      ],
                      "arg_description": "Sampling temperature (0.0-2.0)",
                      "default_value": 0.7
                    },
                    {
                      "media_urn": "media:inference;numeric;sampling;task;top-p;user",
                      "name": "top-p",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--top-p"
                        }
                      ],
                      "arg_description": "Top-p (nucleus) sampling parameter",
                      "default_value": 0.9
                    },
                    {
                      "media_urn": "media:numeric;seed",
                      "name": "seed",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--seed"
                        }
                      ],
                      "arg_description": "Random seed for reproducibility",
                      "default_value": 42
                    },
                    {
                      "media_urn": "media:enc=utf-8;inference;model;model-loading;operator;policy",
                      "name": "model-loading",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-loading"
                        }
                      ],
                      "arg_description": "How the model's files are brought into memory: `map` memory-maps them, `read` reads them whole, `auto` maps from a local disk and reads from a network filesystem.",
                      "default_value": "auto"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:enc=utf-8;ext=txt;plain-text",
                      "name": "output",
                      "output_description": "Generated text streamed as raw text chunks",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:candle;describe-image;in=\"media:ext=png;image\";ml-model;out=\"media:enc=utf-8;ext=txt;image-description;plain-text\"",
                  "version": 4,
                  "title": "Describe Image (Candle) (Candle (Rust safetensors), ML Model)",
                  "aliases": [
                    "vision-describe-candle",
                    "describe-image-candle"
                  ],
                  "cap_description": "Generate image descriptions using BLIP models with Candle ML framework",
                  "documentation": "## Purpose\n\nGenerates a natural-language description of a PNG image using BLIP (Bootstrapped Language-Image Pretraining) models running locally via Candle. Suitable for alt-text generation, image indexing, and content moderation pipelines.\n\n## Inputs\n\n- A PNG image file.\n- An optional caption PREFIX the model continues (BLIP conditional captioning, e.g. \"a photograph of\") — BLIP is a captioner, not an instruction-follower, so the prompt is not a question or instruction. Without a prompt, BLIP produces a general caption.\n- An optional maximum caption length in tokens (default 256).\n- A BLIP model spec from HuggingFace. Defaults to `Salesforce/blip-image-captioning-large`, the Candle vision model in the offline travel kit.\n\n## Outputs\n\nA text description of the image as a plain string.\n\n## Notes\n\n- BLIP models produce shorter, more caption-like descriptions than vision-language models (LLaVA/Qwen). For detailed, instruction-following descriptions, prefer [Describe Image (GGUF)](https://capdag.com/browse/cap:describe-image;gguf;in=\"media:ext=png;image\";ml-model;out=\"media:enc=utf-8;ext=txt;image-description;plain-text\";vision) or [Describe Image (MLX)](https://capdag.com/browse/cap:describe-image;in=\"media:ext=png;image\";ml-model;mlx;out=\"media:enc=utf-8;ext=txt;image-description;plain-text\";vision).\n- Input must be PNG. An image in another format is converted first with [Convert Image Format](https://capdag.com/browse/cap:convert-image;in=media:image;out=media:image); a machine planned from a JPEG or WebP source takes that step by itself.\n- For embedding an image into a vector space rather than describing it, use [Generate Image Embeddings (Candle)](https://capdag.com/browse/cap:generate-image-embeddings;candle;in=\"media:ext=png;image\";ml-model;out=\"media:embedding-vector;enc=utf-8;record\").\n\n## Backend\nThe inference framework or runtime that loads and executes a model. Backend choice\ndetermines weight format, hardware acceleration, and runtime characteristics. A media\nURN that omits the backend tag is backend-agnostic — it accepts any backend.\n\nCandle is a lightweight Rust-based ML framework. Loads models in safetensors format\ndirectly on CPU, Metal, or CUDA. Embeddable in Rust applications without Python\nruntime overhead.\n\n## ML model\nMarker indicating the cap invokes a machine-learning model. Inputs typically\ninclude a model spec or model artifact; the cap is subject to model-resolution\nand hardware-pressure policies.\n\nThe cap invokes a machine-learning model.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=png;image"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the image file to describe"
                    },
                    {
                      "media_urn": "media:enc=utf-8;prompt",
                      "name": "prompt",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--prompt"
                        }
                      ],
                      "arg_description": "Optional caption PREFIX the model continues (BLIP conditional captioning, e.g. \"a photograph of\") — not an instruction. Omit for unconditional captioning."
                    },
                    {
                      "media_urn": "media:inference;limit;max-tokens;numeric;task;user",
                      "name": "max-tokens",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--max-tokens"
                        }
                      ],
                      "arg_description": "Maximum caption length in tokens",
                      "default_value": 256
                    },
                    {
                      "media_urn": "media:enc=utf-8;system-prompt",
                      "name": "system-prompt",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--system-prompt"
                        }
                      ],
                      "arg_description": "System prompt that frames the model's behaviour for the request. Applied via the model's chat template when the downloaded VLM carries one (chat-template-jinja or chat-template-short); dropped for base/completion vision models such as BLIP. Default is a generic helpful-assistant frame; concrete per-image instructions belong in the prompt slot.",
                      "default_value": "You are a helpful assistant. Respond to the user's input with a useful, accurate, and concise reply. If the input is a document or excerpt, treat it as the subject of the user's request and respond about it."
                    },
                    {
                      "media_urn": "media:candle;enc=utf-8;model-spec;repo-safetensors;tokenizer-unified;vision",
                      "name": "model",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model"
                        }
                      ],
                      "arg_description": "BLIP model name from HuggingFace",
                      "default_value": "hf:Salesforce/blip-image-captioning-large?include=*.json,*.safetensors"
                    },
                    {
                      "media_urn": "media:enc=utf-8;inference;model;model-loading;operator;policy",
                      "name": "model-loading",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-loading"
                        }
                      ],
                      "arg_description": "How the model's files are brought into memory: `map` memory-maps them, `read` reads them whole, `auto` maps from a local disk and reads from a network filesystem.",
                      "default_value": "auto"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:enc=utf-8;ext=txt;image-description;plain-text",
                      "name": "output",
                      "output_description": "Generated text description of the image",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                }
              ]
            }
          ],
          "latestVersion": "1.375.1167",
          "versions": {
            "1.375.1167": {
              "releaseDate": "2026-10-15T07:24:33Z",
              "changelog": [
                "Initial release"
              ],
              "minAppVersion": "1.0.0",
              "builds": [
                {
                  "platform": "darwin-arm64",
                  "package": {
                    "name": "candlecartridge-1.375.1167-darwin-arm64.pkg",
                    "url": "https://cartridges.machinefabric.com/release/candlecartridge/1.375.1167/candlecartridge-1.375.1167-darwin-arm64.pkg",
                    "sha256": "cb636905fbb8a2785688eb19dfb1c4d1d18641abdf0f0bd4da18107f56928624",
                    "size": 6447681
                  },
                  "packages": [
                    {
                      "name": "candlecartridge-1.375.1167-darwin-arm64.pkg",
                      "url": "https://cartridges.machinefabric.com/release/candlecartridge/1.375.1167/candlecartridge-1.375.1167-darwin-arm64.pkg",
                      "sha256": "cb636905fbb8a2785688eb19dfb1c4d1d18641abdf0f0bd4da18107f56928624",
                      "size": 6447681,
                      "format": "pkg"
                    }
                  ],
                  "binary": {
                    "name": "candlecartridge-1.375.1167-darwin-arm64.bin",
                    "url": "https://cartridges.machinefabric.com/release/candlecartridge/1.375.1167/candlecartridge-1.375.1167-darwin-arm64.bin",
                    "sha256": "53c83dfc3bc51333cba6c29e79f6b34f2d0298b38f5411953b32111717d7379a",
                    "size": 20425472,
                    "signature": "untrusted comment: signature from rsign secret key\nRUTbeBdFkW9D4j5OvLOYBytgLHBaOdpn24cvn5lywZPuzJZuPqmkzPv3NDxNLBFoOciy9nMJtHXZpARJAcrPPpQssTpEwLXf1w0=\ntrusted comment: file:candlecartridge-1.375.1167-darwin-arm64.bin sha256=53c83dfc3bc51333cba6c29e79f6b34f2d0298b38f5411953b32111717d7379a\noTm58atDYYBJQ7zBuvF17HlrbZJUBsyngxNS2RC8v70D2lEfe7PZjhA1JG2f7IfgGNRltQjTwpVQ3kuPKGSRDQ==\n"
                  }
                }
              ]
            }
          }
        },
        "ggufcartridge": {
          "name": "ggufcartridge",
          "description": "GGUF model inference cartridge with content inspection",
          "author": "https://github.com/machinefabric",
          "pageUrl": "https://github.com/machinefabric/ggufcartridge",
          "teamId": "P336JK947M",
          "minAppVersion": "1.0.0",
          "categories": [],
          "tags": [],
          "cap_groups": [
            {
              "name": "gguf-models",
              "caps": [
                {
                  "urn": "cap:effect=none",
                  "title": "Identity",
                  "aliases": [
                    "identity"
                  ],
                  "cap_description": "The categorical identity morphism. Echoes input as output unchanged. Mandatory in every capability set.",
                  "args": [
                    {
                      "media_urn": "media:",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:"
                        }
                      ]
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:",
                      "name": "output",
                      "output_description": "The input data, unchanged",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:embeddings-dimensions;gguf;in=\"media:embeddings;enc=utf-8;gguf;model-spec;tokenizer-embedded-gguf\";ml-model;out=\"media:integer;model-dim;numeric\"",
                  "version": 4,
                  "title": "Get Embeddings Dimensions (GGUF) (GGUF (llama.cpp), ML Model)",
                  "aliases": [
                    "embeddings-dimensions-gguf",
                    "embedding-dims-gguf"
                  ],
                  "cap_description": "Query the dimensionality of embeddings for a given GGUF model",
                  "documentation": "## Purpose\n\nReports the vector size that a GGUF embedding model produces by reading `n_embd` from the model's metadata. Use this before creating a vector index so you know how many dimensions to allocate.\n\n## Inputs\n\n- A GGUF model spec (HuggingFace repo or local path). Defaults to `nomic-ai/nomic-embed-text-v1.5-GGUF`, the GGUF embeddings model in the offline travel kit.\n\n## Outputs\n\nA single integer: the `n_embd` value from the GGUF model header.\n\n## Notes\n\n- Reads model metadata only — no inference is run.\n- Use at pipeline setup time to parameterize downstream vector store caps.\n- See also: [Generate Vector Embeddings (GGUF)](https://capdag.com/browse/cap:generate-embeddings;gguf;in=\"media:enc=utf-8\";ml-model;out=\"media:embedding-vector;enc=utf-8;record\")\n\n## Backend\nThe inference framework or runtime that loads and executes a model. Backend choice\ndetermines weight format, hardware acceleration, and runtime characteristics. A media\nURN that omits the backend tag is backend-agnostic — it accepts any backend.\n\nGGUF is the llama.cpp container format. Quantised weights packaged into a single\nfile with embedded metadata. Runs efficiently on CPU and via Metal/CUDA acceleration.\nStandard format for general-purpose LLM and embedding inference across hardware.\n\n## ML model\nMarker indicating the cap invokes a machine-learning model. Inputs typically\ninclude a model spec or model artifact; the cap is subject to model-resolution\nand hardware-pressure policies.\n\nThe cap invokes a machine-learning model.",
                  "args": [
                    {
                      "media_urn": "media:embeddings;enc=utf-8;gguf;model-spec;tokenizer-embedded-gguf",
                      "name": "input",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-spec"
                        },
                        {
                          "stdin": "media:embeddings;enc=utf-8;gguf;model-spec;tokenizer-embedded-gguf"
                        }
                      ],
                      "arg_description": "GGUF model specification to query dimensions for",
                      "default_value": "hf:nomic-ai/nomic-embed-text-v1.5-GGUF?include=*Q4_K_M*.gguf,*.json,*.txt,README*"
                    },
                    {
                      "media_urn": "media:enc=utf-8;inference;model;model-loading;operator;policy",
                      "name": "model-loading",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-loading"
                        }
                      ],
                      "arg_description": "How the model's files are brought into memory: `map` memory-maps them, `read` reads them whole, `auto` maps from a local disk and reads from a network filesystem.",
                      "default_value": "auto"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:integer;model-dim;numeric",
                      "name": "output",
                      "output_description": "Dimensionality of the embeddings (n_embd from model metadata)",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:generate-embeddings;gguf;in=\"media:enc=utf-8\";ml-model;out=\"media:embedding-vector;enc=utf-8;record\"",
                  "version": 5,
                  "title": "Generate Vector Embeddings (GGUF) (GGUF (llama.cpp), ML Model)",
                  "aliases": [
                    "embeddings-generation-gguf",
                    "embeddings-gguf"
                  ],
                  "cap_description": "Generate vector embeddings from text using GGUF models with llama.cpp backend",
                  "documentation": "## Purpose\n\nEncodes text into dense floating-point vectors using quantized GGUF embedding models via llama.cpp. Suitable for semantic search, clustering, and RAG. Long documents are automatically split into overlapping chunks.\n\n## Inputs\n\n- A GGUF model spec (HuggingFace repo or local path). Defaults to `nomic-ai/nomic-embed-text-v1.5-GGUF`, the GGUF embeddings model in the offline travel kit.\n- A text file to embed.\n- Chunk size in words (default 400), chunk overlap in words (default 50), and batch size in tokens (default 2048).\n\n## Outputs\n\nA JSON record containing an array of embedding objects. Each object includes the chunk text, its position, the L2-normalized embedding vector, and model metadata.\n\n## Notes\n\n- GGUF quantization makes models smaller and faster at a small accuracy trade-off. Q4 and Q8 quantizations are common choices.\n- Vectors are L2-normalized. Use cosine similarity or dot product when comparing vectors from this cap.\n- Batch size is a per-decode memory bound, never a correctness ceiling: a chunk whose tokenization exceeds the usable window (the smaller of the model's trained context and the batch size) is embedded window-by-window and the window embeddings are mean-pooled weighted by token count, then L2-normalized — the whole chunk always contributes.\n- Use [Get Embeddings Dimensions (GGUF)](https://capdag.com/browse/cap:embeddings-dimensions;gguf;in=\"media:embeddings;enc=utf-8;gguf;model-spec;tokenizer-embedded-gguf\";ml-model;out=\"media:integer;model-dim;numeric\") to check the vector size.\n- For Apple Silicon, prefer [Generate Vector Embeddings (MLX)](https://capdag.com/browse/cap:generate-embeddings;mlx;in=\"media:enc=utf-8\";ml-model;out=\"media:embedding-vector;enc=utf-8;record\").\n\n## Backend\nThe inference framework or runtime that loads and executes a model. Backend choice\ndetermines weight format, hardware acceleration, and runtime characteristics. A media\nURN that omits the backend tag is backend-agnostic — it accepts any backend.\n\nGGUF is the llama.cpp container format. Quantised weights packaged into a single\nfile with embedded metadata. Runs efficiently on CPU and via Metal/CUDA acceleration.\nStandard format for general-purpose LLM and embedding inference across hardware.\n\n## ML model\nMarker indicating the cap invokes a machine-learning model. Inputs typically\ninclude a model spec or model artifact; the cap is subject to model-resolution\nand hardware-pressure policies.\n\nThe cap invokes a machine-learning model.",
                  "args": [
                    {
                      "media_urn": "media:embeddings;enc=utf-8;gguf;model-spec;tokenizer-embedded-gguf",
                      "name": "model-spec",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-spec"
                        }
                      ],
                      "arg_description": "GGUF model specification (HuggingFace repo or local path)",
                      "default_value": "hf:nomic-ai/nomic-embed-text-v1.5-GGUF?include=*Q4_K_M*.gguf,*.json,*.txt,README*"
                    },
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:enc=utf-8"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to text file to generate embeddings from"
                    },
                    {
                      "media_urn": "media:chunk-size;numeric",
                      "name": "chunk-size",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--chunk-size"
                        }
                      ],
                      "arg_description": "Chunk size in words for splitting input text",
                      "default_value": 400
                    },
                    {
                      "media_urn": "media:chunk-overlap;numeric",
                      "name": "chunk-overlap",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--chunk-overlap"
                        }
                      ],
                      "arg_description": "Chunk overlap in words when splitting input text",
                      "default_value": 50
                    },
                    {
                      "media_urn": "media:batch-size;inference;limit;numeric;operator;task",
                      "name": "batch-size",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--batch-size"
                        }
                      ],
                      "arg_description": "Per-decode token window bound (memory knob). Chunks tokenizing past the usable window are embedded window-by-window and mean-pooled — never rejected or truncated.",
                      "default_value": 2048
                    },
                    {
                      "media_urn": "media:enc=utf-8;inference;model;model-loading;operator;policy",
                      "name": "model-loading",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-loading"
                        }
                      ],
                      "arg_description": "How the model's files are brought into memory: `map` memory-maps them, `read` reads them whole, `auto` maps from a local disk and reads from a network filesystem.",
                      "default_value": "auto"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:embedding-vector;enc=utf-8;record",
                      "name": "output",
                      "output_description": "JSON containing L2-normalized embeddings, chunk metadata and model information",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:constrained;gguf;in=\"media:fmt=json;llm-generation-request;record\";llm;llm-inference-constrained;ml-model;out=\"media:fmt=ndjson;llm-text-stream\"",
                  "version": 3,
                  "title": "Constrained LLM Generation (GGUF) (ML Model, GGUF (llama.cpp), LLM, Constrained)",
                  "aliases": [
                    "llm-inference-constrained-gguf"
                  ],
                  "cap_description": "Generate text with LLGuidance constraints (JSON schema, regex, grammar). Output is NDJSON streaming.",
                  "documentation": "## Purpose\n\nRuns autoregressive text generation with hard structural constraints using LLGuidance. The model is guaranteed to produce output that matches the supplied JSON schema, regular expression, or grammar — making this the right cap when downstream code must parse the LLM output without error handling for malformed text.\n\n## Inputs\n\nA JSON generation request record that additionally includes a `constraint` field. The constraint can be one of:\n- `json_schema`: a JSON Schema object the output must validate against\n- `regex`: a regular expression string the output must match\n- `grammar`: a context-free grammar in GBNF or LLGuidance format\n\n## Outputs\n\nAn NDJSON stream of constrained tokens and a final completion message, same format as the unconstrained inference caps.\n\n## Notes\n\n- Constraint enforcement happens at the token-sampling level via LLGuidance — the model cannot produce tokens that would violate the constraint.\n- Structured output via JSON schema is the most common use case: specify the exact fields and types you need and receive valid JSON every time.\n- Performance overhead compared to unconstrained inference is small for simple schemas; complex grammars may add latency.\n- Use this cap when building pipelines where a downstream cap expects well-formed JSON and you cannot tolerate parse failures.\n- See also: [Make a Decision](https://capdag.com/browse/cap:make-decision;constrained;in=\"media:enc=utf-8\";language=en;out=\"media:decision;fmt=json;record\") and [Generate JSON](https://capdag.com/browse/cap:generate-json;constrained;in=\"media:enc=utf-8\";language=en;out=\"media:fmt=json;record\") for higher-level constrained tasks.\n\n## ML model\nMarker indicating the cap invokes a machine-learning model. Inputs typically\ninclude a model spec or model artifact; the cap is subject to model-resolution\nand hardware-pressure policies.\n\nThe cap invokes a machine-learning model.\n\n## Backend\nThe inference framework or runtime that loads and executes a model. Backend choice\ndetermines weight format, hardware acceleration, and runtime characteristics. A media\nURN that omits the backend tag is backend-agnostic — it accepts any backend.\n\nGGUF is the llama.cpp container format. Quantised weights packaged into a single\nfile with embedded metadata. Runs efficiently on CPU and via Metal/CUDA acceleration.\nStandard format for general-purpose LLM and embedding inference across hardware.\n\n## Model task\nThe inference modality of a model. Model-task narrows what kind of inference cap a\nmodel spec is suitable for: an LLM cannot serve transcription, a transcription model\ncannot serve text generation. The task tag is part of the model-spec URN; it is set\nby the cap declaring its model-spec input slot, not derived from the model file.\n\nCausal language model for text generation and instruction following. Accepts a text\nprompt and produces a text continuation, typically token-by-token via streaming.\n\n## Constrained\nMarker indicating constrained generation: output is forced to satisfy a schema\nor grammar. The model is guided so only valid tokens are sampled at each step;\noutput is structurally guaranteed.\n\nThe cap performs constrained generation.",
                  "args": [
                    {
                      "media_urn": "media:fmt=json;llm-generation-request;record",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:fmt=json;llm-generation-request;record"
                        }
                      ],
                      "arg_description": "The generation request with constraint field (json_schema, regex, or grammar)"
                    },
                    {
                      "media_urn": "media:enc=utf-8;hf-token;secret",
                      "name": "hf-token",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--hf-token"
                        }
                      ],
                      "arg_description": "HuggingFace bearer token. Required when targeting a gated repository."
                    },
                    {
                      "media_urn": "media:enc=utf-8;inference;model;model-loading;operator;policy",
                      "name": "model-loading",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-loading"
                        }
                      ],
                      "arg_description": "How the model's files are brought into memory: `map` memory-maps them, `read` reads them whole, `auto` maps from a local disk and reads from a network filesystem.",
                      "default_value": "auto"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:fmt=ndjson;llm-text-stream",
                      "name": "output",
                      "output_description": "NDJSON stream of constrained tokens and completion",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:gguf;in=\"media:fmt=json;llm-generation-request;record\";llm;llm-inference;ml-model;out=\"media:fmt=ndjson;llm-text-stream\"",
                  "version": 3,
                  "title": "LLM Text Generation (GGUF) (GGUF (llama.cpp), LLM, ML Model)",
                  "aliases": [
                    "llm-inference-gguf"
                  ],
                  "cap_description": "Generate text using GGUF models with llama.cpp backend. Output is NDJSON streaming tokens.",
                  "documentation": "## Purpose\n\nRuns autoregressive text generation using quantized GGUF models via llama.cpp. Accepts a fully-structured generation request and streams output as NDJSON tokens. This is the primary low-level inference cap for GGUF-based pipelines.\n\n## Inputs\n\nA single JSON generation request record containing: the prompt, model spec (HuggingFace GGUF repo or local path), sampling parameters (temperature, top-k, top-p, min-p, repeat penalty, max tokens, seed, context length), and an optional system prompt. Context length 0 (or omitted) auto-sizes to prompt + max-tokens, capped at the model's trained context; the prompt prefills in batch-sized windows, so batch size never limits prompt length and input is never silently truncated.\n\nOptional HuggingFace bearer token (`hf_token`) for gated repositories.\n\n## Outputs\n\nAn NDJSON stream. Each line is a JSON object carrying token text, status events (`started`, `complete`), and a final summary with token counts and timing.\n\n## Notes\n\n- Every execution is streaming — there is no non-streaming mode.\n- GGUF quantization reduces memory requirements significantly. Q8_0 preserves most accuracy; Q4_K_M is a good balance of size and quality.\n- For constrained output (JSON schema, regex), use [Constrained LLM Generation (GGUF)](https://capdag.com/browse/cap:llm-inference-constrained;constrained;gguf;in=\"media:fmt=json;llm-generation-request;record\";llm;ml-model;out=\"media:fmt=ndjson;llm-text-stream\").\n- For Apple Silicon, prefer [LLM Text Generation (MLX)](https://capdag.com/browse/cap:llm-inference;in=\"media:fmt=json;llm-generation-request;record\";llm;ml-model;mlx;out=\"media:fmt=ndjson;llm-text-stream\").\n\n## Backend\nThe inference framework or runtime that loads and executes a model. Backend choice\ndetermines weight format, hardware acceleration, and runtime characteristics. A media\nURN that omits the backend tag is backend-agnostic — it accepts any backend.\n\nGGUF is the llama.cpp container format. Quantised weights packaged into a single\nfile with embedded metadata. Runs efficiently on CPU and via Metal/CUDA acceleration.\nStandard format for general-purpose LLM and embedding inference across hardware.\n\n## Model task\nThe inference modality of a model. Model-task narrows what kind of inference cap a\nmodel spec is suitable for: an LLM cannot serve transcription, a transcription model\ncannot serve text generation. The task tag is part of the model-spec URN; it is set\nby the cap declaring its model-spec input slot, not derived from the model file.\n\nCausal language model for text generation and instruction following. Accepts a text\nprompt and produces a text continuation, typically token-by-token via streaming.\n\n## ML model\nMarker indicating the cap invokes a machine-learning model. Inputs typically\ninclude a model spec or model artifact; the cap is subject to model-resolution\nand hardware-pressure policies.\n\nThe cap invokes a machine-learning model.",
                  "args": [
                    {
                      "media_urn": "media:fmt=json;llm-generation-request;record",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:fmt=json;llm-generation-request;record"
                        }
                      ],
                      "arg_description": "The generation request containing prompt, model spec, and parameters"
                    },
                    {
                      "media_urn": "media:enc=utf-8;hf-token;secret",
                      "name": "hf-token",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--hf-token"
                        }
                      ],
                      "arg_description": "HuggingFace bearer token. Required when targeting a gated repository."
                    },
                    {
                      "media_urn": "media:enc=utf-8;inference;model;model-loading;operator;policy",
                      "name": "model-loading",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-loading"
                        }
                      ],
                      "arg_description": "How the model's files are brought into memory: `map` memory-maps them, `read` reads them whole, `auto` maps from a local disk and reads from a network filesystem.",
                      "default_value": "auto"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:fmt=ndjson;llm-text-stream",
                      "name": "output",
                      "output_description": "NDJSON stream of tokens, status updates, and completion message",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:gguf;in=\"media:fmt=json;llm-generation-request;record\";llm;llm-model-info;ml-model;out=\"media:fmt=json;llm-model-info;record\"",
                  "version": 3,
                  "title": "Get Model Info (GGUF) (GGUF (llama.cpp), LLM, ML Model)",
                  "aliases": [
                    "llm-model-info-gguf"
                  ],
                  "cap_description": "Query metadata and capabilities of a GGUF model",
                  "documentation": "## Purpose\n\nReturns metadata stored in a GGUF model file's header: architecture, parameter count, quantization type, context length, vocabulary size, and other configuration fields. Use this to inspect a model before using it in a pipeline.\n\n## Inputs\n\nA generation request JSON record with `request_type` set to `model_info` and the model spec to inspect.\n\n## Outputs\n\nA JSON object with model metadata fields extracted from the GGUF header.\n\n## Notes\n\n- No inference is run; this reads the GGUF file metadata only.\n- Use this cap to verify that a model's context length and architecture are compatible with your pipeline before committing to a full inference run.\n- For vocabulary extraction (needed by constrained generation), use [Get Model Vocabulary (GGUF)](https://capdag.com/browse/cap:llm-vocab;gguf;in=\"media:fmt=json;llm-generation-request;record\";llm;ml-model;out=\"media:fmt=json;llm-vocab-response;record\").\n\n## Backend\nThe inference framework or runtime that loads and executes a model. Backend choice\ndetermines weight format, hardware acceleration, and runtime characteristics. A media\nURN that omits the backend tag is backend-agnostic — it accepts any backend.\n\nGGUF is the llama.cpp container format. Quantised weights packaged into a single\nfile with embedded metadata. Runs efficiently on CPU and via Metal/CUDA acceleration.\nStandard format for general-purpose LLM and embedding inference across hardware.\n\n## Model task\nThe inference modality of a model. Model-task narrows what kind of inference cap a\nmodel spec is suitable for: an LLM cannot serve transcription, a transcription model\ncannot serve text generation. The task tag is part of the model-spec URN; it is set\nby the cap declaring its model-spec input slot, not derived from the model file.\n\nCausal language model for text generation and instruction following. Accepts a text\nprompt and produces a text continuation, typically token-by-token via streaming.\n\n## ML model\nMarker indicating the cap invokes a machine-learning model. Inputs typically\ninclude a model spec or model artifact; the cap is subject to model-resolution\nand hardware-pressure policies.\n\nThe cap invokes a machine-learning model.",
                  "args": [
                    {
                      "media_urn": "media:fmt=json;llm-generation-request;record",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:fmt=json;llm-generation-request;record"
                        }
                      ],
                      "arg_description": "Request with request_type=model_info and model_spec"
                    },
                    {
                      "media_urn": "media:enc=utf-8;inference;model;model-loading;operator;policy",
                      "name": "model-loading",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-loading"
                        }
                      ],
                      "arg_description": "How the model's files are brought into memory: `map` memory-maps them, `read` reads them whole, `auto` maps from a local disk and reads from a network filesystem.",
                      "default_value": "auto"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:fmt=json;llm-model-info;record",
                      "name": "output",
                      "output_description": "JSON object with model metadata",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:generate-text;gguf;in=\"media:enc=utf-8\";llm;ml-model;out=\"media:enc=utf-8;ext=txt;plain-text\"",
                  "version": 4,
                  "title": "Generate Text with LLM (GGUF) (GGUF (llama.cpp), LLM, ML Model)",
                  "aliases": [
                    "llm-text-generation-gguf",
                    "generate-text-gguf"
                  ],
                  "cap_description": "Generate text using GGUF models with llama.cpp backend",
                  "documentation": "## Purpose\n\nAccepts a raw text prompt and generates a text continuation using a quantized GGUF model via llama.cpp. This is a simpler prompt-in / text-out interface. Offers more sampling controls than the Candle equivalent (top-k, min-p, repetition penalty, context length).\n\n## Inputs\n\n- A text prompt (plain text). Prompts of any size that fit the model's trained context work out of the box: the context window is auto-sized to prompt + max-tokens and the prompt is prefilled in batch-sized windows.\n- A GGUF model spec (HuggingFace repo or local path). Defaults to `bartowski/Llama-3.2-1B-Instruct-GGUF` Q4_K_M, the GGUF LLM in the offline travel kit.\n- Sampling parameters: max tokens (512), temperature (0.7), top-k (40), top-p (0.9), min-p (0.05), repetition penalty (1.1), seed (42), max context length (unset = auto), batch size (2048).\n\n## Outputs\n\nGenerated text streamed as raw text chunks (not NDJSON).\n\n## Notes\n\n- For structured output, system prompts, or streaming JSON events, use [LLM Text Generation (GGUF)](https://capdag.com/browse/cap:llm-inference;gguf;in=\"media:fmt=json;llm-generation-request;record\";llm;ml-model;out=\"media:fmt=ndjson;llm-text-stream\") instead.\n- Context sizing: leaving `--max-context-length` UNSET auto-sizes the context to prompt + max-tokens, capped at the model's trained context — memory stays proportional to actual need. A value is an explicit resource bound (also capped at the trained context); if the prompt leaves no generation room inside it, the cap fails hard with the exact token counts. Input is never silently truncated.\n- Batch size is tokens-per-decode-call during prompt prefill — a throughput/memory knob. It never limits prompt length.\n\n## Backend\nThe inference framework or runtime that loads and executes a model. Backend choice\ndetermines weight format, hardware acceleration, and runtime characteristics. A media\nURN that omits the backend tag is backend-agnostic — it accepts any backend.\n\nGGUF is the llama.cpp container format. Quantised weights packaged into a single\nfile with embedded metadata. Runs efficiently on CPU and via Metal/CUDA acceleration.\nStandard format for general-purpose LLM and embedding inference across hardware.\n\n## Model task\nThe inference modality of a model. Model-task narrows what kind of inference cap a\nmodel spec is suitable for: an LLM cannot serve transcription, a transcription model\ncannot serve text generation. The task tag is part of the model-spec URN; it is set\nby the cap declaring its model-spec input slot, not derived from the model file.\n\nCausal language model for text generation and instruction following. Accepts a text\nprompt and produces a text continuation, typically token-by-token via streaming.\n\n## ML model\nMarker indicating the cap invokes a machine-learning model. Inputs typically\ninclude a model spec or model artifact; the cap is subject to model-resolution\nand hardware-pressure policies.\n\nThe cap invokes a machine-learning model.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:enc=utf-8"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Input text prompt for generation"
                    },
                    {
                      "media_urn": "media:enc=utf-8;system-prompt",
                      "name": "system-prompt",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--system-prompt"
                        }
                      ],
                      "arg_description": "System prompt that frames the model's behaviour for the request. Applied via the model's chat template when the downloaded model carries one (chat-template-jinja or chat-template-short); ignored for base/completion models. Default is a generic helpful-assistant frame that works for arbitrary user input — task-specific prompts (summarise, translate, explain) belong in the user-message slot.",
                      "default_value": "You are a helpful assistant. Respond to the user's input with a useful, accurate, and concise reply. If the input is a document or excerpt, treat it as the subject of the user's request and respond about it."
                    },
                    {
                      "media_urn": "media:enc=utf-8;gguf;llm;model-spec;tokenizer-embedded-gguf",
                      "name": "model-spec",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-spec"
                        }
                      ],
                      "arg_description": "GGUF model specification (HuggingFace repo or local path)",
                      "default_value": "hf:bartowski/Llama-3.2-1B-Instruct-GGUF?include=*Q4_K_M*.gguf,*.json,*.txt,README*&exclude=*IQ1*,*IQ2*,*fp16*"
                    },
                    {
                      "media_urn": "media:enc=utf-8;hf-token;secret",
                      "name": "hf-token",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--hf-token"
                        }
                      ],
                      "arg_description": "HuggingFace bearer token. Required when targeting a gated repository. Without it, gated downloads fail with a clear authentication error."
                    },
                    {
                      "media_urn": "media:inference;limit;max-tokens;numeric;task;user",
                      "name": "max-tokens",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--max-tokens"
                        }
                      ],
                      "arg_description": "Maximum number of tokens to generate",
                      "default_value": 512
                    },
                    {
                      "media_urn": "media:inference;numeric;sampling;task;temperature;user",
                      "name": "temperature",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--temperature"
                        }
                      ],
                      "arg_description": "Sampling temperature (0.0-2.0)",
                      "default_value": 0.7
                    },
                    {
                      "media_urn": "media:inference;numeric;sampling;task;top-k;user",
                      "name": "top-k",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--top-k"
                        }
                      ],
                      "arg_description": "Top-k sampling parameter",
                      "default_value": 40
                    },
                    {
                      "media_urn": "media:inference;numeric;sampling;task;top-p;user",
                      "name": "top-p",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--top-p"
                        }
                      ],
                      "arg_description": "Top-p (nucleus) sampling parameter",
                      "default_value": 0.9
                    },
                    {
                      "media_urn": "media:inference;min-p;numeric;sampling;task;user",
                      "name": "min-p",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--min-p"
                        }
                      ],
                      "arg_description": "Min-p sampling parameter",
                      "default_value": 0.05
                    },
                    {
                      "media_urn": "media:numeric;seed",
                      "name": "seed",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--seed"
                        }
                      ],
                      "arg_description": "Random seed for reproducibility",
                      "default_value": 42
                    },
                    {
                      "media_urn": "media:inference;limit;max-context-length;model;numeric;operator",
                      "name": "max-context-length",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--max-context-length"
                        }
                      ],
                      "arg_description": "Maximum context length. Leave unset to auto-size to prompt + max-tokens, capped at the model's trained context. A value is an explicit resource bound (also capped at the trained context); a prompt that leaves no generation room inside it fails hard with exact token counts — input is never silently truncated."
                    },
                    {
                      "media_urn": "media:batch-size;inference;limit;numeric;operator;task",
                      "name": "batch-size",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--batch-size"
                        }
                      ],
                      "arg_description": "Tokens per decode call during prompt prefill — a throughput/memory knob. Never limits prompt length.",
                      "default_value": 2048
                    },
                    {
                      "media_urn": "media:numeric;repetition-penalty",
                      "name": "repetition-penalty",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--repetition-penalty"
                        }
                      ],
                      "arg_description": "Repetition penalty",
                      "default_value": 1.1
                    },
                    {
                      "media_urn": "media:enc=utf-8;inference;model;model-loading;operator;policy",
                      "name": "model-loading",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-loading"
                        }
                      ],
                      "arg_description": "How the model's files are brought into memory: `map` memory-maps them, `read` reads them whole, `auto` maps from a local disk and reads from a network filesystem.",
                      "default_value": "auto"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:enc=utf-8;ext=txt;plain-text",
                      "name": "output",
                      "output_description": "Generated text streamed as raw text chunks",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:gguf;in=\"media:fmt=json;llm-generation-request;record\";llm;llm-vocab;ml-model;out=\"media:fmt=json;llm-vocab-response;record\"",
                  "version": 3,
                  "title": "Get Model Vocabulary (GGUF) (GGUF (llama.cpp), LLM, ML Model)",
                  "aliases": [
                    "llm-vocab-gguf"
                  ],
                  "cap_description": "Extract vocabulary tokens from a GGUF model for constraint initialization",
                  "documentation": "## Purpose\n\nExtracts the full token vocabulary from a GGUF model. The vocabulary is required by LLGuidance and other constrained decoding backends before they can compile JSON schemas, regexes, or grammars into token-level masks.\n\n## Inputs\n\nA generation request JSON record with `request_type` set to `vocab` and the model spec to read.\n\n## Outputs\n\nA JSON object with a `vocab` array (list of token strings) and a `vocab_size` integer.\n\n## Notes\n\n- This cap is typically called once per model at constraint initialization time, not per inference request.\n- The vocab array indices correspond to token IDs used internally by the model's tokenizer.\n- See also: [Constrained LLM Generation (GGUF)](https://capdag.com/browse/cap:llm-inference-constrained;constrained;gguf;in=\"media:fmt=json;llm-generation-request;record\";llm;ml-model;out=\"media:fmt=ndjson;llm-text-stream\") which depends on this vocabulary.\n\n## Backend\nThe inference framework or runtime that loads and executes a model. Backend choice\ndetermines weight format, hardware acceleration, and runtime characteristics. A media\nURN that omits the backend tag is backend-agnostic — it accepts any backend.\n\nGGUF is the llama.cpp container format. Quantised weights packaged into a single\nfile with embedded metadata. Runs efficiently on CPU and via Metal/CUDA acceleration.\nStandard format for general-purpose LLM and embedding inference across hardware.\n\n## Model task\nThe inference modality of a model. Model-task narrows what kind of inference cap a\nmodel spec is suitable for: an LLM cannot serve transcription, a transcription model\ncannot serve text generation. The task tag is part of the model-spec URN; it is set\nby the cap declaring its model-spec input slot, not derived from the model file.\n\nCausal language model for text generation and instruction following. Accepts a text\nprompt and produces a text continuation, typically token-by-token via streaming.\n\n## ML model\nMarker indicating the cap invokes a machine-learning model. Inputs typically\ninclude a model spec or model artifact; the cap is subject to model-resolution\nand hardware-pressure policies.\n\nThe cap invokes a machine-learning model.",
                  "args": [
                    {
                      "media_urn": "media:fmt=json;llm-generation-request;record",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:fmt=json;llm-generation-request;record"
                        }
                      ],
                      "arg_description": "Request with request_type=vocab and model_spec"
                    },
                    {
                      "media_urn": "media:enc=utf-8;inference;model;model-loading;operator;policy",
                      "name": "model-loading",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-loading"
                        }
                      ],
                      "arg_description": "How the model's files are brought into memory: `map` memory-maps them, `read` reads them whole, `auto` maps from a local disk and reads from a network filesystem.",
                      "default_value": "auto"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:fmt=json;llm-vocab-response;record",
                      "name": "output",
                      "output_description": "JSON object with vocab array and vocab_size",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:gguf;in=\"media:ext=png;image\";ml-model;ocr;out=\"media:digitized-text;enc=utf-8;ext=txt;plain-text\";read-text",
                  "version": 5,
                  "title": "OCR (GGUF) (GGUF (llama.cpp), ML Model, OCR)",
                  "aliases": [
                    "ocr-gguf"
                  ],
                  "cap_description": "Digitize verbatim text from an image with a GGUF OCR vision model (default GLM-OCR)",
                  "documentation": "## Purpose\n\nReads an image and returns the literal text written inside it. Uses a dedicated GGUF\nOCR vision-language model via llama.cpp's multimodal (mtmd) API. The default model is\n[GLM-OCR](https://huggingface.co/ggml-org/GLM-OCR-GGUF) — a 0.9B-parameter OCR\nspecialist that reaches state-of-the-art OmniDocBench scores while remaining small\nenough to run quickly on CPU or Metal.\n\nThis cap is for *transcription* of text that appears in an image, not for *describing*\nwhat the image depicts. For descriptions, use [Describe Image (GGUF)](https://capdag.com/browse/cap:describe-image;gguf;in=\"media:ext=png;image\";ml-model;out=\"media:enc=utf-8;ext=txt;image-description;plain-text\";vision).\n\n## Inputs\n\n- A GGUF OCR model spec (HuggingFace repo or local path). Defaults to `hf:ggml-org/GLM-OCR-GGUF`.\n- A PNG image file.\n- A text prompt that nudges the model's output format. Defaults to `\"OCR\"`. OCR-specialised\n  GGUF models recognise short directive prompts — try `\"OCR markdown\"` to preserve layout\n  as Markdown, or `\"OCR HTML table\"` for tabular content.\n- Max tokens (default 1024 — OCR output is often longer than a caption) and temperature\n  (default 0.0 — OCR is a deterministic transcription task; randomness only adds errors).\n\n## Outputs\n\nThe recognised text as plain UTF-8. When prompted with `\"OCR markdown\"` the same channel\ncarries Markdown-formatted text — still UTF-8 text and still flows into any text consumer.\n\n## Notes\n\n- Best results on screenshots, scanned pages, and photographs of printed text. Handwriting\n  is supported but harder; expect more errors on cursive or low-contrast samples.\n- OCR models perform poorly when asked to *describe* an image — they are trained for\n  transcription. Pick the right cap for the job.\n- Lower temperature (0.0–0.2) yields cleaner transcriptions. Higher values increase\n  hallucinated characters and should be avoided for OCR.\n- The model file plus its mmproj projector is ~1 GB at Q8_0 quantisation; first run\n  triggers a one-time download via the model cartridge.\n- Input must be PNG. An image in another format is converted first with [Convert Image Format](https://capdag.com/browse/cap:convert-image;in=media:image;out=media:image); a machine planned from a JPEG or WebP source takes that step by itself.\n\n## Backend\nThe inference framework or runtime that loads and executes a model. Backend choice\ndetermines weight format, hardware acceleration, and runtime characteristics. A media\nURN that omits the backend tag is backend-agnostic — it accepts any backend.\n\nGGUF is the llama.cpp container format. Quantised weights packaged into a single\nfile with embedded metadata. Runs efficiently on CPU and via Metal/CUDA acceleration.\nStandard format for general-purpose LLM and embedding inference across hardware.\n\n## ML model\nMarker indicating the cap invokes a machine-learning model. Inputs typically\ninclude a model spec or model artifact; the cap is subject to model-resolution\nand hardware-pressure policies.\n\nThe cap invokes a machine-learning model.\n\n## Model task\nThe inference modality of a model. Model-task narrows what kind of inference cap a\nmodel spec is suitable for: an LLM cannot serve transcription, a transcription model\ncannot serve text generation. The task tag is part of the model-spec URN; it is set\nby the cap declaring its model-spec input slot, not derived from the model file.\n\nOptical character recognition model. Specialised vision model that extracts the\nverbatim text contained in an image — printed pages, screenshots, photographed\nsigns, handwriting. Distinct from a generic vision-language model: an OCR model is\ntrained to transcribe what is *written* in the image rather than describe what the\nimage *depicts*. Output is the recognised text, optionally with layout markup.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;gguf;model-spec;ocr;tokenizer-embedded-gguf",
                      "name": "model-spec",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-spec"
                        }
                      ],
                      "arg_description": "GGUF OCR model specification (HuggingFace repo or local path)",
                      "default_value": "hf:ggml-org/GLM-OCR-GGUF?include=GLM-OCR-Q8_0.gguf,mmproj-GLM-OCR-Q8_0.gguf"
                    },
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=png;image"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the image file to transcribe"
                    },
                    {
                      "media_urn": "media:enc=utf-8",
                      "name": "prompt",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--prompt"
                        }
                      ],
                      "arg_description": "Directive prompt for the OCR model (e.g. \"OCR\", \"OCR markdown\", \"OCR HTML table\")",
                      "default_value": "OCR"
                    },
                    {
                      "media_urn": "media:enc=utf-8;system-prompt",
                      "name": "system-prompt",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--system-prompt"
                        }
                      ],
                      "arg_description": "System prompt that frames the OCR model's behaviour. Applied via the model's chat template when the downloaded model carries one (chat-template-jinja or chat-template-short); ignored for bare-prompt OCR specialists such as GLM-OCR. Default is a generic helpful-assistant frame; the per-image directive (\"OCR markdown\", \"transcribe receipts\") belongs in the prompt slot.",
                      "default_value": "You are a helpful assistant. Respond to the user's input with a useful, accurate, and concise reply. If the input is a document or excerpt, treat it as the subject of the user's request and respond about it."
                    },
                    {
                      "media_urn": "media:inference;limit;max-tokens;numeric;task;user",
                      "name": "max-tokens",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--max-tokens"
                        }
                      ],
                      "arg_description": "Maximum number of tokens to generate (OCR output is often long; default raised vs description caps)",
                      "default_value": 1024
                    },
                    {
                      "media_urn": "media:inference;numeric;sampling;task;temperature;user",
                      "name": "temperature",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--temperature"
                        }
                      ],
                      "arg_description": "Sampling temperature (0.0-2.0). Keep at 0.0 for deterministic transcription.",
                      "default_value": 0
                    },
                    {
                      "media_urn": "media:enc=utf-8;inference;model;model-loading;operator;policy",
                      "name": "model-loading",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-loading"
                        }
                      ],
                      "arg_description": "How the model's files are brought into memory: `map` memory-maps them, `read` reads them whole, `auto` maps from a local disk and reads from a network filesystem.",
                      "default_value": "auto"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:digitized-text;enc=utf-8;ext=txt;plain-text",
                      "name": "output",
                      "output_description": "Verbatim text digitized from the image, persistable as a `.txt` file",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:describe-image;gguf;in=\"media:ext=png;image\";ml-model;out=\"media:enc=utf-8;ext=txt;image-description;plain-text\";vision",
                  "version": 4,
                  "title": "Describe Image (GGUF) (GGUF (llama.cpp), ML Model, Vision)",
                  "aliases": [
                    "vision-describe-gguf",
                    "describe-image-gguf"
                  ],
                  "cap_description": "Generate detailed image descriptions using GGUF multimodal models (moondream, Qwen3-VL, LLaVA, Gemma) with llama.cpp backend",
                  "documentation": "## Purpose\n\nGenerates detailed, instruction-following natural-language descriptions of PNG images using GGUF multimodal (vision-language) models via llama.cpp. Default is moondream2 2025-04-14, the GGUF vision model in the offline travel kit; also runs Qwen3-VL, SmolVLM2, LLaVA, Gemma, and any other GGUF VLM that ships a text+mmproj pair. The prompt can ask specific questions about image content.\n\n## Inputs\n\n- A GGUF vision model spec (HuggingFace repo or local path). Defaults to `ggml-org/moondream2-20250414-GGUF`.\n- A PNG image file.\n- A text prompt (default: \"Describe this image in detail.\"). Customize to ask specific questions.\n- Max tokens (default 256) and temperature (default 0.6).\n\n## Outputs\n\nA text description of the image as a plain string.\n\n## Notes\n\n- Vision-language models follow instructions in the prompt, making them more flexible than BLIP-style captioning models.\n- Lower temperature (0.3-0.5) produces more factual, less creative descriptions.\n- For Apple Silicon, prefer [Describe Image (MLX)](https://capdag.com/browse/cap:describe-image;in=\"media:ext=png;image\";ml-model;mlx;out=\"media:enc=utf-8;ext=txt;image-description;plain-text\";vision) for better performance.\n- Input must be PNG. An image in another format is converted first with [Convert Image Format](https://capdag.com/browse/cap:convert-image;in=media:image;out=media:image); a machine planned from a JPEG or WebP source takes that step by itself.\n\n## Backend\nThe inference framework or runtime that loads and executes a model. Backend choice\ndetermines weight format, hardware acceleration, and runtime characteristics. A media\nURN that omits the backend tag is backend-agnostic — it accepts any backend.\n\nGGUF is the llama.cpp container format. Quantised weights packaged into a single\nfile with embedded metadata. Runs efficiently on CPU and via Metal/CUDA acceleration.\nStandard format for general-purpose LLM and embedding inference across hardware.\n\n## ML model\nMarker indicating the cap invokes a machine-learning model. Inputs typically\ninclude a model spec or model artifact; the cap is subject to model-resolution\nand hardware-pressure policies.\n\nThe cap invokes a machine-learning model.\n\n## Model task\nThe inference modality of a model. Model-task narrows what kind of inference cap a\nmodel spec is suitable for: an LLM cannot serve transcription, a transcription model\ncannot serve text generation. The task tag is part of the model-spec URN; it is set\nby the cap declaring its model-spec input slot, not derived from the model file.\n\nVision-language model for image captioning, visual question answering, and other\nmultimodal tasks. Accepts text and images, produces text.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;gguf;model-spec;tokenizer-embedded-gguf;vision",
                      "name": "model-spec",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-spec"
                        }
                      ],
                      "arg_description": "GGUF vision model specification (HuggingFace repo or local path)",
                      "default_value": "hf:ggml-org/moondream2-20250414-GGUF"
                    },
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=png;image"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the image file to describe"
                    },
                    {
                      "media_urn": "media:enc=utf-8",
                      "name": "prompt",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--prompt"
                        }
                      ],
                      "arg_description": "Text prompt for the image description",
                      "default_value": "Describe this image in detail."
                    },
                    {
                      "media_urn": "media:enc=utf-8;system-prompt",
                      "name": "system-prompt",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--system-prompt"
                        }
                      ],
                      "arg_description": "System prompt that frames the model's behaviour for the request. Applied via the model's chat template when the downloaded VLM carries one (chat-template-jinja or chat-template-short); ignored for bare-prompt vision models such as GLM-OCR. Default is a generic helpful-assistant frame; concrete per-image instructions belong in the prompt slot.",
                      "default_value": "You are a helpful assistant. Respond to the user's input with a useful, accurate, and concise reply. If the input is a document or excerpt, treat it as the subject of the user's request and respond about it."
                    },
                    {
                      "media_urn": "media:inference;limit;max-tokens;numeric;task;user",
                      "name": "max-tokens",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--max-tokens"
                        }
                      ],
                      "arg_description": "Maximum number of tokens to generate",
                      "default_value": 256
                    },
                    {
                      "media_urn": "media:inference;numeric;sampling;task;temperature;user",
                      "name": "temperature",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--temperature"
                        }
                      ],
                      "arg_description": "Sampling temperature (0.0-2.0)",
                      "default_value": 0.6
                    },
                    {
                      "media_urn": "media:enc=utf-8;inference;model;model-loading;operator;policy",
                      "name": "model-loading",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--model-loading"
                        }
                      ],
                      "arg_description": "How the model's files are brought into memory: `map` memory-maps them, `read` reads them whole, `auto` maps from a local disk and reads from a network filesystem.",
                      "default_value": "auto"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:enc=utf-8;ext=txt;image-description;plain-text",
                      "name": "output",
                      "output_description": "Text description of the image",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                }
              ],
              "adapter_urns": [
                "media:ext=gguf;model"
              ]
            }
          ],
          "latestVersion": "1.400.1302",
          "versions": {
            "1.400.1302": {
              "releaseDate": "2026-10-15T07:25:19Z",
              "changelog": [
                "Initial release"
              ],
              "minAppVersion": "1.0.0",
              "builds": [
                {
                  "platform": "darwin-arm64",
                  "package": {
                    "name": "ggufcartridge-1.400.1302-darwin-arm64.pkg",
                    "url": "https://cartridges.machinefabric.com/release/ggufcartridge/1.400.1302/ggufcartridge-1.400.1302-darwin-arm64.pkg",
                    "sha256": "5e57791d78320f0291076e6568a5d85df1b5aa214f1d773abf76b58491f6661d",
                    "size": 3765622
                  },
                  "packages": [
                    {
                      "name": "ggufcartridge-1.400.1302-darwin-arm64.pkg",
                      "url": "https://cartridges.machinefabric.com/release/ggufcartridge/1.400.1302/ggufcartridge-1.400.1302-darwin-arm64.pkg",
                      "sha256": "5e57791d78320f0291076e6568a5d85df1b5aa214f1d773abf76b58491f6661d",
                      "size": 3765622,
                      "format": "pkg"
                    }
                  ],
                  "binary": {
                    "name": "ggufcartridge-1.400.1302-darwin-arm64.bin",
                    "url": "https://cartridges.machinefabric.com/release/ggufcartridge/1.400.1302/ggufcartridge-1.400.1302-darwin-arm64.bin",
                    "sha256": "8aa9af8a736aee68554ddb256991efcf2fcee1b4ac3e66614693daf712d39943",
                    "size": 8815216,
                    "signature": "untrusted comment: signature from rsign secret key\nRUTbeBdFkW9D4veJv0WlB4pCiAD9IKCj4ucfa06daNWXn6RgPJjNG7qVFn45TiIlKPGT6fc3EXosdwcm8OpybGD3NHIuinvLJAI=\ntrusted comment: file:ggufcartridge-1.400.1302-darwin-arm64.bin sha256=8aa9af8a736aee68554ddb256991efcf2fcee1b4ac3e66614693daf712d39943\nFAhn9NlSRzQqpfGTjUVjJvim6lCRljaIlZd3aoilJT0LzhsQDwMCFooM3tn6xXHLbBL7Ga/SRR/gTyS60u08CQ==\n"
                  }
                }
              ]
            }
          }
        },
        "mlxcartridge": {
          "name": "mlxcartridge",
          "description": "MLX inference cartridge for CapDAG - LLM, Vision, and Embeddings on Apple Silicon",
          "author": "https://github.com/machinefabric",
          "pageUrl": "",
          "teamId": "P336JK947M",
          "minAppVersion": "1.0.0",
          "categories": [],
          "tags": [],
          "cap_groups": [
            {
              "caps": [
                {
                  "aliases": [
                    "identity"
                  ],
                  "outputs": [
                    {
                      "is_sequence": false,
                      "output_description": "The input data, unchanged",
                      "name": "output",
                      "media_urn": "media:",
                      "streaming": false,
                      "optional": false
                    }
                  ],
                  "urn": "cap:effect=none",
                  "args": [
                    {
                      "is_sequence": false,
                      "streaming": false,
                      "media_urn": "media:",
                      "name": "input",
                      "required": true,
                      "sources": [
                        {
                          "stdin": "media:"
                        }
                      ]
                    }
                  ],
                  "cap_description": "The categorical identity morphism. Echoes input as output unchanged. Mandatory in every capability set.",
                  "title": "Identity"
                },
                {
                  "args": [
                    {
                      "streaming": false,
                      "required": false,
                      "arg_description": "Path to MLX embedding model directory",
                      "media_urn": "media:embeddings;enc=utf-8;mlx;model-spec",
                      "is_sequence": false,
                      "name": "input",
                      "default_value": "hf:mlx-community/all-MiniLM-L6-v2-4bit",
                      "sources": [
                        {
                          "position": 0
                        },
                        {
                          "stdin": "media:embeddings;enc=utf-8;mlx;model-spec"
                        }
                      ]
                    }
                  ],
                  "urn": "cap:embeddings-dimensions;in=\"media:embeddings;enc=utf-8;mlx;model-spec\";ml-model;mlx;out=\"media:integer;model-dim;numeric\"",
                  "aliases": [
                    "embeddings-dimensions-mlx",
                    "embedding-dims-mlx"
                  ],
                  "cap_description": "Query the dimensionality of embeddings for a given MLX model",
                  "outputs": [
                    {
                      "output_description": "Dimensionality of the embeddings (positive integer)",
                      "is_sequence": false,
                      "streaming": false,
                      "optional": false,
                      "media_urn": "media:integer;model-dim;numeric",
                      "name": "output"
                    }
                  ],
                  "title": "Get Embeddings Dimensions (MLX) (ML Model, MLX (Apple Silicon))"
                },
                {
                  "args": [
                    {
                      "streaming": false,
                      "media_urn": "media:embeddings;enc=utf-8;mlx;model-spec",
                      "sources": [
                        {
                          "cli_flag": "--model"
                        }
                      ],
                      "is_sequence": false,
                      "name": "model",
                      "arg_description": "Path to MLX embedding model directory",
                      "default_value": "hf:mlx-community/all-MiniLM-L6-v2-4bit",
                      "required": false
                    },
                    {
                      "streaming": false,
                      "media_urn": "media:enc=utf-8;file-path",
                      "sources": [
                        {
                          "stdin": "media:enc=utf-8"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "is_sequence": false,
                      "name": "input",
                      "arg_description": "Path to text file to generate embeddings from",
                      "required": true
                    },
                    {
                      "streaming": false,
                      "media_urn": "media:chunk-size;numeric",
                      "sources": [
                        {
                          "cli_flag": "--chunk-size"
                        }
                      ],
                      "is_sequence": false,
                      "name": "chunk-size",
                      "arg_description": "Chunk size in words for splitting input text",
                      "default_value": 400,
                      "required": false
                    },
                    {
                      "streaming": false,
                      "media_urn": "media:chunk-overlap;numeric",
                      "sources": [
                        {
                          "cli_flag": "--chunk-overlap"
                        }
                      ],
                      "is_sequence": false,
                      "name": "chunk-overlap",
                      "arg_description": "Chunk overlap in words when splitting input text",
                      "default_value": 50,
                      "required": false
                    }
                  ],
                  "outputs": [
                    {
                      "output_description": "JSON containing embeddings, chunk metadata and model information",
                      "is_sequence": false,
                      "media_urn": "media:embedding-vector;enc=utf-8;record",
                      "optional": false,
                      "streaming": false,
                      "name": "output"
                    }
                  ],
                  "title": "Generate Vector Embeddings (MLX) (MLX (Apple Silicon), ML Model)",
                  "aliases": [
                    "embeddings-generation-mlx",
                    "embeddings-mlx"
                  ],
                  "cap_description": "Generate vector embeddings from text using MLX-based models on Apple Silicon",
                  "urn": "cap:generate-embeddings;in=\"media:enc=utf-8\";ml-model;mlx;out=\"media:embedding-vector;enc=utf-8;record\""
                },
                {
                  "args": [
                    {
                      "required": true,
                      "arg_description": "The generation request containing prompt, model spec, and parameters",
                      "is_sequence": false,
                      "media_urn": "media:fmt=json;llm-generation-request;record",
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:fmt=json;llm-generation-request;record"
                        }
                      ],
                      "name": "input"
                    },
                    {
                      "required": false,
                      "arg_description": "HuggingFace bearer token. Required when targeting a gated repository.",
                      "is_sequence": false,
                      "media_urn": "media:enc=utf-8;hf-token;secret",
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--hf-token"
                        }
                      ],
                      "name": "hf-token"
                    }
                  ],
                  "outputs": [
                    {
                      "output_description": "NDJSON stream of tokens, status updates, and completion message",
                      "is_sequence": false,
                      "media_urn": "media:fmt=ndjson;llm-text-stream",
                      "optional": false,
                      "streaming": false,
                      "name": "output"
                    }
                  ],
                  "title": "LLM Text Generation (MLX) (LLM, ML Model, MLX (Apple Silicon))",
                  "aliases": [
                    "llm-inference-mlx"
                  ],
                  "cap_description": "Generate text using MLX models on Apple Silicon. Output is NDJSON streaming tokens.",
                  "urn": "cap:in=\"media:fmt=json;llm-generation-request;record\";llm;llm-inference;ml-model;mlx;out=\"media:fmt=ndjson;llm-text-stream\""
                },
                {
                  "args": [
                    {
                      "required": true,
                      "arg_description": "Input text prompt for generation",
                      "is_sequence": false,
                      "media_urn": "media:enc=utf-8",
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:enc=utf-8"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "name": "input"
                    },
                    {
                      "is_sequence": false,
                      "required": false,
                      "arg_description": "System prompt that frames the model's behaviour for the request. Applied via the model's chat template when the downloaded model carries one (chat-template-jinja or chat-template-short); ignored for base/completion models. Default is a generic helpful-assistant frame that works for arbitrary user input — task-specific prompts (summarise, translate, explain) belong in the user-message slot.",
                      "default_value": "You are a helpful assistant. Respond to the user's input with a useful, accurate, and concise reply. If the input is a document or excerpt, treat it as the subject of the user's request and respond about it.",
                      "media_urn": "media:enc=utf-8;system-prompt",
                      "sources": [
                        {
                          "cli_flag": "--system-prompt"
                        }
                      ],
                      "name": "system-prompt",
                      "streaming": false
                    },
                    {
                      "is_sequence": false,
                      "required": false,
                      "arg_description": "MLX model specification (HuggingFace model ID or local path)",
                      "default_value": "hf:mlx-community/Llama-3.2-3B-Instruct-4bit",
                      "media_urn": "media:enc=utf-8;llm;mlx;model-spec",
                      "sources": [
                        {
                          "cli_flag": "--model-spec"
                        }
                      ],
                      "name": "model-spec",
                      "streaming": false
                    },
                    {
                      "is_sequence": false,
                      "required": false,
                      "arg_description": "HuggingFace bearer token. Required when targeting a gated repository.",
                      "media_urn": "media:enc=utf-8;hf-token;secret",
                      "sources": [
                        {
                          "cli_flag": "--hf-token"
                        }
                      ],
                      "name": "hf-token",
                      "streaming": false
                    },
                    {
                      "is_sequence": false,
                      "required": false,
                      "arg_description": "Maximum number of tokens to generate",
                      "default_value": 512,
                      "media_urn": "media:inference;limit;max-tokens;numeric;task;user",
                      "sources": [
                        {
                          "cli_flag": "--max-tokens"
                        }
                      ],
                      "name": "max-tokens",
                      "streaming": false
                    },
                    {
                      "is_sequence": false,
                      "required": false,
                      "arg_description": "Sampling temperature (0.0-2.0)",
                      "default_value": 0.7,
                      "media_urn": "media:inference;numeric;sampling;task;temperature;user",
                      "sources": [
                        {
                          "cli_flag": "--temperature"
                        }
                      ],
                      "name": "temperature",
                      "streaming": false
                    },
                    {
                      "is_sequence": false,
                      "required": false,
                      "arg_description": "Top-p (nucleus) sampling parameter",
                      "default_value": 0.9,
                      "media_urn": "media:inference;numeric;sampling;task;top-p;user",
                      "sources": [
                        {
                          "cli_flag": "--top-p"
                        }
                      ],
                      "name": "top-p",
                      "streaming": false
                    },
                    {
                      "is_sequence": false,
                      "required": false,
                      "arg_description": "Repetition penalty",
                      "default_value": 1.1,
                      "media_urn": "media:numeric;repetition-penalty",
                      "sources": [
                        {
                          "cli_flag": "--repetition-penalty"
                        }
                      ],
                      "name": "repetition-penalty",
                      "streaming": false
                    },
                    {
                      "is_sequence": false,
                      "required": false,
                      "arg_description": "Random seed for reproducibility (0 = non-deterministic)",
                      "default_value": 0,
                      "media_urn": "media:numeric;seed",
                      "sources": [
                        {
                          "cli_flag": "--seed"
                        }
                      ],
                      "name": "seed",
                      "streaming": false
                    }
                  ],
                  "outputs": [
                    {
                      "output_description": "Generated text streamed as raw text chunks",
                      "is_sequence": false,
                      "media_urn": "media:enc=utf-8;ext=txt;plain-text",
                      "optional": false,
                      "streaming": false,
                      "name": "output"
                    }
                  ],
                  "title": "Generate Text with LLM (MLX) (LLM, ML Model, MLX (Apple Silicon))",
                  "aliases": [
                    "llm-text-generation-mlx",
                    "generate-text-mlx"
                  ],
                  "cap_description": "Generate text using MLX-based LLM models on Apple Silicon",
                  "urn": "cap:generate-text;in=\"media:enc=utf-8\";llm;ml-model;mlx;out=\"media:enc=utf-8;ext=txt;plain-text\""
                },
                {
                  "args": [
                    {
                      "is_sequence": false,
                      "required": false,
                      "arg_description": "Path to MLX vision model directory",
                      "default_value": "hf:mlx-community/Qwen3-VL-4B-Instruct-4bit",
                      "media_urn": "media:enc=utf-8;mlx;model-spec;vision",
                      "sources": [
                        {
                          "cli_flag": "--model"
                        }
                      ],
                      "name": "model",
                      "streaming": false
                    },
                    {
                      "is_sequence": false,
                      "required": true,
                      "arg_description": "Path to the image file to describe (local path or HTTP(S) URL)",
                      "media_urn": "media:enc=utf-8;file-path",
                      "sources": [
                        {
                          "stdin": "media:ext=png;image"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "name": "input",
                      "streaming": false
                    },
                    {
                      "is_sequence": false,
                      "required": false,
                      "arg_description": "Text prompt for the image description",
                      "default_value": "Describe this image in detail.",
                      "media_urn": "media:enc=utf-8",
                      "sources": [
                        {
                          "cli_flag": "--prompt"
                        }
                      ],
                      "name": "prompt",
                      "streaming": false
                    },
                    {
                      "is_sequence": false,
                      "required": false,
                      "arg_description": "System prompt that frames the model's behaviour for the request. Applied via the model's chat template when the downloaded VLM carries one (chat-template-jinja or chat-template-short); ignored for base/completion vision models. Default is a generic helpful-assistant frame; concrete per-image instructions (\"describe in JSON\", \"transcribe text\", \"read receipts\") belong in the prompt slot.",
                      "default_value": "You are a helpful assistant. Respond to the user's input with a useful, accurate, and concise reply. If the input is a document or excerpt, treat it as the subject of the user's request and respond about it.",
                      "media_urn": "media:enc=utf-8;system-prompt",
                      "sources": [
                        {
                          "cli_flag": "--system-prompt"
                        }
                      ],
                      "name": "system-prompt",
                      "streaming": false
                    },
                    {
                      "is_sequence": false,
                      "required": false,
                      "arg_description": "Maximum number of tokens to generate",
                      "default_value": 256,
                      "media_urn": "media:inference;limit;max-tokens;numeric;task;user",
                      "sources": [
                        {
                          "cli_flag": "--max-tokens"
                        }
                      ],
                      "name": "max-tokens",
                      "streaming": false
                    }
                  ],
                  "outputs": [
                    {
                      "output_description": "Text description of the image",
                      "is_sequence": false,
                      "media_urn": "media:enc=utf-8;ext=txt;image-description;plain-text",
                      "optional": false,
                      "streaming": false,
                      "name": "output"
                    }
                  ],
                  "title": "Describe Image (MLX) (ML Model, MLX (Apple Silicon), Vision)",
                  "aliases": [
                    "vision-describe-mlx",
                    "describe-image-mlx"
                  ],
                  "cap_description": "Generate detailed image descriptions using MLX-based vision-language models on Apple Silicon",
                  "urn": "cap:describe-image;in=\"media:ext=png;image\";ml-model;mlx;out=\"media:enc=utf-8;ext=txt;image-description;plain-text\";vision"
                }
              ],
              "name": "mlx-inference"
            }
          ],
          "latestVersion": "1.370.1953",
          "versions": {
            "1.370.1953": {
              "releaseDate": "2026-10-15T07:25:59Z",
              "changelog": [
                "Initial release"
              ],
              "minAppVersion": "1.0.0",
              "builds": [
                {
                  "platform": "darwin-arm64",
                  "package": {
                    "name": "mlxcartridge-1.370.1953-darwin-arm64.pkg",
                    "url": "https://cartridges.machinefabric.com/release/mlxcartridge/1.370.1953/mlxcartridge-1.370.1953-darwin-arm64.pkg",
                    "sha256": "6cd97be463eb5152d1e0436e9770eae1ef23d8a9115c01ceda01e11869a44d18",
                    "size": 8652258
                  },
                  "packages": [
                    {
                      "name": "mlxcartridge-1.370.1953-darwin-arm64.pkg",
                      "url": "https://cartridges.machinefabric.com/release/mlxcartridge/1.370.1953/mlxcartridge-1.370.1953-darwin-arm64.pkg",
                      "sha256": "6cd97be463eb5152d1e0436e9770eae1ef23d8a9115c01ceda01e11869a44d18",
                      "size": 8652258,
                      "format": "pkg"
                    }
                  ],
                  "binary": {
                    "name": "mlxcartridge-1.370.1953-darwin-arm64.bin",
                    "url": "https://cartridges.machinefabric.com/release/mlxcartridge/1.370.1953/mlxcartridge-1.370.1953-darwin-arm64.bin",
                    "sha256": "acc342fe4da202a60fdccf6292c63d96409247ac4d59d562a2a777708375a8e7",
                    "size": 27124192,
                    "signature": "untrusted comment: signature from rsign secret key\nRUTbeBdFkW9D4rXDLdC9E2avdQlXs4Qqz0Plt8IBsGVOqonZ7MAsiWyaAx30CibiQrQmEsn1Mc1YQ/cQJEP4OC+oiyQKbDTbMAQ=\ntrusted comment: file:mlxcartridge-1.370.1953-darwin-arm64.bin sha256=acc342fe4da202a60fdccf6292c63d96409247ac4d59d562a2a777708375a8e7\nopd2LdYhWcdB4K1K8ig+HPVLghYMxqx7panecwyiC34tE3OuNNIivMoxb6xYPqQ2GOfRKyjMxYulj0k5ccm/AQ==\n"
                  }
                }
              ]
            }
          }
        },
        "imagecartridge": {
          "name": "imagecartridge",
          "description": "Cross-format raster image conversion (PNG, JPEG, GIF, BMP, TIFF, WebP).",
          "author": "https://github.com/machinefabric",
          "pageUrl": "https://github.com/machinefabric/imagecartridge",
          "teamId": "P336JK947M",
          "minAppVersion": "1.0.0",
          "categories": [],
          "tags": [],
          "cap_groups": [
            {
              "name": "image-formats",
              "caps": [
                {
                  "urn": "cap:effect=none",
                  "title": "Identity",
                  "aliases": [
                    "identity"
                  ],
                  "cap_description": "The categorical identity morphism. Echoes input as output unchanged. Mandatory in every capability set.",
                  "args": [
                    {
                      "media_urn": "media:",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:"
                        }
                      ]
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:",
                      "name": "output",
                      "output_description": "The input data, unchanged",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-image;in=\"media:ext=bmp;image\";out=\"media:ext=jpeg;image\"",
                  "version": 2,
                  "title": "Convert BMP to JPEG",
                  "aliases": [
                    "convert-image-bmp-to-jpeg",
                    "bmp2jpeg"
                  ],
                  "cap_description": "Re-encode a BMP image as a JPEG",
                  "documentation": "## Purpose\n\nDecodes a BMP and writes it as a JPEG, drastically reducing file size for photographic content.\n\n## Inputs\n\nA BMP file.\n\n## Outputs\n\nA JPEG file at quality 85.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=bmp;image"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the BMP file to convert"
                    },
                    {
                      "media_urn": "media:jpeg-quality;numeric",
                      "name": "quality",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--quality"
                        }
                      ],
                      "arg_description": "JPEG encode quality, 1-100",
                      "default_value": 85
                    },
                    {
                      "media_urn": "media:background-color;enc=utf-8",
                      "name": "background",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--background"
                        }
                      ],
                      "arg_description": "Matte color (hex #RRGGBB) that transparency composites onto — JPEG has no alpha channel",
                      "default_value": "#FFFFFF"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:ext=jpeg;image",
                      "name": "output",
                      "output_description": "JPEG-encoded image",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-image;in=\"media:ext=bmp;image\";out=\"media:ext=png;image\"",
                  "version": 2,
                  "title": "Convert BMP to PNG",
                  "aliases": [
                    "convert-image-bmp-to-png",
                    "bmp2png"
                  ],
                  "cap_description": "Re-encode a BMP image as a PNG",
                  "documentation": "## Purpose\n\nDecodes a Windows BMP file and writes it as a PNG. BMP files are large and uncompressed; PNG is the practical replacement.\n\n## Inputs\n\nA BMP file. Standard 24-bit and 32-bit color depths are supported.\n\n## Outputs\n\nA PNG file with the same pixel content.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=bmp;image"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the BMP file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:ext=png;image",
                      "name": "output",
                      "output_description": "PNG-encoded image",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-image;in=\"media:ext=gif;image\";out=\"media:ext=jpeg;image\"",
                  "version": 2,
                  "title": "Convert GIF to JPEG",
                  "aliases": [
                    "convert-image-gif-to-jpeg",
                    "gif2jpeg"
                  ],
                  "cap_description": "Re-encode a GIF image as a JPEG",
                  "documentation": "## Purpose\n\nDecodes a GIF (first frame for animated GIFs) and writes it as a JPEG.\n\n## Inputs\n\nA GIF file. For animated GIFs, the first frame is used.\n\n## Outputs\n\nA JPEG file at quality 85.\n\n## Notes\n\n- Animated GIF inputs convert their FIRST frame only (a warning is logged when frames are dropped). Full animation extraction is a different capability.\n\nGIF transparency is composited against white. Animation frames are dropped.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=gif;image"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the GIF file to convert"
                    },
                    {
                      "media_urn": "media:jpeg-quality;numeric",
                      "name": "quality",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--quality"
                        }
                      ],
                      "arg_description": "JPEG encode quality, 1-100",
                      "default_value": 85
                    },
                    {
                      "media_urn": "media:background-color;enc=utf-8",
                      "name": "background",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--background"
                        }
                      ],
                      "arg_description": "Matte color (hex #RRGGBB) that transparency composites onto — JPEG has no alpha channel",
                      "default_value": "#FFFFFF"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:ext=jpeg;image",
                      "name": "output",
                      "output_description": "JPEG-encoded image",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-image;in=\"media:ext=gif;image\";out=\"media:ext=png;image\"",
                  "version": 2,
                  "title": "Convert GIF to PNG",
                  "aliases": [
                    "convert-image-gif-to-png",
                    "gif2png"
                  ],
                  "cap_description": "Re-encode a GIF image as a PNG",
                  "documentation": "## Purpose\n\nDecodes a GIF (first frame for animated GIFs) and writes it as a PNG. Useful when downstream caps require PNG input.\n\n## Inputs\n\nA GIF file. For animated GIFs, the first frame is used.\n\n## Outputs\n\nA PNG file containing the (first) frame.\n\n## Notes\n\n- Animated GIF inputs convert their FIRST frame only (a warning is logged when frames are dropped). Full animation extraction is a different capability.\n\nAnimated GIFs collapse to their first frame. Transparency is preserved.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=gif;image"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the GIF file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:ext=png;image",
                      "name": "output",
                      "output_description": "PNG-encoded image",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-image;in=\"media:ext=jpeg;image\";out=\"media:ext=png;image\"",
                  "version": 3,
                  "title": "Convert JPEG to PNG",
                  "aliases": [
                    "convert-image-jpeg-to-png",
                    "jpeg2png"
                  ],
                  "cap_description": "Re-encode a JPEG image as a PNG",
                  "documentation": "## Purpose\n\nDecodes a JPEG image and re-encodes it as a lossless PNG. Use this when downstream cartridges only accept PNG (for example, [Describe Image (Candle)](https://capdag.com/browse/cap:describe-image;candle;in=\"media:ext=png;image\";ml-model;out=\"media:enc=utf-8;ext=txt;image-description;plain-text\")), or when archiving JPEGs without further compression loss.\n\n## Inputs\n\nA JPEG file. The decoder accepts standard JFIF and Exif-tagged JPEGs.\n\n## Outputs\n\nA PNG file with the same pixel content.\n\n## Notes\n\n- EXIF orientation from the source is applied to the pixels, so the output displays upright even though the target format carries no orientation metadata.\n\nThe conversion is decode-then-encode. JPEG quantization artifacts are preserved exactly as a PNG cannot reverse them. PNG is larger on disk than the source JPEG for typical photographic content.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=jpeg;image"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the JPEG file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:ext=png;image",
                      "name": "output",
                      "output_description": "PNG-encoded image",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-image;in=\"media:ext=jpeg;image\";out=\"media:ext=webp;image\"",
                  "version": 2,
                  "title": "Convert JPEG to WebP",
                  "aliases": [
                    "convert-image-jpeg-to-webp",
                    "jpeg2webp"
                  ],
                  "cap_description": "Re-encode a JPEG image as a lossless WebP",
                  "documentation": "## Purpose\n\nDecodes a JPEG and writes it as a lossless WebP. Useful for archiving JPEGs without introducing further generation loss while reducing file size relative to PNG.\n\n## Inputs\n\nA JPEG file.\n\n## Outputs\n\nA lossless WebP file with the same pixel content.\n\n## Notes\n\n- EXIF orientation from the source is applied to the pixels, so the output displays upright even though the target format carries no orientation metadata.\n\nThe original JPEG quantization is preserved exactly; the WebP is lossless.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=jpeg;image"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the JPEG file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:ext=webp;image",
                      "name": "output",
                      "output_description": "Lossless WebP image",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-image;in=\"media:ext=png;image\";out=\"media:ext=jpeg;image\"",
                  "version": 2,
                  "title": "Convert PNG to JPEG",
                  "aliases": [
                    "convert-image-png-to-jpeg",
                    "png2jpeg"
                  ],
                  "cap_description": "Re-encode a PNG image as a JPEG",
                  "documentation": "## Purpose\n\nDecodes a PNG and re-encodes it as a JPEG. Use when a smaller file is preferred and the loss of transparency and the introduction of compression artifacts are acceptable.\n\n## Inputs\n\nA PNG file. RGBA inputs have the alpha channel composited against white.\n\n## Outputs\n\nA JPEG file at quality 85 (default, adjustable via --quality). EXIF orientation from the source is applied to the pixels, so the output displays upright.\n\n## Notes\n\nJPEG does not support transparency. Alpha is composited on a white background. Quality is fixed at 85; if you need different quality, request a feature.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=png;image"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the PNG file to convert"
                    },
                    {
                      "media_urn": "media:jpeg-quality;numeric",
                      "name": "quality",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--quality"
                        }
                      ],
                      "arg_description": "JPEG encode quality, 1-100",
                      "default_value": 85
                    },
                    {
                      "media_urn": "media:background-color;enc=utf-8",
                      "name": "background",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--background"
                        }
                      ],
                      "arg_description": "Matte color (hex #RRGGBB) that transparency composites onto — JPEG has no alpha channel",
                      "default_value": "#FFFFFF"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:ext=jpeg;image",
                      "name": "output",
                      "output_description": "JPEG-encoded image",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-image;in=\"media:ext=png;image\";out=\"media:ext=webp;image\"",
                  "version": 2,
                  "title": "Convert PNG to WebP",
                  "aliases": [
                    "convert-image-png-to-webp",
                    "png2webp"
                  ],
                  "cap_description": "Re-encode a PNG image as a lossless WebP",
                  "documentation": "## Purpose\n\nDecodes a PNG and writes it as a lossless WebP. Lossless WebP is typically smaller than PNG for the same pixel content.\n\n## Inputs\n\nA PNG file (with or without alpha).\n\n## Outputs\n\nA lossless WebP file with the same pixel content.\n\n## Notes\n\nThis produces lossless WebP only. Lossy WebP encoding is not exposed.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=png;image"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the PNG file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:ext=webp;image",
                      "name": "output",
                      "output_description": "Lossless WebP image",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-image;in=\"media:ext=tiff;image\";out=\"media:ext=jpeg;image\"",
                  "version": 2,
                  "title": "Convert TIFF to JPEG",
                  "aliases": [
                    "convert-image-tiff-to-jpeg",
                    "tiff2jpeg"
                  ],
                  "cap_description": "Re-encode a TIFF image as a JPEG",
                  "documentation": "## Purpose\n\nDecodes a TIFF (the first image in a multi-image TIFF) and writes it as a JPEG.\n\n## Inputs\n\nA TIFF file (uncompressed, LZW, PackBits or Deflate). Multi-page TIFFs use the first page.\n\n## Outputs\n\nA JPEG file at quality 85.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=tiff;image"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the TIFF file to convert"
                    },
                    {
                      "media_urn": "media:jpeg-quality;numeric",
                      "name": "quality",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--quality"
                        }
                      ],
                      "arg_description": "JPEG encode quality, 1-100",
                      "default_value": 85
                    },
                    {
                      "media_urn": "media:background-color;enc=utf-8",
                      "name": "background",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--background"
                        }
                      ],
                      "arg_description": "Matte color (hex #RRGGBB) that transparency composites onto — JPEG has no alpha channel",
                      "default_value": "#FFFFFF"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:ext=jpeg;image",
                      "name": "output",
                      "output_description": "JPEG-encoded image",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-image;in=\"media:ext=tiff;image\";out=\"media:ext=png;image\"",
                  "version": 2,
                  "title": "Convert TIFF to PNG",
                  "aliases": [
                    "convert-image-tiff-to-png",
                    "tiff2png"
                  ],
                  "cap_description": "Re-encode a TIFF image as a PNG",
                  "documentation": "## Purpose\n\nDecodes a TIFF (the first image in a multi-image TIFF) and writes it as a PNG. Useful when downstream caps require PNG input.\n\n## Inputs\n\nA TIFF file. For multi-page TIFFs, only the first page is used.\n\n## Outputs\n\nA PNG file with the same pixel content.\n\n## Notes\n\n- EXIF orientation from the source is applied to the pixels, so the output displays upright even though the target format carries no orientation metadata.\n\n- Multi-page TIFF inputs convert their FIRST page only (a warning is logged when pages are dropped).\n\nUncompressed, LZW, PackBits and Deflate-compressed TIFFs are supported. JPEG-in-TIFF and CCITT fax compressions are not supported and will fail hard.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=tiff;image"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the TIFF file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:ext=png;image",
                      "name": "output",
                      "output_description": "PNG-encoded image",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-image;in=\"media:ext=webp;image\";out=\"media:ext=jpeg;image\"",
                  "version": 2,
                  "title": "Convert WebP to JPEG",
                  "aliases": [
                    "convert-image-webp-to-jpeg",
                    "webp2jpeg"
                  ],
                  "cap_description": "Re-encode a WebP image as a JPEG",
                  "documentation": "## Purpose\n\nDecodes a WebP image and writes it as a JPEG.\n\n## Inputs\n\nA WebP file (still image; animated WebP first frame is used).\n\n## Outputs\n\nA JPEG file at quality 85.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=webp;image"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the WebP file to convert"
                    },
                    {
                      "media_urn": "media:jpeg-quality;numeric",
                      "name": "quality",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--quality"
                        }
                      ],
                      "arg_description": "JPEG encode quality, 1-100",
                      "default_value": 85
                    },
                    {
                      "media_urn": "media:background-color;enc=utf-8",
                      "name": "background",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--background"
                        }
                      ],
                      "arg_description": "Matte color (hex #RRGGBB) that transparency composites onto — JPEG has no alpha channel",
                      "default_value": "#FFFFFF"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:ext=jpeg;image",
                      "name": "output",
                      "output_description": "JPEG-encoded image",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-image;in=\"media:ext=webp;image\";out=\"media:ext=png;image\"",
                  "version": 2,
                  "title": "Convert WebP to PNG",
                  "aliases": [
                    "convert-image-webp-to-png",
                    "webp2png"
                  ],
                  "cap_description": "Re-encode a WebP image as a PNG",
                  "documentation": "## Purpose\n\nDecodes a WebP image and writes it as a PNG. Lossy and lossless WebP are both supported on input.\n\n## Inputs\n\nA WebP file (still image; animated WebP first frame is used).\n\n## Outputs\n\nA PNG file with the same pixel content.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=webp;image"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the WebP file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:ext=png;image",
                      "name": "output",
                      "output_description": "PNG-encoded image",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                }
              ],
              "adapter_urns": [
                "media:ext=bmp;image",
                "media:ext=gif;image",
                "media:ext=jpeg;image",
                "media:ext=png;image",
                "media:ext=tiff;image",
                "media:ext=webp;image"
              ]
            }
          ],
          "latestVersion": "1.166.397",
          "versions": {
            "1.166.397": {
              "releaseDate": "2026-10-15T07:26:36Z",
              "changelog": [
                "Initial release"
              ],
              "minAppVersion": "1.0.0",
              "builds": [
                {
                  "platform": "darwin-arm64",
                  "package": {
                    "name": "imagecartridge-1.166.397-darwin-arm64.pkg",
                    "url": "https://cartridges.machinefabric.com/release/imagecartridge/1.166.397/imagecartridge-1.166.397-darwin-arm64.pkg",
                    "sha256": "71b4ad75efde88e3b702d80b4142f21c43edffa4869063e9b16b330f375db14b",
                    "size": 2101103
                  },
                  "packages": [
                    {
                      "name": "imagecartridge-1.166.397-darwin-arm64.pkg",
                      "url": "https://cartridges.machinefabric.com/release/imagecartridge/1.166.397/imagecartridge-1.166.397-darwin-arm64.pkg",
                      "sha256": "71b4ad75efde88e3b702d80b4142f21c43edffa4869063e9b16b330f375db14b",
                      "size": 2101103,
                      "format": "pkg"
                    }
                  ],
                  "binary": {
                    "name": "imagecartridge-1.166.397-darwin-arm64.bin",
                    "url": "https://cartridges.machinefabric.com/release/imagecartridge/1.166.397/imagecartridge-1.166.397-darwin-arm64.bin",
                    "sha256": "ea7b2c19f85cc7f8892a26b73100904313c0729e143f23f95778cfa1d39c81d9",
                    "size": 5650480,
                    "signature": "untrusted comment: signature from rsign secret key\nRUTbeBdFkW9D4qO4G/Tp+Qg2RRc8+Son8+WuuxJmOxHCiHyavMHo+YMXJrcuLekjhMFupr6lyMPC6VxkR3vU/LivIt8fsNH5bgM=\ntrusted comment: file:imagecartridge-1.166.397-darwin-arm64.bin sha256=ea7b2c19f85cc7f8892a26b73100904313c0729e143f23f95778cfa1d39c81d9\noRQoyxQcE2IFS/XvBw8LaGyqSXPiReGiTjPgMG6ubTW0s3km9FNMtmD4dNcGr2zShpftgKLeEZRM0pXgWyEQBg==\n"
                  }
                }
              ]
            }
          }
        },
        "audiocartridge": {
          "name": "audiocartridge",
          "description": "Cross-format audio conversion (MP3, FLAC, OGG/Vorbis, AAC, M4A, AIFF, Opus, WAV → WAV/FLAC).",
          "author": "https://github.com/machinefabric",
          "pageUrl": "https://github.com/machinefabric/audiocartridge",
          "teamId": "P336JK947M",
          "minAppVersion": "1.0.0",
          "categories": [],
          "tags": [],
          "cap_groups": [
            {
              "name": "audio-formats",
              "caps": [
                {
                  "urn": "cap:effect=none",
                  "title": "Identity",
                  "aliases": [
                    "identity"
                  ],
                  "cap_description": "The categorical identity morphism. Echoes input as output unchanged. Mandatory in every capability set.",
                  "args": [
                    {
                      "media_urn": "media:",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:"
                        }
                      ]
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:",
                      "name": "output",
                      "output_description": "The input data, unchanged",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-audio;in=\"media:audio;ext=aac\";out=\"media:audio;ext=flac\"",
                  "version": 2,
                  "title": "Convert AAC to FLAC",
                  "aliases": [
                    "convert-audio-aac-to-flac",
                    "aac2flac"
                  ],
                  "cap_description": "Decode AAC (ADTS) and re-encode as lossless FLAC",
                  "documentation": "## Purpose\n\nDecodes a raw AAC (ADTS-framed) file and writes it as FLAC.\n\n## Inputs\n\nAn AAC file in ADTS framing.\n\n## Outputs\n\nA FLAC file. Bit depth is preserved up to FLAC's 24-bit cap: 16-bit-or-less sources encode as 16-bit FLAC, 17-24-bit as 24-bit FLAC (both lossless); wider-than-24-bit and float sources reduce to 24-bit WITH triangular dithering (a stated depth reduction, never a silent truncation).",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:audio;ext=aac"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the AAC file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=flac",
                      "name": "output",
                      "output_description": "FLAC-encoded audio",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-audio;in=\"media:audio;ext=aac\";out=\"media:audio;ext=wav\"",
                  "version": 2,
                  "title": "Convert AAC to WAV",
                  "aliases": [
                    "convert-audio-aac-to-wav",
                    "aac2wav"
                  ],
                  "cap_description": "Decode AAC (ADTS) to uncompressed WAV (PCM)",
                  "documentation": "## Purpose\n\nDecodes a raw AAC (ADTS-framed) file and writes it as PCM WAV (bit depth preserved from the source).\n\n## Inputs\n\nAn AAC file in ADTS framing. AAC tracks inside MP4 containers should use the M4A converter.\n\n## Outputs\n\nA PCM WAV file. PCM WAV preserving the source's bit depth: 16-bit-or-less sources encode as pcm_s16le, 17-24-bit as pcm_s24le, wider integer as pcm_s32le, float sources as pcm_f32le — all lossless, nothing is truncated.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:audio;ext=aac"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the AAC file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=wav",
                      "name": "output",
                      "output_description": "PCM WAV (source bit depth preserved)",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-audio;in=\"media:audio;ext=aiff\";out=\"media:audio;ext=flac\"",
                  "version": 2,
                  "title": "Convert AIFF to FLAC",
                  "aliases": [
                    "convert-audio-aiff-to-flac",
                    "aiff2flac"
                  ],
                  "cap_description": "Decode AIFF and re-encode as lossless FLAC",
                  "documentation": "## Purpose\n\nDecodes an AIFF file and writes it as FLAC. Both are lossless; FLAC is dramatically smaller.\n\n## Inputs\n\nAn AIFF file. AIFF-C with PCM payload is supported.\n\n## Outputs\n\nA FLAC file. Bit depth is preserved up to FLAC's 24-bit cap: 16-bit-or-less sources encode as 16-bit FLAC, 17-24-bit as 24-bit FLAC (both lossless); wider-than-24-bit and float sources reduce to 24-bit WITH triangular dithering (a stated depth reduction, never a silent truncation).",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:audio;ext=aiff"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the AIFF file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=flac",
                      "name": "output",
                      "output_description": "FLAC-encoded audio",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-audio;in=\"media:audio;ext=aiff\";out=\"media:audio;ext=wav\"",
                  "version": 2,
                  "title": "Convert AIFF to WAV",
                  "aliases": [
                    "convert-audio-aiff-to-wav",
                    "aiff2wav"
                  ],
                  "cap_description": "Decode an AIFF file to uncompressed WAV (PCM)",
                  "documentation": "## Purpose\n\nDecodes an AIFF (Audio Interchange File Format) file and writes it as PCM WAV (bit depth preserved from the source). AIFF and WAV are both PCM containers; this is a re-container.\n\n## Inputs\n\nAn AIFF file. AIFF-C with PCM payload is supported. AIFF-C with compressed payloads is not.\n\n## Outputs\n\nA PCM WAV file. PCM WAV preserving the source's bit depth: 16-bit-or-less sources encode as pcm_s16le, 17-24-bit as pcm_s24le, wider integer as pcm_s32le, float sources as pcm_f32le — all lossless, nothing is truncated.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:audio;ext=aiff"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the AIFF file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=wav",
                      "name": "output",
                      "output_description": "PCM WAV (source bit depth preserved)",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-audio;in=\"media:audio;ext=flac\";out=\"media:audio;ext=wav\"",
                  "version": 2,
                  "title": "Convert FLAC to WAV",
                  "aliases": [
                    "convert-audio-flac-to-wav",
                    "flac2wav"
                  ],
                  "cap_description": "Decode FLAC to uncompressed WAV (PCM)",
                  "documentation": "## Purpose\n\nDecodes a FLAC file and writes it as PCM WAV (bit depth preserved from the source). Both formats are lossless; this is a re-container, useful when downstream caps require WAV.\n\n## Inputs\n\nA FLAC file.\n\n## Outputs\n\nA PCM WAV file. PCM WAV preserving the source's bit depth: 16-bit-or-less sources encode as pcm_s16le, 17-24-bit as pcm_s24le, wider integer as pcm_s32le, float sources as pcm_f32le — all lossless, nothing is truncated.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:audio;ext=flac"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the FLAC file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=wav",
                      "name": "output",
                      "output_description": "PCM WAV (source bit depth preserved)",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-audio;in=\"media:audio;ext=m4a\";out=\"media:audio;ext=flac\"",
                  "version": 2,
                  "title": "Convert M4A to FLAC",
                  "aliases": [
                    "convert-audio-m4a-to-flac",
                    "m4a2flac"
                  ],
                  "cap_description": "Decode an M4A (AAC-in-MP4) file and re-encode as lossless FLAC",
                  "documentation": "## Purpose\n\nDemuxes the audio track from an M4A container, decodes the AAC bitstream, and writes it as FLAC.\n\n## Inputs\n\nAn M4A file. AAC and ALAC tracks are supported.\n\n## Outputs\n\nA FLAC file. Bit depth is preserved up to FLAC's 24-bit cap: 16-bit-or-less sources encode as 16-bit FLAC, 17-24-bit as 24-bit FLAC (both lossless); wider-than-24-bit and float sources reduce to 24-bit WITH triangular dithering (a stated depth reduction, never a silent truncation).",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:audio;ext=m4a"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the M4A file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=flac",
                      "name": "output",
                      "output_description": "FLAC-encoded audio",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-audio;in=\"media:audio;ext=m4a\";out=\"media:audio;ext=wav\"",
                  "version": 2,
                  "title": "Convert M4A to WAV",
                  "aliases": [
                    "convert-audio-m4a-to-wav",
                    "m4a2wav"
                  ],
                  "cap_description": "Decode an M4A (AAC-in-MP4) file to uncompressed WAV (PCM)",
                  "documentation": "## Purpose\n\nDemuxes the audio track from an M4A container and decodes the AAC (or ALAC) bitstream as PCM WAV (bit depth preserved from the source).\n\n## Inputs\n\nAn M4A file. AAC and Apple Lossless (ALAC) audio tracks are supported.\n\n## Outputs\n\nA PCM WAV file at the source's native sample rate and channel count. PCM WAV preserving the source's bit depth: 16-bit-or-less sources encode as pcm_s16le, 17-24-bit as pcm_s24le, wider integer as pcm_s32le, float sources as pcm_f32le — all lossless, nothing is truncated.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:audio;ext=m4a"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the M4A file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=wav",
                      "name": "output",
                      "output_description": "PCM WAV (source bit depth preserved)",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-audio;in=\"media:audio;ext=mp3\";out=\"media:audio;ext=flac\"",
                  "version": 2,
                  "title": "Convert MP3 to FLAC",
                  "aliases": [
                    "convert-audio-mp3-to-flac",
                    "mp32flac"
                  ],
                  "cap_description": "Decode MP3 and re-encode as lossless FLAC",
                  "documentation": "## Purpose\n\nDecodes an MP3 file and writes it as FLAC. Useful for archiving the decoded MP3 without further generation loss.\n\n## Inputs\n\nAn MP3 file.\n\n## Outputs\n\nA FLAC file containing the decoded PCM exactly as the MP3 decoder produced it. Bit depth is preserved up to FLAC's 24-bit cap: 16-bit-or-less sources encode as 16-bit FLAC, 17-24-bit as 24-bit FLAC (both lossless); wider-than-24-bit and float sources reduce to 24-bit WITH triangular dithering (a stated depth reduction, never a silent truncation).\n\n## Notes\n\nThe output preserves the MP3 decoder's PCM exactly; no further lossy compression is applied.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:audio;ext=mp3"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the MP3 file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=flac",
                      "name": "output",
                      "output_description": "FLAC-encoded audio",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-audio;in=\"media:audio;ext=mp3\";out=\"media:audio;ext=wav\"",
                  "version": 3,
                  "title": "Convert MP3 to WAV",
                  "aliases": [
                    "convert-audio-mp3-to-wav",
                    "mp32wav"
                  ],
                  "cap_description": "Decode MP3 to uncompressed WAV (PCM)",
                  "documentation": "## Purpose\n\nDecodes an MP3 file and writes it as PCM WAV (bit depth preserved from the source). This is the canonical step before transcription, since [Transcribe Audio (Candle)](https://capdag.com/browse/cap:candle;in=\"media:audio;ext=wav\";ml-model;out=\"media:enc=utf-8;record;transcription\";transcribe) requires WAV input.\n\n## Inputs\n\nAn MP3 file (CBR or VBR, any sample rate or channel count Symphonia supports).\n\n## Outputs\n\nA PCM WAV file at the source's native sample rate and channel count. PCM WAV preserving the source's bit depth: 16-bit-or-less sources encode as pcm_s16le, 17-24-bit as pcm_s24le, wider integer as pcm_s32le, float sources as pcm_f32le — all lossless, nothing is truncated.\n\n## Notes\n\nThe output is bit-exact decoded PCM; no resampling is performed. If a downstream consumer requires a specific sample rate, follow with a resampling cap.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:audio;ext=mp3"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the MP3 file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=wav",
                      "name": "output",
                      "output_description": "PCM WAV (source bit depth preserved)",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-audio;in=\"media:audio;ext=ogg\";out=\"media:audio;ext=flac\"",
                  "version": 2,
                  "title": "Convert OGG to FLAC",
                  "aliases": [
                    "convert-audio-ogg-to-flac",
                    "ogg2flac"
                  ],
                  "cap_description": "Decode OGG (Vorbis) and re-encode as lossless FLAC",
                  "documentation": "## Purpose\n\nDecodes an OGG-Vorbis file and writes it as FLAC.\n\n## Inputs\n\nAn OGG file containing a Vorbis stream.\n\n## Outputs\n\nA FLAC file containing the decoded PCM. Bit depth is preserved up to FLAC's 24-bit cap: 16-bit-or-less sources encode as 16-bit FLAC, 17-24-bit as 24-bit FLAC (both lossless); wider-than-24-bit and float sources reduce to 24-bit WITH triangular dithering (a stated depth reduction, never a silent truncation).",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:audio;ext=ogg"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the OGG file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=flac",
                      "name": "output",
                      "output_description": "FLAC-encoded audio",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-audio;in=\"media:audio;ext=ogg\";out=\"media:audio;ext=wav\"",
                  "version": 2,
                  "title": "Convert OGG to WAV",
                  "aliases": [
                    "convert-audio-ogg-to-wav",
                    "ogg2wav"
                  ],
                  "cap_description": "Decode OGG (Vorbis) to uncompressed WAV (PCM)",
                  "documentation": "## Purpose\n\nDecodes an OGG-Vorbis file and writes it as PCM WAV (bit depth preserved from the source).\n\n## Inputs\n\nAn OGG file containing a Vorbis stream.\n\n## Outputs\n\nA PCM WAV file at the source's native sample rate and channel count. PCM WAV preserving the source's bit depth: 16-bit-or-less sources encode as pcm_s16le, 17-24-bit as pcm_s24le, wider integer as pcm_s32le, float sources as pcm_f32le — all lossless, nothing is truncated.\n\n## Notes\n\nOnly Vorbis streams in OGG are supported. For Opus-in-OGG, use the dedicated Opus conversion cap.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:audio;ext=ogg"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the OGG file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=wav",
                      "name": "output",
                      "output_description": "PCM WAV (source bit depth preserved)",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-audio;in=\"media:audio;ext=opus\";out=\"media:audio;ext=flac\"",
                  "version": 2,
                  "title": "Convert Opus to FLAC",
                  "aliases": [
                    "convert-audio-opus-to-flac",
                    "opus2flac"
                  ],
                  "cap_description": "Decode Opus and re-encode as FLAC",
                  "documentation": "## Purpose\n\nDecodes an Opus audio file (typically wrapped in an Ogg container) and writes the resulting PCM as a FLAC file.\n\n## Inputs\n\nAn Opus file.\n\n## Outputs\n\nA FLAC file containing the decoded PCM as produced by the Opus decoder at 48 kHz. Bit depth is preserved up to FLAC's 24-bit cap: 16-bit-or-less sources encode as 16-bit FLAC, 17-24-bit as 24-bit FLAC (both lossless); wider-than-24-bit and float sources reduce to 24-bit WITH triangular dithering (a stated depth reduction, never a silent truncation).\n\n## Notes\n\nOpus always decodes to 48 kHz PCM internally. The FLAC output therefore reports a 48 kHz sample rate regardless of the encoder hint embedded in the OpusHead identification packet.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:audio;ext=opus"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the Opus file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=flac",
                      "name": "output",
                      "output_description": "FLAC-encoded audio",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-audio;in=\"media:audio;ext=opus\";out=\"media:audio;ext=wav\"",
                  "version": 2,
                  "title": "Convert Opus to WAV",
                  "aliases": [
                    "convert-audio-opus-to-wav",
                    "opus2wav"
                  ],
                  "cap_description": "Decode an Opus file to uncompressed WAV (PCM)",
                  "documentation": "## Purpose\n\nDecodes an Opus stream (in OGG container) and writes it as PCM WAV (bit depth preserved from the source). Opus is the modern lossy codec used by WebRTC and many browser-recorded audio streams.\n\n## Inputs\n\nAn Opus file (OGG-Opus container).\n\n## Outputs\n\nA PCM WAV file at 48 kHz (Opus's native rate). PCM WAV preserving the source's bit depth: 16-bit-or-less sources encode as pcm_s16le, 17-24-bit as pcm_s24le, wider integer as pcm_s32le, float sources as pcm_f32le — all lossless, nothing is truncated.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:audio;ext=opus"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the Opus file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=wav",
                      "name": "output",
                      "output_description": "PCM WAV at 48 kHz (source bit depth preserved)",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:convert-audio;in=\"media:audio;ext=wav\";out=\"media:audio;ext=flac\"",
                  "version": 2,
                  "title": "Convert WAV to FLAC",
                  "aliases": [
                    "convert-audio-wav-to-flac",
                    "wav2flac"
                  ],
                  "cap_description": "Re-encode WAV as lossless FLAC",
                  "documentation": "## Purpose\n\nEncodes a WAV file as FLAC. Both formats are lossless; FLAC is typically half the size or less for the same audio.\n\n## Inputs\n\nA PCM WAV file. PCM WAV preserving the source's bit depth: 16-bit-or-less sources encode as pcm_s16le, 17-24-bit as pcm_s24le, wider integer as pcm_s32le, float sources as pcm_f32le — all lossless, nothing is truncated.\n\n## Outputs\n\nA FLAC file with the same audio content. Bit depth is preserved up to FLAC's 24-bit cap: 16-bit-or-less sources encode as 16-bit FLAC, 17-24-bit as 24-bit FLAC (both lossless); wider-than-24-bit and float sources reduce to 24-bit WITH triangular dithering (a stated depth reduction, never a silent truncation).",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:audio;ext=wav"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the WAV file to convert"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=flac",
                      "name": "output",
                      "output_description": "FLAC-encoded lossless audio",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:encode-audio-frames;in=\"media:audio;audio-frames;pcm\";out=\"media:audio;ext=wav\"",
                  "version": 4,
                  "title": "Encode Audio Frames as WAV",
                  "aliases": [
                    "encode-audio-frames-wav",
                    "frames2wav"
                  ],
                  "cap_description": "Assemble a PCM audio-frame sequence (live microphone capture or replay) into a single WAV file",
                  "documentation": "## Purpose\n\nFolds a sequence of raw PCM audio frames — the CONTENT a resolved live\nmicrophone feed delivers (13.2 §Reference Media) — into one WAV file. This\nis the bridge between live audio capture and every WAV-consuming cap:\n`microphone → encode-audio-frames-wav → transcribe` is the canonical live\ntranscription machine, and `microphone → encode-audio-frames-wav` alone is\na recorder.\n\n## Inputs\n\nA sequence of `media:audio;audio-frames;pcm` items: signed 16-bit little-endian\ninterleaved PCM buffers. The stream-level metadata MUST carry the capture\nformat actuals (`sample_rate`, `channels`) — a frame stream without them\ncannot be encoded and fails loudly.\n\n## Outputs\n\nOne WAV file (PCM s16le) containing every delivered frame, in capture\norder.\n\n## Notes\n\n- This is a FOLD with deferred emission (15.2 §Live-Feed Machines): over a\n  live feed the WAV materializes when the feed ends — a stop condition\n  fires, or the run is stopped (close-tap-and-drain). A stopped recording\n  is a valid, complete recording.\n- Overrun gaps (12.5 §Overrun) are genuine discontinuities: the dropped\n  frames are simply absent from the file. The gap accounting stays on the\n  run's protocol counters — nothing is silently synthesized to paper over\n  loss.\n- An empty frame sequence is a real input error, not an empty WAV: a feed\n  that delivered nothing means the capture never produced data, and\n  downstream caps must not run on a silent zero-length file.",
                  "args": [
                    {
                      "media_urn": "media:audio;audio-frames;pcm",
                      "name": "input",
                      "required": true,
                      "is_sequence": true,
                      "streaming": true,
                      "sources": [
                        {
                          "stdin": "media:audio;audio-frames;pcm"
                        }
                      ],
                      "arg_description": "Sequence of raw PCM (s16le) audio frame buffers with sample_rate/channels stream metadata"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=wav",
                      "name": "output",
                      "output_description": "A single WAV (PCM s16le) file assembled from the frame sequence",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": true
                    }
                  ]
                }
              ],
              "adapter_urns": [
                "media:audio;ext=aac",
                "media:audio;ext=aiff",
                "media:audio;ext=flac",
                "media:audio;ext=m4a",
                "media:audio;ext=mp3",
                "media:audio;ext=ogg",
                "media:audio;ext=opus",
                "media:audio;ext=wav"
              ]
            }
          ],
          "latestVersion": "1.189.507",
          "versions": {
            "1.189.507": {
              "releaseDate": "2026-10-15T07:27:16Z",
              "changelog": [
                "Initial release"
              ],
              "minAppVersion": "1.0.0",
              "builds": [
                {
                  "platform": "darwin-arm64",
                  "package": {
                    "name": "audiocartridge-1.189.507-darwin-arm64.pkg",
                    "url": "https://cartridges.machinefabric.com/release/audiocartridge/1.189.507/audiocartridge-1.189.507-darwin-arm64.pkg",
                    "sha256": "46e061d2c9ea5784cadca9cd2c27a4793db1d0703f3c46307da73e94d18e94d1",
                    "size": 4394332
                  },
                  "packages": [
                    {
                      "name": "audiocartridge-1.189.507-darwin-arm64.pkg",
                      "url": "https://cartridges.machinefabric.com/release/audiocartridge/1.189.507/audiocartridge-1.189.507-darwin-arm64.pkg",
                      "sha256": "46e061d2c9ea5784cadca9cd2c27a4793db1d0703f3c46307da73e94d18e94d1",
                      "size": 4394332,
                      "format": "pkg"
                    }
                  ],
                  "binary": {
                    "name": "audiocartridge-1.189.507-darwin-arm64.bin",
                    "url": "https://cartridges.machinefabric.com/release/audiocartridge/1.189.507/audiocartridge-1.189.507-darwin-arm64.bin",
                    "sha256": "09dcc5a04fcc5eb6c4acbad33f2236b49af5be981738aba9950bd38a93a5d071",
                    "size": 10983408,
                    "signature": "untrusted comment: signature from rsign secret key\nRUTbeBdFkW9D4plUBb3GQ3jT1frzLvyzETk8QOrUVH/CeFVroDgUJfSu+gcZz3/sA79X+BQymbQOVDQSMtUcSs9GEoqWEOY3vwg=\ntrusted comment: file:audiocartridge-1.189.507-darwin-arm64.bin sha256=09dcc5a04fcc5eb6c4acbad33f2236b49af5be981738aba9950bd38a93a5d071\nRQqMdvrMYntXIRPBcd6PvhSP3zxzJ3EZtL/zYrTHLWmU7bPIob4DoSUoQfBvy8hiiOnL+VNj77yBEDYTa2ViAw==\n"
                  }
                }
              ]
            }
          }
        },
        "videocartridge": {
          "name": "videocartridge",
          "description": "Extract audio tracks (no re-encoding) and decode video frames from MP4, MOV, WebM and MKV containers.",
          "author": "https://github.com/machinefabric",
          "pageUrl": "https://github.com/machinefabric/videocartridge",
          "teamId": "P336JK947M",
          "minAppVersion": "1.0.0",
          "categories": [],
          "tags": [],
          "cap_groups": [
            {
              "name": "video-formats",
              "caps": [
                {
                  "urn": "cap:effect=none",
                  "title": "Identity",
                  "aliases": [
                    "identity"
                  ],
                  "cap_description": "The categorical identity morphism. Echoes input as output unchanged. Mandatory in every capability set.",
                  "args": [
                    {
                      "media_urn": "media:",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:"
                        }
                      ]
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:",
                      "name": "output",
                      "output_description": "The input data, unchanged",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:extract-audio-track;in=\"media:ext=mkv;video\";out=\"media:audio;ext=opus\"",
                  "version": 2,
                  "title": "Extract Audio Track from MKV",
                  "aliases": [
                    "extract-audio-track-mkv",
                    "audio-from-mkv"
                  ],
                  "cap_description": "Demux the audio track from a Matroska MKV and write it as an Opus file",
                  "documentation": "## Purpose\n\nExtracts the audio track from a Matroska MKV container and writes it as an Opus file.\n\n## Inputs\n\nAn MKV file with an Opus audio track.\n\n## Outputs\n\nAn Opus file (OGG-Opus). No re-encoding occurs.\n\n## Notes\n\nIf the MKV has any audio codec other than Opus, this cap fails hard. Other codec adapters can be added as separate caps.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=mkv;video"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the MKV file"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=opus",
                      "name": "output",
                      "output_description": "Opus audio track",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:extract-audio-track;in=\"media:ext=mov;video\";out=\"media:audio;ext=m4a\"",
                  "version": 2,
                  "title": "Extract Audio Track from MOV",
                  "aliases": [
                    "extract-audio-track-mov",
                    "audio-from-mov"
                  ],
                  "cap_description": "Demux the audio track from a QuickTime MOV and write it as an M4A file",
                  "documentation": "## Purpose\n\nExtracts the AAC audio track from a QuickTime MOV file and writes it as an M4A. The MOV container is structurally identical to MP4 for the audio remux path.\n\n## Inputs\n\nA MOV file with an AAC audio track.\n\n## Outputs\n\nAn M4A file containing the source's AAC audio track. No re-encoding occurs.\n\n## Notes\n\nIf the MOV has no AAC audio track, the cap fails hard. There is no audio re-encoding fallback.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=mov;video"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the MOV file"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=m4a",
                      "name": "output",
                      "output_description": "M4A (AAC-in-MP4) audio track",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:extract-audio-track;in=\"media:ext=mp4;video\";out=\"media:audio;ext=m4a\"",
                  "version": 2,
                  "title": "Extract Audio Track from MP4",
                  "aliases": [
                    "extract-audio-track-mp4",
                    "audio-from-mp4"
                  ],
                  "cap_description": "Demux the audio track from an MP4 video and write it as an M4A file",
                  "documentation": "## Purpose\n\nExtracts the AAC audio track from an MP4 container and writes it as an M4A file (the same AAC bitstream, re-containered without re-encoding). This is the canonical first step when you have a video and want to feed its audio into a transcription pipeline.\n\n## Inputs\n\nAn MP4 file with an AAC audio track. Video tracks are ignored.\n\n## Outputs\n\nAn M4A file containing the source's AAC audio track. No re-encoding occurs; the AAC bitstream is bit-exact.\n\n## Notes\n\nIf the MP4 has no AAC audio track, the cap fails hard. There is no audio re-encoding fallback.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=mp4;video"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the MP4 file"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=m4a",
                      "name": "output",
                      "output_description": "M4A (AAC-in-MP4) audio track",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:extract-audio-track;in=\"media:ext=webm;video\";out=\"media:audio;ext=opus\"",
                  "version": 2,
                  "title": "Extract Audio Track from WebM",
                  "aliases": [
                    "extract-audio-track-webm",
                    "audio-from-webm"
                  ],
                  "cap_description": "Demux the audio track from a WebM container and write it as an Opus file",
                  "documentation": "## Purpose\n\nExtracts the audio track from a WebM container and writes it as an Opus file (OGG-Opus). WebM uses Opus or Vorbis for audio; this cap targets Opus.\n\n## Inputs\n\nA WebM file with an Opus audio track.\n\n## Outputs\n\nAn Opus file (OGG-Opus). No re-encoding occurs.\n\n## Notes\n\nIf the WebM has a Vorbis audio track instead of Opus, this cap fails hard. There is no codec fallback.",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=webm;video"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the WebM file"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:audio;ext=opus",
                      "name": "output",
                      "output_description": "Opus audio track",
                      "optional": false,
                      "is_sequence": false,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:extract-frames;in=\"media:ext=mkv;video\";out=\"media:ext=png;image\"",
                  "version": 3,
                  "title": "Extract Frames from MKV",
                  "aliases": [
                    "extract-frames-mkv",
                    "frames-mkv"
                  ],
                  "cap_description": "Decode the MKV video track and emit each frame as a PNG image",
                  "documentation": "## Purpose\n\nDecodes a Matroska MKV video and emits its frames as a sequence of PNG images. With no `--fps` argument every decoded frame is emitted; with `--fps N`, frames are decimated to approximately `N` per second by selecting the first decoded frame whose presentation timestamp passes each `1/N`-second boundary.\n\n## Inputs\n\n- An MKV file (path or stdin).\n- An optional target frame rate (default: every frame).\n\n## Outputs\n\nA sequence of PNG images, one per emitted frame.\n\n## Notes\n\n- Decoding happens in-process via embedded ffmpeg static archives — no system ffmpeg dependency, no shell-out.\n- For audio extraction from the same file, use [Extract Audio Track from MKV](https://capdag.com/browse/cap:extract-audio-track;in=\"media:ext=mkv;video\";out=\"media:audio;ext=opus\").",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=mkv;video"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the MKV file to process"
                    },
                    {
                      "media_urn": "media:fps;numeric",
                      "name": "fps",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--fps"
                        }
                      ],
                      "arg_description": "Target frames per second. Omit to emit every decoded frame."
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:ext=png;image",
                      "name": "output",
                      "output_description": "PNG images, one per emitted frame",
                      "optional": false,
                      "is_sequence": true,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:extract-frames;in=\"media:ext=mov;video\";out=\"media:ext=png;image\"",
                  "version": 3,
                  "title": "Extract Frames from MOV",
                  "aliases": [
                    "extract-frames-mov",
                    "frames-mov"
                  ],
                  "cap_description": "Decode the MOV video track and emit each frame as a PNG image",
                  "documentation": "## Purpose\n\nDecodes a QuickTime MOV video and emits its frames as a sequence of PNG images. With no `--fps` argument every decoded frame is emitted; with `--fps N`, frames are decimated to approximately `N` per second by selecting the first decoded frame whose presentation timestamp passes each `1/N`-second boundary.\n\n## Inputs\n\n- A MOV file (path or stdin).\n- An optional target frame rate (default: every frame).\n\n## Outputs\n\nA sequence of PNG images, one per emitted frame.\n\n## Notes\n\n- Decoding happens in-process via embedded ffmpeg static archives — no system ffmpeg dependency, no shell-out.\n- For audio extraction from the same file, use [Extract Audio Track from MOV](https://capdag.com/browse/cap:extract-audio-track;in=\"media:ext=mov;video\";out=\"media:audio;ext=m4a\").",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=mov;video"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the MOV file to process"
                    },
                    {
                      "media_urn": "media:fps;numeric",
                      "name": "fps",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--fps"
                        }
                      ],
                      "arg_description": "Target frames per second. Omit to emit every decoded frame."
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:ext=png;image",
                      "name": "output",
                      "output_description": "PNG images, one per emitted frame",
                      "optional": false,
                      "is_sequence": true,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:extract-frames;in=\"media:ext=mp4;video\";out=\"media:ext=png;image\"",
                  "version": 3,
                  "title": "Extract Frames from MP4",
                  "aliases": [
                    "extract-frames-mp4",
                    "frames-mp4"
                  ],
                  "cap_description": "Decode the MP4 video track and emit each frame as a PNG image",
                  "documentation": "## Purpose\n\nDecodes an MP4 video and emits its frames as a sequence of PNG images. With no `--fps` argument every decoded frame is emitted; with `--fps N`, frames are decimated to approximately `N` per second by selecting the first decoded frame whose presentation timestamp passes each `1/N`-second boundary.\n\n## Inputs\n\n- An MP4 file (path or stdin).\n- An optional target frame rate (default: every frame).\n\n## Outputs\n\nA sequence of PNG images, one per emitted frame.\n\n## Notes\n\n- Decoding happens in-process via embedded ffmpeg static archives — no system ffmpeg dependency, no shell-out.\n- Decoded frames are colour-converted to RGBA and re-encoded to PNG via the `image` crate; the byte stream is identical in shape to other `media:ext=png;image` producers in the cap fabric (e.g. PDF page rendering), so downstream image consumers work without adjustment.\n- For audio extraction from the same file, use [Extract Audio Track from MP4](https://capdag.com/browse/cap:extract-audio-track;in=\"media:ext=mp4;video\";out=\"media:audio;ext=m4a\").",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=mp4;video"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the MP4 file to process"
                    },
                    {
                      "media_urn": "media:fps;numeric",
                      "name": "fps",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--fps"
                        }
                      ],
                      "arg_description": "Target frames per second. Omit to emit every decoded frame."
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:ext=png;image",
                      "name": "output",
                      "output_description": "PNG images, one per emitted frame",
                      "optional": false,
                      "is_sequence": true,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:extract-frames;in=\"media:ext=webm;video\";out=\"media:ext=png;image\"",
                  "version": 3,
                  "title": "Extract Frames from WebM",
                  "aliases": [
                    "extract-frames-webm",
                    "frames-webm"
                  ],
                  "cap_description": "Decode the WebM video track and emit each frame as a PNG image",
                  "documentation": "## Purpose\n\nDecodes a WebM video and emits its frames as a sequence of PNG images. With no `--fps` argument every decoded frame is emitted; with `--fps N`, frames are decimated to approximately `N` per second by selecting the first decoded frame whose presentation timestamp passes each `1/N`-second boundary.\n\n## Inputs\n\n- A WebM file (path or stdin).\n- An optional target frame rate (default: every frame).\n\n## Outputs\n\nA sequence of PNG images, one per emitted frame.\n\n## Notes\n\n- Decoding happens in-process via embedded ffmpeg static archives — no system ffmpeg dependency, no shell-out.\n- For audio extraction from the same file, use [Extract Audio Track from WebM](https://capdag.com/browse/cap:extract-audio-track;in=\"media:ext=webm;video\";out=\"media:audio;ext=opus\").",
                  "args": [
                    {
                      "media_urn": "media:enc=utf-8;file-path",
                      "name": "input",
                      "required": true,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "stdin": "media:ext=webm;video"
                        },
                        {
                          "position": 0
                        }
                      ],
                      "arg_description": "Path to the WebM file to process"
                    },
                    {
                      "media_urn": "media:fps;numeric",
                      "name": "fps",
                      "required": false,
                      "is_sequence": false,
                      "streaming": false,
                      "sources": [
                        {
                          "cli_flag": "--fps"
                        }
                      ],
                      "arg_description": "Target frames per second. Omit to emit every decoded frame."
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:ext=png;image",
                      "name": "output",
                      "output_description": "PNG images, one per emitted frame",
                      "optional": false,
                      "is_sequence": true,
                      "streaming": false
                    }
                  ]
                },
                {
                  "urn": "cap:in=\"media:image;video-frame\";out=\"media:ext=png;image\";video-frames-to-png",
                  "version": 3,
                  "title": "Video Frames to PNG Images",
                  "aliases": [
                    "video-frames-to-png",
                    "frames2png"
                  ],
                  "cap_description": "Deliver a video-frame sequence (live webcam capture or replay) as a standard PNG image sequence",
                  "documentation": "## Purpose\n\nTurns a sequence of `media:image;video-frame` items — the CONTENT a\nresolved live webcam feed delivers (13.2 §Reference Media) — into the\nstandard PNG image sequence every image-consuming cap understands. This is\nthe bridge between live video capture and the rest of the fabric:\n`webcam → video-frames-to-png` is the canonical frame-capture machine, the\nvideo analog of `microphone → encode-audio-frames-wav`.\n\n## Inputs\n\nA sequence of `media:image;video-frame` items: individually encoded PNG\nframes with `seq`/`pts_us`/`capture_ts_us` per-item metadata and the\ncapture format actuals (`width`, `height`, `fps`, `pixel_format`) on the\nstream metadata.\n\n## Outputs\n\nA sequence of `media:ext=png;image` items — one PNG per delivered frame,\nin capture order, per-item metadata preserved.\n\n## Notes\n\n- Items STREAM: each frame is emitted as it arrives (15.2 §Live-Feed\n  Machines), so an unbounded feed yields an unbounded PNG sequence — the\n  stop condition (or a run stop) bounds it, never buffering.\n- Every item is verified to actually be a PNG (magic bytes). A frame\n  stream carrying any other encoding is a real input error, not a\n  silently mislabeled image.\n- Overrun gaps (12.5 §Overrun) are genuine discontinuities: dropped frames\n  are simply absent. Nothing is synthesized to paper over loss.\n- An empty frame sequence is a real input error, not an empty sequence: a\n  feed that delivered nothing means the capture never produced data.",
                  "args": [
                    {
                      "media_urn": "media:image;video-frame",
                      "name": "input",
                      "required": true,
                      "is_sequence": true,
                      "streaming": true,
                      "sources": [
                        {
                          "stdin": "media:image;video-frame"
                        }
                      ],
                      "arg_description": "Sequence of encoded video-frame items (PNG) with capture metadata"
                    }
                  ],
                  "outputs": [
                    {
                      "media_urn": "media:ext=png;image",
                      "name": "output",
                      "output_description": "PNG image sequence, one item per delivered frame, capture order",
                      "optional": false,
                      "is_sequence": true,
                      "streaming": true
                    }
                  ]
                }
              ],
              "adapter_urns": [
                "media:ext=mkv;video",
                "media:ext=mov;video",
                "media:ext=mp4;video",
                "media:ext=webm;video"
              ]
            }
          ],
          "latestVersion": "1.178.471",
          "versions": {
            "1.178.471": {
              "releaseDate": "2026-10-15T07:27:57Z",
              "changelog": [
                "Initial release"
              ],
              "minAppVersion": "1.0.0",
              "builds": [
                {
                  "platform": "darwin-arm64",
                  "package": {
                    "name": "videocartridge-1.178.471-darwin-arm64.pkg",
                    "url": "https://cartridges.machinefabric.com/release/videocartridge/1.178.471/videocartridge-1.178.471-darwin-arm64.pkg",
                    "sha256": "09fca07ad9d31f403253e61111cdb05763c712e29ec84dd3264d0e7d55dc5584",
                    "size": 4446541
                  },
                  "packages": [
                    {
                      "name": "videocartridge-1.178.471-darwin-arm64.pkg",
                      "url": "https://cartridges.machinefabric.com/release/videocartridge/1.178.471/videocartridge-1.178.471-darwin-arm64.pkg",
                      "sha256": "09fca07ad9d31f403253e61111cdb05763c712e29ec84dd3264d0e7d55dc5584",
                      "size": 4446541,
                      "format": "pkg"
                    }
                  ],
                  "binary": {
                    "name": "videocartridge-1.178.471-darwin-arm64.bin",
                    "url": "https://cartridges.machinefabric.com/release/videocartridge/1.178.471/videocartridge-1.178.471-darwin-arm64.bin",
                    "sha256": "1d577f29ea38a6431f4e9873f36a746c0df964d1698041cf234572a07689b016",
                    "size": 11103680,
                    "signature": "untrusted comment: signature from rsign secret key\nRUTbeBdFkW9D4vc4jxeLiG2cTKBgAWVQBhPqdJ5tYQ4yJuLnuCSmphusFyCxhMSx2yuLBRlhU5wuYol0eEbGzD5WpIB8PxBETAg=\ntrusted comment: file:videocartridge-1.178.471-darwin-arm64.bin sha256=1d577f29ea38a6431f4e9873f36a746c0df964d1698041cf234572a07689b016\nTlSnx+PCzcSWBSc55cGKWRkacgWEMQMBxmGjoFhHibHZRwStRGxjyRWdfIJK6K6OhuIwsED07jQBKxtfrSV7Bw==\n"
                  }
                }
              ]
            }
          }
        }
      }
    },
    "nightly": {
      "cartridges": {}
    }
  }
}