CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-git-cz

Semantic emojified git commit CLI tool with interactive prompts and Commitizen integration

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

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

docs

cli.md

commitizen.md

configuration.md

formatting.md

index.md

questions.md

utilities.md

tile.json