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

ossbridge

v0.3.0

Published

CLI for bidirectional sync between a private monorepo and a public OSS mirror

Readme

ossbridge

A CLI for bidirectional sync between a private canonical monorepo and a public OSS mirror. Manages the full lifecycle of external contributions: validation, merge, sync, and attribution.

Why ossbridge?

Managing OSS contributions when your canonical repo is private is painful. You need to:

  • Accept PRs on the public repo without exposing secrets
  • Run full validation in the private repo
  • Preserve contributor attribution across the sync
  • Close OSS PRs automatically after merge
  • Handle failures, race conditions, and edge cases

This typically means hundreds of lines of YAML spread across multiple workflows, with no tests, no type safety, and failures that manifest as PRs stuck in weird states.

ossbridge encapsulates this complexity in a single, testable CLI. Your workflows become thin declarations. The state machine is explicit. Failures are clear.

Quick Start

1. Create config files

Create ossbridge.json at the root of your OSS package:

{
  "schema": "ossbridge/v1",
  "privateRepo": "yourorg/private-monorepo",
  "ossRepo": "yourorg/oss-repo",
  "ossPath": "packages/mylib",
  "maintainers": ["@yourorg/maintainers", "alice", "bob"],
  "triggerComment": "/run-private-tests",
  "requiredChecks": ["oss-quick-ci"],
  "auth": {
    "privateToken": "OSSBRIDGE_PRIVATE_TOKEN",
    "ossToken": "OSSBRIDGE_OSS_TOKEN"
  }
}

At the private repo root, create a ref that points to the OSS package:

{
  "schema": "ossbridge/v1",
  "ref": "packages/mylib"
}

The config lives in the OSS package because the OSS repo can only see files within its folder. The private repo uses a ref so the CLI knows where to find it.

2. Set up secrets

The auth block specifies which environment variable names the CLI reads at runtime. Add matching GitHub secrets to both repos:

| Token | Scopes | | ------------------------- | -------------------------- | | OSSBRIDGE_PRIVATE_TOKEN | repo | | OSSBRIDGE_OSS_TOKEN | repo, write:discussion |

3. Add workflows

Wire up your GH action workflow yaml files to use the cli. This will be company and project specific in most cases, but see example-monorepo/ for a complete working setup with all workflow files, configs, and a step-by-step setup guide.

How It Works

Lifecycle

A contribution moves through eight steps across both repos:

  1. Contributor opens a PR on the OSS repo. Standard CI runs (lint, tests) on OSS project without access to secrets.

  2. Maintainer triggers validation by commenting the configured trigger phrase (e.g. /run-private-tests). The dispatch-pr command (OSS repo) verifies the commenter is a maintainer, confirms required checks have passed, records the PR's HEAD SHA, labels the PR ossbridge:accepted, and dispatches an ossbridge-import event to the private repo.

  3. Private repo imports the PR. The import-pr command (private repo) fetches the PR's commits, remaps file paths from OSS root into the monorepo subtree (/ → {ossPath}/), creates a branch ossbridge/{pr-number}, and opens a PR titled [OSS #{n}] {title} against private main. The OSS PR is labeled ossbridge:validating.

  4. Full CI runs in the private repo with secret access — integration tests, e2e, etc.

  5. Results are reported back. The report-result command (private repo) reads the CI conclusion, updates the state comment on the OSS PR, and sets ossbridge:validated or ossbridge:failed.

  6. Maintainer reviews and merges the private PR. Before merge completes, verify-merge (private repo, wired as a required status check) confirms the OSS PR hasn't changed since validation (SHA match), is still open, and has the ossbridge:validated label.

  7. Changes sync to OSS. On push to private main, sync-downstream (private repo) identifies commits touching the subtree, remaps paths back ({ossPath}/ → /), and pushes to OSS main. Original author attribution is preserved — git blame shows the contributor on both repos.

  8. OSS PR closes automatically. On push to OSS main, close-synced-prs (OSS repo) finds PRs whose changes have landed, posts a thank-you comment with commit links, removes all ossbridge:* labels, and closes the PR.

State Machine

PRs move through states tracked via GitHub labels:

[opened] → [ossbridge:accepted] → [ossbridge:validating] → [ossbridge:validated] → [closed]
                                                          ↘
                                                            [ossbridge:failed]

Command Reference

All commands read ossbridge.json from the repository root by default. Use --config <path> to override.

dispatch-pr

Runs in: OSS repo | Trigger: issue_comment

Preconditions (all must hold or exits 1):

  • Comment body matches triggerComment from config
  • Commenter is in maintainers list (supports @org/team slugs)
  • All requiredChecks have passed on the PR's HEAD
  • PR is open
  • PR has no existing ossbridge:* label (prevents double-dispatch)

Effects:

  • Creates a comment on the OSS PR containing: contributor notification + embedded state JSON (records HEAD SHA, acceptor, timestamp)
  • Adds ossbridge:accepted label
  • Dispatches ossbridge-import event to private repo with {ossPrNumber, ossPrSha} payload

Exit codes: 0 dispatched, 1 precondition failed

import-pr

Runs in: Private repo | Trigger: repository_dispatch type ossbridge-import

Preconditions:

  • OSS PR is open
  • OSS PR HEAD SHA matches the SHA from the dispatch payload (detects if PR was updated after trigger)
  • No existing private PR for this OSS PR (unless --force)

Effects:

  • Creates branch ossbridge/{oss-pr-number} in private repo
  • Opens PR titled [OSS #{n}] {title} against private main, body contains ossbridge metadata and file list with remapped paths
  • Updates state comment on OSS PR with private PR link
  • Sets ossbridge:validating label on OSS PR
  • Comments on OSS PR with link to private PR

Flags: --force re-import even if private PR exists

Exit codes: 0 private PR created/updated, 1 import failed

report-result

Runs in: Private repo | Trigger: workflow_run on ossbridge/* branches

Preconditions:

  • Private PR body contains ossbridge metadata
  • OSS repo in metadata matches config

Effects:

  • Updates state comment on OSS PR with validation result and timestamp
  • Sets ossbridge:validated or ossbridge:failed label (replaces previous ossbridge label)
  • Posts pass/fail notification comment on OSS PR (with failure details if applicable)

Flags: --passed / --failed override the CI conclusion (for manual recovery)

Note: skipped CI conclusion is treated as passed.

Exit codes: 0 result reported, 1 could not determine result or post status

verify-merge

Runs in: Private repo | Trigger: required status check (PR check or merge queue)

Preconditions:

  • Private PR body contains ossbridge metadata

Checks (any failure exits 1 and blocks merge):

  • OSS PR is still open
  • OSS PR HEAD SHA matches the SHA recorded at dispatch time
  • ossbridge:validated label is present (not ossbridge:failed, not ossbridge:validating)

Effects on failure:

  • SHA mismatch: posts "Validation Invalidated" comment on OSS PR showing expected vs current SHA

Exit codes: 0 safe to merge, 1 not safe

Wire this as a required status check to prevent merging stale validations.

sync-downstream

Runs in: Private repo | Trigger: push to main

Effects:

  • Compares commits between previous sync point and current HEAD
  • Filters to commits that touch files under ossPath
  • For each relevant commit: remaps paths {ossPath}/* → /*, preserves author attribution
  • Pushes to OSS repo main

Exit codes: 0 sync completed (or nothing to sync), 1 sync failed

close-synced-prs

Runs in: OSS repo | Trigger: push to main

Effects:

  • Finds open PRs with ossbridge:validated label
  • For each PR, checks if its changes have landed in main (handles both regular and squash merges via commit comparison)
  • Posts thank-you comment with canonical and mirrored commit links
  • Removes all ossbridge:* labels
  • Closes the PR

Flags: --pr {n} close a specific PR

Exit codes: 0 PRs closed (or none to close), 1 failed to close

status

Runs in: Either repo | Trigger: manual

Inspect PR state for debugging. Reads state from OSS PR comments and labels, discovers private PR by branch name if no state exists.

bunx ossbridge status --pr 42
OSS PR #42: Add custom validators
  State: open
  SHA: abc123def456
  Phase: validating
  Accepted by: alice at 2025-01-15T10:30:00Z
  Private PR: #17 (https://github.com/yourorg/private-monorepo/pull/17)
  Labels: ossbridge:validating
  Validation started: 2025-01-15T10:30:12Z

Configuration

Full config

{
  "schema": "ossbridge/v1",

  "privateRepo": "yourorg/private-monorepo",
  "ossRepo": "yourorg/oss-repo",
  "ossPath": "packages/mylib",

  "maintainers": ["@yourorg/maintainers", "alice", "bob"],
  "triggerComment": "/run-private-tests",
  "requiredChecks": ["oss-quick-ci"],

  "mergeMethod": "squash",
  "squashCommitIncludesHistory": true,

  "labels": {
    "accepted": "ossbridge:accepted",
    "validating": "ossbridge:validating",
    "validated": "ossbridge:validated",
    "failed": "ossbridge:failed"
  },

  "auth": {
    "privateToken": "OSSBRIDGE_PRIVATE_TOKEN",
    "ossToken": "OSSBRIDGE_OSS_TOKEN"
  },

  "notifications": {
    "validationStarted": "## Private Validation Started\n\n...",
    "validationPassed": "## Validation Passed\n\n...",
    "validationFailed": "## Validation Failed\n\n{failureDetails}",
    "prClosed": "## Merged!\n\n..."
  }
}

Field reference

| Field | Type | Required | Description | | ----------------------------- | -------- | -------- | ---------------------------------------------------------------------- | | schema | string | yes | Must be "ossbridge/v1" | | privateRepo | string | yes | owner/repo format | | ossRepo | string | yes | owner/repo format | | ossPath | string | yes | Path within private repo that maps to OSS root | | maintainers | string[] | yes | GitHub usernames or @org/team slugs authorized to trigger validation | | triggerComment | string | yes | Comment text that triggers validation | | requiredChecks | string[] | yes | Status checks that must pass before dispatch | | mergeMethod | string | no | "squash" (default), "merge", or "rebase" | | squashCommitIncludesHistory | boolean | no | Include original commit messages in squash body (default: true) | | labels | object | no | Custom label names (defaults: ossbridge:accepted, etc.) | | auth.privateToken | string | yes | Env var name for private repo token | | auth.ossToken | string | yes | Env var name for OSS repo token | | notifications | object | no | Custom notification templates (see variables below) |

Notification template variables:

| Variable | Description | | -------------------- | --------------------------------- | | {ossPrNumber} | OSS PR number | | {privatePrNumber} | Private PR number | | {privatePrUrl} | URL to private validation PR | | {failureDetails} | CI failure logs | | {triggerComment} | The configured trigger comment | | {privateCommitUrl} | URL to canonical commit | | {ossCommitUrl} | URL to synced commit | | {maintainer} | Username who triggered validation |

Config resolution

  1. --config <path> flag
  2. ossbridge.json in current working directory
  3. ossbridge.json in repository root (detected via git)

Ref configs are automatically followed to load the actual configuration.

CI Integration

Each repo gets an ossbridge.yml workflow. The OSS repo handles inbound PRs (dispatch-pr on comment, close-synced-prs on push to main). The private repo handles import, validation, and sync (import-pr on dispatch, report-result on workflow completion, sync-downstream on push to main). A separate ossbridge-verify.yml wires verify-merge as a required check.

Minimal OSS repo workflow:

name: ossbridge
on:
  issue_comment:
    types: [created]
  push:
    branches: [main]

jobs:
  dispatch-pr:
    if: github.event_name == 'issue_comment' && github.event.issue.pull_request
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: oven-sh/setup-bun@v1
      - run: bunx ossbridge dispatch-pr
        env:
          OSSBRIDGE_PRIVATE_TOKEN: ${{ secrets.OSSBRIDGE_PRIVATE_TOKEN }}
          OSSBRIDGE_OSS_TOKEN: ${{ secrets.OSSBRIDGE_OSS_TOKEN }}

See example-monorepo/ for the complete set of workflows for both repos, including the step-by-step setup guide.

Error Handling and Recovery

| Failure | Behavior | | ------------------------------- | -------------------------------------------------------------------- | | Maintainer not authorized | dispatch-pr exits 1, posts explanatory comment | | Required checks not passed | dispatch-pr exits 1, posts which checks are missing | | PR already in workflow | dispatch-pr exits 1 (duplicate-dispatch guard) | | OSS PR closed during validation | verify-merge exits 1, blocks merge | | OSS PR updated after validation | verify-merge exits 1, posts "Validation Invalidated" with SHA diff | | Private CI fails | report-result sets ossbridge:failed label, posts failure details | | Sync conflict | sync-downstream exits 1 | | Missing auth token | All commands exit 1, message indicates which env var is missing |

Manual recovery

# Force re-import (clears existing private PR)
bunx ossbridge import-pr --force --pr 42

# Manually mark as passed
bunx ossbridge report-result --passed --pr 42

# Manually close a PR that landed
bunx ossbridge close-synced-prs --pr 42

Limitations

  • Single subtree only — one directory to one OSS repo
  • GitHub only — no GitLab/Bitbucket support
  • No merge conflict resolution — sync fails on conflicts
  • Linear history assumed — complex merges may produce unexpected results