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.
  • .lil single-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 generated Lilac::Bindings::<Class>#bind_template_hook takes precedence over the runtime scanner, so there's no double-binding when both paths coexist on the same page. Set codegen: :off to validate the runtime path against the same .lil source.
  • 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.