fusion-ai-host
Local tool execution for the Fusion stack — the hands on the user's machine. Where
fusion-ai is the brain (the model + agent loop), fusion-ai-host
is the set of tools that execute where the user's files and local toolchains live — list a folder,
search a repo, rename a file, convert an IFC — reachable from the loop over an outbound-only
connection, with no inbound port on the machine.
The device half is compiled to a single self-contained binary with bun build --compile; the server
half is source-published (consumers bundle the TypeScript directly).
Install
Published to GitHub Packages under the @tikab-interactive scope, so an .npmrc with a
read:packages token is required:
@tikab-interactive:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}bun add @tikab-interactive/fusion-ai-host zodzod is used for tool input schemas.
The two halves
Two entry points, mirroring fusion-ai and fusion-ai/agent:
@tikab-interactive/fusion-ai-host— the device runtime: the tool contract, the built-in tools, enrollment, and therunHostdispatch loop. Compiled to one binary per OS.@tikab-interactive/fusion-ai-host/server— the VM-side, in-memory dispatcher that routes a call to a connected device and awaits its result. Schema-agnostic: the consuming app owns the device-registry table and its migration.
A headless CLI, on purpose
The connector is, and stays, a headless command line. There is no desktop or GUI app, no Tauri port, and no tray / menu-bar wrapper planned: the runtime is the server-side agent loop, and this binary is only the hand it reaches with — the browser is the interface. (Contrast a no-server desktop agent, where the app is the runtime and a window is unavoidable.)
That holds because of who runs it. The connector is for power users doing in-place work on local files —
surveyors, scan-to-BIM specialists, heavy Revit / AutoCAD users — who are terminal-adjacent and tend to
prefer a scriptable, re-runnable command (fusion-host convert e57 --to las --merge ./scans) to a
window. The heavy domain pipelines those commands drive are the named-shell-out tier, not the
built-in filesystem tools, and a CLI is arguably the better surface for them. A tray wrapper is demoted,
not planned — worth building only if a concrete need for in-place local work from a non-terminal user
actually appears.
The one ergonomic debt worth paying regardless is enrollment: the click-the-link device flow has to be smooth — a clear link, an unmistakable "you're connected" confirmation, and good errors when the internal CA isn't trusted — because it is the single point of friction even a power user meets.
The product-side framing — the audience split and the two data-locality scenarios — lives in the stack docs: a headless CLI, on purpose.
Quick start
The whole device side is one entrypoint — declare a tool set, point it at your server, compile:
import { , } from "@tikab-interactive/fusion-ai-host";
await ({
: .. ?? "https://pulsn.internal",
: , // list_directory, read_file, grep, write_file, …
: [.. ?? "."], // the canonicalized scope
});bun build --compile --target=bun-windows-x64 ./host.ts --outfile fusion-host.exeOn first run the CLI enrols with a pairing code, then dials out and waits for calls. From here:
- Tools — the
defineLocalToolcontract, the built-in catalogue, propose/apply, and the scope model. - The device runtime —
runHost, enrollment, the dispatch loop, and packaging/signing. - The dispatcher — wiring
…/serverinto an app: routes, presence, and the approve flow.