Exec File Plugin
The exec-file plugin allows you to execute local or remote script files with full support for variable interpolation in file paths, arguments, parameters, and working directories.
Overview
Unlike the exec plugin which runs inline shell commands, exec-file executes external script files. This is useful for:
- Running setup/configuration scripts
- Executing remote scripts from URLs
- Running scripts with dynamic arguments based on user input
- Passing environment variables to scripts
- Supporting multiple runtimes (Node.js, Bash, PowerShell, etc.)
Configuration
interface ExecFileConfig {
file: string; // Path to script (local or remote URL)
runtime?: ExecFileRuntime; // 'node' | 'bash' | 'sh' | 'pwsh' | 'powershell' (auto-detected if omitted)
args?: string[]; // Arguments to pass to the script
parameters?: Record<string, string>; // Environment variables
cwd?: string; // Working directory
condition?: string; // Optional condition to execute
}
Configuration Fields
file(required): Path to the script file to execute- Local:
'scripts/setup.js','./scripts/setup.sh' - Remote:
'https://example.com/scripts/setup.js' - Supports variable interpolation:
'scripts/-setup.js'
- Local:
runtime(optional): Runtime environment to execute the file- If not specified, auto-detected from file extension:
.js,.cjs,.mjsβnode.sh,.bashβbash.ps1βpwsh
- Falls back to
nodeif detection fails - Manual options:
'node','bash','sh','pwsh','powershell'
- If not specified, auto-detected from file extension:
args(optional): Array of arguments to pass to the script- Each argument supports variable interpolation
- Example:
['--name=', '--author=']
parameters(optional): Environment variables to pass to the script- Values support variable interpolation
- Example:
{ "PROJECT_NAME": "", "AUTHOR": "" }
cwd(optional): Working directory for script execution- Supports variable interpolation
- Default:
process.cwd()
condition(optional): JavaScript expression to conditionally execute the task- Example:
'runSetup === true'
- Example:
Runtime Auto-Detection
The plugin automatically detects the appropriate runtime based on the file extension:
{
"type": "exec-file",
"config": {
"file": "scripts/setup.js"
// Runtime automatically detected as 'node'
}
}
Detection Rules:
.js,.cjs,.mjsβnode.sh,.bashβbash.ps1βpwsh- Unknown extension β
node(default)
Variable Interpolation
All string fields support `` interpolation:
| Field | Supports Interpolation | Example |
|---|---|---|
file |
β Yes | 'scripts/-setup.js' |
args |
β Yes (each arg) | ['--name='] |
parameters |
β Yes (values) | { "NAME": "" } |
cwd |
β Yes | '-scripts' |
Variables are resolved from:
- Prompt responses
- Variable definitions
- Built-in config values (projectName, author, etc.)
Examples
Basic Node.js Script Execution
{
"id": "run-setup",
"name": "Run Setup Script",
"type": "exec-file",
"config": {
"file": "scripts/setup.js",
"runtime": "node"
}
}
Script with Variable Interpolation
{
"id": "run-project-setup",
"name": "Run Project-Specific Setup",
"type": "exec-file",
"config": {
"file": "scripts/-setup.js",
"runtime": "node"
}
}
Script with Arguments
{
"id": "configure-project",
"name": "Configure Project",
"type": "exec-file",
"config": {
"file": "scripts/configure.js",
"runtime": "node",
"args": ["--name=", "--author=", "--license="]
}
}
Script with Environment Variables
{
"id": "build-project",
"name": "Build Project",
"type": "exec-file",
"config": {
"file": "scripts/build.js",
"runtime": "node",
"parameters": {
"PROJECT_NAME": "",
"BUILD_ENV": "",
"AUTHOR": ""
}
}
}
Script with Custom Working Directory
{
"id": "run-in-subdir",
"name": "Run Script in Subdirectory",
"type": "exec-file",
"config": {
"file": "scripts/build.js",
"runtime": "node",
"cwd": "packages/"
}
}
Remote Script Execution
Execute a script from a remote URL:
{
"id": "run-remote-setup",
"name": "Run Remote Setup Script",
"type": "exec-file",
"config": {
"file": "https://raw.githubusercontent.com/your-org/scripts/main/setup.js",
"runtime": "node",
"args": ["--project="]
}
}
Note: Remote scripts are fetched, saved to a temporary file, executed, and then cleaned up automatically.
Conditional Execution
{
"id": "optional-setup",
"name": "Optional Setup Script",
"type": "exec-file",
"config": {
"file": "scripts/optional-setup.js",
"runtime": "node",
"condition": "includeOptionalSetup === true"
}
}
Bash Script Execution
{
"id": "run-bash-script",
"name": "Run Bash Setup",
"type": "exec-file",
"config": {
"file": "scripts/setup.sh",
"runtime": "bash",
"args": [""]
}
}
PowerShell Script Execution
{
"id": "run-powershell-script",
"name": "Run PowerShell Setup",
"type": "exec-file",
"config": {
"file": "scripts/setup.ps1",
"runtime": "pwsh",
"parameters": {
"ProjectName": ""
}
}
}
Complete Example with Prompts
{
"prompts": [
{
"id": "projectName",
"type": "input",
"message": "What is your project name?",
"default": "my-project"
},
{
"id": "author",
"type": "input",
"message": "Author name?",
"default": "Your Name"
},
{
"id": "runSetup",
"type": "confirm",
"message": "Run setup script?",
"default": true
}
],
"tasks": [
{
"id": "run-setup-script",
"name": "Run Project Setup Script",
"description": "Executes the project setup script with user-provided values",
"required": true,
"enabled": true,
"type": "exec-file",
"config": {
"file": "scripts/setup.js",
"runtime": "node",
"args": ["--name=", "--author="],
"parameters": {
"PROJECT_NAME": "",
"AUTHOR": ""
},
"condition": "runSetup === true"
}
}
]
}
Script Access to Variables
Via Command-Line Arguments
Scripts can access interpolated arguments:
Task config:
{
"args": ["--name=", "--author="]
}
Node.js script:
const args = process.argv.slice(2);
// args = ['--name=my-project', '--author=John Doe']
Via Environment Variables
Scripts can access interpolated environment variables:
Task config:
{
"parameters": {
"PROJECT_NAME": "",
"AUTHOR": ""
}
}
Node.js script:
const projectName = process.env.PROJECT_NAME;
const author = process.env.AUTHOR;
Bash script:
#!/bin/bash
echo "Project: $PROJECT_NAME"
echo "Author: $AUTHOR"
Remote vs Local Scripts
Local Scripts
- Resolved relative to the taskβs source location
- Supports relative paths:
'./scripts/setup.js' - Supports absolute paths
- File must exist or an error is thrown
Remote Scripts
- Fetched from HTTP/HTTPS URLs
- Saved to temporary file
- Executed
- Automatically cleaned up after execution
- Must be accessible without authentication
Comparison with exec Plugin
| Feature | exec Plugin |
exec-file Plugin |
|---|---|---|
| Inline commands | β Yes | β No |
| External script files | β No | β Yes |
| Remote scripts | β No | β Yes |
| Multiple runtimes | β No | β Yes |
| Variable interpolation | β Yes (in command) | β Yes (in file, args, params, cwd) |
| Environment variables | β Yes (inherited) | β Yes (custom parameters) |
Use Cases
-
Project Initialization Scripts
{ "file": "scripts/init-.js", "runtime": "node", "args": ["--name="] } -
Remote Configuration Scripts
{ "file": "https://example.com/configs/setup.js", "runtime": "node" } -
Cross-Platform Scripts
{ "file": "scripts/setup.ps1", "runtime": "pwsh", "parameters": { "Name": "" } } -
Conditional Setup
{ "file": "scripts/advanced-setup.js", "runtime": "node", "condition": "advancedMode === true" }
Using exec-file in Variables and Prompts
The exec-file plugin can also be used in variable values and prompt defaults to dynamically resolve values by executing script files.
In Variables
Execute a script file and use its output as a variable value:
{
"variables": [
{
"id": "currentVersion",
"value": {
"type": "exec-file",
"file": "scripts/get-version.js"
}
},
{
"id": "gitBranch",
"value": {
"type": "exec-file",
"file": "scripts/get-branch.sh",
"runtime": "bash"
}
},
{
"id": "envConfig",
"value": {
"type": "exec-file",
"file": "scripts/get-config.js",
"args": ["--env="],
"parameters": {
"CONFIG_PATH": ""
}
}
}
]
}
Script Output Parsing:
- JSON: Automatically parsed if output starts with
{or[ - Numbers: Automatically parsed if output matches number pattern
- Booleans:
true/falsestrings converted to boolean - Strings: Everything else returned as string
Example script for version (scripts/get-version.js):
const package = require('./package.json');
console.log(package.version); // Output: "1.2.3"
In Prompt Defaults
Execute a script to provide dynamic default values for prompts:
{
"prompts": [
{
"id": "projectName",
"type": "input",
"message": "Project name:",
"default": {
"type": "exec-file",
"file": "scripts/suggest-name.js"
}
},
{
"id": "gitUser",
"type": "input",
"message": "Git username:",
"default": {
"type": "exec-file",
"file": "scripts/get-git-user.sh",
"runtime": "bash"
}
},
{
"id": "useTypeScript",
"type": "confirm",
"message": "Use TypeScript?",
"default": {
"type": "exec-file",
"file": "scripts/detect-ts.js"
}
}
]
}
Example script for boolean default (scripts/detect-ts.js):
const fs = require('node:fs');
const hasTsConfig = fs.existsSync('tsconfig.json');
console.log(hasTsConfig); // Output: true or false
Runtime Auto-Detection in Values
Runtime is automatically detected from file extension, even in variables and prompts:
{
"variables": [
{
"id": "nodePath",
"value": {
"type": "exec-file",
"file": "scripts/find-node.sh"
// Runtime automatically detected as 'bash' from .sh extension
}
}
]
}
Best Practices
- Use Relative Paths: Reference scripts relative to your configuration for portability
- Version Remote Scripts: Use versioned URLs or commit hashes for remote scripts
- Error Handling: Scripts should return appropriate exit codes
- Security: Only execute trusted scripts, especially from remote sources
- Cross-Platform: Use Node.js for cross-platform scripts when possible
- Documentation: Document what your scripts do and what arguments they accept
Error Handling
The plugin will throw an error if:
- The script file doesnβt exist (local files)
- The remote URL fails to fetch (remote files)
- The script execution fails (non-zero exit code)
- The runtime is not installed on the system
Security Considerations
- Local Scripts: Ensure scripts are from trusted sources
- Remote Scripts: Only use HTTPS URLs and verify the source
- Code Review: Review scripts before executing them
- Execution Context: Scripts run with the same permissions as the scaffoldfy process
See Also
- exec Plugin - For inline shell commands
- Prompts - For collecting user input
- Variables - For defining reusable values
- Conditional Execution - For advanced conditional logic