or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cli.mdcommitizen.mdconfiguration.mdformatting.mdindex.mdquestions.mdutilities.md
tile.json

questions.mddocs/

Interactive Questions

The interactive question system provides custom prompts with fuzzy search, character limits, and validation for gathering commit information through user interaction.

Capabilities

Question Runner

/**
 * 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.

Question Factory

/**
 * 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.

Non-Interactive Mode

/**
 * 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"

Question Types

Commit Type Selection

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:

  • Fuzzy search through commit type names
  • Displays emoji, type, and description in selection list
  • Respects disableEmoji configuration option

Scope Selection

Autocomplete 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.

Subject Input

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:

  • Real-time character counter with color coding (green > 15, yellow > 5, red ≤ 5)
  • Shows commit type and scope as leading label
  • Validates minimum length requirement
  • Auto-trims whitespace and removes trailing periods

Body Input

Optional longer description input.

// Question configuration for commit body
const bodyQuestion = {
  type: 'input',
  name: 'body',
  message: 'Provide a longer description of the change:\n '
};

Breaking Changes Input

Input for describing breaking changes.

// Question configuration for breaking changes
const breakingQuestion = {
  type: 'input', 
  name: 'breaking',
  message: 'Describe the breaking changes:\n '
};

Issues Input

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 '
};

Lerna Package Selection

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 Components

Limited Input Prompt

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:

  • Character counter with progress bar
  • Color-coded remaining characters (green/yellow/red)
  • Leading label showing commit type and scope context
  • Real-time input length enforcement

Usage Examples

Basic Interactive Flow

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: ''
  // }
}

Pre-filled Answers

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
}

Non-Interactive Usage

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);
}

Custom Question Creation

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));
}