The spreadsheet toolkit for coding agents — edit, render, calculate, and lint Excel workbooks.
Documentation | How we built it
curl -fsSL https://witanlabs.com/agents/install.sh | shDownload 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/witanInstall from PyPI (recommended for sandboxed agent environments):
# one-shot run without permanent install
uvx witan --help
# persistent install
pip install witanRequires Go (version from go.mod):
go install github.com/witanlabs/witan-cli@latest# 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 'wb.sheet("Summary").cell("A1").value'witan-cli currently exposes four spreadsheet commands:
witan xlsx calcwitan xlsx execwitan xlsx lintwitan xlsx render
The lower-level Witan spreadsheet runtime supports broader workbook operations; this CLI focuses on the four agent-facing workflows above.
Authentication can be done via witan auth login, --api-key, or WITAN_API_KEY.
Environment variables:
WITAN_API_KEY: API key (optional when usingwitan auth login)WITAN_API_URL: API base URL override (default:https://api.witanlabs.com)WITAN_STATELESS: set1ortrueto force stateless modeWITAN_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 (
--statelessorWITAN_STATELESS=1): sends workbook bytes on every request, no server-side file reuse
Limits:
- Workbook inputs must be
<= 25MB.
# 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.0The local binary is written to ./witan.
Releases are handled by GitHub Actions:
- Publish workflow:
.github/workflows/witan-cli-release.yml(triggered by pushingv*tags) - Artifacts:
witan-darwin-arm64.tar.gzwitan-darwin-amd64.tar.gzwitan-linux-amd64.tar.gzwitan-linux-arm64.tar.gzwitan-windows-amd64.zipwitan-windows-arm64.zipwitan-install.shwitan-*.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):
- Add release notes under
## UnreleasedinCHANGELOG.md. - Create a GitHub Release in the UI with a new tag
vX.Y.Z(or prerelease tagvX.Y.Z-suffix). - Tag push triggers
Witan CLI Release. - The workflow builds artifacts, attaches them to the GitHub Release, and publishes to PyPI for stable tags.
- On successful release, CI runs
scripts/roll-changelog.sh, pushes the changelog update to achore/changelog-release-X.Y.Zbranch, and opens a PR into the default branch. - For stable tags, verify
witan==X.Y.Zon PyPI andwitan --version.
Manual git tag ... && git push ... is equivalent to UI tag creation and triggers the same workflow.
Go CI runs in .github/workflows/golang.yml on pushes to main and pull requests.