Skip to main content

Agent-first CLI for Excel workbooks

Project description

xl

Agent-first CLI for Excel workbooks (.xlsx / .xlsm)

A transactional spreadsheet execution layer that lets AI agents and humans inspect, plan, validate, and apply workbook changes deterministically — like terraform for Excel.

xl wb inspect -f budget.xlsx          # discover structure
xl plan add-column -f budget.xlsx \   # generate a plan (non-mutating)
   -t Sales -n Margin \
   --formula "=[@Revenue]-[@Cost]" \
   --out plan.json
xl validate plan -f budget.xlsx \     # check before applying
   --plan plan.json
xl apply -f budget.xlsx \             # preview changes
   --plan plan.json --dry-run
xl apply -f budget.xlsx \             # apply with safety backup
   --plan plan.json --backup
xl verify assert -f budget.xlsx \     # confirm expected state
   --assertions '[{"type":"table.column_exists","table":"Sales","column":"Margin"}]'

Every command returns a structured JSON envelope:

{
  "ok": true,
  "command": "table.ls",
  "result": [...],
  "errors": [],
  "warnings": [],
  "metrics": { "duration_ms": 42 }
}

No Excel installation required — works entirely with openpyxl.


Features

  • Inspect — sheets, tables, named ranges, fingerprints, lock status
  • Read — cell values, range statistics (min/max/mean/sum/count/stddev), formula search by regex
  • Query — SQL over table data via DuckDB (SELECT Region, SUM(Sales) FROM Sales GROUP BY Region)
  • Mutate — add/delete columns, append rows, set cells/formulas, number formats, column widths, freeze panes
  • Patch plans — generate JSON plans, compose multi-step plans, validate before applying
  • Apply — execute plans with --dry-run preview and --backup safety copy
  • Verify — post-apply assertions (table.column_exists, cell.value_equals, row_count.gte, ...)
  • Diff — cell-level comparison between two workbook files
  • Lint — detect volatile functions, broken references, formula anti-patterns
  • Workflows — multi-step YAML pipelines with xl run
  • Server mode — stdio JSON server for agent tool integration (MCP/ACP)

Safety rails

All mutating commands include built-in protections:

Feature Description
--dry-run Preview every change without writing to disk
--backup Timestamped .bak copy before any write
Fingerprint conflict detection Plans record the file's xxhash; apply rejects if the workbook changed since the plan was created
Exclusive file locking Sidecar .xl.lock prevents concurrent mutations; --wait-lock N retries for N seconds
Formula protection Refuses to overwrite existing formulas unless --force-overwrite-formulas is set
Policy files Optional xl-policy.yaml for protected sheets, ranges, mutation thresholds, and command restrictions

Installation

Requires Python 3.12+ and uv.

From PyPI (recommended)

uv tool install xl-agent-cli

# Verify
xl version
xl --help

One-shot with uvx

uvx --from xl-agent-cli xl --help

Local development install

git clone https://github.com/ThomasRohde/xl-cli.git
cd xl-cli
uv sync

# Verify
uv run xl version
uv run xl --help

Global install from source

git clone https://github.com/ThomasRohde/xl-cli.git
cd xl-cli
uv tool install --from . xl-agent-cli

If xl is not found, open a new terminal so your PATH refreshes.


Quick start

1. Inspect a workbook

xl wb inspect -f data.xlsx

Returns sheets, tables (with columns and row counts), named ranges, and a fingerprint hash.

2. List tables

xl table ls -f data.xlsx

3. Query with SQL

xl query -f data.xlsx \
  --sql "SELECT Region, SUM(Revenue) as Total FROM Sales GROUP BY Region ORDER BY Total DESC"

4. Add a calculated column (safe workflow)

# Generate a plan (does NOT modify the workbook)
xl plan add-column -f data.xlsx -t Sales -n GrossMarginPct \
  --formula "=[@GrossMargin]/[@Revenue]" \
  --out plan.json

# Validate the plan
xl validate plan -f data.xlsx --plan plan.json

# Preview what would change
xl apply -f data.xlsx --plan plan.json --dry-run

# Apply for real with backup
xl apply -f data.xlsx --plan plan.json --backup

# Verify the result
xl verify assert -f data.xlsx \
  --assertions '[{"type":"table.column_exists","table":"Sales","column":"GrossMarginPct"}]'

5. Format a report

xl format number -f report.xlsx --ref "Sales[Revenue]" --style currency --decimals 2
xl format width -f report.xlsx --sheet Sheet1 --columns A,B,C,D --width 15
xl format freeze -f report.xlsx --sheet Sheet1 --ref B2

6. Compare before and after

xl diff compare --file-a original.xlsx --file-b modified.xlsx

Command reference

Group Commands Description
xl wb inspect, create, lock-status Workbook metadata, creation, fingerprint, lock check
xl sheet ls, create, delete, rename Sheet lifecycle and management
xl table create, ls, add-column, append-rows, delete, delete-column Table operations
xl cell get, set Read/write individual cells
xl range stat, clear Range statistics and clearing
xl formula set, lint, find Set formulas, lint for issues, search by regex
xl format number, width, freeze Number formats, column widths, freeze panes
xl query (top-level) SQL queries over table data via DuckDB
xl plan show, add-column, create-table, set-cells, format, compose, delete-sheet, rename-sheet, delete-table, delete-column Generate and compose patch plans
xl validate workbook, plan, refs, workflow Validate health, plans, references, workflows
xl apply (top-level) Apply patch plans with --dry-run and --backup
xl verify assert Post-apply assertions
xl diff compare Cell-level workbook comparison
xl run (top-level) Execute multi-step YAML workflows
xl serve (top-level) stdio server for agent tool integration
xl guide (top-level) Machine-readable JSON orientation guide

Use xl <group> --help or xl <group> <command> --help for detailed usage.


Reference syntax

Commands that target cells, ranges, or table columns use ref syntax:

Pattern Example Usage
SheetName!Cell Sheet1!B2 Single cell
SheetName!Start:End Sheet1!A1:D10 Cell range
TableName[ColumnName] Sales[Revenue] Table column (formula/format)
=[@ColumnName] =[@Revenue]-[@Cost] Structured ref inside table formulas

Exit codes

Code Meaning
0 Success
10 Validation error (bad input, schema mismatch, invalid plan)
20 Protection error (protected range or sheet)
30 Formula error (overwrite blocked, parse failure)
40 Conflict (fingerprint mismatch — workbook changed)
50 IO error (file not found, locked, permission denied)
60 Recalculation error
70 Unsupported operation
90 Internal error

Agent integration

xl is designed to be driven by AI coding agents. Every command returns machine-parseable JSON, uses deterministic exit codes, and provides progressive discovery:

xl guide                        # full structured JSON orientation (start here)
xl --help                       # command group overview
xl table --help                 # group detail with examples
xl table add-column --help      # command detail with usage examples

Token-optimized help (TOON)

When an LLM drives the CLI, verbose Rich-formatted --help output wastes tokens. Set LLM=true to switch all help to TOON (Token-Oriented Object Notation) — a compact key:value format that cuts token usage by ~75%.

# Enable TOON for the session
export LLM=true          # bash/zsh
$env:LLM = "true"        # PowerShell

xl --help
name: xl
description: Agent-first CLI for reading transforming and validating Excel workbooks
options[2]:
  flag,type,required,default,help
  --version/-V,flag,false,false,Print version and exit.
  --human,flag,false,false,Force human-readable help (overrides LLM=true).
groups[11]:
  name,description
  cell,Read and write individual cell values.
  table,Table operations — list add columns append rows.
  ...

The --human flag overrides LLM=true for a single invocation:

xl --human --help         # Rich output even with LLM=true set
Condition Help format
Default (no env var) Rich/Markdown (human-readable)
LLM=true TOON (compact, token-optimized)
LLM=true + --human Rich/Markdown (override)

stdio server mode

For tool-use integrations (MCP, ACP, or custom):

xl serve --stdio

Reads JSON commands from stdin, writes JSON responses to stdout.


Development

# Install with dev dependencies
uv sync

# Run all tests
uv run pytest tests/ -v

# Run a specific test file
uv run pytest tests/test_cli.py -v

# Run the CLI directly
uv run xl --help

Tech stack

Component Library
Excel engine openpyxl
CLI framework Typer
Data models Pydantic v2
JSON serialization orjson
SQL queries DuckDB
Terminal output Rich
YAML parsing PyYAML
Structured logging structlog
File locking portalocker
Fingerprinting xxhash
Build hatchling

Project structure

src/xl/
├── cli.py                  # Typer CLI app, all command definitions
├── contracts/              # Pydantic models (ResponseEnvelope, PatchPlan, WorkflowSpec)
├── engine/                 # WorkbookContext, response dispatcher, verify, workflow runner
├── adapters/               # openpyxl engine, DuckDB queries
├── validation/             # Plan/workbook validators, policy engine
├── io/                     # Fingerprint, backup, atomic write, file locking
├── observe/                # Timer and event utilities
├── diff/                   # Workbook comparison logic
├── help/                   # TOON help output for LLM consumers
└── server/                 # stdio server mode

tests/                      # Unit, integration, golden, property, performance tests

License

MIT

Project details


Download files

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

Source Distribution

xl_agent_cli-1.6.1.tar.gz (181.4 kB view details)

Uploaded Source

Built Distribution

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

xl_agent_cli-1.6.1-py3-none-any.whl (73.5 kB view details)

Uploaded Python 3

File details

Details for the file xl_agent_cli-1.6.1.tar.gz.

File metadata

  • Download URL: xl_agent_cli-1.6.1.tar.gz
  • Upload date:
  • Size: 181.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for xl_agent_cli-1.6.1.tar.gz
Algorithm Hash digest
SHA256 693781814bac9093df9699085da99c4846246a7fee2737f0a0ab3e5cd3761424
MD5 c415420e8ede6d4aef2a02c703e5b358
BLAKE2b-256 c8105de6ea589adb9810e3e0ce143949021aaecfbbfcb91ffc0d9a14c0a4c894

See more details on using hashes here.

Provenance

The following attestation bundles were made for xl_agent_cli-1.6.1.tar.gz:

Publisher: pypi.yml on ThomasRohde/xl-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 xl_agent_cli-1.6.1-py3-none-any.whl.

File metadata

  • Download URL: xl_agent_cli-1.6.1-py3-none-any.whl
  • Upload date:
  • Size: 73.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for xl_agent_cli-1.6.1-py3-none-any.whl
Algorithm Hash digest
SHA256 980e5bae46c4d86ec2e123823ac64d148a2bd2ddfe3408d5b53d4118e9ab9a62
MD5 c7c3725409150d9e77d82cfaaaad28b9
BLAKE2b-256 1a02580f4f1486ec576f688def9be6c83997892875da0ee476cfc9ad8b23ceb8

See more details on using hashes here.

Provenance

The following attestation bundles were made for xl_agent_cli-1.6.1-py3-none-any.whl:

Publisher: pypi.yml on ThomasRohde/xl-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