From a sequence to a workflow: let `.lil` make decisions
A linear script is perfect while the answer is always “do A, then B, then C”. The moment you need to ask whether a directory exists, reuse a path, capture a result or stop with a meaningful reason, you are writing a workflow rather than a list.
Use the smallest automation language that fits the job
A file that begins with #lil belongs to the Core linear runner: ordinary commands execute in order, and that simplicity is a feature. It is ideal for setup lists, repeatable diagnostics and short procedures.
install runhelp runVariables turn copied paths into named intent
set root lil-playground gives a path a role. Later $root, $source and $archive say what the values mean instead of forcing you to edit the same literal in five places.
Good variable names make a script portable. Keep environment-specific values near the top, keep secrets out, and prefer a few clear variables over clever string construction.
set root lil-playground
set source lil-playground/project
set archive lil-playground/project.zipA condition should protect an assumption
if dir "$source" is not decoration: it prevents the archive step from silently operating on the wrong target. Conditions are most valuable around assumptions that would otherwise become destructive or confusing failures.
exists, file, empty, eq, ne, ok, fail and command, with not for inversion. Keep branches short enough that a reader can still understand why each path exists.
if dir "$source"
stat "$source"
else
stop "Project directory is missing"
endCapture output when the next decision depends on it
capture name <command> executes an ordinary lil command and stores its plain result in a variable. Built-ins such as $last, $status, $cwd and $line expose common execution state.
Do not capture everything just because you can. Captured terminal text is useful when it is small and stable; structured files or dedicated format commands are better when data needs to survive across tools or over time.
capture current pwd -s
if empty "$current"
stop "Current directory is unavailable"
endDecide what failure means before you automate
The default stop lets the script fail with a reason that makes sense to a human.
Run unfamiliar workflows with -n first. Dry-run validates and expands commands without executing them; -v then shows complete output during a real run. Preview is not bureaucracy — it is how automation stays understandable.
run workflow.lil -nrun workflow.lil -vSplit large workflows by responsibility, not by line count
A workflow can
.lil is not encryption: it protects format and integrity against accidental edits, not confidentiality or authorship.
run -p workflow.lil workflow.packed.lilrun workflow.packed.lilAutomation intentionally has fewer privileges than an interactive human
Interactive UI commands are blocked in ordinary workflows, and privileged non-interactive commands such as @command auto-install convenience is also rejected inside
That friction is deliberate. A reproducible workflow should declare its module dependencies before execution and should not unexpectedly install code, prompt for secrets or destroy the terminal halfway through a run.
Keep this as a script
Save this as workflow.lil, create a lil-playground/project directory if you want the success path, and run it first with
set root lil-playground
set source lil-playground/project
set archive lil-playground/project.zip
if not dir "$root"
stop "lil-playground is missing"
end
if dir "$source"
capture current pwd -s
zip "$source" "$archive" -f
stat "$archive"
else
stop "Project directory is missing"
end