Task Types Reference

Complete reference for all available task types in scaffoldfy.

Task Structure

Every task has the following properties:

Required Properties

Optional Properties

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:

  1. Omitted (default):
    • enabled defaults to true (task will run)
    • required defaults to true (task failure stops execution)
  2. Simple boolean: true or false
  3. Conditional object: { "type": "condition", "value": "JavaScript expression" }
  4. 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:

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

  1. Conditions are JavaScript expressions evaluated at runtime
  2. The expression has access to:
    • All root-level prompt values
    • All root-level variable values
    • All config values
  3. If the condition evaluates to false, the task is completely skipped
  4. If the condition evaluates to true, the task proceeds normally

Evaluation Timing:

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:

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:

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


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


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


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


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


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

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


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


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


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


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


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


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

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

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:


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:

Example:

{
  "type": "update-json",
  "config": {
    "file": "package.json",
    "updates": { "private": true },
    "condition": "makePrivate === true"
  }
}

Supported operators:

Common patterns:

Template Variables

All task configs support template variable interpolation using `` syntax:

Error Handling

Dry Run Mode

All tasks respect --dry-run flag:


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)