The interactive question system provides custom prompts with fuzzy search, character limits, and validation for gathering commit information through user interaction.
/**
* Run interactive questions to collect commit information
* @param state - Application state with configuration and answers
* @param cliAnswers - Pre-filled answers from CLI arguments (optional)
* @returns Promise resolving to collected answers object
*/
async function runInteractiveQuestions(
state: State,
cliAnswers?: Partial<Answers>
): Promise<Answers>;Updates the state object with user responses and returns the complete answers.
/**
* Create filtered questions based on state and CLI answers
* @param state - Application state with configuration
* @param cliAnswers - Answers already provided via CLI
* @returns Array of inquirer question objects ready for prompting
*/
function createQuestions(state: State, cliAnswers: Partial<Answers>): Question[];Filters out questions that already have answers from CLI arguments.
/**
* Populate state with answers for non-interactive execution
* @param state - Application state to update
* @param answers - Object containing answer values with defaults
*/
function runNonInteractiveMode(
state: State,
answers: { type?: string; subject?: string; [key: string]: any }
): void;Default values: type: "chore", subject: "automated commit"
Provides fuzzy searchable autocomplete for commit types with emoji previews.
// Question configuration for type selection
const typeQuestion = {
type: 'autocomplete',
name: 'type',
message: 'Select the type of change that you\'re committing:',
source: (answers, input) => Promise<Array<{ name: string; value: string }>>
};Features:
disableEmoji configuration optionAutocomplete question for project scope selection (only shown if scopes are configured).
// Question configuration for scope selection
const scopeQuestion = {
type: 'autocomplete',
name: 'scope',
message: 'Select the scope this component affects:',
source: (answers, input) => Promise<string[]>
} | null;Returns null if no scopes are configured or scopes array is empty.
Character-limited input with live character counter and validation.
// Question configuration for commit subject
const subjectQuestion = {
type: 'limitedInput',
name: 'subject',
message: 'Write a short, imperative mood description of the change:',
maxLength: number, // config.maxMessageLength - 3 (for emoji)
leadingLabel: (answers) => string, // Shows type and scope prefix
validate: (input) => boolean | string,
filter: (input) => string // Trims and removes trailing periods
};Features:
Optional longer description input.
// Question configuration for commit body
const bodyQuestion = {
type: 'input',
name: 'body',
message: 'Provide a longer description of the change:\n '
};Input for describing breaking changes.
// Question configuration for breaking changes
const breakingQuestion = {
type: 'input',
name: 'breaking',
message: 'Describe the breaking changes:\n '
};Input for linking GitHub issues.
// Question configuration for issues
const issuesQuestion = {
type: 'input',
name: 'issues',
message: 'Add issue references (e.g. "fix #123", "re #123"):\n '
};Multi-select checkbox for affected packages in Lerna monorepos.
// Question configuration for Lerna packages
const lernaQuestion = {
type: 'checkbox',
name: 'lerna',
message: 'Select the packages this commit affects:',
choices: string[] // Package names from Lerna workspace
} | null;Only shown in Lerna monorepo environments with detected packages.
Custom prompt extending inquirer's InputPrompt with character limits and visual feedback.
/**
* Custom input prompt with character limit and visual feedback
*/
class LimitedInputPrompt extends InputPrompt {
constructor(options: {
maxLength: number;
leadingLabel?: string | ((answers: any) => string);
message: string;
name: string;
validate?: (input: string) => boolean | string;
filter?: (input: string) => string;
});
/** Calculate remaining characters based on current input */
remainingChar(): number;
/** Handle keypress events with length enforcement */
onKeypress(): void;
/** Get colored text showing remaining characters */
getCharsLeftText(): string;
/** Render prompt with character counter and leading label */
render(error?: string): void;
}Visual Features:
const createState = require('git-cz/lib/createState');
const runInteractiveQuestions = require('git-cz/lib/runInteractiveQuestions');
async function collectCommitInfo() {
const state = createState();
// Run interactive prompts
const answers = await runInteractiveQuestions(state);
console.log('Collected answers:', answers);
// {
// type: 'feat',
// scope: 'auth',
// subject: 'add OAuth integration',
// body: 'Implemented OAuth 2.0 flow',
// breaking: '',
// issues: '#123',
// lerna: ''
// }
}const createState = require('git-cz/lib/createState');
const runInteractiveQuestions = require('git-cz/lib/runInteractiveQuestions');
async function collectWithDefaults() {
const state = createState();
// Pre-fill some answers
const cliAnswers = {
type: 'fix',
scope: 'api'
};
// Only prompts for remaining questions
const answers = await runInteractiveQuestions(state, cliAnswers);
console.log('Final answers:', answers);
// Will only prompt for subject, body, breaking, issues, lerna
}const createState = require('git-cz/lib/createState');
const runNonInteractiveMode = require('git-cz/lib/runNonInteractiveMode');
function automatedCommit() {
const state = createState();
// Set answers without prompting
runNonInteractiveMode(state, {
type: 'chore',
subject: 'update dependencies',
body: 'Updated all package dependencies to latest versions'
});
console.log('State updated:', state.answers);
}const createQuestions = require('git-cz/lib/createQuestions');
function getFilteredQuestions() {
const state = createState();
// Skip type and scope questions
const cliAnswers = {
type: 'feat',
scope: 'ui'
};
const questions = createQuestions(state, cliAnswers);
// Returns questions for: subject, body, breaking, issues, lerna
console.log('Questions to ask:', questions.map(q => q.name));
}