npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@utkarsh2325/git-context

v0.6.1

Published

Know your Git state from inside Node.js.

Readme

git-context

CI

Know your Git state from inside Node.js.

git-context is a zero-configuration, read-only TypeScript library that exposes the Git repository state around an application, script, deployment, migration, or CI job. It intentionally is not a complete Git wrapper.

Installation

npm install @utkarsh2325/git-context

Node.js 20 or later and the git executable are required.

Quick Start

import { git } from "@utkarsh2325/git-context";

const context = git();

console.log({
  branch: context.branch,
  commit: context.shortCommit,
  dirty: context.dirty,
});

git() finds the enclosing repository through Git itself, so it works seamlessly from nested directories, monorepo packages, and linked worktrees. It returns a fresh snapshot on every call so deployment checks never rely on stale clean/dirty state.

Usage

1. Reading Repository Context

Call git() to read an immutable snapshot of the current repository:

import { git } from "git-context";

const context = git();

console.log(`Branch: ${context.branch}`);
console.log(`Commit: ${context.commit} (${context.shortCommit})`);
console.log(`Clean: ${!context.dirty}`);
console.log(`Author: ${context.author} <${context.email}>`);
console.log(`Root: ${context.root}`);

if (context.remote) {
  console.log(`Remote: ${context.remote} (${context.remoteUrl})`);
}

GitContext Properties

| Property | Type | Description | |---|---|---| | branch | string \| null | Current branch name, or null when HEAD is detached | | commit | string | Full 40-character SHA of HEAD | | shortCommit | string | Abbreviated SHA of HEAD (7+ characters) | | dirty | boolean | true if tracked, staged, or untracked changes exist | | detached | boolean | true if HEAD points directly at a commit rather than a branch | | author | string | Author name of the HEAD commit | | email | string | Author email of the HEAD commit | | root | string | Absolute filesystem path to the repository root directory | | commitDate | string | ISO 8601 commit timestamp of HEAD | | tag | string \| undefined | Exact tag pointing at HEAD, if tagged | | ahead | number \| undefined | Commits ahead of upstream tracking branch, if configured | | behind | number \| undefined | Commits behind upstream tracking branch, if configured | | stashCount | number | Number of stash entries saved in the repository | | mergeConflict | boolean | true if unmerged files exist (merge conflict state) | | submodules | readonly SubmoduleInfo[] | List of submodules with paths, commit SHAs, and dirty states | | remote | string \| undefined | Preferred remote name (origin when present, otherwise first available) | | remoteUrl | string \| undefined | URL of the preferred remote |

2. Checking Repository Presence

Check whether a directory is inside a Git repository before executing Git-dependent logic:

import { git } from "git-context";

if (git.isRepository()) {
  const context = git();
  console.log(`Running in Git repo at ${context.root}`);
} else {
  console.log("Not running inside a Git repository; skipping Git checks.");
}

3. Enforcing Safety Guards

Prevent accidental deployments, database migrations, or release publishing from dirty working trees, untracked changes, or wrong branches:

import { git } from "git-context";

// Require a specific branch (throws BranchMismatchError if mismatched or detached)
git.requireBranch("main");

// Require a completely clean working tree (throws DirtyRepositoryError if dirty)
git.assertClean();

// Enforce both in a single check
git.requireCleanBranch("main");

// Generic assertion combining multiple criteria:
git.assert({
  branch: ["main", "release"], // accept array of allowed branches
  clean: true,                 // require clean working tree
  detached: false,             // reject detached HEAD
  tag: true,                   // require HEAD to have an exact tag (or specific string like "v1.0.0")
  unpushed: true,              // require no unpushed commits ahead of upstream
});

// Proceed with sensitive task safely
await deploy();

4. Watch Mode (Event-Driven)

React to Git changes in real time (e.g. for development servers, watch scripts, or live status displays):

import { git } from "git-context";

const watcher = git.watch({ interval: 1000 });

// Fired whenever commit, branch, or dirty state changes
watcher.on("change", (newContext, oldContext) => {
  console.log(`Repository changed: ${oldContext.shortCommit} → ${newContext.shortCommit}`);
});

// Fired when working tree transitions from clean to dirty
watcher.on("dirty", (context) => {
  console.warn("Working tree has uncommitted changes!");
});

// Fired when working tree transitions back to clean
watcher.on("clean", (context) => {
  console.log("Working tree is now clean.");
});

// Stop polling when done
watcher.stop();

5. Configuration File Support

Define repository assertion rules in .gitcontextrc.json or package.json#gitContext and enforce them with a single line:

{
  "$schema": "https://github.com/KDM-cli/git-context",
  "assertions": {
    "branch": "main",
    "clean": true,
    "detached": false,
    "unpushed": true
  },
  "format": "table"
}
import { git } from "git-context";

// Enforce rules defined in configuration:
git.assertFromConfig();

// Or load the parsed config object directly:
const config = git.loadConfig();

6. Inspecting Another Directory (cwd)

By default, git-context discovers the repository enclosing process.cwd(). Pass { cwd } to any method to inspect a different repository, submodule, or workspace:

import { git } from "git-context";

const repoContext = git({ cwd: "/srv/release-checkout" });

git.requireCleanBranch("main", { cwd: "/srv/release-checkout" });

7. Error Handling

git-context throws dedicated, typed errors extending GitContextError:

import {
  git,
  GitContextError,
  DirtyRepositoryError,
  BranchMismatchError,
  DetachedHeadError,
  TagMismatchError,
  UnpushedCommitsError,
  RepositoryNotFoundError,
  GitExecutableNotFoundError,
} from "git-context";

try {
  git.assert({
    branch: "main",
    clean: true,
    tag: true,
  });
} catch (error) {
  if (error instanceof DirtyRepositoryError) {
    console.error("Please commit or stash changes before deploying.");
  } else if (error instanceof BranchMismatchError) {
    console.error(`Expected branch "${error.expected}", but found "${error.actual}".`);
  } else if (error instanceof DetachedHeadError) {
    console.error("HEAD is detached; checkout a named branch.");
  } else if (error instanceof TagMismatchError) {
    console.error(`Tag requirement failed (expected: ${error.expected}, actual: ${error.actual}).`);
  } else if (error instanceof UnpushedCommitsError) {
    console.error(`Please push ${error.ahead} local commit(s) before publishing.`);
  } else if (error instanceof RepositoryNotFoundError) {
    console.error(`No Git repository found from: ${error.cwd}`);
  } else if (error instanceof GitExecutableNotFoundError) {
    console.error("Git is not installed or not found on PATH.");
  } else if (error instanceof GitContextError) {
    console.error(`Git context error: ${error.message}`);
  }
}

8. Command Line Interface (CLI)

Run git-context directly from the terminal without installing:

npx git-context

Output Formats

  • Table (default): Color-coded, aligned table output displaying branch, commit, dirty status, author, remotes, tracking, stash count, merge conflict alerts, and submodules.
  • Minimal (--format=minimal): Compact one-liner with color highlights, ideal for terminal prompts and status lines (e.g., main* a1b2c3d [1↑0↓]).
  • JSON (--json or --format=json): Machine-readable JSON for CI/CD pipelines and scripting.
# Compact format
npx git-context --format=minimal

# Disable ANSI colors
npx git-context --no-color

# Output JSON
npx git-context --json

Scaffold Configuration (init)

Generate a .gitcontextrc.json configuration file and a sample scripts/deploy-guard.ts guard script:

npx git-context init

Flags:

  • --format=<format>: Output format: table (default), json, minimal
  • --json: Output machine-readable JSON (alias for --format=json)
  • --no-color: Disable colored output
  • -h, --help: Show usage and options
  • --version: Show version number

Examples

See the examples/ directory:

Design and Security

All Git commands are executed with Node's non-shell process API (execFileSync) using explicit argument arrays. git-context:

  • Never interpolates arguments into a shell command (safe from shell injection)
  • Never changes Git configuration or modifies the repository (read-only)
  • Never contacts remote servers or performs network requests
  • Emits zero telemetry
  • Communicates failures through typed, actionable errors

License

MIT