Getting Started with scaffoldfy

This guide will help you get started with @pixpilot/scaffoldfy (formerly scaffoldfy) - a flexible and powerful task automation utility for project setup, cleanup, and configuration tasks.

Installation

Install the package using npm (or your preferred package manager):

npm install @pixpilot/scaffoldfy

Or install globally:

npm install -g @pixpilot/scaffoldfy

Using without Installation

You can also run scaffoldfy without installing it using npx:

npx @pixpilot/scaffoldfy --config ./setup/setup-tasks.json

Quick Start

Interactive Mode

The simplest way to use the tool - it will prompt you for configuration:

scaffoldfy

With Configuration File

Define your tasks in a JSON or TypeScript file and pass it to the CLI:

scaffoldfy --config ./tasks.json

Or with TypeScript:

scaffoldfy --config ./tasks.ts

Schema Validation

By default, all JSON task configuration files are validated against the JSON schema to catch configuration errors early. The schema validation ensures:

If validation fails, you’ll see detailed error messages pointing to the issues:

scaffoldfy --config ./tasks.json
# Validating task configuration against schema...
# ❌ Schema validation failed:
#
# The following validation errors were found:
#
#   • /tasks/0: Missing required property "type"
#   • /name: Value must match pattern: ^[a-z\d]+(?:-[a-z\d]+)*$

You can skip validation (not recommended) with the --no-validate flag:

scaffoldfy --config ./tasks.json --no-validate

Dry Run Mode

Preview what changes would be made without actually applying them:

scaffoldfy --config ./tasks.json --dry-run

Learn more: Dry Run Mode Documentation

Force Execution

Force execution even if checks fail:

scaffoldfy --force

Debug Mode

Enable debug logging to see detailed information about what’s happening:

scaffoldfy --config ./tasks.json --debug

Debug mode provides verbose output including:

This is particularly useful for:

CLI Options

Option Description
--config <path> Path to config file (JSON or TypeScript, default: ./config-tasks.json)
--dry-run Preview changes without applying them
--force Force execution even if checks fail
--no-validate Skip schema validation of task configuration (validation is enabled by default)
-h, --help Show help message
-v, --version Show version

Programmatic Usage

Using TypeScript Tasks

import { runWithTasks } from '@pixpilot/scaffoldfy';
import { tasks } from './my-tasks';

// Run with default options (interactive)
await runWithTasks(tasks);

// Run with dry-run enabled
await runWithTasks(tasks, { dryRun: true });

// Force execution
await runWithTasks(tasks, { force: true });

Loading Tasks from JSON

import fs from 'node:fs';
import { runWithTasks } from '@pixpilot/scaffoldfy';

const configFilePath = './config.json';
const tasksJson = JSON.parse(fs.readFileSync(configFilePath, 'utf-8'));

await runWithTasks(tasksJson.tasks);

Custom Task Example

import type { TaskDefinition } from '@pixpilot/scaffoldfy';
import { runWithTasks } from '@pixpilot/scaffoldfy';

const customTasks: TaskDefinition[] = [
  {
    id: 'setup-project',
    name: 'Setup Project',
    description: 'Initialize project with custom settings',
    required: true,
    enabled: true,
    type: 'update-json',
    config: {
      file: 'package.json',
      updates: {
        name: '',
        author: '',
        version: '0.1.0',
      },
    },
  },
  {
    id: 'create-readme',
    name: 'Create README',
    description: 'Generate project README',
    required: true,
    enabled: true,
    type: 'write',
    config: {
      file: 'README.md',
      template: `# 

Created by 

## Installation

\`\`\`sh
npm install
\`\`\`
`,
    },
  },
];

await runWithTasks(customTasks);

JSON Tasks Format

Basic Structure

{
  "$schema": "https://unpkg.com/@pixpilot/scaffoldfy/schema",
  "name": "my-config",
  "description": "Optional description of what this configuration does",
  "dependencies": ["optional-dependency-config"],
  "tasks": [
    {
      "id": "unique-id",
      "name": "Task Name",
      "description": "What this task does",
      "required": true,
      "enabled": true,
      "type": "update-json",
      "config": {
        "file": "package.json",
        "updates": {
          "name": ""
        }
      }
    }
  ]
}

Note:

With Interactive Prompts

Add user prompts at the root level to collect custom input:

{
  "name": "project-setup-with-prompts",
  "description": "Configure project with interactive prompts",
  "prompts": [
    {
      "id": "projectName",
      "type": "input",
      "message": "What is your project name?",
      "required": true
    },
    {
      "id": "useTypeScript",
      "type": "confirm",
      "message": "Use TypeScript?",
      "default": true
    }
  ],
  "tasks": [
    {
      "id": "setup",
      "name": "Project Setup",
      "description": "Configure project settings",
      "required": true,
      "enabled": true,
      "type": "update-json",
      "config": {
        "file": "package.json",
        "updates": {
          "name": ""
        }
      }
    }
  ]
}

Learn more: Interactive Prompts Guide

With Dependencies

Tasks can depend on other tasks to ensure correct execution order:

{
  "name": "task-dependencies-example",
  "description": "Demonstrates task execution order with dependencies",
  "tasks": [
    {
      "id": "update-config",
      "name": "Update Config",
      "description": "Update configuration files",
      "required": true,
      "enabled": true,
      "type": "update-json",
      "config": {
        "file": "config.json",
        "updates": { "version": "1.0.0" }
      }
    },
    {
      "id": "install-deps",
      "name": "Install Dependencies",
      "description": "Install after config update",
      "required": false,
      "enabled": true,
      "dependencies": ["update-config"],
      "type": "exec",
      "config": {
        "command": "npm install"
      }
    }
  ]
}

Conditional Tasks

Use conditions to control task execution based on user input or configuration:

{
  "id": "remove-examples",
  "name": "remove-examples",
  "description": "Delete example files if not needed",
  "required": false,
  "enabled": true,
  "type": "delete",
  "config": {
    "condition": "removeExamples === true",
    "paths": ["examples", "samples"]
  }
}

Learn more: Advanced Features Guide

IDE Integration

VSCode

Add the schema reference to get autocomplete and validation in your JSON task files:

{
  "$schema": "https://unpkg.com/@pixpilot/scaffoldfy/schema",
  "tasks": []
}

WebStorm / IntelliJ IDEA

The JSON schema will be automatically detected if the $schema property is set in your JSON file.

Real-World Example

Here’s a complete example that sets up a Node.js project:

{
  "$schema": "https://unpkg.com/@pixpilot/scaffoldfy/schema",
  "name": "node-project-setup",
  "prompts": [
    {
      "id": "projectName",
      "type": "input",
      "message": "Project name?",
      "required": true
    },
    {
      "id": "description",
      "type": "input",
      "message": "Project description?"
    },
    {
      "id": "license",
      "type": "select",
      "message": "Choose a license:",
      "choices": ["MIT", "Apache-2.0", "GPL-3.0", "BSD-3-Clause"],
      "default": "MIT"
    }
  ],
  "tasks": [
    {
      "id": "project-info",
      "name": "Project Information",
      "description": "Update package.json with project details",
      "required": true,
      "enabled": true,
      "type": "update-json",
      "config": {
        "file": "package.json",
        "updates": {
          "name": "",
          "description": "",
          "license": "",
          "author": ""
        }
      }
    },
    {
      "id": "create-readme",
      "name": "Create README",
      "description": "Generate project README file",
      "required": true,
      "enabled": true,
      "type": "write",
      "config": {
        "file": "README.md",
        "template": "# \n\n\n\n## License\n\n"
      }
    },
    {
      "id": "git-init",
      "name": "Initialize Git",
      "description": "Set up git repository",
      "required": false,
      "enabled": true,
      "dependencies": ["create-readme"],
      "type": "git-init",
      "config": {}
    }
  ]
}

Best Practices

  1. Always use dry-run first - Test with --dry-run before applying changes to see exactly what will happen
  2. Keep tasks atomic - Each task should do one thing well and have a clear purpose
  3. Use dependencies wisely - Chain tasks that must run in a specific order
  4. Mark critical tasks as required - Essential tasks are required: true by default. Set required: false for optional tasks that shouldn’t stop execution on failure
  5. Document your tasks - Write clear names and descriptions for maintainability
  6. Version your task files - Keep task definitions in version control alongside your project
  7. Leverage the schema - Add $schema to JSON files for IDE autocomplete and validation
  8. Test with different inputs - Try various configuration values to ensure robustness
  9. Preview changes - Use dry-run mode to verify behavior before execution

Troubleshooting

“No tasks defined” error

Make sure you’re either:

“Circular dependency detected” error

Review your task dependencies - one or more tasks have circular references. Check the dependencies arrays in your tasks to ensure they form a directed acyclic graph (DAG).

“Task not found” error

A task lists a dependency that doesn’t exist. Verify that all task IDs in dependencies arrays match existing task IDs exactly.

Configuration variables not replaced

Ensure you’re using the correct syntax: `` and that the variable:

File not found errors

Check that:

Next Steps

Now that you’re familiar with the basics, explore these topics:

Need Help?