[RFC] crinit: Pluggable filesystem-driven template engine for Crystal (upstream crystal init evolution)

Hi everyone,

Currently, crystal init app and crystal init lib generate hardcoded skeletons embedded in compiler macros. While fine for getting started, real-world projects invariably require customized scaffolding: domain-segregated layouts, alternative licenses (GPL, Apache, BSD), container recipes, systemd unit files, CI/CD matrices, and static analysis setups (Ameba, Flaw).

To address this, we developed crinit as a prototype and working implementation for an upstream RFC to evolve crystal init into a pluggable, filesystem-driven scaffolding engine.

Core Mechanics

  1. Filesystem Tree Mirroring with Macro Safety:
    • A template is simply a directory containing files, directories, and an optional template.yml manifest.
    • Template tokens use double curly braces ({{name}}, {{module_name}}, {{author}}, {{year}}, {{crystal_version}}).
    • Standard Crystal macros ({% ... %}, {{ ... }}) inside generated source code pass through untouched without escaping.
  2. Resolution Hierarchy:
    Templates resolve deterministically with zero configuration:
    • CLI flag: --template <path>
    • Environment: $CRYSTAL_TEMPLATE_PATH
    • Workspace: ./.crystal/templates/<name>
    • User directory: $XDG_DATA_HOME/crystal/templates/<name> (Linux/BSD) or OS equivalent
    • System directory: /usr/share/crystal/templates/<name>
    • Built-in fallback: Embedded app and lib skeletons (100% backward-compatible)
  3. Remote Assets with Offline Fallback (ADR-004):
    Templates can declare static external assets (e.g. CSS/JS libraries or licenses) fetched over HTTPS with SHA-256 integrity validation. A 4-tier pipeline guarantees air-gapped/offline reliability:
    Local CacheHTTPS DownloadBundled Template FallbackGraceful .todo Stub.

Reference Examples in Repository

We’ve added three concrete template implementations to examples/:

  • cli-tool: OptionParser integration, version module, and isolated specs.
  • enterprise-service: Domain layout (config/, src/{{name}}/cli.cr), Podman Quadlet container files, RPM .spec, and GPLv3 licensing.
  • kemal-web: Kemal hypermedia web layout with remote asset declarations (Pico CSS, Datastar) and bundled offline fallbacks.

Links

Looking forward to feedback on the resolution order, token conventions, and manifest schema before opening the formal RFC against crystal-lang/rfcs.