npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bilig/headless

v0.107.8

Published

Formula WorkPaper runtime for Node.js services and agent tools with JSON persistence and formula readback.

Readme

@bilig/headless

npm: @bilig/headless npm weekly downloads GitHub CodeQL OpenSSF Scorecard License: MIT

@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-challenge

The 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/headless

For 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 smoke

For a generated starter project:

npm create @bilig/workpaper@latest pricing-workpaper
npm create @bilig/workpaper@latest pricing-agent -- --agent

That 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 kB tarball, 4.89 MB unpacked, 777 package entries.
  • Boundary: the main import is the WorkPaper formula/JSON runtime; XLSX import/export stays behind the @bilig/headless/xlsx subpath; MCP is the bilig-workpaper-mcp binary wrapper; reduced workbook reports use the bilig-formula-clinic binary.
  • Cold-start gate: Node imports the main entrypoint, builds a two-sheet WorkPaper, and reads 24000 under 1000 ms without 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 signatures

The 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-challenge

Expected 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 build

When 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(), or WorkPaper.buildFromSnapshot().
  • Edit values, formulas, and blanks with workbook.setCellContents(address, value).
  • Apply large sparse literal patches with workbook.setCellValues(updates) or workbook.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(), and getRangeSerialized().
  • Persist with exportWorkPaperDocument() and serializeWorkPaperDocument().
  • Restore with parseWorkPaperDocument() and createWorkPaperFromDocument().
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:

Agent and tool-call examples:

MCP examples:

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/mcp

That 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-adapters

Start 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:

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/headless
import { 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-corpus

The 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-corpus

Proof 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: true output, benchmark caveat, known limits, and feedback ask together.
  • Auditing imported Excel files is a separate workflow. Cached formula values embedded in .xlsx files are useful for triage, but Bilig accuracy claims should be checked against a fresh Microsoft Excel recalculation.
  • Run pnpm workpaper:bench:competitive:check from the repository. The checked-in artifact shows 100/100 comparable WorkPaper mean wins and 100/100 mean+p95 wins; the current worst p95 row is sheet-rename-dependencies at 0.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 return undefined on misses.
  • @bilig/headless exposes onDetailed(), onceDetailed(), and offDetailed() for detailed event payloads.
  • Stable compatibility adapters are available through graph, rangeMapping, arrayMapping, sheetMapping, addressMapping, dependencyGraph, evaluator, columnSearch, and lazilyTransformingAstService.
  • Financial date formulas such as XIRR() and XNPV() 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 build

Before publishing or claiming production readiness:

pnpm publish:runtime:check
pnpm workpaper:bench:competitive:check
pnpm run ci

Regenerate the competitive benchmark artifact only when intentionally updating benchmark evidence:

pnpm workpaper:bench:competitive:generate
pnpm workpaper:bench:competitive:check

Do 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:

  1. Read this README and the root README.md first.
  2. Use the packaged AGENTS.md or SKILL.md when another coding agent needs a portable WorkPaper instruction set.
  3. Use public exports from @bilig/headless; do not import from src/, dist/internal, or @bilig/core unless the task is package-internal engine work.
  4. Use zero-based { sheet, row, col } addresses and resolve sheet ids with getSheetId().
  5. Use WorkPaper.buildFromSheets() for hand-authored fixtures, WorkPaper.buildFromSnapshot() for importer-produced snapshots, and exportWorkPaperDocument() / createWorkPaperFromDocument() for persistence round trips.
  6. Do not treat embedded XLSX cached formula values as an accuracy oracle.
  7. Add or tighten regression tests before changing config rebuilds, range bounds, formulas, persistence, events, row/column moves, or sheet lifecycle.
  8. Run focused headless tests before broader gates.
  9. Preserve benchmark definitions and workload sizes.
  10. 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.

Stay Connected

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.