askill
nx-executors

nx-executorsSafety 85Repository

Create and use custom Nx executors in TypeScript monorepos. Covers executor structure, package references (@scope:executor), schema definitions, ExecutorContext API, and best practices for reusable build tasks.

0 stars
1.2k downloads
Updated 2/4/2026

Package Files

Loading files...
SKILL.md

Custom Nx Executors

Create reusable build, test, and development tasks for Nx workspaces.

Quick Start

1. Create Executor Structure

tools/executors/
├── my-executor/
│   ├── executor.ts      # Implementation
│   ├── schema.json      # JSON Schema
│   └── schema.d.ts      # TypeScript types
├── executors.json       # Registry
└── package.json         # Package definition

2. Define Schema

tools/executors/my-executor/schema.json:

{
  "$schema": "http://json-schema.org/schema",
  "cli": "nx",
  "title": "My Executor",
  "description": "What this executor does",
  "type": "object",
  "properties": {
    "option1": {
      "type": "string",
      "description": "Description of option1"
    },
    "option2": {
      "type": "number",
      "description": "Description of option2",
      "default": 42
    }
  },
  "required": ["option1"]
}

tools/executors/my-executor/schema.d.ts:

export interface MyExecutorSchema {
  option1: string;
  option2?: number;
}

3. Implement Executor

tools/executors/my-executor/executor.ts:

import { ExecutorContext } from '@nx/devkit';
import { MyExecutorSchema } from './schema';

export default async function myExecutor(
  options: MyExecutorSchema,
  context: ExecutorContext
): Promise<{ success: boolean }> {
  console.log('Executing my-executor');
  console.log('Project:', context.projectName);

  try {
    // Executor logic
    return { success: true };
  } catch (error) {
    console.error('Executor failed:', error);
    return { success: false };
  }
}

4. Register in Registry

tools/executors/executors.json:

{
  "executors": {
    "my-executor": {
      "implementation": "./my-executor/executor",
      "schema": "./my-executor/schema.json",
      "description": "What this executor does"
    }
  }
}

5. Configure Package

tools/executors/package.json:

{
  "name": "@scope/tools",
  "version": "0.1.0",
  "main": "../src/index.ts",
  "executors": "./executors.json"
}

6. Enable Package References

Root package.json:

{
  "workspaces": [
    "packages/*",
    "tools/executors"
  ]
}

tsconfig.base.json:

{
  "compilerOptions": {
    "paths": {
      "@scope/tools": ["tools/src/index.ts"]
    }
  }
}

Create entry point tools/src/index.ts:

/**
 * @scope/tools package entry point
 * Allows Nx to resolve package before accessing executors
 */

7. Use in Project

project.json:

{
  "targets": {
    "my-task": {
      "executor": "@scope/tools:my-executor",
      "options": {
        "option1": "value",
        "option2": 123
      }
    }
  }
}

8. Run

# Show help
bunx nx run my-project:my-task --help

# Execute
bunx nx run my-project:my-task

ExecutorContext API

Access project and workspace information:

export default async function myExecutor(
  options: MyExecutorSchema,
  context: ExecutorContext
) {
  const projectName = context.projectName;
  const projectRoot = context.projectGraph.nodes[projectName].data.root;
  const projectConfig = context.projectGraph.nodes[projectName].data;
  
  // Use project information
}

Package References

Recommended: Package Reference

{
  "executor": "@scope/tools:dev-proxy"
}

Benefits:

  • Clean, semantic reference
  • Refactoring-safe
  • Self-documenting

Avoid: Relative Path Reference

{
  "executor": "../../tools/executors:dev-proxy"
}

Problems:

  • Breaks if structure changes
  • Unclear ownership
  • Harder to maintain

Testing Executors

Show Help

bunx nx run <project>:<target> --help

Verifies:

  • Executor can be resolved
  • Schema is valid
  • Options are correctly defined

Execute

bunx nx run <project>:<target>

Dry Run

bunx nx run <project>:<target> --dry-run

Debugging

Enable Verbose Output

bunx nx run <project>:<target> --verbose

Check Executor Resolution

bunx nx show project <project> --web

Verify Package Structure

# Verify workspace inclusion
bun pm ls | grep @scope/tools

# Verify path mapping
cat tsconfig.base.json | grep -A2 "@scope/tools"

# Verify package import
node -e "require.resolve('@scope/tools')"

Best Practices

1. Always Use Package Reference

// Good
"executor": "@scope/tools:dev-proxy"

// Bad
"executor": "../../tools/executors:dev-proxy"

2. Provide Clear Schema Documentation

{
  "properties": {
    "port": {
      "type": "number",
      "description": "Port for development server",
      "default": 3000
    }
  }
}

3. Handle Errors Gracefully

try {
  // Logic
  return { success: true };
} catch (error) {
  console.error('Error:', error.message);
  return { success: false };
}

4. Use ExecutorContext

export default async function myExecutor(
  options: MyExecutorSchema,
  context: ExecutorContext
) {
  const projectName = context.projectName;
  const projectRoot = context.projectGraph.nodes[projectName].data.root;
  // Use context
}

5. Support Standard Options

  • --verbose for detailed output
  • --dry-run for preview mode
  • --skip-nx-cache to bypass cache

Troubleshooting

"Unable to resolve @scope/tools:executor-name"

Verify all three requirements:

  1. tools/executors in workspace (package.json)
  2. ✅ Path mapping in tsconfig.base.json
  3. ✅ Entry point exists (tools/src/index.ts)
  4. main field in tools/executors/package.json

Executor not found in executors.json

Solution: Add to tools/executors/executors.json:

{
  "executors": {
    "your-executor": {
      "implementation": "./your-executor/executor",
      "schema": "./your-executor/schema.json",
      "description": "Your executor description"
    }
  }
}

Schema validation errors

Check required fields and types:

bunx nx run project:target --help

Migration: Relative Paths to Package References

Before:

{
  "targets": {
    "dev": {
      "executor": "../../tools/executors:dev-proxy"
    }
  }
}

After:

{
  "targets": {
    "dev": {
      "executor": "@scope/tools:dev-proxy"
    }
  }
}

Steps:

  1. Complete workspace configuration
  2. Update all project.json files
  3. Test: bunx nx run <project>:<target> --help
  4. Commit changes

Resources

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

96/100Analyzed 2/11/2026

An exceptional technical guide for Nx executors, providing end-to-end instructions from project structure to debugging and migration.

85
95
90
98
95

Metadata

Licenseunknown
Version-
Updated2/4/2026
Publisherpantheon-org

Tags

apici-cdtesting