Skip to content

Package Surfaces

SurfacePackageRuntime
JavaScript / WASM@libraz/formulonBrowser, worker, Node
Native Node@libraz/formulon-nativeNode.js N-API addon; prebuilt binaries ship for darwin-arm64/linux-x64/linux-arm64 (or build from a source checkout)
Pythonformulonpy3 wheel using wasmtime
CLIformulon-cli-<os>-<arch>Standalone binary
C ABIheaders and native libraryCustom hosts
MCP@libraz/formulon-mcpstdio MCP server for agents
Reference UI@libraz/formulon-cellBrowser integration-test UI

All surfaces should expose the same calculation core. Differences should be packaging differences, not semantic differences.

formulon-cell and formulon-mcp are built specifically on the WASM package, not directly on the C ABI — they reach the calculation core the same way any browser or Node consumer of @libraz/formulon does.

Glossary: surface

A packaging boundary on top of the shared C++17 engine. Every surface speaks to the engine through the C ABI (directly or transitively). What changes between surfaces is host language, memory ownership, and IO style — never formula semantics.

Surface maturity

SurfaceMaturityNotes
WASMbroadest JS APIFull generated formulon.d.ts, browser and Node support
Pythonbroad workbook API, but trailing WASM/Node on the newest additionswasmtime-backed wrapper, context-manager workbook lifecycle
CLIfocused toolseval, recalc, dump
Native NodeWASM-shaped APISame Workbook surface as WASM, through a native N-API addon
C ABIbinding contractStable low-level contract for packaged surfaces
MCPagent-facing surfaceBuilt on top of WASM; allowlisted method dispatch
formulon-cellreference UIPublic integration-test and example surface, not a complete Excel-compatible UI

Python still trails on the scalar ad-hoc evaluators

evaluateFormulaText / evaluateConditionalFormula (read-only scalar ad-hoc evaluation) and sheet-wide comment enumeration exist on the C API, Native Node addon, and WASM only. Python's Workbook has no equivalent scalar evaluation method, and only exposes singular get_comment / set_comment — there is no comment-enumeration call like Native Node's getComments(sheet) or the C API's fm_sheet_get_comment_count / fm_sheet_get_comment_at_index. As of 0.9.5 Python does expose the whole-array evaluator evaluate_formula_array (returning the full spilled result rather than the top-left element) and the pure merge_function_metadata helper, so the remaining gap is the scalar evaluators and comment enumeration. (Conditional-format rule creation does return the new rule index on Python, matching the other surfaces — that 0.9.4 addition is not Python-limited.)

When surfaces disagree

If two surfaces produce different values for the same workbook and the same profile, treat it as a bug or a documented compatibility gap. The parity runner under make parity-test exercises shared fixtures across available channels and reports both missing and mismatched results. Native Node and WASM are expected to have the same result envelopes and Workbook method shape; their differences are operational, such as native threads, copy costs, and the WASM memory ceiling.