A CLI tool for creating and managing Fusion Framework projects. Supports both interactive and non-interactive (batch) modes.
curl -fsSL https://raw.githubusercontent.com/cipherunits/fusion-tool/main/scripts/install.sh | bashOr install from source:
git clone https://github.com/cipherunits/fusion-tool.git
cd fusion-tool && cargo install --path .curl -fsSL https://raw.githubusercontent.com/cipherunits/fusion-tool/main/scripts/install.sh | bashOr install from source:
git clone https://github.com/cipherunits/fusion-tool.git
cd fusion-tool && cargo install --path .In PowerShell:
irm https://raw.githubusercontent.com/cipherunits/fusion-tool/main/scripts/install.ps1 | iexThis installs fusion.exe into %LOCALAPPDATA%\Programs\fusion and adds that
directory to your user PATH. Open a new terminal window afterwards, then:
fusion --helpTo install somewhere else, set FUSION_INSTALL_DIR (and optionally
FUSION_VERSION) before running the installer:
$env:FUSION_INSTALL_DIR = "C:\tools\fusion"
irm https://raw.githubusercontent.com/cipherunits/fusion-tool/main/scripts/install.ps1 | iexDownload the latest .zip from
GitHub Releases and
extract fusion.exe into a folder of your choice. Running it from another
directory (for example fusion in cmd) only works once that folder is on your
PATH:
[Environment]::SetEnvironmentVariable(
"Path",
[Environment]::GetEnvironmentVariable("Path", "User") + ";C:\tools\fusion",
"User"
)Or install from source:
git clone https://github.com/cipherunits/fusion-tool.git
cd fusion-tool
cargo install --path .fusion initYou will be prompted for:
- Programming language (Python, TypeScript, or ASP.NET Core)
- Project name
- Project description
The project is created in the current directory unless you pass a directory:
fusion init my-appfusion init --lang python --name myproject --description "My awesome project"| Argument | Type | Description | Required |
|---|---|---|---|
[DIRECTORY] |
string | Target directory, created if missing (defaults to the current directory) | No |
--lang |
string | python, typescript, asp-core |
No |
--name |
string | Project name | No |
--description |
string | Project description | No |
Any option you leave out is asked interactively.
fusion init --lang python --name my-app
fusion init --lang typescript --name my-app --description "A TypeScript app"
fusion init ./my-projects/test-app --lang python --name testCommands are declared per environment in the commands block of
fusion.<env>.json, so each project defines its own. Run one by name:
fusion command run # dev, the default environment
fusion command run --stage
fusion command run:stage # same thing, shorter
fusion command run --prod
fusion command run --env test # any environment you createdLeave the name out to see what an environment declares:
fusion command --stageThe command runs in the project root through your shell (sh -c on Linux and
macOS, cmd /C on Windows), with FUSION_ENV set to the chosen environment so
that core/settings loads the matching config. Its exit code becomes the exit
code of fusion, which keeps it usable in scripts and CI.
Without a flag or a :env suffix, the environment comes from FUSION_ENV if it
is set, and falls back to dev.
Fusion modules are publishable library packages (separate repos). Authors
scaffold with fusion module init, push to GitHub, and apps install with
fusion add --github. After install, import the package in your Fusion app
like any other dependency — modules are not route/API plugins.
fusion module initYou will be prompted for:
- Implementation language — Python, TypeScript, C#, or Rust (Rust can target all hosts via PyO3 / N-API / a C# class library)
- Module name (id)
- Description
- Output directory (defaults to
fusion-<id>-mod)
Non-interactive:
fusion module init --lang python --name example --description "My first module"
fusion module init --lang csharp --name security --description "Security helpers"
fusion module init --lang rust --name auth --description "Auth helpers" ./fusion-auth-modRecommended package naming (not required):
| Host | Pattern | Example (--name jwt) |
|---|---|---|
| Python | fusion_<name>_mod |
fusion_jwt_mod → from fusion_jwt_mod import ... |
| npm/TS | fusion-<name>-mod |
fusion-jwt-mod → import { ... } from "fusion-jwt-mod" |
| C# | Fusion<Name>Mod |
FusionJwtMod → using FusionJwtMod; |
Every package gets a fusion.module.toml manifest and a small example export
(e.g. hello() / Module.Hello()). Replace that with your own library code.
From inside a Fusion project:
fusion add --github OWNER/MODULE_NAME
fusion add --github OWNER/MODULE_NAME@v1.0.0
fusion add --github https://github.com/OWNER/MODULE_NAMEThis downloads the repo, validates fusion.module.toml, vendors it under
.fusion/modules/<id>/, runs the declared build/install steps (pip install -e .,
maturin, npm, or dotnet build), and records the module in fusion-framework.toml as
[[modules]]. TypeScript hosts get a package.json file: link; C# (asp-core)
hosts get dotnet add reference to the vendored .csproj.
Then import it:
from fusion_example_mod import hello
print(hello("world"))using FusionExampleMod;
Console.WriteLine(Module.Hello("world"));fusion updateChecks the latest GitHub release and, if it is newer, downloads the build for
your platform and replaces the running fusion binary in place. It works the
same on Linux, macOS and Windows, keeps the current install location, and needs
no reinstall or PATH change. Nothing happens if you are already up to date.
If fusion was installed to a system-wide directory, run the update with the
permissions needed to write there (for example sudo fusion update).
fusion --versionfusion --help
fusion init --help
fusion command --help
fusion module init --help
fusion add --helpRunning fusion init creates (Python shown; TypeScript/C# use matching extensions):
<project-directory>/
├── core/
│ └── settings.py # Settings overlay (UPPERCASE keys)
├── src/
│ └── modules/
│ └── products/
│ └── products.py # Sample FMA route module (+ custom HTTP route)
├── main.py # Entry point (listen lives here only)
├── requirements.txt # fusion-framework pin (Python)
├── pyproject.toml # Project metadata (Python)
├── fusion-framework.toml # Project + tool + installed modules
├── fusion.dev.json # Development environment
├── fusion.prod.json # Production environment
├── fusion.stage.json # Staging environment
└── .gitignore # Language-specific ignore rules
main and core/settings follow the extension of the selected language, so a
TypeScript project gets main.ts and core/settings.ts instead. C# uses main.cs,
*.csproj (net10.0), and [Route] / [HttpGet] attributes.
core/settings.py reads the config block of fusion.<env>.json from the
project root, where <env> comes from the FUSION_ENV environment variable and
defaults to dev:
python main.py # uses fusion.dev.json
FUSION_ENV=prod python main.py # uses fusion.prod.jsonEach environment is one fusion.<env>.json in the project root. Add as many as
you like: a fusion.test.json becomes the test environment, no configuration
needed anywhere else.
{
"env": "stage",
"config": { "port": 8081 },
"commands": {
"run": "docker compose up",
"stop": "docker compose down"
}
}config is yours to shape and is what core/settings / Fusion runtime reads. commands holds
project commands that fusion command runs.
Default scaffold ports: dev 8080, stage 8081, prod 9090. Each env also includes
fingerprint.enabled (framework identity headers) and a swagger block (enabled in dev,
off in prod/stage).
FusionApp registers framework identity headers middleware by default
(framework_headers / frameworkHeaders / Middleware.FrameworkHeaders). Extra middleware
is optional via the generated MIDDLEWARE list.
Generated apps pin fusion-framework 1.2.3 (Python requirements.txt / pyproject.toml,
Node package.json, C# PackageReference on net10.0). The starter route module
demonstrates convention handlers plus a custom HTTP route (http_get / httpGet / [HttpGet]).
New projects also get a swagger block under config (enabled in dev, off in
prod/stage). Edit it to control the docs UI, OpenAPI info, auth, and navbar:
{
"env": "dev",
"config": {
"host": "127.0.0.1",
"port": 8080,
"swagger": {
"enabled": true,
"path": "/swagger",
"title": "Fusion API Docs",
"info": {
"title": "Fusion API",
"version": "1.0.0",
"description": "API documentation generated by fusion-framework"
},
"servers": [{ "url": "/", "description": "Current host" }],
"auth": {
"persistAuthorization": true,
"schemes": {
"BearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" },
"ApiKeyAuth": { "type": "apiKey", "in": "header", "name": "X-API-Key" }
},
"global": [],
"oauth": {
"clientId": "",
"appName": "Fusion API",
"usePkceWithAuthorizationCodeGrant": true
}
},
"navbar": {
"enabled": true,
"showUrlInput": true
},
"ui": {
"deepLinking": true,
"docExpansion": "list",
"filter": true,
"tryItOutEnabled": true
}
}
},
"commands": { "run": "python main.py" }
}auth.schemes/auth.globalbecome OpenAPI security definitionsauth.oauthis passed to Swagger UIinitOAuthnavbar.enabledturns on the Topbar (StandaloneLayout)swagger.uimaps to Swagger UI configuration
- Rust (1.70+)
- Cargo
cargo build --releasecargo run -- initcargo testfusion --version reports the Cargo.toml version, so bump it first and then
push a matching tag. CI refuses to build a tag that disagrees with Cargo.toml:
# bump version = "1.0.4" in Cargo.toml first
git commit -am "release v1.0.4"
git tag v1.0.4
git push origin main && git push origin v1.0.4This is the version of the tool only. The framework version that ends up in a
generated fusion-framework.toml is FUSION_FRAMEWORK_VERSION in
src/setting/config.rs and is bumped separately.
MIT