@bilig/headless
v0.164.11
Published
Lower-level WorkPaper formula runtime for Node services with JSON persistence and verified formula readback.
Maintainers
Readme
@bilig/headless
@bilig/headless is the lower-level formula and WorkPaper runtime behind the
scoped @bilig/workpaper entrypoint.
If this npm page is the first thing you found, run the package proof before reading the full API docs:
npm exec --yes --package @bilig/workpaper@latest -- bilig-evaluate --door workpaper-service --jsonIt should print verified: true after editing an input cell, recalculating a
dependent formula, exporting WorkPaper JSON, restoring it, and reading the same
calculated value again.
Choose the narrow package by the state you own:
| You own... | Start with | First proof |
| ------------------------------------------ | ------------------------------------------------------------- | ------------------------------------------------------------------------ |
| WorkPaper state inside a service | npm install @bilig/workpaper | bilig-evaluate --door workpaper-service --json |
| A new service or route | npm create @bilig/workpaper@latest pricing-workpaper | npm run smoke |
| Tool or MCP integration | npm create @bilig/workpaper@latest pricing-agent -- --agent | bilig-evaluate --door agent-mcp --json |
| Lower-level runtime subpaths | npm install @bilig/headless | The examples below prove WorkPaper JSON, provenance, and package weight. |
| A saved workbook file remains the contract | npm install @bilig/xlsx-formula-recalc | bilig-evaluate --door workbook-compatibility --json |
Use @bilig/headless when the workbook is the business logic, but production
needs API readback, tests, persistence, and deterministic 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. Tool hosts
can expose narrow operations such as readRange and setInputCell instead of
guessing state from screenshots.
The npm tarball also includes AGENTS.md and SKILL.md so tool hosts
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,
WorkPaper agent tool, and
llms-full.txt.
This package is not a browser grid or desktop Excel automation. Workbook file
import/export is available from the @bilig/workpaper/xlsx and
@bilig/headless/xlsx subpaths for services that need 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 fixture report
without uploading workbook contents.
Saved workbook files are supported, but separate. Use the compatibility report
or recalculation example only when the file boundary is the product contract:
docs/workbook-compatibility-report.md,
examples/xlsx-recalculation-node,
and docs/xlsx-formula-recalculation-node.md.
Choose An Evaluation Path
| If you are evaluating... | Start here | What should be true before you 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 and pnpm --dir examples/serverless-workpaper-api run hono-route | A realistic route-style workflow returns formula readback and restoredMatchesAfter: true. |
| Saved workbook files | Workbook Compatibility Report and XLSX formula recalculation example | Use this only when a workbook file remains the integration contract. |
| 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. |
| Runtime intent contracts | Workbook runtime intent API | @bilig/workbook can describe plans, receipts, and strict runtime proof without owning state. |
| Tool-owned workbook files | Workbook Compatibility Report | A tool can inspect file risks before the service trusts imported formulas. |
| Technical review note | WorkPaper maintainer proof note | One compact page has the npm check, benchmark caveat, known limits, and open questions. |
| Trust and performance | npm provenance and benchmark evidence | npm shows SLSA provenance, and benchmark claims match the checked artifact. |
| Almost a fit | implementation gap discussion | Name the formula, import/export, persistence, framework, MCP, package, or benchmark gap. |
| Formula or XLSX bug | formula bug clinic and submit a workbook fixture | Share one reduced public fixture that maintainers can turn into a test. |
| Real workbook blocked | submit a workbook fixture | Use the structured form when a reduced workbook is ready. |
Reduced workbook already in hand? If the blocker is an import, formula, or persistence gap, generate the fixture report:
npm exec --package @bilig/workpaper@latest -- bilig-formula-clinic ./reduced.xlsx --cells "Summary!B7,Inputs!B2"Handing a spreadsheet task to another coding agent?
npm exec --yes --package @bilig/workpaper@latest -- bilig-agent-start --json
npm exec --yes --package @bilig/workpaper@latest -- bilig-evaluate --door workpaper-service --json
npm exec --yes --package @bilig/workpaper@latest -- bilig-evaluate --door agent-mcp --jsonThe first command tells the agent which proof path to run. The second command proves the direct WorkPaper API. The third proves the agent tool path with tool discovery, cell mutation, formula readback, JSON export, and restart proof. Both run without cloning the repository.
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, project-root .mcp.json
for Claude Code, Cursor and VS Code MCP configs, .junie/mcp/mcp.json for Junie,
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:
859 kBtarball,5.24 MBunpacked,835package 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 local 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 --json
npm exec --package @bilig/[email protected] -- bilig-mcp-challenge --jsonExpected 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 for service-owned JSON state, not every desktop spreadsheet feature.",
"Use saved-file compatibility evaluators only when a workbook file is the integration contract."
]
}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-agents-sdk-mcpstarts the WorkPaper MCP stdio server throughMCPServerStdio, converts its tools withgetAllMcpTools(), and verifies computed readback through the Agents SDK.npm run agent:openai-agents-sdk-hosted-mcpconnectsMCPServerStreamableHttptohttps://bilig.proompteng.ai/mcp, discovers the hosted WorkPaper MCP tools, and verifies stateless computed readback.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.pnpm --dir examples/mastra-workpaper-tool run smokeuses the real@mastra/corecreateTool()API around the same WorkPaper read/write contract: https://github.com/proompteng/bilig/tree/main/examples/mastra-workpaper-tool.uv run --python 3.12 --with google-adk --with mcp python examples/google-adk-workpaper-mcp/google_adk_workpaper_mcp.pyproves Google ADKMcpToolsetcan import the same file-backed WorkPaper MCP tools and return verified formula readback: https://github.com/proompteng/bilig/blob/main/docs/google-adk-workpaper-mcp.md.
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
npm exec --package @bilig/[email protected] -- bilig-workpaper-mcp --from-xlsx ./pricing.xlsx
npm exec --package @bilig/[email protected] -- bilig-workpaper-mcp --from-xlsx ./pricing.xlsx --workpaper ./.bilig/pricing.workpaper.json --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, set_cell_contents_and_readback,
get_cell_display_value, export_workpaper_document, and validate_formula;
--init-demo-workpaper creates the demo JSON file when it is missing, and
--from-xlsx ./pricing.xlsx imports an existing XLSX into an in-memory server
for readback, throwaway edits, and analyze_workbook_risk. Add
--workpaper ... --writable when the imported workbook must persist edits to a
WorkPaper JSON file. --writable persists set_cell_contents edits back to the same file.
The set_cell_contents_and_readback tool does the same write while
reading a dependent output range in the same MCP call. 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 the
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/latest/download/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 a route-shaped check: 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. For large imported
XLSX files, prefer importXlsxFile(path) with
exportWorkPaperXlsxToFileAsync(workbook, outputPath): the import reads through
the file-backed ZIP byte-source path, and scalar literal exports patch the
original XLSX package from that source reader instead of forcing the full
exportSnapshot() -> exportXlsx() in-memory round trip.
pnpm add @bilig/headlessimport { WorkPaper } from '@bilig/headless'
import { exportWorkPaperXlsxToFileAsync, importXlsxFile } from '@bilig/headless/xlsx'
const imported = importXlsxFile('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 })
await exportWorkPaperXlsxToFileAsync(workbook, 'model-edited.xlsx')
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 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, recalculates an approval decision, persists JSON, and verifies restored readback.
- For a shorter evaluation page, read formula workbooks for Node services and tool integrations. It compresses the WorkPaper boundary, MCP file-backed mode, benchmark caveat, and alternative-tool guidance into one evaluation path.
- For a compact review note, use the
WorkPaper maintainer proof note.
It keeps the empty npm-project command,
verified: trueoutput, benchmark caveat, known limits, and open questions together. - For saved-file integration, 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. - 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. - The public workbook corpus report is generated from the checked 22-workbook public scorecard. It records 602 source candidates, 22 cached public workbooks, 812,868 cells, 46,211 formula cells, 6/6 formula-oracle matches, and the three resource-limited classifications.
- 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, open an implementation gap discussion: https://github.com/proompteng/bilig/discussions/new?category=general. If the fixture is already reduced and public, submit it through the public fixture form with the exact cell address, formula, expected value, observed value, and command output: https://github.com/proompteng/bilig/issues/new?template=workbook_fixture.yml. If you are still reducing the fixture, discuss the shape first: 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, Google Sheets QUERY/SORTN in Node, docs/javascript-spreadsheet-library-headless-node.md, formula workbooks for Node services and tool integrations, headless spreadsheet engine for Node services and tool hosts, XLSX formula recalculation in Node.js, Excel file as a Node calculation engine, stale XLSX formula cache in Node.js, stale formula readback chooser, 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
- Implementation gaps: 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.
