fluentcidocs
Website GitHub

Build pipelines

Module dependencies

Install reusable modules, own their metadata, and call dependencies through Extism or typed component interfaces.

Give each module its own manifest

Put fluentci-module.toml at the root of a module, alongside its SDK sources. New module starters create this file automatically.

name = "deploy"
version = "0.1.0"
license = "MIT"
description = "Build and deploy the application"
sdk = "typescript"
runtime = "component"
repository = "https://github.com/example/pipelines"
readme_url = "https://raw.githubusercontent.com/example/pipelines/main/README.md"
logo = "https://example.com/deploy.png"
topics = ["deployment", "build"]
os = ["linux", "macos"]
arch = ["aarch64", "x86_64"]

[dependencies]
math = { path = "../math" }

The manifest owns publishing metadata and build settings: name, version, license, description, repository, readme_url, logo, topics, os, arch, sdk, runtime, entry, artifact, build, and optional function metadata. Description, URLs, and classification fields remain optional. Name, version, and license are required when publishing.

A workspace can continue declaring [[modules]] in fluentci.toml. Its name is a local alias and its path locates the source; the module manifest supplies the module's own metadata and SDK settings. Versions belong to each module, not package.version.

Add and install modules

Run fluentci add from the directory containing fluentci-module.toml:

# Official publisher: the @fluentci.io scope may be omitted.
fluentci add [email protected]

# Another publisher, with an explicit local alias.
fluentci add @tsiry-sandratraina.com/[email protected] --alias compiler-cache

# A local source module or prebuilt Wasm file.
fluentci add math --path ../math
fluentci add math --path ./artifacts/math.wasm

# A direct Wasm URL.
fluentci add math --url https://example.com/math.wasm

# A source module inside a Git monorepo.
fluentci add math --git https://github.com/example/modules --rev main --subdir modules/math

add preserves manifest comments, updates [dependencies], installs the dependency, and updates fluentci.lock. A failed install restores the manifest declaration. The CLI adds /fluentci_modules/ to the module's .gitignore.

For a module cloned from Git, install the dependencies already declared in its manifest:

fluentci install
fluentci install --frozen-lockfile
fluentci update

Registry references accept exact versions or latest; omitting a version requests latest. SemVer ranges are not supported. latest remains pinned until an explicit update. Registry artifacts are verified by SHA-256; Git sources are pinned to a commit; direct URL dependencies are also pinned by checksum.

Commit fluentci-module.toml and fluentci.lock. Do not commit fluentci_modules/ or generated .fluentci/dependencies/ bindings. Local path dependencies remain local source references, so their source changes are rebuilt.

Inspect and run a dependency

An installed alias can be used directly from the module root:

fluentci run math --help
fluentci run math add --help
fluentci run math add --left 20 --right 22
fluentci run --frozen-lockfile math add --left 20 --right 22

These commands use the declared dependency and its lock entry. They do not resolve an unrelated registry package with the same alias. Function arguments and return types come from the compiled module's metadata or WIT interface.

Import a component dependency from code

A component module depends on another component, with an exported WIT interface. SDK components export api; an external component can export a single unambiguous interface. Core Extism Wasm cannot satisfy a native WIT component import.

For example, the Rust math module can define these jobs:

pub struct AddArgs {
    pub left: u32,
    pub right: u32,
}

pub fn add(args: AddArgs) -> u32 {
    args.left + args.right
}

Install it with fluentci add math --path ../math. FluentCI extracts the dependency's actual WIT, generates import bindings before building the parent, and connects the import to the dependency's exported interface. Developers do not copy or maintain that WIT manually.

TypeScript

import { add } from "fluentci:dependency/math";

export function sum(): number {
  return add({ left: 20, right: 22 });
}

The CLI generates TypeScript declarations in fluentci_modules/imports.d.ts; compiler inspection includes these declarations. New TypeScript component starters include the generated declarations in tsconfig.json automatically. Existing projects should add "fluentci_modules/**/*.d.ts" to their include list.

Rust

use crate::fluentci::dependency_math::math;

pub fn sum() -> u32 {
    math::add(math::AddArgs { left: 20, right: 22 })
}

The namespace and record types come from generated wit-bindgen imports.

Python

from wit_world.imports import math

def sum() -> int:
    return math.add(math.AddArgs(left=20, right=22))

componentize-py generates the imported interface and its record classes. For PureScript, Gleam, ReScript, and ClojureScript, a JavaScript FFI bridge can import fluentci:dependency/math through the same component build adapter.

Before execution or publishing, FluentCI type-checks and composes the dependency into the parent component. The resulting Wasm is self-contained: consumers do not need the publisher's source paths or fluentci_modules/ directory. Transitive component dependencies are composed as they are built. Incompatible interfaces and source dependency cycles fail before executing module functions.

The FluentCI host package remains fluentci:[email protected]. A module release's version is separate from the WIT host API version.

Editor autocomplete

After fluentci add or fluentci install, TypeScript editors can complete exported functions from fluentci:dependency/<alias>, show argument and return types, and report incorrect calls. These declarations are derived from the installed component's WIT, including function documentation; no handwritten signature file is required. Run fluentci update to refresh a dependency and regenerate its types.

Rust imports are generated by wit-bindgen during the component build. Use rust-analyzer with build scripts enabled and the wasm32-wasip2 target. Python's import modules are generated by componentize-py during the build; make its generated binding directory available to the editor's Python analysis path. FluentCI does not currently generate native editor declarations for Extism's string-based callModule API, or separate language-server stubs for every SDK.

Call an Extism dependency from code

Extism uses the existing SDK module-call operation with the dependency alias as its module argument. For example, using the PureScript guest SDK:

import Effect (Effect)
import FluentCI.Plugin as P

restore :: Effect (P.Result String)
restore = P.callModule "compiler-cache" "restore" "{}"

Use the callee's actual input contract; restore here is an example function name. For a typed JSON export, pass its JSON input object. For a legacy text export, pass its text input. The module's help lists the supported functions and fields.

The equivalent Rust SDK call is:

let output = fluentci_pdk::dag().call(
    "compiler-cache",
    "restore",
    vec![r#"{}"#],
)?;

The compiled parent carries its dependency artifacts in a portable Wasm custom section. Nested calls resolve aliases in the callee's own dependency scope, so transitive dependencies do not accidentally use a parent's aliases. Calls share the invocation's host execution context. An Extism caller can also invoke a component dependency through the host-call compatibility path; native component imports use the typed composition path described above.

Made with ♥ in Antananarivo, Madagascar.
Search documentation