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

@intomind/sdk

v1.4.3

Published

The IntoMind instrument client for JavaScript: the protocol, the session, the timebase, recording and the six export formats, and a Web Bluetooth transport.

Readme

@intomind/sdk

The IntoMind instrument client for JavaScript. One package, every IntoMind device, in a browser and in Node.

import { requestAndConnect } from "@intomind/sdk";

const device = await requestAndConnect({
  onEvent(event) {
    if (event.type === "samples") plot(event.batch);
    if (event.type === "gap") mark(event.gap);
  },
});
await device.send(device.session.startStream());

It owns the protocol spoken to a device, the session that turns notifications into events, the clock that puts those events on the host's timeline, and one transport for the browser. It knows nothing about any particular device beyond what that device tells it, and nothing about any application built on top of it.

What is in here

| | | |---|---| | src/protocol.ts | the wire, and nothing else | | src/session.ts | one device as a state machine: bytes in, events out | | src/timebase.ts | device time onto host time, and what it refuses to believe | | src/web-bluetooth.ts | the browser transport, and the only file that touches a radio | | src/capture/ | recordings: the recorder, the reader and the six exports, as the Python library makes them | | src/capture/node.ts | recordings on disk, in the folder the Python library uses, for Node | | src/index.ts | the public surface |

The protocol, the session, and the timebase do no input and no output. They take bytes that arrived and hand back bytes to send, so they run over whatever Bluetooth stack you already have, on whatever runtime you already use, and they can be tested without either.

import { Session, protocol } from "@intomind/sdk";

const session = new Session();
session.onDeviceInfo(await readDeviceInfoSomehow());
for (const event of session.onNotification(protocol.FILL.EEG_DATA, notification)) {
  // ...
}

Capabilities are the device's answer, never this package's assumption

A device declares what it is over the protocol, and everything follows from that declaration. The channel count, the converter's resolution and reference, the rates it offers, whether it can detect lead-off, whether it carries a model: all of it is asked and none of it is assumed.

session.requireInfo().channels   // what the device said
session.can("model")             // a capability bit, not a version number
session.setLeadoff(true)         // throws NotCapable if the device never claimed it

A table of specific hardware in this package is a defect. A capability the device does not claim is not asked for, and asking anyway throws rather than putting a byte on the wire the device will refuse.

The timeline is never silently repaired

Every sample carries the device's own index and the device time of its own conversion. A forward step in that index is a loss with an exact count. A step that is not forward is a break whose extent is not a number, and this package says so rather than returning a count that would be a fiction.

if (event.type === "gap") {
  event.gap.samplesLost;   // a number, or null for a break
}

A gap is emitted before the samples that follow it, so a caller writing samples down writes the gap down first. Nothing splices.

The contract is tested, not assumed

contract/conformance.json is emitted by the firmware from the codec the device itself runs. Every message this package decodes, it decodes to the fields that file states, and every malformed one it refuses for the reason that file states: truncated, invalid, or reserved, which are three different errors because the contract treats them as three different things.

npm test

No device, no network, no build step. That is the command, and there is no other. It needs Node 22.18 or newer, which runs the TypeScript as it is written. npm run build produces the JavaScript that is published, which runs on Node 20 and in any current browser.

Time

A device's clock is a different crystal from the host's. The fit between them is a line, and one exchange cannot tell a clock difference from a slow answer, so one exchange fixes an offset and claims no rate. A skew beyond a thousand parts per million, or a slope whose standard error is worse than a hundred parts per million, is refused rather than believed. The offset is kept, because the offset is the part that was measured.

await device.timeSync();
device.session.timebase?.fit;            // skewUsed says whether the rate is real
device.session.hostTime(batch.deviceTime);

Recordings

The session records as the Python library records, and @intomind/sdk/capture reads recordings and exports them in the Python library's six formats: BDF, EDF, CSV and TSV byte for byte the files Python writes, NPZ and MATLAB holding the same arrays.

for (let i = 0; i < 5; i++) await device.timeSync();
device.session.armRecorder();
await device.request(device.session.resetEpoch());
await device.request(device.session.startStream());
// ...
await device.request(device.session.stopStream());
const saved = device.session.saveRecording("my-recording");  // each file's name and bytes

The model

A device can carry an encoder that turns a window of signal into an embedding, and a head that turns that embedding into a few outputs. A head is weights, never code.

import { buildHead, quantizeEmbedding, evaluateHead, decodeHead } from "@intomind/sdk";

const blob = buildHead(weights, bias, scale, { name: "focus" });
evaluateHead(decodeHead(blob), quantizeEmbedding(embedding));

The embedding is quantized to a fixed scale that is part of the contract, so what a head produces on a host is what it produces on the device, because the device evaluates exactly those integers.

The browser

web-bluetooth.ts is the only file that reaches navigator.bluetooth. Web Bluetooth needs a secure context and a user gesture, so requestDevice has to be called from a click. Everything else in this package works with no browser at all, which is how the tests run.

License

Free software under the GNU Affero General Public License, version 3. A commercial license is available for building a closed product on this code or running a modified service without publishing the changes. Write to [email protected]. See LICENSING.md, and CONTRIBUTING.md before a first pull request.

IntoMind is a trademark of IntoMind, Inc. The license covers the code, not the name.