Skip to content

LaskTasks in pinned containers, checked before they run

Tasks are typed functions in one file. Their commands run in container images pinned by digest, the same on your laptop and in CI, and never on the host unless the file says so.

Lask in one minute, in five steps: try a command in the REPL, keep it as a task, run it, run the same thing on a laptop and in CI, and keep secrets in Vault.

A main.lask that lints and tests a Python project, with neither Python nor the linter installed:

lask
// Each program comes from a pinned image.
command { "python" } on #python:3.13.7-alpine3.22
command { "ruff" } on #ghcr.io/astral-sh/ruff:0.13.3-alpine

// Lint and test at the same time.
ci() = do {
  lint = async $ ruff check app
  test = async $ python -m unittest discover -s app
  all([lint, test])
}
bash
$ lask sync      # pull both images and pin their digests in lask.lock.json
$ lask run ci    # run both commands, each in its own container

Misspell python as pyhton on line 8, and lask check reports it before anything runs:

text
$ lask check
main.lask:8:16-8:52: E-TYPE-COMMAND-NOENV [static]: 'pyhton' is not a declared command; ...

Your first real task file builds this file step by step.

Released under the MIT License.