bilig

Headless spreadsheet engine for Node services and agents

@bilig/headless is a TypeScript WorkPaper runtime for backend workflows that still make the most sense as cells and formulas. It gives a Node service or agent tool an API for writing cells, recalculating formulas, reading computed values, and saving the workbook as JSON.

Use it when a workbook is the business-logic shape, but a browser spreadsheet UI is the wrong runtime boundary.

The job it fits

Good fits:

Poor fits:

Try the package first

Start from an empty directory and run the maintained quickstart when you want the shortest package sanity check:

mkdir bilig-headless-eval
cd bilig-headless-eval
npm init -y
npm pkg set type=module
npm install @bilig/headless
npm install -D tsx typescript @types/node
curl -fsSLo quickstart.ts https://proompteng.github.io/bilig/npm-eval.ts
npx tsx quickstart.ts

Expected shape:

{
  "before": 24000,
  "after": 38400,
  "afterRestore": 38400,
  "sheets": ["Inputs", "Summary"],
  "bytes": 1000,
  "verified": true
}

The byte count can move between releases. The important signal is verified: true: an input changed, a dependent formula recalculated, the document serialized to JSON, and the restored workbook produced the same value.

For a route-shaped evaluator path, run the quote approval WorkPaper API proof. It starts from an empty Node directory, downloads one maintained TypeScript route smoke, writes quote inputs into known cells, recalculates net revenue, gross margin, and approval decision, serializes the WorkPaper JSON, restores it, and verifies restoredMatchesAfter: true.

If you arrived from HN or LibHunt

The useful question is not whether Bilig is a smaller Excel clone. It is whether your service needs a workbook-shaped calculation boundary that can be tested without opening a browser spreadsheet.

Use the smallest proof that matches your blocker:

Bilig is indexed on the LibHunt headless-spreadsheet topic, but the repo is the current source of truth for releases, limitations, and API examples. If one proof almost maps but fails on a real formula, import, or workflow boundary, open an implementation gap with the smallest reproducer you can share.

Backend service shape

A service should keep the WorkPaper behind a narrow business boundary:

  1. Load or build the workbook.
  2. Accept typed business inputs.
  3. Write those inputs into known cells.
  4. Read computed values from known output cells.
  5. Persist the exported WorkPaper document.

The canonical service example is the serverless WorkPaper API. It includes a quote approval API, framework adapters, and persistence adapters for common Node deployment shapes.

Use the Node service WorkPaper recipe when you want the smallest local service boundary before adopting a framework.

Agent tool shape

An agent should not infer workbook state from screenshots when it needs a durable result. Expose explicit tools instead:

That makes writeback testable: the tool call writes a cell, the runtime recalculates, and the agent reads the exact output cell before claiming success.

Start with the agent tool-calling recipe or the MCP spreadsheet tool server.

Decision boundary

Use @bilig/headless when the runtime requirement is formula-backed workbook state inside TypeScript. Use other tools when the primary requirement is different:

Requirement Start with
Formula-backed business logic inside a Node service @bilig/headless WorkPaper
Agent writeback with verified readback WorkPaper tools or the MCP server
XLSX file import, export, styling, and reports SheetJS, ExcelJS, or the @bilig/headless/xlsx subpath
Broad formula coverage in an established headless engine HyperFormula comparison first
Shared Google Workspace document with permissions and comments Google Sheets API

Read the headless spreadsheet engine comparison when the boundary is not obvious.

Repository and release notes: https://github.com/proompteng/bilig.

If it almost matches but a gap blocks adoption, open an implementation gap discussion: https://github.com/proompteng/bilig/discussions/new?category=general.