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

@lookloot/capture-sdk

v1.0.6

Published

Public LookLoot capture SDK for partner desktop apps.

Readme

LookLoot Capture SDK

Add LookLoot capture to a partner desktop app with a small app-side client and a server-side token route.

Install

pnpm add @lookloot/capture-sdk

The package is ESM-only, targets Node.js 22 or newer, and belongs in the Electron main-process package. The host app must provide Electron. The SDK package bundles Windows input/audio helpers and the FFmpeg fallback dependency.

Partners install only @lookloot/capture-sdk. The private runtime and shared capture contracts are bundled into the published SDK build, so partners do not add @lookloot/capture-runtime or @lookloot/capture-contracts to their app.

Windows game capture normally requires a bundled OBS Studio portable runtime. Do not depend on a user-installed OBS copy. For packaged Electron builds, copy the portable OBS root to resources/obs so resources/obs/bin/64bit/obs64.exe exists. For local development or custom packagers, pass obsPath to the SDK or set LOOKLOOT_OBS_PATH. Overwolf Electron apps can choose captureEngine: "overwolf-recorder" and package Overwolf's Recorder module instead of OBS.

Prepare that runtime during your app build:

npx lookloot-capture-prepare-obs --out vendor/obs

The prepare command is idempotent. Once vendor/obs/bin/64bit/obs64.exe exists for the requested OBS version, it exits without re-downloading or re-extracting OBS. Re-run with --force only when you want to refresh the output directory. The download cache defaults to the OS user cache directory; pass --cache or set LOOKLOOT_OBS_CACHE_DIR when CI needs a managed cache path.

1. Mint device tokens on your backend

Keep your LookLoot partner key on your server. Your app should call your own backend, and your backend should exchange the registered source app ID plus either a signed-in user ID or an anonymous SDK install ID for a short-lived LookLoot device token.

// Example Express-style route on your backend.
app.post("/api/lookloot/device-token", optionalUser, async (req, res) => {
  const externalUserId = req.user?.id ? `user:${req.user.id}` : undefined;
  const anonymousId = externalUserId ? undefined : req.body?.anonymousId;

  const upstream = await fetch("https://www.lookloot.gg/api/partner/auth/token", {
    method: "POST",
    headers: {
      authorization: `Bearer ${process.env.LOOKLOOT_PARTNER_KEY}`,
      "content-type": "application/json",
    },
    body: JSON.stringify({
      externalUserId,
      anonymousId,
      appId: req.body?.appId,
      appVersion: req.body?.appVersion,
      deviceName: req.body?.deviceName,
    }),
  });

  if (!upstream.ok) {
    const detail = await upstream.text().catch(() => "");
    console.error("[lookloot] token upstream failed", upstream.status, detail);
    res.status(502).json({ error: "Could not create LookLoot device token" });
    return;
  }

  const data = await upstream.json();
  res.json({
    token: data.token,
    deviceId: data.deviceId,
    partnerEndUserId: data.partnerEndUserId,
    externalUserId: data.externalUserId,
    anonymous: data.anonymous,
    app: data.app,
  });
});

Only token is required by the SDK. The other response fields are useful for your own logs and device-management UI. appId must be an active LookLoot-registered app slug for your partner account; it is not freeform client metadata. externalUserId is optional when the user is not signed in. In that case, forward the SDK-provided anonymousId; LookLoot stores a stable hash of it instead of a raw user identity.

The token endpoint accepts appId plus exactly one of externalUserId or anonymousId. appVersion and deviceName are optional. Additional request fields are ignored.

2. Initialize in your app

import { app } from "electron";
import { join } from "node:path";
import { LookLootCapture } from "@lookloot/capture-sdk";

const capture = new LookLootCapture({
  appId: "your-registered-app-slug",
  appVersion: app.getVersion(),
  dataDir: join(app.getPath("userData"), "lookloot"),
  deviceName: app.getName(),
  obsPath: process.env.LOOKLOOT_OBS_PATH,
  captureEngine: "auto",
  getDeviceToken: async ({ appId, appVersion, deviceName, anonymousId }) => {
    const res = await fetch("https://your-api.example.com/api/lookloot/device-token", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ appId, appVersion, deviceName, anonymousId }),
    });

    if (!res.ok) throw new Error("LookLoot token request failed");
    const data = await res.json();
    return data.token;
  },
});

capture.on("state-change", (state) => {
  // "idle" | "active"
});

capture.on("error", (error) => {
  console.error("[lookloot]", error);
});

await capture.init();

dataDir is optional. Passing your app's userData path is recommended so working files stay inside your app profile.

obsPath is optional in packaged Electron apps when OBS is bundled at resources/obs. It is recommended for local smoke tests and nonstandard packagers.

captureEngine is optional and defaults to "auto", which currently uses the bundled OBS runtime. Use "overwolf-recorder" only in Overwolf Electron builds that include "recorder" in overwolf.packages and pass app.overwolf.packages to the SDK.

Apps that already install a privileged helper can also pass elevatedCapturePipeName. This lets the SDK route protected/admin game capture through that helper without exposing OBS UI or falling back to desktop capture. Most partner apps should omit it unless they own that helper lifecycle.

If omitted, the SDK uses an OS-appropriate LookLoot folder:

| OS | Default | | --- | --- | | macOS | ~/Library/Application Support/LookLoot/Capture | | Windows | %LOCALAPPDATA%\LookLoot\Capture | | Linux | $XDG_STATE_HOME/lookloot/capture or ~/.local/state/lookloot/capture |

3. Package the Windows capture runtime

The SDK package is intentionally not bloated with the full OBS runtime. Your Windows installer must include the official portable OBS Studio runtime as an Electron resource:

{
  "build": {
    "extraResources": [
      {
        "from": "vendor/obs",
        "to": "obs",
        "filter": ["**/*"]
      }
    ],
    "asarUnpack": [
      "**/node_modules/ffmpeg-static/**",
      "**/node_modules/@lookloot/capture-sdk/dist/input-helper/**/*",
      "**/node_modules/@lookloot/capture-sdk/dist/audio-helper/**/*"
    ]
  }
}

vendor/obs should be the portable OBS root that contains bin/64bit/obs64.exe, data, and obs-plugins. Package it only through extraResources; if your app files glob includes vendor, add an exclusion such as !vendor/** so vendor/obs is not packaged twice. Keep any custom OBS download cache outside packaged app files. After packaging, verify that your unpacked app contains resources/obs/bin/64bit/obs64.exe.

API

new LookLootCapture(options)
await capture.init()
await capture.start()
await capture.stop()
await capture.dispose()
capture.getState()
capture.getRuntimeDiagnostics()
await capture.runLocalVerification()
await capture.openLocalVerificationViewer()
capture.on("state-change", listener)
capture.on("error", listener)

Most apps only need init() and the state-change event. After init() succeeds, the SDK watches for detected game processes and starts recording automatically as soon as one is detected. Recording stops when the game exits, when stop() is called, or when dispose() runs during app shutdown. The SDK is not limited to a LookLoot telemetry allowlist; it detects known game processes and common game-library install paths while filtering normal desktop/browser windows. The SDK installs an Electron before-quit cleanup handler by default so sudden app exits still get a chance to finalize the active session; call dispose() yourself if your app has a custom shutdown flow. init() is safe to call again to refresh a rotated device token. start() remains available for explicit retry/manual capture requests and returns Promise<{ ok: true } | { ok: false; reason: string }>; getRuntimeDiagnostics() lets installers and smoke tests confirm the selected capture engine, FFmpeg, and helper assets are present before capture starts.

For developer self-checks, runLocalVerification() records a short disk-only local capture without calling getDeviceToken or uploading anything. Open a game, keep it focused, press a few keys or click while it runs, then inspect result.video, result.input, and result.sessionDir. Call openLocalVerificationViewer(result) to open a bundled visual report with local video playback, game/status checks, and keyboard/mouse input highlights. This verifies local video and input capture before checking Deployed Telemetry dashboard ingestion.

Security Notes

  • Do not ship LOOKLOOT_PARTNER_KEY in desktop or browser code.
  • The public SDK only exposes coarse "idle" / "active" state.
  • Published packages ship the obfuscated bundled runtime, type declarations, this README, recorder helper HTML, the OBS preparation CLI, and bundled Windows input/audio helpers. Source maps and source files are not published.
  • OBS Studio is redistributed as a separate runtime in your desktop installer, not embedded into the npm package.