Vedaksha — Vision from Vedas
Clean-room Rust ephemeris and Vedic astrology engine, built for the agentic-AI era. Sub-arcsecond planetary precision, every algorithm traced to a primary source, any chart queryable as a property graph.
Website · Docs · Playground · API reference · Blog
clean-room · 0.103″ mean longitude vs JPL Horizons · 1,147 tests (per push) + 24,350 oracle rows · MCP-native · BUSL-1.1 → Apache 2.0
Install · Quick start · Accuracy · What's inside · MCP + property graph · Provenance · License
Install
| Platform | Install | Notes |
|---|---|---|
| Rust | cargo add vedaksha | full pipeline |
| Python | pip install vedaksha | engine via WebAssembly, py3-none-any, Python ≥ 3.9 — no Rust toolchain |
| WASM | npm install vedaksha-wasm | browser & edge, no data files |
| MCP | cargo install vedaksha-mcp | stdio + HTTP (bearer auth) |
| Docker | docker run -e VEDAKSHA_MCP_TOKEN=… -p 3100:3100 ghcr.io/arthiqlabs/vedaksha-mcp | multi-arch (amd64 + arm64) |
Compute janam kundali (natal charts), panchanga, dashas, nakshatras, vargas, shadbala, ashtakavarga, muhurta and transits/gochara from a sub-arcsecond ephemeris (VSOP87A, ELP/MPP02, JPL DE440s/DE441).
flowchart LR
K["JPL DE440s / DE441<br/>SPK kernel, ~31 MB"] --> E
V["VSOP87A + ELP/MPP02<br/>compiled to constants,<br/>no data files"] --> E
E["Ephemeris core<br/>precession · nutation<br/>light-time · ΔT"] --> W["Western<br/>houses · aspects<br/>dignities"]
E --> J["Jyotish<br/>nakshatras · dashas · vargas<br/>panchanga · shadbala · muhurta"]
W --> C["ComputedChart"]
J --> C
C --> G["Property graph<br/>Cypher · SurrealQL<br/>JSON-LD · RAG text"]
C --> M["MCP server<br/>17 tools · stdio + HTTP"]
C --> S["Rust · Python · WASM"]
Quick start
from vedaksha import Vedaksha
vk = Vedaksha()
chart = vk.natal_chart(julian_day=2451545.0, latitude=28.6139, longitude=77.2090)
cargo install vedaksha-mcp && vedaksha-mcp # stdio: Claude Desktop, Cursor, VS Code
The Rust path is a compiled doctest in crates/vedaksha/src/lib.rs.
Every Julian Day on the public surfaces is UT1, not TT and not TDB. The engine converts to TT internally for the dynamical terms and uses UT1 for Earth rotation, which fixes the ascendant, MC and all twelve cusps. Passing a TDB Julian Day adds ΔT worth of rotation instead of removing it — 0.289° (17.3′) at today's ΔT ≈ 69 s, on every cusp. The one exception is the raw SPK query (state_vector), which indexes the kernel directly and takes TDB.
Accuracy
These figures are reproducible, not just asserted: vedaksha-parity
is a separate harness (maintained by the same authors as this engine) that anyone can run against
their own copies of the reference kernels to check the published numbers below.
Every figure is printed by a named test. Reproduce the ephemeris tables with bash scripts/download_de440s.sh, then cargo test -p vedaksha-ephem-core --release -- --include-ignored --nocapture; the ayanamsha figures come from cargo test -p vedaksha-astro sidereal, and the cross-check against an independent Python derivation of the same primaries from cargo test -p vedaksha-astro --test ayanamsha_fixture.
What the headline 0.103″ measures — precisely. It is a mean apparent geocentric ecliptic-longitude residual, not a general position-accuracy figure: the fixture also carries ref_latitude, ref_distance and ref_speed, but oracle_comparison.rs marks them dead_code and none of the three enters this number. It covers only the measured-ΔT era, 1900–2025, at 1,535 comparisons per body (15,350 total across 10 bodies) — the full 1900–2100 grid moves the mean to 0.878″ for reasons unrelated to ephemeris accuracy (see below). And it compares against planetary-system barycentres, not physical planet centres, matching what the DE440s kernel stores and what SpkReader returns; querying centres instead would inject a spurious ~0.1″ offset for the outer planets (scripts/generate_horizons_oracle.py) — the same order of magnitude as the headline mean itself. These three facts are also published as data in metrics.json's accuracy block (quantity, era, targetConvention), so the site renders them rather than anyone hand-copying this paragraph.
SpkReader vs JPL Horizons (DE441) — oracle_comparison.rs, 24,350 committed rows (10 bodies × 2,435 dates, 1900–2100). Horizons serves DE441, so this measures our DE440s pipeline against an independent kernel.
| Era | Comparisons | Mean | Max |
|---|---|---|---|
| 1900–2025 (ΔT measured) | 15,350 | 0.103″ | 1.187″ (Uranus) |
| 1900–2100 (all) | 24,350 | 0.878″ | 44.912″ (Moon, 2099) |
15,349 of 15,350 comparisons before 2026 are sub-arcsecond. Past 2025 the residual is ΔT prediction, not ephemeris error: our Espenak–Meeus extrapolation and Horizons' ΔT diverge by ~68 s at 2099, and the error scales with a body's angular rate — the Moon (0.64″/s) picks up ~45″, Pluto essentially none. At 2099-02-06, five bodies spanning 0.03–0.64″/s all imply the same 66–71 s offset, which is the signature of a clock difference, not a position error.
AnalyticalProvider vs JPL Horizons — analytical_oracle.rs, 1900–2025: overall mean 0.239″, worst case 1.896″ (Neptune), Moon 0.169″ mean via ELP/MPP02. 13,815 comparisons across 9 bodies (1,535 dates per body) over the measured-ΔT era; see metrics.json's accuracy.analytical block.
Per body, because the mean hides a pattern worth knowing before you pick this provider:
| body | mean″ | body | mean″ |
|---|---|---|---|
| Sun | 0.180 | Jupiter | 0.239 |
| Moon | 0.169 | Saturn | 0.251 |
| Mercury | 0.180 | Uranus | 0.267 |
| Venus | 0.180 | Neptune | 0.503 |
| Mars | 0.178 |
The inner bodies sit in a tight band at ~0.18″ and the error then grows monotonically outward.
That is the truncation, and it is a property of how the series is cut rather than of any one
planet: scripts/generate_vsop87a.py drops terms below a uniform absolute amplitude of
1e-7 AU, applied identically to all eight. Saturn is not cut harder than Mercury — it retains
the most terms of any planet, 7,530 of 30,046. But an absolute cut leaves a residual whose size
scales with the orbit, so converting each body's angular error back into a position error gives
9× the threshold at 1 AU, 60× at Jupiter, 116× at Saturn, 249× at Uranus and 734× at Neptune.
Tightening the threshold would shrink this at the cost of the coefficient set, which is what
makes this provider viable in WASM and at the edge. If you need the outer planets to
sub-0.1″, use SpkReader, where they are the best bodies rather than the worst: Jupiter
0.083″ and Saturn 0.061″ against the same oracle, versus ~0.13″ for the inner planets.
Until 2026-08-20 those figures were 2.06″ mean and 24.22″ worst, and this README attributed the gap to VSOP87A being a truncated theory. That was wrong, and the wording protected a defect of ours: the analytical provider answered EarthMoonBarycenter with VSOP87A's Earth-centre series, so the observer sat 4,671 km off, and earth_state divided a barycentre-relative Moon by 1 + EMRAT instead of EMRAT for a further 56.8 km. Both are fixed. The second one moved the SPK path too, 0.106″ → 0.103″.
ELP/MPP02 Moon — lunar_horizons.rs: 0.015″ at J2000, 0.020–0.053″ across 1500–2500 CE.
What is not measured
- House cusps are not validated against any external reference.
- No ayanamsha is validated against another implementation, and that is deliberate. All eleven are derived forward from a primary — a chapter, a committee, a proposer's own paper, or a star catalogue — and each reproduces its own anchor to 1e-9° and, where its primary documents one, its own zero year. What is not claimed is agreement with anyone else's numbers: comparing against them would be the reverse-engineering this re-derivation exists to undo. See
docs/audit/2026-08-17-ayanamsha-cleanroom/. - Dasha and nakshatra tests are invariant tests, not external comparisons: they verify that BPHS constants sum to 120 years and that boundaries tile the circle.
- Two Shadbala components are partial, and the gap is in the tool description, not just here. Sthana Bala carries four of its five sub-components — Uchcha, Ojhayugma, Kendradi and Drekkana — but not Saptavargaja Bala, which needs a Moolatrikona degree table and a panchadha maitri derivation we do not yet hold from a primary. Kala Bala covers Nathonnatha and Paksha only. Dig, Cheshta, Naisargika and Drik Bala are whole.
Technical report
A full write-up of both ephemeris pipelines, their measured accuracy, and the clean-room
provenance of every algorithm: docs/paper/main.tex (build with
make -C docs/paper pdf, requires tectonic).
It goes well beyond the summary above, and reports several things that are stated nowhere else:
- Independent cross-validation by a third party against two national-agency ephemerides from two different agencies (JPL DE440 and IMCCE INPOP21a), rather than agreement with JPL alone.
- Analytical-path accuracy across 1550–2650 CE, per body and per century-band of distance from J2000, with the time scale removed from the comparison by addressing both sides in TT so that ΔT divergence cannot contaminate the residual.
- Component-level validation of the SPK reader against another implementation's read of a comparable kernel, isolating the DAF/SPK parser and Chebyshev evaluation from the apparent-place pipeline layered on top.
- A methodological note on reproducibility: bit-level output is architecture-scoped, because the SIMD trigonometric kernel maps to one AVX2 register but two NEON registers. Accuracy is not — measured identical to a milliarcsecond on both.
- What is not validated, stated plainly, including house cusps, the true node, and every ayanamsha.
Status: not peer reviewed, and not submitted anywhere. It is a technical report, not a preprint. Every measured figure in it is specific to the engine version named on its title page.
What's inside
Two ephemeris providers. SpkReader reads JPL DE440s (~31 MB) for sub-arcsecond work. AnalyticalProvider compiles VSOP87A + ELP/MPP02 to constants and needs no data files — for WASM, edge and Cloudflare Workers.
Jyotish, from primary sources. 27 nakshatras with padas and lords · 5 dasha systems (Vimshottari, Yogini, Ashtottari, and Jaimini's Chara & Narayana) · all 16 vargas (D-1 → D-60) · six-component shadbala with Ishta/Kashta phala (two components partial — see above) · 11 ayanamshas, each traceable to a chapter, a star or a committee · panchanga's five limbs, with vara reckoned from local sunrise and Rahu/Gulika Kalam as real time windows · graded drishti per BPHS Ch. 26 · mean, true and osculating nodes, all referred to the ecliptic of date, with the J2000 variant tracking DE441's OM to 0.6″ (KP sub-lord ready).
Western: calculation, not interpretation. 10 house systems, major aspects with applying/separating motion, essential dignities, synastry and composite. ChartConfig defaults to tropical. There is no Western interpretive layer and no parity with the Jyotish surface.
Crates, published to crates.io in lockstep: vedaksha (umbrella, 7 locales) · -math · -ephem-core · -astro · -vedic · -graph · -mcp.
MCP + property graph
17 tools, discoverable with a single tools/list. The catalog is generated from the Rust definitions and locked by a snapshot test, so it cannot silently drift from the code.
compute_natal_chart · compute_dasha · compute_vargas · compute_karakas · compute_combustion · compute_shadbala · compute_ashtakavarga · compute_transit · compute_gochara · search_transits · search_muhurta · compute_panchanga · compute_drishti · compute_bhavas · compute_synastry · compute_composite · emit_graph
Any chart converts to a property graph via emit_graph or vedaksha_graph::chart_to_graph, emitting Cypher, SurrealQL, JSON-LD, JSON or RAG embedding text. An agent can then ask "which planets aspect the 7th-house lord?" as a graph query instead of re-implementing chart logic. Computations themselves return typed structs; the graph is a projection you ask for.
What a chart actually yields: 4 of the ontology's 9 node types (Chart, Planet, Sign, House) and 7 of its 12 edge types. Nakshatra, Pada, Pattern, DashaPeriod and FixedStar are defined in vedaksha_graph::ontology but are not built from a ComputedChart, which does not carry the data they need. Compute those through their own APIs.
VEDAKSHA_MCP_TOKEN=… vedaksha-mcp --http --port 3100
HTTP mode requires Authorization: Bearer <token> on every POST and refuses to start without VEDAKSHA_MCP_TOKEN, unless you pass --insecure-no-auth for a trusted network. /health and the informational GET stay open.
Clean-room provenance
Every implemented algorithm carries a // Source: doc-comment naming its primary paper or treatise — VSOP87A, ELP/MPP02, IAU standards, BPHS, Jaimini. Two subsystems have been re-derived from primary sources behind a documented firewall, and each ships its own audit directory: the lunar theory (2026-05-09) and the sidereal surface (2026-08-17). Each records the primaries, the process, what was searched and rejected, and a generator that re-derives the values so the claim can be re-run rather than taken on trust. See also DATA_PROVENANCE.md. This is the evidence a BUSL-1.1 licensee can audit.
In production
| Product | What it is |
|---|---|
| kundalimcp.com | Agentic-AI Jyotish MCP with the full computation suite. Builds directly on the vedaksha-* crates. |
| kundali.live | Consumer endpoint — chat-based readings and self-serve PDF reports. |
License
Business Source License 1.1 — SPDX BUSL-1.1, which is what crates.io, PyPI and npm display.
- Non-commercial — free (personal, research, education, internal tools).
- Commercial — $500, charged once per organization. Unlimited products and seats, perpetual, and it covers the version you license and every version released after it — not charged again per release. Purchase →
- Converts to Apache 2.0 four years after each version's release. That future licence
text is kept at
CHANGE-LICENSE.txt— it is the Change License in BUSL terms, not a licence you may choose today.
See LICENSE, SECURITY.md, CONTRIBUTING.md and MAINTENANCE.md.
Copyright © 2026 ArthIQ Labs LLC · Licensed under the Business Source License 1.1 (BUSL-1.1).