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

@invigile/sdk

v0.4.21

Published

Invigile browser proctoring SDK — embed integrity monitoring into your exam or interview page.

Downloads

917

Readme

@invigile/sdk

npm version license

Browser proctoring SDK for Invigile — embed integrity monitoring into your own exam or interview page.

Invigile runs in ghost mode: it flags tab switches, clipboard use, multi-face / gaze events, identity mismatches, and optional OS signals without showing warnings to the candidate. Results land in the Invigile Evidence Room.

Requirements

  • A modern browser (window / DOM). This package is browser-only — do not import it in Node or edge runtimes.
  • An Invigile account and API key (sk_invigile_…)
  • An interview whose external_id matches your ATS exam ID (or use interviewId)

Install

npm install @invigile/sdk
# or
yarn add @invigile/sdk
# or
pnpm add @invigile/sdk

Setup (once)

  1. In the Invigile dashboard, create an interview and set external_id to your ATS assessment ID.
  2. Create an API key under Dashboard → Integrations.
  3. Point apiBaseUrl at your Invigile app host (production: https://app.invigile.com).
  4. Allow your ATS origin in Invigile’s INVIGILE_CORS_ORIGINS (comma-separated).
# Your ATS / exam app
INVIGILE_API_KEY=sk_invigile_...
INVIGILE_API_BASE_URL=https://app.invigile.com

Prefer keeping the API key server-side when you can. If the browser must call initInvigile with apiKey, use a dedicated key and rotate it regularly.

Quick start

import { initInvigile, stopInvigile } from "@invigile/sdk";

await initInvigile({
  apiKey: process.env.INVIGILE_API_KEY!,
  apiBaseUrl: "https://app.invigile.com",
  externalId: "your-exam-id", // must match interview.external_id
  candidate: {
    email: "[email protected]",
    externalId: "ats-user-123", // optional ATS user id
  },
});

// When the session ends (or on React unmount)
await stopInvigile();

initInvigile opens a session, loads the interview policy, and starts listeners. Call stopInvigile() when the assessment ends.

React / Next.js (client component)

"use client";

import { useEffect } from "react";
import { initInvigile, stopInvigile } from "@invigile/sdk";

export function ExamProctoring({
  examExternalId,
  candidateEmail,
}: {
  examExternalId: string;
  candidateEmail: string;
}) {
  useEffect(() => {
    let active = true;

    void initInvigile({
      apiKey: process.env.NEXT_PUBLIC_INVIGILE_API_KEY!,
      apiBaseUrl: process.env.NEXT_PUBLIC_INVIGILE_API_BASE_URL!,
      externalId: examExternalId,
      candidate: { email: candidateEmail },
    }).catch((err) => {
      if (active) console.error("Invigile could not start:", err);
    });

    return () => {
      active = false;
      void stopInvigile();
    };
  }, [examExternalId, candidateEmail]);

  return null;
}

Recommended flow: Pre-gate → monitor

Use pre-gate on the welcome / intro screen (permissions, identity, OS Agent when required). Use init only on the assessment screen (no modal).

import { preGateInvigile, initInvigile, stopInvigile } from "@invigile/sdk";

const candidate = {
  email: "[email protected]",
  externalId: "ats-user-123",
};

// 1) Welcome screen
const gate = await preGateInvigile({
  apiKey: process.env.INVIGILE_API_KEY!,
  apiBaseUrl: "https://app.invigile.com",
  externalId: "your-exam-id",
  candidate,
});

// 2) Assessment screen — reuse camera / identity / agent link from the gate
await initInvigile({
  apiKey: process.env.INVIGILE_API_KEY!,
  apiBaseUrl: "https://app.invigile.com",
  externalId: "your-exam-id",
  candidate,
  camera: gate.cameraStream ?? undefined,
  diditSessionId: gate.diditSessionId ?? undefined,
  agentLinkToken: gate.agentLinkToken ?? undefined,
});

await stopInvigile();

When identity, vision, and OS signals are all off in the interview policy, preGateInvigile returns immediately without a modal.

Configuration

Pass either externalId or interviewId — not both.

| Option | Type | Required | Description | | ------ | ---- | -------- | ----------- | | apiKey | string | yes* | Invigile API key (sk_invigile_…) | | apiBaseUrl | string | yes | Invigile app base URL | | externalId | string | one of | Your ATS exam / assessment id | | interviewId | string | one of | Invigile interview UUID | | candidate.email | string | yes | Candidate email | | candidate.externalId | string | no | Your ATS user id | | camera | MediaStream \| HTMLVideoElement \| false | no | Reuse an existing camera, or false to skip | | diditSessionId | string | no | From preGateInvigile (identity continuity) | | agentLinkToken | string | no | From preGateInvigile (OS Agent signals) | | resume | boolean | no | Reopen a finished session (default true) | | debug | boolean | no | Verbose console logs (or localStorage.invigile_debug=1) | | sessionToken | string | yes* | Advanced: skip session open and attach with a server-issued token |

*Use either the apiKey + candidate flow or a sessionToken from your backend.

Camera (vision)

When multi_face, gaze_escape, or identity_verify are enabled on the interview, the SDK requests the camera itself. Raw video never leaves the browser — only signal metadata (and optional blurred evidence frames when opted in) is sent.

// Default: SDK calls getUserMedia when vision is enabled
await initInvigile({ apiKey, apiBaseUrl, externalId, candidate });

// ATS already has a stream — no second permission prompt
await initInvigile({ ..., camera: existingMediaStream });

// Disable camera entirely
await initInvigile({ ..., camera: false });

import { setCameraMonitoring } from "@invigile/sdk";
setCameraMonitoring(false); // pause inference without stopping tracks

Subpath exports

| Import | Use case | | ------ | -------- | | @invigile/sdk | initInvigile, stopInvigile, preGateInvigile, camera helpers | | @invigile/sdk/pre-gate | Welcome modal only | | @invigile/sdk/agent | OS Agent pairing / status helpers | | @invigile/sdk/agent-link | Agent link create / attach / revoke | | @invigile/sdk/vision | Vision tuning / lab |

Debug

await initInvigile({ ..., debug: true });
// or in DevTools:
localStorage.setItem("invigile_debug", "1");

Documentation

License

UNLICENSED — proprietary software. See your Invigile agreement for usage terms.