Mora Studio

Code, feedback, and the running system in one place.

Mora Studio is a native Common Lisp livecoding environment. Structural editing and contextual documentation help keep short forms readable. Inline views reveal the pattern, controls let you perform a value or write it into the score, and the inspector exposes the objects that evaluation created.

Native Studio is a native application. The language does not require it: the pattern system and runtime work from an SBCL listener without OpenGL. To hear pattern forms without installing anything, try the Play page.

Native, and optional

Studio combines a Common Lisp listener, structural source editing, source-linked pattern feedback, interactive controls, and an OpenGL canvas. The editor and the running language share the same Lisp image: a pattern, transform, visual operator, or application object can be inspected and redefined while the session continues.

Evaluation runs on a worker rather than inside the frame renderer, and session changes are marshaled onto the session thread. With Studio and SuperDirt configured, this form installs a repeating sound pattern; evaluating it again after an edit replaces that channel's pattern, and the second form stops it:

Common Lisp
(d1! (s "bd ~ sn [hh hh]"))

(d1! (silence))

Sample names refer to sounds loaded in the connected SuperDirt library.

Editing structure, not only text

The editor supports Lisp-aware indentation, matching parentheses, syntax highlighting, structural navigation and paredit operations, selection, clipboard use, multiple cursors, undo and redo, files, and a REPL.

Source-linked feedback includes evaluation flashes, playing-token highlights, channel annotations, and pattern views. Each annotation is linked to the source occurrence of the installed pattern, not found by searching for matching text, so editing unrelated source leaves a playing annotation in place. Custom language extensions get the same precise attribution by taking part in Mora's provenance protocol.

Documentation where you type

Completion
Name completion uses the live Lisp environment, with Mora-specific ranking.
Ghost hints
The remaining arguments appear after an operator name as you type.
Signature snippets
An operator expands into editable argument positions. Tab advances and exits after the last one; Shift+Tab moves back.
Keyword popup
Known parameters are offered inside the current call.
Contextual documentation
Distinguishes an operator's callable signature, a bound variable's current value, and a keyword's parameter role. Examples are shown as Lisp forms, not flattened prose.
Your own definitions
User functions participate through ordinary docstrings and signature registration. Document a custom parameter's unit and effect, since discoverability alone does not explain it.

Studio is also a listener: documentation, macro expansion, object inspection, references, disassembly, thread inspection, and definition navigation work against the running image. Comma commands give quick access to it. They are Studio commands, not Lisp forms for a score file.

Studio comma commands
,help
,describe notes
,sig piano-roll
,apropos pattern
,channels
,settings
,theme

Perform a value, or write it into the score

Controls are retained named values, not decorative images. A knob or slider can be changed by the mouse, by code, or by a MIDI mapping, and re-evaluating an unchanged declaration does not reset its performed value. This phrase places controls at their use sites:

Common Lisp
(d1! (>> (notes "f3 ab3 c4 eb4")
         (s "psin")
         (lpf (knob :cutoff 6000
                    :min 200
                    :max 16000
                    :curve :log
                    :unit :hz))
         (gain (slider :level 1
                       :min 0
                       :max 1.5
                       :step .01))))

The modifier you hold decides whether a gesture is a live performance, an authored change, or both:

Gestures on a knob or slider
Gesture Live value Source text Evaluation
Plain drag Changes during the drag Unchanged No form re-evaluation
Option-drag Unchanged Changes No automatic evaluation
Command-drag Kept until release Changes Associated form executes once on release
Control-drag Changes during the drag Changes Write-through control update
Shift with a drag Finer movement Follows the chosen mode Follows the chosen mode
Double-click Resets to the declaration's reset value Follows the chosen mode Follows the chosen mode

Source replacement is limited to the control's tracked value expression. Code can set and read the same named value, and midi-map and midi-learn connect controls to incoming MIDI:

Common Lisp
(set-control :level .8)
(get-control :cutoff)

See the score, measure the sound

Pattern views query temporal events. Signal views analyze measured audio. A piano roll cannot prove that an external synthesizer is audible, and an input waveform is not the same thing as the events that generated it.

piano-roll keeps the note grid still and moves the playhead; punch-card moves notes beneath a fixed playhead. Both allocate rows only for the pitches or sample identities actually present. Plain painting edits source, and Cmd painting evaluates the associated form once on release.

Common Lisp
(d1! (>> (notes "f3 ab3 c4 eb4")
         (s "psin")
         (piano-roll :cycles 2
                     :grid 16
                     :note-length 1/8
                     :labels t)
         (punch-card :cycles 2
                     :grid 8
                     :labels t)))

scope, frequency-scope, and spectrum read measured signal taps and need a configured, non-stale return signal. Silence is not replaced with an invented waveform.

The running image is the environment

Functions, classes, and methods can be defined while working, and ordinary Lisp variables and functions hold reusable musical and visual material instead of a separate configuration language. The inspector exposes the objects that evaluation created.

SLYNK and a local MCP server provide separate development interfaces. The MCP server exposes inspection and structured session operations; unrestricted Lisp evaluation through it is disabled by default and must be explicitly enabled. Both listen only on the local machine.

Studio's code reload (Cmd+Shift+R) is guarded: it recompiles while the window keeps running, and rebuilds native graphics resources afterwards.

On stage

  1. Development panes Console, inspector, REPL, and other panes. Zen hides them.
  2. Editor Your code, with source-linked highlights and inline views. Background intensity can fade around editing to keep it legible.
  3. Visual canvas Shader operators and ordered :post chains in the native OpenGL renderer.
Schematic, not a screenshot. In a performance layout the code sits over the visual canvas; the development layout also exposes the panes. F11 toggles zen and F10 toggles borderless fullscreen, independently.

Fullscreen changes the window's presentation on the display; zen changes which panes are visible. Studio also supports other window sizes rather than baking the renderer into one resolution. code samples the editor's texture into the visual pipeline, without capturing an unrelated application's screen.

In the editor, including zen, Shift+Return at a stem or part selector requests PHALAR recommendations from the audible mix and lists up to five ranked choices under the form. The inspector's Samples tab (F6) adds original names, tags, waveforms, and explicit preview; showing it leaves zen.

Errors have a compact summary banner and a console history. The transient performance display is separate from an explicitly entered debugger and restart workflow.

Keybindings

Bindings are shown with macOS modifiers. Focus-specific bindings override the global map, and Cmd+/ shows the installed map inside Studio.

Practical Studio keybindings
ActionBinding
Evaluate current form Cmd+Return
Evaluate buffer Cmd+Shift+Return
Evaluate selection Cmd+Shift+E
Toggle comments on the selected lines Cmd+; or Ctrl+;
Show keybinding help Cmd+/ or Cmd+Shift+/
Open Sample Explorer (modal) Cmd+P
Switch the inspector pane between Inspector and Samples F6
Show and focus Samples Cmd+Option+P
Open file picker Cmd+O
Search Cmd+F or Ctrl+S
Next search match Cmd+G or Ctrl+G
Previous search match Cmd+Shift+G or Ctrl+Shift+G
Guarded code reload Cmd+Shift+R
Toggle canvas Cmd+B
Toggle ghost hints Ctrl+Option+G
Toggle keyword dropdowns Cmd+Option+; or Ctrl+Option+;
Borderless desktop fullscreen F10
Zen / performance layout F11

In the editor, Cmd+Shift+G means previous search match; use Ctrl+Option+G for the ghost-hint toggle there. Cmd+Option+G is the separate go-to-line binding. After Shift+Return at a stem or part selector, Ctrl+Shift+N and Ctrl+Shift+P move between ranked recommendations, and Option+Shift+Return writes the chosen one into the code without evaluating it.

Requirements

Graphics
OpenGL 4.1 core and GLSL 410.
Native libraries
GLFW and libffi, plus FreeType for native font rendering.
Lisp
SBCL, with dependencies managed through Qlot.
Services
The launcher connects to SuperDirt and starts optional services such as Link, MIDI, SLYNK, and the MCP server when they are configured.

Search the documentation

Results update as you type. Use the up and down arrow keys to choose a result and Enter to open it.