Skip to content

Actions

Actions are immediate Lua scripts that run against the Plinken engine. They can execute DAW commands, query session state, call external programs, and automate any task you’d otherwise do by hand.

Open the Action Editor from the Action menu, or run a script programmatically with the lua:execute command.

CommandDescription
lua:createCreate a new empty action
lua:loadLoad an action into the editor
lua:saveSave the current action
lua:executeRun the current action
lua:deleteDelete an action
lua:listList all available actions

Execute any DAW command. The call is deferred to the next frame — it queues the command and returns immediately. Use the same command IDs as Plinken’s internal command system.

-- Mute track 1
pl.cmd("track:mute", { trackId = 1 })
-- Set tempo
pl.cmd("transport:set-tempo", { tempo = 128 })
-- Solo a track
pl.cmd("track:solo", { trackId = 3 })
ParameterTypeRequiredDescription
idstringyesCommand ID (e.g. "track:mute", "transport:play")
payloadtablenoCommand-specific parameters

Use plinken.list_commands() to discover all available command IDs.


Output a message to the console panel. Useful for debugging and status updates.

pl.log("Processing complete")
pl.log("Track count: " .. tostring(trackCount))
ParameterTypeRequiredDescription
msgstringyesMessage to display

The standard Lua print function is redirected to the script output buffer. Output appears in the Action Editor’s result pane.

print("hello") -- appears in output buffer
print("a", "b", "c") -- tab-separated, as normal Lua print

Yield execution for the specified number of milliseconds. Maximum sleep time is 30 000 ms (30 seconds). Use this to wait for commands to take effect before querying state.

pl.cmd("transport:play", {})
pl.sleep(1000) -- wait 1 second
pl.cmd("transport:stop", {})
ParameterTypeRequiredDescription
msnumberyesMilliseconds to sleep (1–30 000)

Returns session context as a table. Useful for scripts that need to know which project or space they’re operating in.

local ctx = pl.get_context()
pl.log("Account: " .. ctx.account)
pl.log("Project: " .. ctx.project)
FieldTypeDescription
accountstringCurrent account ID
projectstringCurrent project name
spacestringActive space/session
teamstringTeam identifier
videostringActive video asset (if any)

Returns the current transport state. Tempo, playback status, time position, and more.

local t = pl.get_transport()
pl.log("Tempo: " .. t.tempo .. " BPM")
pl.log("Playing: " .. tostring(t.playing))
pl.log("Position: " .. t.position .. " beats")
FieldTypeDescription
temponumberCurrent tempo in BPM
playingboolWhether transport is playing
recordingboolWhether transport is recording
positionnumberPlayhead position in beats
timenumberPlayhead position in seconds
time_sig_numnumberTime signature numerator
time_sig_dennumberTime signature denominator
loop_startnumberLoop region start (beats)
loop_endnumberLoop region end (beats)
loop_enabledboolWhether loop is active

Returns a table of all registered command IDs. Use this to discover what commands are available for pl.cmd().

local cmds = plinken.list_commands()
for _, id in ipairs(cmds) do
print(id)
end

Returns: array of strings — command IDs like "track:mute", "transport:play", "mixer:set-volume".


Run an allowlisted external program. The call blocks until the program finishes and returns its stdout as a string.

-- Get duration of a media file
local info = pl.exec("ffprobe", {
"-v", "quiet",
"-print_format", "json",
"-show_format",
"assets/vocals.wav"
})
pl.log(info)
ParameterTypeRequiredDescription
programstringyesProgram name (must be allowlisted)
argstablenoArray of string arguments

Returns: string — the program’s stdout output.

The Lua sandbox restricts which programs can be executed. See the allowlist below.


Returns the list of programs that pl.exec() can call.

local progs = plinken.allowed_programs()
for _, name in ipairs(progs) do
print(name)
end

Returns: array of strings.


These programs are available to pl.exec():

ProgramCategoryDescription
ffmpegMediaVideo/audio encoding and conversion
ffprobeMediaMedia file inspection
imagemagickMediaImage processing (legacy name)
convertMediaImageMagick convert command
soxAudioAudio processing and effects
blender3DBlender headless rendering and scripting
houdini3DHoudini interactive
hython3DHoudini Python scripting
hbatch3DHoudini batch processing
unity3DUnity batch mode
resolveVideoDaVinci Resolve scripting
lilypondMusicMusic engraving / sheet music
csoundMusicAudio synthesis
sonic-piMusicLive coding music
python3GeneralPython 3 interpreter
pythonGeneralPython interpreter
nodeGeneralNode.js runtime

local t = pl.get_transport()
if t.playing then
pl.cmd("transport:stop", {})
pl.log("Stopped")
else
pl.cmd("transport:play", {})
pl.log("Playing")
end
local tracks_to_mute = { 1, 3, 5 }
for _, id in ipairs(tracks_to_mute) do
pl.cmd("track:mute", { trackId = id })
end
pl.log("Muted tracks 1, 3, 5")
local files = { "vocals.wav", "drums.wav", "bass.wav" }
for _, f in ipairs(files) do
local out = f:gsub("%.wav$", ".mp3")
pl.exec("ffmpeg", {
"-i", "assets/" .. f,
"-codec:a", "libmp3lame",
"-b:a", "320k",
"exports/" .. out
})
pl.log("Exported " .. out)
end
local info = pl.exec("ffprobe", {
"-v", "quiet",
"-print_format", "json",
"-show_streams",
"assets/final_mix.wav"
})
print(info)
-- Write a LilyPond source file, then render to PDF
pl.exec("lilypond", {
"--output=exports/score",
"assets/arrangement.ly"
})
pl.log("Score rendered to exports/score.pdf")
-- Print a full session summary
local ctx = pl.get_context()
local transport = pl.get_transport()
pl.log("=== Session Report ===")
pl.log("Project: " .. ctx.project)
pl.log("Space: " .. ctx.space)
pl.log("Tempo: " .. transport.tempo .. " BPM")
pl.log("Time Sig: " .. transport.time_sig_num .. "/" .. transport.time_sig_den)
pl.log("Position: " .. string.format("%.2f", transport.time) .. "s")
pl.log("Playing: " .. tostring(transport.playing))
pl.log("Loop: " .. tostring(transport.loop_enabled))
local cmds = plinken.list_commands()
pl.log("Commands: " .. #cmds .. " registered")
local progs = plinken.allowed_programs()
pl.log("Programs: " .. #progs .. " available")
pl.log("======================")