Commands in doc-kit are defined as modules that export a command object conforming to the Command interface:
interface Command {
name: string;
description: string;
options: { [key: string]: Option };
action: (options: any) => Promise<void>;
}Each command consists of:
- name: The command name used in the CLI (e.g.,
generate,interactive) - description: A short description shown in help text
- options: An object mapping option names to their definitions
- action: The async function that executes when the command is run
Create a new file in bin/commands/ with your command name:
// bin/commands/my-command.mjs
import logger from '../../src/logger/index.mjs';
/**
* @type {import('./types').Command}
*/
export default {
name: 'my-command',
description: 'Does something useful',
options: {
// Define your options here (see next section)
},
async action(opts) {
logger.info('Starting my-command', opts);
// Your command logic here
logger.info('Completed my-command');
},
};Add your command to the exports in bin/commands/index.mjs:
import generate from './generate.mjs';
import interactive from './interactive.mjs';
import myCommand from './my-command.mjs'; // Add this
export default [
generate,
interactive,
myCommand, // Add this
];The CLI in packages/core/bin/cli.mjs automatically loads commands from bin/commands/index.mjs, so no changes are needed there if you followed step 2.
Options define the flags and parameters your command accepts. Each option has:
interface Option {
flags: string[]; // CLI flags (e.g., ['-i', '--input <value>'])
desc: string; // Description for help text
prompt?: PromptConfig; // Interactive mode configuration
}options: {
input: {
flags: ['-i', '--input <patterns...>'],
desc: 'Input file patterns (glob)',
prompt: {
type: 'text',
message: 'Enter input glob patterns',
variadic: true,
required: true,
},
},
force: {
flags: ['-f', '--force'],
desc: 'Force overwrite existing files',
prompt: {
type: 'confirm',
message: 'Overwrite existing files?',
initialValue: false,
},
},
mode: {
flags: ['-m', '--mode <mode>'],
desc: 'Operation mode',
prompt: {
type: 'select',
message: 'Choose operation mode',
options: [
{ label: 'Fast', value: 'fast' },
{ label: 'Thorough', value: 'thorough' },
],
},
},
}<value>- Required argument[value]- Optional argument<values...>- Variadic (multiple values)[values...]- Optional variadic
Single-line text input.
prompt: {
type: 'text',
message: 'Enter a value',
initialValue: 'default',
required: true,
}Yes/no confirmation.
prompt: {
type: 'confirm',
message: 'Are you sure?',
initialValue: false,
}Single choice from a list.
prompt: {
type: 'select',
message: 'Choose one',
options: [
{ label: 'Option 1', value: 'opt1' },
{ label: 'Option 2', value: 'opt2' },
],
}Multiple choices from a list.
prompt: {
type: 'multiselect',
message: 'Choose multiple',
options: [
{ label: 'Choice A', value: 'a' },
{ label: 'Choice B', value: 'b' },
],
}The interactive command automatically uses the prompt configuration from your options. When users run:
doc-kit interactiveThey'll be prompted to select a command, then guided through all required options.
- message: Question to ask the user
- type: Input type (
text,confirm,select,multiselect) - required: Whether the field must have a value
- initialValue: Default value
- variadic: Whether multiple values can be entered (for
texttype) - options: Choices for
select/multiselecttypes
Always provide helpful messages and sensible defaults:
threads: {
flags: ['-p', '--threads <number>'],
desc: 'Number of threads to use (minimum: 1)',
prompt: {
type: 'text',
message: 'How many threads to allow',
initialValue: String(cpus().length), // Smart default
},
},