Projgen is a powerful, template-driven CLI tool for scaffolding new projects. Instead of manually setting up boilerplate code every time, you define a JSON template once and let Projgen handle the rest — running commands, writing files, patching configs, and cloning repositories.
npm install -g @projgen/cliOr run directly without installing:
npx @projgen/cli create ./my-template.jsonprojgen create [templatePath] [skipPrompts]Aliases: projgen c projgen cr
Example:
projgen create ./templates/test.jsonProjgen will validate the template, prompt you for any defined variables, and then execute all steps in order.
You can add -y to skip all Variables Prompts that are optional or have a default value and will only get prompted for required variables without default value.
Used to add a template to the local registry.
projgen add [templatePath] [alias]Aliases: projgen a
| parameter | description |
|---|---|
| templatePath | the path to a json file containing the template |
| alias | a optional property to define the alias used to reference the template in the cr command |
If no alias is provided, template.id is used.
This command fails if the alias is already getting used in the registry or if there is already a template with the same id. -> Templates are stored in a file with template.id as filename, that's why you can't have duplicate ids.
Example:
projgen add ./some-template.json myTemplatenow the template in some-template.json can be run using projgen c myTemplate
Used to list the contents of the local registry (Registry Version, Templates and Linked Registries)
projgen listAliases: projgen ls
Used to remove a template from the registry.
projgen removeAliases: projgen rm
A template is a JSON file that defines variables (user prompts) and steps (actions to scaffold the project).
{
"id": "my-template",
"name": "My Template",
"description": "A short description of what this template creates",
"version": "1.0.0",
"author": "Your Name",
"variables": [...],
"steps": [...]
}Variables are prompted to the user interactively before any steps run. They can be referenced inside step fields using {{variableName}} syntax.
| Type | Description |
|---|---|
string |
Free-text input, supports default and required |
number |
Numeric input, supports default and required |
boolean |
True/false toggle, supports default |
select |
Single or multi-select from a list of options |
Example:
{
"variables": [
{
"name": "projectName",
"type": "string",
"message": "What is the name of your project?",
"required": true
},
{
"name": "framework",
"type": "select",
"message": "Which framework would you like to use?",
"options": ["react", "vue", "svelte"],
"multiple": false,
"required": true
}
]
}Steps are executed in order after all variables have been collected. Each step supports an optional when condition to control whether it runs.
{
"type": "run",
"command": "npm install",
"cwd": "./my-project"
}| Parameter | Required | Description |
|---|---|---|
type |
Required | Is run to define Run step |
when |
Optional | Any potential conditionals |
command |
Required | The command to Run |
cwd |
Optional | Path to the directory to run the command from |
Creates the file if it doesn't exist, overwrites it if it does.
{
"type": "write",
"path": "src/index.ts",
"content": "console.log('Hello, {{projectName}}!');"
}Can also be used with a URL instead of content to simplify writing a bigger file. Is best used with something like (gist)[https://gist.github.com/] for sharing.
{
"type": "write",
"path": "src/index.ts",
"url": "https://gist.githubusercontent.com/LorisRue/ae20c81981af5c3d7aa7f2139b30a89c/raw/ee9ceda05a598c5cd0601d6cd40d86f1c8729686/example"
}| Parameter | Required | Description |
|---|---|---|
type |
Required | Is write to define Write step |
when |
Optional | Any potential conditionals |
path |
Required | The Path to the file to write |
content |
Optional* | The text to write to the file |
url |
Optional* | A URL to pull the text from |
*Either content or url have to be set. If both are set, url gets priority.
Modify specific parts of an existing file.
| Operation | Description |
|---|---|
replace |
Replace matched text (use empty string to delete) |
insert-after |
Insert content after the matched text |
insert-before |
Insert content before the matched text |
append |
Append content to the end of the file |
prepend |
Prepend content to the beginning of the file |
{
"type": "patch-text",
"path": "README.md",
"operation": "append",
"content": "\n## License\nMIT"
}You can also fetch content from a URL instead of providing it inline:
{
"type": "patch-text",
"path": ".eslintrc.json",
"operation": "replace",
"find": "{}",
"url": "https://raw.githubusercontent.com/my-org/configs/main/.eslintrc.json"
}| Parameter | Required | Description |
|---|---|---|
type |
Required | Is run to define Run step |
when |
Optional | Any potential conditionals |
path |
Required | Path to file to patch |
operation |
Required | The operation to perform (mentioned above) |
find |
Optional* | A string to search for in the file to perform the operation to. |
content |
Optional** | The text to patch (replace, insert...). |
url |
Optional** | The Url to get the text to patch from |
*find is required for all operations except for append and prepend, since they are relative to the entire file.
**Either content or url have to be set. If both are set, url gets priority.
Use content="" and operation="replace" to remove the text defined in find
Surgically modify JSON config files using a path array.
| Operation | Description |
|---|---|
set |
Set a value at a path, creating it if it doesn't exist |
append |
Append a value to an array or object (key-value) at a path |
remove |
Remove the value at a path |
Example JSON:
{
"name": "my-app",
"scripts": {
"test": "vitest",
"build": "tsc"
}
}Template Step Example
{
"type": "patch-json",
"path": "package.json",
"operation": "set",
"jsonPath": ["scripts", "test"],
"value": "vitest run"
}You can also access a index of an array by just using the index as a string.
{
"arr": [
{
"something": "a thing",
"someObject": { "oneAttribute": "Some wrong thing" }
},
{ "something": "another thing" }
]
}{
"type": "patch-json",
"path": "example.json",
"operation": "set",
"jsonPath": ["arr", "0", "someObject", "oneAttribute"],
"value": "Some right thing"
}This would turn "Some wrong thing" into "Some right thing"
To access the test property inside that example JSON, use jsonPath: ["scripts", "test"]. That points to package.json.scripts.test.
| Parameter | Required | Description |
|---|---|---|
type |
Required | Is run to define Run step |
when |
Optional | Any potential conditionals |
path |
Required | Path to json file to patch |
operation |
Required | The operation to perform (mentioned above) |
jsonPath |
Required | The "json path" to the entry to change (see example). |
value |
Optional* | The value to insert |
*value is required for set and append, but will be ignored for remove
Any step can include a when array to conditionally execute based on variable values. The step will only execute if all conditions are met.
{
"type": "run",
"command": "npm install tailwindcss",
"when": [
{
"variable": "useTailwind",
"operator": "eq",
"value": true
}
]
}| Parameter | Description |
|---|---|
| variable | The name of a variable defined in the variables array |
| operator | the operator to use (see below) |
| value | The value to check for (not needed for isNull and isNotNull) |
Available operators:
| Operator | Name | Description | Valid Datatypes |
|---|---|---|---|
| eq | Equals | Checks if variable is equal to value | All |
| neq | Not Equals | Checks if variable is not equal to value | All |
| gt | Greater Than | Checks if variable is greater than value | Number |
| lt | Less Than | Checks if variable is less than value | Number |
| gte | Greater Than or Equal | Checks if variable is greater than or equal to value | Number |
| lte | Less Than or Equal | Checks if variable is less than or equal to value | Number |
| contains | Contains | Checks if an array variable contains the value | Array |
| notContains | Does Not Contain | Checks if an array variable does not contain the value | Array |
| isNull | Is Null | Checks if variable content is null | All (value ignored) |
| isNotNull | Is Not Null | Checks if variable content is not null | All (value ignored) |
| matches | Matches Regex | Checks if a string variable matches a regex pattern | String |
| notMatches | Does Not Match Regex | Checks if a string variable does not match a regex pattern | String |
- Node.js >= 18
- npm
git clone https://github.com/Projgen/core.git
cd core
npm install| Script | Description |
|---|---|
npm run dev |
Start in development mode (watch) |
npm run build |
Compile TypeScript to dist/ |
npm start |
Run the compiled code from dist/ |
npm test |
Run tests with Vitest |
npm run lint |
Lint the codebase with ESLint |
npm run format |
Format code with Prettier |
MIT — see LICENSE for details.