Changelog¶
All three packages ship at the same version, so a version number means the same release everywhere. Each package's own notes are below.
The releases page carries the same notes with links to the commits.
Python package¶
indikit on PyPI: the driver SDK, the async client and the web bridge.
0.2.0 (2026-08-15)¶
⚠ BREAKING CHANGES¶
- protocol: timestamps on Vector, Message and DelProperty are timezone-aware UTC, so comparing one against a naive datetime.now() raises TypeError. A naive datetime passed to prop.set(timestamp=) or device.message(timestamp=) is read as UTC, not local. parse_indi() no longer raises on a malformed value; it returns fewer messages, and the count is on the parser. format_number changes at exact half ticks.
Added¶
- cli: add Typer serve/run/monitor commands (e583d5e)
- client: add PropertyStore cache with subscriptions (56e7950)
- client: add public send() for forwarding messages upstream (9c573dd)
- client: add reconnecting IndiClient (82a4cee)
- cli: indi-nexus new scaffolds a runnable driver (c53b24c)
- cli: run drivers in-process with serve --device (e19f168)
- docs: add a live weather demo running in the browser (da64737)
- docs: MkDocs Material site with live demo, both APIs, Pages deploy (1da18e4)
- docs: rebuild the weather demo around the real panel and a proper dashboard (a6c8d2d)
- docs: redesign the custom UI as a dome wallboard (cf67168)
- driver: add @every and @on_new decorators (a9ee27e)
- driver: add BoundProperty and Device base class (4a9f7b3)
- driver: add stdio runtime and package entrypoint (7a841d8)
- driver: built-in CONNECTION lifecycle and connection-gated jobs (1a32b14)
- driver: serialize dispatch, type properties, and quiet the wire (2824378)
- examples: add a dome simulator driver (aefacf1)
- examples: add a hardware-shaped weather station driver (a7da59d)
- examples: add a telescope simulator driver (90ebb9e)
- examples: add an Open-Meteo driver for real public data (4a6def5)
- examples: gate the dome behind CONNECTION; test both simulators (3a9bc9a)
- examples: port libindi's CCD Simulator to the SDK (2f0626a)
- examples: publish wind bearing and apparent temperature (65d92bb)
- examples: serve any driver in the demo bridge via --device (463826e)
- examples: serve several drivers in one panel (c3a325f)
- panel: animate the messages rail and use a bottom drawer on mobile (da4804d)
- panel: backend-less demo build with an in-browser dome simulator (460f072)
- panel: disclose the messages panel from its own title bar (705a33a)
- panel: dock the message log as a right-hand sidebar (c57e596)
- panel: dock the message log as a VS Code-style bottom panel (69a87f4)
- panel: dock the messages log as a collapsible side panel (47ff543)
- panel: move the messages toggle into the sidebar menu (d147f04)
- panel: navbar-height messages bar, unread badge, and tooltips (721e6c9)
- panel: toggle the messages sidebar from a header icon button (007f781)
- protocol: add enableBLOB message and BLOBPolicy (60f3c08)
- protocol: add JSON codec and base64 BLOB serialization (8195c92)
- protocol: add slugify and Element.from_labels (97b067f)
- protocol: add typed INDI protocol core with XML codec (c39975a)
- protocol: pure vector accessors for handler ergonomics (fe5af28)
- react: add per-kind value hooks (28f27a2)
- react: add the shadcn accordion primitive (5341f4f)
- react: add the shadcn drawer primitive (9180b8f)
- react: export the test harness as @indi-nexus/react/testing (8440709)
- testing: add DeviceHarness (a737146)
- web: add @indi-nexus/client transport and property store (6c77924)
- web: add @indi-nexus/react hooks and shadcn/ui components (c46ab2d)
- web: add Bridge and FastAPI app (WebSocket + REST snapshot) (5048e91)
- web: add self-contained debug inspector page (f6441b9)
- web: add the reference panel app (2d7e9c2)
- web: debug-info display setting for technical INDI detail (f38af6f)
- web: live current-value readouts on writable elements (c631c1e)
- web: mark the selected switch in the action colour and pulse Busy (cf55441)
- web: serve the built panel from FastAPI; add demo bridge harness (eff8e1a)
- web: stack message-log entries and follow the newest (cd91cdf)
- web: useElement hook for single-value reads (b1623cf)
Fixed¶
- build: keep node_modules out of the sdist and the package sources in (718abd2)
- ci: build workspace packages before typecheck and test (072e32f)
- ci: give Mermaid a browser to render diagrams with (aa92a79)
- ci: pin pnpm version for pnpm/action-setup (e977c47)
- ci: pin setup-uv to a tag that exists (965440c)
- client: ignore a socket that has already been superseded (7b4d0e2)
- client: keep a property's state when a set does not carry one (dfa9a46)
- client: key BLOB policies on a pair, and drop non-object frames (ff2d87e)
- client: render numbers the way the wire renders them (9903f21)
- demo: put the simulators back in step with their drivers (0c475d8)
- driver: gate @every jobs on setup() completion (7ceeabd)
- driver: honor the getProperties device filter (856768b)
- driver: ignore client writes addressed to other devices (31ad723)
- driver: survive exceptions from @on_new handlers and setup() (cce961f)
- examples: power-gate the demo animation and accept partial switch writes (95d1c99)
- protocol: make
name in vectortell the truth (30275d6) - protocol: survive a hostile peer and stamp timestamps in UTC (bfe2ddf)
- react: restore pointer cursor on enabled buttons under Tailwind v4 (42bb085)
- transport: add close to the transport contract and release sockets (0fdc210)
- typing: ship a py.typed marker (4664027)
- web: buffer INDI messages and replay them to late-joining viewers (93c258e)
- web: drop the tick and stop a switch deselecting itself (2fc020d)
- web: make the active member of a switch vector legible (fdfd135)
- web: make the panel and the wallboard work on a phone (ffc1d7e)
- web: stack writable-element rows so labels and readouts always fit (aec4436)
- web: start the bridge without waiting for indiserver (e0274f3)
- web: track src/lib/utils.ts (gitignored by the Python lib/ rule) (b777e09)
- web: use relative imports in @indi-nexus/react instead of the @/ alias (8d1bd3a)
Packaging¶
- add httpx dev dependency and filter starlette test warning (c2ed83c)
- automate PyPI and npm releases (097a3b9)
- bundle the reference panel into the wheel (e7dd273)
- ci: move every action off the deprecated Node 20 runtime (bacd233)
- keep breaking changes on the minor while below 1.0 (1a9d647)
- let Release Please own the changelog and drop towncrier (8a37c37)
- manage the changelog with towncrier (990b29b)
- require Python 3.12 and drop the anyio dependency (128d042)
- set up Python packaging, dependencies, and dev tooling (7ff13cd)
- test and declare Python 3.13 and 3.14 (f962290)
Documentation¶
- add DEVELOPMENT.md with the full command reference (40a8192)
- add quickstart and command reference to README (9df062f)
- add the real-data tutorial and its custom UI (47980b1)
- adopt Python 3.12, asyncio, and NumPy-docstring conventions (802a16a)
- claude: split the guidance by area and add the global working rules (da96e31)
- correct the macOS install claim and cut repetition (a9e8027)
- cover the new SDK surface, port guide, and mermaid diagrams (f94fd80)
- cut duplication and fix broken cross-references (44781e8)
- cut the 0.1.0 changelog for today, and write up releasing (93c1a26)
- describe INDINexus, stack, and workflows in README and CLAUDE.md (e69104d)
- docstring type fields are plain text, not backticked (300b85a)
- document the examples and the three ways to run a driver (1fc9f03)
- driver: add Numpydoc parameter types to docstrings (429d920)
- driver: document the driver SDK and add demo device (f9d8dae)
- driver: NumPy-style docstrings across the driver SDK (7ed606a)
- drop backticks from docstring type fields (5c733ee)
- examples: add monitor_client example with tests (3d1f137)
- examples: docstring the demo device methods (f12b7f5)
- feature all three simulators in the demo (6638357)
- fix the claims an audit found were no longer true (65c8cc9)
- focus the README on quickstart and link the development guide (82a9fdc)
- general refactor - tighten prose and update project URLs (7b3b76e)
- improve mermaid diagram contrast on light backgrounds (ff1c796)
- install from PyPI, and be clear indiserver is the hub (25bba24)
- let the diagrams follow the theme, and validate them in CI (40152d7)
- link the weather demo and give it a nav tab (893a139)
- make the flat-field lamp a real example and run it in the browser (21ddd52)
- mark client layer done; refresh README (8f0d5da)
- mark M5 done and document the frontend (e902251)
- mark web bridge and CLI done; add bridge E2E and docs (992d401)
- protocol: add Numpydoc parameter types to docstrings (d95cb56)
- protocol: NumPy-style docstrings across the protocol layer (12ae2d9)
- rewrite the public docs for a first-time reader (02abc5c)
- serve the live demo as its own page and move the site to a subdomain (f7fd934)
- specify Numpydoc parameter formatting rules (79c7554)
- split the changelog into sections and publish it on the docs site (e91502e)
- tests: add NumPy-style docstrings to the test suite (0bcb910)
- tests: type the docstring parameter entries in the suite (7b2c470)
- tighten CLAUDE.md and point it at DEVELOPMENT.md (73509ad)
- update CLAUDE.md for the transport, runtime, and bridge changes (79b9b93)
- web: add readmes and licences to the published npm packages (169e304)
Changed¶
- driver: extract shared transport contract (bbfb996)
- driver: replace anyio with asyncio in the runtime (7f65305)
- examples: adopt the SDK connection surface and accessors (00cb80d)
- protocol: use stdlib StrEnum for the wire enums (e4ff825)
- web: map an INDI state to its colour in one place (2084e66)
0.1.0 - 2026-08-11¶
Python package (indi-nexus)¶
Added¶
- A nightly interop suite that runs against a real
indiserverand real libindi drivers. Every other test here reads our own XML with our own parser, which is self-consistent by construction and so cannot catch a deviation from the spec; these put libindi on the other side of the wire. It covers libindi's own clients driving our drivers, our client against all twelve simulators libindi ships, a differential comparison againstindi_getprop, BLOB delivery, reconnecting to a real socket, and a browser driving a C++ driver through the whole stack. Real traffic captured from those drivers is committed as a fixture and replayed by the fast suite, so a pull request gets the benefit without libindi installed. examples/flat_panel.py: the flat-field lamp driver the "Writing a driver" guide builds line by line. It was previously only a listing in the guide, so nothing checked it still ran; it is now a real example covered by the test suite, and the guide points at it.indi-nexus serve --device module:Classruns drivers inside the web process, so a driver can be tried on screen with onlypip install indi-nexusand noindiserverto install first. Repeat the flag for several devices. It is a development convenience, not a hub: it serves one client and stops with the command.indiserverremains what anything real runs under, andservewithout--deviceconnects to it exactly as before. This replacesexamples/demo_bridge.py, whose hub now lives in the package asindi_nexus.web.InProcessHub.
Fixed¶
"RA" in vectornow answers truthfully.Vectordefined__getitem__without__contains__, so Python fell back to indexing 0, 1, 2 against a name lookup and returnedFalsefor an element that was present, without raising. The interop suite found it by writing the obvious thing.indi-nexus servenow starts even whenindiserveris unreachable, instead of hanging in startup with no output. The panel loads and reports a disconnected state, and the bridge connects on its own onceindiserverappears.IndiClient.start()gained awaitkeyword for this; its default is unchanged, so scripts and monitors still block until the first connection.
Packaging¶
- Published to PyPI as
indi-nexus, sopip install indi-nexusgets the driver SDK, the async client, the web bridge and the bundled reference panel. Releases are cut frommainby release-please and uploaded with trusted publishing, so no registry credentials are stored in the repository. - The source distribution no longer bundles
web/node_modules(about 8 MB of build dependencies), and it now contains the TypeScript sources of@indi-nexus/clientand@indi-nexus/react, which were being dropped from it.
Documentation¶
- Getting started now installs from PyPI instead of cloning the repository and building the
frontend. The panel is compiled into the wheel, so
pip install indi-nexusis the whole setup, and the first driver you see running is one you scaffolded rather than an example that only exists in a checkout. - The architecture diagrams now follow whichever theme they are rendered in. They carried a hardcoded light palette, so on a dark page the boxes became a bright island and the labels went unreadable; ownership is shown with the border instead of colour. CI validates every diagram with Mermaid's own CLI, so a broken one fails the build rather than rendering as an empty box.
Frontend (@indi-nexus/client, @indi-nexus/react)¶
Changed¶
- Busy now pulses, on both the state badge and the status-light dots. It is the one state that means "still happening", and a still badge cannot tell an instrument mid-move from one that stopped there. The pulse holds still for anyone whose system asks for reduced motion.
- Every indicator that shows an INDI state now reads its colour from one place. A component
cannot build a Tailwind class name at runtime, so each of the five places that showed a
state carried its own copy of the four-way mapping, and they drifted. Elements now declare
data-indi-stateand the theme sets--indi-statefrom it, so a badge, a dot, a bar and an SVG fill can each use whichever CSS property they need.StateDotis exported for frontends built on the hooks.
Fixed¶
- The selected member of a switch vector is now unmistakable, and safer to click. It was drawn
with the same
accenttoken the toggles hover to, so a hovered unselected member looked identical to the selected one, and the fill itself was nearly invisible against the card; it now wears the same teal as the Set button, a colour hovering never reaches. Clicking the member that is already on no longer turns it off. UnderOneOfManyexactly one member is on by definition, so there was no such state to reach - a stray click on a lit "On" would have switched the instrument off. Selecting the member you want is now the only way to change it.AtMostOne, which genuinely permits none, still clears that way.
Packaging¶
- Published to npm as
@indi-nexus/clientand@indi-nexus/react, released in lockstep with the Python package and uploaded with trusted publishing.
Documentation¶
- A flat-panel demo on the documentation site, running the guide's driver as an in-browser simulator behind the panel that ships in the wheel, so the driver a reader has just been taught can be operated with nothing installed.
@indi-nexus/clientand@indi-nexus/reactnow ship a README and a copy of the licence, so both have documentation on their npm pages.
@indikit/client¶
The framework-agnostic TypeScript client and property store.
@indikit/react¶
The React hooks and shadcn/ui components.