@kamilio/hatch-sleep-sdk
v0.1.3
Published
Unofficial JavaScript SDK and Toolcraft CLI for Hatch Sleep devices
Maintainers
Readme
hatch-sleep-sdk
Unofficial, typed JavaScript SDK and Toolcraft-powered CLI for Hatch Sleep devices. It uses the same private Hatch cloud APIs as the mobile app. Hatch does not publish or support these APIs, so applications should handle upstream changes gracefully.
Supported devices
Discovery recognizes Rest Mini, Rest+, Rest (2nd generation), Rest Baby, Restore, Restore 2, and Restore 3 product identifiers. Normalized shadow reads and controls currently support the second-generation Rest family (riot and riotPlus). Unsupported products fail explicitly instead of receiving an unsafe payload.
Install
npm install @kamilio/hatch-sleep-sdkNode.js 18.18 or newer is required.
The published hatch CLI bundles Toolcraft 0.0.92 and its CLI-only dependencies into a standalone artifact. Consumers do not install a separate Toolcraft runtime, and the SDK library entry points do not load Toolcraft. The package includes THIRD_PARTY_NOTICES.md for bundled code, verified through Toolcraft's public schema-versioned composition manifest. Tests use Toolcraft's deterministic command-tree snapshot API to verify the complete CLI surface and its in-memory report renderer to assert declared-secret redaction without parsing help text or writing diagnostic files.
JavaScript SDK
import { HatchClient } from "@kamilio/hatch-sleep-sdk";
const hatch = new HatchClient({
email: process.env.HATCH_LOGIN,
password: process.env.HATCH_PASSWORD,
timeoutMs: 15_000,
retries: 2,
});
try {
const [device] = await hatch.listDevices();
if (!device) throw new Error("No Hatch devices found");
const state = await hatch.getState(device);
console.log(state);
} finally {
await hatch.close();
}Control methods change the physical device. stopSound() stops audio while preserving the active light snapshot. stop() ends remote sound or an active routine without forcing unrelated light or sound fields, and turnLightOff() controls only the light:
async function controlDevice(hatch, device) {
await hatch.setLight(device, {
red: 255,
green: 120,
blue: 20,
brightness: 35,
});
await hatch.playSound(device, { sound: "White Noise", volume: 30 });
await hatch.stopSound(device);
await hatch.stop(device);
await hatch.turnLightOff(device);
}Device selection
Methods accept a device object or a unique device ID, MAC address, AWS thing name, or case-insensitive name. The selector can be omitted when the account has exactly one device. hatch devices list prints each selector-safe AWS thing name alongside the account-local ID and MAC address.
Client lifecycle and retries
timeoutMs must be positive. retries must be an integer from 0 through 10; exponential backoff and server-provided retry delays are capped. A custom apiUrl must use HTTPS, cannot contain credentials/query/fragment data, and retains its base path.
Use clearSession() to cancel active login, REST retry, Cognito, and device operations and discard cached Hatch/AWS sessions while keeping the client reusable. Prefer await close() for deterministic terminal cleanup; concurrent calls share the same shutdown promise and result. destroy() starts that same terminal cleanup as a fire-and-forget compatibility helper, so a later close() can still await its completion or observe its failure. MQTT shutdown actively cancels queued work and has a bounded teardown wait; connection errors invalidate the socket so the next queued operation creates a fresh connection.
REST and Cognito timeouts race both the request and response body against cancellation, so an injected fetch implementation cannot make shutdown or timeout handling wait forever by ignoring AbortSignal. REST, Cognito, and MQTT payloads have a one-megabyte maximum before JSON parsing or publishing; circular desired state is rejected before a socket is opened.
API
login()andclearSession()manage authentication.listDevices()andresolveDevice()discover devices.getState()andupdateState()read or update the AWS IoT shadow.listSounds()andlistFavorites()discover playable content; sound results include sanitizedimageUrlartwork when Hatch exposes it.setLight()andturnLightOff()control the light.setVolume(),playSound(),playFavorite(),stopSound(), andstop()control playback.setClock()andsetToddlerLock()control Rest-specific features.close()clears credentials and single-flights callers while waiting for AWS clients to close;destroy()remains as a synchronous fire-and-forget compatibility helper.
HatchShadowConnection, ShadowConnectionOptions, and ShadowCredentials are exported for advanced callers that already possess temporary AWS IoT credentials. Normal integrations should use HatchClient, which obtains and rotates those credentials and validates the supported Hatch protocol.
Public SDK failures derive from HatchError and expose a stable code, with status when an HTTP response supplied one. Callers can distinguish HatchAuthenticationError, HatchRateLimitError, HatchValidationError, HatchDeviceNotFoundError, HatchAmbiguousDeviceError, and HatchUnsupportedDeviceError without parsing message text.
CLI
The hatch binary is generated by Toolcraft. Set credentials in the environment:
export HATCH_LOGIN="[email protected]"
export HATCH_PASSWORD="your-password"
hatch devices list
hatch status
hatch light set --red 255 --green 100 --blue 20 --brightness 40
hatch sound list
hatch sound play "White Noise" --volume 30
hatch play preset "Bedtime"
hatch favorites list
hatch favorites play "Bedtime"
hatch clock on --brightness 25
hatch lock on
hatch sound stopAdd --output json to any command for machine-readable output. Use --device when an account has multiple devices.
The status command includes normalized battery level and Hatch charging-status code when the device reports them.
Hatch calls saved routines “favorites”; play preset is the user-facing alias for playing one of the active favorites.
Digit-only sound, favorite, and preset arguments are tried as IDs first and then as exact titles when no ID matches.
Turning off the light preserves routine and remote sound playback; light-only remote mode is stopped when its light is turned off.
Security and reliability
- Passwords and Hatch/AWS tokens are never returned from public methods.
- Temporary AWS credentials are cached only in memory and refreshed before expiration.
- Requests have timeouts, bounded retries, normalized errors, and one automatic re-login for expired Hatch sessions.
- Malformed cloud channels are clamped, impossible device metadata is ignored or rejected, and remote sound URLs must be credential-free HTTP(S) URLs without query strings or fragments.
- Public
rawpayloads recursively remove credential-like fields and unsafe URL values; cloud-controlled display text is bounded and stripped of terminal and bidi controls, while Hatch and AWS Cognito error text is discarded if it contains credential terminology, account or identity secrets, or URLs. - Device discovery returns isolated copies, so changing a returned device or nested
rawmetadata cannot corrupt the client's cached catalog. - Toolcraft error-report verification asserts that declared Hatch secret values remain redacted.
- On command failure, Toolcraft diagnostics are created under
.toolcraft/errors; the CLI sets an owner-only process umask first, and package verification requires private report directories and files on POSIX systems. - This library never logs credentials or raw authentication responses.
- Custom API base URLs must use HTTPS and cannot contain credentials, query parameters, or fragments.
- AWS IoT endpoints must use a structured AWS region and a matching
amazonaws.comoramazonaws.com.cnIoT hostname.
Development
npm test runs the offline SDK suite with per-file V8 coverage and fails when any runtime module falls below 89% statements/lines, 80% branches, or 90% functions. CLI entry wiring and both ESM/CommonJS package entry points are verified separately from a clean packed-package consumer.
Disclaimer
This project is not affiliated with or endorsed by Hatch Baby, Inc. “Hatch” and related marks belong to their respective owner.
