Skip to main content
wit can be used as a library in your Node.js applications, giving you programmatic access to all version control operations.

Installation

npm install wit

Quick Start

// Import from the wit package
import { Repository } from 'wit';

// Initialize a new repository
const repo = Repository.init('/path/to/project');

// Or open an existing one
const repo = Repository.open('/path/to/existing');

// Add files
repo.add('src/index.ts');
repo.add('.');  // Add all

// Commit
const hash = repo.commit('Initial commit');

// Check status
const status = repo.status();
console.log(status.staged);
console.log(status.modified);
console.log(status.untracked);

// View log
const commits = repo.log({ limit: 10 });

Core Classes

Repository

Main class for repository operations

Search

Search commits, files, and content

Notifications

User notification management

Organizations

Organization and team management

Webhooks

Webhook configuration and delivery

Module Structure

import {
  // Core
  Repository,
  ObjectStore,
  Refs,
  
  // Search
  SearchEngine,
  
  // Types
  Commit,
  Tree,
  Blob,
  Status,
  DiffResult,
} from 'wit';

Common Patterns

Error Handling

import { Repository, WitError, NotFoundError } from 'wit';

try {
  const repo = Repository.open('/path/to/repo');
  const commit = repo.getCommit('abc123');
} catch (error) {
  if (error instanceof NotFoundError) {
    console.error('Commit not found');
  } else if (error instanceof WitError) {
    console.error('wit error:', error.message);
  } else {
    throw error;
  }
}

Async Operations

Most operations are synchronous, but some (like large file operations) are async:
// Sync
const hash = repo.commit('Message');

// Async
const results = await repo.search('query');

Working with Commits

// Get a commit
const commit = repo.getCommit('a1b2c3d4');
console.log(commit.message);
console.log(commit.author);
console.log(commit.timestamp);

// Get parent
const parent = repo.getCommit(commit.parentHash);

// Get tree
const tree = repo.getTree(commit.treeHash);
for (const entry of tree.entries) {
  console.log(entry.name, entry.mode, entry.hash);
}

Working with Diffs

// Diff working tree vs index
const unstaged = repo.diff();

// Diff index vs HEAD
const staged = repo.diff({ staged: true });

// Diff between commits
const changes = repo.diff({ 
  from: 'abc123', 
  to: 'def456' 
});

// Process diff
for (const file of changes.files) {
  console.log(file.path, file.status);
  for (const hunk of file.hunks) {
    console.log(hunk.header);
  }
}

Branching

// List branches
const branches = repo.branches();

// Create branch
repo.createBranch('feature');

// Switch branch
repo.switch('feature');

// Get current branch
const current = repo.currentBranch();

Type Definitions

Status

interface Status {
  branch: string;
  staged: FileStatus[];
  modified: FileStatus[];
  untracked: string[];
  ahead: number;
  behind: number;
}

interface FileStatus {
  path: string;
  status: 'added' | 'modified' | 'deleted' | 'renamed';
  oldPath?: string;  // For renames
}

Commit

interface Commit {
  hash: string;
  message: string;
  author: string;
  email: string;
  timestamp: Date;
  parentHash: string | null;
  treeHash: string;
}

DiffResult

interface DiffResult {
  files: FileDiff[];
}

interface FileDiff {
  path: string;
  status: 'added' | 'modified' | 'deleted';
  hunks: DiffHunk[];
}

interface DiffHunk {
  header: string;
  lines: DiffLine[];
}

interface DiffLine {
  type: 'context' | 'add' | 'remove';
  content: string;
  oldLine?: number;
  newLine?: number;
}

Example: Build Tool Integration

import { Repository } from 'wit';

async function buildIfChanged(paths: string[]) {
  const repo = Repository.open('.');
  const status = repo.status();
  
  // Check if any of our paths changed
  const changedFiles = [
    ...status.staged.map(f => f.path),
    ...status.modified.map(f => f.path),
  ];
  
  const needsBuild = paths.some(p => 
    changedFiles.some(f => f.startsWith(p))
  );
  
  if (needsBuild) {
    console.log('Changes detected, building...');
    await runBuild();
  } else {
    console.log('No changes in watched paths');
  }
}

buildIfChanged(['src/', 'lib/']);

Example: Commit Hook

import { Repository } from 'wit';

function preCommitHook() {
  const repo = Repository.open('.');
  const status = repo.status();
  
  // Check for forbidden patterns
  for (const file of status.staged) {
    const content = repo.getFileContent(file.path);
    if (content.includes('console.log')) {
      console.error(`Found console.log in ${file.path}`);
      process.exit(1);
    }
  }
  
  console.log('Pre-commit checks passed');
  process.exit(0);
}

preCommitHook();

tRPC API

wit provides a tRPC API for web and programmatic access. See the individual API reference pages for details:

Next Steps

Repository API

Full Repository class reference

Search API

Search and semantic search reference