Your first script¶
Skip the code?
If you only need a script that maps your controller to Live (volume, mute, transport, device knobs…), the Script Generator builds and downloads one for you. This page teaches you the Python path — the foundation everything else on this site is built on.
This page takes you from nothing to a Remote Script that Live actually loads, in the smallest number of steps. It assumes you have read the Architecture overview , if not, read that first, it is the mental model everything here relies on.
The goal here is deliberately tiny: a script that loads, prints to the log, and shows a message in Live's status bar. No controls yet. Once this works, you have a foundation you can trust, and adding controls (see From idea to script) is just more of the same.
Where scripts live¶
Live looks for Remote Scripts in two places. Always use the User Library, it survives Live updates and keeps your work separate from the factory scripts.
macOS ~/Music/Ableton/User Library/Remote Scripts/
Windows \Users\<you>\Documents\Ableton\User Library\Remote Scripts\
The factory scripts (the ones documented in the API Reference) sit elsewhere, inside the application bundle, and you should treat them as read-only reading material, useful to learn from, not to edit:
macOS /Applications/Ableton Live <N>.app/Contents/App-Resources/MIDI Remote Scripts/
Windows \ProgramData\Ableton\Live <N>\Resources\MIDI Remote Scripts\
The folder and its files¶
A script is a Python package: a folder whose name is what Live shows in the Control
Surface dropdown. Create this under your User Library Remote Scripts/:
The folder name (MyFirstScript) is the name you will pick in Live. Avoid spaces. The one
required entry point is a function called create_instance in __init__.py, Live imports
the package and calls it once, handing you a c_instance handle to its C++ side.
Put this in __init__.py:
from __future__ import absolute_import, unicode_literals
from _Framework.ControlSurface import ControlSurface
class MyFirstScript(ControlSurface):
def __init__(self, c_instance):
super(MyFirstScript, self).__init__(c_instance)
self.show_message('MyFirstScript loaded!')
self.log_message('MyFirstScript: hello from the embedded interpreter')
def create_instance(c_instance):
return MyFirstScript(c_instance)
That is a complete, valid Remote Script. show_message writes to Live's status bar (bottom
of the window); log_message writes to Log.txt. Both come from ControlSurface.
Activating it in Live¶
- Restart Live (it scans the Remote Scripts folders at startup, a new folder is only discovered on launch).
- Open Preferences → Link, Tempo & MIDI (called Link/MIDI in older versions).
- In a free Control Surface row, open the dropdown,
MyFirstScriptshould be listed. Select it. - Leave Input and Output as needed (none required for this no-control example).
If the script loaded, you will see MyFirstScript loaded! flash in the status bar.
Log.txt is your lifeline¶
The status bar shows almost nothing useful when things go wrong; Log.txt shows everything,
including the full Python traceback when your script raises. Keep it open in a tail.
macOS ~/Library/Preferences/Ableton/Live <N>/Log.txt
Windows \Users\<you>\AppData\Roaming\Ableton\Live <N>\Preferences\Log.txt
Watch it live while you work:
A successful load shows your log_message line. A broken script shows a traceback with the
file and line, that is where you debug. If the script does not appear in the dropdown at
all, the cause is almost always one of: wrong folder location, a folder name with a space, or
a syntax error that prevented the package from importing (the traceback will be in Log.txt).
The edit → reload loop¶
There is no hot reload. Live imports your script once at startup and caches the compiled bytecode. After every change to the source:
- Save the file.
- In Live, set the Control Surface row to None, then back to your script, this is often enough to re-instantiate.
- If behaviour still looks stale (especially after changing imports or adding files), restart Live. This always clears the cache.
A practical rhythm: keep Log.txt tailing in one window, your editor in another, and Live's
Preferences open on the MIDI tab so the None ↔ script toggle is one click away.
Framework generation
This skeleton uses _Framework (the v2 base class), which loads in Live 9, 10 and 11
and still loads in Live 12. Live 12's own factory scripts are written against
ableton.v3.control_surface, which has a different setup style, see
v2 vs v3 framework. For learning and for the broadest compatibility, start
with _Framework as shown here. Always confirm class and method names against the
API Reference for the Live version you target.
Next¶
You have a script that loads. Now give it controls: From idea to script builds a real, useful control surface step by step, eight encoders on the selected device plus transport, using exactly this skeleton as its starting point.