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

@screenpipe/sdk

v0.4.3

Published

Screen recording SDK for Electron and Node apps, powered by screenpipe's native capture stack.

Readme

@screenpipe/sdk

Commercial screen recording SDK for Electron, Swift, Tauri, and Node apps.

The SDK exposes the capture primitives from the native screenpipe stack: record an MP4, grab JPEG preview snapshots, read a mic level for preflight UI, and inspect the focused app.

SDK Surfaces

| Surface | Source | Example | | --- | --- | --- | | Node | index.js, index.d.ts | examples/record-10s.mjs | | Electron | electron, session | examples/electron-app | | Swift | Package.swift, Sources/Screenpipe | examples/swift-app | | Tauri | tauri | examples/tauri-app |

Detailed embed notes live in docs/integration.md.

Example Apps

| Electron | Swift | Tauri | | --- | --- | --- | | Electron example app | Swift example app | Tauri example app | | examples/electron-app | examples/swift-app | examples/tauri-app |

See examples/README.md for run commands and smoke checks for all three apps.

Install

npm install @screenpipe/sdk
# or
bun add @screenpipe/sdk

This package is source-available under the Screenpipe Enterprise License. It is not covered by the root repository MIT license. See LICENSE.md.

Node Quick Start

import { Recorder, requestPermissions } from "@screenpipe/sdk";

const permissions = await requestPermissions();
if (!permissions.screen) {
  throw new Error("Screen Recording permission is required");
}

const recorder = new Recorder({
  output: "/tmp/session.mp4",
  // Optional privacy filters — recording pauses (hard cut in the MP4)
  // while a matching window/URL is focused.
  // Plain strings match anywhere; `App::Title` scopes to one window of one app.
  ignoredWindows: ["1password", "private", "Slack::#hr"],
  ignoredUrls: ["wellsfargo.com", "chase"],
});
await recorder.start();

// ... user does stuff ...

await recorder.stop();

Core API

new Recorder(options)

  • options.output (string, required): path where the MP4 is written.

  • options.monitorId (number, optional): display id; defaults to the primary display.

  • options.microphone (boolean, optional): accepted for forward compatibility.

  • options.systemAudio (boolean, optional): accepted for forward compatibility.

  • options.ignoredWindows (string[], optional): substring patterns matched case-insensitively against the focused app name and window title. While a matching window is in focus, the recorder skips writing frames — the MP4 contains a hard cut over the filtered period. Mirrors the engine's --ignored-windows CLI flag.

    Each pattern may use an optional App::Title scope: "Slack::#hr" skips only the #hr window inside Slack and leaves other Slack channels recording. "::Confidential" matches any app whose title contains "Confidential". Plain "Slack" keeps the legacy "app OR title contains" behavior.

  • options.includedWindows (string[], optional): substring whitelist. If non-empty, frames are written ONLY while a matching window is focused. Scoped entries ("Greenhouse::Candidates") create a per-app whitelist — other apps stay unaffected. Unscoped entries keep the legacy "must match app or title" global semantics. Mirrors --included-windows.

  • options.ignoredUrls (string[], optional): URL patterns to skip (case-insensitive, domain-aware match — chase matches chase.com and online.chase.com but not purchase.com). When the focused browser is on a matching URL, the recorder skips writing frames. Mirrors --ignored-urls.

Filtering uses the macOS Accessibility API; without that permission the filter fails open (records everything). Without any filter list set, the recorder stays on the zero-overhead fast path — no a11y polling is done.

Methods

| Method | Purpose | | --- | --- | | start() | Start screen capture and write frames into the MP4. | | stop() | Stop capture, flush the MP4 trailer, and close the file. Safe to call more than once. | | snapshot() | Capture the recorder's monitor as a JPEG preview. | | framesWritten() | Return frames written since start(). | | audioLevel() | Return a smoothed microphone RMS level in [0, 1] for preflight UI. | | focusedApp() | Return best-effort focused-window metadata; requires Accessibility permission on macOS. | | filterStatus() | Return { paused, reason } for the window/URL filter. Poll, or subscribe via the session wrapper's paused/resumed events. | | setFilters(patch) | Replace the active filter lists at runtime — { ignoredWindows?, includedWindows?, ignoredUrls? }. Takes effect within ≤ 1 s. | | requestPermissions() | Trigger or check supported OS permissions. |

Filter events (session wrapper)

createScreenpipeSession emits paused and resumed events whenever the filter verdict flips. Payload: { paused: boolean, reason: string | null } where reason is one of "ignored_window", "included_window_mismatch", "ignored_url", "incognito", "excluded_app".

session.on("paused", ({ reason }) => {
  showBanner(`recording paused — ${reason}`);
});
session.on("resumed", () => {
  hideBanner();
});

// Runtime toggle (e.g. user flips "Pause on banking" in your settings UI):
await session.setFilters({ ignoredUrls: ["chase", "wellsfargo.com"] });

Audio is not muxed into the MP4 in v0.1.0.

Telemetry & user identification

The session wrapper reports a small, PII-scrubbed set of crash and usage events to screenpipe so we can keep the SDK healthy in the wild. Pass a userId and that identifier is attached to every event, so a specific end user of your app shows up in screenpipe's Sentry (crashes) and PostHog (usage) dashboards.

import { createScreenpipeSession } from "@screenpipe/sdk/session";

const session = createScreenpipeSession({
  userId: currentUser.id, // identifies this user in screenpipe's dashboards
  appName: "acme-recorder", // optional segmentation tag
});
  • What is sent. Crashes/errors go to Sentry (with the error message). Usage goes to PostHog: recording_started, recording_stopped (frame/byte/duration counts only), recording_paused/recording_resumed (with the enum reason), permissions_changed, plus one session_initialized ping. Window titles, app names, URLs and output file paths are never sent to PostHog.
  • What is NOT sent. No screen content, no audio, no clipboard, no app_switched stream, no frames_progress ticks.
  • Opt out. Set telemetry: false in the options, or set the env var SCREENPIPE_SDK_TELEMETRY=0 (also honors DO_NOT_TRACK=1 and SCREENPIPE_DISABLE_ANALYTICS=1). When off, the SDK makes no network calls.

Without a userId, events fall back to a per-session anonymous id, so set userId if you want stable identification across sessions.

Per-surface usage

All four surfaces accept the same userId / appName / telemetry knobs.

Electron (via the session passed to registerScreenpipeIpc):

registerScreenpipeIpc({ ipcMain, app, sessionOptions: { userId: currentUser.id } });

Swift (forwarded to the bundled Node bridge as env vars):

let config = ScreenpipeClient.Configuration(
  sdkRoot: sdkRoot,
  userId: currentUser.id,        // identifies this user in screenpipe's dashboards
  appName: "acme-recorder",      // optional
  telemetryEnabled: true         // set false to disable
)
let client = try ScreenpipeClient(configuration: config)

Tauri — reporting happens natively in the Rust plugin (no webview fetch, so no Content-Security-Policy to configure). The JS client forwards the identity to the plugin via screenpipe_identify on creation:

const client = createScreenpipeTauriClient({ userId: currentUser.id });

You can also set it (or a Rust-side default) when registering the plugin:

tauri::Builder::default()
    .plugin(screenpipe_tauri::init(
        screenpipe_tauri::ScreenpipeConfig::default().user_id("user-123"),
    ))

Development

bun install
bun run build:debug
node --test --test-concurrency=1 "__test__/**/*.test.mjs"
swift test

Example app smoke checks:

npm --prefix examples/electron-app run smoke
npm --prefix examples/tauri-app run smoke
SCREENPIPE_SWIFT_EXAMPLE_SMOKE=1 swift run --package-path examples/swift-app ScreenpipeExample

Run the optional native Tauri example compile with:

SCREENPIPE_RUN_NATIVE_EXAMPLE_BUILDS=1 node --test --test-concurrency=1 __test__/examples_e2e.test.mjs

Before publishing:

cargo test --lib
bun run build
bun run prepublishOnly
npm pack --dry-run

Publish generated platform packages first, then publish the root @screenpipe/sdk package.

Platforms

| OS | Architecture | Status | | --- | --- | --- | | macOS | Apple Silicon | Supported | | macOS | Intel | Supported | | Windows | x64 | Builds in CI; runtime validation required before public launch | | Windows | ARM64 | Builds in CI; runtime validation required before public launch | | Linux | - | Not supported in v0.1.0 |