Differences from After Effects
Where Nubu Motion scripting deliberately departs from After Effects expressions, and the trouble each departure removes.
If you arrive with After Effects expressions in your fingers, most of your instincts transfer: value, time, thisComp, thisLayer, wiggle, linear, clamp and seedRandom all mean what you expect, and each member's reference page notes its AE equivalent where one exists. The differences below are deliberate, and each one removes a class of AE trouble. If you have never used After Effects, skip this page happily - the rest of the documentation assumes nothing.
References travel by id, not by name
AE looks layers up by name and silently takes the first match - rename a layer, or add a second with the same name, and expressions break or change meaning. Here every layer, comp, property and control has a stable id, and references store the id. The editor still lets you TYPE and READ names (completions offer them, applied scripts display them), but what is stored can never be broken by a rename. See References and ids.
Scripts, not per-property expression slots
There is no option-click on a stopwatch and no expression box per property. Scripts are the one surface: each declares the properties it drives in outputs, and one script may drive many properties across many comps. A driven property row shows a small indicator naming its script; the row's own controls still edit the BASE value the script reads through value.
Zero-based counting, bottom-first layers
Indices start at 0 everywhere, like the rest of JavaScript. layer.index 0 is the BOTTOM layer of the stack, not the top - the same order every array in the document uses. AE's 1-based, top-first thisComp.layer(1) has no counterpart to trip over.
The frame grid is canonical
Frames are integers on the comp's exact rational frame rate, and frame is the canonical clock; time in seconds is derived from it. AE's floating seconds accumulate rounding error over long comps; here the grid cannot drift. timeToFrames and framesToTime convert between the two spellings.
return is required
A single-output script produces its value with an explicit return. AE's habit of leaving a trailing expression as the implicit result does not parse as a rule here - the IDE offers the fix when it sees the pattern.
Scripts can remember
state() gives a script a store that survives from frame to frame, folded deterministically from the first frame so scrubbing equals playing. memo() caches expensive one-off computation per document revision. AE expressions are stateless by design; simulations that were impossible there (bounces, trails, counters) are a few lines here. See State and time.
Errors are typed and harmless
A failing script never crashes the editor or the render. It reports one of fifteen typed error codes on its status, its outputs fall back to their base values for that frame, and the next frame evaluates afresh. Infinite loops are stopped by a poll budget and presented as a fixable budget issue.
What does not exist here
No 3D, cameras or lights - the engine has no such features yet. No sampleImage. No Intl or Temporal (see JavaScript support). The old AE instinct that only some properties take expressions has no counterpart either: scripts write every ANIMATABLE property in the drive set - transforms, paint, text content, effects, physics forces, text animators and the per-layer audio level alike - and only the command-changed statics sit outside it.