{"id":49026944,"url":"https://github.com/kreuzberg-dev/alef","last_synced_at":"2026-05-01T09:04:31.157Z","repository":{"id":350654475,"uuid":"1197540366","full_name":"kreuzberg-dev/alef","owner":"kreuzberg-dev","description":"Generate fully-typed, lint-clean language bindings for Rust libraries across 11 languages","archived":false,"fork":false,"pushed_at":"2026-04-29T08:27:38.000Z","size":7592,"stargazers_count":14,"open_issues_count":6,"forks_count":4,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-29T08:35:43.936Z","etag":null,"topics":["bindgen","c","c-ffi","code-generation","csharp","elixir","ffi","golang","java","language-bindings","napi-rs","php","polyglot","pyo3","python","r","ruby","rust","typescript","wasm"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kreuzberg-dev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-31T17:01:28.000Z","updated_at":"2026-04-29T08:27:37.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/kreuzberg-dev/alef","commit_stats":null,"previous_names":["kreuzberg-dev/alef"],"tags_count":93,"template":false,"template_full_name":null,"purl":"pkg:github/kreuzberg-dev/alef","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kreuzberg-dev%2Falef","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kreuzberg-dev%2Falef/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kreuzberg-dev%2Falef/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kreuzberg-dev%2Falef/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kreuzberg-dev","download_url":"https://codeload.github.com/kreuzberg-dev/alef/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kreuzberg-dev%2Falef/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32490815,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"online","status_checked_at":"2026-05-01T02:00:05.856Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bindgen","c","c-ffi","code-generation","csharp","elixir","ffi","golang","java","language-bindings","napi-rs","php","polyglot","pyo3","python","r","ruby","rust","typescript","wasm"],"created_at":"2026-04-19T07:10:21.134Z","updated_at":"2026-05-01T09:04:31.121Z","avatar_url":"https://github.com/kreuzberg-dev.png","language":"Rust","readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg width=\"100%\" alt=\"kreuzberg.dev banner\" src=\"https://github.com/user-attachments/assets/1b6c6ad7-3b6d-4171-b1c9-f2026cc9deb8\" /\u003e\n\n\u003cdiv style=\"display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; margin-top: 16px;\"\u003e\n\n\u003ca href=\"https://crates.io/crates/alef-cli\"\u003e\n  \u003cimg src=\"https://img.shields.io/crates/v/alef-cli?color=007ec6\" alt=\"crates.io\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://github.com/kreuzberg-dev/alef/actions/workflows/ci.yml\"\u003e\n  \u003cimg src=\"https://img.shields.io/github/actions/workflow/status/kreuzberg-dev/alef/ci.yml?label=CI\u0026color=007ec6\" alt=\"CI\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://github.com/kreuzberg-dev/alef/blob/main/LICENSE\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/License-MIT-007ec6\" alt=\"License\"\u003e\n\u003c/a\u003e\n\n\u003c/div\u003e\n\n\u003cbr\u003e\n\n\u003ca href=\"https://discord.gg/xt9WY3GnKR\"\u003e\n  \u003cimg height=\"22\" src=\"https://img.shields.io/badge/Discord-Join%20our%20community-7289da?logo=discord\u0026logoColor=white\" alt=\"Discord\"\u003e\n\u003c/a\u003e\n\n\u003c/div\u003e\n\n# Alef\n\nGenerate fully-typed, lint-clean language bindings for Rust libraries across 11 languages. Alef handles the entire pipeline -- API extraction, code generation, type stubs, package scaffolding, build orchestration, version sync, and e2e test generation -- from a single TOML config file.\n\n## Key Features\n\n- **API extraction** -- Parses your Rust crate's public API via `syn` into a language-agnostic intermediate representation. Handles `pub use` re-exports across workspace crates, `#[cfg(feature)]` gating, serde `rename_all` metadata, doc comments, `Default` detection, and transparent newtype resolution.\n- **11 language backends** -- Each backend generates idiomatic, lint-clean binding code using the target language's native framework. See the [supported languages](#supported-languages) table below.\n- **Configurable DTO styles** -- Choose how types are represented in each language: Python `dataclass` vs `TypedDict` vs `pydantic` vs `msgspec`, TypeScript `interface` vs `zod`, Ruby `Struct` vs `dry-struct` vs `Data`, and more. Input and output types can use different styles.\n- **Type stubs** -- Generates `.pyi` (Python), `.rbs` (Ruby), and `.d.ts` (TypeScript) type definition files for editor support and static analysis in consuming projects.\n- **Package scaffolding** -- Generates complete package manifests for each language: `pyproject.toml`, `package.json`, `.gemspec`, `composer.json`, `mix.exs`, `go.mod`, `pom.xml`, `.csproj`, `DESCRIPTION` (R), and `Cargo.toml` for binding crates.\n- **E2E test generation** -- Write test fixtures as JSON, get complete runnable test suites for all configured languages. Supports 40+ assertion types, field path aliases, per-language overrides, and skip conditions.\n- **Adapter patterns** -- Define custom FFI bridging patterns in config: `sync_function`, `async_method`, `callback_bridge`, `streaming`, and `server_lifecycle`. Alef generates the glue code for each backend.\n- **Trait bridges** -- Generate FFI bridges so foreign-language objects can implement Rust traits (plugin pattern). Configured via `[[trait_bridges]]`; supported across all 11 backends.\n- **Version sync** -- Propagates the version from `Cargo.toml` to all package manifests, C headers, pkg-config files, and any custom file via regex text replacements.\n- **Build orchestration** -- Wraps `maturin`, `napi`, `wasm-pack`, and `cargo`+`cbindgen` with post-processing steps (e.g., patching `.d.ts` files for `verbatimModuleSyntax` compatibility).\n- **Pipeline commands with smart defaults** -- `alef lint`, `test`, `build`, `setup`, `update`, `clean` ship with built-in per-language defaults that dispatch on the configured package manager (`uv`/`pip`/`poetry` for Python; `pnpm`/`npm`/`yarn` for Node) via the top-level `[tools]` section. Every default carries a POSIX `command -v` precondition so missing tools warn-and-skip instead of failing the run.\n- **Override knobs that absorb common customisations** -- per-language `run_wrapper`, `extra_lint_paths`, and `project_file` (Java/C#) reduce override boilerplate so consumers rarely need to redefine entire `[lint.\u003clang\u003e]` / `[build_commands.\u003clang\u003e]` tables.\n- **Publish pipeline** -- `alef publish prepare|build|package|validate` vendors the core crate, cross-compiles release artifacts (cargo / cross / maturin / napi / wasm-pack), and packages distributables (C FFI tarball with pkg-config/CMake, PHP PIE archive, Go FFI tarball).\n- **Visitor FFI** -- Generates a 40-method visitor callback interface via C FFI, enabling the visitor pattern in Go, Java, C#, and other FFI-based languages.\n- **Config validation** -- `alef.toml` is validated at load time. Custom command tables that override a main field must declare a `precondition` so warn-and-skip behavior is preserved on user systems. Fields whose value matches the built-in default emit a `tracing::warn!` so consumer configs stay minimal.\n- **Caching** -- blake3-based content hashing skips regeneration when source and config haven't changed. `alef verify` checks staleness in CI (including README freshness).\n\n## Supported Languages\n\n| Language | Framework | Package Format | Test Framework | DTO Styles |\n|----------|-----------|----------------|----------------|------------|\n| Python | [PyO3](https://pyo3.rs) | PyPI (.whl) | pytest | `dataclass`, `typed-dict`, `pydantic`, `msgspec` |\n| TypeScript/Node.js | [NAPI-RS](https://napi.rs) | npm | vitest | `interface`, `zod` |\n| WebAssembly | [wasm-bindgen](https://rustwasm.github.io/wasm-bindgen/) | npm | vitest | -- |\n| Ruby | [Magnus](https://github.com/matsadler/magnus) | RubyGems (.gem) | RSpec | `struct`, `dry-struct`, `data` |\n| PHP | [ext-php-rs](https://github.com/davidcole1340/ext-php-rs) | Composer | PHPUnit | `readonly-class`, `array` |\n| Go | cgo + C FFI | Go modules | go test | `struct` |\n| Java | [Panama FFM](https://openjdk.org/jeps/454) | Maven (.jar) | JUnit | `record` |\n| C# | P/Invoke | NuGet (.nupkg) | xUnit | `record` |\n| Elixir | [Rustler](https://github.com/rusterlium/rustler) | Hex | ExUnit | `struct`, `typed-struct` |\n| R | [extendr](https://extendr.github.io/extendr/) | CRAN | testthat | `list`, `r6` |\n| C | [cbindgen](https://github.com/mozilla/cbindgen) | Header (.h) | -- | -- |\n\n## Quick Start\n\n### Install\n\n```bash\n# Pre-built binary (fastest)\ncargo binstall alef-cli\n\n# From crates.io\ncargo install alef-cli\n\n# Via Homebrew\nbrew install kreuzberg-dev/tap/alef\n\n# From source\ngit clone https://github.com/kreuzberg-dev/alef.git\ncd alef \u0026\u0026 cargo install --path crates/alef-cli\n```\n\n### Initialize\n\n```bash\ncd your-rust-crate\nalef init --lang python,node,ruby,go\n```\n\nThis creates `alef.toml` with your crate's configuration.\n\n### Generate Bindings\n\n```bash\nalef generate              # Generate all configured languages\nalef generate --lang node  # Generate for specific language\nalef generate --clean      # Regenerate everything (ignore cache)\n```\n\n### Build\n\n```bash\nalef build                 # Build all languages\nalef build --lang node     # Build Node.js (runs napi build + patches .d.ts)\nalef build --release       # Release profile\n```\n\n### Test\n\n```bash\nalef test                  # Run all language tests\nalef test --e2e            # Include e2e tests\nalef test --lang python,go # Specific languages\n```\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `alef init` | Initialize `alef.toml` for your crate |\n| `alef extract` | Extract API surface from Rust source into IR JSON |\n| `alef generate` | Generate language bindings from IR |\n| `alef stubs` | Generate type stubs (`.pyi`, `.rbs`, `.d.ts`) |\n| `alef scaffold` | Generate package manifests (`pyproject.toml`, `package.json`, etc.) |\n| `alef readme` | Generate per-language README files |\n| `alef build` | Build bindings with native tools (`maturin`, `napi`, `wasm-pack`, etc.) |\n| `alef test` | Run per-language test suites (`--e2e` for e2e tests, `--coverage` for coverage) |\n| `alef lint` | Run configured linters on generated output |\n| `alef fmt` | Run only the format phase of lint |\n| `alef update` | Update dependencies per language (`--latest` for aggressive upgrades) |\n| `alef setup` | Install dependencies per language |\n| `alef clean` | Clean build artifacts per language |\n| `alef sync-versions` | Sync version from `Cargo.toml` to all manifests (use `--set \u003cversion\u003e` to override) |\n| `alef verify` | Check if bindings are up-to-date (CI mode with `--exit-code`) |\n| `alef diff` | Show what would change without writing |\n| `alef all` | Run full pipeline: generate + stubs + scaffold + readme + e2e + docs + sync |\n| `alef e2e` | Generate e2e test projects from JSON fixtures (subcommands: `generate`, `init`, `scaffold`, `list`, `validate`) |\n| `alef publish` | Vendor, cross-compile, and package release artifacts (subcommands: `prepare`, `build`, `package`, `validate`) |\n| `alef cache` | Manage build cache (subcommands: `clear`, `status`) |\n\n## Configuration-Driven Defaults\n\nAll operational commands (`lint`, `fmt`, `update`, `setup`, `clean`, `build`, `test`) ship with built-in per-language defaults. No configuration is required to use them — run `alef lint` or `alef update` out of the box. Defaults dispatch on the top-level `[tools]` section (package-manager selection) and per-language knobs (`run_wrapper`, `extra_lint_paths`, `project_file`) — both described below — so most consumer projects can avoid redefining whole command tables.\n\nEvery built-in default declares a POSIX `command -v \u003ctool\u003e` **precondition**: when the underlying tool is missing on the user's system, the language is skipped with a warning rather than failing the run. When you override a main command field (`format`, `command`, `update`, `install`, `clean`, `build`, …), you **must** declare a `precondition` of your own so the warn-and-skip semantics survive on consumer systems — alef rejects override tables that omit it at config load.\n\nOverride any default by adding the corresponding section to `alef.toml`:\n\n```toml\n# Override Node lint commands\n[lint.node]\nformat = \"oxfmt packages/node/src/\"\ncheck = \"oxlint packages/node/src/\"\n\n# Add coverage support for Python tests\n[test.python]\ncommand = \"pytest packages/python/tests/\"\ncoverage = \"pytest --cov packages/python/tests/ --cov-report=xml\"\n\n# Override dependency update commands\n[update.python]\nupdate = \"uv sync\"\nupgrade = \"uv sync -U\"\n\n# Override setup/clean\n[setup.node]\ninstall = \"pnpm install --frozen-lockfile\"\n\n[clean.node]\nclean = \"rm -rf node_modules dist\"\n\n# Override build commands\n[build_commands.python]\nbuild = \"maturin develop\"\nbuild_release = \"maturin build --release\"\n```\n\nAll command fields accept either a single string or an array of strings.\n\nNode and WASM scaffolding uses the [Oxc](https://oxc.rs) toolchain: `oxfmt` for formatting and `oxlint` for linting. Biome is no longer included in generated Node/WASM projects.\n\n### `[tools]` -- Package Manager Selection\n\nThe top-level `[tools]` section selects which package-manager / dev-tool variants every default pipeline command targets. All fields are optional; defaults match what most projects use.\n\n```toml\n[tools]\npython_package_manager = \"uv\"      # uv | pip | poetry  (default: uv)\nnode_package_manager = \"pnpm\"      # pnpm | npm | yarn  (default: pnpm)\nrust_dev_tools = [                 # tools `alef setup rust` installs via `cargo install`\n  \"cargo-edit\",\n  \"cargo-sort\",\n  \"cargo-machete\",\n  \"cargo-deny\",\n  \"cargo-llvm-cov\",\n]\n```\n\nThe Python and Node selections drive the default `lint`, `test`, `setup`, `update`, and `clean` commands — switching to `pip` swaps `uv run pytest` for plain `pytest`, switching to `yarn` swaps `pnpm up` for `yarn upgrade`, etc. Set `rust_dev_tools = []` to skip dev-tool installation entirely.\n\n### Per-language override knobs\n\nThree optional per-language fields cover the most common reasons consumers used to redefine entire command tables. They feed into every relevant default command (`format`, `check`, `typecheck`, `command`, `coverage`, `update`, `upgrade`, `install`, `clean`, `build`, `build_release`).\n\n```toml\n# Wrap every default tool invocation. Common for projects that need to\n# inherit the package-manager environment without a `before` hook.\n[python]\nrun_wrapper = \"uv run --no-sync\"  # → \"uv run --no-sync ruff format packages/python\"\n\n# Append extra paths to default lint commands.\n[python]\nextra_lint_paths = [\"scripts\"]    # → \"ruff format packages/python scripts\"\n\n# For Maven / .NET, point default lint/build/test commands at a project\n# descriptor instead of the package directory.\n[java]\nproject_file = \"pom.xml\"\n\n[csharp]\nproject_file = \"MySolution.slnx\"\n```\n\n`run_wrapper`, `extra_lint_paths`, and `project_file` are accepted on every binding language section (`[python]`, `[node]`, `[ruby]`, `[php]`, `[elixir]`, `[wasm]`, `[go]`, `[java]`, `[csharp]`, `[r]`). `project_file` only takes effect for `[java]` and `[csharp]`.\n\n## Configuration Reference\n\nAlef is configured via `alef.toml` in your project root. Run `alef init` to generate a starter config.\n\n### Minimal Example\n\n```toml\nlanguages = [\"python\", \"node\", \"go\", \"java\"]\n\n[crate]\nname = \"my-library\"\nsources = [\"src/lib.rs\", \"src/types.rs\"]\n\n[output]\npython = \"crates/my-library-py/src/\"\nnode = \"crates/my-library-node/src/\"\nffi = \"crates/my-library-ffi/src/\"\n\n[python]\nmodule_name = \"_my_library\"\n\n[node]\npackage_name = \"@myorg/my-library\"\n\n[dto]\npython = \"dataclass\"\nnode = \"interface\"\n```\n\n`languages` is a top-level array, so it must appear **before** the first `[table]` header — otherwise TOML scopes it as `[crate].languages` and parsing fails.\n\n### `[crate]` -- Source Configuration\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `name` | string | *required* | Rust crate name |\n| `sources` | string[] | *required* | Rust source files to extract |\n| `version_from` | string | `\"Cargo.toml\"` | File to read version from (supports workspace Cargo.toml) |\n| `core_import` | string | `{name}` with `-` replaced by `_` | Import path for the core crate in generated bindings |\n| `workspace_root` | string | -- | Workspace root for resolving `pub use` re-exports from sibling crates |\n| `skip_core_import` | bool | `false` | Skip adding `use {core_import};` to generated bindings |\n| `features` | string[] | `[]` | Cargo features treated as always-present (`#[cfg(feature)]` fields are included) |\n| `path_mappings` | map | `{}` | Rewrite extracted Rust path prefixes (e.g., `{ \"spikard\" = \"spikard_http\" }`) |\n\n### `languages` -- Target Languages\n\nTop-level array of languages to generate bindings for:\n\n```toml\nlanguages = [\"python\", \"node\", \"ruby\", \"php\", \"elixir\", \"wasm\", \"ffi\", \"go\", \"java\", \"csharp\", \"r\"]\n```\n\nThe `ffi` language generates the C FFI layer required by `go`, `java`, and `csharp`. If you enable any of those three, `ffi` is implicitly included.\n\n### `[exclude]` / `[include]` -- Filtering\n\n```toml\n[exclude]\ntypes = [\"InternalHelper\"]\nfunctions = [\"deprecated_fn\"]\nmethods = [\"MyType.internal_method\"]   # dot-notation: \"TypeName.method_name\"\n\n[include]\ntypes = [\"PublicApi\", \"Config\"]        # whitelist only these types\nfunctions = [\"extract\", \"parse\"]       # whitelist only these functions\n```\n\n### `[output]` -- Output Directories\n\nPer-language output directories for generated Rust binding code:\n\n```toml\n[output]\npython = \"crates/{name}-py/src/\"\nnode = \"crates/{name}-node/src/\"\nruby = \"crates/{name}-rb/src/\"\nphp = \"crates/{name}-php/src/\"\nelixir = \"crates/{name}-rustler/src/\"\nwasm = \"crates/{name}-wasm/src/\"\nffi = \"crates/{name}-ffi/src/\"\ngo = \"packages/go/\"\njava = \"packages/java/src/main/java/\"\ncsharp = \"packages/csharp/\"\nr = \"crates/{name}-extendr/src/\"\n```\n\nThe `{name}` placeholder is replaced with the crate name.\n\n### Language-Specific Sections\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e[python]\u003c/strong\u003e\u003c/summary\u003e\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `module_name` | string | `_{name}` | Python module name (the native extension name) |\n| `async_runtime` | string | -- | Async runtime spec for `pyo3_async_runtimes` |\n| `stubs.output` | string | -- | Output directory for `.pyi` stub files |\n| `features` | string[] | inherits `[crate] features` | Per-language Cargo feature override |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e[node]\u003c/strong\u003e\u003c/summary\u003e\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `package_name` | string | `{name}` | npm package name |\n| `features` | string[] | inherits `[crate] features` | Per-language Cargo feature override |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e[ruby]\u003c/strong\u003e\u003c/summary\u003e\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `gem_name` | string | `{name}` with `_` | Ruby gem name |\n| `stubs.output` | string | -- | Output directory for `.rbs` type stubs |\n| `features` | string[] | inherits `[crate] features` | Per-language Cargo feature override |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e[php]\u003c/strong\u003e\u003c/summary\u003e\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `extension_name` | string | `{name}` with `_` | PHP extension name |\n| `feature_gate` | string | `\"extension-module\"` | Feature gate wrapping all generated code |\n| `stubs.output` | string | -- | Output directory for PHP facades/stubs |\n| `features` | string[] | inherits `[crate] features` | Per-language Cargo feature override |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e[elixir]\u003c/strong\u003e\u003c/summary\u003e\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `app_name` | string | `{name}` with `_` | Elixir application name |\n| `features` | string[] | inherits `[crate] features` | Per-language Cargo feature override |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e[wasm]\u003c/strong\u003e\u003c/summary\u003e\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `exclude_functions` | string[] | `[]` | Functions to exclude from WASM bindings |\n| `exclude_types` | string[] | `[]` | Types to exclude from WASM bindings |\n| `type_overrides` | map | `{}` | Override types (e.g., `{ \"DOMNode\" = \"JsValue\" }`) |\n| `features` | string[] | inherits `[crate] features` | Per-language Cargo feature override |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e[ffi]\u003c/strong\u003e\u003c/summary\u003e\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `prefix` | string | `{name}` with `_` | C symbol prefix for all exported functions |\n| `error_style` | string | `\"last_error\"` | Error reporting convention |\n| `header_name` | string | `{prefix}.h` | Generated C header filename |\n| `lib_name` | string | `{prefix}_ffi` | Native library name (for Go/Java/C# linking) |\n| `visitor_callbacks` | bool | `false` | Generate visitor/callback FFI support |\n| `features` | string[] | inherits `[crate] features` | Per-language Cargo feature override |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e[go]\u003c/strong\u003e\u003c/summary\u003e\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `module` | string | `github.com/kreuzberg-dev/{name}` | Go module path |\n| `package_name` | string | derived from module path | Go package name |\n| `features` | string[] | inherits `[crate] features` | Per-language Cargo feature override |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e[java]\u003c/strong\u003e\u003c/summary\u003e\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `package` | string | `dev.kreuzberg` | Java package name |\n| `ffi_style` | string | `\"panama\"` | FFI binding style (Panama Foreign Function \u0026 Memory API) |\n| `features` | string[] | inherits `[crate] features` | Per-language Cargo feature override |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e[csharp]\u003c/strong\u003e\u003c/summary\u003e\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `namespace` | string | PascalCase of `{name}` | C# namespace |\n| `target_framework` | string | -- | Target framework version |\n| `features` | string[] | inherits `[crate] features` | Per-language Cargo feature override |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e[r]\u003c/strong\u003e\u003c/summary\u003e\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `package_name` | string | `{name}` | R package name |\n| `features` | string[] | inherits `[crate] features` | Per-language Cargo feature override |\n\n\u003c/details\u003e\n\n### `[dto]` -- Type Generation Styles\n\nControls how Rust structs are represented in each language's public API:\n\n```toml\n[dto]\npython = \"dataclass\"         # dataclass | typed-dict | pydantic | msgspec\npython_output = \"typed-dict\"  # separate style for return types (optional)\nnode = \"interface\"           # interface | zod\nruby = \"struct\"              # struct | dry-struct | data\nphp = \"readonly-class\"       # readonly-class | array\nelixir = \"struct\"            # struct | typed-struct\ngo = \"struct\"                # struct\njava = \"record\"              # record\ncsharp = \"record\"            # record\nr = \"list\"                   # list | r6\n```\n\n### `[scaffold]` -- Package Metadata\n\nMetadata used when generating package manifests:\n\n```toml\n[scaffold]\ndescription = \"My library for doing things\"\nlicense = \"MIT\"\nrepository = \"https://github.com/org/repo\"\nhomepage = \"https://docs.example.com\"\nauthors = [\"Your Name\"]\nkeywords = [\"parsing\", \"extraction\"]\n```\n\n### `[[adapters]]` -- Custom FFI Adapters\n\nDefine custom binding patterns that alef can't extract automatically:\n\n```toml\n[[adapters]]\nname = \"convert\"\npattern = \"sync_function\"\ncore_path = \"my_crate::convert\"\nparams = [\n  { name = \"input\", type = \"String\" },\n  { name = \"options\", type = \"Options\", optional = true },\n]\nreturns = \"Result\"\nerror_type = \"ConvertError\"\ngil_release = true    # Python: release GIL during call\n```\n\nSupported patterns: `sync_function`, `async_method`, `callback_bridge`, `streaming`, `server_lifecycle`.\n\n### `[generate]` / `[generate_overrides.\u003clang\u003e]` -- Generation Control\n\nToggle individual generation passes (all default to `true`):\n\n```toml\n[generate]\nbindings = true          # struct wrappers, From impls, module init\nerrors = true            # error type hierarchies from thiserror enums\nconfigs = true           # config builder constructors from Default types\nasync_wrappers = true    # async/sync function pairs with runtime management\ntype_conversions = true  # recursive type marshaling helpers\npackage_metadata = true  # package manifests (pyproject.toml, package.json, etc.)\npublic_api = true        # idiomatic public API wrappers\n\n# Override per language:\n[generate_overrides.wasm]\nasync_wrappers = false\n```\n\n### `[sync]` -- Version Synchronization\n\nConfigure the `alef sync-versions` command (use `--set \u003cversion\u003e` to override the version read from `Cargo.toml`):\n\n```toml\n[sync]\nextra_paths = [\"packages/go/go.mod\"]\n\n[[sync.text_replacements]]\npath = \"crates/*/cbindgen.toml\"\nsearch = 'header = \".*\"'\nreplace = 'header = \"/* v{version} */\"'\n```\n\n### `[test.\u003clang\u003e]` / `[lint.\u003clang\u003e]` / `[update.\u003clang\u003e]` / `[setup.\u003clang\u003e]` / `[clean.\u003clang\u003e]` / `[build_commands.\u003clang\u003e]`\n\nOverride per-language commands for any operational task. All fields accept a string or an array of strings.\n\nEvery command config section supports two hook fields:\n\n- **`precondition`** -- A shell command that must exit 0 for the main command to run. If it fails, the language is skipped with a warning (not an error). Useful for languages that need a shared library or tool to be present.\n- **`before`** -- Command(s) to run before the main command. Unlike `precondition`, failure aborts the command for that language. Accepts a single string or an array. Use this to build prerequisites (e.g., FFI libraries, maturin develop).\n\n```toml\n# Go lint needs the FFI shared library built first\n[lint.go]\nprecondition = \"test -f target/release/libmy_lib_ffi.dylib\"\nformat = \"gofmt -w packages/go/\"\ncheck = \"cd packages/go \u0026\u0026 golangci-lint run ./...\"\n\n# Python test needs maturin develop first\n[test.python]\nbefore = \"cd packages/python \u0026\u0026 maturin develop --release\"\ncommand = \"cd packages/python \u0026\u0026 uv run pytest tests/ -v\"\ncoverage = \"cd packages/python \u0026\u0026 uv run pytest --cov=. --cov-report=lcov\"\n\n# Node test needs the NAPI binding built first\n[test.node]\nbefore = \"napi build --platform --manifest-path crates/my-lib-node/Cargo.toml\"\ncommand = \"npx vitest run\"\n\n[lint.python]\nformat = \"ruff format packages/python/\"\ncheck = \"ruff check packages/python/\"\ntypecheck = \"mypy packages/python/\"\n\n[update.node]\nupdate = \"pnpm up\"\nupgrade = \"pnpm up --latest\"\n\n[setup.python]\ninstall = \"uv sync\"\n\n[clean.rust]\nclean = \"cargo clean\"\n\n[build_commands.python]\nbuild = \"maturin develop\"\nbuild_release = \"maturin build --release\"\n```\n\nRust is a first-class language in all pipelines -- add `\"rust\"` to your `languages` array to include Rust in `alef build`, `alef test`, `alef lint`, etc. alongside your binding languages.\n\n### `[e2e]` -- E2E Test Generation\n\nConfigure fixture-driven test generation:\n\n```toml\n[e2e]\nfixtures = \"fixtures\"\noutput = \"e2e\"\nlanguages = [\"python\", \"node\", \"rust\", \"go\"]\n\n[e2e.call]\nfunction = \"extract\"\nmodule = \"my_library\"\nasync = true\nargs = [\n  { name = \"path\", field = \"input.path\", type = \"string\" },\n]\n```\n\n### `[opaque_types]` -- External Type Declarations\n\nDeclare types from external crates that alef can't extract:\n\n```toml\n[opaque_types]\nTree = \"tree_sitter_language_pack::Tree\"\n```\n\nThese get opaque wrapper structs in all backends with handle-based FFI access.\n\n### `[custom_modules]` / `[custom_registrations]` -- Hand-Written Code\n\nDeclare hand-written modules that alef should include in `mod` declarations and module init:\n\n```toml\n[custom_modules]\npython = [\"custom_handler\"]\n\n[custom_registrations.python]\nclasses = [\"CustomHandler\"]\nfunctions = [\"custom_extract\"]\ninit_calls = [\"register_custom_types(m)?;\"]\n```\n\n## Architecture\n\n```text\nRust Source Files\n       |\n  [alef extract]\n       |\n  Intermediate Representation (IR)\n  ApiSurface { types, functions, enums, errors }\n       |\n  [alef generate]\n       |\n  +----+----+----+----+----+----+----+----+----+----+----+\n  |    |    |    |    |    |    |    |    |    |    |    |\n PyO3 NAPI WASM FFI  Magnus PHP Rustler extendr Go Java C#\n  |    |    |    |\n  |    |    |    +-- cbindgen --\u003e C header\n  |    |    +-- wasm-pack --\u003e npm\n  |    +-- napi build --\u003e npm + .d.ts\n  +-- maturin --\u003e PyPI wheel + .pyi\n```\n\n### Crate Structure\n\n| Crate | Role |\n|-------|------|\n| [`alef-core`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-core) | IR types, config schema, `Backend` trait |\n| [`alef-extract`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-extract) | Rust source to IR extraction via `syn` |\n| [`alef-codegen`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-codegen) | Shared code generation (type mappers, converters, builders) |\n| [`alef-adapters`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-adapters) | Adapter pattern code generators |\n| [`alef-cli`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-cli) | CLI binary with all commands |\n| [`alef-docs`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-docs) | API reference documentation generator |\n| [`alef-e2e`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-e2e) | Fixture-driven e2e test generator |\n| [`alef-readme`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-readme) | Per-language README generator |\n| [`alef-scaffold`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-scaffold) | Package manifest generator |\n| [`alef-backend-pyo3`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-backend-pyo3) | Python backend |\n| [`alef-backend-napi`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-backend-napi) | TypeScript/Node.js backend |\n| [`alef-backend-wasm`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-backend-wasm) | WebAssembly backend |\n| [`alef-backend-ffi`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-backend-ffi) | C FFI backend (used by Go, Java, C#) |\n| [`alef-backend-magnus`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-backend-magnus) | Ruby backend |\n| [`alef-backend-php`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-backend-php) | PHP backend |\n| [`alef-backend-rustler`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-backend-rustler) | Elixir backend |\n| [`alef-backend-extendr`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-backend-extendr) | R backend |\n| [`alef-backend-go`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-backend-go) | Go backend |\n| [`alef-backend-java`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-backend-java) | Java backend |\n| [`alef-backend-csharp`](https://github.com/kreuzberg-dev/alef/tree/main/crates/alef-backend-csharp) | C# backend |\n\n## Pre-commit Hooks\n\nAlef ships pre-commit hooks that consumer projects can use to keep generated output up to date.\n\n### Verify mode (CI-friendly, check-only)\n\nFails if any generated file is stale (including per-language READMEs) -- does not modify files:\n\n```yaml\n# .pre-commit-config.yaml\nrepos:\n  - repo: https://github.com/kreuzberg-dev/alef\n    rev: v0.7.9\n    hooks:\n      - id: alef-verify\n```\n\n### Generate mode (auto-regenerate)\n\nRegenerates all output (bindings, stubs, docs, readme, scaffold) when source files change:\n\n```yaml\n# .pre-commit-config.yaml\nrepos:\n  - repo: https://github.com/kreuzberg-dev/alef\n    rev: v0.7.9\n    hooks:\n      - id: alef-generate\n```\n\n### README-only refresh\n\nRegenerate per-language README files without re-running the full pipeline. Useful when only the README templates or snippets have changed:\n\n```yaml\nrepos:\n  - repo: https://github.com/kreuzberg-dev/alef\n    rev: v0.7.9\n    hooks:\n      - id: alef-readme\n```\n\nAll hooks trigger on `.rs` and `.toml` file changes (`alef-readme` additionally watches the `[readme].template_dir` and `snippets_dir`). They require `alef` to be installed and available on `PATH`. `alef verify` checks bindings, stubs, scaffold, docs, **and** READMEs against on-disk files — staleness in any of them fails the hook.\n\n## Contributing\n\nContributions welcome! Please open an issue or PR on [GitHub](https://github.com/kreuzberg-dev/alef).\n\n## License\n\n[MIT](LICENSE) -- Copyright (c) 2025-2026 Kreuzberg, Inc.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkreuzberg-dev%2Falef","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkreuzberg-dev%2Falef","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkreuzberg-dev%2Falef/lists"}