{"id":47332832,"url":"https://github.com/proompteng/bilig","last_synced_at":"2026-05-17T10:02:37.327Z","repository":{"id":344142005,"uuid":"1180482213","full_name":"proompteng/bilig","owner":"proompteng","description":"Fast headless spreadsheet engine for Node.js formulas, workbook automation, WorkPaper JSON, and agent workflows.","archived":false,"fork":false,"pushed_at":"2026-05-15T05:02:37.000Z","size":48228,"stargazers_count":23,"open_issues_count":120,"forks_count":17,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-15T06:49:55.226Z","etag":null,"topics":["agent-tools","ai-agents","coding-agents","formula-engine","headless-spreadsheet","headless-workbook","langchain","mcp","model-context-protocol","nodejs","spreadsheet","spreadsheet-api","spreadsheet-automation","spreadsheet-engine","spreadsheet-formulas","typescript","vercel-ai-sdk","workbook-api","workbook-automation","xlsx"],"latest_commit_sha":null,"homepage":"https://proompteng.github.io/bilig/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/proompteng.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":"SUPPORT.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-13T04:50:28.000Z","updated_at":"2026-05-15T05:01:25.000Z","dependencies_parsed_at":null,"dependency_job_id":"ef5f035f-2cf9-4d38-b0fc-2dd7cc98b3f6","html_url":"https://github.com/proompteng/bilig","commit_stats":null,"previous_names":["proompteng/bilig"],"tags_count":210,"template":false,"template_full_name":null,"purl":"pkg:github/proompteng/bilig","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/proompteng%2Fbilig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/proompteng%2Fbilig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/proompteng%2Fbilig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/proompteng%2Fbilig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/proompteng","download_url":"https://codeload.github.com/proompteng/bilig/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/proompteng%2Fbilig/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33095031,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-16T04:41:52.686Z","status":"ssl_error","status_checked_at":"2026-05-16T04:41:52.009Z","response_time":115,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-tools","ai-agents","coding-agents","formula-engine","headless-spreadsheet","headless-workbook","langchain","mcp","model-context-protocol","nodejs","spreadsheet","spreadsheet-api","spreadsheet-automation","spreadsheet-engine","spreadsheet-formulas","typescript","vercel-ai-sdk","workbook-api","workbook-automation","xlsx"],"created_at":"2026-03-17T21:22:44.630Z","updated_at":"2026-05-17T10:02:37.288Z","avatar_url":"https://github.com/proompteng.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# bilig\n\n[![CI](https://github.com/proompteng/bilig/actions/workflows/ci.yml/badge.svg)](https://github.com/proompteng/bilig/actions/workflows/ci.yml)\n[![GitHub Repo stars](https://img.shields.io/github/stars/proompteng/bilig?style=social)](https://github.com/proompteng/bilig/stargazers)\n[![npm: @bilig/headless](https://img.shields.io/npm/v/@bilig/headless?label=%40bilig%2Fheadless)](https://www.npmjs.com/package/@bilig/headless)\n[![npm weekly downloads](https://img.shields.io/npm/dw/@bilig/headless?label=npm%20downloads)](https://www.npmjs.com/package/@bilig/headless)\n[![MCP server score](https://glama.ai/mcp/servers/proompteng/bilig/badges/score.svg)](https://glama.ai/mcp/servers/proompteng/bilig)\n[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)\n\n**Formulas for TypeScript services.**\n\nUse [`@bilig/headless`](https://www.npmjs.com/package/@bilig/headless) when a\ncalculation is easiest to review as cells and formulas, but it has to run in a\nNode service, queue worker, serverless route, test, or coding-agent tool.\n\nIt gives you a `WorkPaper`: build sheets, write inputs, recalculate, read the\ncell value, and save the workbook as JSON. No browser grid is involved.\n\nGood fits: pricing rules, budget checks, payout models, import validation, and\nagent tools that need read-after-write proof. Bad fits: manual spreadsheet\nediting, Office macros, desktop Excel automation, or one-off arithmetic where a\nworkbook would be ceremony.\n\nProject site: \u003chttps://proompteng.github.io/bilig/\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/github-social-preview.png\" alt=\"bilig headless workbook runtime for formulas in TypeScript\" /\u003e\n\u003c/p\u003e\n\n## Try It In 90 Seconds\n\nThis uses the published npm package. It builds a workbook, changes one input,\nreads the calculated value, saves JSON, restores the workbook, and prints the\nsame value again.\n\n```sh\nmkdir bilig-headless-eval\ncd bilig-headless-eval\nnpm init -y\nnpm pkg set type=module\nnpm install @bilig/headless\nnpm install -D tsx typescript @types/node\ncurl -fsSLo quickstart.ts https://proompteng.github.io/bilig/npm-eval.ts\nnpx tsx quickstart.ts\n```\n\nExpected output:\n\n```json\n{\n  \"before\": 24000,\n  \"after\": 38400,\n  \"afterRestore\": 38400,\n  \"sheets\": [\"Inputs\", \"Summary\"],\n  \"bytes\": 1000,\n  \"verified\": true\n}\n```\n\nThe TypeScript file is maintained in\n[`examples/headless-workpaper/npm-eval.ts`](examples/headless-workpaper/npm-eval.ts).\nThe exact byte count can change between package versions; `verified: true` and\nmatching `after`/`afterRestore` values are the check.\n\n## TypeScript API Shape\n\nMost integrations are just this: build a workbook, write an input, read the\ncalculated value, and save the workbook state.\n\n```ts\nimport { WorkPaper, exportWorkPaperDocument, serializeWorkPaperDocument } from '@bilig/headless'\n\nconst workbook = WorkPaper.buildFromSheets({\n  Inputs: [\n    ['Metric', 'Value'],\n    ['Customers', 20],\n    ['Average revenue', 1200],\n  ],\n  Summary: [\n    ['Metric', 'Value'],\n    ['Revenue', '=Inputs!B2*Inputs!B3'],\n  ],\n})\n\nconst inputs = workbook.getSheetId('Inputs')\nconst summary = workbook.getSheetId('Summary')\nif (inputs === undefined || summary === undefined) {\n  throw new Error('Workbook is missing required sheets')\n}\n\nworkbook.setCellContents({ sheet: inputs, row: 1, col: 1 }, 32)\n\nconst revenue = workbook.getCellDisplayValue({ sheet: summary, row: 1, col: 1 })\nconst saved = serializeWorkPaperDocument(exportWorkPaperDocument(workbook, { includeConfig: true }))\n\nconsole.log({ revenue, savedBytes: saved.length })\n```\n\n## When To Reach For It\n\nUse `@bilig/headless` when:\n\n- a Node service owns a workbook-shaped calculation;\n- an agent needs tools such as `readRange` and `setInputCell`, with computed\n  before/after values instead of screenshots;\n- tests need deterministic spreadsheet state and formula readback;\n- a workflow needs to save the edited workbook as JSON and restore it later.\n\nUse something else when you need a visual spreadsheet grid, Office macros,\ndesktop Excel automation, or a one-off arithmetic helper. Do not treat embedded\nXLSX cached formula values as truth; use the Excel oracle workflow when accuracy\nmatters.\n\n## Start Here\n\nPick the path closest to what you are building.\n\n- If you are evaluating the npm package:\n  [90-second npm eval](#try-it-in-90-seconds) and\n  [Node quickstart](docs/try-bilig-headless-in-node.md).\n- If you are writing code against the API:\n  [packages/headless/README.md](packages/headless/README.md) and the\n  [WorkPaper read/write cheat sheet](packages/headless/README.md#workpaper-readwrite-cheat-sheet).\n- If you are putting workbook logic in a service:\n  [Node service recipe](docs/node-service-workpaper-recipe.md),\n  [server-side spreadsheet automation](docs/server-side-spreadsheet-automation-node.md),\n  [Node spreadsheet formula engine](docs/node-spreadsheet-formula-engine.md),\n  [framework adapters](docs/node-framework-workpaper-adapters.md), and\n  [workbook automation examples](docs/workbook-automation-examples-node.md).\n  The runnable serverless boundary lives in\n  [examples/serverless-workpaper-api](examples/serverless-workpaper-api);\n  run `npm run next-route-handler`, `npm run next-server-action`,\n  `npm run next-server-action-formdata`, `npm run framework-adapters`, and\n  `npm run persistence-adapters` from that example.\n- If an agent needs workbook tools:\n  [agent tool-calling recipe](docs/agent-workpaper-tool-calling-recipe.md),\n  [OpenAI Responses tools](docs/openai-responses-workpaper-tool-call.md),\n  [AI SDK and LangChain adapters](docs/vercel-ai-sdk-langchain-spreadsheet-tool.md),\n  [agent framework adapters](examples/headless-workpaper#agent-framework-adapters),\n  [MCP server guide](docs/mcp-workpaper-tool-server.md),\n  [MCP tool server shape](examples/headless-workpaper#mcp-tool-server-shape),\n  [MCP directory status](docs/mcp-spreadsheet-server-directory.md),\n  [MCP client setup](docs/mcp-client-setup.md), and\n  [Claude Desktop MCPB bundle](docs/claude-desktop-mcpb-workpaper.md).\n- If you are comparing libraries:\n  [evaluate Excel formulas in Node.js](docs/evaluate-excel-formulas-in-node-typescript.md),\n  [Google Sheets API boundary](docs/google-sheets-api-alternative-node-workpaper.md),\n  [docs/javascript-spreadsheet-library-headless-node.md](docs/javascript-spreadsheet-library-headless-node.md),\n  [docs/sheetjs-exceljs-alternative-formula-workbook-api.md](docs/sheetjs-exceljs-alternative-formula-workbook-api.md),\n  [headless engine comparison](docs/headless-spreadsheet-engine-comparison.md), and\n  [HyperFormula notes](docs/hyperformula-alternative-headless-workpaper.md).\n- If you want a first contribution:\n  [starter issues](docs/starter-issues.md),\n  [first-timers-only issues](https://github.com/proompteng/bilig/issues?q=is%3Aissue%20state%3Aopen%20label%3Afirst-timers-only),\n  [GitHub Discussions](https://github.com/proompteng/bilig/discussions), and\n  [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## Examples You Can Run\n\nThe runnable examples are TypeScript files. Some source imports end in `.js`\nbecause Node ESM resolves compiled package output that way; the files you edit\nand run are still `.ts`.\n\nFrom `examples/headless-workpaper`:\n\n```sh\nnpm install\nnpm start\nnpm run json-records\nnpm run csv-shaped\nnpm run invoice-totals\nnpm run budget-variance\nnpm run fulfillment-capacity\nnpm run quote-approval\nnpm run subscription-mrr\nnpm run persistence\n```\n\nThe most useful entry points:\n\n- [JSON records input](examples/headless-workpaper#json-records-input)\n- [CSV shaped input](examples/headless-workpaper#csv-shaped-input)\n- [invoice totals](examples/headless-workpaper#invoice-totals)\n- [budget variance alerts](examples/headless-workpaper#budget-variance-alerts)\n- [fulfillment capacity plan](examples/headless-workpaper#fulfillment-capacity-plan)\n- [quote approval threshold](examples/headless-workpaper#quote-approval-threshold)\n- [subscription MRR forecast](examples/headless-workpaper#subscription-mrr-forecast)\n\nFor agent tools:\n\n```sh\nnpm run agent:verify\nnpm run agent:tool-call\nnpm run agent:openai-responses\nnpm run agent:ai-sdk-generate-text\nnpm run agent:ai-sdk-stream-text\nnpm run agent:framework-adapters\nnpm run agent:mcp-tools\nnpm run agent:mcp-stdio\n```\n\nThe AI SDK example uses\n[`ai-sdk-generate-text-tool-smoke.ts`](examples/headless-workpaper/ai-sdk-generate-text-tool-smoke.ts).\nThe OpenAI Responses guide is\n[`docs/openai-responses-workpaper-tool-call.md`](docs/openai-responses-workpaper-tool-call.md).\nThe agent framework guide is\n[`docs/vercel-ai-sdk-langchain-spreadsheet-tool.md`](docs/vercel-ai-sdk-langchain-spreadsheet-tool.md).\n\nThe package also ships the MCP stdio binary:\n\n```sh\nnpm exec --package @bilig/headless -- bilig-workpaper-mcp\n```\n\nIt is published in the official MCP Registry as\n`io.github.proompteng/bilig-workpaper`:\n\u003chttps://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.proompteng%2Fbilig-workpaper\u003e.\n\n## Proof You Can Reproduce\n\n- The 90-second TypeScript check above edits one input, restores the saved JSON\n  document, and verifies the dependent formula result.\n- Run `pnpm workpaper:bench:competitive:check`. The checked-in artifact shows\n  [`46/46` comparable WorkPaper mean wins](docs/what-workpaper-benchmark-proves.md)\n  and names the slower p95 row: `lookup-approximate-duplicates` at `1.043x`.\n- The benchmark card is generated from that artifact:\n  [`docs/assets/workpaper-benchmark-card.png`](docs/assets/workpaper-benchmark-card.png).\n- Read the [compatibility limits](docs/where-bilig-is-not-excel-compatible-yet.md)\n  before importing real Excel workbooks.\n- For XLSX accuracy audits, use the\n  [Excel oracle harness](docs/xlsx-corpus-verifier-walkthrough.md#run-the-excel-oracle-harness).\n  It separates import success, timeouts, stale cached formula values, and fresh\n  Microsoft Excel recalculation results.\n- Track public signals in the\n  [growth snapshot](https://proompteng.github.io/bilig/community-growth-snapshot.html):\n  stars, npm downloads, starter issues, Discussions, traffic, and clones.\n- The WorkPaper MCP server is listed in the\n  [official MCP Registry](https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.proompteng%2Fbilig-workpaper)\n  and on [Glama](https://glama.ai/mcp/servers/proompteng/bilig). The\n  [directory status page](docs/mcp-spreadsheet-server-directory.md) keeps the\n  npm command and directory evidence in one place.\n- Public feedback threads:\n  [workflow questions](https://github.com/proompteng/bilig/discussions/157),\n  [service examples](https://github.com/proompteng/bilig/discussions/213),\n  [persistence adapters](https://github.com/proompteng/bilig/discussions/307),\n  [JavaScript spreadsheet library guide](https://github.com/proompteng/bilig/discussions/308),\n  [OpenAI Responses tool calls](https://github.com/proompteng/bilig/discussions/335),\n  and [benchmark critique](https://github.com/proompteng/bilig/discussions/340).\n\nIf the 90-second check matches a problem you have, star or bookmark the repo:\n\u003chttps://github.com/proompteng/bilig/stargazers\u003e.\n\n## XLSX Accuracy Policy\n\nCached formula values embedded in `.xlsx` files are cache diagnostics, not an\naccuracy verdict. A Bilig correctness bug should only be claimed when the\nexpected value came from a fresh Excel recalculation oracle.\n\n```sh\nOUT=.cache/excel-oracle-evaluation\npnpm workpaper:xlsx-oracle -- prepare-oracle /path/to/xlsx-corpus \"$OUT\"\npnpm workpaper:xlsx-oracle -- evaluate-cache /path/to/xlsx-corpus \"$OUT\"\npnpm workpaper:xlsx-oracle -- evaluate-oracle /path/to/xlsx-corpus \"$OUT/recalculated\" \"$OUT\"\npnpm workpaper:xlsx-oracle -- summarize \"$OUT\"\n```\n\n`evaluate-cache` writes `cache-diagnostic.json` and stays non-authoritative.\n`evaluate-oracle` writes `excel-oracle-report.json`, and `summarize` writes\n`summary.md`. If Excel automation is unavailable, cells are classified as\n`missing_excel_oracle` instead of being promoted to bugs.\n\n## What Is In This Repo\n\n- `packages/headless`: WorkPaper runtime and npm package.\n- `packages/excel-import`: XLSX import/export boundary. Install both packages\n  with `pnpm add @bilig/headless @bilig/excel-import` when you need file import\n  and export.\n- `packages/formula`: formula parser, binder, compiler, and evaluator.\n- `packages/core`: workbook engine, snapshots, mutation flow, and scheduler.\n- `packages/grid` and `apps/web`: browser spreadsheet shell.\n- `apps/bilig`: fullstack monolith runtime, API surface, and static asset\n  server.\n- `packages/renderer`: React workbook renderer.\n- `packages/protocol`, `packages/binary-protocol`, `packages/agent-api`, and\n  `packages/worker-transport`: protocol and integration boundaries.\n- `packages/wasm-kernel`: AssemblyScript/WASM numeric fast path.\n- `packages/benchmarks`: benchmark harness and performance contracts.\n\nFor XLSX import/export from TypeScript:\n\n```ts\nimport { WorkPaper } from '@bilig/headless'\nimport { exportXlsx, importXlsx } from '@bilig/excel-import'\n```\n\nUse `WorkPaper.buildFromSnapshot(imported.snapshot)` after import and\n`workbook.exportSnapshot()` before `exportXlsx()`.\n\n## Local Development\n\nUse Node `24+`, Bun, and `pnpm@10.32.1`.\n\n```sh\npnpm install\npnpm dev:web\npnpm dev:web-local\npnpm dev:sync\n```\n\nFor a full local preflight:\n\n```sh\npnpm lint\npnpm typecheck\npnpm test\npnpm test:browser\npnpm run ci\n```\n\nGenerated sources and public evidence are checked:\n\n```sh\npnpm protocol:check\npnpm formula-inventory:check\npnpm workspace-resolution:check\npnpm workpaper:bench:competitive:check\npnpm docs:discovery:check\n```\n\n## For Coding Agents\n\nStart with the public package boundary unless the task is explicitly engine\nwork.\n\n1. Read `packages/headless/README.md` before touching WorkPaper behavior.\n2. Use public exports from `@bilig/headless`; do not reach into `src/` or\n   `dist/` when writing consumer examples.\n3. Keep examples TypeScript-first.\n4. Do not call stale XLSX cached formula values an accuracy oracle.\n5. Add focused tests before changing formulas, persistence, range bounds,\n   config rebuilds, events, row/column moves, or sheet lifecycle.\n6. Run the focused package tests first, then broaden to `pnpm run ci`.\n\n## Contributing\n\nRead [CONTRIBUTING.md](CONTRIBUTING.md) before opening a PR. If this is your\nfirst patch, start with the\n[new contributor guide](docs/new-contributor-guide.md) and then claim a scoped\nstarter issue.\n\nGood first patches usually fit one of these shapes:\n\n- formula fixtures with clear expected behavior;\n- small WorkPaper examples that prove a real service or agent workflow;\n- focused correctness fixes with regression tests;\n- grid accessibility and keyboard-behavior improvements;\n- docs that turn an existing architecture note into a runnable command.\n\nThe shortest public on-ramp is the\n[`starter issues`](docs/starter-issues.md) queue. It keeps code/test picks,\nexample tasks, adapters, and focused docs work in one current list, with small\nacceptance commands for first patches.\n\nIf this is your first contribution to `bilig`, use the\n[`first-timers-only`](https://github.com/proompteng/bilig/issues?q=is%3Aissue%20state%3Aopen%20label%3Afirst-timers-only)\nfilter.\n\n## CI\n\nForgejo Actions is the primary CI surface via\n`.forgejo/workflows/forgejo-ci.yml`. GitHub Actions mirrors the verification\ncontract in `.github/workflows/ci.yml`.\n\nThe strict gate includes frozen lockfile install, full `pnpm run ci`, artifact\nbudget checks, browser smoke, and tracked-file cleanliness checks.\n\n## License\n\nMIT.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fproompteng%2Fbilig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fproompteng%2Fbilig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fproompteng%2Fbilig/lists"}