Library / SDK
astrid-runtime/sdk-js avatar
astrid-runtime/sdk-js

astrid-runtime/sdk-js: building Astrid capsules in TypeScript

JavaScript and TypeScript SDK for building Astrid capsules.

8,096 stars37 forksTypeScriptApache-2.0

At a glance

What is it?
The JavaScript and TypeScript SDK for Astrid capsules compiles your code to a wasip2 component and packs it into a .capsule archive. It is alpha software with an 11 MB binary, and the README says so.
Who is it for?
Adopt sdk-js if you are writing daemon-mode Astrid capsules in TypeScript and can accept an alpha SDK plus a roughly 11 MB raw wasm binary. Stay with sdk-rust if binary size or production stability matters more than ergonomics, since the host ABI is identical and a capsule can be ported without kernel changes.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 55 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What sdk-js is for, and who it is not for

Astrid capsules are wasm components that a kernel installs and runs. The kernel speaks a fixed host ABI, and the Rust SDK, sdk-rust, was the original way to target it. sdk-js exists so the same capsule can be written in JavaScript or TypeScript instead. The README is explicit that the two SDKs share "the same WIT contract, same wasip2 Component Model output, same .capsule archive format", and it claims the kernel cannot tell which language built a given binary.

The audience is therefore narrow and specific: developers who already run an Astrid kernel and want to write capsule logic in TypeScript, using node:fs/promises, node:child_process, WHATWG fetch, async iterators and disposable resource handles rather than Rust traits. The README frames the difference in idiom terms, saying that where the Rust SDK feels like writing against std, this one translates those patterns into Node conventions. If you are not targeting an Astrid kernel, nothing here applies to you. This is not a general-purpose JavaScript SDK, and the name overlaps heavily with unrelated search traffic around AWS, ArcGIS and other vendors' SDKs.

The three packages and the decorator surface

The workspace ships three packages. @astrid-runtime/sdk is the author-facing API, described as a module-by-module mirror of the Rust prelude: fs, net, process, env, time, log, plus Astrid-specific modules named ipc, kv, http, hooks, uplink, identity, approval, runtime, elicit, capabilities and interceptors. @astrid-runtime/build is the build orchestrator, which the README says runs tsc, esbuild and the ComponentizeJS programmatic API and emits a wasm32-wasip2 component. @astrid-runtime/sdk/contracts holds TypeScript types generated from astrid-contracts.wit, covering IPC event types such as Message, ToolCall, GenerateRequest and StreamEvent, usable on both ends of cross-capsule IPC.

The decorator set replaces Rust attributes one for one: @capsule, @tool, @interceptor, @hook, @command, @install, @upgrade and @run. That mapping is the main ergonomic argument for the SDK. A class marked @capsule holds state as ordinary fields, and a method marked @tool with mutable: true can increment that state, which is what the README's greeting counter example does. Whether that state survives across instantiations is not something the README addresses, and the notes directory referenced for design decisions is not reproduced here.

Install and first capsule: a short tutorial

The README's quick start assumes Node >=20 and TypeScript 5.2 or later. Create a directory, initialise a package, and install the SDK plus the build tooling as a dev dependency:

bash
mkdir my-capsule && cd my-capsule
npm init -y
npm install @astrid-runtime/sdk
npm install --save-dev @astrid-runtime/build typescript

Next, write a Capsule.toml manifest. The README's example declares the package name and version, a component entry pointing at the wasm file, a kv capability wildcard, and a publish entry for tool.v1.execute.* marked with wit = "opaque":

toml
[package]
name = "my-capsule"
version = "0.1.0"

[[component]]
id = "my-capsule"
file = "my-capsule.wasm"
type = "executable"

[capabilities]
kv = ["*"]

[publish]
"tool.v1.execute.*" = { wit = "opaque" }

Then write src/index.ts. The example class registers a greet tool that logs through the SDK's log module and returns a message plus a call count, and an @install lifecycle method that logs on installation:

typescript
import { capsule, tool, install, log, kv } from "@astrid-runtime/sdk";

@capsule
export class MyCapsule {
  greetings = 0;

  @tool("greet", { mutable: true })
  greet({ name }: { name: string }): { message: string; count: number } {
    this.greetings++;
    log.info(`greeting ${name} (#${this.greetings})`);
    return { message: `Hello, ${name}!`, count: this.greetings };
  }

  @install
  onInstall(): void {
    log.info("my-capsule installed");
  }
}

Build with the astrid CLI. The README gives two equivalent forms, and says the result lands in dist/my-capsule.capsule:

bash
astrid build           # or: astrid capsule install .

If you are working from a kernel checkout instead, the development section shows building astrid-build with cargo and pointing it at the example directory:

bash
cd core
cargo build -p astrid-build
./target/debug/astrid-build ../sdk-js/examples/test-capsule

The pipeline behind that command is documented as tsc for typecheck and emit, esbuild for bundling dist/ together with @astrid-runtime/sdk into one ESM while marking astrid:* WIT specifiers external, then ComponentizeJS to produce the wasip2 component, then a Rust-side pack_capsule_archive step. The README states that @astrid-runtime/build/src/index.mjs is a small Node CLI that Rust's astrid build invokes when it detects a package.json and Capsule.toml project.

Binary size is the trade-off you are accepting

The README devotes a section to this and does not soften it. A JavaScript capsule costs roughly 11 MB raw and 3.5 MB gzipped inside the .capsule archive, because the StarlingMonkey runtime is embedded. A Rust capsule of the same contract is around 200 KB. That is roughly two orders of magnitude, and it is a property of the runtime embed rather than of your own code, so no amount of tree shaking will remove it.

The README's own framing is that this is acceptable for daemon-mode workloads where capsules load once. That qualifier matters. If your deployment instantiates capsules frequently, or if archive size is constrained by where you ship it, the size difference is the deciding factor and the README says as much: "if size matters more than ergonomics, write Rust". Because the host ABI is identical, porting a hot capsule between the two languages requires no kernel changes, which makes the choice reversible rather than permanent.

Alpha status, smoke testing and what the README leaves open

The status section states plainly that this is alpha. It says the vertical slice has been proven end to end: TypeScript to wasip2 component to .capsule, installed by astrid capsule install, with kernel lifecycle hook execution. It then says the daemon-mode tool-dispatch round-trip, shown as a /tool greet command with a JSON argument, is on the same code path as install because it uses the same wasmtime instantiation and linker contract, and describes it as "ready for human-operator smoke testing".

Read that carefully. Lifecycle installation is described as proven; interactive tool dispatch is described as sharing the code path and awaiting smoke testing. Those are different levels of confidence, and anyone planning to build on the tool-call surface should treat the second claim as untested rather than as a guarantee. The README also does not document rollback, upgrade failure handling, or what happens to capsule state across reinstantiation, and it points to notes/phase-{0,1,2,3-install}.md for known follow-ups without listing them. There is no compatibility matrix for kernel versions, and no statement about which Astrid kernel release the v0.2.0 SDK targets.

sdk-rust is the alternative, and the difference is not just syntax

The obvious alternative is sdk-rust, the companion SDK from the same organisation. The README positions them as siblings producing indistinguishable binaries: same WIT contract, same wasip2 output, same archive format. The practical difference is the runtime you embed. Rust capsules compile close to the metal and land around 200 KB; JavaScript capsules carry StarlingMonkey and land around 11 MB raw. The second difference is the programming model. Rust capsules expose attributes and traits; sdk-js exposes decorators over classes and maps host facilities to Node idioms such as async iterators and WHATWG fetch.

Choosing between them is therefore a question of what you are optimising for. If you want the smallest artifact and the fewest moving parts in the build chain, sdk-rust wins on both counts and the README concedes the size point directly. If your team writes TypeScript and the capsule is a long-lived daemon that loads once, the size penalty is a one-time cost and the decorator API is the reason to pick sdk-js. Neither choice locks you in, because the ABI is shared.

Licence, workspace layout and upgrade cost

The repository is dual-licensed under MIT and Apache 2.0, with separate LICENSE-MIT and LICENSE-APACHE files, and the workspace package.json declares "license": "MIT OR Apache-2.0". Copyright is attributed to Joshua J. Bouw and Unicity Labs. Dual licensing of this kind is permissive and standard for SDKs; the choice between the two texts is yours, and the repository does not state a preference. This is a description of what the files say, not legal advice.

The layout is an npm workspace with packages/, examples/test-capsule/ as a minimal end-to-end example mirroring the Rust example, notes/ with phase-by-phase development notes, and a tsconfig.base.json at the root. The root scripts are build and test, both delegating to workspaces with --if-present, and the only root devDependency is TypeScript ^5.6.0. The engine requirement is Node >=20.

Upgrade cost is hard to judge from what is published. There are two releases, v0.1.0 in May 2026 and v0.2.0 in August 2026, and the last push to the repository was on 2026-08-05, the same day as the v0.2.0 tag. The CHANGELOG.md exists at the top level but its contents are not reproduced here, so there is no published migration note to read. On a pre-1.0 SDK with two releases, expect the decorator surface and the build pipeline to move, and pin the SDK and build packages together so the tsc, esbuild and ComponentizeJS stages stay in step.

Editorial conclusion

Adopt sdk-js if you are writing daemon-mode Astrid capsules in TypeScript and can accept an alpha SDK plus a roughly 11 MB raw wasm binary. Stay with sdk-rust if binary size or production stability matters more than ergonomics, since the host ABI is identical and a capsule can be ported without kernel changes. Before committing, verify that your Node version satisfies the >=20 engine requirement, that `astrid build` produces a .capsule in dist/, and that the tool-dispatch round trip described in the README works against your kernel build.

Frequently asked questions

What is sdk-js?

It is the JavaScript and TypeScript SDK for building Astrid capsules, published as @astrid-runtime/sdk with a build orchestrator in @astrid-runtime/build. It produces the same wasip2 component and .capsule archive format as the Rust SDK.

What is an SDK in JavaScript?

In this project's case the SDK is the author-facing module set you import when writing a capsule, covering fs, net, process, env, time, log and Astrid-specific modules such as ipc, kv, http and hooks. It is a library you depend on, plus a build tool that turns your code into a wasm component.

What is the difference between an SDK and an API?

sdk-js is the SDK: the decorators, modules and build pipeline you write against. The API it targets is the Astrid host ABI, described in the README as a fixed WIT contract shared with sdk-rust, which the kernel exposes to whichever language built the capsule.

What does SDK stand for?

The README does not expand the acronym. It only describes @astrid-runtime/sdk as the capsule author API and a module-by-module mirror of the Rust prelude.

Is an SDK like a library?

In this repository the SDK is a workspace of npm packages you install, so it behaves like a library you import. It also ships @astrid-runtime/build, a CLI that runs tsc, esbuild and ComponentizeJS to produce the wasm component.

Official sources

  1. astrid-runtime/sdk-js on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/astrid-runtime-sdk-js.svg)](https://hysenlabs.com/projects/astrid-runtime-sdk-js)