Quickstart

Install Witan, create a workbook, and run the main verification commands. No signup or API key is required for the personal tier.

1. Install

Install the standalone binary with the quick install script:

curl -fsSL https://witanlabs.com/install.sh | sh

This detects your platform and installs the witan binary to /usr/local/bin by default. For Windows, sandboxed environments, or manual release downloads, see the CLI Scripting page.

Alternatively, use npm or PyPI when those runtimes fit your environment better:

# npm one-shot
npx witan --help

# npm project install
npm install witan

# PyPI one-shot
uvx witan --help

# PyPI persistent install
pip install witan

The npm package includes the CLI and JavaScript SDK. The PyPI package includes the CLI and Python SDK.

2. Install the agent skills

If you use Witan through Claude Code, Codex, Deep Agents, or another skills-aware agent, install the Witan skills in your project:

npx skills add witanlabs/witan-cli

This adds the Witan skills — for spreadsheet work, witan-xlsx and witan-read-source. Agent workflows should install them before working with Witan so the agent has commands, flags, and workbook workflows in context. See Agent Skills for platform-specific notes.

3. Verify

witan --version

If the command prints a version string, the CLI is installed.

4. Create a workbook

Create a small workbook in the current directory:

witan xlsx exec quickstart.xlsx --create --save --stdin <<'WITAN'
await xlsx.addSheet(wb, "Summary")
await xlsx.setCells(wb, [
  { address: "Summary!A1", value: "Metric" },
  { address: "Summary!B1", value: "Q1" },
  { address: "Summary!C1", value: "Q2" },
  { address: "Summary!A2", value: "Revenue" },
  { address: "Summary!B2", value: 1200, format: "$#,##0" },
  { address: "Summary!C2", value: 1500, format: "$#,##0" },
  { address: "Summary!A3", value: "Costs" },
  { address: "Summary!B3", value: 700, format: "$#,##0" },
  { address: "Summary!C3", value: 850, format: "$#,##0" },
  { address: "Summary!A4", value: "Profit" },
  { address: "Summary!B4", formula: "=B2-B3", format: "$#,##0" },
  { address: "Summary!C4", formula: "=C2-C3", format: "$#,##0" }
])
return await xlsx.readRange(wb, "Summary!A1:C4")
WITAN

The workbook is exposed inside the JavaScript runtime as the global wb. Methods on xlsx do the work. The result is returned as JSON, and --save writes quickstart.xlsx to disk.

--create refuses to overwrite an existing file. If you rerun this step, delete quickstart.xlsx first or choose a different filename.

5. Read a cell

witan xlsx exec quickstart.xlsx --expr 'await xlsx.readCell(wb, "Summary!C4")'

This reads the Q2 profit formula result from the workbook you just created.

6. Render a range

witan xlsx render quickstart.xlsx -r "Summary!A1:C4"

The command prints the output image path and render metadata:

/var/folders/xx/.../witan-render-123456.png
Summary!A1:C4 | ~384×120px | dpr=2

7. Recalculate

witan xlsx calc quickstart.xlsx

By default this runs a full-workbook calculation, writes updated cached formula values back to disk, and reports formula errors. Use --verify for a non-mutating check, or --range to seed recalculation from specific ranges while still following downstream dependents.

You do not need a separate calc step after normal exec writes. Write APIs such as xlsx.setCells recalculate affected formulas before returning.

8. Lint

witan xlsx lint quickstart.xlsx

Fifteen rules check for issues recalculation can miss, including overlapping SUMs, unsorted lookups, mixed currencies, clipped display values, and overlapping objects.

Combine operations in one script

exec can chain workbook operations into one request. This example discovers structure, looks up a value by label, writes it, and verifies the result:

witan xlsx exec quickstart.xlsx --save --stdin <<'WITAN'
const summary = await xlsx.describeSheet(wb, "Summary")
const tables = Object.values(summary.tables)
const table = tables[0]
if (!table) throw new Error("No table detected on Summary")

const [q2Revenue] = await xlsx.tableLookup(wb, {
  table: table.address,
  rowLabel: "Revenue",
  columnLabel: "Q2"
})
if (!q2Revenue) throw new Error("Q2 revenue not found")

const result = await xlsx.setCells(wb, [{
  address: q2Revenue.address,
  value: 1650,
  format: "$#,##0"
}])

const profit = await xlsx.readCell(wb, "Summary!C4")
const lint = await xlsx.lint(wb, { rangeAddresses: [table.address] })
return { updated: q2Revenue.address, profit: profit.text,
         errors: result.errors, warnings: lint.total }
WITAN

The --save flag persists writes to the file on disk. Without it, exec is non-persistent by default: your script can modify the live workbook session, recalculate, lint, and inspect the result, but the local workbook file is not overwritten.

Next steps

  • Concepts — understand the workbook handle, sandbox runtime, and access tracking before you build more.
  • CLI Scripting, render, calc, lint — full reference for each command.
  • Skills — platform-specific notes for agent skill installation.