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

To provide documentation for consumers when they hover over your package name in an import statement, use the package keyword along with a @Docs annotation at the top of your src/main.fm file.

src/main.fm
@Docs("
# My Package
This package provides a collection of useful functions and native plugins.
")
package my_package
import native.core

When a user writes import my_package and hovers over my_package, they will see these custom docs instantly.


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 fmp new --plugin <plugin_name> (or fmp new -p <plugin_name>) to scaffold a new Rust plugin in the ./native directory. (Note: Ensure the plugin name is different from your Flame package name).
  2. Register it: Run fmp add --plugin ./native (or fmp add -p ./native) to register the plugin in flame.toml under [plugins]. The plugin name is automatically read from native/Cargo.toml.
  3. Use it: Import it in your Flame scripts using the 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
fmp 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
fmp 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 using the package manager:

bash
fmp add github.com/username/my_package@v1.0.0
# or declare in flame.toml and run:
fmp install

Flame fetches the package natively, caches the Flame sources and .fmi interface files, and makes your package functionality instantly available. Consumers never need to manually copy Rust source code or manage Cargo files in their applications. During fmp build, Flame’s dependency analysis automatically integrates only the required native plugins into that application’s specialized runtime.