Skip to content

Creating Flame Packages

Creating a package in Flame allows you to bundle reusable Flame scripts, custom annotations, and even native Rust plugins into a single, distributable unit. When you distribute a Flame package (e.g., via GitHub), consumers can easily pull it into their projects and benefit from full IDE support and seamless native interop.


To declare that your project is a package (rather than an executable application), set the type to "pkg" in your flame.toml file.

[project]
name = "my_package"
version = "0.1.0"
type = "pkg"
# Optional: define a local Rust plugin bundled with this package
[plugins]
native_core = "./native"

When type = "pkg", running flame build will generate a standalone, self-contained package folder inside target/<profile>/pkg/my_package that is ready for distribution.


A complete Flame package typically follows this directory structure:

my_package/
├── flame.toml
├── src/
│ └── main.fm # Main entry point for the package
├── native/ # (Optional) Local Rust plugin directory
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
└── test/ # Test files
└── my_test.fm

For consumers to use your package’s features, you must explicitly export them in your Flame scripts. You can export functions, structs, enums, and even custom annotations.

src/main.fm
import native.core
// Export a custom annotation
export annotation MyAnnotation()
// Export a struct
export struct Config {
pub key: String
}
// Export a function that uses your local native plugin
export fn process_data(config: Config) -> String {
// Calling the native plugin bundled inside your package
core.process(config.key)
}

When a user imports your package, only the exported symbols will be available in their environment.


Flame makes it incredibly easy to bundle native Rust plugins inside your package.

  1. Create the Rust Plugin: Run flame native init <plugin-name> to create a new Rust plugin in the native directory.
  2. Register it: Run flame add --plugin <path_to_plugin_folder(e.g., ./native)> to add it to your package as a plugin, it will add the plugin in flame.toml under [plugins].
  3. Use it: Import it in your Flame scripts using native. prefix and its registered name (e.g., import native.core).

Testing your package ensures its reliability before distribution. Flame includes a built-in testing framework that seamlessly resolves your package’s modules.

Write your tests in the test/ directory. You can easily import your package’s source code by importing main or specific files from the src/ directory.

test/my_test.fm
import main
@Test
fn test_process_data() {
let conf = main.Config { key: "test_key" }
let result = main.process_data(conf)
assertEq(result, "processed_test_key")
}

Run your tests using the Flame CLI:

Terminal window
flame test

Flame’s package resolution system is smart enough to resolve import main inside the test/ folder directly to your src/main.fm file, providing full IDE autocomplete and diagnostics during test development.


When you are ready to distribute your package, simply run:

Terminal window
flame build

Because type = "pkg", Flame acts as a package bundler. It will create a directory at target/pkg/my_package containing:

  • Your flame.toml manifest.
  • Your entire src/ directory.
  • Generated .fmi interface files from your local plugins.

You don’t need a centralized package registry to distribute your package! Just push your repository to GitHub.

Consumers can install your package exactly as it is configured natively:

Terminal window
flame add github.com/username/my_package@v1.0.0

Flame will clone the repository natively, parse the exported annotations and functions, and make your bundled Rust plugins instantly available in their projects.