This page ships a Markdown twin for AI tools.

Guides

Sheets docs

Install @texuli/sheets, load a workbook, evaluate formulas, show the grid. In development. Owned formula engine.

Back to overview

What Sheets is

Sheets is an embeddable spreadsheet: @texuli/sheets holds an owned formula engine (a linear-time parser into the @texuli/core/expression AST, 54 documented functions, a dependency graph with incremental recalculation), a framework-free workbook model, CSV import and export, and an accessible Svelte 5 grid view. The package is published as 0.18.0 and is **in development** (pre-1.0). Pin the exact version or use ^0.17.0.

It is not a hosted spreadsheet service. Collaboration, localized formula display and native (Kotlin) evaluation are planned, not shipped. The host app stores the workbook.

The technical docs you are reading live at /guides/solutions/sheets/.

What you get

  • A validated workbook as data (format: "texuli-sheet", formatVersion: 1).
  • An owned formula language: no INDIRECT, OFFSET, LAMBDA or RAND.
  • Structural edits that rewrite references.
  • CSV in and out that keeps formula injection neutralized.
  • SheetView over the @texuli/data grid editing layer.

There is no HTML sink. Values paint as text.

Install

Svelte 5 (^5.57.2) is a peer of @texuli/sheets. Import @texuli/tokens/base.css once.

npm install @texuli/sheets

Load and show a sheet

Sheets from a file, an agent or a share link go through loadUntrustedSheet first.

<script lang="ts">
  import { loadUntrustedSheet } from '@texuli/sheets/model';
  import { SheetView } from '@texuli/sheets/view';
  import '@texuli/tokens/base.css';

  let { json }: { json: string } = $props();
  const loaded = loadUntrustedSheet(json);
  let sheet = $state(loaded.ok ? loaded.sheet : null);
</script>

{#if sheet}
  <SheetView bind:sheet now={() => Date.now()} />
{/if}

Drive the workbook

import { createWorkbook, displayValue, loadUntrustedSheet } from '@texuli/sheets/model';

const loaded = loadUntrustedSheet(json);
if (loaded.ok) {
  const workbook = createWorkbook(loaded.sheet, { now: () => Date.now() });
  workbook.setInput('costs', 0, 1, 150);
  displayValue(workbook.value('costs', 2, 1));
  const next = workbook.toDocument();
}

Workbook

The canonical document is data: format, formatVersion, optional meta, and sheets. Each tab has a stable id, a name formulas use, rows, columns and cells keyed by A1 address. validateSheet refuses unknown members, sizes past SHEET_LIMITS, control and bidi characters, and formulas that do not parse. It never throws.

loadUntrustedSheet from @texuli/sheets/model bounds work then validates. createWorkbook keeps computed values current; setInput recalculates only dependents.

import { createWorkbook, loadUntrustedSheet, validateSheet } from '@texuli/sheets/model';

Owned formula engine

parseFormula and evaluateFormula live in @texuli/sheets/formula. The parser is linear-time into the @texuli/core/expression AST. Fifty-four documented functions sit in a closed table. Evaluation is bounded: overruns are #LIMIT!, cycles are #CYCLE!. TODAY and NOW read the clock the host passes.

import { evaluateFormula, parseFormula } from '@texuli/sheets/formula';

const parsed = parseFormula('=SUM(B2:B4)');

Most hosts never call these directly: createWorkbook parses, binds and evaluates every cell.

CSV

@texuli/sheets/csv parses and writes CSV, imports as a sheet and exports a sheet. Import keeps =… fields as text unless the caller opts in. Export neutralizes formula injection (=, +, -, @, tab, carriage return).

Sheet view

SheetView from @texuli/sheets/view is the accessible spreadsheet with tabs and a formula bar. It sits on the @texuli/data grid editing layer. Bind the document with bind:sheet and pass now so TODAY and NOW have a clock.

The cell editor loads lazily on the first Enter or F2.

Player host

createSheetPlayerHost from @texuli/sheets/host is the sheet half of the player's sheetHost seam. Pass it as sheetHost on Player. Agents emit sheets as data through the catalog spreadsheet id; checkSheetDraft from @texuli/sheets/model is the draft check the catalog injects as checkSheet.

Grid

The view is the data grid's APG grid with one tab stop, arrow-key navigation, Enter or F2 to edit, Escape to cancel, undo and redo, and TSV copy and paste. Columns are named by their letters. The first column holds row numbers. The formula bar is a named group. Formula errors are announced.

The cell editor is named by its column letter, for example textbox B. Host tests await it before typing.

No HTML

Values paint as text. There is no {@html}, innerHTML, eval or new Function.

Status

Sheets is **in development**. @texuli/sheets is on npm as 0.18.0. Under 0.x a new minor may break. Native evaluation is planned, not built.

Not built

  • Collaboration on @texuli/document/sync
  • Localized formula display
  • Native (Kotlin) evaluation
  • A hosted spreadsheet or storage service

Hard limits include 10,000-item ranges and 32,768-character strings. The formula language has no INDIRECT, OFFSET, LAMBDA or RAND.

Untrusted sheets

A sheet from an agent, a file or a share link is untrusted data. Use loadUntrustedSheet from @texuli/sheets/model before any deep work. validateSheet and checkSheetDraft return diagnostics instead of throwing.

Catalog and skill

Agents emit a spreadsheet catalog node (blueprint spec 0.8.0). @texuli/player paints it through createSheetPlayerHost. The Texuli skill covers the package under skills/texuli/build-ui/SKILL.md.

Do not invent a hosted runner or an MCP operation that is not in @texuli/tools. Formulas stay in the closed language; they never reach the host except TODAY and NOW through the clock the host passes.