Task Types Reference
Complete reference for all available task types in scaffoldfy.
Task Structure
Every task has the following properties:
Required Properties
id(string): Unique identifier for the taskname(string): Human-readable task nametype(string): Task type (see below for all available types)
Optional Properties
description(string): Detailed description of what the task does. Defaults to empty string if omitted.-
required(booleanobject): Whether failure of this task should stop the process. Defaults to trueif omitted. Can be a boolean or conditional object withtypefield (see “Conditional Task Execution” section). Set tofalsefor non-critical tasks. -
enabled(booleanobject): Whether this task should execute. Defaults to trueif omitted. Can be a boolean or conditional object withtypefield (see “Conditional Task Execution” section). config(object): Task-specific configuration (varies by task type)dependencies(string[]): IDs of tasks that must run before this onerollback(object): How to rollback if something failsoverride(string): Merge strategy when extending configurations ('merge'or'replace')
Minimal Task Example
{
"id": "my-task",
"name": "My Task",
"type": "write",
"config": {
"file": "README.md",
"template": "# My Project"
}
}
This will use defaults: description: "", required: true, enabled: true.
Conditional Task Execution
Tasks can be conditionally enabled using the enabled field, or can be dynamically set as required/optional using the required field. Both fields support the same conditional formats.
Enabled and Required Fields
Both enabled and required fields support the following formats:
- Omitted (default):
enableddefaults totrue(task will run)requireddefaults totrue(task failure stops execution)
- Simple boolean:
trueorfalse - Conditional object:
{ "type": "condition", "value": "JavaScript expression" } - Executable object:
{ "type": "exec", "value": "shell command" }- Run a command to determine the value
Simple Boolean
{
"id": "my-task",
"name": "My Task",
"enabled": true,
"type": "write",
"config": {
"file": "README.md",
"template": "# My Project"
}
}
Conditional with Type Field
{
"id": "typescript-setup",
"name": "Setup TypeScript",
"enabled": {
"type": "condition",
"value": "useTypeScript === true"
},
"type": "write",
"config": {
"file": "tsconfig.json",
"template": "{ \"compilerOptions\": {} }"
}
}
Executable Enabled
Run a shell command to determine if the task should be enabled:
{
"id": "git-hooks-setup",
"name": "Setup Git Hooks",
"enabled": {
"type": "exec",
"value": "git rev-parse --is-inside-work-tree"
},
"type": "exec",
"config": {
"command": "npx husky install"
}
}
The command output is parsed as a boolean:
- Empty string,
"0","false", or"no"(case-insensitive) =false - Everything else =
true - Failed commands =
false
Conditional Required Field
The required field supports the same conditional formats as enabled. This allows you to dynamically determine whether a task failure should stop execution based on runtime conditions.
Simple boolean:
{
"id": "optional-cleanup",
"name": "Cleanup temporary files",
"type": "delete",
"required": false,
"config": {
"paths": ["temp/**"]
}
}
Conditional required:
{
"id": "production-checks",
"name": "Production environment checks",
"type": "exec",
"required": {
"type": "condition",
"value": "environment === 'production'"
},
"config": {
"command": "npm run verify"
}
}
Executable required:
{
"id": "critical-in-ci",
"name": "CI-only critical task",
"type": "exec",
"required": {
"type": "exec",
"value": "test -n \"$CI\""
},
"config": {
"command": "npm run critical-checks"
}
}
In this example, the task is only required (failure stops execution) when running in a CI environment. In local development, failure will log a warning but continue.
How Conditional Enabled Works
- Conditions are JavaScript expressions evaluated at runtime
- The expression has access to:
- All root-level prompt values
- All root-level variable values
- All config values
- If the condition evaluates to
false, the task is completely skipped - If the condition evaluates to
true, the task proceeds normally
Evaluation Timing:
- Tasks are evaluated twice during execution:
- Initial filter (lazy mode): Before prompts are collected. Tasks with conditions referencing undefined prompts or exec commands are included (not filtered out yet).
- Final filter (strict mode): After all prompts and variables are collected. Tasks are evaluated with the full context (including exec command execution), and only enabled tasks are executed.
This two-phase approach allows you to use prompt values in task enabled conditions without errors. Tasks referencing prompts that don’t exist yet or using exec commands will be temporarily included, then properly filtered once all user input is collected and commands are executed.
Examples
Enable Based on Prompt Value
{
"prompts": [
{
"id": "useTypeScript",
"type": "confirm",
"message": "Use TypeScript?",
"default": true
}
],
"tasks": [
{
"id": "setup-typescript",
"name": "Setup TypeScript",
"enabled": {
"type": "condition",
"value": "useTypeScript === true"
},
"type": "write",
"config": {
"file": "tsconfig.json",
"template": "{ \"compilerOptions\": {} }"
}
}
]
}
Complex Conditional Logic
{
"id": "setup-ci",
"name": "Setup CI/CD",
"enabled": {
"type": "condition",
"value": "includeCI === true && (platform === 'github' || platform === 'gitlab')"
},
"type": "write",
"config": {
"file": ".github/workflows/ci.yml",
"template": "name: CI"
}
}
Task Config Conditions
Individual task configs also support a condition field that determines whether the task operations should execute. The condition is a JavaScript expression evaluated at runtime with access to all prompt values and variables.
Type: ConditionExpression (string)
Examples:
"useTypeScript === true""nodeVersion >= 16 && includeTests === true""packageManager === 'pnpm'""!keepExampleCode"
If the config condition evaluates to false, the task will be skipped. If omitted, the task will always execute (when enabled).
Note: The difference between enabled and config.condition:
enabled: Controls whether the task runs at all (evaluated before the task)config.condition: Controls whether the task’s operations execute (evaluated during the task)
In most cases, use enabled for conditional task execution.
update-json
Update JSON files with new values. Supports nested properties using dot notation.
Configuration
interface Config {
file: string; // Path to JSON file
updates: Record<string, unknown>; // Key-value pairs to update
condition?: string; // Optional: only execute if condition evaluates to true
}
Example
{
"type": "update-json",
"config": {
"file": "package.json",
"updates": {
"name": "",
"scripts.test": "vitest",
"repository.url": ""
}
}
}
Conditional Example
{
"type": "update-json",
"config": {
"file": "package.json",
"updates": {
"private": true
},
"condition": "makePrivate === true"
}
}
Features
- Nested property updates using dot notation (e.g.,
"scripts.test") - Template variable interpolation
- Preserves JSON formatting
- Deep object merging
- Optional condition: JavaScript expression evaluation (skips task if false)
template
Create or overwrite files from templates with variable interpolation.
Configuration
interface Config {
file: string; // Path to file to create/overwrite
template: string; // Template string with
condition?: string; // Optional: only execute if condition evaluates to true
allowCreate?: boolean; // Optional: whether to allow creating the file if it doesn't exist (default: true)
}
Example
{
"type": "write",
"config": {
"file": "README.md",
"template": "# \n\nAuthor: \n\nRepository: "
}
}
Conditional Example
{
"type": "write",
"config": {
"file": "CONTRIBUTING.md",
"template": "# Contributing Guide\n\nThank you for contributing!",
"condition": "includeContributing === true"
}
}
Prevent File Creation Example
{
"type": "write",
"config": {
"file": "existing-file.md",
"template": "This will only be written if the file already exists",
"allowCreate": false
}
}
Features
- Full template variable interpolation
- Creates directories if needed
- Overwrites existing files
- Optional condition: JavaScript expression evaluation (skips task if false)
- Optional allowCreate: Control whether to create files that don’t exist (default: true)
create
Create new files with optional content. Similar to template but specifically designed for file creation, with support for both inline content and external template files.
Configuration
interface Config {
file: string; // Path to file to create
template?: string; // Inline template string (supports simple syntax)
templateFile?: string; // Path to external template file (relative to project root). .hbs files use Handlebars automatically
condition?: string; // Optional: only execute if condition evaluates to true
}
Example: Inline Template
{
"type": "create",
"config": {
"file": "README.md",
"template": "# \n\nAuthor: \n\nRepository: "
}
}
Example: External Template File
{
"type": "create",
"config": {
"file": "src/config.ts",
"templateFile": "templates/config.template.ts"
}
}
Example: Handlebars Template
{
"type": "create",
"config": {
"file": "README.md",
"templateFile": "templates/readme.hbs"
}
}
When using a .hbs file, Handlebars syntax is automatically used. Otherwise, simple `` interpolation is used.
Conditional Example
{
"type": "create",
"config": {
"file": "CONTRIBUTING.md",
"template": "# Contributing Guide\n\nThank you for contributing!",
"condition": "includeContributing === true"
}
}
Features
- Creates files with optional content
- Supports inline templates via
templateproperty - Supports external template files via
templateFileproperty - Automatic Handlebars support for
.hbsfiles - Simple `` interpolation for non-Handlebars templates
- Creates parent directories if needed
- Skips if file already exists (won’t overwrite)
- Optional condition: JavaScript expression evaluation (skips task if false)
regex-replace
Replace text in files using regular expressions.
Configuration
interface Config {
file: string; // Path to file to modify
pattern: string; // Regular expression pattern
replacement: string; // Replacement string
flags?: string; // Regex flags (g, i, m, etc.)
condition?: string; // Optional: only execute if condition evaluates to true
}
Example
{
"type": "regex-replace",
"config": {
"file": ".github/workflows/ci.yml",
"pattern": "old-repo-name",
"replacement": "",
"flags": "g"
}
}
Conditional Example
{
"type": "regex-replace",
"config": {
"file": "README.md",
"pattern": "\\[DRAFT\\]\\s*",
"replacement": "",
"flags": "g",
"condition": "!isDraft"
}
}
Features
- Full regex support
- Optional flags (case-insensitive, multiline)
- Template variables in replacement strings
- Optional condition: JavaScript expression evaluation (skips task if false)
replace-in-file
Simple find and replace in files (string literal matching).
Configuration
interface Config {
file: string;
replacements: Array<{
find: string; // String to find
replace: string; // String to replace with
}>;
condition?: string; // Optional: only execute if condition evaluates to true
}
Example
{
"type": "replace-in-file",
"config": {
"file": "CONTRIBUTING.md",
"replacements": [
{ "find": "template-name", "replace": "" },
{ "find": "template-author", "replace": "" }
]
}
}
Conditional Example
{
"type": "replace-in-file",
"config": {
"file": "README.md",
"replacements": [{ "find": "[BETA]", "replace": "" }],
"condition": "!isBeta"
}
}
Features
- Multiple replacements in single file
- Global replacement (all occurrences)
- Template variable interpolation
- Skips non-existent files gracefully
- Optional condition: JavaScript expression evaluation (skips task if false)
delete
Delete files or directories, optionally based on condition evaluation.
Configuration
interface Config {
paths: string[];
condition?: string; // Optional: only delete if condition evaluates to true
}
Example
Basic deletion:
{
"type": "delete",
"config": {
"paths": ["coverage", "dist", "temp", "node_modules/.cache"]
}
}
Conditional deletion:
{
"type": "delete",
"config": {
"condition": "!keepExamplePackages",
"paths": ["packages/example", "examples"]
}
}
Features
- Recursive directory deletion
- Multiple paths in single task
- Skips non-existent paths
- Force deletion (no confirmation)
- Optional condition: JavaScript expression evaluation
- Condition context: Access to all config variables (including prompt values)
- Conditional logic: Supports boolean logic (
!,&&,||) - Skips deletion if condition is false or invalid
Note: When using conditions, you can reference values from task prompts. For example, if you have a confirm prompt with id: "keepExamplePackages", you can use !keepExamplePackages in your condition to delete when the user answers “No”.
rename
Rename or move files and directories.
Configuration
interface Config {
from: string; // Current path
to: string; // New path
condition?: string; // Optional: only execute if condition evaluates to true
}
Example
{
"type": "rename",
"config": {
"from": "template.config.js",
"to": ".config.js"
}
}
Conditional Example
{
"type": "rename",
"config": {
"from": "example.config.js",
"to": ".config.js",
"condition": "useCustomConfig === true"
}
}
Features
- Template variable interpolation in paths
- Works with files and directories
- Creates parent directories if needed
- Skips if source doesn’t exist
- Optional condition: JavaScript expression evaluation (skips task if false)
move
Move files or directories from one location to another.
Configuration
interface Config {
from: string; // Source path
to: string; // Destination path
condition?: string; // Optional: only execute if condition evaluates to true
}
Example
{
"type": "move",
"config": {
"from": "templates/example.config.js",
"to": "config/.config.js"
}
}
Conditional Example
{
"type": "move",
"config": {
"from": "temp/generated-files",
"to": "src/generated",
"condition": "useGenerated === true"
}
}
Features
- Template variable interpolation in paths
- Works with files and directories
- Creates parent directories if needed
- Skips if source doesn’t exist
- Original file is removed (moved, not copied)
- Optional condition: JavaScript expression evaluation (skips task if false)
copy
Copy files or directories from one location to another. Unlike move, the original files remain intact.
Configuration
interface Config {
from: string; // Source path
to: string; // Destination path
condition?: string; // Optional: only execute if condition evaluates to true
}
Example
{
"type": "copy",
"config": {
"from": "templates/base-structure",
"to": "src/"
}
}
Conditional Example
{
"type": "copy",
"config": {
"from": "examples/sample-files",
"to": "examples/",
"condition": "includeExamples === true"
}
}
Features
- Template variable interpolation in paths
- Works with files and directories
- Recursive directory copying
- Creates parent directories if needed
- Skips if source doesn’t exist
- Original files remain intact (copied, not moved)
- Optional condition: JavaScript expression evaluation (skips task if false)
append
Append content to existing files. Useful for adding entries to .gitignore, README.md, or other configuration files.
Configuration
interface Config {
file: string; // Target file path
content?: string; // Inline content (supports syntax)
template?: string; // Alias for content
templateFile?: string; // Path to external template file (.hbs files use Handlebars)
newline?: boolean; // Add newline before appending (default: true)
condition?: string; // Optional: only execute if condition evaluates to true
}
Example
{
"type": "append",
"config": {
"file": ".gitignore",
"content": "\n# Custom ignores\n*.local\n.env\n"
}
}
With Template Variables
{
"type": "append",
"config": {
"file": "README.md",
"template": "\n## \n\nCreated by \n"
}
}
With Template File
{
"type": "append",
"config": {
"file": "CHANGELOG.md",
"templateFile": "templates/changelog-entry.md"
}
}
Without Newline
{
"type": "append",
"config": {
"file": "inline-data.txt",
"content": ", more data",
"newline": false
}
}
Conditional Example
{
"type": "append",
"config": {
"file": ".gitignore",
"content": "\n# IDE files\n.vscode/\n.idea/\n",
"condition": "includeIDEIgnores === true"
}
}
Features
- Template variable interpolation in content
- Support for both inline content and template files
- Handlebars support for
.hbstemplate files - Creates file if it doesn’t exist
- Automatically adds newline before content if file doesn’t end with one (unless
newline: false) - Support for both
contentandtemplatefields (aliases) - Optional condition: JavaScript expression evaluation (skips task if false)
mkdir
Create directory structure. Useful for setting up project scaffolding.
Configuration
interface Config {
path: string; // Directory path to create
condition?: string; // Optional: only execute if condition evaluates to true
}
Example
{
"type": "mkdir",
"config": {
"path": "src/components/ui"
}
}
Multiple Directories Example
Use multiple tasks to create several directories:
{
"tasks": [
{
"id": "create-src",
"name": "Create src directory",
"type": "mkdir",
"config": {
"path": "src"
}
},
{
"id": "create-tests",
"name": "Create tests directory",
"type": "mkdir",
"config": {
"path": "tests"
}
}
]
}
Conditional Example
{
"type": "mkdir",
"config": {
"path": "src/e2e-tests",
"condition": "includeE2ETests === true"
}
}
Features
- Template variable interpolation in paths
- Recursive directory creation (creates parent directories automatically)
- Handles existing directories gracefully (no error)
- Cross-platform path support
- Optional condition: JavaScript expression evaluation (skips task if false)
git-init
Initialize a new git repository.
Configuration
interface Config {
removeExisting: boolean;
initialCommit: boolean;
message?: string;
condition?: string; // Optional: only execute if condition evaluates to true
}
Example
{
"type": "git-init",
"config": {
"removeExisting": true,
"initialCommit": true,
"message": "feat: initial project setup"
}
}
Conditional Example
{
"type": "git-init",
"config": {
"removeExisting": true,
"initialCommit": true,
"message": "feat: initial project setup",
"condition": "initializeGit === true"
}
}
Features
- Clean slate: removes old git history
- Optional initial commit
- Custom commit message
- Stages all files if creating initial commit
- Optional condition: JavaScript expression evaluation (skips task if false)
exec
Execute shell commands.
Configuration
interface Config {
command: string;
cwd?: string;
condition?: string; // Optional: only execute if condition evaluates to true
}
Example
{
"type": "exec",
"config": {
"command": "npm install && npm build",
"cwd": "./"
}
}
Conditional Example
{
"type": "exec",
"config": {
"command": "npm run generate-docs",
"condition": "includeDocs === true"
}
}
Features
- Full shell command support
- Template variable interpolation
- Custom working directory
- Captures stdout/stderr
- Returns exit code
- Optional condition: JavaScript expression evaluation (skips task if false)
Security Note
Be careful with exec tasks as they can run arbitrary commands. Only use in trusted task files.
exec-file
Execute local or remote script files with support for multiple runtimes (Node.js, Bash, PowerShell, etc.).
Configuration
interface Config {
file: string; // Path to script (local or remote URL), supports
runtime?: 'node' | 'bash' | 'sh' | 'pwsh' | 'powershell'; // Default: 'node'
args?: string[]; // Arguments (supports in each arg)
parameters?: Record<string, string>; // Environment variables (values support )
cwd?: string; // Working directory (supports )
condition?: string; // Optional: only execute if condition evaluates to true
}
Example: Basic Node.js Script
{
"type": "exec-file",
"config": {
"file": "scripts/setup.js",
"runtime": "node"
}
}
Example: Script with Variable Interpolation
{
"type": "exec-file",
"config": {
"file": "scripts/-setup.js",
"runtime": "node",
"args": ["--name=", "--author="],
"parameters": {
"PROJECT_NAME": "",
"AUTHOR": ""
}
}
}
Example: Remote Script
{
"type": "exec-file",
"config": {
"file": "https://raw.githubusercontent.com/your-org/scripts/main/setup.js",
"runtime": "node",
"args": ["--project="]
}
}
Example: Bash Script
{
"type": "exec-file",
"config": {
"file": "scripts/setup.sh",
"runtime": "bash",
"args": [""]
}
}
Conditional Example
{
"type": "exec-file",
"config": {
"file": "scripts/advanced-setup.js",
"runtime": "node",
"condition": "advancedMode === true"
}
}
Features
- Execute local or remote script files
- Support for multiple runtimes: Node.js, Bash, Shell, PowerShell
- Full variable interpolation in
file,args,parameters, andcwd - Pass arguments to scripts
- Pass environment variables via
parameters - Custom working directory
- Remote scripts are automatically fetched and cleaned up
- Optional condition: JavaScript expression evaluation (skips task if false)
Security Note
Be careful with exec-file tasks, especially when executing remote scripts. Only use scripts from trusted sources.
See Also
For comprehensive documentation, examples, and best practices, see:
- Exec File Plugin Documentation - Complete guide with advanced examples
Common Features Across All Tasks
Conditional Execution
All task types now support optional conditional execution via the condition?: string field:
let condition: string; // JavaScript expression that evaluates to true/false
How it works:
- Add a
conditionfield to any task config - The condition is a JavaScript expression evaluated with config variables
- Task executes only if condition evaluates to
true - Task is skipped if condition evaluates to
falseor is invalid - Access to all config variables (including prompt values)
Example:
{
"type": "update-json",
"config": {
"file": "package.json",
"updates": { "private": true },
"condition": "makePrivate === true"
}
}
Supported operators:
- Comparison:
===,!==,>,<,>=,<= - Logical:
&&,||,! - Ternary:
condition ? true : false - Property access:
config.value
Common patterns:
"condition": "!keepExamples"- Skip if keepExamples is false"condition": "environment === 'production'"- Only in production"condition": "includeTests && !skipLinting"- Multiple conditions"condition": "version >= 2"- Numeric comparison
Template Variables
All task configs support template variable interpolation using `` syntax:
- ``
- ``
- ``
- ``
- ``
- ``
- Custom variables from prompts (e.g., ``)
Error Handling
- Required tasks (default): Stop execution on failure
- Non-required tasks (
required: false): Log warning and continue - File not found: Most tasks handle gracefully
- Invalid config: Validation error before execution
- Invalid condition: Task is skipped with warning
Dry Run Mode
All tasks respect --dry-run flag:
- Show what would be done
- No actual file system changes
- No command execution
- Validates configuration
Task Type Selection Guide
| Use Case | Task Type |
|---|---|
| Update package.json | update-json |
| Create new files (overwrite ok) | write |
| Create new files (don’t overwrite) | create |
| Create from external template | create (with templateFile) |
| Create with Handlebars template | create (with .hbs file) |
| Find and replace (regex) | regex-replace |
| Find and replace (simple) | replace-in-file |
| Remove files/folders | delete |
| Conditional operations | Any task type (with enabled.condition) |
| Rename/move files | rename |
| Move files (relocate) | move |
| Copy files/folders | copy |
| Append to existing files | append |
| Create directories | mkdir |
| Reset git history | git-init |
| Run commands | exec |
| Execute script files | exec-file |
| Execute remote scripts | exec-file (with URL) |
| Run scripts with custom runtime | exec-file (with runtime) |
| Execute only when user agrees | Any task type (with prompt + enabled) |