Skip to content

1.0 release notes 18 October 2026 ​

Interstellar Tools 1.0: a stable API for orbital mechanics

All five packages go to 1.0.0 together: types, constants, temporal, equations and mcp.

These notes cover everything that changed between the 0.x releases and 1.0. For the code changes, step by step, see the migration guide from 0.x to 1.0. Questions? See getting help.

Overview ​

1.0 is a promise more than a feature: from 1.0 on, the public API only breaks in a major release. Every type, function, dataset field, MCP tool and resource you use today keeps working through every 1.x release.

To make that promise, the 0.x releases settled the shape of the API. The biggest change is how orbits are described: every body now has a stable id, the parent it's bound to, and an orbit around that parent, so the datasets form one tree from galaxies down to moons. Around that, the datasets got real J2000 positions, the equations can place a body at any date, everything about drawing moved into its own display object, and an MCP server lets AI assistants compute answers with the library instead of guessing them.

If you're on a recent 0.x release, most of the work is renaming fields. If you're on 0.60 or older, start with the orbit tree.

What's new ​

The orbit tree ​

In 0.60, a body carried its orbital elements as loose fields, and named its system by display name. From 0.61, every body points to its parent by id, and carries an orbit around it. Systems are barycenters, nodes in the tree that stars and planets orbit, so binary and multiple stars work the same way as a planet around a star.

The orbit treeThe Milky Way is the root. The Solar System and Alpha Centauri orbit it. The Sun orbits the Solar System barycenter, Earth orbits the Sun and the Moon orbits Earth. Alpha Centauri AB and Proxima Centauri orbit Alpha Centauri, and stars A and B orbit Alpha Centauri AB.milky-waysolar-systemalpha-centaurisunearthmoonalpha-centauri-abproxima-centauriAB
Every line up the tree is a parent id, and every body has an orbit around its parent. Dashed boxes are systems: barycenters, not bodies.
ts
const earth = PLANETS.find((planet) => planet.id === 'earth')!;
const { parent, orbit } = earth;
// parent: 'sun'
// orbit: { a: { value: 1, unit: 'au' }, e: 0.0167, period: …, angle: … }

Ids are stable and never translated, so look bodies up by id, not by name.

Real data at J2000 ​

Every orbit.angle is now the true anomaly at J2000 (1 January 2000, 12:00 TT), taken from JPL data: the planets, the comets and the moons. Planets also carry their real position at J2000 in x, y and z. The datasets have tests that check positions and angles agree, so a placeholder can't slip back in.

New in 1.0:

  • mu, the gravitational parameter G·M in m³/s², on the Sun, the planets and the larger moons, from JPL. It's exactly what the orbit equations take, so circularSpeed(r, earth.mu!) needs no constants of your own.
  • Spica is a binary: a spica system with stars spica-a and spica-b.
  • Star pairs have orientation: Alpha Centauri A and B carry i, om and their argument of periapsis w, 180° apart, and Spica's stars i and w.
  • Corrected moon orbits: 14 semi-major axes, some off by a factor of two, and three eccentricities now match JPL's mean elements, and a test checks every moon's period against Kepler's third law.

Direction without a negative period ​

In 0.x, a negative period meant an orbit went the usual way round, and a positive one meant it was retrograde. A negative duration surprises anyone who computes with it, so from 0.63 every period is positive, and the few retrograde orbits say so with retrograde: true.

Prograde and retrograde orbitsLeft: Earth travels counter-clockwise, seen from the north, with a positive period and no retrograde flag. Right: Halley's comet travels clockwise, with a positive period and retrograde true.earth · period 365.256 d1p-halley · retrograde: true
Seen from the north. A renderer moves a body by orbit.retrograde ? -1 : 1; the period is always a plain duration.

Drawing kept apart ​

A body's physical data and how to draw it are now separate. Colour, size, opacity and density moved into an optional display object, the way orbital elements live in orbit. A renderer keeps the state it computes there too, with clearer names: semiMinorAxis, focusOffsetX and orbitPath.

Body data and display dataA planet object with id, parent, orbit and radius, next to its display object with color, size and the renderer's semiMinorAxis, focusOffsetX and orbitPath.id: 'earth'parent: 'sun'orbit: { a, e, period, angle }radius, x, y, z, mudisplay: {color, size ← datasetssemiMinorAxis, … ← renderer}
Left: what the body is. Right: how to draw it. The datasets only ship drawing hints; the rest is for a renderer to compute.

@interstellar-tools/equations ​

  • Positions at any date: meanAnomalyAt(orbit, date) and trueAnomalyAt(orbit, date) place a body on its orbit, counting from J2000.
  • Any span of time: advanceMeanAnomaly(orbit, timeStep) (renamed from meanToEccentricAnomaly) moves forwards or backwards over any span, without losing precision.
  • Units: convertDistanceUnit and normalizeDistanceUnit convert between m, km, au, light-years and parsecs, like the temporal unit functions do for time.
  • Consistent arguments: mu is the last argument everywhere, including meanMotion(a, mu) and hyperbolicPeriapsisSpeed(vInfinity, rp, mu).
  • More robust solvers: solveKepler is correct for any finite mean anomaly and returns a value in [0, 2π), and the Newton and high-eccentricity solvers converge where they used to fail.

@interstellar-tools/temporal ​

The unit tables SECONDS_PER and NORMALIZE_TEMPORAL_UNIT (renamed from NORMALIZE_UNIT) are frozen, unknown units throw a RangeError, and convertTemporalUnit accepts an alias such as 'days' as its target.

@interstellar-tools/mcp, new in 0.x ​

An MCP server that gives AI assistants 15 tools, from Hohmann transfers to unit conversions, plus the datasets as resources. Assistants compute answers with tested equations instead of recalling a number that looks plausible. It runs locally over stdio, or remotely over HTTP with a host check against DNS rebinding.

shell
claude mcp add --transport stdio interstellar-tools -- npx -y @interstellar-tools/mcp

Trust and security ​

  • Every package is published from CI with npm provenance, and each GitHub release has a CycloneDX SBOM.
  • The project has the OpenSSF Best Practices passing badge and Baseline levels 1 and 2.
  • Every commit carries a Developer Certificate of Origin sign-off.

What's not changing ​

  • Package names and entry points. All five packages keep their names, are ESM only, and run on Node 22.9 or newer and in modern bundlers.
  • Most equations. Apart from the renames and argument orders above, the equations keep their names, arguments and units (SI throughout).
  • Units on values. Distances and durations still carry their unit as { value, unit }.
  • Dataset ids stay the same, except spica, which is now the system (the stars are spica-a and spica-b).

Deprecated ​

APIUse insteadRemoved in, at the earliest
MeasureInterfaceDistanceInterface2.0

MeasureInterface was deprecated in 0.63, before 1.0, so it stays through all of 1.x.

Removed ​

Nothing that was deprecated. The breaking changes of 0.x are in the migration guide.

FAQ ​

What do I get from 1.0? ​

  • Stability. Nothing you use breaks before 2.0. Minor releases add, patch releases fix.
  • Data you can compute with. Real J2000 positions and angles, and mu on the bodies, so a position or a speed needs nothing but the library.
  • A clearer model. One orbit tree from galaxies to moons, with the same rules for a moon, a planet and a binary star.

Do I need to upgrade right away? ​

No, but only the latest release of each package gets fixes (see the security policy). Once 1.0 is out, 0.x gets no more releases, including security fixes, so plan to move when you can. From 1.0 on, support covers a whole major, and when 2.0 ships, 1.x still gets high and critical security fixes for 6 months.

How big is the upgrade? ​

It depends on where you start:

  • From 0.62 or later: small. Mostly reading orbit.retrograde instead of the period's sign, and a few type changes.
  • From 0.60 or earlier: bigger. Orbital fields moved into orbit, and system names became parent ids. The changes are mechanical, and the migration guide has a checklist with before-and-after code for each.

Upgrade all the packages together: they depend on each other.

What happens to deprecated APIs? ​

They keep working for one full major. An API deprecated in any 1.x release, or at 2.0, stays in every 2.x release, and goes in 3.0 at the earliest. See deprecations.

Does this change how the MCP server is set up? ​

No. The command, the options and the tool names stay the same. The dataset resources follow the new dataset shape, so an assistant that reads orbit.period sees positive periods and orbit.retrograde.

Getting help ​

  • Something doesn't work after upgrading? Check the migration guide for the version you came from, then open an issue with the package versions and a short example.
  • A question, or not sure where to start? Open an issue too; questions are welcome.
  • A security problem? Don't open an issue. Report it privately, as the security policy describes.
  • Every change in detail: each package's CHANGELOG.md.