lxephemeris-cli 1.0.0

CLI tooling for lxephemeris (calc, houses, panchanga, swetest, validate-bundle, license-verify)
lxephemeris-cli-1.0.0 is not a library.

lxephemeris

The modern astronomical & astrological computation engine for Python, Node.js, and Rust.
100% memory-safe Rust core. Lock-free multi-threading. Zero external files required to start — with native NASA JPL DE440s support for sub-milliarcsecond precision.

CI Rust SDKs Golden Suite License


import lxephemeris

# Works out of the box with zero external files (or loads NASA JPL DE440s if present)
engine = lxephemeris.Engine()

jd_utc = lxephemeris.utc_from_local(2026, 10, 27, 14, 30, 0.0, tz_name="America/New_York")
obs = lxephemeris.Observer(latitude_deg=40.7128, longitude_deg=-74.0060, altitude_m=10.0)

# Full natal snapshot: planets, 23 house systems, aspects, Hermetic lots, lunar phase & sect in ~150 µs
chart = engine.chart_snapshot(jd_utc, obs)

Why We Built lxephemeris

If you have ever built a production astrology, horary, Vedic, Human Design, or astronomical API in Python or Node.js, you know the pain of the existing ecosystem.

For nearly three decades, almost every backend in the industry has been forced to glue together Swiss Ephemeris (libswe / pyswisseph) — a C library designed in the 1990s for single-threaded desktop apps — alongside PyEphem and Kerykeion.

When we ran that legacy stack under high concurrency in production, we kept hitting the same architectural walls:

  1. Global Mutable C State & Thread-Safety Bugs: libswe stores ephemeris paths (swe_set_ephe_path), sidereal modes (swe_set_sid_mode), and topocentric observers (swe_set_topo) in process-global static C variables. If Thread A computes a Vedic (Lahiri) chart while Thread B computes a Western (Tropical) chart, they silently corrupt each other's math. Fixing this in Python required ratusan lines of global RLock wrappers that killed multi-core throughput.
  2. A Mountain of Monkey-Patches: High-level wrappers had to be patched just to return accurate charts:
    • Kerykeion silently clamps latitudes above ±66°, causing a 7.85° Ascendant error in Northern Europe, Alaska, and Svalbard, and truncates birth-time seconds (second=0), shifting the Ascendant by up to 15 arcminutes.
    • Rounding planet longitudes (round(lon, 4)) before house assignment routinely drops cusp planets into the wrong house.
    • PyEphem's Sun().hlong returns Earth's heliocentric longitude shifted by 180° (breaking Chinese Jieqi solar terms), and ephem.Ecliptic(ephem.Moon(obs)) rotates topocentric coordinates using static J2000 obliquity (23 arcminutes of error).
  3. 22 Upstream Calculation & C Buffer Bugs:
    • Missing .se1 ephemeris files cause libswe to silently downgrade to a lower-precision fallback without raising an error.
    • swe_house_pos returns an invalid 0.0 at high latitudes or circumpolar declinations.
    • swe_fixstar2_ut("Mira") matches Mirach (>17° error) due to naive prefix matching in C.
    • Star-anchored sidereal modes (True Citra, Revati, Pushya) wobble by ±20.5 arcseconds every year because annual stellar aberration is mixed into the anchor star.
  4. Slow FFI Loops for Transits, Returns & Timelines: Finding a year of exact transit windows, retrograde stations, Void-of-Course Moon intervals, or a 3-pass Saturn Return meant running tens of thousands of Python/JS bisection calls across the C FFI boundary — taking hundreds of milliseconds per request.
  5. Dependency Sprawl: Teams had to maintain 5–6 different libraries — one for planetary positions, one for lunar phases, one for natal wheels, another for Vedic Panchanga/Dasha, another for Hellenistic Lots, and custom scripts for Human Design gates or Chinese calendars.

So we built lxephemeris from scratch in 100% safe Rust (#![forbid(unsafe_code)]).

No C pointers. No global state. No monkey-patches. Just one ultra-fast, mathematically rigorous engine with first-class native SDKs for Python (PyO3), Node.js / TypeScript (napi-rs), and Rust.


What Makes lxephemeris Better

1. One Engine Replaces 6+ Libraries (Batteries Included)

Instead of stitching together pyswisseph + ephem + kerykeion + custom scripts, lxephemeris ships every major astronomical and astrological subsystem natively in Rust:

  • Solar System & 68 Minor Bodies: Sun..Pluto, 7 Lunar points (Mean_Node, True_Node, Mean_South_Node, True_South_Node, Mean_Lilith, True_Lilith, and smooth $C^2$ Interpolated_Lilith), 9 Uranian hypotheticals (Cupido..Poseidon, Isis), and 68 JPL SB441-N16 asteroids, centaurs, and dwarf planets (Chiron, Ceres, Pallas, Juno, Vesta, Pholus, Nessus, Eris, Sedna, Haumea, Makemake, Lilith (1181), Proserpina (26), etc.).
  • 23 House Systems + Polar Safety: Placidus, Koch, Porphyry, Regiomontanus, Campanus, Equal, Whole Sign, Alcabitius, Morinus, Topocentric (Polich-Page), Krusinski, APC, Carter, Sunshine, Gauquelin (36 sectors), and more — with explicit PolarPolicy (Strict, FallbackToWholeSign, FallbackToPorphyry) so Arctic/Antarctic charts never crash or flip 180°.
  • Native Event & Timing Solvers:
    • Aspects & Transits: Static natal & synastry aspects (calc_chart_aspects, calc_synastry_aspects), declination parallels/contraparallels, exact sky-to-sky aspect windows (mutual_aspects_in_range), natal transit timelines (natal_transits_in_range), and Void-of-Course Moon intervals (void_of_course_moon_in_range).
    • Planetary Returns & Stations: Exact Solar, Lunar, Saturn, and Chiron returns (planetary_return, planetary_returns_in_range) that automatically detect all 3 passes of a retrograde return loop, plus exact retrograde/direct stations (search_stations_in_range).
  • Vedic / Jyotish Suite:
    • 43+1 Sidereal Ayanamsas: All 43 standard models (Lahiri, True Citra, Krishnamurti (KP), Raman, Fagan-Bradley, Suryasiddhanta, Yukteshwar, etc.) plus custom user-defined ayanamsas — free of annual aberration wobble.
    • Panchanga, Muhurta & Vargas: Full 5-limb panchanga (Tithi, Nakshatra + Pada, Yoga, Karana, Vara, plus Rahukalam, Yamagandam, Gulika Kalam, Abhijit Muhurta), all 16 Parashara Shodashavarga (D1..D60), and 120-year Vimshottari Dasha (Maha, Antar, Pratyantar).
  • Traditional & Hellenistic Suite: Day/Night chart sect (chart_sect), 24 Chaldean Planetary Hours (planetary_hours), and 7 Hermetic Lots (Fortune, Spirit, Eros, Necessity, Courage, Victory, Nemesis with diurnal/nocturnal reversal).
  • Human Design & Chinese Solar Calendar:
    • Human Design: Exact -88° prenatal Design solar arc solver (human_design_epoch) and 64 I-Ching Mandala Gates × 6 Lines × Color × Tone × Base (map_zodiac_placement).
    • Chinese Almanac: All 24 Solar Terms (Jieqi / Zhongqi, solar_terms_in_range), 4 cardinal seasons (seasons_in_year), and lunar phase solvers (lunar_phases_in_range, 8-phase & 28-phase lunar_phase_summary).
  • Fixed Stars, Brady Parans, Eclipses & Occultations:
    • 52 Embedded Fixed Stars (VizieR Hipparcos-2 I/311 + XHIP V/137D with full 3D space motion) + custom sefstars.txt / JSON catalog loader.
    • Bernadette Brady Parans (find_parans) & Schaefer Heliacal Risings/Settings.
    • Solar & Lunar Eclipses (global & local Besselian solvers with Saros series/member and path width) & Lunar Occultations of stars, planets, and asteroids.

2. Zero External Files Required — Or Sub-Milliarcsecond JPL DE440s

  • Instant Zero-File Start (Engine()): Works the second you install it. When no external .bsp files are configured, lxephemeris uses its built-in DE440s-calibrated analytical engine covering -3000 CE .. +3000 CE with zero disk I/O.
  • Observatory-Grade SPK Mode (Engine.from_data_dir("./data")): Point the engine at NASA JPL DE440s (1849–2150), DE440 (1550–2650), DE441 (-13200..+17191), or INPOP21a plus asteroids_68_1850_2100.bsp for < 0.003 arcsecond agreement with NASA JPL Horizons.

3. 5–15× Faster (Single-Pass Analytical Velocities)

Legacy ephemeris libraries compute planet speed (°/day) by evaluating the ephemeris 3 separate times ($t - \Delta t, t, t + \Delta t$) and taking a finite difference — which is both 3× slower and prone to $0\circ / 360\circ$ wrap-around glitches.

  • lxephemeris differentiates Chebyshev polynomials, relativistic light-time, aberration, and the IAU 2006/2000A frame rotation matrix analytically in a single pass:
    • 12.8 µs per planetary position + instantaneous velocity.
    • ~150–240 µs for a complete natal chart (chart_snapshot).
    • Releases the Python GIL and runs multi-core Rayon batch queries (calc_batch, calc_batch_flat_f64, houses_batch) across all CPU cores.

4. Drop-In Migration for Existing pyswisseph Codebases

Don't want to rewrite your whole app at once? lxephemeris includes a thread-safe SweAdapter that mirrors the swisseph API (calc_ut, houses_ex2, fixstar2_ut, get_ayanamsa_ex_ut, sol_eclipse_when_glob, lun_eclipse_when, nod_aps_ut, pheno_ut, rise_trans, azalt, julday, revjul, and SE_* constants) — scoped safely to an engine instance instead of global C state.


How lxephemeris Compares

Feature lxephemeris Swiss Ephemeris (pyswisseph) Kerykeion PyEphem (ephem) Skyfield
Core Architecture 100% Safe Rust (#![forbid(unsafe_code)]) Legacy C (libswe, 1990s) Python wrapper over pyswisseph Legacy C (libastro) Pure Python / NumPy
Thread Safety Lock-free Send + Sync (0 state bleed) ❌ Global mutable C static state ❌ Inherits pyswisseph globals ⚠️ Mutable Body objects ✅ Thread-safe
Works with 0 External Files ✅ Built-in analytical engine (-3000..+3000) ⚠️ Silent fallback if .se1 missing ✅ Bundles .se1 files ✅ Analytical only ❌ Requires downloading .bsp
JPL DE440s / DE441 Precision ✅ Native DAF/SPK (< 0.003") Compressed .se1 re-fits Via pyswisseph ❌ Truncated VSOP87 (multi-arcsec drift) ✅ Native SPK
Single Body + Speed Latency 12.8 µs (analytical Jacobian) ~45–90 µs (3-pt finite diff) ~25–80 ms per subject ~80–150 µs ~600–2,000 µs
23 Houses & Arctic/Polar Safety ✅ All 23 + explicit PolarPolicy ⚠️ Silent polar fallback & house_pos=0.0 bug ❌ Clamps |lat| > 66° (7.85° ASC error) ❌ No astrological houses ❌ No astrological houses
68 Astrological Minor Bodies ✅ Single verified .bsp + Keplerian fallback Manage 68 separate .se1 files Partial ❌ Manual orbital elements Manual SPK segments
43+1 Sidereal Ayanamsas ✅ Aberration-free star anchors ⚠️ ±20.5" annual aberration wobble on star anchors ⚠️ Leaves secondary points tropical ❌ None ❌ None
Transit, Return & VoC Moon Solvers ✅ Native Rust Newton-Illinois solvers ❌ Write your own FFI loops ❌ Static charts only ❌ Basic rising/phase only Discrete almanac only
Vedic (Panchanga, Dasha, D1–D60) ✅ Built-in ❌ None ❌ None ❌ None ❌ None
Traditional (Sect, Hours, 7 Lots) ✅ Built-in ❌ None ❌ None ❌ None ❌ None
Human Design (64 Gates & -88° Arc) ✅ Built-in ❌ None ❌ None ❌ None ❌ None
SDKs with Identical Math Python, Node.js/TS, Rust, CLI C + separate 3rd-party bindings Python only Python only Python only

Quickstart

Python (lxephemeris)

import lxephemeris

# 1. Start immediately (zero external files needed) or load NASA JPL DE440s from ./data
engine = lxephemeris.Engine()
# engine = lxephemeris.Engine.from_data_dir("./data", verify_manifest_sha256=True)

# 2. Local wall-clock time -> UTC Julian Date (preserves fractional seconds & PEP 495 DST fold)
jd_utc = lxephemeris.utc_from_local(2026, 10, 24, 14, 0, 32.5, tz_name="Europe/Berlin", fold=0)
obs = lxephemeris.Observer(51.5074, -0.1278, 35.0)

# 3. Single body position + analytical speed + visual magnitude
sun = engine.calc("Sun", jd_utc, scale="UTC")
chiron = engine.calc("Chiron", jd_utc, scale="UTC")
print(f"Sun: {sun.lon_deg:.6f}° (speed={sun.lon_speed_deg_day:.6f}°/d, Vmag={sun.magnitude_v:.2f})")

# 4. Polar-safe houses & cusp boundary guard (eps = 1e-9°)
houses = engine.houses(
    jd_utc,
    latitude_deg=51.5074,
    longitude_deg=-0.1278,
    system="P",
    scale="UTC",
    polar_policy="fallback_to_whole_sign",
)
sun_house = lxephemeris.house_of_lon(sun.lon_deg, houses.cusps_deg, eps_deg=1e-9)

# 5. All-in-one Natal Snapshot, Solar Return, Vedic Panchanga, & Human Design Gate
snapshot = engine.chart_snapshot(jd_utc, obs)
solar_return = engine.planetary_return("Sun", jd_utc, jd_utc + 350.0)
panchanga = engine.panchanga(jd_utc, obs, ayanamsa="lahiri")
hd = lxephemeris.map_zodiac_placement(sun.lon_deg)
print(f"ASC: {houses.asc_deg:.4f}° | Sun in House {sun_house} | HD Gate {hd.hd_gate}.{hd.hd_line}")

Node.js / TypeScript (lxephemeris)

import { Engine, utcFromLocal, houseOfLon, mapZodiacPlacement } from "lxephemeris";

// 1. Start immediately (zero external files needed) or load NASA JPL DE440s from ./data
const engine = new Engine();
// const engine = Engine.fromDataDir("./data", 4, null, true);

const jdUtc = utcFromLocal(2026, 10, 24, 14, 0, 32.5, "Europe/Berlin");
const jdSplit = { jd1: jdUtc, jd2: 0.0 };
const obs = { latitudeDeg: 51.5074, longitudeDeg: -0.1278, altitudeM: 35 };

const sun = engine.calc("Sun", jdSplit, "UTC");
const houses = engine.houses(jdSplit, obs, "P", "UTC", "fallback_to_whole_sign");
const sunHouse = houseOfLon(sun.lonDeg, houses.cuspsDeg, 1e-9);
const snapshot = engine.chartSnapshot(jdUtc, obs);
const hd = mapZodiacPlacement(sun.lonDeg);

console.log(
  `Sun: ${sun.lonDeg.toFixed(6)}° in House ${sunHouse} | HD Gate ${hd.hdGate}.${hd.hdLine} | Lots: ${snapshot.lots.length}`
);

Rust (lxephemeris-core)

use lxephemeris_core::{
    AspectPreset, BodyId, CalcOptions, Engine, HouseOptions, HouseSystem, Observer,
    PlanetId, PolarPolicy, TimeInput, JD_J2000,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. Zero-file analytical start (or Engine::from_data_dir("./data", EngineConfig::default())?)
    let engine = Engine::default();

    // 2. Single-pass position + analytical velocity (12.8 µs)
    let t = TimeInput::from_tt_jd(JD_J2000);
    let sun = engine.calc(BodyId::Planet(PlanetId::Sun), t, CalcOptions::default())?;
    println!("Sun: lon={:.6}°, speed={:.6} °/day", sun.lon_deg, sun.lon_speed_deg_day);

    // 3. Polar-safe houses & one-call ChartSnapshot
    let obs = Observer::new(51.5074, -0.1278, 35.0)?;
    let houses = engine.houses(
        t,
        obs,
        HouseOptions {
            system: HouseSystem::Placidus,
            polar_policy: PolarPolicy::FallbackToWholeSign,
            ..Default::default()
        },
    )?;
    let snapshot = engine.chart_snapshot(
        t,
        obs,
        &[BodyId::Planet(PlanetId::Sun), BodyId::Planet(PlanetId::Moon)],
        HouseOptions::default(),
        CalcOptions::default(),
        AspectPreset::Major,
        1.0,
    )?;
    println!("ASC={:.4}°, MC={:.4}°, Lots={}", houses.angles.asc_deg, houses.angles.mc_deg, snapshot.lots.len());
    Ok(())
}

Command-Line Interface (lxephemeris-cli)

# Calculate planetary & asteroid positions (works out of the box with zero external files)
cargo run --release -p lxephemeris-cli -- calc --jd 2460676.5 --bodies Sun,Moon,Chiron

# Calculate house cusps & angles
cargo run --release -p lxephemeris-cli -- houses --jd 2460676.5 --lat 51.5074 --lon -0.1278 --system P

# Vedic Panchanga for New Delhi
cargo run --release -p lxephemeris-cli -- panchanga --jd 2460676.5 --lat 28.6139 --lon 77.2090 --ayanamsa lahiri

# Legacy swetest-compatible output
cargo run --release -p lxephemeris-cli -- swetest -b1.1.2000 -p0123456789 -fPlbR

# Synchronize IERS finals2000A (Delta-T / UT1-UTC) & leap-second tables
cargo run --release -p lxephemeris-cli -- data-sync --data-dir ./data

# Fetch NASA JPL planetary kernels (de440s, de440, de441, inpop21a)
cargo run --release -p lxephemeris-cli -- fetch-kernel --kernel de440s --data-dir ./data

22 Upstream Bugs Eliminated by Design

Every behavioral difference between lxephemeris and legacy tools is documented and regression-tested in docs/SE_DIVERGENCES.md.

Swiss Ephemeris (SWE-01..SWE-11)

  • SWE-01 (Global State Race Conditions): set_ephe_path, set_sid_mode, and set_topo mutate process-global C state. In lxephemeris, all configuration is immutable or passed per call (Send + Sync).
  • SWE-02 (Star-Anchored Ayanamsa Wobble): True Citra, Revati, and Pushya in libswe include annual stellar aberration ($\pm 20.5''$ yearly oscillation). lxephemeris evaluates star anchors strictly in the geometric frame.
  • SWE-03 (swe_house_pos Returning 0.0): libswe returns an invalid 0.0 house position at circumpolar declinations or high latitudes. lxephemeris uses a closed-form 3D horizon/prime-vertical projection valid on $[1.0, 13.0)$.
  • SWE-04 (Mira / Mirach Star Collision): swe_fixstar2_ut("Mira") prefix-matches Mirach ($>17^\circ$ error). lxephemeris uses exact normalized name, Bayer, and Hipparcos ID matching.
  • SWE-05 (Sidereal Velocity Double-Nutation): Fixes frame-rate and nutation-rate inconsistencies in sidereal speeds.
  • SWE-06 (Silent Ephemeris Fallback): Missing .se1 files silently downgrade accuracy in libswe. lxephemeris validates SHA-256 manifests explicitly and exposes engine.is_moshier_mode().
  • SWE-07 (Silent Polar House Flips): Replaces silent Porphyry substitution and $180^\circ$ Ascendant flips with explicit PolarPolicy (Strict, FallbackToWholeSign, FallbackToPorphyry).
  • SWE-08 (Zero/Negative Stellar Parallax Explosion): Guards Hipparcos-2 parallax $\varpi \le 0$ against division-by-zero and $180^\circ$ sky inversions.
  • SWE-09 ($0\circ / 360\circ$ Velocity Glitch): Single-pass analytical Jacobians eliminate finite-difference branch-cut spikes at $0^\circ \ Aries$.
  • SWE-10 (Besselian Eclipse Aberration Mixing): Separates solar annual aberration from lunar shadow-plane coordinates (0.2–0.6 s contact improvement).
  • SWE-11 (SE_MEAN_APOG Oscillation): Provides true secular IERS 2003 Mean_Lilith alongside osculating True_Lilith and smooth $C^2$ Interpolated_Lilith.

PyEphem (EPH-01..EPH-05)

  • EPH-01 (Sun().hlong $180^\circ$ Inversion): Fixes the heliocentric Earth / geocentric Sun confusion that breaks Chinese Jieqi solar terms.
  • EPH-02 (Topocentric Moon $0.38^\circ$ Obliquity Error): Rotates topocentric coordinates using true obliquity of date $\varepsilon(t)$ instead of static J2000 obliquity.
  • EPH-03 (Static FixedBody Stars): Applies full 3D Hipparcos-2 proper motion, parallax, and radial velocity in star parans.
  • EPH-04 (Truncated VSOP87 / ELP2000 Drift): Replaces libastro series with JPL DE440s and DE440-calibrated series.
  • EPH-05 (Naive Datetime & DST Fold Loss): utc_from_local enforces explicit IANA timezone + PEP 495 fold disambiguation.

Kerykeion (KER-01..KER-06)

  • KER-01 ($\pm 66^\circ$ Latitude Clamping): Eliminates the silent latitude clamp that caused a $7.85^\circ$ Ascendant error at Svalbard ($78.22^\circ\text{N}$).
  • KER-02 ($0.0 \to 0.0001^\circ$ Equator/Greenwich Hack): Handles $(0\circ, 0\circ)$ exactly with zero coordinate falsification.
  • KER-03 (Birth-Time Seconds Truncation): Preserves full f64 sub-second precision (preventing up to $15'$ of Ascendant drift).
  • KER-04 (Cusp Rounding House Drop): house_of_lon uses a formal 1e-9° boundary epsilon instead of round(lon, 4).
  • KER-05 (Mixed Tropical Points in Sidereal Charts): Applies sidereal ayanamsa uniformly across all planets, minor bodies, nodes, Liliths, lots, and fixed stars.
  • KER-06 (Hardcoded $23.4367^\circ$ Obliquity): Uses exact IAU 2006/2000A true obliquity and GAST everywhere.

Verification & Benchmarks

lxephemeris is continuously verified against 37,416 golden reference vectors generated from NASA JPL Horizons (DE440 / SB441-N16), IAU SOFA, USNO, and reference astronomical catalogs across 145+ Rust tests, 18 Python test suites, and 12 Node.js test suites:

Verification Suite Vectors Coverage Status
Core Planetary, 68 Asteroids, 52 Stars & 23 Houses 10,242 1850..2100 full-domain grid across 10 planets, 68 minor bodies, 7 lunar points, 9 Uranians, 52 stars, 23 house systems PASS
Events, Parans, Eclipses, Occultations & 43 Ayanamsas 10,540 Rise/set/transit, 24 Solar Terms (Jieqi), HD -88° solar arc, stations, lunistices, Brady parans, Moshier (-500..+2500 CE), pheno_ut, nod_aps_ut PASS
Extreme Boundaries & 22 Upstream Bug Immunity Grid 10,000 Arctic/Antarctic houses, $0\circ/360\circ$ wrap velocities, retrograde triple passes, circumpolar house_pos, star-anchor sidereal nodes, DST folds PASS
Vedic Panchanga/Dasha/Vargas, Aspects, Returns & Lots 5,000 Panchanga, 16 Parashara Vargas (D1..D60), Vimshottari Dasha, 24 Planetary Hours, 7 Hermetic Lots, exact aspect windows, planetary returns, 64 HD Gates PASS
First-Principles NASA JPL Horizons & IAU SOFA Oracles 1,634 Direct JPL Horizons DE440 ICRF (< 0.003"), SB441-N16 68 minor bodies (< 0.00001"), IAU SOFA pmpx stars, Holden/Munkasey houses PASS
Total Verified Reference Vectors 37,416 100% Pass across Rust, Python (PyO3), and Node.js (napi-rs) 100% PASS

Documentation


Licensing & Commercial Use

lxephemeris is distributed under a Dual License (LICENSE.md):

  1. Free Non-Commercial License (PolyForm-Noncommercial-1.0.0)
    Free for personal projects, hobbyists, academic research, educational institutions, and non-profit organizations — plus a 30-day evaluation grant for commercial teams testing lxephemeris in non-production environments.

  2. Commercial License (LicenseRef-Commercial)
    Required for commercial products, paid SaaS/APIs, monetized mobile/web apps, and internal business production deployments.

    • Get a Commercial License: Submit a request at https://procoders.tech/contacts/ or email lxephemeris@procoders.tech.
    • 100% Offline Activation (Ed25519): Commercial customers receive an offline cryptographic license key (LXEPHEMERIS_LICENSE_KEY or LXEPHEMERIS_LICENSE_FILE) verified locally in microseconds — zero runtime phone-home, zero network calls, and perpetual fallback on covered engine releases.
# Verify your commercial license key via CLI, Python, Node.js, or Rust
export LXEPHEMERIS_LICENSE_KEY="lxeph_live_v1...."
lxephemeris-cli license-verify --require-commercial