@wpkernel/cli
Command-line interface for scaffolding and managing WP Kernel projects with Rails-like conventions and WordPress best practices.
Overview
The WP Kernel CLI provides generators, project setup, and development workflow automation. It follows the "convention over configuration" principle to get you building WordPress products quickly.
Architecture
Installation
Global Installation (Recommended)
npm install -g @wpkernel/cli
# or
pnpm add -g @wpkernel/cli
One-time Usage
npx @wpkernel/cli init my-project
# or
pnpm dlx @wpkernel/cli init my-project
Commands
Project Initialization
Create a new plugin:
wpk init my-awesome-plugin --template=plugin
cd my-awesome-plugin
Create a new theme:
wpk init my-theme --template=theme
cd my-theme
Interactive setup:
wpk init
# Prompts for project name, type, features, etc.
Code Generation
Generate a resource:
wpk generate resource Post
# Creates resource definition, types, and tests
Generate an action:
wpk generate action CreatePost
# Creates action with orchestration boilerplate
Generate a view component:
wpk generate view PostList
# Creates block bindings and interactivity setup
Generate a job:
wpk generate job SendNotification
# Creates background job with polling support
Development Workflow
Start development server:
wpk start
# Watches kernel inputs, regenerates on change, and proxies the Vite dev server
Build for production:
wpk build
# Optimized build with WordPress externals
Run tests:
wpk test
# Runs unit and E2E tests
Type checking:
wpk typecheck
# Validates TypeScript across project
Project Structure
Generated projects follow WordPress and WP Kernel conventions:
my-plugin/
├── plugin.php # Main plugin file
├── package.json # Node dependencies
├── composer.json # PHP dependencies
├── vite.config.ts # Build configuration
├── tsconfig.json # TypeScript config
├── src/ # Source code
│ ├── resources/ # Data layer definitions
│ ├── actions/ # Write orchestration
│ ├── views/ # Block bindings & interactivity
│ ├── jobs/ # Background processing
│ └── index.ts # Entry point
├── includes/ # PHP bridge code
├── __tests__/ # Test files
└── dist/ # Built assets
Advanced Generator Patterns
Complete CRUD Feature Generation
The most powerful pattern - generate an entire feature with all necessary files:
wpk generate feature Job --with=resource,admin-table,actions,tests
Generated Structure:
src/
├── resources/
│ └── job.ts # Resource definition with REST routes
├── actions/
│ ├── CreateJob.ts # Create action with validation
│ ├── UpdateJob.ts # Update action with optimistic updates
│ ├── DeleteJob.ts # Delete action with confirmation
│ └── BulkDeleteJobs.ts # Batch operations
├── .generated/
│ ├── ui/
│ │ ├── app/
│ │ │ └── job/admin/JobsAdminScreen.tsx # ResourceDataView screen wired to kernel
│ │ └── dataviews/jobDataView.ts # createResourceDataViewController scaffold
│ └── php/
│ └── Admin/Menu_JobsAdminScreen.php # Optional menu registration
├── types/
│ └── job.d.ts # TypeScript interfaces
└── __tests__/
├── resources/
│ └── job.test.ts # Resource unit tests
├── actions/
│ └── job-actions.test.ts # Action integration tests
└── e2e/
└── job-admin.spec.ts # End-to-end admin tests
Generated assets land under
.generated/
by default. Commit them directly or promote them into your source tree as part of your build step.
PHP Bridge Files:
includes/
├── resources/
│ └── class-job-resource.php # REST API endpoints
└── admin/
└── class-job-admin.php # Admin menu registration
Customizable Generation Templates
Resource with Custom Options
wpk generate resource Product \
--rest-base=products \
--with-cache \
--with-events \
--php-class=Product \
--capabilities=manage_products
Generated Resource:
// src/resources/product.ts
import { defineResource } from '@wpkernel/core/resource';
export interface Product {
id: number;
name: string;
price: number;
status: 'draft' | 'published' | 'archived';
created_at: string;
updated_at: string;
}
export const product = defineResource<Product>({
name: 'product',
routes: {
list: { path: '/my-plugin/v1/products', method: 'GET' },
get: { path: '/my-plugin/v1/products/:id', method: 'GET' },
create: { path: '/my-plugin/v1/products', method: 'POST' },
update: { path: '/my-plugin/v1/products/:id', method: 'PUT' },
delete: { path: '/my-plugin/v1/products/:id', method: 'DELETE' },
},
cacheKeys: {
list: (query) => ['product', 'list', query],
get: (id) => ['product', id],
},
events: {
created: 'wpk.resource.product.created',
updated: 'wpk.resource.product.updated',
deleted: 'wpk.resource.product.deleted',
},
});
Admin Interface Generation
wpk generate admin-page ProductsList \
--resource=Product \
--features=search,filter,bulk-actions \
--wp-version=6.7
Generated Admin Page:
// .generated/ui/app/product/admin/ProductsAdminScreen.tsx
import {
createResourceDataViewController,
createDataFormController,
ResourceDataView,
} from '@wpkernel/ui/dataviews';
import { product } from '../../resources/product';
import { CreateProduct } from '../../actions/product';
const controller = createResourceDataViewController({
resource: product,
config: product.ui?.admin?.dataviews!,
});
const createProductForm = createDataFormController({
action: CreateProduct,
onSuccess: ({ invalidate }) => invalidate(controller.keys.list()),
});
export default function ProductsAdminScreen() {
return (
<ResourceDataView
controller={controller}
dataForm={createProductForm}
emptyState={{
title: 'No products yet',
description: 'Create the first product to publish it in the catalog.',
actionLabel: 'Add product',
}}
/>
);
}
Actions declared in product.ui.admin.dataviews.actions
determine which kernel actions run for row and bulk operations (for example products.delete
mapping to DeleteProduct
).
Action Generation with Patterns
wpk generate action CreateProduct \
--resource=Product \
--with=validation,events,jobs,optimistic \
--permissions=create_products
Generated Action:
// src/actions/CreateProduct.ts
import { defineAction } from '@wpkernel/core/actions';
import { product } from '../resources/product';
import { KernelError } from '@wpkernel/core/error';
import { events } from '@wpkernel/core/events';
import { jobs } from '@wpkernel/core/jobs';
export const CreateProduct = defineAction(
'CreateProduct',
async ({ name, price, status = 'draft' }) => {
// Generated validation
if (!name?.trim()) {
throw new KernelError('ValidationError', {
message: 'Product name is required',
field: 'name',
});
}
// Permission check
if (!currentUserCan('create_products')) {
throw new KernelError('PermissionError', {
message: 'You cannot create products',
capability: 'create_products',
});
}
// Optimistic update
const tempId = `temp-${Date.now()}`;
product.cache.setItem(tempId, { name, price, status });
try {
const created = await product.create({ name, price, status });
// Remove temp item, add real item
product.cache.removeItem(tempId);
product.cache.setItem(created.id, created);
// Events
events.emit('wpk.resource.product.created', {
data: created,
meta: { userId: getCurrentUserId() },
});
// Background job for featured products
if (status === 'published') {
await jobs.enqueue('IndexProductForSearch', {
productId: created.id,
});
}
return created;
} catch (error) {
// Revert optimistic update
product.cache.removeItem(tempId);
throw error;
}
}
);
Template Customization
Custom Generator Templates
# Create custom template
wpk template create my-crud-feature
Template Structure:
.wpk/templates/my-crud-feature/
├── template.config.js # Template configuration
├── prompts.js # Interactive prompts
├── files/
│ ├── resource.ts.hbs # Handlebars template for resource
│ ├── admin-page.tsx.hbs # Admin interface template
│ ├── actions/
│ │ ├── create.ts.hbs # Create action template
│ │ └── update.ts.hbs # Update action template
│ └── tests/
│ └── e2e.spec.ts.hbs # E2E test template
└── hooks/
├── pre-generate.js # Pre-generation hooks
└── post-generate.js # Post-generation cleanup
Template Configuration:
// .wpk/templates/my-crud-feature/template.config.js
export default {
name: 'my-crud-feature',
description: 'Complete CRUD feature with custom patterns',
prompts: [
{
type: 'input',
name: 'entityName',
message: 'Entity name (singular):',
validate: (input) => input.length > 0,
},
{
type: 'multiselect',
name: 'features',
message: 'Select features:',
choices: [
{ title: 'Admin Table', value: 'admin-table' },
{ title: 'REST API', value: 'rest-api' },
{ title: 'Background Jobs', value: 'jobs' },
{ title: 'Email Notifications', value: 'email' },
],
},
],
files: {
'src/resources/{{kebabCase entityName}}.ts': 'resource.ts.hbs',
'src/admin/pages/{{pascalCase entityName}}List.tsx':
'admin-page.tsx.hbs',
// ... other file mappings
},
};
WordPress Version-Specific Generation
Modern WordPress (6.7+) Features
wpk generate admin-table JobsList \
--wp-version=6.7 \
--features=dataviews,script-modules,interactivity
Generates code using:
ResourceDataView
+createResourceDataViewController
- Script Modules for loading
- Inline creation via
createDataFormController
- Latest
@wordpress/components
Legacy-Compatible Generation
wpk generate admin-table JobsList \
--wp-version=6.5 \
--fallback-components
Generates code using:
- Standard HTML tables with WordPress styling
- Traditional script enqueuing
- Basic @wordpress/components only
- Graceful feature degradation
Development Workflow Integration
Complete Development Setup
# Initialize project with full toolchain
wpk create my-plugin --template=complete
# Generates:
# - WordPress plugin structure
# - Vite build configuration
# - TypeScript setup with strict mode
# - Jest + Playwright testing setup
# - ESLint + Prettier configuration
# - GitHub Actions CI/CD
# - Development Docker environment
Incremental Feature Development
# Start with basic plugin
wpk create my-plugin --template=minimal
# Add features incrementally
wpk add feature User --with=resource,actions
wpk add admin-interface UsersList --resource=User
wpk add background-job SendWelcomeEmail --trigger=user-created
wpk add e2e-tests user-management
Advanced Patterns
Multi-Resource Features
wpk generate feature JobApplication \
--resources=Job,Application,Candidate \
--relationships=job-has-many-applications \
--admin-workflow=application-pipeline
Plugin-to-Plugin Integration
wpk generate integration WooCommerce \
--hooks=woocommerce_order_created \
--sync-resources=Order,Customer \
--admin-pages=order-analytics
Headless/API-First Generation
wpk generate api-plugin ContentManagement \
--mode=headless \
--auth=jwt \
--resources=Post,Media,User \
--admin=false
Code Generation
Resource Generator
wpk generate resource Post --rest-base=posts
Creates:
src/resources/Post.ts
- Resource definitionsrc/types/Post.ts
- TypeScript types__tests__/resources/Post.test.ts
- Unit testsincludes/resources/class-post.php
- PHP REST endpoints
Action Generator
wpk generate action CreatePost --resource=Post
Creates:
src/actions/CreatePost.ts
- Action orchestration__tests__/actions/CreatePost.test.ts
- Unit tests- Event emission boilerplate
- Cache invalidation setup
View Generator
wpk generate view PostList --block-type=dynamic
Creates:
src/views/PostList/
- Component directory- Block binding configuration
- Interactivity API setup
- CSS and template files
Configuration
Project Config (wpk.config.ts
)
import { defineConfig } from '@wpkernel/cli';
export default defineConfig({
namespace: 'my-plugin',
restNamespace: 'my-plugin/v1',
textDomain: 'my-plugin',
php: {
namespace: 'MyPlugin',
classPrefix: 'MP_',
},
build: {
externals: ['@wordpress/data', '@wordpress/components'],
cssFramework: 'tailwind', // or 'none'
},
});
Generator Options
Customize generated code with flags:
# Generate with custom options
wpk generate resource User \
--rest-base=users \
--with-cache \
--with-events \
--php-class=User
Integration Features
TypeScript Setup
- Strict mode enabled
- WordPress type definitions
- Path mapping for clean imports
- Test environment configuration
Build Configuration
- Vite with WordPress externals
- Tree-shaking optimized
- CSS preprocessing (Sass/PostCSS)
- Asset optimization
Testing Setup
- Jest for unit tests
- Playwright for E2E tests
- @wpkernel/e2e-utils integration
- Coverage reporting
WordPress Integration
- wp-env configuration
- Plugin/theme headers
- Enqueue scripts setup
- REST API registration
Development Workflow
Typical Development Session
# Start development environment
wpk start
# Generate new feature
wpk generate resource Product
wpk generate action CreateProduct
# Run tests
wpk test --watch
# Build for deployment
wpk build
Hot Reloading
The CLI sets up hot module replacement for rapid development:
- JavaScript/TypeScript changes reload automatically
- CSS changes apply without page refresh
- PHP changes restart wp-env server
Deployment
Production Build
wpk build --mode=production
Generates:
- Minified JavaScript bundles
- Optimized CSS
- Source maps (optional)
- Asset manifest
Plugin Distribution
wpk package
Creates a deployable plugin zip with:
- Built assets
- PHP files
- Plugin headers
- README and license files
CLI Development
Custom Generators
Extend the CLI with custom generators:
// generators/custom-generator.ts
import { defineGenerator } from '@wpkernel/cli/generator';
export default defineGenerator({
name: 'custom',
description: 'Generate custom components',
templates: [...],
async generate(options) {
// Custom generation logic
},
});
Plugin System
Add functionality via plugins:
// wpk.config.ts
import customPlugin from './plugins/custom-plugin';
export default defineConfig({
plugins: [customPlugin()],
});
Integration Guides
- Getting Started - Installation and setup
- Quick Start - Create your first project
- Contributing - Development workflow
Related Documentation
- Resources Guide - Understanding resource patterns
- Actions Guide - Action orchestration