API Reference

Use Branchwright programmatically in your Node.js applications.

Main API

Branchwright Class

The main interface for programmatic usage:

import { Branchwright } from '@branchwright/cli';

const branchwright = new Branchwright(config?);

Constructor

new Branchwright(config?: BranchwrightConfig)

Creates a new instance with optional configuration. If no config is provided, it will attempt to load from branchwright.config.ts.

Methods

validate(branchName: string): Promise<ValidationResult>

Validate a branch name against configured rules.

const result = await branchwright.validate('feat/user-auth');

if (result.valid) {
  console.log('✓ Branch name is valid');
} else {
  console.log(`✗ ${result.message}`);
  console.log('Suggestions:', result.suggestions);
}
create(): Promise<string>

Launch interactive branch creation wizard.

const branchName = await branchwright.create();
console.log(`Created: ${branchName}`);
lint(options?: LintOptions): Promise<LintResult[]>

Validate one or more branches.

// Lint current branch
const results = await branchwright.lint();

// Lint all branches
const allResults = await branchwright.lint({ all: true });

// Lint specific branches
const specificResults = await branchwright.lint({ 
  branches: ['feat/auth', 'fix/bug'] 
});
getValidator(): Validator

Get the underlying validator instance for advanced usage.

getCreator(): Creator

Get the underlying creator instance for advanced usage.

Type Definitions

BranchwrightConfig

interface BranchwrightConfig {
  branchTypes?: BranchTypeOption[];
  template?: string;
  maxDescriptionLength?: number;
  descriptionStyle?: 'kebab-case' | 'snake_case' | 'camelCase' | 'PascalCase';
  ignoredBranches?: string[];
  rules?: Rules;
  extraQuestions?: InteractiveQuestions;
  questions?: QuestionConfig;
  plugins?: string[];
  presets?: string[];
  showCliTips?: boolean;
}

BranchTypeOption

interface BranchTypeOption {
  name: string;   // Short identifier (feat, fix, etc.)
  label: string;  // Display name for prompts
}

ValidationResult

interface ValidationResult {
  valid: boolean;
  message?: string;
  suggestions?: string[];
  violations?: RuleViolation[];
}

LintOptions

interface LintOptions {
  all?: boolean;
  branches?: string[];
  json?: boolean;
}

LintResult

interface LintResult {
  branch: string;
  valid: boolean;
  message?: string;
  violations?: RuleViolation[];
}

Rule System API

defineRule

Create custom validation rules:

import { defineRule } from '@branchwright/cli';

const myRule = defineRule(
  {
    id: 'my-rule',
    meta: {
      title: 'My Custom Rule',
      description: 'Validates something specific',
    },
    defaultSeverity: 'required',
  },
  (context: RuleContext) => {
    // Return null if valid
    if (isValid(context.branchName)) {
      return null;
    }
    
    // Return violation if invalid
    return {
      message: 'Branch name is invalid',
      suggestions: ['alternative-name'],
    };
  }
);

RuleContext

interface RuleContext {
  branchName: string;
  config: BranchwrightConfig;
  options?: any;  // Rule-specific options
}

evaluateRules

Evaluate multiple rules against a branch name:

import { evaluateRules, coreRuleRegistry } from '@branchwright/cli';

const violations = await evaluateRules(
  'feat/my-branch',
  config,
  coreRuleRegistry
);

violations.forEach(v => {
  console.error(`${v.ruleId}: ${v.message}`);
});

createRegistry

Create a custom rule registry:

import { createRegistry, coreRuleRegistry } from '@branchwright/cli';

const customRegistry = createRegistry(
  ...coreRuleRegistry.entries(),
  myCustomRule,
  anotherCustomRule
);

Utility Functions

defineConfig

Type-safe configuration helper:

import { defineConfig } from '@branchwright/cli';

export default defineConfig({
  // Full TypeScript autocomplete and validation
  branchTypes: [/* ... */],
  template: '{{type}}/{{desc}}',
});

loadConfig

Load configuration from a file:

import { loadConfig } from '@branchwright/cli';

const config = await loadConfig('./path/to/config.ts');

Integration Examples

Custom CLI Tool

#!/usr/bin/env node
import { Branchwright } from '@branchwright/cli';

async function main() {
  const brw = new Branchwright();
  
  if (process.argv[2] === 'validate') {
    const branch = process.argv[3] || getCurrentBranch();
    const result = await brw.validate(branch);
    process.exit(result.valid ? 0 : 1);
  }
}

main();

Express.js Webhook

import express from 'express';
import { Branchwright } from '@branchwright/cli';

const app = express();
const brw = new Branchwright();

app.post('/validate-branch', async (req, res) => {
  const { branchName } = req.body;
  const result = await brw.validate(branchName);
  
  res.json({
    valid: result.valid,
    message: result.message,
  });
});

GitHub Action

import { Branchwright } from '@branchwright/cli';
import * as core from '@actions/core';

async function run() {
  try {
    const brw = new Branchwright();
    const branch = process.env.GITHUB_HEAD_REF;
    const result = await brw.validate(branch);
    
    if (!result.valid) {
      core.setFailed(result.message);
    }
  } catch (error) {
    core.setFailed(error.message);
  }
}

run();

Husky Pre-push Hook

#!/usr/bin/env node
import { Branchwright } from '@branchwright/cli';
import { execSync } from 'child_process';

async function validateCurrentBranch() {
  const brw = new Branchwright();
  const branch = execSync('git branch --show-current')
    .toString()
    .trim();
  
  const result = await brw.validate(branch);
  
  if (!result.valid) {
    console.error(`✗ Invalid branch name: ${result.message}`);
    process.exit(1);
  }
  
  console.log('✓ Branch name is valid');
}

validateCurrentBranch();

Advanced Usage

Custom Validator

import { Validator } from '@branchwright/cli';

class CustomValidator extends Validator {
  async validate(branchName: string) {
    // Custom validation logic
    const result = await super.validate(branchName);
    
    // Add additional checks
    if (branchName.includes('temp')) {
      return {
        valid: false,
        message: 'Temporary branches not allowed',
      };
    }
    
    return result;
  }
}

Rule Plugin Development

// my-plugin.ts
import { defineRule } from '@branchwright/cli';

export default [
  defineRule(
    {
      id: 'team-prefix',
      meta: {
        title: 'Team prefix required',
        description: 'Branch must start with team name',
      },
      defaultSeverity: 'required',
    },
    (context) => {
      const { team } = context.options;
      if (!context.branchName.startsWith(`${team}/`)) {
        return {
          message: `Branch must start with ${team}/`,
          suggestions: [`${team}/${context.branchName}`],
        };
      }
      return null;
    }
  ),
  // More rules...
];

// Usage in config
export default defineConfig({
  plugins: ['./my-plugin.ts'],
  rules: {
    'team-prefix': ['required', { team: 'frontend' }],
  },
});