Using JGen
Releases and versions
JGen's own version line, which Chenile versions each release builds against and targets, and what changed in each release.
How JGen is versioned
JGen is released on its own cadence, separately from Chenile. Up to 2.1.35, JGen and Chenile shared a version number; from 2.5.1 on, JGen has its own.
- Only released Chenile. A JGen release is built against a Chenile version that is already on Maven Central, never an unreleased one.
- Generated projects target a released Chenile. The default
chenileVersionin JGen’s configuration is the latest released Chenile. Change it with a config file (jgen -e myconfig, then-c). A blueprint that needs a newer Chenile declaressinceVersionand refuses an olderchenileVersion. jgen --versionprints JGen’s version, the Chenile version generated projects target by default, and the Chenile version JGen was built with.- Maven coordinates: from 2.5.1, JGen’s libraries are published as
org.chenile.jgen:jgen-baseandorg.chenile.jgen:jgen-ext-pebble. Standalone blueprints and extensions compile against these. - stm-cli is versioned and released separately too: see stm-cli.
| JGen | Built with Chenile | Generates Chenile (default) | Maven group | Status |
|---|---|---|---|---|
| 2.5.1 | 2.1.35 | 2.1.35 | org.chenile.jgen |
in development |
| 2.1.35 | 2.1.35 | 2.1.35 | org.chenile |
released October 31, 2026 |
Install or upgrade with brew upgrade ajapros/jgen-tap/jgen, or see Install.
2.5.1 in development
Not released yet. The first JGen release on its own version line. It contains everything merged since 2.1.35.
Versioning and coordinates
- Version line: JGen moves from 2.1.35 to 2.5.1. It is built with Chenile 2.1.35, and generated projects target Chenile 2.1.35 by default.
- Maven coordinates: the libraries move from
org.chenile:jgen-basetoorg.chenile.jgen:jgen-base(andorg.chenile.jgen:jgen-ext-pebble). Standalone blueprints generated byjgen-blueprintuse the new coordinates and the JGen version that generated them. Existing standalone blueprints should change theirjgen-basedependency toorg.chenile.jgen:jgen-base:2.5.1. jgen --versionnow also shows both Chenile versions.- stm-cli is no longer built here. It has its own repository and releases, and installs from the same tap:
brew install ajapros/jgen-tap/stm-cli.make allandsetpath.shin chenile-gen now cover JGen only.
new blueprints in their own Git repository
The jgen-blueprint blueprint has a new input, standaloneRepo. With y it generates a self-contained blueprint
project and makes it a local Git repository on branch main with one commit, ready to push. The project has its
own groupId and version, jgen-base as a provided dependency, a README, a .gitignore and a release workflow that
attaches the jar to a GitHub release for jgen -g github:owner/repo. JGen prints the remaining steps: create the
GitHub repository, add the remote, push, tag.
Every generated blueprint now also has a working starter template, a corrected init hook and a test that generates from it.
Blueprints get a fifth hook point, finalHook. It runs last, after the generation record is written, and suits
work outside the file tree.
_DoT_ for dotfiles in templates
A new template convention: every _DoT_ in a file or folder name becomes a dot, so _DoT_gitignore is generated
as .gitignore and _DoT_github/workflows as .github/workflows. Maven drops dotfiles from blueprint jars, so this
is how a blueprint ships them. It runs right after __key__ placeholders (as the dot path tag, below).
See the template reference.
GITHUB_REPOSITORY and PATTERN validation rules
Two new input validation rules:
GITHUB_REPOSITORYacceptsowner/repoand follows GitHub’s naming limits. Thejgen-blueprintblueprint now uses it forgithubRepository, instead of a check in its hook.PATTERNwithpatternandpatternMessagecovers a format specific to one blueprint. The whole value must match, and the message is what users see. The pattern is checked when the blueprint loads.
Error messages for every rule now say what a valid value looks like. See input validation.
generated projects as Git repositories
Any blueprint can now have JGen make its output a local Git repository, with no code:
- Turning it on: set the input
initGitto true, either as a prompt or from a hook. JGen then runsgit initon branchmain, adds everything and makes one commit. This is a new pipeline step,git-initializer, which runs after the generation record is written. - Connecting to GitHub: a blueprint that names a
GITHUB_REPOSITORYinput in its newgitRepositoryFieldproperty also gets that repository as theoriginremote, ready to push. - Remote style: SSH by default, or HTTPS when the config has
gitRemoteProtocolset tohttps. - Commit message:
gitCommitMessagesets it. - What it never does: create the GitHub repository or push.
jgen-blueprint now uses this feature for standalone blueprint projects.
Homebrew installs find their Java
The Homebrew formula depends on openjdk@25, which Homebrew does not put on the PATH. In 2.1.35 the jgen
launcher only found Java through JAVA_HOME or the PATH. It now also looks in Homebrew’s openjdk@25 location, so
brew install ajapros/jgen-tap/jgen works on a machine with no other Java.
template-only blueprints
A blueprint with no Java hooks no longer needs a jar. You lay out the repository like a jar’s resources
(src/main/resources/META-INF/blueprint.json plus the template folder) and push a version tag.
- Using it from GitHub:
jgen -g github:owner/repo@tagdownloads the source archive at that tag when the release has no blueprint jar, or when the tag has no release at all. - Trust and hashes: these work as for jars. The hash covers the blueprint’s files, so it stays stable if GitHub re-packs the tag.
- Java hooks are refused: a descriptor that declares an
initHookis rejected, because it needs Java classes. JavaScript hooks (below) are allowed. - Local folders:
dir:<folder>uses a template-only blueprint from your disk while you write it.
blueprint catalogs
You can now use blueprints by short name: jgen -g terraform, terraform@1.2.0, or acme/terraform for a specific
catalog. jgen --search [text] lists matches by name, description or tag.
- Official catalog:
ajapros/jgen-catalogis built in and searched first. Its entries are reviewed, so the sources it lists are trusted without a prompt. - Team catalogs: add your own in
~/.jgen/settings.json. They go through the normal trust prompt unless you mark them trusted. - Version pins: a catalog can pin versions to SHA-256 hashes, which JGen enforces.
- Caching: catalogs are cached for an hour and work offline.
- Installed blueprints still win: if a blueprint with the same name is installed, JGen uses it.
See blueprint catalogs.
blueprint hooks in JavaScript
Blueprint hooks can now be JavaScript files instead of Java classes. blueprint.json lists them under scripts,
by hook name (postInputCapture, childBlueprintInputs, postProcess, final). JGen runs them with GraalJS,
which ships inside JGen.
- No build: a blueprint whose hooks are scripts is still a template-only blueprint, usable straight from
GitHub, a catalog or
dir:. - What scripts get: inputs as JSON, a
jgenobject with naming helpers and access to declaredFILEinputs, and inpostProcessandfinalaprojectobject to read, write, move and delete files in the generated project. - Sandbox: no Java classes, no network, processes, threads or environment, no files outside the project, and a statement limit against runaway loops.
- Checked early: scripts compile when the blueprint loads, so syntax errors and missing functions show up before any prompt.
- Mixing: a script runs after a Java hook of the same kind.
See scripting hooks.
path tags, and adding your own
The rules for file and folder names (.filelist, __key__, _DoT_, %%key=value%%) used to be four separate
pipeline steps. They are now path tags, applied in order by one step, path-tag-processor.
- Same output: existing blueprints generate exactly what they did. The old step classes remain, deprecated, for anyone who built a chain of their own.
- Conditional folders merge: a sub-folder of a
%%key=value%%folder that already exists in the parent is now merged into it. It used to be silently dropped. - New tags without changing JGen: implement
PathTag, list it inMETA-INF/services/org.chenile.jgen.template.tags.PathTagand drop the jar in the blueprints folder. Itsorderdecides where it runs. Built-in tags can’t be replaced, and duplicate names are an error. - Regeneration: the generation record lists the extension tags that were active (in its
extensionsfield), andjgen -rrefuses to regenerate when one is missing.
See path tags.
extensions for other template and target languages
JGen can now be extended for very different uses without forking it. There are three extension points, all
installed by dropping a jar in the blueprints folder (discovered with ServiceLoader):
- Template engines. The render step picks the engine by file extension. Mustache stays built in, and a new
module,
jgen-ext-pebble, adds Pebble (.peb, Twig and Jinja syntax), which ships with the CLI and the portal. JGen’s Pebble doesn’t escape output, and a missing value renders as empty. - Language packs. Packs add validation rules and template helpers for a target language. Blueprints name a
pack’s rules in
validationlike built-in ones. An unknown rule name is still rejected when the field is read. The built-in packs are:- python:
PYTHON_MODULE,PYTHON_PACKAGEandPYPI_PROJECT; - node:
NPM_PACKAGEandJS_IDENTIFIER.
- python:
- Path tags, as described above.
- Shared helpers. Template helpers now reach every engine and JavaScript hook:
capitalize,uncapitalize,camelCase,pascalCase,snakeCase,upperSnakeCaseandkebabCase, plus any pack’s. In Mustache they are lambdas ({{#snakeCase}}{{entity}}{{/snakeCase}}), and in Pebble filters. requires. A blueprint lists the extensions it needs, with optional minimum versions ("pebble","terraform@1.2"), and is refused when they are missing.- Records and regeneration. The generation record’s new
extensionsfield lists the added extensions a project depended on, andjgen -rneeds them installed. - Listing them.
jgen --extensionslists everything installed. - Safety. Names are unique across all kinds, so built-ins can’t be replaced. Engines can’t share a file extension, and packs can’t redefine built-in rules or existing helpers.
See Extending JGen.
2.1.35
Released October 31, 2026, as part of Chenile 2.1.35. It brought:
- one validator for blueprint inputs;
- generation records and
jgen -r; - blueprints from GitHub;
- installs with Homebrew and JBang.
See the Chenile 2.1.35 release notes.
Earlier JGen versions were released with Chenile; see chenile.org release notes.