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

git-tree-state

v0.1.1

Published

Incremental git file status for a repository

Downloads

248

Readme

git-tree-state

Incremental git file status for a repository. Performs one full git status snapshot at startup, then keeps a cached per-file map in sync via filesystem events and scoped porcelain refreshes.

Install

npm install git-tree-state

One-shot APIs

import { getRepoGitState, getFileGitState } from 'git-tree-state';

const allDirty = await getRepoGitState('/path/to/repo');
const oneFile = await getFileGitState('/path/to/repo', 'src/app.ts');

Watcher API

Filesystem events are dirty hints only. The watcher debounces changed paths, runs scoped git status --porcelain=v2 -z -- <paths>, compares against the cache, and emits change only when the computed git state actually changes. Git metadata (index, HEAD, refs) is watched separately, so commands like git add, git commit, git reset, and checkout also trigger semantic updates.

import { createGitStateWatcher } from 'git-tree-state';

const watcher = await createGitStateWatcher('/path/to/repo', {
  debounceMs: 100,
  ignored: ['**/dist/**'],
});

console.log(watcher.getState());

const unsubscribe = watcher.on('change', (changes) => {
  for (const change of changes) {
    console.log(change.path, change.previous, '->', change.current);
  }
});

// Force a resync if watcher events may have been dropped:
await watcher.refresh();

await watcher.close();
unsubscribe();

Performance model

| Operation | Cost | |-----------|------| | Startup | One full git status --porcelain=v2 -z | | File edit | Debounced batch of scoped status calls for dirty paths only | | Git metadata change (git add, commit, reset, checkout) | Debounced full status refresh | | Listener | Fires only on semantic GitState transitions (including dirty → clean) |

Use refresh() to force a resync after missed watcher events or external operations you do not trust the watcher to catch.

Types

type GitState = {
  status:
    | 'added'
    | 'modified'
    | 'deleted'
    | 'renamed'
    | 'copied'
    | 'unknown';
  staged: boolean;
  unstaged: boolean;
  path: string;
  oldPath?: string;
};

type GitStateChange = {
  path: string;
  previous?: GitState;
  current?: GitState;
};

Simulation harness

For scenario-style tests and local inspection, use the test-support simulation harness in src/test-support/simulator.ts. It runs real git and filesystem operations against createGitStateWatcher() and renders a terminal tree with per-file git state badges.

npm test -- src/simulation.test.ts
npm run simulate

Set GIT_TREE_STATE_SIM_PRINT=1 to print tree snapshots after each step (npm run simulate enables this automatically).

Development

npm install
npm test
npm run build
npm run simulate

CI and release

CI

Every push and pull request to main runs .github/workflows/ci.yml: npm ci, build, and test on Node 20 and 22.

Release (manual staged publish)

Releases are triggered manually via .github/workflows/release.yml using npm staged publishing.

1. Start the workflow

In GitHub: Actions → Release → Run workflow, enter the version (e.g. 1.2.3 or 1.2.3-beta.1 — no v prefix).

The workflow will:

  1. Run tests on Node 22
  2. Set package.json version to the input you provided
  3. Build the package
  4. Run npm stage publish (uploads to npm’s staging queue; not installable yet)

2. Approve on npm

A maintainer with 2FA must approve before the version goes live:

  • npmjs.com → package → Staged Packages → Approve, or
  • npm stage approve git-tree-state@<version>

Prerequisites

| Requirement | Notes | |-------------|--------| | Trusted publishing | Configure on npm for this repo/workflow; use stage-only so CI can npm stage publish but not npm publish | | npm CLI ≥ 11.15.0 | Release job upgrades npm globally before staging | | Node ≥ 22.14.0 | Release job uses Node 22 | | Package on registry | Staging requires an existing package; publish 0.1.0 manually once if needed | | 2FA on npm | Required for the approval step (CI cannot approve) |

Provenance

The release workflow sets id-token: write for OIDC. With trusted publishing configured on npm, provenance attestations are generated automatically when staging — no NPM_TOKEN or --provenance flag in the workflow.