Skip to main content

Witan spreadsheet CLI and Python SDK for coding agents

Project description

witan-cli

The spreadsheet toolkit for coding agents — edit, render, calculate, and lint Excel workbooks.

Documentation | How we built it

Install

Quick Install Script

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

From GitHub Releases

Download the latest artifacts from:

Example (macOS Apple Silicon):

curl -fsSL https://github.com/witanlabs/witan-cli/releases/latest/download/witan-darwin-arm64.tar.gz | tar -xz
install -m 0755 witan /usr/local/bin/witan

From PyPI

Install the bundled CLI and Python SDK from PyPI:

# one-shot run without permanent install
uvx witan --help

# persistent install
pip install witan

Python SDK example:

from witan import Workbook

with Workbook("report.xlsx") as wb:
    sheets = wb.list_sheets()
    tsv = wb.read_range_tsv("Summary!A1:F20")

Create and save a new workbook:

from witan import Workbook

with Workbook("model.xlsx", create=True) as wb:
    wb.add_sheet("Inputs")
    wb.set_cells([{"address": "Inputs!A1", "value": "Revenue"}])
    wb.save()

Async sessions are available for asyncio applications:

from witan import AsyncWorkbook

async with AsyncWorkbook("report.xlsx") as wb:
    cell = await wb.read_cell("Summary!A1")

Notebook and REPL sessions can use an explicit close instead of a context manager:

from witan import Workbook

wb = Workbook("report.xlsx")
tsv = wb.read_range_tsv("Summary!A1:F20")
wb.close()

In Jupyter/IPython, async sessions can use top-level await:

from witan import AsyncWorkbook

wb = AsyncWorkbook("report.xlsx")
cell = await wb.read_cell("Summary!A1")
await wb.close()

From Source

Requires Go (version from go.mod):

go install github.com/witanlabs/witan-cli@latest

Quick Start

# Authenticate (recommended)
witan auth login

# Render a range
witan xlsx render report.xlsx -r "Sheet1!A1:F20"

# Recalculate formulas
witan xlsx calc report.xlsx

# Lint formulas
witan xlsx lint report.xlsx

# Run JS against workbook
witan xlsx exec report.xlsx --expr 'await xlsx.readCell(wb, "Summary!A1")'

# Create a new workbook from scratch
witan xlsx exec model.xlsx --create --save --code 'await xlsx.addSheet(wb, "Inputs"); return true'

# Author a ListObject table in one call
witan xlsx exec model.xlsx --save --stdin <<'WITAN'
await xlsx.addListObject(wb, "Sheet1", {
  name: "SalesTable",
  ref: "A1:C4",
  showTotalsRow: true,
  columns: [
    { name: "Region", totalsRowLabel: "Total" },
    { name: "Sales", totalsRowFunction: "sum" },
    { name: "DoubleSales", calculatedColumnFormula: "=B2*2" }
  ],
  rows: [
    [{ value: "North" }, { value: 10 }, {}],
    [{ value: "South" }, { value: 20 }, {}]
  ]
})
return await xlsx.readRange(wb, "SalesTable")
WITAN

# Author a What-If Data Table block
witan xlsx exec model.xlsx --save --stdin <<'WITAN'
await xlsx.addDataTable(wb, "Sheet1", {
  type: "oneVariableColumn",
  ref: "E1:F4",
  columnInputCell: "H1",
  inputValues: [5, 10, 15],
  formulas: ["=H1*2"]
})
return await xlsx.getDataTable(wb, "Sheet1!E1:F4")
WITAN

# Author a chart from workbook data
witan xlsx exec dashboard.xlsx --save --stdin <<'WITAN'
await xlsx.addChart(wb, "Summary", {
  name: "Revenue",
  position: { from: { cell: "F2" }, to: { cell: "N18" } },
  groups: [
    {
      type: "column",
      series: [
        {
          name: { ref: "Data!B1" },
          categories: "Data!A2:A9",
          values: "Data!B2:B9"
        }
      ]
    }
  ],
  title: { text: "Revenue" },
  legend: { position: "right" }
})
await xlsx.previewStyles(wb, "Summary!F2:N18")
WITAN

What This CLI Covers

witan-cli exposes four spreadsheet commands:

  • witan xlsx calc
  • witan xlsx exec
  • witan xlsx lint
  • witan xlsx render

The PyPI package also exposes witan.Workbook and witan.AsyncWorkbook, backed by witan xlsx rpc subprocess sessions. Public SDK methods use snake_case names matching the xlsx exec operation surface, such as read_range_tsv, find_cells, sweep_inputs, set_cells, add_chart, and set_conditional_formatting.

The lower-level Witan spreadsheet runtime supports broader workbook operations; this CLI focuses on the four agent-facing workflows above.

Auth, Config, and Modes

Authentication can be done via witan auth login, --api-key, or WITAN_API_KEY. Use witan auth status to inspect the active credential, validation state, and selected organization.

Environment variables:

  • WITAN_API_KEY: API key (optional when using witan auth login)
  • WITAN_API_URL: API base URL override (default: https://api.witanlabs.com)
  • WITAN_STATELESS: set 1 or true to force stateless mode
  • WITAN_CONFIG_DIR: override config directory (default: ~/.config/witan)
  • WITAN_MANAGEMENT_API_URL: management API override for auth login/token exchange

Modes:

  • Stateful (default when authenticated): uploads workbook revisions and reuses them across commands
  • Stateless (--stateless or WITAN_STATELESS=1): sends workbook bytes on every request, no server-side file reuse

In stateful mode, load-balancer affinity cookies are persisted at ~/.config/witan/cookies.json or $WITAN_CONFIG_DIR/cookies.json when WITAN_CONFIG_DIR is set.

witan xlsx exec --create always uses the stateless exec endpoint and only supports new .xlsx targets.

Limits:

  • Workbook inputs must be <= 25MB.

Development

# build local binary
make build

# run test suite
make test

# static checks
make vet
make format-check

# build release artifacts into dist/
make dist VERSION=v0.1.0

# build PyPI wheels (stable tags only)
make pypi-wheels VERSION=v0.1.0

The local binary is written to ./witan.

Release Process

Releases are handled by GitHub Actions:

  • Publish workflow: .github/workflows/witan-cli-release.yml (triggered by pushing v* tags)
  • Artifacts:
    • witan-darwin-arm64.tar.gz
    • witan-darwin-amd64.tar.gz
    • witan-linux-amd64.tar.gz
    • witan-linux-arm64.tar.gz
    • witan-windows-amd64.zip
    • witan-windows-arm64.zip
    • witan-install.sh
    • witan-*.whl (PyPI wheels for supported platforms; stable tags only)
    • witan-checksums.txt

PyPI publishing:

  • Stable tags (vX.Y.Z) publish wheels to PyPI using GitHub OIDC trusted publishing.
  • Pre-release tags (for example v1.2.3-rc.1) skip PyPI publish.

GitHub release publishing:

  • The workflow uploads artifacts directly to the matching GitHub Release tag.
  • If the release already exists (for example, created in the GitHub UI), assets are attached with --clobber.

Cutting a release (UI-driven):

  1. Add release notes under ## Unreleased in CHANGELOG.md.
  2. Create a GitHub Release in the UI with a new tag vX.Y.Z (or prerelease tag vX.Y.Z-suffix).
  3. Tag push triggers Witan CLI Release.
  4. The workflow builds artifacts, attaches them to the GitHub Release, and publishes to PyPI for stable tags.
  5. On successful release, CI runs scripts/roll-changelog.sh, pushes the changelog update to a chore/changelog-release-X.Y.Z branch, and opens a PR into the default branch.
  6. For stable tags, verify witan==X.Y.Z on PyPI, witan --version, python -m witan --version, and from witan import Workbook, AsyncWorkbook.

Manual git tag ... && git push ... is equivalent to UI tag creation and triggers the same workflow.

CI

Go and Python CI runs in .github/workflows/golang.yml on pushes to main and pull requests. The workflow runs go test, go vet, pytest, mypy, and python -m compileall python/witan.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

witan-0.10.0-py3-none-win_arm64.whl (3.4 MB view details)

Uploaded Python 3Windows ARM64

witan-0.10.0-py3-none-win_amd64.whl (3.8 MB view details)

Uploaded Python 3Windows x86-64

witan-0.10.0-py3-none-musllinux_1_2_x86_64.whl (3.7 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

witan-0.10.0-py3-none-musllinux_1_2_aarch64.whl (3.3 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

witan-0.10.0-py3-none-manylinux_2_17_x86_64.whl (3.7 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

witan-0.10.0-py3-none-manylinux_2_17_aarch64.whl (3.3 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

witan-0.10.0-py3-none-macosx_11_0_arm64.whl (3.4 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

witan-0.10.0-py3-none-macosx_10_15_x86_64.whl (3.7 MB view details)

Uploaded Python 3macOS 10.15+ x86-64

File details

Details for the file witan-0.10.0-py3-none-win_arm64.whl.

File metadata

  • Download URL: witan-0.10.0-py3-none-win_arm64.whl
  • Upload date:
  • Size: 3.4 MB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for witan-0.10.0-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 d38866338d8973fc3e381fdc3e98a2cc9454f83f18770b9db09e7308173c81ab
MD5 79d7d097f9e8387c98618fafc6a62190
BLAKE2b-256 e483b69f82532cb807a5c3d990d7362759af7a7b29d37aa2aae1005fec800807

See more details on using hashes here.

Provenance

The following attestation bundles were made for witan-0.10.0-py3-none-win_arm64.whl:

Publisher: witan-cli-release.yml on witanlabs/witan-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file witan-0.10.0-py3-none-win_amd64.whl.

File metadata

  • Download URL: witan-0.10.0-py3-none-win_amd64.whl
  • Upload date:
  • Size: 3.8 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for witan-0.10.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 a3574c430e9566771506cd130283149a07ca937bbd8a4eaf93394d43be6b447b
MD5 78c5ee52cbdf38866641a8b5a94fb77f
BLAKE2b-256 8e756a5cdc29cdf5a6a45ef21bce0b97699b863d5acea6617af8b73289070d51

See more details on using hashes here.

Provenance

The following attestation bundles were made for witan-0.10.0-py3-none-win_amd64.whl:

Publisher: witan-cli-release.yml on witanlabs/witan-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file witan-0.10.0-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for witan-0.10.0-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 8bfe5f752c9215c5d01b2fc6de45c74d4dbf0df0dbddec7379137eba5bc26dcc
MD5 2dfbf402c3859e74b8e35f95e18bbc18
BLAKE2b-256 c3564c95d9149ac8fdae8318fc274e8d1d0c477f7a9b13a4cfb21bd5571cc083

See more details on using hashes here.

Provenance

The following attestation bundles were made for witan-0.10.0-py3-none-musllinux_1_2_x86_64.whl:

Publisher: witan-cli-release.yml on witanlabs/witan-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file witan-0.10.0-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for witan-0.10.0-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 fe38c4be3b6663070c38297d1059ddc1d0bcb54aa1b413cdc07eb40b04efeadf
MD5 d8499023bad230612429116e7ee8ba5d
BLAKE2b-256 17df5025356936a4412b46b23013e3197fcdf0a00605983f87c89accb1c6eedc

See more details on using hashes here.

Provenance

The following attestation bundles were made for witan-0.10.0-py3-none-musllinux_1_2_aarch64.whl:

Publisher: witan-cli-release.yml on witanlabs/witan-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file witan-0.10.0-py3-none-manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for witan-0.10.0-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 36383dd33b391a100e56fc8601224480bf6d320b4eba887e27f744e8ef899823
MD5 de4ac2cff1336c96e56e7aa2782a4dc4
BLAKE2b-256 45c0c60752a98fe77d242b6d1fab7b9fa1add0f9f5bebc43053448b2fc6d42c2

See more details on using hashes here.

Provenance

The following attestation bundles were made for witan-0.10.0-py3-none-manylinux_2_17_x86_64.whl:

Publisher: witan-cli-release.yml on witanlabs/witan-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file witan-0.10.0-py3-none-manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for witan-0.10.0-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 989546e51d50812203454a1754ebdea3fbb148eeba8a8a1ae72cf457efc2637b
MD5 8d70dfc3aea3d993078ea4929406217f
BLAKE2b-256 19f7b61321adbe226d5b23da22354f16c8c39f8ce1dfc9734a3e7e8477f48d0e

See more details on using hashes here.

Provenance

The following attestation bundles were made for witan-0.10.0-py3-none-manylinux_2_17_aarch64.whl:

Publisher: witan-cli-release.yml on witanlabs/witan-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file witan-0.10.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for witan-0.10.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 13c4bd44c3a292f6bae5aa1731c3311a22989f9a86a067a0406c2b24e40b7144
MD5 5b72b1c98c4e93bc28d6d97734751855
BLAKE2b-256 8d951ccc34687e1da8e52de070dce3e239d1891dca0635b7245266d0727f9c4a

See more details on using hashes here.

Provenance

The following attestation bundles were made for witan-0.10.0-py3-none-macosx_11_0_arm64.whl:

Publisher: witan-cli-release.yml on witanlabs/witan-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file witan-0.10.0-py3-none-macosx_10_15_x86_64.whl.

File metadata

File hashes

Hashes for witan-0.10.0-py3-none-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 4d719d0d7d31c8a12054122cbd54827cd3758ff5badadfabfb3ef28ff7faa7da
MD5 97e93880686a7631550310a4093d0dd1
BLAKE2b-256 99cee224f9178e44063e6b84d65ef9da6e30b25e5d175021a2e8ba71caf5e3a6

See more details on using hashes here.

Provenance

The following attestation bundles were made for witan-0.10.0-py3-none-macosx_10_15_x86_64.whl:

Publisher: witan-cli-release.yml on witanlabs/witan-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page