Simple code generation without Python, Node.js, or external dependencies.
Featuregen is a tiny, dependency-free code generator written in POSIX shell.
It transforms template files into one or more source files using a small, purpose-built template language.
Need help creating a template? Use the optional AI-powered Telegram assistant to generate a starting point.
The repository contains the Featuregen engine itself (implemented as a POSIX shell script) together with a comprehensive automated test suite written in Kotlin and JUnit, making the project easy to verify and extend.
- Zero dependencies
- POSIX shell compatible
- Multiple output files from a single template
- Built-in string transformation functions
- Simple and readable template language
Template:
@expect package
@expect fullName
@let shortName = extractIgnoringCase(fullName, Feature)
@let snakeCaseName = snake(fullName)
@let packagePath = pathFromPackage(package)
@file path=~<<packagePath>>/~<<snakeCaseName>>/di/~<<shortName>>Module.kt
@@fstart
package ~<<package>>.~<<snakeCaseName>>.di
import ~<<package>>.~<<snakeCaseName>>.presentation.~<<shortName>>ViewModel
val ~<<shortName>>Module = module {
viewModelOf(::~<<shortName>>ViewModel)
}
@@fend
Run:
./featuregen template.featuregen \
package=foo.bar \
fullName=FeatureLoginGenerated file:
foo/bar/feature_login/di/LoginModule.kt
Contents:
package foo.bar.feature_login.di
import foo.bar.feature_login.presentation.LoginViewModel
val LoginModule = module {
viewModelOf(::LoginViewModel)
}Requires a variable to be provided.
@expect package
Variables are passed as command-line arguments.
name=FeatureLogin
package=com.example.demoReference them using
~<<name>>
Generation fails if the variable is missing.
Creates a new variable from a built-in function.
@let packagePath = pathFromPackage(package)
Defines the destination file.
@file path=src/~<<packagePath>>/Login.kt
Everything between @@fstart and @@fend becomes the contents of a generated file.
@@fstart
Hello
@@fend
| Function | Description |
|---|---|
camel(value) |
Converts text to camelCase |
snake(value) |
Converts text to snake_case |
screamingSnake(value) |
Converts text to SCREAMING_SNAKE_CASE |
pathFromPackage(value) |
Converts com.example.app → com/example/app |
extractIgnoringCase(value, remove) |
Removes a substring ignoring case |
featuregenVersion() |
Returns the current Featuregen version |
Lines starting with // outside file blocks are treated as comments and ignored by the generator.
// This is a comment
@expect package
@file path=src/~<<packagePath>>/Example.kt
@@fstart
// This comment will be written to the generated file.
@@fend
Inside @@fstart and @@fend, every line—including those starting with //—is treated as file content.
FeatureGen includes an optional AI-powered Telegram assistant that helps you create .featuregen templates by describing the files and structure you want to generate.
Describe what you want to build, or provide a code snippet, and the bot will help you create the corresponding template.
Useful for:
- bootstrapping a ready-to-run Featuregen setup (script + template)
- creating new templates
➡️ Use the bot here: @featuregen_bot
Note: The bot is an external tool and is not required to use FeatureGen.