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

@swmansion/argent-cloud-sdk

v0.2.0

Published

Client library for Argent Cloud: typed HTTP API plus MoQ device streaming and input.

Readme

@swmansion/argent-cloud-sdk

Client library for Argent Cloud. It covers the two things every client needs — the control plane (router's HTTP API) and the device plane (MoQ video, input and screenshots) — so headless and interactive clients share one implementation instead of each keeping its own copy. Remote builds live alongside them in BuildsApi.

The control plane tracks a versioned wire protocol; this release speaks PROTOCOL_VERSION 2.

Used by the Argent Cloud webui and by the @swmansion/argent package.

Install

npm install @swmansion/argent-cloud-sdk @moq/net

@moq/watch is needed only for video rendering, and ws + @fails-components/webtransport only under Node. All three are optional peers.

Control plane

SimulatorApi speaks router's HTTP API. How a request is authenticated is the transport's business, so the same class works whether you hold a session token yourself or sit behind a proxy that holds one for you:

import {
  RouterAuthClient,
  SimulatorApi,
  makeBearerTransport,
} from "@swmansion/argent-cloud-sdk";

const auth = new RouterAuthClient(makeBearerTransport(routerUrl, undefined));
const { token } = await auth.login(username, apiKey);

const api = new SimulatorApi(makeBearerTransport(routerUrl, token));
await api.acquire(60);
const devices = await api.listSimulators();

Behind a session-owning proxy — the webui's Rust binary, say — swap in makeProxyTransport("/api") and skip the auth and session calls entirely.

Failures throw ApiError carrying the router's stable code; use isRetryable to spot a machine_unavailable you can wait out. A simctl that ran and refused throws SimctlError instead, carrying its exit code and both raw output streams.

Protocol version

The router's protocol is versioned, and a mismatch is a hard break rather than a degraded mode — so check it before issuing anything else:

await auth.assertProtocolVersion();          // probes GET /version
// or, from a login reply you already have:
assertProtocolVersion(loginResult.protocol_version);

Running simctl

simctl and spawn answer with a frame stream, so stdout and stderr stay separate and the exit status comes back with them. A non-zero exit is a successful call — the command ran and said no:

const { stdout, exit } = await api.simctl(["list", "devices", "--json"]);
if (exit?.code !== 0) throw new Error("simctl refused");
const devices = JSON.parse(new TextDecoder().decode(stdout));

Subcommands that name local files (addmedia, install_app_data, keychain add-cert) need those files uploaded with them — simctlStaged takes a tar of them plus the argv indices they occupy. Building the tar is yours; the SDK ships no tar writer.

Builds

BuildsApi submits a project tarball for a remote xcodebuild run. The submit response is the log stream, and the build id arrives with the headers, so status and cancellation are available while logs are still arriving:

import { BuildsApi } from "@swmansion/argent-cloud-sdk";

const builds = new BuildsApi(makeBearerTransport(routerUrl, token));
const { buildId, frames } = await builds.submit(descriptor, sourceTarGz);

for await (const frame of frames) {
  if (frame.kind === "result") console.log(frame.result);
  else process.stdout.write(frame.bytes);
}

await builds.installBuilt(buildId, udid);

Device plane

import {
  MoqDeviceSession,
  openWithDirectFallback,
  createDirectFallbackState,
} from "@swmansion/argent-cloud-sdk";

const fallback = createDirectFallbackState();
const connection = await openWithDirectFallback({
  getDirect: () => api.moqDirectInfo(udid),
  getRelay: () => api.moqInfo(udid),
  state: fallback,
});

const session = new MoqDeviceSession(connection);
await session.touch("Down", 0.5, 0.5);
await session.touch("Up", 0.5, 0.5);
const png = await session.screenshot();

openWithDirectFallback prefers the relay-less endpoint and drops to the relay if it isn't reachable. Share one DirectFallbackState across reconnects to the same device so a dead direct route is only discovered once.

Reconnect policy is deliberately yours: watch session.closed and open a new session when it settles.

Video (browser)

import { attachVideo } from "@swmansion/argent-cloud-sdk/video";

const video = attachVideo(session.connection, canvas, {
  onResize: () => relayoutOverlay(),
});
// later: video.close()

Node

There is no WebTransport in Node, so install the polyfill globals once before the first connect:

import { installNodeWebTransport } from "@swmansion/argent-cloud-sdk/node";

await installNodeWebTransport();

The input protocol

Input is protobuf DataChannelCommand on the MoQ control track. The encoder in src/proto/encoder.ts is written by hand rather than generated, so the browser bundle carries no protobuf runtime. proto/datachannel.proto is the canonical schema, and test/encoder.test.ts checks every encoder branch against protobufjs parsing that file — if the schema and the encoder drift apart, the test fails.

When simulator-server's schema changes, update both together.

Developing against an unpublished build

The webui depends on this package by path, so its dev loop needs nothing extra. For argent, which depends on the published version, build a tarball and install it:

npm run build && npm pack

Then in the argent checkout:

npm install /path/to/argent-cloud-sdk/swmansion-argent-cloud-sdk-<version>.tgz