@bilig/headless
v0.107.8
Published
Formula WorkPaper runtime for Node.js services and agent tools with JSON persistence and formula readback.
Maintainers
Readme
@bilig/headless
@bilig/headless is the full WorkPaper runtime for Node.js services and agent
tools.
If this npm page is the first thing you found, start with the path that matches the search or production bug you actually have:
| Problem or search intent | Start here | Proof before adoption |
| ------------------------------------------------------------- | ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| SheetJS formula result not updating or stale xlsx results | npm install @bilig/sheetjs-formula-recalc | npx --package @bilig/sheetjs-formula-recalc sheetjs-recalc --demo --json returns fresh readback. |
| xlsx-populate writes formulas but Node reads old values | npm install @bilig/xlsx-formula-recalc | npx --package @bilig/xlsx-formula-recalc xlsx-recalc --demo --json updates the cached value. |
| ExcelJS formula cells need recalculated values | npm install exceljs @bilig/exceljs-formula-recalc | npx --package @bilig/exceljs-formula-recalc exceljs-recalc --demo --json mutates the workbook boundary. |
| An AI agent needs spreadsheet tools instead of UI automation | npm create @bilig/workpaper@latest pricing-agent -- --agent | AI spreadsheet agent tool shows the write/recalc/read/persist loop. |
| Formula workbook state belongs in a service or agent tool | npm install @bilig/workpaper | npm exec --package @bilig/[email protected] -- bilig-agent-challenge prints verified: true. |
| You need the lower-level runtime package and subpaths | npm install @bilig/headless | The examples below prove WorkPaper JSON, XLSX import/export, provenance, and package footprint. |
Use @bilig/headless when the spreadsheet is the business logic, but
production needs API readback, tests, persistence, and agent-readable proof
instead of a person opening a spreadsheet app.
Your code owns a WorkPaper: build sheets, write inputs, recalculate formulas,
read the cell value, and save the workbook as JSON. Product code gets
reviewable workbook-shaped logic without shipping a spreadsheet UI. Coding
agents get narrow tools such as readRange and setInputCell instead of
guessing state from screenshots.
The npm tarball also includes AGENTS.md and SKILL.md so coding agents
inspecting node_modules/@bilig/headless can find the write/read/persist loop
locally. The public docs expose the same path through
AGENTS.md,
agent.json,
skill.txt,
AI spreadsheet agent tool, and
llms-full.txt.
This package is not a browser grid, desktop Excel automation, or a source of
truth for stale XLSX cached formula values. XLSX import/export is available from
the @bilig/headless/xlsx subpath for services that need workbook ingestion
around the same WorkPaper model.
The bilig-workpaper-mcp binary still ships for hosts that specifically need an
MCP stdio boundary. It is not the default evaluation path; prove the direct npm
or TypeScript path first unless your tool host requires MCP.
The bilig-formula-clinic binary turns a reduced XLSX into a paste-ready
fixture report without uploading workbook contents.
Choose An Evaluation Path
| 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. |
| XLSX import/export | XLSX formula recalculation example | It imports XLSX, edits inputs, recalculates, exports XLSX, reimports, and verifies formulas. |
| Agent or MCP tools | Headless WorkPaper agent handbook and MCP spreadsheet tool server | The agent can pick MCP, direct TypeScript, or route tools and prove write/readback/persist. |
| 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. |
Reduced workbook already in hand?
npm exec --package @bilig/[email protected] -- bilig-formula-clinic ./reduced.xlsx --cells "Summary!B7,Inputs!B2"Handing a spreadsheet task to another coding agent?
npm exec --package @bilig/[email protected] -- bilig-agent-challenge
npm exec --package @bilig/[email protected] -- bilig-mcp-challengeThe first command proves the direct WorkPaper API. The second command proves
the file-backed MCP path by initializing JSON-RPC, listing
tools/resources/prompts, editing Inputs!B3, reading recalculated Summary!B3,
exporting WorkPaper JSON, restarting from disk, and returning verified: true.
Both run without cloning the repository or downloading a TypeScript file.
Install
Requires Node 22+ and ESM imports.
npm install @bilig/headlessFor a route-shaped quote approval API today:
git clone --depth 1 https://github.com/proompteng/bilig.git
cd bilig
pnpm --dir examples/serverless-workpaper-api install --ignore-workspace
pnpm --dir examples/serverless-workpaper-api run smokeFor a generated starter project:
npm create @bilig/workpaper@latest pricing-workpaper
npm create @bilig/workpaper@latest pricing-agent -- --agentThat command is published through @bilig/create-workpaper. The publish gate is documented at
https://proompteng.github.io/bilig/create-bilig-workpaper.html.
The --agent starter adds AGENTS.md, CLAUDE.md, Cursor and VS Code MCP
configs, mcp/bilig-workpaper.mcp.json, npm run agent:verify, and
npm run mcp:server.
Current checked npm footprint for @bilig/[email protected]:
- Pack dry run:
797 kBtarball,4.89 MBunpacked,777package 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; reduced workbook reports use thebilig-formula-clinicbinary. - 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.
Published Package Trust
@bilig/headless is published with npm registry signatures and SLSA provenance
attestations. Check the package version you are about to adopt in a service:
npm view @bilig/headless@latest version dist.attestations dist.signatures --json
npm audit signaturesThe release workflow uses GitHub Actions OIDC and publishes runtime packages
with npm publish --provenance. The public verification path is documented in
the
npm provenance and package trust guide.
Repository security posture is tracked by
OpenSSF Scorecard
and uploaded to GitHub code scanning on every main update.
For a clean copy-paste run, use the Node quickstart. For the shortest explanation of when the package is worth using, start with Why use Bilig?. If you are choosing between formula engines, read the TypeScript guide for evaluating Excel formulas in Node.js and the Google Sheets API boundary.
TypeScript API Shape
Most integrations are this loop: create a workbook, write an input, read the calculated cell, 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 })Addresses are zero-based { sheet, row, col } objects. A formula is a string
that begins with =. Sheet ids are numeric and should be resolved with
workbook.getSheetId(name).
Clean npm Sanity Check
Run this before cloning the repository. It checks the published npm package by building a workbook, changing an input, saving the document, restoring it, and checking that the dependent formula still reads back correctly.
npm exec --package @bilig/[email protected] -- bilig-agent-challenge
npm exec --package @bilig/[email protected] -- bilig-mcp-challengeExpected output:
{
"editedCell": "Inputs!B2",
"dependentCell": "Summary!B2",
"before": 24000,
"after": 38400,
"afterRestore": 38400,
"persistedDocumentBytes": 999,
"sheets": ["Inputs", "Summary"],
"checks": {
"formulaReadbackChanged": true,
"exportedWorkPaperDocument": true,
"restoredMatchesAfter": true
},
"verified": true,
"limitations": [
"This challenge proves the WorkPaper write/read/persist loop, not full Excel desktop compatibility.",
"For XLSX-specific behavior, run bilig-formula-clinic or the XLSX recalculation example with a real workbook fixture."
],
"star": "https://github.com/proompteng/bilig/stargazers",
"watchReleases": "https://github.com/proompteng/bilig/subscription",
"adoptionBlocker": "https://github.com/proompteng/bilig/discussions/new?category=general",
"nextStep": "If this proof matches your workflow, open a concrete blocker or adoption note: https://github.com/proompteng/bilig/discussions/new?category=general"
}For teams that want to inspect the TypeScript source before running it, the
older curl-based quickstart remains at
https://proompteng.github.io/bilig/try-bilig-headless-in-node.html and uses
the maintained file at https://proompteng.github.io/bilig/npm-eval.ts
(examples/headless-workpaper/npm-eval.ts). The
exact byte count can change between package versions; verified: true,
checks.restoredMatchesAfter, and matching after/afterRestore values are
the check.
Inside this monorepo:
pnpm install
pnpm --filter @bilig/headless buildWhen To Use It
Reach for @bilig/headless when:
- a service owns a workbook-shaped calculation and needs formula readback;
- an agent tool must prove the value after an edit;
- a queue worker or route needs deterministic spreadsheet state without a UI;
- tests need the same formula model that production code uses;
- a workbook document needs to round-trip as JSON after code changes it.
Use something else when you need:
- manual spreadsheet editing;
- a browser grid by itself;
- Office macros, COM automation, or desktop Excel integration;
- one-off arithmetic where a workbook model adds no value.
Quickstart
The shortest local path is still TypeScript. Put the API shape above in a
sanity.ts file, run it with tsx, and expect the dependent formula to change
after the setCellContents() call. For a maintained file that already includes
restore verification, use the clean npm sanity check.
WorkPaper Read/Write Cheat Sheet
The public surface is intentionally small:
- Create workbooks with
WorkPaper.buildEmpty(),WorkPaper.buildFromArray(),WorkPaper.buildFromSheets(), orWorkPaper.buildFromSnapshot(). - Edit values, formulas, and blanks with
workbook.setCellContents(address, value). - Apply large sparse literal patches with
workbook.setCellValues(updates)orworkbook.setSheetCellValues(sheetId, updates). - Read computed values with
workbook.getCellValue(address). - Read display text with
workbook.getCellDisplayValue(address). - Read formula text with
workbook.getCellFormula(address). - Read persisted cell input with
workbook.getCellSerialized(address). - Read ranges with
getRangeValues(),getRangeFormulas(), andgetRangeSerialized(). - Persist with
exportWorkPaperDocument()andserializeWorkPaperDocument(). - Restore with
parseWorkPaperDocument()andcreateWorkPaperFromDocument().
import {
WorkPaper,
createWorkPaperFromDocument,
exportWorkPaperDocument,
parseWorkPaperDocument,
serializeWorkPaperDocument,
type WorkPaperCellAddress,
} from '@bilig/headless'
const workbook = WorkPaper.buildFromSheets(
{
Sheet1: [
[10, 20, '=A1+B1'],
[7, '=A2*3', null],
],
},
{ maxRows: 1_000, maxColumns: 100, useColumnIndex: true },
)
const sheet = workbook.getSheetId('Sheet1')
if (sheet === undefined) {
throw new Error('Sheet1 was not created')
}
const at = (row: number, col: number): WorkPaperCellAddress => ({ sheet, row, col })
workbook.setCellContents(at(1, 2), '=A2+B2')
const saved = serializeWorkPaperDocument(exportWorkPaperDocument(workbook, { includeConfig: true }))
const restored = createWorkPaperFromDocument(parseWorkPaperDocument(saved))
console.log({
formula: workbook.getCellFormula(at(1, 2)),
display: workbook.getCellDisplayValue(at(1, 2)),
sheets: restored.getSheetNames(),
})For formula errors, pair getCellDisplayValue() with
getCellFormulaDiagnostics(). That lets a service return useful #VALUE! or
#NAME? diagnostics instead of silently accepting unsupported inputs.
Runnable Examples
The example catalog lives in
examples/headless-workpaper.
The examples are TypeScript files. Some imports end in .js because Node ESM
resolves compiled package output that way; the files you edit and run are still
.ts.
Start with the data shape closest to your app:
npm run json-records: JSON records inputnpm run csv-shaped: CSV shaped inputnpm run invoice-totals: invoice totalsnpm run budget-variance: budget variance alertsnpm run fulfillment-capacity: fulfillment capacity plannpm run quote-approval: quote approval thresholdnpm run subscription-mrr: subscription MRR forecastnpm run persistence: persistence round tripnpm run range-readback: range readbacknpm run sheet-inspection: sheet inspection
Agent and tool-call examples:
npm run agent:verifyproves an agent writeback by checking the dependent formula, saved JSON, restored workbook, and formula text.npm run agent:tool-callexposesreadRangeandsetInputCellstyle tool calls with computed before/after readback.npm run agent:openai-agents-sdkcreates real@openai/agentsAgentandtool()objects, then invokes them locally with WorkPaper readback: https://github.com/proompteng/bilig/blob/main/docs/openai-agents-sdk-workpaper-tool.md.npm run agent:openai-responsesshows the OpenAI Responses tool-call loop.npm run agent:ai-sdk-generate-textuses the real Vercel AI SDKgenerateText()andtool()APIs; the runnable file isai-sdk-generate-text-tool-smoke.ts.npm run agent:ai-sdk-stream-textcovers the matching streamed tool-call path inai-sdk-stream-text-tool-smoke.ts.npm run agent:framework-adaptersmaps the same validated WorkPaper operations into AI SDK, LangChain, Mastra, LlamaIndex.TS, LangGraph.js, CopilotKit, and Cloudflare Agents: https://github.com/proompteng/bilig/tree/main/examples/headless-workpaper#agent-framework-adapters.
MCP examples:
npm run agent:mcp-toolsreturns dependency-freetools/listandtools/callJSON-RPC shapes: https://github.com/proompteng/bilig/tree/main/examples/headless-workpaper#mcp-tool-server-shape.NODE_NO_WARNINGS=1 npm run --silent agent:mcp-transcriptstarts the stdio server, sendsinitialize,tools/list, and a verifiedset_workpaper_input_cellcall, then asserts formula readback and JSON persistence: https://github.com/proompteng/bilig/blob/main/docs/mcp-workpaper-tool-server.md#copy-paste-json-rpc-transcript.NODE_NO_WARNINGS=1 npm run --silent agent:mcp-file-transcriptruns the packagedbilig-workpaper-mcp --workpaperfile-backed mode, persists an input edit to WorkPaper JSON, verifies a recalculated cell, and exposes the file-backed resources and prompts: https://github.com/proompteng/bilig/blob/main/docs/mcp-workpaper-tool-server.md#copy-paste-json-rpc-transcript.npm run agent:mcp-stdioruns the same handlers over newline-delimited stdio.- The package ships npm-executable binaries:
npm exec --package @bilig/[email protected] -- bilig-formula-clinic ./reduced.xlsx --cells "Summary!B7,Inputs!B2"
npm exec --package @bilig/[email protected] -- bilig-workpaper-mcp
npm exec --package @bilig/[email protected] -- bilig-workpaper-mcp --workpaper ./pricing.workpaper.json --init-demo-workpaper --writable
docker build --target bilig-workpaper-mcp -t bilig-workpaper-mcp:local .bilig-formula-clinic imports a reduced XLSX locally, samples formulas, reads
requested cells through WorkPaper, and prints a Markdown fixture report.
Default mode starts the built-in demo workbook. File-backed mode loads a
persisted WorkPaper JSON document and exposes list_sheets, read_range,
read_cell, set_cell_contents, get_cell_display_value,
export_workpaper_document, and validate_formula; --init-demo-workpaper
creates the demo JSON file when it is missing, and --writable persists
set_cell_contents edits back to the same file. File-backed mode also exposes
resources/list, resources/read, prompts/list, and prompts/get for
bilig://workpaper/manifest, bilig://workpaper/agent-handoff,
bilig://workpaper/sheets, bilig://workpaper/current-document,
edit_and_verify_workpaper, and debug_workpaper_formula.
The Docker target exists for MCP directory introspection. It installs the
published npm package, seeds a demo WorkPaper JSON file inside the image, and
starts bilig-workpaper-mcp --workpaper /workpaper/pricing.workpaper.json
--init-demo-workpaper --writable so scanners see the general file-backed
WorkPaper tools without building the Bilig web app.
The package metadata includes
mcpName: io.github.proompteng/bilig-workpaper, and the server is listed in the
official MCP Registry:
https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.proompteng%2Fbilig-workpaper.
It is also live on Glama with Try in Browser, A-grade tool pages, and all
seven file-backed WorkPaper tools:
https://glama.ai/mcp/servers/proompteng/bilig.
Clients that support Streamable HTTP MCP can also use the hosted stateless demo endpoint:
https://bilig.proompteng.ai/mcpThat endpoint is request-local and does not persist user files. Use it for connector smoke tests and tool discovery; use local file-backed stdio when a project needs to save a WorkPaper JSON file.
For setup details, use the
headless WorkPaper agent handbook,
MCP server guide,
spreadsheet MCP server comparison,
MCP directory status,
MCP client setup,
and
Claude Desktop MCPB guide.
The released Claude Desktop bundle is published at
https://github.com/proompteng/bilig/releases/download/libraries-v0.107.8/bilig-workpaper.mcpb.
Smithery users can install the hosted demo with
npx -y smithery mcp add gkonushev/bilig-workpaper.
Service Routes
For HTTP and serverless examples, start with
examples/serverless-workpaper-api.
pnpm --dir examples/serverless-workpaper-api install --ignore-workspace
pnpm --dir examples/serverless-workpaper-api run quote-approval-api
pnpm --dir examples/serverless-workpaper-api run next-route-handler
pnpm --dir examples/serverless-workpaper-api run next-server-action
pnpm --dir examples/serverless-workpaper-api run next-server-action-formdata
pnpm --dir examples/serverless-workpaper-api run framework-adapters
pnpm --dir examples/serverless-workpaper-api run persistence-adaptersStart with pnpm --dir examples/serverless-workpaper-api run quote-approval-api
when you want the production-shaped proof: input JSON writes Inputs!B2:B6,
formulas recalculate, the WorkPaper
JSON is persisted, and a restored workbook returns the same approval decision.
Useful anchors:
- quote approval API smoke
- Next.js App Router smoke
- Next.js Server Action smoke
- Next.js Server Action FormData smoke
- framework adapters
- persistence adapters
The public framework guide is https://proompteng.github.io/bilig/node-framework-workpaper-adapters.html.
XLSX Import And Export
Use the @bilig/headless/xlsx subpath for XLSX import, WorkPaper calculation,
edits, and XLSX export from the same published npm package:
pnpm add @bilig/headlessimport { readFileSync, writeFileSync } from 'node:fs'
import { WorkPaper } from '@bilig/headless'
import { exportXlsx, importXlsx } from '@bilig/headless/xlsx'
const imported = importXlsx(new Uint8Array(readFileSync('model.xlsx')), 'model.xlsx')
const workbook = WorkPaper.buildFromSnapshot(imported.snapshot, {
evaluationTimeoutMs: 30_000,
useColumnIndex: true,
})
const firstSheetName = imported.snapshot.sheets[0]?.name
const firstSheet = firstSheetName === undefined ? undefined : workbook.getSheetId(firstSheetName)
if (firstSheet === undefined) throw new Error('Workbook has no sheets')
workbook.setCellContents({ sheet: firstSheet, row: 1, col: 1 }, 150_000)
const displayValue = workbook.getCellDisplayValue({ sheet: firstSheet, row: 1, col: 1 })
writeFileSync('model-edited.xlsx', exportXlsx(workbook.exportSnapshot()))
workbook.dispose()
console.log({ displayValue })WorkPaper.buildFromSnapshot() preserves imported XLSX metadata such as
defined names, tables, hidden sheets, and translated structured references. Use
workbook.exportSnapshot() with exportXlsx() when exporting a WorkPaper after
edits.
For a runnable Node proof, use
examples/xlsx-recalculation-node.
It imports a pricing workbook XLSX, changes input cells, reads the recalculated
decision, exports the edited XLSX, reimports it, and verifies formula readback.
External Workbook References
XLSX files can contain links to other workbooks. @bilig/headless/xlsx
preserves those package artifacts, but it does not open or recalculate linked
workbooks by itself.
The importer exposes linked-workbook state in structured metadata:
snapshot.workbook.metadata.externalWorkbookReferences: linked workbook package paths, external targets, workbook names when available, and cached sheet names.snapshot.workbook.metadata.unsupportedFormulaDependencies: affected formula cells, original and imported formula text, linked workbook references, and whether cached formula or linked-cell values were used.
Use one of these policies:
- Resolve: provide ordinary local inputs or formulas after import, then
recalculate with
WorkPaper. - Preserve stale: keep imported cached values and preserved external-link artifacts, but treat formula correctness as unaudited for those dependencies.
- Strict-fail: reject the import when either metadata field above is non-empty.
The real-workbook corpus scorecard reports external references as
xlsx.externalLinks.workbookReferencesPreserved and direct formula dependencies
as xlsx.externalLinks.formulaDependenciesUnsupported, with linked workbook,
affected formula, and cached-value counts.
Accuracy Policy
Do not call a Bilig accuracy bug from stale XLSX cache data.
Embedded cached formula values are useful diagnostics, but they are not the source of truth. For XLSX formula accuracy, prepare a fresh Microsoft Excel oracle and evaluate against the recalculated copy:
OUT=.cache/excel-oracle-evaluation
pnpm workpaper:xlsx-corpus:check -- /path/to/xlsx-corpusThe Excel oracle harness should be provided by a workspace package, not a
root-level one-off script. If Excel automation is unavailable, the harness marks cells as
missing_excel_oracle instead of promoting cache mismatches to correctness
bugs.
For quick cache triage only:
pnpm workpaper:xlsx-corpus:check -- /path/to/xlsx-corpusProof You Can Reproduce
- The clean TypeScript sanity 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 XLSX import/export evaluation, 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. - 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. - Auditing imported Excel files is a separate workflow. Cached formula values
embedded in
.xlsxfiles are useful for triage, but Bilig accuracy claims should be checked against a fresh Microsoft Excel recalculation. - Run
pnpm workpaper:bench:competitive:checkfrom the repository. The checked-in artifact shows100/100comparable WorkPaper mean wins and100/100mean+p95 wins; the current worst p95 row issheet-rename-dependenciesat0.792x. - The shareable benchmark card is generated from the checked-in artifact:
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.
- Open benchmark critique lives in Discussion 340.
If it almost matches but a gap blocks adoption, use the adoption blocker form: https://github.com/proompteng/bilig/discussions/new?category=general. If a reduced workbook, import/export case, or service workflow would prove the gap better, submit a public fixture: https://github.com/proompteng/bilig/issues/new?template=workbook_fixture.yml. Fixture discussion: https://github.com/proompteng/bilig/discussions/414.
Production Status
Use this package for documented WorkPaper workflows: programmatic workbook creation, formula evaluation, structural edits, persistence round trips, service-side spreadsheet automation, and agent-driven workbook operations.
Current release posture:
- The contract is the WorkPaper/headless API exported by this package.
- Excel-file ingestion belongs to import/export pipelines before data reaches
WorkPaper. - Use
WorkPaper.buildFromSnapshot()for importer-produced workbook snapshots so Excel defined names, tables, and translated formulas stay attached to the runtime model. - Custom function plugins and callback hooks are runtime registrations; persist workbook data, then register custom behavior in application code before restore.
- Recent hardening covered config rebuilds, move-range bounds, persisted document validation, and benchmark gates.
Compatibility Notes
- The facade follows HyperFormula-style workbook workflows, but it is not byte-for-byte compatible with HyperFormula.
- Public lookup helpers such as
getSheetId(),getSheetName(),simpleCellAddressFromString(), and named-expression reads returnundefinedon misses. @bilig/headlessexposesonDetailed(),onceDetailed(), andoffDetailed()for detailed event payloads.- Stable compatibility adapters are available through
graph,rangeMapping,arrayMapping,sheetMapping,addressMapping,dependencyGraph,evaluator,columnSearch, andlazilyTransformingAstService. - Financial date formulas such as
XIRR()andXNPV()accept numeric Excel serial dates. Text date strings are not coerced in headless formulas.
Validation Commands
For a headless-only code change, start here:
pnpm exec vitest run \
packages/headless/src/__tests__/work-paper-runtime.test.ts \
packages/headless/src/__tests__/work-paper-parity.test.ts \
packages/headless/src/__tests__/persistence.test.ts \
packages/headless/src/__tests__/persistence.fuzz.test.ts
pnpm --filter @bilig/headless buildBefore publishing or claiming production readiness:
pnpm publish:runtime:check
pnpm workpaper:bench:competitive:check
pnpm run ciRegenerate the competitive benchmark artifact only when intentionally updating benchmark evidence:
pnpm workpaper:bench:competitive:generate
pnpm workpaper:bench:competitive:checkDo not change benchmark definitions, scoring, sampling, or workload sizes to hide losses.
For Coding Agents
Start here when Codex, Claude Code, or another agent is modifying or consuming this package:
- Read this README and the root
README.mdfirst. - Use the packaged
AGENTS.mdorSKILL.mdwhen another coding agent needs a portable WorkPaper instruction set. - Use public exports from
@bilig/headless; do not import fromsrc/,dist/internal, or@bilig/coreunless the task is package-internal engine work. - Use zero-based
{ sheet, row, col }addresses and resolve sheet ids withgetSheetId(). - Use
WorkPaper.buildFromSheets()for hand-authored fixtures,WorkPaper.buildFromSnapshot()for importer-produced snapshots, andexportWorkPaperDocument()/createWorkPaperFromDocument()for persistence round trips. - Do not treat embedded XLSX cached formula values as an accuracy oracle.
- Add or tighten regression tests before changing config rebuilds, range bounds, formulas, persistence, events, row/column moves, or sheet lifecycle.
- Run focused headless tests before broader gates.
- Preserve benchmark definitions and workload sizes.
- Document edge-case behavior honestly: tracked formula names are routed, but arbitrary Excel workbooks, host features, and locale/date argument edges still need fixtures before production claims.
Public Entry Points
The package root exports:
WorkPaper- WorkPaper address, range, config, sheet, change, event, and adapter types
- WorkPaper error classes
- persistence helpers:
exportWorkPaperDocument()createWorkPaperFromDocument()serializeWorkPaperDocument()parseWorkPaperDocument()isPersistedWorkPaperDocument()pickPersistableWorkPaperConfig()
More Guides
When the sanity check passes, these are the next useful pages.
- Service workflows: server-side spreadsheet automation, Node service recipe, serverless API route recipe, CSV-shaped input recipe, workbook automation examples, and framework adapters.
- Agent and MCP workflows: headless WorkPaper agent handbook, agent tool-calling recipe, OpenAI Agents SDK guide, OpenAI Responses guide, AI SDK, LangChain, and agent framework guide, MCP server guide, MCP directory page, MCP client setup, and Claude Desktop MCPB bundle (download).
- Choosing the stack: screenshot automation boundary, Node spreadsheet formula engine, Google Sheets API boundary, docs/javascript-spreadsheet-library-headless-node.md, formula workbooks for Node services and agent tools, headless spreadsheet engine for Node services and agents, XLSX formula recalculation in Node.js, Excel file as a Node calculation engine, stale XLSX formula cache in Node.js, SheetJS formula result not updating 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, docs/sheetjs-exceljs-alternative-formula-workbook-api.md, headless engine comparison, and HyperFormula comparison.
- Accuracy and compatibility: compatibility boundaries, XLSX corpus verifier walkthrough, local benchmark walkthrough, and benchmark proof note.
- Formula edge cases: XLOOKUP exact fixture, SUMIFS paired criteria fixture, and GROUPBY spill fixture.
Stay Connected
- Website: https://proompteng.github.io/bilig/
- GitHub: https://github.com/proompteng/bilig
- npm: https://www.npmjs.com/package/@bilig/headless
- Adoption blockers: https://github.com/proompteng/bilig/discussions/new?category=general
- Watch releases: https://github.com/proompteng/bilig/subscription
- Security policy: https://github.com/proompteng/bilig/blob/main/SECURITY.md
- Support policy: https://github.com/proompteng/bilig/blob/main/SUPPORT.md
- Ask a workflow question: https://github.com/proompteng/bilig/discussions/157
- Share service examples: https://github.com/proompteng/bilig/discussions/213
- Discuss persistence adapters: https://github.com/proompteng/bilig/discussions/307
- Discuss JavaScript spreadsheet library positioning: https://github.com/proompteng/bilig/discussions/308
- Discuss OpenAI Responses tool calls: https://github.com/proompteng/bilig/discussions/335
- Discuss benchmark fairness: https://github.com/proompteng/bilig/discussions/340
- Pick a scoped first patch: starter issues or first-timers-only issues.
Versioning
@bilig/headless ships as part of the aligned bilig runtime package set. Treat
documented public exports as the supported surface, keep integration tests around
your own workbook corpus, and rerun the validation gates before upgrading in
production.
