Open source · Apache-2.0 · Alpha

Spreadsheets, the way you already work.

OpenCalc is an open-source, Excel-compatible spreadsheet. It opens your .xlsx files without quietly losing anything, keeps the ribbon and the shortcuts your hands already know, and runs in your browser, on your desktop, inside your own product — and under your AI agents.

No sign-up, nothing uploaded The engine runs on your machine

An animated spreadsheet: quarterly figures are typed in, totals calculate, a SORTBY formula spills a ranked list, a collaborator named Ana changes one value and everything that depends on it recalculates — the ranking reorders — and the file is saved as .xlsx with nothing dropped.
  1. Type
  2. Calculate
  3. Spill
  4. Co-edit
  5. Save
347worksheet functions, with dynamic arrays and LAMBDA
6file formats it opens: .xlsx .xlsm .ods .csv .tsv .psv
0things dropped silently — what isn't modelled is kept or named
1M+cells: the capacity the grid is built for, at 60 fps

01 The product, not a mock-up

It's running right here. Click in and type.

This is the real editor — the same ribbon, formula bar and grid you get at editor.html — calculating in this page with WebAssembly. Nothing you type leaves your browser.

OpenCalc — running in this page, client-side Full screen
Try Ctrl+Z, F2, a =XLOOKUP, or open an .xlsx of your own from the File tab. See it embedded with the SDK

02 What it is

An Excel-compatible spreadsheet, built in the open.

Everything you reach for in a spreadsheet, with the file formats, ribbon and keyboard you already know — plus the parts a closed product can't give you.

.xlsx .ods .csv engine Compatibility report 1,204 cells 3 charts 2 tables 1 kept verbatim 0dropped
.xlsx · .xlsm · .ods · .csv

Opens your files. Never drops anything quietly.

Formatting, tables, charts, validation, protection, print setup and defined names survive the round-trip. Anything the model can't hold yet is carried through byte for byte or counted and named in a compatibility report — never silently discarded.

File Home Insert Formulas Data Clipboard BIFont Alignment ΣEditing Ctrl + Shift + L F2 F4 F9
Ribbon · KeyTips · shortcuts

The ribbon and shortcuts you already know.

The same tabs, groups and dialogs in the same places, Alt-key KeyTips, and the keyboard shortcuts your hands learned years ago. Nothing to relearn.

fx =SORT(UNIQUE(A2:A8))   A B C 1234567 Fruit PearFigPearAppleKiwiFig Distinct Apple Fig Kiwi Pear
347 functions

Formulas that spill.

Dynamic arrays — FILTER, SORT, UNIQUE, XLOOKUP — LET and LAMBDA with MAP, REDUCE and SCAN, structured references, and autocomplete with signatures.

Team plan.xlsx Me A K Ana Kofi
Real-time · self-hosted

Edit together, live.

Share a link and see each other's cursors and edits as they happen — on a collaboration server you run yourself, with presence and reconnect built in.

Q3 budget.xlsx — OpenCalc xlsx Works offline
macOS · Windows · Linux

A real desktop app.

The engine as native Rust in its own window. Double-click an .xlsx, .xlsm, .ods or .csv to open it; no network needed.

main tests ✓ Apache-2.0
Apache-2.0 · Rust · no telemetry

Open source, all the way down.

Every line is on GitHub — the engine, the editor, the desktop shell and the servers. CI-gated, fuzzed and benchmarked; unsafe is forbidden. No licence check, nothing phones home, and fidelity bugs with a file attached are the most useful thing you can send.

Read the source

03 Shipping now

What works today

A verified list, not a roadmap — everything here is exercised by the editor above. What is still pending is in the roadmap below.

Editing

  • Inline and formula-bar editing
  • Rich clipboard — formulas and formats travel
  • Drag-fill with reference shifting
  • Find and replace across the sheet
  • Right-click insert / delete rows and columns
  • Undo and redo, one step per edit

Formulas & calc

  • 347 of the 356 functions in the spec
  • Dynamic arrays that spill — FILTER, SORT, UNIQUE, XLOOKUP
  • LET and LAMBDA, with MAP, REDUCE, SCAN and BYROW
  • Autocomplete with signatures; click or drag to insert refs
  • Cross-sheet and whole-row/column references
  • Automatic or manual calculation, as the file asks

Format & structure

  • Fonts, colors, alignment, borders, wrap, rich text
  • Number formats: currency, percent, dates, custom
  • Conditional formatting, data validation, protection
  • Tables with structured references and banding
  • Sort, per-column filter, outlines, freeze panes
  • Page setup, print areas and manual page breaks

Analysis

  • Pivot tables — build, filter, refresh, GETPIVOTDATA
  • Drag fields between Rows, Columns, Filters and Values
  • Eleven aggregates, subtotals and grand totals
  • Charts: column, bar, line, area, pie, doughnut, scatter
  • Insert, retitle, move and resize on the grid
  • Charts written as real chart parts, not pictures

Reads and writes .xlsx and .xlsm · reads and writes .ods (values and formulas; what it cannot carry is counted) · imports and exports CSV, TSV, PSV. Formatting, tables, charts, validation, protection, print setup and defined names survive the round-trip — and anything not yet modelled is carried through byte for byte rather than dropped.

04 Embed it

Ship a spreadsheet inside your product.

One custom element and your users get the editor above — .xlsx in and out, 347 functions, pivot tables and charts, all client-side. React, Next.js, Vue, Svelte or plain HTML.

  1. Install

    The element and, on React, its wrapper. No UI framework peer dependency.

    # the editor as a custom element
    npm install @opencalc/sheet
  2. Serve the engine yourself

    The WebAssembly binary is copied into your build and served from your origin — never from a CDN we run.

    # package.json → postinstall
    opencalc-assets ./public/opencalc
  3. Mount it

    Give it a height and it boots. Open a workbook, get bytes back, listen for changes.

your-app.example/reports <opencalc-sheet>
Load a file, react to edits, save it back@opencalc/sheet
import "@opencalc/sheet";
// <opencalc-sheet style="height:600px"></opencalc-sheet>
const sheet = document.querySelector("opencalc-sheet");

sheet.theme({ light: { accentColor: "#7c3aed" } }); // typed CSS tokens
sheet.chrome({ statusbar: false });                 // hide whole regions…
sheet.commands({ hidden: ["file.open"] });         // …or single controls

await sheet.configure({ access: "view" });         // "edit" | "view" | "preview"
await sheet.open(bytes, "budget.xlsx");

sheet.on("cellsChanged", async (e) => {
  if (e.source !== "api") persist(await sheet.save()); // deterministic .xlsx
});

The element isolates itself in a shadow root: your CSS cannot reach in and ours cannot reach out. Read-only and preview refuse writes in the engine, not by hiding buttons. Alpha: published as 0.0.x — pin what you test against.

05 For AI agents

Hand a workbook to an agent.

casual-calc-mcp is an MCP server that lets Claude, or any MCP client, open, read, write, recalculate and save spreadsheets with the same engine — and get back the same compatibility report you would.

open_workbooklist_sheetsread_rangewrite_cellsevaluaterecalculaterunsaveclose
  1. Sandboxed to the folders you name

    It touches files only under --root, every path canonicalised; with no root, every file tool refuses. It speaks stdio and has no network code.

  2. Bounded

    File size, cells per call and open workbooks are all capped, so a runaway agent cannot exhaust the machine.

  3. Build it from source today

    cargo build --release -p casual-calc-mcp
    claude mcp add opencalc -- ./target/release/casual-calc-mcp --root ~/Sheets

The MCP server's README

06 Three products, one engine

Which one do you want?

The engine is the same in all three — the same import, the same 347 functions, the same writer. What differs is where it runs and what it is allowed to reach.

Question SDK@opencalc/sheet · 0.0.1 Desktop app0.0.3 Self‑hostedthree images · 0.0.1
Where it runs Your web page, as WebAssembly macOS (Apple Silicon), Windows x64, Linux x64 — the engine as native Rust Your servers — amd64 and arm64
How you get it npm i @opencalc/sheet .dmg · .exe · .deb · .AppImage docker run casualoffice/calc
The whole engine — .xlsx, formulas, charts, pivots Yes Yes Yes
Opening a file from the operating system Through your own code — you hand it the bytes Native dialogs, and double‑click on .xlsx .xlsm .ods .csv .tsv Through the document host, or your own storage
Several people in one sheet at once No — a single‑user editing surface Yes, as a participant Yes — this is the server that orders and relays
Fits into A web component, or the React wrapper The file types above Nextcloud, ownCloud, SharePoint, Moodle, Alfresco — one discovery URL
Signed by the operating system Not applicable Not yet — the bypass is two clicks, and the download page walks through it Not applicable
Worth knowing Each element carries its own engine, so page a long list in and out rather than mounting fifty. A pivot built here exports as its cells, not as a live Excel pivot. Pasting from another application arrives as values without formatting. The .deb needs Ubuntu 23.04 or newer; the AppImage runs on 22.04. No Helm chart yet, and Redis is a single node. Prometheus metrics are on /metrics.

Not yet, in any of the three. PDF export is written and tested in the engine but is not reachable from a published product — it ships when the Rust SDK does. .xls (the pre‑2007 binary format) is refused rather than half‑read; .xlsm opens, and its macros survive a round‑trip byte for byte, but nothing here executes them. Custom worksheet functions written in JavaScript are deliberately absent — they would make a recalculation unrepeatable. Menus and toolbar tooltips are localized; panels and dialogs are still English.

07 Under the hood

One pipeline. Three hosts.

A layered Rust core. Parsing sits below evaluation, so import and editing use the formula AST without pulling in the calc engine at all — and the same input always produces the same model, values, layout and bytes.

  1. .xlsx · .ods · csv
  2. bounded admission
  3. import
  4. workbook model
  5. recalc
  6. layout
  7. render · write

Native desktop

A Tauri host where the whole engine — including calc — runs as native Rust at full speed.

WebAssembly

The same core compiled to wasm32, driving a canvas grid entirely client-side. The editor above is the proof.

Headless

No UI at all — batch convert, recalculate, and rasterize a viewport to a deterministic PNG on a server.

Embed the enginecasual-calc-sdk
// One session composes every layer: open, edit, recalc, render, save.
let mut session = WorkbookSession::open(bytes)?;
session.edit(Operation::SetCell { sheet: 0, at: a1("B2"), cell })?;
let png  = session.render_png(0, &viewport)?;   // virtualized grid → PNG
let xlsx = session.save()?;                     // deterministic bytes

08 Self-hosted

Run the whole thing yourself, before you integrate anything.

Co-editing is not a feature you should have to take on trust. Two containers, one command, and you are sharing a link with a colleague and typing into the same sheet. Download gives you an .xlsx with what you both typed — the server hands the finished bytes back to the host rather than keeping them.

The collaboration server is what OpenCalc supplies — ordering, presence, the socket. The host is what your product supplies — documents, identity, tokens, saving: four endpoints and a signature, and the host you just ran is the worked example.

terminaldocker compose
# change OPENCALC_SHARED_SECRET in .env$ cp .env.example .env$ docker compose up$ open http://localhost:8080# make a sheet, press Share, send the link​# and a cluster, when one node is not enough$ docker compose -f docker-compose.cluster.yml up
Published images

casualoffice/calc, calc-host and wopi — pulled, not built. Add --build to build from your checkout.

amd64 and arm64

Each with an SBOM and a build-provenance attestation naming the repository, workflow and commit it came from.

Your network only

Nothing phones home, no licence check, and no document leaves your servers. Prometheus metrics on /metrics.

09 The trade-off everyone else makes

Fidelity, or embeddability. Pick both.

Most options force a compromise: a suite you can't embed, a converter that quietly drops what it doesn't understand, or a web grid that treats the DOM as the source of truth and calculates on a server.

Approach
Embeddable
Offline calc
Loss-aware
Deterministic bytes
A full office suiteExcel, LibreOffice Calc
No
Yes
Yes
No
A converter libraryread or write, no model
Yes
Partial
No
Varies
A web grid + server calcDOM as source of truth
Partial
No
No
No
OpenCalcone Rust core, any host
Yes
Yes
Yes
Yes

Categories, not products — Excel and LibreOffice Calc remain our semantics and fidelity oracles, and we study IronCalc, calamine and Univer openly.

10 Honest status

Where it is, and what's next.

Delivered in capability-gated phases. The workbook has to be read, modeled, preserved, written back, laid out and rendered before a single cell is evaluated.

  1. Phase 0–1B
    Foundation, import and semantic writer
    Bounded XLSX reader, normalized model, preservation ledger, and a round-trip that is a gated semantic fixed point.
    Done
  2. Phase 1C–1D
    Grid layout and render
    Column and row geometry, merges, number-format display, display list, CPU raster and viewport virtualization.
    Done · glyph shaping pending
  3. Phase 1E
    Browser grid editor
    Canvas grid over the WebAssembly engine: selection, formatting, structural ops, undo and redo.
    Done
  4. Phase 2
    Formula and calc engine
    347 of the spec's 356 functions, dynamic arrays, LET and LAMBDA. The nine that are missing each need something this cannot have — a live OLAP cube, a COM server — and are named rather than counted. The incremental dependency graph and the sub-50 ms worst case are the remaining work.
    In progress
  5. Phase 3
    Spreadsheet features
    Conditional formatting, data validation, protection, tables and structured references, autofilter, print setup, charts and pivot tables — all shipped. A pivot built here still exports as its cells rather than as a live Excel pivot; that part of the writer is deliberately staged.
    Done · one gap named
  6. Phase 4–6
    SDK, collaboration, desktop, 1.0
    The SDK is published and takes a configuration; real-time collaboration runs on a clustered server with resume, presence and relay; the desktop shell ships for three platforms. What remains is API stability, the Helm chart, and support guarantees.
    In progress

Open the editor and start typing.

No sign-up, no upload, no build step. Bring an .xlsx and watch it round-trip — then take the same thing to your desktop, your servers or your own product.