About ucmix
ucmix is a command-line tool for reading and changing parameters on PreSonus StudioLive Series III mixers over UCNET. It provides direct parameter access alongside commands for configuration, scenes, projects, and mixer profiles.
Key features
- 01Read and write mixer parameters
- 02Batch parameter updates
- 03Dump and apply configurations
- 04Manage scenes and scope filters
- 05Discover mixers and save profiles
Use cases
- 01Adjust channel and monitor-mix settings
- 02Back up or apply mixer configurations
- 03Store and recall mixer scenes
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ steveclarke/ ucmix --skill ucmixAfter installing, type/ucmixin Claude Code to confirm it loaded.
Bundled filesreference/paths.md
Details
From the project READMEucmix — StudioLive mixer control
ucmix reads and writes any parameter on a PreSonus StudioLive Series III mixer
over the mixer's own network protocol (UCNET). No PreSonus software is required
or involved — it talks straight to the mixer's control port.
First checks
command -v ucmix
ucmix --version
ucmix profile ls # is a mixer saved?
If ucmix is missing, install it:
brew install steveclarke/tap/ucmix
If no mixer is configured, find and save one (mixers announce themselves on the LAN):
ucmix discover # list mixers on the network
ucmix setup # interactive: pick one, name it, save it as the current profile
# or, if you already know the address:
ucmix profile add foh --host 192.168.1.50 --use
Every command then uses the current profile. Override per-command with -p <name>
or --host <ip>.
The model — two verbs over one namespace
The mixer is one flat namespace of ~20,000 parameters, each a path → value:
line/ch1/username = "Drums" # channel 1 name
line/ch1/48v = true # phantom power
line/ch1/volume = -6 # fader, dB
aux/ch1/limit/threshold = -6 # monitor-mix limiter, dB
fx/ch1/plugin/reflection = 0.79 # a reverb knob (raw)
Everything the mixer can do is one of those paths. Two verbs cover all of it:
ucmix get <path>— read one valueucmix set <path> <value>— write one value; alsoset p1=v1 p2=v2 …orset -f <file>(apath valueper line) to write many over one connection
Read reference/paths.md for the path grammar (groups, channel indexing, and the
value form for each parameter family). To see the exact live paths on a specific
board, run ucmix dump (all) or ucmix dump <prefix> (filtered).
Humanized vs raw values
Common controls accept human values and the tool converts to the wire form:
| Path family | You write | Not the raw wire value |
|---|---|---|
.../48v, .../mute, .../*on*, .../link | on / off | (bool) |
.../volume, .../aux{n}, .../FXA..FXH, .../limit/threshold | dB, e.g. -6dB | |
.../limit/release | ms, e.g. 400 | |
.../username | a string, e.g. "Vox Steve" | |
.../color | hex, e.g. 4ed2ff | reads back as 8 lowercase RGBA digits (4ed2ffff) |
.../iconid | an icon id, e.g. vocals/leadvocals | |
.../adc_src (input patch) | the input number, e.g. 5 |
Every other path has no humanizing layer — you pass the raw wire value the
mixer expects, usually a float in 0..1 (e.g. fx/ch1/plugin/lpf 0.869), an
integer index, or an enum number. get <path> returns the raw value; get <path> --raw forces raw even on humanized paths. When reproducing a captured setting,
read its raw value and write that same raw value back.
Commands
Run ucmix <command> --help for flags; the CLI evolves, so verify against --help
rather than trusting this list to be complete.
get <path>/set <path> <value>— read / write one parameterset p1=v1 p2=v2 …/set -f <file>— write many parameters over one connectionchannel <n> <verb> <value>/mix <name|n> <verb> <value>/send <ch> <mix> <dB>— human shortcuts oversetfor the common channel-strip, monitor-mix, and send actions (a thin veneer; the rawsetpath model still covers everything). Built for humans at a keyboard — an agent should keep using rawget/setbelow.dump [prefix]— read every path (or those under a prefix);--as-configemits YAMLverify <config.yml>/apply <config.yml>— board as code: diff / write a whole configstore <project> <name>— store the current state as a new scene (--replaceto overwrite one);recall <project> <scene>— load a stored scene;rename <project> <scene> <new-name>— retitle one;delete <project> <scene>— remove one (destructive; needs--yesor a prompt). Project and scene arguments accept either the display title ("135 Main Live","Opening") or the board's slot name ("03.135 Main Live.proj","04.Opening.scn")reset— factory reset (destructive; needs--yes)ls projects— list projects on the board;ls scenes <project>— list a project's scenes.<project>is a name fromls projects(e.g.01.Sevenview Live.proj). Both take--json.project ls— list projects with their titles, marking the one the board has loadedfilters ls [scene|advanced|project]/filters set <group> <tile> <on|off>— the scope filters that decide what a store, recall or reset touchesdiscover/setup/profile/config— find/save/manage mixer connections
Agent rules
- Use
--jsonfor any command whose output you will parse;--no-colorfor plain text. - Verify writes with a fresh
get.setreports that it sent the value, not that the board is now in that state. Read it back to confirm. - Prefer humanized values (
-6dB,on, an input number) where a path family supports them; fall back to raw0..1wire values for everything else. - To copy a setting from one board/state to another,
get <path> --rawthenset <path> <that raw value>— raw round-trips exactly. - Write many parameters in one call —
set p1=v1 p2=v2 …orset -f <file>— rather than loopingset. A batch reuses one connection and commits once; separatesetprocesses reconnect per write and can drop writes under rapid reconnect. resetandapply --resetare destructive — only with--yesand a clear target.- Never assume a path exists; confirm with
dump <prefix>orgeton a real board.
Scenes — store, recall, rename
store allocates the next free scene slot itself, the same way UC Surface does, and
refuses to overwrite an existing scene of that name unless given --replace. A project
holds 20 scene slots; ErrNoFreeSlot means they are all taken (delete one in UC Surface).
store and recall wait for the board to confirm the operation and fail if it never
does — a store that reports success really is on disk. This matters because the
underlying request is fire-and-forget: earlier versions printed success as soon as the bytes
were sent, and a scene the board dropped looked saved. If store errors, treat the scene as
NOT stored.
Because they wait on the board, both take a few seconds. That is the board committing to flash, not a hang.
ucmix store "135 Main Live" "Opening" # new scene, next free slot
ucmix store "135 Main Live" "Opening" --replace # overwrite it deliberately
ucmix rename "135 Main Live" "Opening" "Opening Set" # retitle, keeps its slot
ucmix recall "135 Main Live" "Opening Set"
ucmix delete "135 Main Live" "Opening Set" --yes # destructive, frees the slot
delete frees the scene's slot, which the next store reuses. Like store and recall
it waits for the board to confirm. It prompts before acting; --yes skips the prompt and
is required when there is no terminal.
The project layer and scope filters
A project is the setup a scene sits on: input source and patching, AVB/SD/USB routing,
flex mode, GEQ, solo. Scenes live inside a project. project ls lists the projects and marks
the loaded one. Storing or recalling a project as a unit is not implemented — the request
UC Surface sends for it has not been captured (issue #6), and project store / project recall fail with that explanation rather than guessing at the format.
The scope filters are the blue tiles that decide what a store, recall or reset actually
touches. Each tile is an ordinary parameter, so it reads through get/dump and writes
through set; filters is the named surface over them.
ucmix filters ls # every tile in every group, with its state
ucmix filters ls scene --json # one group, machine-readable
ucmix filters set scene 48v on # include phantom power in a store/recall
ucmix filters set project inputpatching off
Groups: scene (Scene Filter, global/fltr*), advanced (Advanced Scene Filter,
advancedscenefilters/*), project (Project Filter, projectfilters/*). Tile names are the
board's own key names, so a tile names the parameter it writes; - and _ are
interchangeable. filters set reads the tile back on a fresh connection and reports what the
board holds, the same as set and the noun verbs.
A board ships with the scene filter's 48v tile excluded, which is why recalling a scene
leaves phantom power as it is. Changing a filter changes what every later store and recall
carries — it is a global setting, not a per-command flag.
Known limitations
ls projects/ls sceneslist the board's presets over the FR/FD file-request protocol (the same one UC Surface uses). A board that never answers fails with a clear timeout and hint instead of hanging. Empty slots and the project config file are dropped from the output; only occupied projects/scenes are shown.applywrites over one connection with a library commit barrier and verifies on a fresh connection (a freshget).set -f <file>is the same batch write path without the verify.renameis confirmed by re-listing the project, not by a board acknowledgment (the board sends none for a rename).store,recall, anddeleteall wait on a real one.resetis still unconfirmed fire-and-forget — it reports that the request was sent, not that the board acted on it.- Scope-filter reads are hardware-confirmed on a 32R (firmware 3.4.0), and the write path was confirmed by flipping one tile and reading it back. A project store/recall has no captured request and is not implemented.
- The high-pass filter is calibrated: Hz over the board's 24 Hz – 1 kHz sweep,
logarithmic,
0= off. The limiter release curve and reverb-type enums are not — their humanized conversions are approximate. Use raw values when exactness matters. - Some UCNET parameters have no control in UC Surface (e.g. an FX return's Main/LR
assign,
fxreturn/chN/lr). Writing one leaves the board in a state the operator cannot see or undo from the console. Prefer a change that maps to a visible UC Surface control (e.g. pull the FX return fader down for a dry main, not an LR unassign), and when a write has no UI equivalent, say so.