Fields
Fields are how your tool exchanges data with the user. They're declared in artifuncs.json under fields.input, fields.output, and settings. Each field has a type plus optional options.
Common options
These apply to every field type unless noted:
| Option | Type | Description |
|---|---|---|
label | string | Human-readable label shown above the field. Defaults to the field name. |
subtext | string | Small helper text shown under the label. Keep it short (roughly one line) — long subtext wraps and pushes the layout around. |
topRightHint | string | Small muted hint pinned to the top-right of the label row (e.g. "png, jpg, webp"). Good for format/limit reminders. |
placeholder | string | Placeholder text inside empty inputs (text-like fields only). |
default | any | Initial value. Type must match the field. |
readonly | boolean | User can read but not edit. Used for outputs. |
disabled | boolean | Field is greyed out and inert. |
copiable | boolean | Shows a copy-to-clipboard button. Useful on outputs. |
clearable | boolean | Shows a clear (×) button to wipe the value. |
subtext vs topRightHint: subtext is helper text near the field; topRightHint is a compact reminder pinned to the right edge of the label row — ideal for accepted formats or limits. Keep both short — a phrase, not a sentence — so they render on one line and don't crowd the form. Put longer guidance in userInstructions instead.
"avatar": {
"type": "file",
"label": "Source image",
"topRightHint": "png, jpg, webp",
"accept": "image/*"
}
text-field
Single-line text.
"name": {
"type": "text-field",
"label": "Your name",
"placeholder": "Ada Lovelace",
"default": ""
}
password
Single-line text that's masked as you type — same options as text-field. An eye button sits inside the field on the right; hold it down to reveal the value, release to re-mask. While the field is focused it also warns if Caps Lock is on. Use it for secrets like API keys or tokens so they aren't shoulder-surfed.
"apiKey": {
"type": "password",
"label": "API key",
"placeholder": "sk-…"
}
textarea
Multi-line text. Same options as text-field.
"notes": {
"type": "textarea",
"label": "Notes",
"placeholder": "Long-form text…"
}
code
A monospaced code box. Editable as an input, display-only as an output — so the same type serves "paste your config here" and "here's the generated result".
"payload": {
"type": "code",
"label": "Payload",
"language": "json",
"placeholder": "{ }"
}
::doc-field-example{type="code" label="Payload" options='{ "language": "python", "lineNumbers": true }' initial="total = sum(int(x) for x in input"values")"} ::
Options: language (syntax highlighting — json, python, javascript, typescript,
yaml, bash, sql, diff, html, css, markdown, xml, toml, ini, plus aliases
like js/py/yml; anything unknown renders as plain text) · filename (shows a header
with a copy button) · lineNumbers · wrap (on by default) · maxHeight in px ·
readonly to force display-only even as an input.
Colouring parts of the value
The value is normally just the code string. To highlight specific parts of what your func returns, return an object instead — the colouring travels with the value, because it depends on the value (where a JWT's dots fall), not on static field config:
def process(input, settings):
return {"token": {
"code": input["jwt"],
"segments": {"split": ".", "colors": ["warn", "info", "success"]},
}}
marks works the same way, for ranges rather than delimiters:
return {"payload": {"code": src, "marks": [
{"start": err.offset, "end": err.offset + err.length,
"underline": "wavy", "color": "danger", "title": err.message},
]}}
Both accept the same selectors and styles as the af-code-block view component —
see View components.
number
Numeric input. Accepts integers or floats.
"precision": {
"type": "number",
"label": "Precision",
"default": 2
}
slider
Numeric slider with a draggable thumb. Set min / max / step to define the scale and an
optional unit appended to the readout.
"volume": {
"type": "slider",
"label": "Volume",
"min": 0,
"max": 100,
"step": 1,
"default": 65,
"unit": "%"
}
Range mode — give it a tuple default and you get two thumbs, one per end. The value
stays an ordered [lo, hi] pair (the thumbs can't cross), and process() receives the array:
"heightRange": {
"type": "slider",
"label": "Height range",
"min": 0,
"max": 100,
"default": [40, 50]
}
slider adds: min (default 0), max (default 100), step (default 1; floats like
0.05 work), unit (readout suffix, e.g. "%").
checkbox
Boolean toggle.
"verbose": {
"type": "checkbox",
"label": "Verbose output",
"default": false
}
date
Date picker. Stored as YYYY-MM-DD.
"due": {
"type": "date",
"label": "Due date",
"clearable": true
}
file
File upload (input) or downloadable file reference (output). On input, the user picks a file from disk and your code receives its filename; on output you return a file for the user to download. See Files for how to read and write the bytes from inside process.
| Option | Description |
|---|---|
accept | Comma-separated MIME types or extensions, e.g. "image/*,.csv". |
multiple | Accept multiple files. |
maxSize | Max bytes per file. |
maxFiles | Max number of files when multiple is set. Picking past the limit appends only what fits and shows an inline "N files maximum" error — it doesn't reject the whole selection. |
"upload": {
"type": "file",
"label": "Upload CSV",
"accept": ".csv",
"maxSize": 5242880
}
image
Image output. Place it in output and return the same { path, size } shape a file output uses — the UI fetches the bytes back from the sandbox and renders the picture inline, with edit and download buttons in the top-right corner. A plain URL or data: URI string works too, if your func produces the image without writing it to disk.
Edit opens a full editor in a modal: crop and straighten, finetune (brightness, contrast, saturation, exposure, temperature, gamma, clarity, vignette), filter presets, freehand and shape annotations, an erase brush that cuts the background out to transparency (with a restore brush to carve back), stickers, background fill, pixelated redaction, decorative frames, and output resize — with undo/redo throughout. Edits are local to the browser: they change what you see and what the download button hands you, but they never rewrite the value the func returned, so a run stays reproducible. The "edited" badge reverts them.
Used as an input it behaves exactly like file (a picker); set accept to keep the choice to images.
"output": {
"thumbnail": {
"type": "image",
"label": "Generated thumbnail"
}
}
Empty until the run produces something:
color
Single color picker. Stored as a hex string — #RRGGBB, or #RRGGBBAA when an alpha (< 1) is chosen via the picker's alpha slider.
| Option | Description |
|---|---|
showTextField | Show a hex input next to the swatch. |
showSwatches | Show preset color swatches. |
variant | "minimal" — just the rounded-square swatch, no hex text. |
"brand": {
"type": "color",
"label": "Brand color",
"default": "#FF3C00",
"showTextField": true
}
color-palette
A list of hex colors that the user can add to or remove from. Stored as an array of strings.
"palette": {
"type": "color-palette",
"label": "Palette",
"default": ["#FF3C00", "#1A0A05"]
}
list
Array of homogeneous items. Use itemType to declare the type of each item — any field type from this page is allowed.
| Option | Description |
|---|---|
itemType | Field type used for each item. Defaults to text-field. |
addValueButtonText | Custom label for the "add item" button. |
"keywords": {
"type": "list",
"label": "Keywords",
"itemType": "text-field",
"default": []
}
select
Dropdown for picking a single value from a fixed set. Declare the choices with options. Stored as a string.
| Option | Description |
|---|---|
options | Array of selectable values. |
All common options (subtext, default, readonly, disabled, clearable, copiable, …) apply.
"size": {
"type": "select",
"label": "Size",
"subtext": "Pick the output size",
"options": ["Small", "Medium", "Large"],
"default": "Medium"
}
multi-select
Dropdown for picking any number of values from a fixed set. Same options as select. Stored as an array of strings.
| Option | Description |
|---|---|
options | Array of selectable values. |
"toppings": {
"type": "multi-select",
"label": "Toppings",
"options": ["Cheese", "Mushroom", "Olives"],
"default": []
}
Outputs
Output fields use the same type values as inputs. They're rendered as read-only by default. Add copiable: true to make them easy to copy:
"output": {
"result": {
"type": "text-field",
"label": "Result",
"copiable": true
}
}
A textarea output auto-grows to fit the result (capped, then scrolls) and shows a drag handle so the reader can resize it:
A select / multi-select placed in output renders automatically as a read-only display — plain text for select, chips for multi-select — with no dropdown chrome. Add copiable: true for a copy button:
"output": {
"tags": {
"type": "multi-select",
"label": "Detected tags",
"options": ["nature", "landscape", "portrait"],
"copiable": true
}
}
Settings
Settings declared under the top-level settings block use the exact same field types and options as inputs. They appear in a separate panel and persist across runs.