@hyperfrontend/versioning/commits

commits/

Conventional commit parsing and models.

Overview

Parsing and models for the Conventional Commits specification. Uses state-machine tokenization for predictable O(n) performance.

Usage Examples

Parsing Commits

import { parseConventionalCommit, isConventionalCommit } from '@hyperfrontend/versioning'

// Parse a commit message
const commit = parseConventionalCommit('feat(api): add user endpoint')
console.log(commit.type) // 'feat'
console.log(commit.scope) // ['api']
console.log(commit.subject) // 'add user endpoint'

// Multi-scope headers produce multi-element arrays
const multi = parseConventionalCommit('feat(versioning,questions): add filter')
console.log(multi.scope) // ['versioning', 'questions']

// Scopeless commits produce an empty array
const scopeless = parseConventionalCommit('docs: update README')
console.log(scopeless.scope) // []

// Check format before parsing
if (isConventionalCommit(message)) {
  const parsed = parseConventionalCommit(message)
}

Breaking Changes

import { parseConventionalCommit } from '@hyperfrontend/versioning'

// Breaking change via !
const breaking1 = parseConventionalCommit('feat!: remove deprecated API')
console.log(breaking1.breaking) // true

// Breaking change via footer
const breaking2 = parseConventionalCommit(`fix: update signature

BREAKING CHANGE: The return type is now a Promise`)
console.log(breaking2.breaking) // true
console.log(breaking2.breakingDescription) // 'The return type is now a Promise'

Body and Footers

import { parseConventionalCommit } from '@hyperfrontend/versioning'

const commit = parseConventionalCommit(`feat(core): add validation

This adds input validation to all public methods.
Invalid inputs now throw descriptive errors.

Refs: ABC-123
Closes #456`)

console.log(commit.body)
// 'This adds input validation to all public methods.\nInvalid inputs now throw descriptive errors.'

console.log(commit.footers)
// [
//   { key: 'Refs', value: 'ABC-123', separator: ':' },
//   { key: 'Closes', value: '456', separator: ' #' }
// ]

Creating Commits

import { createConventionalCommit, createCommitFooter } from '@hyperfrontend/versioning'

const commit = createConventionalCommit('feat', 'add feature', {
  scope: ['api'],
  body: 'Detailed description',
  footers: [createCommitFooter('Refs', 'ABC-123'), createCommitFooter('Closes', '456', ' #')],
  breaking: true,
})

console.log(commit.raw)
// 'feat(api)!: add feature\n\nDetailed description\n\nRefs: ABC-123\nCloses #456'

// Multi-scope headers
const multi = createConventionalCommit('feat', 'shared change', { scope: ['versioning', 'questions'] })
console.log(multi.raw) // 'feat(versioning,questions): shared change'

Semver Integration

import { parseConventionalCommit, getSemverBump } from '@hyperfrontend/versioning'

const commit = parseConventionalCommit('feat: add feature')
const bump = getSemverBump(commit.type, commit.breaking)
console.log(bump) // 'minor'

const breaking = parseConventionalCommit('fix!: change API')
const breakingBump = getSemverBump(breaking.type, breaking.breaking)
console.log(breakingBump) // 'major'

Conventional Commits Format

<type>[optional scope][!]: <description>

[optional body]

[optional footer(s)]

Header

  • type: Describes the category of change (feat, fix, docs, etc.)
  • scope: Optional context in parentheses. Supports multi-scope headers such as feat(versioning,questions): ...; parsed into a readonly string[] (empty when no scope is present).
  • !: Optional breaking change indicator
  • description: Short summary of the change

Body

Free-form text separated from header by a blank line. Can span multiple paragraphs.

Footers

Token-based trailers in key: value or key #value format:

Refs: ABC-123
Fixes #456
BREAKING CHANGE: API signature changed

Security

  • No regex: All parsing uses character-by-character iteration
  • Input limits: 10KB maximum message length enforced
  • ReDoS safe: No regular expressions means no catastrophic backtracking

See Also

  • classify/ — Commit classification for changelog attribution
  • changelog/ — Generates entries from commits
  • flow/ — Analyzes commits to determine version bumps
  • semver/ — Version bumping based on commit types
  • Main README — Package overview and quick start
  • ARCHITECTURE.md — Design principles and data flow

API Reference

ƒ Functions

§function

allOf(...matchers: unknown): InfrastructureMatcher

Combines matchers with AND logic - returns true if ALL matchers match.

Parameters

NameTypeDescription
§...matchers
unknown
Matchers to combine

Returns

InfrastructureMatcher
Combined matcher

Example

Combining matchers with AND logic
const combined = allOf(
  scopeMatcher(['deps']),
  messageMatcher(['security'])
)
§function

anyOf(...matchers: unknown): InfrastructureMatcher

Combines matchers with OR logic - returns true if ANY matcher matches.

Parameters

NameTypeDescription
§...matchers
unknown
Matchers to combine

Returns

InfrastructureMatcher
Combined matcher

Example

Combining matchers with OR logic
const combined = anyOf(
  scopeMatcher(['ci', 'build']),
  messageMatcher(['[infra]']),
  custom((ctx) => ctx.scope.some((s) => s.startsWith('tool-')))
)
§function

buildInfrastructureMatcher(config: InfrastructureConfig): InfrastructureMatcher

Builds a combined matcher from infrastructure configuration.
Combines scope-based matching with any custom matcher using OR logic. Path-based matching is handled separately via git queries.

Parameters

NameTypeDescription
§config
InfrastructureConfig
Infrastructure configuration

Returns

InfrastructureMatcher
Combined matcher, or null if no matchers configured

Example

Building an infrastructure matcher
const matcher = buildInfrastructureMatcher({
  scopes: ['ci', 'build'],
  matcher: (ctx) => ctx.scope.some((s) => s.startsWith('tool-'))
})
§function

classifyCommit(input: CommitWithRaw, context: ClassificationContext): ClassifiedCommit

Classifies a single commit against a project.
Implements the hybrid classification strategy:
  1. Check scope match (fast path)
  2. Check file touch (validation/catch-all)
  3. Check dependency touch (indirect)
  4. Fallback to excluded

Parameters

NameTypeDescription
§input
CommitWithRaw
The commit to classify
§context
ClassificationContext
Classification context with project info

Returns

ClassifiedCommit
Classified commit with source attribution

Example

Classifying a single commit
const classified = classifyCommit(
  { commit: parsedCommit, raw: gitCommit },
  { projectScopes: ['versioning'], fileCommitHashes: new Set(['abc123']) }
)
§function

classifyCommits(commits: unknown, context: ClassificationContext): ClassificationResult

Classifies multiple commits against a project.

Parameters

NameTypeDescription
§commits
unknown
Array of commits to classify
§context
ClassificationContext
Classification context with project info

Returns

ClassificationResult
Classification result with all commits and summary

Example

Classifying multiple commits

const commits = [{ commit: parsedCommit, raw: gitCommit }]
const context = createClassificationContext(['auth'], fileHashes)
const result = classifyCommits(commits, context)
// => { commits: [...], included: [...], excluded: [...], summary: { total: 1, ... } }
§function

createClassificationContext(projectScopes: unknown, fileCommitHashes: ReadonlySet<string>, options?: ClassificationContextOptions): ClassificationContext

Creates a classification context from common inputs.

Parameters

NameTypeDescription
§projectScopes
unknown
Scopes that match the project
§fileCommitHashes
ReadonlySet<string>
Set of commit hashes that touched project files
§options?
ClassificationContextOptions
Additional context options

Returns

ClassificationContext
A ClassificationContext object

Example

Creating a classification context

const context = createClassificationContext(
  ['auth', 'lib-auth'],
  new Set(['abc123', 'def456']),
  { excludeScopes: ['release'] }
)
§function

createClassifiedCommit(commit: ConventionalCommit, raw: GitCommit, source: CommitSource, options?: CreateClassifiedCommitOptions): ClassifiedCommit

Creates a classified commit.

Parameters

NameTypeDescription
§commit
ConventionalCommit
The parsed conventional commit
§raw
GitCommit
The raw git commit
§source
CommitSource
How the commit relates to the project
§options?
CreateClassifiedCommitOptions
Additional classification options

Returns

ClassifiedCommit
A new ClassifiedCommit object

Example

Creating a classified commit

const commit = { type: 'feat', subject: 'add feature', footers: [], breaking: false, raw: '...' }
const raw = { hash: 'abc123', subject: 'feat: add feature', message: '...' }
const classified = createClassifiedCommit(commit, raw, 'direct-scope')
// => { commit, raw, source: 'direct-scope', include: true, preserveScope: false, ... }
§function

createEmptyClassificationSummary(): ClassificationSummary

Creates an empty classification summary.

Returns

ClassificationSummary
A new ClassificationSummary with all counts at zero

Example

Creating an empty classification summary

const summary = createEmptyClassificationSummary()
// => { total: 0, included: 0, excluded: 0, bySource: { 'direct-scope': 0, ... } }
§function

createMatchContext(commit: GitCommit, scope?: unknown): InfrastructureMatchContext

Creates match context from a git commit.
Extracts scope from conventional commit message if present.

Parameters

NameTypeDescription
§commit
GitCommit
Git commit to create context for
§scope?
unknown
Pre-parsed scope array (optional, saves re-parsing)

Returns

InfrastructureMatchContext
Match context for use with matchers

Example

Creating match context from a git commit

const commit = { hash: 'abc123', subject: 'chore(ci): update workflow', message: 'chore(ci): update workflow' }
createMatchContext(commit, ['ci'])
// => { commit, scope: ['ci'], subject: 'chore(ci): update workflow', message: 'chore(ci): update workflow' }
§function

deriveProjectScopes(options: DeriveProjectScopesOptions): unknown

Derives all scope variations that should match a project.
Given a project named 'lib-versioning' with package '@hyperfrontend/versioning', this generates variations like:
  • 'lib-versioning' (full project name)
  • 'versioning' (without lib- prefix)

Parameters

NameTypeDescription
§options
DeriveProjectScopesOptions
Project identification options

Returns

unknown
Array of scope strings that match this project

Examples

Deriving scopes for a library project
deriveProjectScopes({ projectName: 'lib-versioning', packageName: '@hyperfrontend/versioning' })
// Returns: ['lib-versioning', 'versioning']
Deriving scopes for an app project
deriveProjectScopes({ projectName: 'app-demo', packageName: 'demo-app' })
// Returns: ['app-demo', 'demo']
§function

evaluateInfrastructure(commit: GitCommit, matcher: InfrastructureMatcher, scope?: unknown): boolean

Evaluates a commit against an infrastructure matcher.

Parameters

NameTypeDescription
§commit
GitCommit
Git commit to evaluate
§matcher
InfrastructureMatcher
Matcher function to apply
§scope?
unknown
Pre-parsed scope (optional)

Returns

boolean
True if commit matches infrastructure criteria

Example

Evaluating a commit against infrastructure matcher

const commit = { hash: 'abc123', subject: 'chore(ci): update workflow', message: '...' }
const ciMatcher = (ctx) => ctx.scope.includes('ci')
evaluateInfrastructure(commit, ciMatcher, ['ci'])
// => true
§function

extractConventionalCommits(commits: unknown): unknown

Extracts conventional commits from classified commits for changelog generation.

Parameters

NameTypeDescription
§commits
unknown
Array of classified commits

Returns

unknown
Array of conventional commits

Example

Extracting conventional commits

const classified = classifyCommits(commits, context)
const conventional = extractConventionalCommits(classified.included)
// => [{ type: 'feat', subject: 'add login', ... }]
§function

filterIncluded(commits: unknown): unknown

Filters an array of classified commits to only included ones.

Parameters

NameTypeDescription
§commits
unknown
Array of classified commits

Returns

unknown
Only commits marked for inclusion

Example

Filtering for included commits

const classified = classifyCommits(commits, context)
const included = filterIncluded(classified.commits)
// => [{ commit, raw, source: 'direct-scope', include: true, ... }]
§function

messageMatcher(patterns: unknown): InfrastructureMatcher

Creates a matcher that checks if commit message contains any of the given patterns.

Parameters

NameTypeDescription
§patterns
unknown
Patterns to search for in commit message (case-insensitive)

Returns

InfrastructureMatcher
Matcher that returns true if message contains any pattern

Example

Matching message patterns
const matcher = messageMatcher(['[infra]', '[ci skip]'])
§function

not(matcher: InfrastructureMatcher): InfrastructureMatcher

Negates a matcher - returns true if matcher returns false.

Parameters

NameTypeDescription
§matcher
InfrastructureMatcher
Matcher to negate

Returns

InfrastructureMatcher
Negated matcher

Example

Negating a matcher
const notRelease = not(scopeMatcher(['release']))
§function

scopeIsExcluded(commitScopes: unknown, excludeScopes: unknown): boolean

Checks if all scopes of a commit are in the exclude list.
A commit is excluded only when every scope entry matches an exclude scope. Commits with no scope entries are never considered excluded here.

Parameters

NameTypeDescription
§commitScopes
unknown
Scopes from a conventional commit
§excludeScopes
unknown
Array of scopes to exclude

Returns

boolean
True if every commit scope is in the exclude list

Example

Checking if a scope should be excluded

scopeIsExcluded(['release'], ['release', 'deps'])
// => true

scopeIsExcluded(['auth'], ['release', 'deps'])
// => false

scopeIsExcluded([], ['release'])
// => false

scopeIsExcluded(['release', 'auth'], ['release'])
// => false (not every scope is excluded)
§function

scopeMatcher(scopes: unknown): InfrastructureMatcher

Creates a matcher that checks if any commit scope matches any of the given scopes.

Parameters

NameTypeDescription
§scopes
unknown
Scopes to match against (case-insensitive)

Returns

InfrastructureMatcher
Matcher that returns true if any scope element matches

Example

Matching against specific scopes
const matcher = scopeMatcher(['ci', 'build', 'tooling'])
matcher({ scope: ['CI'], ... }) // true
matcher({ scope: ['feat'], ... }) // false
matcher({ scope: ['feat', 'ci'], ... }) // true (any element matches)
§function

scopeMatchesProject(commitScopes: unknown, projectScopes: unknown): boolean

Checks if any element of a commit's scope list matches any of the project scopes.
A commit matches the project when any of its scope entries matches a project scope. Empty commit scopes never match.

Parameters

NameTypeDescription
§commitScopes
unknown
Scopes from a conventional commit
§projectScopes
unknown
Array of scopes that match the project

Returns

boolean
True if at least one commit scope matches the project

Example

Matching scope to project
scopeMatchesProject(['versioning'], ['lib-versioning', 'versioning']) // true
scopeMatchesProject(['logging'], ['lib-versioning', 'versioning']) // false
scopeMatchesProject(['versioning', 'questions'], ['lib-questions']) // true
scopeMatchesProject([], ['lib-versioning']) // false
§function

scopePrefixMatcher(prefixes: unknown): InfrastructureMatcher

Creates a matcher that checks if any commit scope starts with any of the given prefixes.

Parameters

NameTypeDescription
§prefixes
unknown
Scope prefixes to match (case-insensitive)

Returns

InfrastructureMatcher
Matcher that returns true if any scope element starts with any prefix

Example

Matching prefixed scopes
const matcher = scopePrefixMatcher(['tool-', 'infra-'])
matcher({ scope: ['tool-package'], ... }) // true
matcher({ scope: ['lib-utils'], ... }) // false
§function

scopeRegexMatcher(pattern: RegExp): InfrastructureMatcher

Creates a matcher from a regex pattern tested against each scope element.

Parameters

NameTypeDescription
§pattern
RegExp
Regex pattern to test against scopes

Returns

InfrastructureMatcher
Matcher that returns true if any scope element matches the regex

Example

Matching with regex pattern
const matcher = scopeRegexMatcher(/^(ci|build|tool)-.+/)
§function

toChangelogCommit(classified: ClassifiedCommit): ConventionalCommit

Creates a modified conventional commit with scope handling based on classification.
For direct commits, the scope is removed (redundant in project changelog). For indirect commits, the scope is preserved (provides context).

Parameters

NameTypeDescription
§classified
ClassifiedCommit
Commit with classification metadata determining scope display

Returns

ConventionalCommit
A conventional commit with appropriate scope handling

Example

Converting classified commit for changelog

const classified = { commit: { type: 'feat', scope: ['auth'], subject: 'add login', ... }, source: 'direct-scope', preserveScope: false, ... }
toChangelogCommit(classified)
// => { type: 'feat', scope: [], subject: 'add login', ... }
§function

cancelled(error?: Error): StepResult

Helper for building a cancelled result with an optional error.

Parameters

NameTypeDescription
§error?
Error
Cause of cancellation attached to the result (omit when the user aborted cleanly)

Returns

StepResult
Step result that stops the session

Example

Cancelling after an executor throws

try { await executor() } catch (err) { return cancelled(err as Error) }
§function

countHeaderLength(draft: CommitDraft, subject: string): number

Computes the character length of the final header including the type(scope)!: prefix and the supplied subject. Powers the live 72-character countdown shown during the subject prompt.
The subject is passed separately (not read from draft.subject) because the caller typically has not yet committed the in-flight input to the draft.

Parameters

NameTypeDescription
§draft
CommitDraft
Draft supplying type, scope, and breaking marker
§subject
string
Subject text being typed

Returns

number
Character length the final header will occupy

Example

Counting a header mid-type

countHeaderLength({ type: 'feat', scope: ['core'] }, 'add login')
// => 'feat(core): add login'.length === 21
§function

createAuthorSession(options: CreateAuthorSessionOptions): AuthorSession

Prepares an authoring session without executing it. The returned object carries a resolved config (defaults filled in) and the effective step list — allowing bin wrappers to introspect before running.

Parameters

NameTypeDescription
§options
CreateAuthorSessionOptions
Optional overrides for steps and partial config
(default: {})

Returns

AuthorSession
Session description consumable by runAuthorSession

Examples

Using the conventional preset and default config

const session = createAuthorSession()
await runAuthorSession(session)

Overriding only the validate ruleset

createAuthorSession({ config: { validateRuleset: customRuleset } })
§function

createBreakingFromFooter(description: string): BreakingChange

Creates a breaking change from a footer.

Parameters

NameTypeDescription
§description
string
The description of the breaking change

Returns

BreakingChange
A BreakingChange object with source 'footer'

Example

Creating a breaking change from footer

createBreakingFromFooter('The config format has changed')
// => { isBreaking: true, description: 'The config format has changed', source: 'footer' }
§function

createBreakingFromSubject(description?: string): BreakingChange

Creates a breaking change from a subject indicator (!).

Parameters

NameTypeDescription
§description?
string
Optional description of the breaking change

Returns

BreakingChange
A BreakingChange object with source 'subject'

Example

Creating a breaking change from subject

createBreakingFromSubject('remove deprecated API')
// => { isBreaking: true, description: 'remove deprecated API', source: 'subject' }
§function

createCommitFooter(key: string, value: string, separator: ":" | " #"): CommitFooter

Creates a commit footer.

Parameters

NameTypeDescription
§key
string
Footer identifier such as 'Refs', 'Fixes', or 'BREAKING CHANGE'
§value
string
Associated content for the footer entry
§separator
":" | " #"
Delimiter between key and value (':' or ' #')
(default: ':')

Returns

CommitFooter
A new CommitFooter object

Example

Creating commit footers

createCommitFooter('Refs', '#123')
// => { key: 'Refs', value: '#123', separator: ':' }

createCommitFooter('Fixes', '456', ' #')
// => { key: 'Fixes', value: '456', separator: ' #' }
§function

createConventionalCommit(type: string, subject: string, options?: CreateConventionalCommitOptions): ConventionalCommit

Creates a conventional commit.

Parameters

NameTypeDescription
§type
string
The commit type (e.g., 'feat', 'fix')
§subject
string
The commit subject line
§options?
CreateConventionalCommitOptions
Optional configuration for scope, body, footers, etc.

Returns

ConventionalCommit
A new ConventionalCommit object

Example

Creating conventional commits

createConventionalCommit('feat', 'add user authentication')
// => { type: 'feat', subject: 'add user authentication', scope: [], footers: [], breaking: false, raw: 'feat: add user authentication' }

createConventionalCommit('fix', 'resolve memory leak', { scope: ['core'], breaking: true })
// => { type: 'fix', subject: 'resolve memory leak', scope: ['core'], breaking: true, ... }

createConventionalCommit('feat', 'add x', { scope: ['versioning', 'questions'] })
// => { ..., scope: ['versioning', 'questions'], raw: 'feat(versioning,questions): add x' }
§function

createNonBreaking(): BreakingChange

Creates a non-breaking change.

Returns

BreakingChange
A BreakingChange object indicating no breaking change

Example

Creating a non-breaking change

createNonBreaking()
// => { isBreaking: false, source: 'none' }
§function

createSessionContext(config: SessionConfig): SessionContext

Creates a fresh session context seeded with an empty draft.

Parameters

NameTypeDescription
§config
SessionConfig
Resolved session configuration

Returns

SessionContext
Session context ready for the first step

Example

Creating a bare context

createSessionContext(config)
// => { draft: {}, candidateScopes: [], defaultScope: undefined, config }
§function

defaultScope(candidates: unknown): string

Computes the default scope to pre-select in the scope step.
Algorithm (matches locked decision D3):
  1. A single candidate wins outright.
  2. Otherwise, if one candidate's path is a prefix of every other
candidate's path, that nearest common ancestor wins.
  1. Otherwise, there is no default.

Parameters

NameTypeDescription
§candidates
unknown
Scopes produced by discoverScopes

Returns

string
Scope name to pre-select, or undefined when no default is resolvable

Examples

Single owner wins

defaultScope([{ name: 'alpha', path: '/repo/libs/alpha' }])
// => 'alpha'

Common ancestor wins

defaultScope([
  { name: 'root', path: '/repo' },
  { name: 'alpha', path: '/repo/libs/alpha' },
])
// => 'root'

Disjoint ownership has no default

defaultScope([
  { name: 'alpha', path: '/repo/libs/alpha' },
  { name: 'beta', path: '/repo/libs/beta' },
])
// => undefined
§function

discoverScopes(stagedPaths: unknown, options: DiscoverScopesOptions): unknown

Resolves each staged path to its owning project by walking upward to the nearest project.json / package.json, reads the name field, and returns the unique set as DiscoveredScope entries. Entries inside node_modules or .git are dropped before walking; the caller's scopeFilter is applied after collection.

Parameters

NameTypeDescription
§stagedPaths
unknown
Paths emitted by the staged-paths provider (relative or absolute)
§options
DiscoverScopesOptions
Filter + cwd configuration

Returns

unknown
Unique scopes in staging order (first appearance wins)

Example

Discovering scopes for a set of staged files

discoverScopes(['libs/versioning/src/a.ts', 'libs/questions/src/b.ts'], { cwd: '/repo' })
// => [
//   { name: '@hyperfrontend/versioning', path: '/repo/libs/versioning' },
//   { name: '@hyperfrontend/questions', path: '/repo/libs/questions' },
// ]
§function

done(): StepResult

Helper for building a done result.

Returns

StepResult
Step result that advances the runner to the next step

Example

Returning done from a step

async run(): Promise<StepResult> { return done() }
§function

formatCommitMessage(draft: CommitDraft): string

Renders a draft as the final commit message string — the exact text that would be written to .git/COMMIT_EDITMSG. Layout: header, blank line, body, blank line, footers.
If draft.breaking and draft.breakingDescription are set and no BREAKING CHANGE:-family footer is already present, one is synthesized at the top of the footer block so the preview mirrors what a compliant parser will read back.

Parameters

NameTypeDescription
§draft
CommitDraft
Commit draft to render

Returns

string
Full commit message string with \n separators

Examples

Header only

formatCommitMessage({ type: 'feat', subject: 'add login' })
// => 'feat: add login'

Multi-scope breaking change with closing footer

formatCommitMessage({
  type: 'feat',
  scope: ['versioning', 'questions'],
  subject: 'add x',
  breaking: true,
  breakingDescription: 'removed Y',
  footers: [{ key: 'Closes', value: '#1', separator: ':' }],
})
// => 'feat(versioning,questions)!: add x\n\nBREAKING CHANGE: removed Y\nCloses: #1'
§function

formatHeader(draft: CommitDraft): string

Builds the header line (type(scope)!: subject) from a draft.
Missing fields render as empty — this is intentional so the header can be displayed incrementally during authoring (e.g. before the subject has been typed). Scopes are comma-joined to match the parser's multi-scope format.

Parameters

NameTypeDescription
§draft
CommitDraft
Draft to render (may be partial)

Returns

string
Header line; never contains a newline

Examples

Rendering a complete header

formatHeader({ type: 'feat', scope: ['core'], subject: 'add login' })
// => 'feat(core): add login'

Rendering a multi-scope breaking-change header

formatHeader({ type: 'feat', scope: ['versioning', 'questions'], subject: 'add x', breaking: true })
// => 'feat(versioning,questions)!: add x'

Rendering a partially-built draft mid-session

formatHeader({ type: 'fix' })
// => 'fix: '
§function

getSemverBump(type: string, breaking: boolean): "minor" | "patch" | "none" | "major"

Gets the semver bump level for a commit type. Returns 'none' for types that don't trigger a bump.

Parameters

NameTypeDescription
§type
string
The commit type
§breaking
boolean
Whether this is a breaking change

Returns

"minor" | "patch" | "none" | "major"
The semver bump level ('major', 'minor', 'patch', or 'none')

Example

Determining semver bump level

getSemverBump('feat', false)
// => 'minor'

getSemverBump('fix', true)
// => 'major'

getSemverBump('docs', false)
// => 'none'
§function

getStagedPaths(options: StagedPathsOptions): unknown

Default staged-paths provider. Shells out to git diff --cached --name-only -z, splits on NUL, and filters out the trailing empty entry. Returns paths relative to the git repository root (same as git's own output).

Parameters

NameTypeDescription
§options
StagedPathsOptions
Resolver options (cwd, optional timeout)

Returns

unknown
Staged file paths as emitted by git

Example

Reading the current staging area

getStagedPaths({ cwd: '/repo' })
// => ['libs/versioning/src/commits/author/index.ts']
§function

goto(stepId: string): StepResult

Helper for building a goto result pointing at the supplied step id.

Parameters

NameTypeDescription
§stepId
string
Target step id the runner should jump to

Returns

StepResult
Step result that redirects the runner to the named step

Example

Sending the runner back to the `type` step

return goto('type')
§function

isBreakingFooterKey(key: string): boolean

Checks if a footer key indicates a breaking change.

Parameters

NameTypeDescription
§key
string
The footer key to check

Returns

boolean
True if the key indicates a breaking change

Example

Checking if a footer key indicates breaking change

isBreakingFooterKey('BREAKING CHANGE')
// => true

isBreakingFooterKey('BREAKING-CHANGE')
// => true

isBreakingFooterKey('Refs')
// => false
§function

isConventionalCommit(message: string): boolean

Checks if a commit message follows conventional commit format.

Parameters

NameTypeDescription
§message
string
The commit message to check

Returns

boolean
true if the message appears to be a conventional commit

Example

Checking if a message is a conventional commit

isConventionalCommit('feat(auth): add OAuth login')
// => true

isConventionalCommit('WIP: still working on this')
// => false

isConventionalCommit('fix: resolve bug')
// => true
§function

isReleaseType(type: string): boolean

Checks if a commit type triggers a release.

Parameters

NameTypeDescription
§type
string
The commit type to check

Returns

boolean
True if the type triggers a release

Example

Checking for release-triggering types

isReleaseType('feat')
// => true

isReleaseType('chore')
// => false
§function

isStandardType(type: string): unknown

Checks if a commit type is a standard type.

Parameters

NameTypeDescription
§type
string
The commit type to check

Returns

unknown
True if the type is a standard conventional commit type

Example

Checking for standard commit types

isStandardType('feat')
// => true

isStandardType('custom')
// => false
§function

loadCommitConfig(options: LoadCommitConfigOptions): Promise<LoadedCommitConfig>

Loads the user's commit config. Resolution:
  1. overridePath wins when set
  2. Otherwise walk upward from cwd looking for one of CONFIG_FILE_NAMES
until a workspace boundary marker (.git, pnpm-workspace.yaml) is hit
  1. Missing config is not an error — config becomes {}

Parameters

NameTypeDescription
§options
LoadCommitConfigOptions
Search inputs

Returns

Promise<LoadedCommitConfig>
Loaded partial config plus the file it came from (if any)

Example

Auto-discovery from cwd

const { config, sourcePath } = await loadCommitConfig({ cwd: process.cwd() })
§function

normalizeSubject(raw: string): string

Applies subject normalisation rules (decision D10): trim edges and strip a single trailing period.

Parameters

NameTypeDescription
§raw
string
Subject string as entered by the user

Returns

string
Normalized subject

Example

Stripping whitespace and a trailing period

normalizeSubject('  add login flow.  ') // => 'add login flow'
§function

parseBody(lines: string[], startIndex: number): ParsedBody

Parses the body section of a commit message.
The body starts after the first blank line and continues until we encounter a footer (key: value or key #value pattern) or end of message.

Parameters

NameTypeDescription
§lines
string[]
All lines of the commit message
§startIndex
number
Index to start looking for body (after header)

Returns

ParsedBody
Parsed body or undefined if no body

Example

Parsing commit body

const lines = [
  'feat: add login',
  '',
  'Implements OAuth flow.',
  '',
  'Refs: #123'
]
const result = parseBody(lines, 1)
// => { body: 'Implements OAuth flow.', endIndex: 4 }
§function

parseConventionalCommit(message: string): ConventionalCommit

Parses a conventional commit message.

Parameters

NameTypeDescription
§message
string
The complete commit message

Returns

ConventionalCommit
Parsed ConventionalCommit object

Example

Parsing a complete conventional commit message

parseConventionalCommit('feat(auth): add login\n\nImplements OAuth.\n\nRefs: #123')
// => {
//   type: 'feat',
//   scope: ['auth'],
//   subject: 'add login',
//   body: 'Implements OAuth.',
//   footers: [{ key: 'Refs', value: '#123', separator: ':' }],
//   breaking: false,
//   raw: '...'
// }
§function

parseFooters(lines: string[], startIndex: number): ParsedFooters

Parses the footer section of a commit message.

Parameters

NameTypeDescription
§lines
string[]
All lines of the commit message
§startIndex
number
Index where footers start

Returns

ParsedFooters
Parsed footers

Example

Parsing commit footers

const lines = ['feat: add feature', '', 'Refs: #123', 'Fixes #456']
const result = parseFooters(lines, 2)
// => {
//   footers: [
//     { key: 'Refs', value: '#123', separator: ':' },
//     { key: 'Fixes', value: '456', separator: ' #' }
//   ],
//   breakingDescription: undefined
// }
§function

parseHeader(line: string): ParsedHeader

Parses a conventional commit header line.
Supports comma-separated multi-scope headers such as feat(a,b): x which produce a multi-element scope array. Single-scope headers produce a one-element array, and scopeless headers produce an empty array.

Parameters

NameTypeDescription
§line
string
The first line of the commit message

Returns

ParsedHeader
Parsed header with type, scope array, subject, and breaking flag

Example

Parsing conventional commit headers

parseHeader('feat(auth): add OAuth login')
// => { type: 'feat', scope: ['auth'], subject: 'add OAuth login', breaking: false }

parseHeader('fix!: critical security patch')
// => { type: 'fix', scope: [], subject: 'critical security patch', breaking: true }

parseHeader('feat(versioning,questions): add searchable select')
// => { type: 'feat', scope: ['versioning', 'questions'], subject: 'add searchable select', breaking: false }
§function

parseReferences(raw: string): unknown

Parses a free-form references string into issue footers. Accepts commas, semicolons, or whitespace between entries; ignores tokens that don't match the keyword #number shape.

Parameters

NameTypeDescription
§raw
string
Raw user input from the issues prompt

Returns

unknown
Footers matching each recognized reference

Example

Parsing a mixed references string

parseReferences('fixes #123, re #456')
// => [
//   { key: 'Fixes', value: '123', separator: ' #' },
//   { key: 'Re', value: '456', separator: ' #' },
// ]
§function

resolveSessionConfig(overrides: PartialSessionConfig): SessionConfig

Overlays a partial config over the built-in defaults, producing a fully populated SessionConfig usable by the runner.

Parameters

NameTypeDescription
§overrides
PartialSessionConfig
Partial config supplied by the caller (may be undefined)
(default: {})

Returns

SessionConfig
Fully resolved configuration

Example

Resolving with no overrides

resolveSessionConfig()
// => { types: DEFAULT_SESSION_TYPES, scopeOptional: false, ... }
§function

runAuthorSession(session: AuthorSession): Promise<SessionOutcome>

Executes the session step-by-step. Handles goto jumps, surfaces Ctrl-C cancellations as { status: 'cancelled' } outcomes, and — on success — returns the final formatted message alongside the committed status.

Parameters

NameTypeDescription
§session
AuthorSession
Session description produced by createAuthorSession

Returns

Promise<SessionOutcome>
Terminal outcome describing how the session ended

Example

Running a session to completion

const session = createAuthorSession({ config: { skipCommit: true } })
const outcome = await runAuthorSession(session)
// => { status: 'committed', message: 'feat: ...' }
§function

toDraft(commit: ConventionalCommit): CommitDraft

Promotes any ConventionalCommit to a CommitDraft. Useful for editing a parsed commit inside an authoring session.

Parameters

NameTypeDescription
§commit
ConventionalCommit
Parsed conventional commit

Returns

CommitDraft
A draft carrying the same fields as the commit

Example

Promoting a parsed commit to an editable draft

toDraft(parseConventionalCommit('feat: add login'))
// => { type: 'feat', scope: [], subject: 'add login', footers: [], breaking: false }
§function

typeToChoice(type: SessionType): Choice<string>

Maps a SessionType to a Choice usable by the select prompt.

Parameters

NameTypeDescription
§type
SessionType
Session type entry to render as a selectable choice

Returns

Choice<string>
Choice with the type name as both label and value, plus an optional hint

Example

Rendering the feat type as a select choice

typeToChoice({ name: 'feat', description: 'A new feature' })
// => { label: 'feat', value: 'feat', hint: 'A new feature' }
§function

validateCommit(commit: ConventionalCommit, ruleset: Ruleset): ValidationResult

Runs every rule configured in the ruleset against a parsed commit and aggregates the resulting warnings and errors.
Rules whose config is 'off' (or absent from the ruleset) are skipped. Unknown rule names in the ruleset are ignored — consumers extend the engine by calling validateCommitWithRules() and supplying additional rules.

Parameters

NameTypeDescription
§commit
ConventionalCommit
Parsed conventional commit to validate
§ruleset
Ruleset
Configuration map from rule name to [level, options?]

Returns

ValidationResult
Aggregated validation result

Example

Validating a commit against a preset ruleset

validateCommit(parseConventionalCommit('feat: add login'), conventionalPreset)
// => { valid: true, warnings: [], errors: [] }
§function

validateCommitMessage(raw: string, ruleset: Ruleset): ValidationResult

Parses a raw commit message and validates the resulting commit against the supplied ruleset. Used by the cl bin and anywhere else validation must start from a string rather than a parsed commit.

Parameters

NameTypeDescription
§raw
string
Raw commit message (as written to .git/COMMIT_EDITMSG)
§ruleset
Ruleset
Configuration map from rule name to [level, options?]

Returns

ValidationResult
Aggregated validation result

Example

Validating a raw commit message

validateCommitMessage('feat: add login', conventionalPreset)
// => { valid: true, warnings: [], errors: [] }

validateCommitMessage('feat: added login', conventionalPreset).warnings
// => [{ level: 'warn', ruleName: 'imperative-mood', message: ... }]
§function

validateCommitWithRules(commit: ConventionalCommit, ruleset: Ruleset, rules: Readonly<Record<string, Rule<never>>>): ValidationResult

Variant of validateCommit that accepts a caller-supplied rule registry. Useful for consumers that want to add project-specific rules without forking the built-in set.

Parameters

NameTypeDescription
§commit
ConventionalCommit
Parsed conventional commit to validate
§ruleset
Ruleset
Configuration map from rule name to [level, options?]
§rules
Readonly<Record<string, Rule<never>>>
Rule registry keyed by rule name

Returns

ValidationResult
Aggregated validation result

Example

Extending the built-in rules with a custom rule

const customRules = { ...BUILT_IN_RULES, 'no-wip': noWipRule }
validateCommitWithRules(commit, { 'no-wip': ['error'] }, customRules)

Interfaces

§interface

ClassificationContext

Classification context containing project and workspace info.

Properties

§readonly dependencyCommitMap?:ReadonlyMap<string, ReadonlySet<string>>
Map of dependency name to set of commit hashes touching that dependency
§readonly excludeScopes?:unknown
Scopes to always exclude
§readonly fileCommitHashes:ReadonlySet<string>
Set of commit hashes that touched project files
§readonly includeScopes?:unknown
Additional scopes to include as direct
§readonly infrastructureCommitHashes?:ReadonlySet<string>
Set of commit hashes that touched infrastructure paths. These commits will be classified as 'indirect-infra'.
§readonly projectScopes:unknown
Scopes that should be considered direct matches
§interface

ClassificationResult

Result of classifying multiple commits.

Properties

§readonly commits:unknown
All classified commits
§readonly excluded:unknown
Commits excluded from changelog
§readonly included:unknown
Commits to include in changelog
§readonly summary:ClassificationSummary
Summary statistics
§interface

ClassificationSummary

Summary statistics from classification.

Properties

§readonly bySource:Readonly<Record<CommitSource, number>>
Breakdown by source type
§readonly excluded:number
Commits excluded from changelog
§readonly included:number
Commits included in changelog
§readonly total:number
Total commits processed
§interface

ClassifiedCommit

A commit with classification metadata for changelog generation.
Contains the original commit data plus attribution information that determines inclusion and presentation in changelogs.

Properties

§readonly commit:ConventionalCommit
The parsed conventional commit
§readonly dependencyPath?:unknown
Dependency chain if indirect (e.g., ['lib-utils'] for lib-app → lib-utils)
§readonly include:boolean
Whether to include this commit in changelog
§readonly preserveScope:boolean
Whether to preserve scope in changelog output
§readonly raw:GitCommit
The raw git commit (for hash, date, etc.)
§readonly source:CommitSource
How this commit relates to the project
§readonly touchedFiles?:unknown
Files in this project touched by the commit (if applicable)
§interface

CommitWithRaw

Input for classification - a parsed commit with its raw git data.

Properties

§readonly commit:ConventionalCommit
The parsed conventional commit
§readonly raw:GitCommit
The raw git commit data
§interface

DeriveProjectScopesOptions

Options for deriving project scopes.

Properties

§readonly additionalScopes?:unknown
Additional scopes to include
§readonly packageName?:string
The npm package name (e.g., '@hyperfrontend/versioning')
§readonly prefixes?:unknown
Project name prefixes to strip for scope matching.
§readonly projectName:string
The project name (e.g., 'lib-versioning')
§interface

InfrastructureConfig

Configuration for building infrastructure commit sets.
Supports multiple detection methods that can be combined:
  • Path-based: Commits touching specific file paths
  • Scope-based: Commits with specific conventional scopes
  • Custom matcher: User-provided matching logic

Properties

§readonly matcher?:InfrastructureMatcher
Custom matcher function for complex logic. Combined with paths/scopes using OR logic.
§readonly paths?:unknown
File/directory paths that indicate infrastructure changes. Used to query git for commits touching these paths.
§readonly scopes?:unknown
Conventional commit scopes that indicate infrastructure. Matched against parsed commit scope.
§interface

InfrastructureMatchContext

Context provided to infrastructure matchers for decision making.
Contains information about a commit that helps determine whether it should be classified as infrastructure-related.

Properties

§readonly commit:GitCommit
The git commit being evaluated
§readonly message:string
Full commit message
§readonly scope:unknown
Parsed conventional scopes (empty array when the commit has no scope)
§readonly subject:string
Commit message subject
§interface

AuthorSession

Prepared session ready to be handed to runAuthorSession. Contains the fully resolved config and the ordered step list that will be executed.

Properties

§readonly config:SessionConfig
Fully resolved session configuration
§readonly steps:unknown
Ordered step list the runner will iterate
§interface

BreakingChange

Breaking change information.

Properties

§readonly description?:string
Description of the breaking change
§readonly isBreaking:boolean
Whether this is a breaking change
§readonly source:"none" | "subject" | "footer"
Source of the breaking change indicator
§interface

CommitDraft

In-progress version of a ConventionalCommit accumulated field-by-field during an interactive authoring session. Every field is optional so the formatter can render intermediate states (e.g. the header as it exists after only type has been picked).

Properties

§readonly body?:string
Full commit body
§readonly breaking?:boolean
Whether this is a breaking change — controls the ! subject marker
§readonly breakingDescription?:string
Breaking change description — surfaces as a BREAKING CHANGE: footer when none is already present
§readonly footers?:unknown
Footer trailers — caller may leave out BREAKING CHANGE:; the formatter will synthesize it when needed
§readonly scope?:unknown
Scopes in parentheses (empty or omitted = no scope)
§readonly subject?:string
Subject line
§readonly type?:string
Commit type (feat, fix, docs, etc.)
§interface

CommitFooter

Footer trailer in a conventional commit message

Properties

§readonly key:string
Footer key (e.g., "BREAKING CHANGE", "Refs", "Fixes")
§readonly separator:":" | " #"
Whether key used : or # separator
§readonly value:string
Footer value
§interface

ConventionalCommit

Parsed conventional commit message per https://www.conventionalcommits.org/en/v1.0.0/

Properties

§readonly body?:string
Full commit body
§readonly breaking:boolean
Whether this is a breaking change
§readonly breakingDescription?:string
Breaking change description (from footer or subject !)
§readonly footers:unknown
Parsed footer trailers
§readonly raw:string
Original raw message
§readonly scope:unknown
Scopes in parentheses (empty array when header has no scope)
§readonly subject:string
Subject line (after colon)
§readonly type:string
Commit type (feat, fix, docs, etc.)
§interface

CreateAuthorSessionOptions

Inputs accepted by createAuthorSession — the caller may supply their own step list; anything missing is resolved against the defaults used by the conventional preset.

Properties

§readonly config?:PartialSessionConfig
Partial configuration overlaid on the built-in defaults
§readonly steps?:unknown
Override for the step sequence; defaults to conventionalPreset
§interface

DiscoveredScope

Single discovered scope with the project root it came from.

Properties

§readonly name:string
Scope identifier (the project's name field)
§readonly path:string
Absolute path to the owning project root
§interface

DiscoverScopesOptions

Options controlling discoverScopes.

Properties

§readonly cwd:string
Working directory that staged paths are resolved against
§readonly scopeFilter?:(context: ScopeFilterContext) => boolean
Optional caller-provided filter; applied after built-in exclusions
§interface

HeaderMaxLengthOptions

Options for the header-max-length rule.

Properties

§readonly maxLength:number
Maximum allowed header length. Use null to disable the check.
§interface

ImperativeMoodOptions

Options for the imperative-mood rule.

Properties

§readonly wordlist?:Readonly<Record<string, string>>
Map of past-tense words (lowercase) to their suggested imperative forms. Overrides DEFAULT_IMPERATIVE_WORDLIST when provided.
§interface

LoadCommitConfigOptions

Inputs accepted by loadCommitConfig.

Properties

§readonly cwd:string
Directory to start the upward search from
§readonly overridePath?:string
Explicit override path from --config <path> — resolved against cwd when relative
§interface

LoadedCommitConfig

Return shape of loadCommitConfig.

Properties

§readonly config:PartialSessionConfig
Resolved configuration (empty object when no config was found)
§readonly sourcePath?:string
Absolute path of the config file that was loaded (undefined when nothing was found)
§interface

ParsedBody

Parsed body section of a commit message.

Properties

§body:string
The body text (may be multiline)
§endIndex:number
Index where the body ends (start of footers or end of message)
§interface

ParsedFooters

Parsed footer section of a commit message.

Properties

§breakingDescription?:string
Breaking change description if found
§footers:CommitFooter[]
All parsed footers
§interface

ParsedHeader

Parsed conventional commit header components.

Properties

§breaking:boolean
Whether this is a breaking change
§scope:unknown
Scopes from parentheses (empty array when header has no scope)
§subject:string
Commit subject line
§type:string
Commit type (feat, fix, chore, etc.)
§interface

Rule

Pure rule definition. Implementations inspect a ConventionalCommit and return zero or more violation messages. The engine applies severity from the ruleset config and aggregates RuleMessages across all rules.

Properties

§readonly name:string
Stable identifier used to key the rule in a Ruleset
§interface

RuleContext

Runtime context passed to a rule invocation.

Properties

§readonly level:RuleLevel
Effective severity the engine will apply to any violations
§readonly options?:TOptions
Rule-specific options resolved from the ruleset config
§interface

RuleMessage

A single violation reported by the engine, tagged with its effective severity.

Properties

§readonly level:"error" | "warn"
Effective severity for this violation
§readonly message:string
Human-readable description of the violation
§readonly ruleName:string
Name of the rule that produced the violation
§interface

ScopeEnumOptions

Options for the scope-enum rule.

Properties

§readonly scopes:unknown
Allowed scope identifiers. Empty array disables the check.
§interface

ScopeFilterContext

Signature for the scope filter passed in SessionConfig.scopeFilter.

Properties

§readonly name:string
name field read from project.json (or package.json as fallback)
§readonly path:string
Absolute path to the discovered project root
§interface

SessionConfig

Fully resolved authoring session configuration. Consumers typically supply a partial shape — the config loader (or createAuthorSession) fills the gaps with defaults before handing the result to the runner.

Properties

§readonly commitExecutor?:CommitExecutor
Overrides the default git commit executor
§readonly cwd:string
Working directory used for git operations and scope discovery
§readonly headerMaxLength:number
Maximum header length used by the subject countdown (null disables)
§readonly imperativeWordlist:Readonly<Record<string, string>>
Wordlist used by the imperative-mood rule in inline validation
§readonly input?:ReadStream
Optional stream override passed to every prompt in the session
§readonly output?:WriteStream
Optional stream override passed to every prompt in the session
§readonly scopeFilter?:(context: ScopeFilterContext) => boolean
Optional filter applied to discovered scopes — receives { path, name }
§readonly scopeMulti:boolean
When true, the scope step collects multiple scopes via multiselect
§readonly scopeOptional:boolean
When true, the scope step may be skipped even if no candidates are found
§readonly skipCommit:boolean
When true, the final commit step is a no-op (session returns the message only)
§readonly stagedPathsProvider:StagedPathsProvider
Resolver for the staged file list; defaults to git diff --cached --name-only -z
§readonly types:unknown
Commit type enum shown in the type step
§readonly validateRuleset:Ruleset
Validation ruleset used for inline and preview-time warnings
§interface

SessionContext

Mutable container threaded through every step. The draft field accumulates the in-progress commit message; candidateScopes/defaultScope are filled by the resolve-scope step and consumed by later steps. config is the fully resolved SessionConfig shared across the session.

Properties

§candidateScopes:unknown
Scopes discovered from the staged file set (may be empty)
§readonly config:SessionConfig
Resolved configuration for the session
§defaultScope:string
Default scope pre-selected by the scope step (undefined = no default)
§draft:CommitDraft
In-progress commit draft accumulated as steps execute
§interface

SessionOutcome

Terminal outcome returned by runAuthorSession.

Properties

§readonly error?:Error
Error attached when the session cancelled due to an explicit failure
§readonly message?:string
Formatted commit message (populated whenever the draft reached the preview step)
§readonly status:SessionStatus
Status tag describing how the session ended
§interface

SessionType

Conventional-commit type entry shown in the type step's choice list.

Properties

§readonly description?:string
Short description rendered as a prompt hint
§readonly name:string
Bare identifier (e.g. feat, fix)
§interface

StagedPathsOptions

Options accepted by the default staged-paths provider.

Properties

§readonly cwd:string
Working directory used as the git command cwd
§readonly timeout?:number
Timeout in milliseconds (default: 30000)
§interface

Step

A named step in an authoring session.

Properties

§readonly id:string
Stable identifier used by goto and for debugging
§interface

StepResult

Outcome produced by a step implementation.

Properties

§readonly error?:Error
Error attached when status === 'cancelled'
§readonly gotoStepId?:string
Target step id when status === 'goto'
§readonly status:StepStatus
Status tag used by the runner to decide how to proceed
§interface

SubjectCaseOptions

Options for the subject-case rule.

Properties

§readonly cases:unknown
One or more accepted case forms. A subject passing any accepted form is valid.
§interface

TypeEnumOptions

Options for the type-enum rule.

Properties

§readonly types:unknown
Allowed commit type identifiers. Empty array disables the check.
§interface

CommitValidationResult

Aggregated outcome of running a ruleset over a commit.

Properties

§readonly errors:unknown
Error-level violations (blocking)
§readonly valid:boolean
True when no error-level violations were recorded
§readonly warnings:unknown
Warn-level violations (non-blocking)

Types

§type

CommitSource

Source of how a commit relates to a project.
Classification determines whether a commit should appear in a project's changelog and how its scope should be displayed.
type CommitSource = "direct-scope" | "direct-file" | "unscoped-file" | "indirect-dependency" | "indirect-infra" | "unscoped-global" | "excluded"
§type

InfrastructureMatcher

Infrastructure matcher function type.
Returns true if the commit should be classified as infrastructure-related. Matchers are composable - combine them using anyOf, allOf, and not.
type InfrastructureMatcher = (context: InfrastructureMatchContext) => boolean
§type

CommitExecutor

Signature for executing the final git commit.
type CommitExecutor = (message: string) => void | Promise<void>
§type

CommitType

Conventional commit type identifier (e.g., 'feat', 'fix', 'docs').
type CommitType = "feat" | "fix" | "docs" | "style" | "refactor" | "perf" | "test" | "build" | "ci" | "chore" | "revert" | string
§type

PartialSessionConfig

Partial shape accepted by createAuthorSession/loadCommitConfig.
type PartialSessionConfig = Partial<SessionConfig>
§type

RuleConfig

Configuration tuple for a single rule in a ruleset.
A bare [level] entry disables the rule when level is 'off', or enables it with no options otherwise. The [level, options] form passes rule-specific options through to the rule's check() implementation.
type RuleConfig = unknown | unknown
§type

RuleLevel

Severity level for a rule in a ruleset.
type RuleLevel = "off" | "warn" | "error"
§type

RuleResult

Aggregated list of violations produced by the engine for a single ruleset run.
type RuleResult = unknown
§type

Ruleset

Mapping from rule name to its config tuple. Rules not present in the map are treated as 'off' by the engine.
type Ruleset = Readonly<Record<string, RuleConfig>>
§type

SessionStatus

Session outcome status constants.
type SessionStatus = Readonly<{ Cancelled: "cancelled"; Committed: "committed" }>
§type

SessionStatus

Session outcome status constants.
type SessionStatus = Readonly<{ Cancelled: "cancelled"; Committed: "committed" }>
§type

StagedPathsProvider

Signature for resolving the staged file paths the session operates on.
type StagedPathsProvider = (options: StagedPathsProviderOptions) => unknown
§type

StepStatus

Result status constants returned by steps.
type StepStatus = Readonly<{ Cancelled: "cancelled"; Done: "done"; Goto: "goto" }>
§type

StepStatus

Result status constants returned by steps.
type StepStatus = Readonly<{ Cancelled: "cancelled"; Done: "done"; Goto: "goto" }>
§type

SubjectCase

Supported subject-case modes.
type SubjectCase = "sentence-case" | "lower-case" | "upper-case" | "kebab-case" | "snake-case" | "start-case"

Variables

§type

CI_SCOPE_MATCHER

Matches common CI/CD scopes.
Matches: ci, cd, build, pipeline, workflow, actions
§type

DEFAULT_INFRA_SCOPE_MATCHER

Combined matcher for common infrastructure patterns.
Combines CI, tooling, and tool-prefix matchers.
§type

TOOL_PREFIX_MATCHER

Matches tool-prefixed scopes (e.g., tool-package, tool-scripts).
§type

TOOLING_SCOPE_MATCHER

Matches common tooling/workspace scopes.
Matches: tooling, workspace, monorepo, nx, root
§type

bodyStep

Step that prompts for an optional commit body. Empty input leaves draft.body unset (the formatter then omits the body section).
§type

breakingStep

Step that asks whether the commit introduces a breaking change. A positive answer follows up with a description prompt; the description is written to draft.breakingDescription and is eventually synthesized into a BREAKING CHANGE: footer by formatCommitMessage.
§type

BUILT_IN_RULES

Registry of built-in rules the engine knows how to run, keyed by rule name.
§type

COMMIT_TYPES

§type

commitStep

Step that renders the draft one last time and hands the message to the configured commit executor. When config.skipCommit is true the step short-circuits so the caller receives the formatted message without touching the working tree.
§type

CONFIG_FILE_NAMES

Supported config file names, searched in this order per directory.
§type

CONVENTIONAL_TYPES

Conventional Commits default type enum used by the preset.
§type

conventionalPreset

Default ruleset mirroring @commitlint/config-conventional's baseline.
| Rule | Level | Options | | ------------------ | ----- | ------------------------ | | type-enum | error | CONVENTIONAL_TYPES | | subject-empty | error | — | | scope-enum | off | — | | subject-case | off | — | | header-max-length | warn | { maxLength: 72 } | | imperative-mood | warn | — |
§type

conventionalStepPreset

Default ordered step list used by createAuthorSession when the caller does not supply their own sequence. Matches decision D8: resolve-scope → type → scope → subject → body → breaking → issues → preview → commit.
§type

DEFAULT_EXCLUDE_SCOPES

Default scopes to exclude from changelogs.
These represent repository-level or infrastructure changes that typically don't belong in individual project changelogs.
§type

DEFAULT_IMPERATIVE_WORDLIST

Default past-tense → imperative word map used when options are omitted.
§type

DEFAULT_PROJECT_PREFIXES

Default project name prefixes that can be stripped for scope matching.
§type

DEFAULT_SESSION_TYPES

Default type enum rendered by the type step when the caller does not supply their own list. Each conventional type is paired with a short hint.
§type

EMPTY_STAGING_MESSAGE

Error thrown to the runner when the staging area is empty.
§type

headerMaxLengthRule

Rule that fails when the reconstructed header (type(scope)!: subject) exceeds the configured maximum length.
§type

imperativeMoodRule

Rule that reports a warning when the first subject word (case-insensitive) matches a known past-tense form. Never blocks; intended as a nudge.
§type

issuesStep

Step that optionally collects issue references (e.g. fixes #123, re #456) and appends them to draft.footers using the # separator form.
The step is additive: existing footers stay, and any breaking-change footer synthesized later by the formatter is unaffected.
§type

MINOR_TYPES

§type

NO_SCOPE_CANDIDATES_MESSAGE

Error thrown when the scope step cannot proceed because no candidates were found.
§type

PATCH_TYPES

§type

PREVIEW_RESTART_STEP_ID

Step id the preview jumps back to when the user rejects the draft.
§type

previewStep

Step that renders the accumulated draft as the final commit message and asks the user to confirm. A negative answer jumps back to the type step while keeping the draft intact for round-trip editing. Validation warnings are printed before the prompt.
§type

RELEASE_TYPES

§type

resolveScopeStep

Non-prompt step that computes the candidate scope list and default scope.
Calls config.stagedPathsProvider()discoverScopesdefaultScope and writes the results into the context. Cancels the session when the staging area is empty (decision E1a).
§type

scopeEnumRule

Rule that fails when any scope on the commit is not in the configured allow-list. A commit with no scopes (empty array) always passes; when scopes are required, pair this rule with a separate scope-empty check.
§type

scopeStep

Step that prompts the user to pick the commit scope(s) from the candidate list discovered by resolve-scope. Respects scopeOptional (cancels with an actionable error when no candidates exist and scope is required) and scopeMulti (multiselect vs. single-select).
§type

subjectCaseRule

Rule that fails when the commit subject does not match any of the configured case forms. An empty subject always passes (handled by subject-empty).
§type

subjectEmptyRule

Rule that fails when the commit subject is empty or whitespace-only.
§type

subjectStep

Step that prompts for the commit subject. Strips the trailing period, trims edges, and enforces a non-empty subject. When headerMaxLength is set, a live countdown re-renders on every keystroke (green → yellow → red as the remaining budget shrinks).
§type

typeEnumRule

Rule that fails when the commit type is not in the configured allow-list.
§type

typeStep

Step that prompts the user for the commit type. Uses the searchable select prompt and seeds the cursor from any existing ctx.draft.type (so a preview → cancel restart re-opens on the previous choice).