Skip to content

Authoring Native Packages

Start with the official native package template for a standalone C or C++ backed package. It includes the manifest, public Kelvra API, ABI header, CMake build, consumer test, changelog, and release workflows.

A native package typically includes:

  • kelvra.toml
  • package.api.kel
  • NativePackageAPI.hpp
  • src/package.cpp
  • CMakeLists.txt
  • tests/main.kel

kelvra.toml is the canonical package manifest name. Older package.toml files are still accepted as a compatibility path, but new packages should use kelvra.toml.

Useful examples:

Reference packages in this repo use metadata like:

kind = "native"
import_name = "math"
namespace = "examples"
name = "math"
version = "0.1.0"
abi_version = 3
description = "Reference namespaced math package."
dependencies = []

The import_name is the name users write in @import("...").

package.api.kel is where you declare the public surface:

package counter
@doc("GC-managed opaque counter handle.")
@native_handle("CounterHandle")
opaque type Counter
@doc("Create a new counter handle.")
fn create(initial i64) Counter

The repo uses this file for:

  • editor-facing signatures
  • public docs strings through @doc(...)
  • opaque package types via opaque type
  • native handle metadata via @native_handle(...)

The compiled shared library registers its exports through NativePackageAPI.hpp. Keep the public header byte-for-byte aligned with the runtime’s canonical header, set the manifest’s abi_version, and declare every supported target under [native].

Host API v2 lets native code retain Kelvra values, release them, inspect retained values, and invoke Kelvra callbacks across garbage collections. The runtime rejects persistent values used from another VM or thread, so packages must keep retained values scoped to their owning runtime and thread. Native ABI 3 packages that do not need Host API v2 remain compatible.

Official runtime-maintained packages use the reserved kelvra:* canonical package space internally. User and example packages should not claim that space outside the sanctioned repo roots.

  1. Create a repository from the official native package template.
  2. Replace its sample module identity, manifest metadata, and import_name.
  3. Declare the public API in package.api.kel.
  4. Implement and register the package in src/package.cpp.
  5. Update the supported native targets and any system dependencies.
  6. Run the template’s consumer test and kelvra validate-package ..
  7. Add a changelog entry, keep the manifest version and vX.Y.Z Git tag in sync, then let the package release workflow publish checksummed artifacts.

To publish prebuilt artifacts through a configured Kelvra registry, use kelvra publish separately for each target with --native-artifact-dir and a registry signing key. GitHub Release archives are not automatically consumed as registry packages.