Formats and tools
API reference
Use this reference to read Soundfish links and files, run the CLI, and check document limits. It covers editable loops and songs built from those loops. For your first composition, start with the getting started guide.
Document schema
A loop is a required title plus canonical, MIDI-expressible content: integer bpm, integer bars, and ordered typed tracks. It is not a record containing a second stored midi byte field.
{
protocol: "soundfish.document/v1";
title: string;
bpm: 40..240 integer;
bars: 1..16;
effects: LoopEffects;
tracks: Array<NotesTrack | DrumsTrack>;
}A notes track has an opaque document-wide trk_ ID, editable name, zero-based GM1 gmProgram, production, lineage, and melodic events. A drums track has the same identity, name, production, and lineage fields, omits the program, may name an optional GS drum kit program 0–127(default 0, Standard), and uses GM percussion pitches 35–81. Every event has a unique evt_ ID, MIDI pitch, half-open step interval, and velocity 1–127. Drum hits occupy exactly one step.
A document may carry an optional integer swing 0–100 (default 0): every odd sixteenth step is delayed by swing / 100 × step / 2, so 66 approximates a triplet feel. An optional meta map describes the music without changing what plays: tonic 0–11 (C = 0), mode from major, minor, dorian, mixolydian, lydian, phrygian, aeolian, harmonic-minor, and genre of at most 32 UTF-8 bytes.
Every optional field uses omit-at-default encoding: kit, swing, meta, and the pan and cutoff lanes are absent from canonical bytes exactly when they hold their defaults, a present default is non-canonical, and meta never enters MusicCID. A document that uses none of them keeps the canonical bytes, MusicCID, and transport digest it had before the 2026-09 revision.
Time is fixed 4/4: 4 beats and 16 sixteenth-note steps per bar. Empty documents and empty tracks are valid.
Loop titles and track names are trimmed before validation and must remain nonempty, contain well-formed Unicode, and fit their 80- and 48-byte UTF-8 limits. Track IDs match ^trk_[a-z0-9][a-z0-9_-]{0,94}$, event IDs match ^evt_[a-z0-9][a-z0-9_-]{0,94}$, and operation IDs match ^op_[a-z0-9][a-z0-9_-]{0,94}$. Track and event IDs are unique across the complete document.
Song arrangement schema
A soundfish.arrangement/v1 document contains a title, a bounded roster of complete soundfish.document/v1 children paired with their MusicCIDs, and an ordered sequence of { loop, label, repeats } entries. Every child remains a 1–16-bar canonical loop. Children share one BPM and swing and compatible stable track IDs, kinds, GM programs, and drum kits, and every embedded child must be referenced. Children that differ only in metaare compatible; the first segment's meta is kept.
Structural parsing checks shape, track compatibility, references, and expansion bounds but does not establish child identity. Async verification re-derives every embedded MusicCID and returns a deeply frozen verified document. Playback resolution accepts only that verified boundary. URL decoding additionally verifies the transport digest, canonical JSON, and ArrangementCID.
Arrangement titles and section labels are trimmed before validation and must remain nonempty, contain well-formed Unicode, and fit their 160- and 80-byte UTF-8 limits. The roster has one canonical loop body per MusicCID. If two build segments have the same MusicCID but different canonical loop bytes—for example, because only titles, IDs, lineage, or display order differ—the v1 builder rejects the arrangement as ambiguous instead of discarding either body.
The local resolver offsets child events and automation into a bounded runtime playback score. The editor shows the ordered occurrences in a horizontal section strip and auditions either the full song or the selected section through one transport. Embedded sections remain read-only; Edit a copy detaches the selected child as an independent editable loop.
Production and automation
Every track owns volume, reverbSend, and delaySend lanes and may author optional pan and cutoff lanes. The document owns reverb.return, delay.return, delay.feedback, and delay.timeMilliBeats lanes. A lane contains one integer base and a canonical list of { step, value, curve } points.
Point steps are unique, sorted, and inside the composition. The base holds before the first point. A point's hold or linear curve controls only the segment to the next explicit point. The final point holds to the cycle end. At the loop seam the lane resets to its base; there is no implicit wrap ramp.
| Lane | Range | Default |
|---|---|---|
| Track volume | 0–10000 bp | 10000 |
| Track reverb send | 0–10000 bp | 0 |
| Track delay send | 0–10000 bp | 0 |
| Track pan (0 left, 10000 right) | 0–10000 bp | 5000 |
| Track cutoff (200 Hz–20 kHz, logarithmic) | 0–10000 bp | 10000 |
| Reverb return | 0–10000 bp | 2000 |
| Delay return | 0–10000 bp | 2500 |
| Delay feedback | 0–9500 bp | 3500 |
| Delay time | 62–4000 milli-beats | 500 |
The editor exposes authored track volume and the base reverb and delay controls. Agents and the CLI can author complete automation point lists. Session master gain and mute are monitoring state and do not enter the document.
Self-contained URLs
Editable loop:
#s1.<music-cid>.<codec>.<payload>.<transport-digest>Read-only song arrangement:
#a1.<arrangement-cid>.<codec>.<payload>.<transport-digest>MusicCID is lowercase base32 CIDv1 with the raw codec and a SHA-256 multihash over a domain-separated semantic CBOR projection. It includes BPM, bars, swing when present, effects, track kind, GM program or drum kit when present, production including pan and cutoff lanes when present, events, and all automation. It excludes composition and track titles, meta, track and event IDs, lineage, operation IDs, runtime assets, and display order. Semantic tracks are byte-sorted; duplicate tracks remain repeated.
ArrangementCID commits to the expanded ordered child-MusicCID sequence and normalized semantic trajectories for every stable track slot. Cross-section routing changes therefore change identity; titles, section labels, repeat grouping, display order, and one consistent global track-ID rename do not.
For loops, codec c carries canonical CBOR bytes. For arrangements, it carries canonical JSON bytes. Codec d carries raw DEFLATE of the corresponding canonical bytes. Payload and transport digest use unpadded base64url. Each transport digest is SHA-256 of its complete uncompressed canonical document, including presentation fields and representational routing details excluded from the content address. Compression changes neither digest. In auto mode the encoder selects d only when it is strictly smaller; explicit codec selection can still force d. Both codecs can therefore produce different valid fragments for the same canonical document and digests. The uncompressed document bytes are canonical; the URL transport spelling is not unique.
MusicCID and ArrangementCID address their respective authored musical meaning. The transport digest detects every change to the transported document. None of these hashes is an author signature. A browser does not send the fragment in the HTTP request; keep it intact and do not upload it to a mutation service.
URL decoding is host-independent: it accepts a fragment alone or reads the verified fragment from any absolute URL. The browser's Copy link action normalizes the copied origin to https://sound.fish/. A loaded loop may also be rewritten to the auto-selected c or d spelling; a loaded arrangement retains its exact valid incoming fragment when copied.
The hard URL limits below are Soundfish encode/decode bounds, not cross-application sharing guarantees. Chat, email, shell, QR, and embedded-browser limits can be smaller. If a large song link is truncated, share the lossless Soundfish JSON instead. For CLI URL input, only the read-only address commands (inspect, verify, handoff, analyze, lint, render, export-json, and export-midi) accept - in the address position to read standard input.
Fixed sound release
GM program and percussion numbers select one permanent Soundfish catalog. The first runtime release renders MuseScore General 0.2.0 through SpessaSynth, including all 128 notes programs and drum pitches 35–81.
Sound-bank samples, the fixed reverb impulse response, and engine builds are runtime releases outside the document and MusicCID. Every address plays through the current fixed release, so Soundfish can improve the global rendering without changing symbolic compositions or their music addresses.
The active soundfish.sound-release/v1 identity is sha256:bf3a64a6e587acefd1091371943c65ca3230541659b5bff77de93e51cd92ad54. It binds the exact bank, worklet, renderer versions, audio graph, automation model, impulse, limiter, delay bounds, and defaults. The root document exposes the same value as data-sound-release for rollout checks. It does not enter MusicCID.
Each loop remains one bounded canonical block. Song playback resolves only the child loops embedded in its bounded arrangement block; there is no remote resolver dependency or Merkle traversal. A future storage graph must reconstruct the same loop and arrangement identity projections and cannot change MusicCID or ArrangementCID.
Compact agent text
Version S1 is a lossless, line-oriented view. Records are tab-separated and already sorted in canonical order.
S1
D <json-title> <bpm> <bars> <reverb-return-base> <delay-return-base> <delay-feedback-base> <delay-time-millibeats-base> [swing|-] [tonic|-] [mode|-] [json-genre|-]
A D <document-lane:r|d|f|t> <step> <value> <curve:h|l>
T <track-id> <track-kind:n|d> <json-name> <gm-program|kit|-> <lineage-kind:o|d> [operation-id source-count] <volume-base> <reverb-send-base> <delay-send-base> [pan-base|-] [cutoff-base|-]
S <source-track-id> <source-digest> # repeated source-count times
A T <track-lane:v|r|d|p|c> <step> <value> <curve:h|l>
E <event-id> <pitch> <startStep> <endStep> <velocity>
X
Z
Records are tab-separated. T..X repeats once per track. In the track-kind
column, n means a notes track and d means a drums track. Notes tracks require
a zero-based GM program; drums tracks carry their GS drum kit program there,
and - means kit 0. In the separate lineage-kind column, o means original and
d means derived. JSON strings use canonical JSON escaping.
Event endStep is the exclusive absolute endpoint, not a duration.
Automation curves control the segment leaving their point. h means hold and
l means linear. Track lanes are v volume, r reverb send, d delay send, p pan,
and c cutoff.
Bracketed trailing columns are optional and omitted when every later column
is also at its default: swing 0, no tonic, no mode, no genre, pan base 5000,
cutoff base 10000. A column at its default is spelled - only when a later
column is present. Modes are major, minor, dorian, mixolydian, lydian,
phrygian, aeolian, and harmonic-minor. Records, tracks, sources, automation
points, and events must already be in canonical order.D carries shared effect bases; A D carries shared effect automation. T uses n for notes and d for drums and carries track production bases. A T carries track automation. Lineage uses o for original or d followed by an operation ID and checked source records.
Compose
Compose is the hand-written authoring format. The CLI compiles it into one canonical loop, so the document, agent text, CBOR, and MusicCID are unchanged. Every position is explicit: a note is pitch@slot>length with 1-based slots inside a bar, bars are separated by |, drum rows are step strings where x is an accent, o a hit, and . a rest, and instruments use the 1-based gm:N number or a General MIDI name. Errors name the line.
# comment to the end of the line
title Night Drive # optional; the rest of the line is the title
bpm 124 # 40 to 240, default 120
bars 4 # 1 to 16; default: the longest line
key F# minor # optional tonic and mode (meta only); key C means C major
genre house # optional, at most 32 bytes (meta only)
swing 20 # 0 to 100, default 0
kit 808 # default kit for drums blocks: name or 0 to 127
fx reverb 2000 delay 2500 feedback 3500 time 500 # document effect bases
drums # or: drums 25, drums 808, drums "Lo-fi"
name Kit # optional track name (default Drums)
vol 9000 rev 500 # vol rev del pan cut, any subset, basis points
kick: x...x...x...x... # x accent 110, o hit 90, . rest
snare: ....x.......x...
hh: o.o.o.o.o.o.o.o. @70/100 # @hit or @hit/accent velocity override
ohh: ..............x.
clap: ....x.......x... | ....x.......x.x. # | separates bars; 2 bars repeat twice
bass gm:34 # 1-based General MIDI number 1 to 128 ...
vel 100 # ... or a name: bass "Fingered Bass"; vel is the default velocity
C2@1>4 C2@7>2 G1@9>4 Bb1@13>4=80 | C2@1>4 C2@7>2 F2@9>4 G2@13>2
# pitch@slot>len=vel: slot 1 to 16 within its bar, len in sixteenth steps (default 1),
# =vel overrides the velocity, | separates bars; C4 is MIDI 60; C7 is a note, Cdom7 a chord
keys "Electric Piano 1" # chords voice from octave 3: Am7 is A3+C4+E4+G4, C is C3+E3+G3
Am7@1>16 | Fmaj7@1>16 | Cmaj7@1>16 | G@1>8 Gsus4@9>8 # + stacks pitches; more lines add voicesA one-bar pattern, or any bar count that divides the loop, repeats to fill it. Chord symbols such as Am7 or Cdom7 expand from octave 3; a letter with only an octave digit is always a note. soundfish compose prints the URL and inspect --format compose prints a loop back in this form; that view keeps every semantic value but not automation points, lineage, or IDs.
Published CLI and skill
Run bunx @hraness/soundfish --help without installing, or use bun add --global @hraness/soundfish and then the installed soundfish command. The primary Soundfish skill ZIP contains one top-level soundfish/ directory and must be inspected before extraction. The legacy edit-soundfish archive is retained only for compatibility.
Full command reference
bunx @hraness/soundfish --help
bun add --global @hraness/soundfish
soundfish templates list [--kind grooves|progressions|bass|songs]
soundfish templates apply grooves/house-basic --key Am --bpm 124 [--compose]
soundfish compose loop.compose
soundfish inspect '<loop-or-song-url>' [--format agent|json|compose] [--annotate]
soundfish verify '<loop-or-song-url>'
soundfish handoff - < final.url > reply.md
soundfish handoff - --check reply.md < final.url
soundfish analyze '<loop-or-song-url>' [--format json]
soundfish lint '<loop-or-song-url>' [--stats stats.json|--render]
soundfish render --dry '<loop-url>' loop.wav [--format json]
soundfish export-json '<loop-or-song-url>' composition.soundfish.json
soundfish export-midi '<loop-or-song-url>' composition.mid
soundfish import-json composition.soundfish.json
soundfish encode document.soundfish [--strict]
soundfish fmt document.soundfish
soundfish add-track '<loop-url>' track.soundfish --operation op_name --from trk_source
soundfish replace-track '<loop-url>' trk_target track.soundfish --operation op_name --from trk_target
soundfish remove-track '<loop-url>' trk_target --operation op_name
soundfish resize '<loop-url>' 8 --operation op_name
soundfish set-tempo '<loop-url>' 124 --operation op_name
soundfish set-title '<loop-url>' 'Night drive' --operation op_name
soundfish set-effects '<loop-url>' --reverb 2500 --time 750 --operation op_name
soundfish set-document-automation '<loop-url>' delay-return --points 0:0:linear,32:4000 --operation op_name
soundfish add-event '<loop-url>' trk_bass --pitch C2 --start 0 --end 4 --velocity 100 --operation op_name
soundfish move-event '<loop-url>' trk_bass evt_id --start 8 --operation op_name
soundfish remove-event '<loop-url>' trk_bass evt_id --operation op_name
soundfish set-kit '<loop-url>' trk_drums 25 --operation op_name
soundfish set-pan '<loop-url>' trk_keys --base 3500 --operation op_name
soundfish set-cutoff '<loop-url>' trk_pad --points 0:2000:linear,63:10000 --operation op_name
soundfish set-swing '<loop-url>' 55 --operation op_name
soundfish set-meta '<loop-url>' --key Am --genre house --operation op_name
soundfish transpose '<loop-url>' trk_bass -12 --operation op_name
soundfish shift '<loop-url>' trk_hats 2 --operation op_name
soundfish humanize '<loop-url>' trk_drums --velocity 12 --seed 7 --operation op_name
soundfish duplicate-bars '<loop-url>' trk_bass 1-2 --to 3 --operation op_name
soundfish double '<loop-url>' --operation op_name
soundfish fill '<loop-url>' trk_drums --bar 4 --seed 3 --operation op_name
soundfish variation '<loop-url>' trk_drums --bars 2,4 --density -20 --seed 3 --operation op_name
soundfish accent '<loop-url>' trk_hats --pattern 100,60,80,60 --operation op_name
soundfish thin '<loop-url>' trk_keys --to-bytes 20000 --operation op_name
soundfish duck '<loop-url>' trk_bass --against trk_drums --pitch 36 --depth 3000 --release 2 --operation op_name
soundfish set-program '<loop-url>' trk_bass 'Electric Bass (finger)' --operation op_name
soundfish set-volume '<loop-url>' trk_bass 8000 --operation op_name
soundfish set-send '<loop-url>' trk_keys --reverb 1500 --delay 500 --operation op_name
soundfish rename '<loop-url>' trk_keys 'Rhodes' --operation op_name
soundfish legato '<loop-url>' trk_pad --operation op_name
soundfish import-midi input.mid [--as-song]
soundfish song build --title 'Night drive' --section 'Intro:<loop-url>x2' --section 'Drop:<loop-url>'
soundfish song sections '<song-url>'
soundfish song detach '<song-url>' 2
soundfish song apply '<song-url>' -- set-tempo 124 --operation op_name
soundfish song doctor
soundfish song import 'https://www.youtube.com/watch?v=VIDEO_ID' --output artifacts/song-imports
soundfish song recut <run-directory> --loop-bars 4
soundfish <command> --helpStandard output stays machine-composable; warnings and failures use standard error. inspect, verify, handoff, analyze, lint, export-json, and export-midi accept a loop or song URL; those commands, render, and the song verbs accept - in the address position to read one URL from standard input. compose - reads compose text, encode - and fmt - read agent text, while import-json - reads Soundfish JSON.add-track and replace-track may use - only in the track-input position; their base loop URL must be an explicit argument. Loop inspection defaults to compact agent text, --format compose prints the authoring view, and --annotate adds comment lines naming programs, kits, and drum sounds; song inspection defaults to lossless JSON. encode canonicalizes valid non-canonical agent text and reports the first changed line on standard error, --strict rejects it, and fmt prints the canonical spelling. Every command prints its own usage with --help and accepts --format json, --base-url, and --fragment-only, except that handoff requires a complete URL and rejects --fragment-only. Exit codes are 0 success, 2 usage, 3 invalid input, 4 conflict, and 5 rejected.
Save final CLI URL output directly as final.url. Run soundfish handoff - < final.url > reply.md to generate one complete verified Markdown link. Keep that line intact and add only plain prose around it; the entire reply must contain no code or HTML. Run soundfish handoff - --check reply.md < final.url before returning the checked reply verbatim. This requires one standalone Markdown link to the same complete canonical document, including title, IDs, and lineage, at the delivery base URL; compressed and uncompressed spellings may differ.
Retain both files for recovery. Regenerate a truncated link from the intact saved URL or use import-json on a lossless export, inspect it, and repeat the handoff procedure. Never guess missing fragment characters. The check covers the saved draft; later copying or delivery can still alter it.
Loop operation verbs and track transforms take the base loop URL and --operation <op_id> and print one URL; the same ID against the same base reproduces the same URL, and a changed base exits 4. Transforms such as transpose, humanize --seed, fill, variation, thin --to-bytes, and duck --against are recorded as replace-track with one-hop lineage from the transformed track. song build, song sections, song detach, and song apply build and edit #a1 addresses; song apply runs one fenced loop operation on every section with one operation ID so the roster stays compatible.
Diagnostics are read-only and advisory. analyze prints the bar count, canonical bytes used of the ceiling, events used of the budget, the MusicCID, the estimated key against the declared meta key, one chord per bar, kick-and-bass collision steps, and per track the program or kit, role, register, a per-bar density grid, empty and identical bars, production bases, and a velocity histogram; a song adds its roster and one analysis per section. lint applies the mechanical critique rubric and prints one finding per line with a stable code, severity, track, bars, and the fixing verb, always exiting 0. render --dry <url> <out.wav> renders one loop cycle in Bun through spessasynth_core and the pinned base bank as dry per-track stems, writes the pre-limiter stereo mix as a WAV whose duration equals the loop length, and prints peak, RMS, crest factor, and band-energy shares (below 120 Hz, 120 to 500 Hz, 500 Hz to 2 kHz, above 2 kHz) per track; lint --stats or lint --render turns those numbers into bass-band, sub-band-crowding, and mix-clipping findings. The render needs the repository checkout; the published CLI reports that and stops.
Operations and lineage
soundfish.operation/v1 envelopes contain an opaque op_ ID, the exact base transport digest, and one pure discriminated operation: create-document, add-track, replace-track, remove-track, move-event, add-event, remove-event, resize-document, set-kit, set-pan, set-cutoff, set-swing, set-meta, or set-document. Owned track and event IDs are derived as 8 hex characters from the operation ID and ordinal. Applying one returns applied, unchanged, conflict, or rejected. Conflict and rejection preserve the base; a result over the canonical byte ceiling is rejected as byte-budget-exceeded.
The bundled CLI constructs every operation, and records transforms as replace-track. Repeat --from <track-id> for each current source of an added or replaced track. The CLI resolves and hashes those tracks from the exact base rather than accepting agent-invented digests. Stable operation IDs make exact replay deterministic.
There is no unauthenticated hosted mutation endpoint. The CLI applies operations locally and emits a new self-contained URL. Optional authenticated account sync stores checkpoints; it is not the public protocol API.
Standard MIDI interchange
Export writes canonical Type 1 MIDI at 96 PPQ (24 ticks per Soundfish step), one conductor track, one track per Soundfish track, independent melodic channels for notes, and channel 10 drums with a program change for a non-zero kit. A non-default pan base is written as controller 10 at tick zero, and swing delays the note-on and note-off of every odd step by round(swing / 100 × 12) ticks. Soundfish metadata preserves titles, IDs, lineage, authored production, effects, automation, swing, and meta for an exact Soundfish export/import round trip.
Song export uses the same Type 1 timing projection and adds standard section-marker events. It carries the fixed tempo and meter, track names, GM programs, notes or drum hits, velocities, duration, and section labels. It does not carry complete Soundfish effects, automation, identities, lineage, or arrangement routing. Export Soundfish JSON as the lossless source and MIDI as the interoperable performance file. The browser More menu exports the whole current song even when one section is selected.
Import accepts Type 0 or Type 1 files of 1–16 bars. A channel-10 program change at tick zero becomes the drum kit, and controllers 7, 10, 91, and 93 at tick zero become the volume, pan, reverb send, and delay send bases. Tracks that end short of a bar are padded, release velocities are dropped, held drum hits are shortened to one step, and housekeeping controllers are ignored, each with a warning. import-midi --as-song builds one loop per section marker and assembles a song, falling back to one flat loop when the spans cannot form one. Tempo or meter changes, off-grid notes, other controllers, pitch bend, aftertouch, SysEx, and SMPTE timing are still rejected. Raw SMF is interchange, not a duplicated canonical storage field.
Local song import
The published command also exposes the local importer:
soundfish song doctor
soundfish song import 'https://www.youtube.com/watch?v=VIDEO_ID' --output artifacts/song-importsIt orchestrates a separately running local StemDeck service for yt-dlp, Demucs separation, beat/downbeat analysis, and optional sections, then a separately installed Basic Pitch process for pitched-stem transcription. It writes stems and analysis locally, JSON/URL/MIDI artifacts for each loop, and JSON/URL/MIDI for the complete song. Standard output remains only the final #a1URL.
Import only media you have the right to download and transform. Separation, beat detection, section analysis, drum classification, and MIDI transcription are estimates; audition and correct the generated composition. Source and stem audio never enter the Soundfish URL or JSON music address.
Browser and performance profile
The supported floor is Safari and iOS Safari 16.4+, Chrome and Edge 113+, and Firefox 113+ over HTTPS. Playback and persistence require AudioWorklet, Web Crypto SHA-256, IndexedDB, and raw-DEFLATE streams. Embedded webviews and in-app browsers are best effort until explicitly certified.
The lower-tier target is an A13-class iPhone or newer, or Android 10+ with a current browser and about 4 GB of memory. Automated validation uses a 360×800 touch viewport, DPR 3, four reported hardware threads, and Chrome DevTools Protocol CPU throttling. A calibrated mid-tier profile is preferred; 6× throttling is the reproducible blocking fallback and 20× is diagnostic only.
Browser emulation measures main-thread JavaScript and layout. It does not reproduce a mobile GPU, memory bandwidth, thermal throttling, or audio hardware, so it does not replace physical-device checks.
Hard limits
| Value | Limit |
|---|---|
| BPM | Integer 40–240 |
| Bars per loop | 1–16 |
| Tracks | 16 |
| Notes tracks | 15 |
| GM1 programs | 128 (0–127) |
| Events per track | 512 |
| Events per document | 832 |
| Loop title | Nonempty after trimming; 80 UTF-8 bytes |
| Track name | Nonempty after trimming; 48 UTF-8 bytes |
| Drum kit | 0–127 |
| Swing | 0–100 |
| Meta genre | 32 UTF-8 bytes |
| Canonical loop CBOR | 24,493 bytes (the binding limit) |
| Loop fragment | 32,768 characters |
| Absolute loop URL | 65,536 characters |
| Agent text | 524,288 UTF-8 bytes |
| Standard MIDI input | 524,288 bytes |
| Embedded arrangement loops | 128 |
| Arrangement sequence entries | 512 |
| Repeats per sequence entry | 64 |
| Expanded loop occurrences | 512 |
| Arrangement bars | 4,096 |
| Resolved arrangement events | 65,536 |
| Arrangement automation and reset points | 65,536 |
| Arrangement title | Nonempty after trimming; 160 UTF-8 bytes |
| Section label | Nonempty after trimming; 80 UTF-8 bytes |
| Canonical arrangement JSON | 392,192 bytes |
| Arrangement fragment | 524,288 characters |
| Absolute arrangement URL | 1,048,576 characters |