Rootless

Automate iOS, iPadOS, and macOS using plain JavaScript. Build custom widgets and interact directly with native APIs.

Download on the App Store
Rootless app interface

Plain JavaScript

Supports ES6. Scripts are stored as plain .js files on your disk.

Native APIs & Documentation

Integrate directly with iOS native APIs. Fully documented, available offline.

Siri Shortcuts

Trigger scripts via Siri. Present tables, websites, and custom HTML natively.

System Integration

Run from the Share Sheet, process inputs, and manage local files via Files.app.

x-callback-url

Communicate seamlessly and trigger workflows with other apps on your device.

Customizable & Ready

Tailor the code editor to your liking. Includes several example scripts to start immediately.

Documentation

Also inside the app, or as rootless.json.

Animation

Animation curves

Every curve takes an optional { duration }; spring also takes { bounce }. Two seconds is a hard ceiling in a widget and the system cuts anything longer off part-way. Longer durations are clamped and a warning appears in the console.

Methods

.delay(seconds)Animation ›

Waits before starting. Counts against the same two-second ceiling.

  • seconds Duration required

    A Duration, or a plain number of seconds.

.speed(multiplier)Animation ›

Scales the duration. 2 runs it twice as fast.

  • multiplier Number required

    Above 1 is faster, below 1 is slower.

.repeatCount(count)Animation ›

Repeats. The two-second ceiling still applies to the whole thing, so a large count will be cut off.

  • count Number required

    How many times.

Animation.default(options?)Animation ›

The system's standard curve.

  • options Any
    • duration Duration

      How long it runs. Clamped to two seconds, the widget ceiling.

Animation.linear(options?)Animation ›

Constant speed throughout.

  • options Any
    • duration Duration

      How long it runs. Clamped to two seconds, the widget ceiling.

Animation.easeIn(options?)Animation ›

Starts slow, ends at full speed.

  • options Any
    • duration Duration

      How long it runs. Clamped to two seconds, the widget ceiling.

Animation.easeOut(options?)Animation ›

Starts at full speed, ends slow.

  • options Any
    • duration Duration

      How long it runs. Clamped to two seconds, the widget ceiling.

Animation.easeInOut(options?)Animation ›

Slow at both ends.

  • options Any
    • duration Duration

      How long it runs. Clamped to two seconds, the widget ceiling.

Animation.bouncy(options?)Animation ›

A spring that overshoots.

  • options Any
    • duration Duration

      How long it runs. Clamped to two seconds, the widget ceiling.

Animation.smooth(options?)Animation ›

A spring with no overshoot.

  • options Any
    • duration Duration

      How long it runs. Clamped to two seconds, the widget ceiling.

Animation.snappy(options?)Animation ›

A spring with a little overshoot.

  • options Any
    • duration Duration

      How long it runs. Clamped to two seconds, the widget ceiling.

Animation.spring(options?)Animation ›

A spring you tune yourself.

  • options Any
    • duration Duration

      How long it runs. Clamped to two seconds.

    • bounce Number

      0 is no overshoot, 1 is very springy. Default 0.

Animation.none()Animation ›

No animation: the update simply appears.

Examples

Curves

Animation.spring({ duration: 0.3, bounce: 0.2 })
Animation.easeInOut({ duration: 0.4 }).delay(0.1)
Animation.linear({ duration: 1 }).speed(2)
Animation.none()                       // no animation at all