An idiomatic TypeScript wrapper around NAIF SPICE - for Node and the browser.
See the codeTypeScript-first access to NASA’s SPICE geometry toolkit — in Node.js and the browser (via WebAssembly).

SPICE is a toolkit (and data format ecosystem) developed by NAIF (NASA’s Navigation and Ancillary Information Facility) for space-mission geometry. It computes positions, orientations, frames, and time conversions using mission-provided “kernels” (ephemerides, constants, pointing, etc.). It’s widely used across NASA and the planetary science community to make geometry calculations reproducible and shareable.
tspice is a set of TypeScript packages that let you load SPICE kernels and execute common SPICE workflows (time conversion, ephemerides, frames, geometry) from modern JS runtimes.
If your target runtime is a browser, or your application is already TypeScript/Node and you want a first-class, typed API over CSPICE, tspice is designed to fill that gap.
tspice links against CSPICE (or a CSPICE-derived build) behind a TypeScript API. If you need CSPICE directly, download it from NAIF.
@rybosome/tspice is ESM-only..wasm assets (you may need to provide an explicit wasmUrl depending on your tooling).SPICE is stateful: loading kernels mutates a process-wide global kernel pool inside SPICE, and many routines read from (and sometimes affect) that shared state.
Isolation (separating kernel-sets and workloads) can be achieved by creating multiple process or WebWorker instances, depending on runtime.
pnpm add @rybosome/tspice
# or: npm i @rybosome/tspice
import { kernels, spiceClients } from "@rybosome/tspice";
async function main() {
// A small, CORS-enabled catalog hosted for quickstart/testing.
// Not suitable for production.
const kernelPack = kernels.tspice().pick(
"lsk/naif0012.tls",
"pck/pck00011.tpc",
"spk/planets/de432s.bsp",
);
// Build the client and load the given kernels
const { spice, dispose } = await spiceClients
.withKernels(kernelPack)
.toAsync({ backend: "wasm" });
try {
const et = await spice.kit.utcToEt("2000 JAN 01 12:00:00");
const state = await spice.kit.getState({ target: "EARTH", observer: "SUN", at: et });
console.log(state.position, state.velocity);
} finally {
await dispose();
}
}
main().catch(console.error);
In a production application, it is recommended to host kernels yourself or enable a proxy.
The kernels.naif() catalog can be configured to point at your hosted entries, or you can load bespoke kernels.
import { kernels } from "@rybosome/tspice";
// Hosting a mirror of NAIF's catalog at https://your-app.example/kernels/naif
const naifKernels = kernels
.naif({
origin: "https://your-app.example/kernels/naif/",
pathBase: "naif/",
})
.pick(
"lsk/naif0012.tls",
"pck/pck00011.tpc",
"spk/planets/de432s.bsp",
);
// Hosting a custom catalog at https://your-app.example/kernels/custom
const customKernels = kernels
.custom({
origin: "https://your-app.example/kernels/custom/",
pathBase: "custom/",
})
.pick("planets/my_custom_kernel.bsp");
import { kernels, spiceClients } from "@rybosome/tspice";
async function main() {
// We can download kernels directly from NAIF servers in Node.
const kernelPack = kernels.naif()
.pick(
"lsk/naif0012.tls",
"pck/pck00011.tpc",
"spk/planets/de432s.bsp",
);
// Use the builder to create a synchronous, caching client.
// `dispose()` is still async and should be awaited.
const { spice, dispose } = await spiceClients
.caching({ maxEntries: 10_000, ttlMs: null })
.withKernels(kernelPack)
.toSync({ backend: "node" });
try {
const et = spice.kit.utcToEt("2000 JAN 01 12:00:00");
const state = spice.kit.getState({ target: "EARTH", observer: "SUN", at: et });
console.log(state.position, state.velocity);
} finally {
await dispose();
}
}
main().catch(console.error);
CSPICE exposes 652 public routines; 162 are currently implemented in tspice.
docs/cspice-function-inventory.mdtspice exposes a stable backend contract that models the CSPICE routine surface. That contract is designed to evolve conservatively as additional CSPICE functions are implemented.
tspice follows SemVer. As a pre-1.0.0 project, minor versions may introduce breaking changes. Within a given minor line (e.g. 0.1.x), patch releases are guaranteed not to break the public API.
Because CSPICE itself is a mature and stable toolkit, long-term API churn in tspice is expected to be low.
In addition to typical unit testing, tspice runs parity tests with CSPICE as the reference, and also checks that the Node and WASM backends stay consistent for the same kernels and inputs. tspice preserves CSPICE double-precision semantics; numeric comparisons are verified against CSPICE with defined tolerances.
packages/py-parity-checking) executes matching workflows against tspice, comparing normalized outputs against live CSPICE-backed SpiceyPy behavior.docs/spicebackend-cspice-mapping.md.@rybosome/tspice (facade) — the user-facing entrypoint (packages/tspice/).SpiceBackend (contract) — the shared TypeScript interface all backends implement (packages/backend-contract/).packages/backend-node/packages/backend-wasm/backend-shim-c (shared C shim) — a shared C integration layer reused by both backends (packages/backend-shim-c/)..wasm.flowchart TD
Facade["@rybosome/tspice (facade)"] --> Contract["SpiceBackend (contract)"]
Contract --> Node["backend-node (native addon)"]
Contract --> Wasm["backend-wasm (Emscripten)"]
Node --> Shim["backend-shim-c (shared C shim)"]
Wasm --> Shim
Shim --> CSPICE["CSPICE (NAIF toolkit)"]
Node native (backend: "node") | WASM (backend: "wasm") | |
|---|---|---|
| Runs in | Node.js only | Browsers + Node.js |
| Artifact | Native addon (.node) | Prebuilt WebAssembly (.wasm) + JS glue |
| Best for | Node services, local kernel archives, potential performance wins | Browsers, Web Workers, portability |
| Kernel I/O shape | OS filesystem paths (plus optional byte staging) | Byte-backed loads into a virtual filesystem |
| Operational constraints | none | Needs the .wasm asset to be served/bundled correctly (often via bundler asset handling or explicit wasmUrl) |
docs/cspice-function-inventory.md)kit functions and client functionality - e.g. batchingSee CONTRIBUTING.md.
MIT — see LICENSE.
TypeScript
58.4%
C++
12.9%
C
10.8%
Python
10.6%
JavaScript
6.7%
An idiomatic TypeScript wrapper around NAIF SPICE - for Node and the browser.
See the codeTypeScript-first access to NASA’s SPICE geometry toolkit — in Node.js and the browser (via WebAssembly).

SPICE is a toolkit (and data format ecosystem) developed by NAIF (NASA’s Navigation and Ancillary Information Facility) for space-mission geometry. It computes positions, orientations, frames, and time conversions using mission-provided “kernels” (ephemerides, constants, pointing, etc.). It’s widely used across NASA and the planetary science community to make geometry calculations reproducible and shareable.
tspice is a set of TypeScript packages that let you load SPICE kernels and execute common SPICE workflows (time conversion, ephemerides, frames, geometry) from modern JS runtimes.
If your target runtime is a browser, or your application is already TypeScript/Node and you want a first-class, typed API over CSPICE, tspice is designed to fill that gap.
tspice links against CSPICE (or a CSPICE-derived build) behind a TypeScript API. If you need CSPICE directly, download it from NAIF.
@rybosome/tspice is ESM-only..wasm assets (you may need to provide an explicit wasmUrl depending on your tooling).SPICE is stateful: loading kernels mutates a process-wide global kernel pool inside SPICE, and many routines read from (and sometimes affect) that shared state.
Isolation (separating kernel-sets and workloads) can be achieved by creating multiple process or WebWorker instances, depending on runtime.
pnpm add @rybosome/tspice
# or: npm i @rybosome/tspice
import { kernels, spiceClients } from "@rybosome/tspice";
async function main() {
// A small, CORS-enabled catalog hosted for quickstart/testing.
// Not suitable for production.
const kernelPack = kernels.tspice().pick(
"lsk/naif0012.tls",
"pck/pck00011.tpc",
"spk/planets/de432s.bsp",
);
// Build the client and load the given kernels
const { spice, dispose } = await spiceClients
.withKernels(kernelPack)
.toAsync({ backend: "wasm" });
try {
const et = await spice.kit.utcToEt("2000 JAN 01 12:00:00");
const state = await spice.kit.getState({ target: "EARTH", observer: "SUN", at: et });
console.log(state.position, state.velocity);
} finally {
await dispose();
}
}
main().catch(console.error);
In a production application, it is recommended to host kernels yourself or enable a proxy.
The kernels.naif() catalog can be configured to point at your hosted entries, or you can load bespoke kernels.
import { kernels } from "@rybosome/tspice";
// Hosting a mirror of NAIF's catalog at https://your-app.example/kernels/naif
const naifKernels = kernels
.naif({
origin: "https://your-app.example/kernels/naif/",
pathBase: "naif/",
})
.pick(
"lsk/naif0012.tls",
"pck/pck00011.tpc",
"spk/planets/de432s.bsp",
);
// Hosting a custom catalog at https://your-app.example/kernels/custom
const customKernels = kernels
.custom({
origin: "https://your-app.example/kernels/custom/",
pathBase: "custom/",
})
.pick("planets/my_custom_kernel.bsp");
import { kernels, spiceClients } from "@rybosome/tspice";
async function main() {
// We can download kernels directly from NAIF servers in Node.
const kernelPack = kernels.naif()
.pick(
"lsk/naif0012.tls",
"pck/pck00011.tpc",
"spk/planets/de432s.bsp",
);
// Use the builder to create a synchronous, caching client.
// `dispose()` is still async and should be awaited.
const { spice, dispose } = await spiceClients
.caching({ maxEntries: 10_000, ttlMs: null })
.withKernels(kernelPack)
.toSync({ backend: "node" });
try {
const et = spice.kit.utcToEt("2000 JAN 01 12:00:00");
const state = spice.kit.getState({ target: "EARTH", observer: "SUN", at: et });
console.log(state.position, state.velocity);
} finally {
await dispose();
}
}
main().catch(console.error);
CSPICE exposes 652 public routines; 162 are currently implemented in tspice.
docs/cspice-function-inventory.mdtspice exposes a stable backend contract that models the CSPICE routine surface. That contract is designed to evolve conservatively as additional CSPICE functions are implemented.
tspice follows SemVer. As a pre-1.0.0 project, minor versions may introduce breaking changes. Within a given minor line (e.g. 0.1.x), patch releases are guaranteed not to break the public API.
Because CSPICE itself is a mature and stable toolkit, long-term API churn in tspice is expected to be low.
In addition to typical unit testing, tspice runs parity tests with CSPICE as the reference, and also checks that the Node and WASM backends stay consistent for the same kernels and inputs. tspice preserves CSPICE double-precision semantics; numeric comparisons are verified against CSPICE with defined tolerances.
packages/py-parity-checking) executes matching workflows against tspice, comparing normalized outputs against live CSPICE-backed SpiceyPy behavior.docs/spicebackend-cspice-mapping.md.@rybosome/tspice (facade) — the user-facing entrypoint (packages/tspice/).SpiceBackend (contract) — the shared TypeScript interface all backends implement (packages/backend-contract/).packages/backend-node/packages/backend-wasm/backend-shim-c (shared C shim) — a shared C integration layer reused by both backends (packages/backend-shim-c/)..wasm.flowchart TD
Facade["@rybosome/tspice (facade)"] --> Contract["SpiceBackend (contract)"]
Contract --> Node["backend-node (native addon)"]
Contract --> Wasm["backend-wasm (Emscripten)"]
Node --> Shim["backend-shim-c (shared C shim)"]
Wasm --> Shim
Shim --> CSPICE["CSPICE (NAIF toolkit)"]
Node native (backend: "node") | WASM (backend: "wasm") | |
|---|---|---|
| Runs in | Node.js only | Browsers + Node.js |
| Artifact | Native addon (.node) | Prebuilt WebAssembly (.wasm) + JS glue |
| Best for | Node services, local kernel archives, potential performance wins | Browsers, Web Workers, portability |
| Kernel I/O shape | OS filesystem paths (plus optional byte staging) | Byte-backed loads into a virtual filesystem |
| Operational constraints | none | Needs the .wasm asset to be served/bundled correctly (often via bundler asset handling or explicit wasmUrl) |
docs/cspice-function-inventory.md)kit functions and client functionality - e.g. batchingSee CONTRIBUTING.md.
MIT — see LICENSE.
TypeScript
58.4%
C++
12.9%
C
10.8%
Python
10.6%
JavaScript
6.7%