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

utilities.mddocs/

Utilities

Helper functions for CLI argument parsing, non-interactive mode, git operations, and Lerna integration.

Capabilities

CLI Argument Parsing

Parse command-line arguments for both interactive and non-interactive modes with git pass-through support.

/**
 * Parse command-line arguments into categorized objects
 * @returns Object with parsed CLI options, answers, and git pass-through parameters
 */
function parseArgs(): {
  cliAnswers: Partial<Answers>;
  cliOptions: CLIOptions;
  passThroughParams: Record<string, string | boolean>;
};

interface CLIOptions {
  /** Disable emoji in commit messages */
  disableEmoji?: boolean;
  /** Preview mode without executing git commit */
  dryRun?: boolean;
  /** Custom format template string */
  format?: string;
  /** Show help screen and exit */
  help?: boolean;
  /** Git hook mode - exit after writing message file */
  hook?: boolean;
  /** Run in non-interactive mode */
  nonInteractive?: boolean;
  /** Show version and exit */
  version?: boolean;
}

Supported CLI Options:

  • -h, --help - Display usage information and exit
  • -v, --version - Print version information and exit
  • --disable-emoji - Disable emoji in commit messages
  • --format - Custom formatting template for commit messages
  • --non-interactive - Run without interactive prompts
  • --dry-run - Preview mode showing what would be executed
  • --hook - Git hook mode (exits after writing commit message file)

Non-Interactive Mode Options:

  • --type - Commit type (defaults to "chore")
  • --subject - Commit message (defaults to "automated commit")
  • --scope - Optional semantic commit scope
  • --body - Extended commit description
  • --breaking - Breaking changes description
  • --issues - GitHub issues references (e.g., "#123")
  • --lerna - Lerna mono-repo packages affected

Pass-Through Parameters: All unrecognized arguments are passed through to the underlying git commit command.

Non-Interactive Mode

Execute git-cz without interactive prompts using predefined answer values.

/**
 * Populate application state with answers for automated execution
 * @param state - Application state object to modify
 * @param answers - Answer values with automatic defaults
 */
function runNonInteractiveMode(
  state: State, 
  answers: NonInteractiveAnswers
): void;

interface NonInteractiveAnswers {
  /** Commit type - defaults to "chore" if not provided */
  type?: string;
  /** Commit subject - defaults to "automated commit" if not provided */
  subject?: string;
  /** Optional commit scope */
  scope?: string;
  /** Optional extended description */
  body?: string;
  /** Optional breaking changes description */
  breaking?: string;
  /** Optional GitHub issues references */
  issues?: string;
  /** Optional Lerna packages affected */
  lerna?: string;
}

Default Values:

  • type: "chore"
  • subject: "automated commit"
  • All other fields default to empty strings

Updates the provided state object in-place with the answer values.

Git Repository Utilities

Helper functions for git repository operations and path resolution.

/**
 * Get the root directory of the current git repository
 * @returns Absolute path to the git repository root directory
 * @throws Error if current directory is not in a git repository
 */
function getGitRootDir(): string;

/**
 * Get the .git directory path for the current repository
 * @returns Absolute path to the .git directory
 */
function getGitDir(): string;

Error Handling:

  • getGitRootDir() throws an Error with message "Could not find Git root folder." if not in a git repository
  • getGitDir() uses the git root directory to construct the .git path

Usage in git-cz:

  • getGitRootDir() is used during state creation to establish the working directory
  • getGitDir() is used to write the COMMIT_EDITMSG file for git commit

Lerna Monorepo Integration

Utilities for detecting and working with Lerna monorepo environments.

/**
 * Lerna utilities for monorepo package management
 */
interface LernaUtils {
  /**
   * Check if the current project is a Lerna monorepo
   * @param state - Application state with root directory
   * @returns True if Lerna configuration is detected
   */
  isLerna(state: State): boolean;

  /**
   * Get all packages in the Lerna monorepo
   * @param state - Application state with root directory
   * @returns Array of package names found in the workspace
   */
  getAllPackages(state: State): string[];

  /**
   * Get packages with uncommitted changes in the Lerna monorepo
   * @param state - Application state with root directory
   * @returns Array of package names with detected changes
   */
  getChangedPackages(state: State): string[];
}

// Import individual functions
const { isLerna, getAllPackages, getChangedPackages } = require("git-cz/lib/util/lerna");

Lerna Detection:

  • Looks for lerna.json configuration file in the repository root
  • Checks for workspaces configuration in package.json
  • Returns false if no Lerna setup is detected

Package Discovery:

  • getAllPackages() scans workspace directories for package.json files
  • getChangedPackages() uses git status to identify packages with modifications
  • Both functions return package names, not directory paths

Usage Examples

Basic CLI Parsing

const parseArgs = require('git-cz/lib/parseArgs');

// Parse current process arguments
const { cliAnswers, cliOptions, passThroughParams } = parseArgs();

console.log('CLI Options:', cliOptions);
// { nonInteractive: true, disableEmoji: false, dryRun: true }

console.log('Pre-filled Answers:', cliAnswers);
// { type: 'feat', subject: 'add new feature', scope: 'auth' }

console.log('Git Pass-through:', passThroughParams);
// { amend: true, 'allow-empty': true }

Non-Interactive Automation

const createState = require('git-cz/lib/createState');
const runNonInteractiveMode = require('git-cz/lib/runNonInteractiveMode');
const formatCommitMessage = require('git-cz/lib/formatCommitMessage');

// Automated commit workflow
const state = createState();

runNonInteractiveMode(state, {
  type: 'fix',
  scope: 'auth',
  subject: 'resolve token refresh issue',
  body: 'Fixed OAuth token refresh timing bug that caused authentication failures',
  issues: '#456'
});

const message = formatCommitMessage(state);
console.log(message);
// fix(auth): 🐛 resolve token refresh issue
//
// Fixed OAuth token refresh timing bug that caused authentication failures
//
// ✅ Closes: #456

Git Repository Operations

const getGitRootDir = require('git-cz/lib/util/getGitRootDir');
const getGitDir = require('git-cz/lib/util/getGitDir');

try {
  const rootDir = getGitRootDir();
  const gitDir = getGitDir();
  
  console.log('Repository root:', rootDir);
  // /Users/developer/projects/my-app
  
  console.log('Git directory:', gitDir);
  // /Users/developer/projects/my-app/.git
  
} catch (error) {
  console.error('Not in a git repository:', error.message);
}

Lerna Monorepo Detection

const createState = require('git-cz/lib/createState');
const { isLerna, getAllPackages, getChangedPackages } = require('git-cz/lib/util/lerna');

const state = createState();

if (isLerna(state)) {
  console.log('Lerna monorepo detected');
  
  const allPackages = getAllPackages(state);
  console.log('All packages:', allPackages);
  // ['@myorg/core', '@myorg/utils', '@myorg/cli', '@myorg/docs']
  
  const changedPackages = getChangedPackages(state);
  console.log('Changed packages:', changedPackages);
  // ['@myorg/core', '@myorg/utils']
  
} else {
  console.log('Not a Lerna monorepo');
}

Comprehensive CLI Tool Integration

const parseArgs = require('git-cz/lib/parseArgs');
const createState = require('git-cz/lib/createState');
const runNonInteractiveMode = require('git-cz/lib/runNonInteractiveMode');
const runInteractiveQuestions = require('git-cz/lib/runInteractiveQuestions');
const formatCommitMessage = require('git-cz/lib/formatCommitMessage');

async function customGitCz() {
  // Parse command line arguments
  const { cliAnswers, cliOptions, passThroughParams } = parseArgs();
  
  // Create application state
  const state = createState({
    disableEmoji: cliOptions.disableEmoji,
    format: cliOptions.format
  });
  
  // Handle interactive vs non-interactive mode
  if (cliOptions.nonInteractive) {
    runNonInteractiveMode(state, cliAnswers);
  } else {
    await runInteractiveQuestions(state, cliAnswers);
  }
  
  // Generate commit message
  const message = formatCommitMessage(state);
  
  if (cliOptions.dryRun) {
    console.log('Would commit with message:');
    console.log(message);
  } else {
    // Execute git commit with pass-through parameters
    console.log('Committing with message:', message);
  }
}

docs

cli.md

commitizen.md

configuration.md

formatting.md

index.md

questions.md

utilities.md

tile.json