Formula workbooks for Node services and agent tools.
Use @bilig/headless when a
calculation is easiest to review as cells and formulas, but it has to run in a
Node service, queue worker, serverless route, test, or coding-agent tool.
It gives you a WorkPaper: build sheets, write inputs, recalculate, read the
cell value, and save the workbook as JSON. No browser grid is involved.
Good fits: pricing rules, budget checks, payout models, import validation, and agent tools that need read-after-write proof. Bad fits: manual spreadsheet editing, Office macros, desktop Excel automation, or one-off arithmetic where a workbook would be ceremony.
Project site: https://proompteng.github.io/bilig/
| If you are evaluating... | Start here | What should be true before you star, watch, or adopt |
|---|---|---|
| Basic fit | Why use Bilig? | The problem is workbook-shaped business logic that needs API readback and persistence. |
| Published npm package | 90-second Node quickstart | It edits one input, recalculates, persists JSON, restores, and prints verified: true. |
| Backend service shape | Quote approval WorkPaper API | A realistic route-style workflow returns formula readback and restoredMatchesAfter: true. |
| Agent or MCP tools | MCP spreadsheet tool server | Tool calls can write an input and return computed readback instead of screenshot claims. |
| Agent-owned XLSX files | Agent XLSX recalculation without LibreOffice | A tool can edit XLSX inputs, recalculate, export, reimport, and return verified: true. |
| Public technical review | Show HN maintainer note | One shareable page has the npm check, benchmark caveat, known limits, and feedback ask. |
| Trust and performance | npm provenance and benchmark evidence | npm shows SLSA provenance, and benchmark claims match the checked artifact. |
| Almost a fit | adoption blocker form | Name the formula, import/export, persistence, framework, MCP, package, or benchmark gap. |
| Formula or XLSX bug | formula bug clinic | Share a reduced public case that can become a test, example, corpus fixture, or docs proof. |
| Real workbook blocked | submit a workbook fixture | Use the structured form when a reduced workbook is ready. |
This uses the published npm package. It builds a workbook, changes one input, reads the calculated value, saves JSON, restores the workbook, and prints the same value again.
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.tsExpected output:
{
"before": 24000,
"after": 38400,
"afterRestore": 38400,
"sheets": ["Inputs", "Summary"],
"bytes": 1000,
"verified": true,
"nextStep": "If this proof matches your service or agent workflow, star or bookmark Bilig: https://github.com/proompteng/bilig/stargazers"
}The TypeScript file is maintained in
examples/headless-workpaper/npm-eval.ts.
The exact byte count can change between package versions; verified: true and
matching after/afterRestore values are the check.
For a route-shaped quote approval API today, run the maintained example:
git clone --depth 1 https://github.com/proompteng/bilig.git
cd bilig/examples/serverless-workpaper-api
npm install
npm run smokeFor a generated project from a blank directory, run
npm create @bilig/workpaper@latest pricing-workpaper through the
@bilig/create-workpaper package. The package source lives in
packages/create-workpaper, and the publish gate
is documented in create a Bilig WorkPaper starter.
If that proof matches a service or agent workflow you maintain, the useful next step is concrete feedback: star or bookmark the repo, then open or answer one adoption blocker in Discussions: formula coverage, stale XLSX cached values, persistence shape, MCP/agent writeback, or benchmark coverage.
Most integrations are just this: build a workbook, write an input, read the calculated value, and save the workbook state.
import { WorkPaper, exportWorkPaperDocument, serializeWorkPaperDocument } from '@bilig/headless'
const workbook = WorkPaper.buildFromSheets({
Inputs: [
['Metric', 'Value'],
['Customers', 20],
['Average revenue', 1200],
],
Summary: [
['Metric', 'Value'],
['Revenue', '=Inputs!B2*Inputs!B3'],
],
})
const inputs = workbook.getSheetId('Inputs')
const summary = workbook.getSheetId('Summary')
if (inputs === undefined || summary === undefined) {
throw new Error('Workbook is missing required sheets')
}
workbook.setCellContents({ sheet: inputs, row: 1, col: 1 }, 32)
const revenue = workbook.getCellDisplayValue({ sheet: summary, row: 1, col: 1 })
const saved = serializeWorkPaperDocument(exportWorkPaperDocument(workbook, { includeConfig: true }))
console.log({ revenue, savedBytes: saved.length })Use @bilig/headless when:
- a Node service owns a workbook-shaped calculation;
- an agent needs tools such as
readRangeandsetInputCell, with computed before/after values instead of screenshots; - tests need deterministic spreadsheet state and formula readback;
- a workflow needs to save the edited workbook as JSON and restore it later.
Use something else when you need a visual spreadsheet grid, Office macros, desktop Excel automation, or a one-off arithmetic helper. Do not treat embedded XLSX cached formula values as truth; use the Excel oracle workflow when accuracy matters.
Current checked npm footprint for @bilig/headless@0.18.26:
- Pack dry run:
425 kBtarball,2.54 MBunpacked,426package entries. - Boundary: the main import is the WorkPaper formula/JSON runtime; XLSX
import/export stays behind the
@bilig/headless/xlsxsubpath; MCP is thebilig-workpaper-mcpbinary wrapper. - Cold-start gate: Node imports the main entrypoint, builds a two-sheet
WorkPaper, and reads
24000under1000 mswithout importing the XLSX subpath. - Runtime: Node
>=22.0.0; Node 22 compatibility is covered by the runtime package workflow.
@bilig/headless is published with npm registry signatures and SLSA provenance
attestations. Verify the package version you are about to adopt:
npm view @bilig/headless@latest version dist.attestations dist.signatures --jsonAfter installing, npm can verify the current dependency tree:
npm audit signaturesThe current package trust path is documented in
npm provenance and package trust.
Repository security posture is tracked by
OpenSSF Scorecard
and uploaded to GitHub code scanning on every main update.
Use the shortest path that proves the package against a real job.
- Run the 90-second npm eval in a blank project.
- Run the flagship
serverless WorkPaper API example:
npm run quote-approval-api. - If the workflow starts with an XLSX file, run the
XLSX formula recalculation in Node:
npm start. - If an agent needs workbook tools, start with the MCP server guide, including the copy-paste JSON-RPC transcript for verified write/readback.
- If a real workbook almost works, start with the formula bug clinic. Then submit a reduced public fixture so the blocker can become a test, example, or corpus case instead of private feedback. Form: https://github.com/proompteng/bilig/issues/new?template=workbook_fixture.yml. Discussion: #414.
The rest of the docs are an index, not a prerequisite.
For comparison and integration details, use the plain-language fit guide, screenshot automation boundary, Google Sheets API boundary, workbook automation examples, the formula workbooks proof page, the Node spreadsheet formula engine guide, server-side spreadsheet automation, framework adapters, formula bug clinic, workbook fixture submissions, AI SDK and LangChain tools, CrewAI adapter, the MCP server guide, spreadsheet MCP server comparison, MCP directory status, MCP client setup, Claude Desktop MCPB bundle, npm provenance and package trust, JavaScript library comparison, headless spreadsheet engine for Node services and agents, XLSX formula recalculation in Node.js, agent XLSX formula recalculation without LibreOffice, Excel file as a Node calculation engine, stale XLSX formula cache in Node.js, Microsoft Graph Excel recalculation in Node.js, xlsx-calc alternative for Node workbook recalculation, ExcelJS formula recalculation in Node.js, ExcelJS shared formulas in Node.js, SheetJS/ExcelJS boundary, and headless engine comparison.
Useful deeper examples: invoice totals,
budget variance alerts,
fulfillment capacity plan,
quote approval threshold,
subscription MRR forecast,
agent framework adapters,
MCP tool server shape,
XLSX formula recalculation in Node,
and serverless quote approval. Run
npm run quote-approval-api, npm run agent:framework-adapters,
npm run agent:mcp-tools, npm run agent:mcp-transcript,
npm run agent:mcp-file-transcript, npm run agent:mcp-stdio, or
npm exec --package @bilig/headless -- bilig-workpaper-mcp when that is the
path you are evaluating.
The serverless example also includes npm run next-route-handler,
npm run next-server-action, npm run next-server-action-formdata,
npm run framework-adapters, and npm run persistence-adapters for
framework-specific boundary checks.
The MCP server is also listed in the official registry: https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.proompteng%2Fbilig-workpaper.
The runnable examples are TypeScript files. Some source imports end in .js
because Node ESM resolves compiled package output that way; the files you edit
and run are still .ts.
From examples/headless-workpaper:
npm install
npm start
npm run json-records
npm run csv-shaped
npm run invoice-totals
npm run budget-variance
npm run fulfillment-capacity
npm run quote-approval
npm run subscription-mrr
npm run persistenceThe most useful entry points:
- JSON records input
- CSV shaped input
- invoice totals
- budget variance alerts
- fulfillment capacity plan
- quote approval threshold
- subscription MRR forecast
For agent tools:
npm run agent:verify
npm run agent:tool-call
npm run agent:openai-responses
npm run agent:ai-sdk-generate-text
npm run agent:ai-sdk-stream-text
npm run agent:framework-adapters
npm run agent:mcp-tools
npm run agent:mcp-file-transcript
npm run agent:mcp-stdioThe AI SDK example uses
ai-sdk-generate-text-tool-smoke.ts.
The OpenAI Responses guide is
docs/openai-responses-workpaper-tool-call.md.
The agent framework guide is
docs/vercel-ai-sdk-langchain-spreadsheet-tool.md.
The package also ships the MCP stdio binary:
npm exec --package @bilig/headless -- bilig-workpaper-mcp
npm exec --package @bilig/headless -- bilig-workpaper-mcp --workpaper ./pricing.workpaper.json --writable
docker build --target bilig-workpaper-mcp -t bilig-workpaper-mcp:local .Without --workpaper, the binary starts the built-in demo workbook. With
--workpaper, it loads your persisted WorkPaper JSON and exposes
list_sheets, read_range, read_cell, set_cell_contents,
get_cell_display_value, export_workpaper_document, and validate_formula;
--writable persists set_cell_contents edits back to the same file.
The Docker target is for MCP directory scanners: it seeds a demo WorkPaper JSON
inside the image and starts the file-backed --writable tool surface so
tools/list returns the general WorkPaper tools without cloning this monorepo.
It is published in the official MCP Registry as
io.github.proompteng/bilig-workpaper:
https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.proompteng%2Fbilig-workpaper.
- The 90-second TypeScript check above edits one input, restores the saved JSON document, and verifies the dependent formula result.
- For a production-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, recalculates an approval decision, persists JSON, and verifies restored readback.
- For an XLSX formula recalculation example, run
examples/xlsx-recalculation-node. It imports a generated XLSX pricing workbook, edits input cells, reads the recalculated approval decision, exports XLSX, reimports it, and verifies the formulas survived the round trip. The public decision page is XLSX formula recalculation in Node.js. - For a shorter public decision page, read formula workbooks for Node services and agent tools. It compresses the WorkPaper boundary, MCP file-backed mode, benchmark caveat, and alternative-tool guidance into one shareable evaluator path.
- For HN, Lobsters, Reddit, or newsletter review, use the
Show HN maintainer note.
It keeps the empty npm-project command,
verified: trueoutput, benchmark caveat, known limits, and feedback ask together. - Run
pnpm workpaper:bench:competitive:check. The checked-in artifact shows80/100comparable WorkPaper mean wins and names the worst p95 holdout:structural-insert-columns-smallat4.075x. - The benchmark card is generated from that artifact:
docs/assets/workpaper-benchmark-card.png. - Read the compatibility limits before importing real Excel workbooks.
- Use the production adoption checklist before promoting a WorkPaper-backed workflow beyond evaluation.
- For XLSX accuracy audits, use the Excel oracle harness. It separates import success, timeouts, stale cached formula values, and fresh Microsoft Excel recalculation results.
- The WorkPaper MCP server is listed in the official MCP Registry and on Glama. The directory status page keeps the npm command, static MCP server card, and directory evidence in one place.
- Public feedback threads: workflow questions, service examples, persistence adapters, JavaScript spreadsheet library guide, OpenAI Responses tool calls, and benchmark critique.
If the 90-second check matches a problem you have, star or bookmark the repo:
https://github.com/proompteng/bilig/stargazers.
If you are evaluating @bilig/headless for production and want release
notifications, watch releases:
https://github.com/proompteng/bilig/subscription.
Cached formula values embedded in .xlsx files are cache diagnostics, not an
accuracy verdict. A Bilig correctness bug should only be claimed when the
expected value came from a fresh Excel recalculation oracle.
OUT=.cache/excel-oracle-evaluation
pnpm workpaper:xlsx-oracle -- prepare-oracle /path/to/xlsx-corpus "$OUT"
pnpm workpaper:xlsx-oracle -- evaluate-cache /path/to/xlsx-corpus "$OUT"
pnpm workpaper:xlsx-oracle -- evaluate-oracle /path/to/xlsx-corpus "$OUT/recalculated" "$OUT"
pnpm workpaper:xlsx-oracle -- summarize "$OUT"evaluate-cache writes cache-diagnostic.json and stays non-authoritative.
evaluate-oracle writes excel-oracle-report.json, and summarize writes
summary.md. If Excel automation is unavailable, cells are classified as
missing_excel_oracle instead of being promoted to bugs.
packages/headless: WorkPaper runtime and npm package.packages/excel-import: XLSX import/export boundary. Install both packages withpnpm add @bilig/headless @bilig/excel-importwhen you need file import and export.packages/formula: formula parser, binder, compiler, and evaluator.packages/core: workbook engine, snapshots, mutation flow, and scheduler.packages/gridandapps/web: browser spreadsheet shell.apps/bilig: fullstack monolith runtime, API surface, and static asset server.packages/renderer: React workbook renderer.packages/protocol,packages/binary-protocol,packages/agent-api, andpackages/worker-transport: protocol and integration boundaries.packages/wasm-kernel: AssemblyScript/WASM numeric fast path.packages/benchmarks: benchmark harness and performance contracts.
For XLSX import/export from TypeScript:
import { WorkPaper } from '@bilig/headless'
import { exportXlsx, importXlsx } from '@bilig/excel-import'Use WorkPaper.buildFromSnapshot(imported.snapshot) after import and
workbook.exportSnapshot() before exportXlsx().
Use Node 24+, Bun, and pnpm@10.32.1.
pnpm install
pnpm dev:web
pnpm dev:web-local
pnpm dev:syncFor a full local preflight:
pnpm lint
pnpm typecheck
pnpm test
pnpm test:browser
pnpm run ciGenerated sources and public evidence are checked:
pnpm protocol:check
pnpm formula-inventory:check
pnpm workspace-resolution:check
pnpm workpaper:bench:competitive:check
pnpm docs:discovery:checkStart with the public package boundary unless the task is explicitly engine work.
- Read
packages/headless/README.mdbefore touching WorkPaper behavior. - Use public exports from
@bilig/headless; do not reach intosrc/ordist/when writing consumer examples. - Keep examples TypeScript-first.
- Do not call stale XLSX cached formula values an accuracy oracle.
- Add focused tests before changing formulas, persistence, range bounds, config rebuilds, events, row/column moves, or sheet lifecycle.
- Run the focused package tests first, then broaden to
pnpm run ci.
Read CONTRIBUTING.md before opening a PR. If this is your first patch, start with the new contributor guide and then claim a scoped starter issue.
Good first patches usually fit one of these shapes:
- formula fixtures with clear expected behavior;
- small WorkPaper examples that prove a real service or agent workflow;
- focused correctness fixes with regression tests;
- grid accessibility and keyboard-behavior improvements;
- docs that turn an existing architecture note into a runnable command.
The shortest public on-ramp is the
starter issues queue. It keeps code/test picks,
example tasks, adapters, and focused docs work in one current list, with small
acceptance commands for first patches.
If this is your first contribution to bilig, use the
first-timers-only
filter.
Read SECURITY.md before sharing vulnerability details, private workbook data, tokens, credentials, or exploit reproductions. Security reports should use GitHub private vulnerability reporting when available, or security@proompteng.ai when the private flow is not visible.
Use SUPPORT.md for the fastest public support path. Good reports include the package version, Node version, OS, exact formula or workbook input, expected value, actual value, and the smallest command or script that reproduces the issue.
Forgejo Actions is the primary CI surface via
.forgejo/workflows/forgejo-ci.yml. GitHub Actions mirrors the verification
contract in .github/workflows/ci.yml.
The strict gate includes frozen lockfile install, full pnpm run ci, artifact
budget checks, browser smoke, and tracked-file cleanliness checks.
MIT.
