unibind

Generates idiomatic TypeScript, Python, Kotlin, and Elixir SDK bindings from one Rust surface.

Updated Aug 5, 2026
One-click install
npx skills add https://github.com/harivansh-afk/loom-index-e2e --skill unibind-harivansh-afk
Or copy as Structured Prompt for Agent▼
Please help me install this Agent Skill.
Skill: unibind
Source: https://github.com/harivansh-afk/loom-index-e2e/tree/main/skills/unibind
Command: npx skills add https://github.com/harivansh-afk/loom-index-e2e --skill unibind-harivansh-afk

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Maintaining four hand-written SDKs for one Rust service produces transliterated, unidiomatic APIs and drift between languages. unibind lowers a single annotated Rust surface into an intent-carrying IR, then renders each language's native idiom, so every SDK reads like a native library. ## Core Features & Use Cases - Intent-based IR lowering: Rust attributes like #[unibind(associated)] and #[unibind::enumeration] express intent (construct, release, closed variant set, stream), and each backend renders its own idiom such as await using in TypeScript, async with in Python, use { } in Kotlin, and tagged tuples in Elixir. - Multi-file exports and doc link resolution: #[unibind::export(parts = [...])] splits a surface across files with compile errors for unregistered files, and every rustdoc intra-doc link is resolved per language or the build fails. - Use Case: When adding a new verb to the ix SDK in crates/ix/sdk-bind, place it in the file owning that namespace, annotate it once, and all four generated SDKs plus their conformance suites update consistently. ## Quick Start Ask the AI to add a new associated constructor to the Machine object in the ix SDK surface and verify the generated TypeScript and Python output follows the intent table.

Frequently Asked Questions about unibind

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I generate TypeScript and Python SDKs from Rust code?▼

Annotate the Rust surface with unibind macros such as `#[unibind::export]` and `#[unibind(associated)]`, and the lowering pipeline produces an IR that each backend renders idiomatically. TypeScript gets promise-returning statics and string-literal unions, Python gets static coroutines and `enum.StrEnum`.

How does unibind render Rust enums in each language?▼

Closed unit enums become a union of string literals in TypeScript, `enum.StrEnum` in Python, an enum class in Kotlin, and atoms in Elixir. The wire spelling is decided once at lowering using serde's rename conventions, while type and member names stay idiomatic per language.

Does unibind support Kotlin and Elixir backends?▼

The JVM backend targets Kotlin rather than Java because Java has no native answer for async, but it currently rejects objects, async functions, and unit enums outright. Elixir supports objects as ResourceArc handles and free async functions, while rejecting object member async and unit enums.

Why does unibind fail the build on broken doc links?▼

Every rustdoc intra-doc link is resolved against the interface and rendered in each language's spelling, such as `{@link Machine.forwardPort}` in TypeScript. A link naming nothing fails generation with the dead target named, because 214 dead links shipped in published files before this gate existed.

How do I split a unibind export across multiple Rust files?▼

List the files in `#[unibind::export(parts = [...])]`; each part is a list of items appended to the module before lowering. Compile errors catch a part listed twice, a missing path, or an unlisted `.rs` file sitting with the parts.

What are the limitations of generated SDK surfaces in unibind?▼

Data-carrying enum variants are rejected by lowering in all backends, and Python lacks runtime validation where TypeScript gets generated Zod schemas. Anything hand-written on top of a generated surface is treated as a bug report against unibind, not a layer to grow.