lilac-cli
Optional build tool for Lilac single-file components (.lil) —
template + Ruby script in one file, compiled to static HTML for the
Lilac component runtime on mruby-wasm.
The runtime is the canonical interpreter of data-* directives, so
Lilac apps can be shipped as plain HTML without this CLI (see the
repo-root README's Quick start). What lilac-cli adds on top:
- Static lint for directive grammar / undeclared signals / dead methods, caught at build time with source positions.
.lilsingle-file component format + project structure (components/+pages/) and<div data-use="..."></div>placeholders.- Pre-compiled bindings (
codegen: :auto, default) — directive interpretation moves from mount time to build time; the generatedLilac::Bindings::<Class>#bind_template_hooktakes precedence over the runtime scanner, so there's no double-binding when both paths coexist on the same page. Setcodegen: :offto validate the runtime path against the same.lilsource. - Dev server with live reload,
scaffold,doctor.
[!WARNING] Pre-alpha. API and CLI surface will change.
Status
| Phase | Status |
|---|---|
1. .lil parser + lilac build (static output) |
✅ |
2. lilac dev (file watch via listen) |
✅ |
3. SSE live reload (via Wsv::Response.sse) |
✅ |
4. lilac new scaffold |
✅ |
5. lilac doctor setup verifier |
✅ |
6. lilac.config.rb project config |
✅ |
What is a .lil file?
A single-file component containing markup, optional sub-templates, and a
Ruby script that defines a Lilac::Component subclass:
<!-- components/counter.lil -->
<template>
<div data-component="counter">
<button data-ref="inc">+</button>
<span data-ref="count">0</span>
</div>
</template>
<!-- Sub-templates use `data-template="..."` — same convention the
Lilac runtime uses for `bind_list` clone-targets. -->
<template data-template="counter-banner">
<div class="banner"></div>
</template>
<script type="text/ruby">
class Counter < Lilac::Component
def setup
@count = signal(0)
refs.inc.on(:click) { @count.update(&:succ) }
bind refs.count, text: @count
end
end
</script>
.lil is HTML5-valid (use a .lil → text/html association in your
editor for syntax highlighting). The build tool extracts the top-level
<template> and <script type="text/ruby"> blocks; everything inside
each block is preserved verbatim.
lilac build reads components/*.lil + pages/*.html, inlines the
referenced component templates and scripts into each page, and writes the
result to dist/.
The kebab-to-CamelCase autoregister feature in Lilac means
<div data-component="counter"></div> resolves to the Counter class with
no Lilac.register call needed.
Installation
gem install lilac-cli
Or in a Gemfile:
group :development do
gem "lilac-cli"
end
Requires Ruby 3.2 or later.
Usage
lilac new my-app # scaffold a fresh project (Counter sample inside)
cd my-app && bundle install
lilac doctor # check project setup (runtime, component refs, paths)
lilac build # produce dist/ (default --target compiled — requires mrbc)
lilac build --target full # opt out: ship runtime parser in dist (mrbc-free)
lilac build --output _site
lilac dev # build + serve + live reload at http://127.0.0.1:5173
# (default --target full so no mrbc needed for iteration)
lilac dev --port 8000 # bind to a different port
lilac preview # serve the built dist/ at http://127.0.0.1:4173
# (no watch / no reload — use to verify production output)
Configuration
Project-wide defaults can live in lilac.config.rb at the project
root (a commented template is generated by lilac new):
Lilac::CLI.configure do |c|
c.components_dir = "src/components"
c.pages_dir = "src/pages"
c.dev_port = 3000
# c.codegen = :off # skip bind_template_hook codegen and let
# the runtime scanner interpret directives
# at mount time (parity-testing or
# runtime-only deployment).
end
Precedence (lowest to highest): built-in defaults → lilac.config.rb
→ CLI flags (--components, --port, etc.).
lilac dev watches components/**/*.lil and pages/**/*.html for
changes, rebuilds on save, and pushes a reload event over SSE to every
connected browser tab.
License
MIT. See LICENSE.txt.