Complete command-line interface system for building custom CLI commands, code generation, and development tools. AdonisJS Core provides an extended Ace implementation with application context integration.
Extended Ace kernel for AdonisJS with application context and dependency injection support.
/**
* The AdonisJS Ace kernel with application integration
*/
class Kernel extends AceKernel<typeof BaseCommand> {
/**
* Create kernel instance with application context
* @param app - Application service instance
*/
constructor(app: ApplicationService);
/**
* Register command with the kernel
* @param command - Command class to register
*/
register(command: typeof BaseCommand): void;
/**
* Handle command execution
* @param argv - Command line arguments
*/
handle(argv: string[]): Promise<void>;
/**
* Get the main command being executed
* @returns Current main command instance
*/
getMainCommand(): BaseCommand | null;
/**
* Print help for available commands
*/
printHelp(): void;
/** Error handler for command execution */
errorHandler: ErrorHandler;
/** UI primitives for command interaction */
ui: UIPrimitives;
/** Prompt system for user input */
prompt: PromptContract;
}Extended base command class with AdonisJS application context and lifecycle methods.
/**
* The base command to create custom ace commands with AdonisJS integration
*/
class BaseCommand extends AceBaseCommand {
/** Command configuration options */
static options: CommandOptions;
/** Application service instance */
app: ApplicationService;
/** Kernel instance */
kernel: Kernel;
/** Whether command should keep app alive */
get staysAlive(): boolean | undefined;
/** Whether command should start the application */
get startApp(): boolean | undefined;
/**
* Create command instance
* @param app - Application service
* @param kernel - Kernel instance
* @param parsed - Parsed command arguments
* @param ui - UI primitives
* @param prompt - Prompt system
*/
constructor(
app: ApplicationService,
kernel: Kernel,
parsed: ParsedOutput,
ui: UIPrimitives,
prompt: Kernel['prompt']
);
/**
* Creates the codemods module to modify source files
* @returns Codemods instance for file manipulation
*/
createCodemods(): Promise<Codemods>;
/**
* Template method for command preparation
* Called before command execution
*/
prepare?(...args: any[]): any;
/**
* Template method for user interaction
* Called after prepare method
*/
interact?(...args: any[]): any;
/**
* Template method for command completion handling
* Called after command finishes or errors
* @returns True to suppress error reporting
*/
completed?(...args: any[]): any;
/**
* Execute the command with full lifecycle
* @returns Command result
*/
exec(): Promise<any>;
/**
* Terminate the app gracefully
* Only triggers termination when this command is the main command
*/
terminate(): Promise<void>;
}Usage Examples:
import { BaseCommand } from "@adonisjs/core/ace";
import { args, flags } from "@adonisjs/ace";
export default class MakeController extends BaseCommand {
static commandName = "make:controller";
static description = "Create a new HTTP controller";
static options: CommandOptions = {
startApp: false,
staysAlive: false,
};
@args.string({ description: "Controller name" })
declare name: string;
@flags.boolean({ description: "Create a resource controller" })
declare resource: boolean;
async run() {
const codemods = await this.createCodemods();
const controllerPath = this.app.makePath(`app/controllers/${this.name}.ts`);
await codemods.makeUsingStub("controller", controllerPath, {
name: this.name,
resource: this.resource,
});
this.logger.success(`Created controller: ${controllerPath}`);
}
}Extended list command for displaying available commands.
/**
* The List command for displaying available commands
*/
class ListCommand extends AceListCommand implements BaseCommand {
/** Command configuration options */
static options: CommandOptions;
/** Application service instance */
app: ApplicationService;
/** Kernel instance */
kernel: Kernel;
/** Whether command should keep app alive */
get staysAlive(): boolean | undefined;
/** Whether command should start the application */
get startApp(): boolean | undefined;
/**
* Creates the codemods module to modify source files
* @returns Codemods instance for file manipulation
*/
createCodemods(): Promise<Codemods>;
/**
* Terminate the app gracefully
*/
terminate(): Promise<void>;
}Comprehensive code modification utilities for generating files, managing configurations, and installing packages during command execution.
/**
* Codemods for modifying source files during command execution
*/
class Codemods extends EventEmitter {
/** Controls whether existing files should be overwritten */
overwriteExisting: boolean;
/** Controls verbose output during package installation */
verboseInstallOutput: boolean;
/**
* Create codemods instance
* @param app - Application service
* @param cliLogger - CLI logger instance
*/
constructor(app: ApplicationService, cliLogger: Logger);
/**
* Define environment variables in .env and .env.example files
* @param environmentVariables - Key-value pairs of environment variables
* @param options - Options for controlling example file content
*/
defineEnvVariables<T extends Record<string, number | string | boolean>>(
environmentVariables: T,
options?: { omitFromExample?: Array<keyof T> }
): Promise<void>;
/**
* Add environment variable validations to start/env.ts
* @param validations - Validation rules for environment variables
*/
defineEnvValidations(validations: EnvValidationNode): Promise<void>;
/**
* Register middleware in start/kernel.ts
* @param stack - Middleware stack ('server', 'router', or 'named')
* @param middleware - Array of middleware definitions
*/
registerMiddleware(
stack: 'server' | 'router' | 'named',
middleware: MiddlewareNode[]
): Promise<void>;
/**
* Register bouncer policies in app/policies/main.ts
* @param policies - Array of policy definitions
*/
registerPolicies(policies: BouncerPolicyNode[]): Promise<void>;
/**
* Update adonisrc.ts configuration file
* @param params - Parameters for RC file updates
*/
updateRcFile(...params: Parameters<CodeTransformer['updateRcFile']>): Promise<void>;
/**
* Register Vite plugin in vite.config.ts
* @param params - Parameters for Vite plugin registration
*/
registerVitePlugin(...params: Parameters<CodeTransformer['addVitePlugin']>): Promise<void>;
/**
* Register Japa plugin in tests/bootstrap.ts
* @param params - Parameters for Japa plugin registration
*/
registerJapaPlugin(...params: Parameters<CodeTransformer['addJapaPlugin']>): Promise<void>;
/**
* Generate file using stub template
* @param stubsRoot - Root directory containing stubs
* @param stubPath - Path to specific stub file
* @param stubState - Data to pass to stub template
* @returns Generation result with status and file information
*/
makeUsingStub(
stubsRoot: string,
stubPath: string,
stubState: Record<string, any>
): Promise<{
destination: string;
relativeFileName: string;
status: 'created' | 'skipped';
skipReason?: string;
}>;
/**
* Install npm packages using detected package manager
* @param packages - Array of packages with names and dependency types
*/
installPackages(packages: { name: string; isDevDependency: boolean }[]): Promise<void>;
/**
* List packages for manual installation with appropriate commands
* @param packages - Array of packages with names and dependency types
*/
listPackagesToInstall(packages: { name: string; isDevDependency: boolean }[]): Promise<void>;
/**
* Get TsMorph project instance for advanced AST manipulation
* @returns TsMorph project or undefined if assembler not available
*/
getTsMorphProject(): Promise<
InstanceType<typeof import('@adonisjs/assembler/code_transformer').CodeTransformer>['project'] | undefined
>;
}Decorators and utilities from @adonisjs/ace for command definition.
/**
* Argument decorators for command parameters
*/
namespace args {
/**
* String argument
* @param options - Argument configuration
*/
function string(options?: ArgumentOptions): PropertyDecorator;
/**
* Number argument
* @param options - Argument configuration
*/
function number(options?: ArgumentOptions): PropertyDecorator;
/**
* Boolean argument
* @param options - Argument configuration
*/
function boolean(options?: ArgumentOptions): PropertyDecorator;
/**
* Spread arguments (array)
* @param options - Argument configuration
*/
function spread(options?: ArgumentOptions): PropertyDecorator;
}
/**
* Flag decorators for command options
*/
namespace flags {
/**
* String flag
* @param options - Flag configuration
*/
function string(options?: FlagOptions): PropertyDecorator;
/**
* Number flag
* @param options - Flag configuration
*/
function number(options?: FlagOptions): PropertyDecorator;
/**
* Boolean flag
* @param options - Flag configuration
*/
function boolean(options?: FlagOptions): PropertyDecorator;
/**
* Array flag
* @param options - Flag configuration
*/
function array(options?: FlagOptions): PropertyDecorator;
}
/**
* CLI helpers for command interaction
*/
namespace cliHelpers {
/**
* Display spinner during async operation
* @param text - Spinner text
*/
function spinner(text: string): SpinnerContract;
/**
* Display table of data
* @param data - Table data
* @param options - Table options
*/
function table(data: any[], options?: TableOptions): void;
/**
* Display list of items
* @param items - List items
* @param options - List options
*/
function list(items: string[], options?: ListOptions): void;
}AdonisJS Core includes several built-in commands for development workflows.
/**
* Built-in command classes available in AdonisJS Core
*/
/** Start development server */
class ServeCommand extends BaseCommand {
static commandName = "serve";
static description = "Start the development server";
}
/** Build application for production */
class BuildCommand extends BaseCommand {
static commandName = "build";
static description = "Build the application for production";
}
/** Run application tests */
class TestCommand extends BaseCommand {
static commandName = "test";
static description = "Run the application test suite";
}
/** Start interactive REPL */
class ReplCommand extends BaseCommand {
static commandName = "repl";
static description = "Start the application REPL";
}
/** Add and configure packages */
class AddCommand extends BaseCommand {
static commandName = "add";
static description = "Add packages to the application";
}
/** Generate application encryption key */
class GenerateKeyCommand extends BaseCommand {
static commandName = "generate:key";
static description = "Generate application encryption key";
}Usage Examples:
// Running built-in commands
import { Ignitor } from "@adonisjs/core";
const ignitor = new Ignitor(new URL("./", import.meta.url));
// Start development server
const ace = ignitor.ace();
await ace.handle(["serve", "--watch"]);
// Run tests
await ace.handle(["test"]);
// Start REPL
await ace.handle(["repl"]);interface CommandOptions {
/** Whether command should keep the application alive */
staysAlive?: boolean;
/** Whether command should start the application */
startApp?: boolean;
}
interface ArgumentOptions {
description?: string;
required?: boolean;
}
interface FlagOptions {
description?: string;
alias?: string;
default?: any;
required?: boolean;
}
interface ParsedOutput {
args: any[];
flags: Record<string, any>;
nodeArgs: string[];
}
interface UIPrimitives {
logger: Logger;
colors: Colors;
icons: Icons;
instructions: Instructions;
}
interface PromptContract {
ask(question: string): Promise<string>;
confirm(question: string): Promise<boolean>;
choice(question: string, choices: string[]): Promise<string>;
multiple(question: string, choices: string[]): Promise<string[]>;
}
interface SpinnerContract {
start(): void;
stop(): void;
succeed(text?: string): void;
fail(text?: string): void;
update(text: string): void;
}
interface TableOptions {
head?: string[];
colWidths?: number[];
}
interface ListOptions {
bullet?: string;
indent?: number;
}
interface ErrorHandler {
render(error: Error, kernel: Kernel): Promise<void>;
}
// Codemods-related types
interface EnvValidationNode {
variables: Record<string, string>;
}
interface MiddlewareNode {
path: string;
position?: 'before' | 'after';
positionAt?: string;
}
interface BouncerPolicyNode {
name: string;
path: string;
}
// External types from @adonisjs/assembler
interface CodeTransformer {
updateRcFile: (...args: any[]) => void;
addVitePlugin: (...args: any[]) => void;
addJapaPlugin: (...args: any[]) => void;
}