or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cli-interface.mdconfiguration.mdcore-api.mdindex.mdvalidation-rules.md
tile.json

configuration.mddocs/

Configuration

Flexible configuration system supporting multiple formats, shareable presets, and extensible rules. Includes built-in configurations for popular project types and development workflows.

Capabilities

Configuration File Formats

Commitlint supports multiple configuration file formats with automatic discovery.

// commitlint.config.js (recommended)
module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [2, 'always', ['feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore']],
    'subject-max-length': [2, 'always', 72]
  }
};

// .commitlintrc.js
module.exports = { /* config */ };

// .commitlintrc.json
{
  "extends": ["@commitlint/config-conventional"],
  "rules": { /* rules */ }
}

// .commitlintrc.yml
extends:
  - '@commitlint/config-conventional'
rules:
  type-enum: [2, 'always', ['feat', 'fix']]

// package.json
{
  "commitlint": {
    "extends": ["@commitlint/config-conventional"]
  }
}

Configuration Schema

Complete configuration interface with all supported options.

interface UserConfig {
  extends?: string | string[];              // Shareable configurations to extend
  formatter?: string;                       // Custom formatter module
  rules?: Partial<RulesConfig>;            // Rule configuration object
  parserPreset?: string | ParserPreset | Promise<ParserPreset>; // Parser preset
  ignores?: ((commit: string) => boolean)[]; // Custom ignore functions
  defaultIgnores?: boolean;                 // Use default ignores (default: true)
  plugins?: (string | Plugin)[];           // Plugin modules
  helpUrl?: string;                        // Help URL for error messages
  prompt?: UserPromptConfig;               // Interactive prompt configuration
}

interface ParserPreset {
  name?: string;                           // Preset name
  path?: string;                           // Preset path
  parserOpts?: ParserOptions;              // Parser options
}

interface ParserOptions {
  commentChar?: string;                    // Comment character (default: #)
  fieldPattern?: RegExp;                   // Field parsing pattern
  headerCorrespondence?: string[];         // Header field correspondence
  headerPattern?: RegExp;                  // Header parsing pattern
  issuePrefixes?: string[];                // Issue prefixes (#, etc.)
  mergeCorrespondence?: string[];          // Merge field correspondence
  mergePattern?: RegExp;                   // Merge parsing pattern
  noteKeywords?: string[];                 // Keywords for notes (BREAKING CHANGE, etc.)
  revertCorrespondence?: string[];         // Revert field correspondence
  revertPattern?: RegExp;                  // Revert parsing pattern
}

Built-in Configuration Presets

Ready-to-use configuration presets for popular project types and conventions.

// @commitlint/config-conventional - Standard conventional commits
{
  extends: ['@commitlint/config-conventional']
}

// @commitlint/config-angular - Angular commit convention
{
  extends: ['@commitlint/config-angular']
}

// @commitlint/config-lerna-scopes - Lerna workspace scopes
{
  extends: ['@commitlint/config-lerna-scopes']
}

// @commitlint/config-nx-scopes - Nx workspace scopes  
{
  extends: ['@commitlint/config-nx-scopes']
}

// Multiple presets
{
  extends: [
    '@commitlint/config-conventional',
    '@commitlint/config-lerna-scopes'
  ]
}

Usage Examples:

# Install conventional config
npm install --save-dev @commitlint/config-conventional

# Install Angular config
npm install --save-dev @commitlint/config-angular

# Install Lerna scopes config
npm install --save-dev @commitlint/config-lerna-scopes

Rule Configuration

Configure validation rules with severity levels and conditions.

// Rule configuration tuple format
type RuleConfigTuple<T> = 
  | Readonly<[RuleConfigSeverity.Disabled]>                    // Disable rule
  | Readonly<[RuleConfigSeverity, RuleConfigCondition]>        // Severity + condition
  | Readonly<[RuleConfigSeverity, RuleConfigCondition, T]>     // Severity + condition + value

enum RuleConfigSeverity {
  Disabled = 0,   // Rule is disabled
  Warning = 1,    // Rule produces warnings
  Error = 2,      // Rule produces errors
}

type RuleConfigCondition = 'always' | 'never';

// Rule configuration object
interface RulesConfig {
  // Type rules
  'type-case': RuleConfigTuple<TargetCaseType>;
  'type-empty': RuleConfigTuple<void>;
  'type-enum': RuleConfigTuple<string[]>;
  'type-max-length': RuleConfigTuple<number>;
  'type-min-length': RuleConfigTuple<number>;
  
  // Scope rules
  'scope-case': RuleConfigTuple<TargetCaseType>;
  'scope-empty': RuleConfigTuple<void>;
  'scope-enum': RuleConfigTuple<string[]>;
  'scope-max-length': RuleConfigTuple<number>;
  'scope-min-length': RuleConfigTuple<number>;
  
  // Subject rules
  'subject-case': RuleConfigTuple<TargetCaseType>;
  'subject-empty': RuleConfigTuple<void>;
  'subject-full-stop': RuleConfigTuple<string>;
  'subject-max-length': RuleConfigTuple<number>;
  'subject-min-length': RuleConfigTuple<number>;
  'subject-exclamation-mark': RuleConfigTuple<void>;
  
  // Header rules
  'header-case': RuleConfigTuple<TargetCaseType>;
  'header-full-stop': RuleConfigTuple<string>;
  'header-max-length': RuleConfigTuple<number>;
  'header-min-length': RuleConfigTuple<number>;
  'header-trim': RuleConfigTuple<void>;
  
  // Body rules
  'body-case': RuleConfigTuple<TargetCaseType>;
  'body-empty': RuleConfigTuple<void>;
  'body-full-stop': RuleConfigTuple<string>;
  'body-leading-blank': RuleConfigTuple<void>;
  'body-max-length': RuleConfigTuple<number>;
  'body-max-line-length': RuleConfigTuple<number>;
  'body-min-length': RuleConfigTuple<number>;
  
  // Footer rules
  'footer-empty': RuleConfigTuple<void>;
  'footer-leading-blank': RuleConfigTuple<void>;
  'footer-max-length': RuleConfigTuple<number>;
  'footer-max-line-length': RuleConfigTuple<number>;
  'footer-min-length': RuleConfigTuple<number>;
  
  // Other rules
  'references-empty': RuleConfigTuple<void>;
  'signed-off-by': RuleConfigTuple<string>;
  'trailer-exists': RuleConfigTuple<string>;
}

type TargetCaseType = 
  | 'camel-case'
  | 'kebab-case' 
  | 'snake-case'
  | 'pascal-case'
  | 'upper-case'
  | 'lower-case'
  | 'sentence-case'
  | 'start-case';

Configuration Examples:

// Basic rule configuration
module.exports = {
  rules: {
    'type-enum': [2, 'always', ['feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore']],
    'type-case': [2, 'always', 'lower-case'],
    'type-empty': [2, 'never'],
    'scope-case': [2, 'always', 'lower-case'],
    'subject-case': [2, 'always', 'sentence-case'],
    'subject-empty': [2, 'never'],
    'subject-max-length': [2, 'always', 72],
    'header-max-length': [2, 'always', 100],
    'body-leading-blank': [2, 'always'],
    'footer-leading-blank': [2, 'always']
  }
};

// Disable specific rules
module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'scope-empty': [0],           // Disable scope-empty rule
    'subject-case': [1, 'always', 'lower-case'], // Warning instead of error
    'body-max-line-length': [2, 'always', 80]    // Custom line length
  }
};

Parser Preset Configuration

Configure commit message parsing behavior.

// Using string preset name
module.exports = {
  parserPreset: 'conventional-changelog-conventionalcommits'
};

// Using preset object
module.exports = {
  parserPreset: {
    name: 'conventional-changelog-conventionalcommits',
    parserOpts: {
      noteKeywords: ['BREAKING CHANGE', 'BREAKING CHANGES', 'DEPRECATED'],
      referenceActions: ['close', 'closes', 'closed', 'fix', 'fixes', 'fixed', 'resolve', 'resolves', 'resolved'],
      issuePrefixes: ['#', 'gh-'],
      noteKeywords: ['BREAKING CHANGE', 'BREAKING CHANGES']
    }
  }
};

// Custom parser preset
module.exports = {
  parserPreset: {
    parserOpts: {
      headerPattern: /^(\w*)(?:\((.*)\))?: (.*)$/,
      headerCorrespondence: ['type', 'scope', 'subject'],
      noteKeywords: ['BREAKING CHANGE', 'BREAKING-CHANGE'],
      revertPattern: /^(?:Revert|revert:)\s"?([\s\S]+?)"?\s*This reverts commit (\w*)\./i,
      revertCorrespondence: ['header', 'hash']
    }
  }
};

Ignore Patterns

Configure which commits should be ignored during linting.

module.exports = {
  // Custom ignore functions
  ignores: [
    (message) => message.includes('[skip]'),
    (message) => message.includes('WIP:'),
    (message) => /^Merge branch/.test(message),
    (message) => /^Revert/.test(message)
  ],
  
  // Disable default ignores
  defaultIgnores: false  // Default: true
};

// Default ignores include:
// - Merge commits
// - Revert commits  
// - Fixup commits
// - Squash commits

Plugin System

Extend commitlint with custom plugins.

// Using plugin modules
module.exports = {
  plugins: [
    'commitlint-plugin-function-rules',
    '@commitlint/plugin-help-wanted'
  ],
  rules: {
    'function-rules/type-enum': [2, 'always', ['feat', 'fix']]
  }
};

// Custom plugin object
const customPlugin = {
  rules: {
    'custom-rule': (parsed, when, value) => {
      // Custom rule implementation
      return [true, 'Custom rule message'];
    }
  }
};

module.exports = {
  plugins: [customPlugin],
  rules: {
    'custom-rule': [2, 'always', 'some-value']
  }
};

Formatter Configuration

Configure output formatting.

module.exports = {
  formatter: '@commitlint/format',  // Default formatter
  // or custom formatter
  formatter: './custom-formatter.js'
};

// Custom formatter implementation
module.exports = (report, options) => {
  const {results} = report;
  return results
    .map(result => `${result.valid ? 'βœ“' : 'βœ—'} ${result.input}`)
    .join('\n');
};

Environment-Specific Configuration

Configure commitlint for different environments.

const isCI = process.env.CI === 'true';

module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'subject-max-length': [2, 'always', isCI ? 50 : 72],
    'body-max-line-length': [isCI ? 2 : 1, 'always', 80]
  },
  helpUrl: isCI 
    ? 'https://ci-docs.example.com/commit-guidelines'
    : 'https://docs.example.com/commit-guidelines'
};

Monorepo Configuration

Configure commitlint for monorepo projects.

// Lerna configuration
module.exports = {
  extends: [
    '@commitlint/config-conventional',
    '@commitlint/config-lerna-scopes'
  ]
};

// Nx configuration  
module.exports = {
  extends: [
    '@commitlint/config-conventional', 
    '@commitlint/config-nx-scopes'
  ]
};

// Custom scope configuration
module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'scope-enum': [2, 'always', [
      'api',
      'web',
      'mobile',
      'shared',
      'docs',
      'ci'
    ]]
  }
};

Interactive Prompt Configuration

Configure interactive commit message prompting.

module.exports = {
  prompt: {
    messages: {
      skip: ':skip',
      max: 'upper %d chars',
      min: '%d chars at least',
      emptyWarning: 'can not be empty',
      upperLimitWarning: 'over limit',
      lowerLimitWarning: 'below limit'
    },
    questions: {
      type: {
        description: "Select the type of change that you're committing:",
        enum: {
          feat: {
            description: 'A new feature',
            title: 'Features',
            emoji: '✨',
          },
          fix: {
            description: 'A bug fix',
            title: 'Bug Fixes', 
            emoji: 'πŸ›',
          }
        }
      },
      scope: {
        description: 'What is the scope of this change (e.g. component or file name)'
      },
      subject: {
        description: 'Write a short, imperative tense description of the change'
      },
      body: {
        description: 'Provide a longer description of the change'
      },
      isBreaking: {
        description: 'Are there any breaking changes?',
        default: false
      },
      breakingBody: {
        description: 'A BREAKING CHANGE commit requires a body. Please enter a longer description of the commit itself'
      },
      breaking: {
        description: 'Describe the breaking changes'
      },
      isIssueAffected: {
        description: 'Does this change affect any open issues?',
        default: false
      },
      issuesBody: {
        description: 'If issues are closed, the commit requires a body. Please enter a longer description of the commit itself'
      },
      issues: {
        description: 'Add issue references (e.g. "fix #123", "re #123".)'
      }
    }
  }
};