CLI

The SheetXL CLI is a command-line tool for automating spreadsheet operations, running scripts, and managing workbooks programmatically.
Installation
The easiest way to use the SheetXL CLI is to run it directly, with no permanent installation. All you need is Node.js (v22 or later; v24 recommended).
Hand it to your agent, or open your terminal and run it yourself:
- agent
- npx
- pnpm
- npm
Paste this into your agent (Claude Code, Codex, Cursor, …), in the folder with your spreadsheets:
I would like to work with my spreadsheet files from the terminal.
Please use SheetXL:
npx -y skills add sheetxl/skills -g --all
Read the SheetXL skill, then ask me what I need before you build.
npx sheetxl
pnpm dlx sheetxl
npm install -g sheetxl
sheetxl
A permanent install; afterwards the command is just sheetxl.
Run by hand, it starts an interactive session, pre-loaded with the SheetXL SDK.
SheetXL>
Type .help in the session for a list of commands.
Usage
sheetxl [options] [workbook]
The workbook is the trailing positional argument. Omit it and you get a blank workbook. One rule decides everything else:
Give it code and it runs, prints, and exits. Give it none and you get an interactive session.
Code means -e, -f, or source piped on stdin.
| You type | You get |
|---|---|
sheetxl | interactive session, blank workbook |
sheetxl book.xlsx | interactive session, wb loaded |
sheetxl -e "wb.getWorksheet()" book.xlsx | evaluate, print, exit |
sheetxl -f script.ts book.xlsx | run a script file, exit |
sheetxl -i -f setup.ts book.xlsx | run the script, then stay interactive |
sheetxl book.xlsx --out book.csv | convert; no code needed |
sheetxl book.xlsx < script.ts | run code from stdin, exit |
If you know duckdb or sqlite3, you already know this shape. The difference is that SheetXL takes TypeScript where they take SQL. And it is the same TypeScript for asking a question and for changing the workbook, so nothing distinguishes a "query" from a "script."
Reading
-e takes an expression, and the value of its final expression is rendered:
npx sheetxl -e "wb" book.xlsx # workbook report
npx sheetxl -e "wb.getWorksheet('Sales')" book.xlsx # sheet report
npx sheetxl -e "wb.getRange('B2:D9').getStats()" book.xlsx # min/max/mean/…
await is implicit. Never write it. wb, log, warn, error, and args are ambient.
Returning a subject describes it, so there is no separate describe or query command to learn. Reports render as markdown by default; use --json for the raw value.
When the code is more than one line, or shell quoting gets awkward, pipe it in instead:
npx sheetxl book.xlsx --save <<'EOF'
const sheet = wb.getWorksheet();
sheet.getRange('B2').setValue('42%');
sheet.getRange('B3').setValue('=SUM(B1:B2)');
EOF
Writing
Nothing is written unless you ask.
npx sheetxl -e "wb.getRange('B2').setValue('42%')" book.xlsx --save # in place
npx sheetxl -e "wb.getRange('B2').setValue('42%')" book.xlsx --out new.xlsx # elsewhere
After a write, the CLI prints what changed (Changed:, Dependents:, …). Pass --no-delta to skip that.
Converting
Name a workbook and an output and the CLI converts between formats, with no code at all. The format comes from the extension: .xlsx, .sxl (SheetXL's native format, smaller and faster to load), .csv, and .json.
npx sheetxl book.xlsx --out book.sxl
npx sheetxl data.csv --out data.xlsx --in.csv.delimiter=";"
--in.<key>=<value> and --out.<key>=<value> pass format options, such as a CSV delimiter.
Executing Scripts
For automation and more complex tasks, pass a local script file with -f. It runs within the SheetXL environment with the SDK available, and it is repeatable: each script receives the workbook the previous one left behind.
npx sheetxl -f path/to/your/script.ts book.xlsx
npx sheetxl -f normalize.ts -f summarize.ts book.xlsx --save
A file with no default export behaves exactly like -e. A file with a default export is handed the run context, and its return value is the result. These are runner scripts; that page covers the context, arguments, and return values in full.
Everything after -- reaches the script as args:
npx sheetxl -f summarize.ts book.xlsx -- --sheet Q3
Interactive Sessions
Starting with no code drops you into an interactive session. Name a workbook and it arrives as wb:
npx sheetxl book.xlsx
Start with no workbook and the session also loads @sheetxl/sdk and @sheetxl/io, so you can build one from scratch and save it:
wb = new Workbook();
wb.getRange('A1').setValues([[1]]);
write('myWorkbook.xlsx', wb);
Two helpers exist only in the session: read('<file-or-url>') loads a workbook and write(file [, wb]) saves one. Promises are awaited for you.
Dot commands control the session itself:
| Command | What it does |
|---|---|
.help | Lists every dot command. |
.api | The API help screen. |
.md [expr] | Renders a result as markdown. |
.write <file> | Saves the session's workbook. |
.grep <pattern> | Searches the open workbook (every read command is also a dot command). |
.exit | Leaves the session. |
Use -i to run code first and stay in the session:
npx sheetxl -i -f fixtures.ts book.xlsx
See our full SDK API Documentation for a complete list of all available classes and methods.
Options
-h prints the short help below. --help prints everything.
| Option | What it does |
|---|---|
-e, -c <code> | Inline code. The final expression is rendered. Repeatable. |
-f <script> | A script file. Repeatable; scripts chain on the same workbook. |
-i, --interactive | Stay in an interactive session after the code runs. |
--out <file> | Write the workbook here. - writes to stdout for piping. |
--save | Write back to the workbook that was opened. |
--no-delta | Do not print what a write changed. |
--json | Print the result as JSON instead of a rendered report. |
--in <file> | The input workbook, as an option instead of the positional. |
--in.<key>=<value> | Format options for reading, such as --in.csv.delimiter=";". |
--out.<key>=<value> | Format options for writing, such as --out.format=csv. |
--md.<key>=<value> | Report options: --md.features=fill,borders picks the sections, --md.mode=value shows full-precision values. |
-- [args...] | Everything after -- is passed to the script as args. |
-v | Prints the CLI, engine, and Node versions. |
Commands
Commands cover the things that are not "operate on this workbook."
npx sheetxl grep "Q[1-4] Total" book.xlsx # search cell contents
npx sheetxl info # engine readiness and environment
npx sheetxl mcp # run as an MCP server
npx sheetxl help # help for any command
| Command | What it does |
|---|---|
grep <pattern> [workbook] | Finds cells by content. The pattern is a regular expression; -F makes it literal, -i ignores case, --fields picks what to search (display text, formulas, comments, shapes, charts, names). |
info | Checks the engine and reports the environment: versions, skills, MCP status. |
setup agent | Prints how to register the MCP server and skills with each AI client, and which are already registered. Installs nothing. |
mcp | Runs the MCP server on stdio, for AI clients. |
compile <files...> | Typechecks scripts without running them, and optionally emits compiled modules with --out. Non-zero exit on errors, so it works as a CI gate. |
screenshot [file] | Renders a range to a PNG, as the app shows it. |
license | Prints the current license. license activate [key] stores a key (or signs you in through the browser when no key is given); license deactivate removes it. |
config | Gets, sets, and lists CLI settings. |
fonts | Adds, lists, and removes the fonts SheetXL measures text with. |
resources | Manages locale packs and other runtime resources. |
skills | Lists and prints the agent reference documents shipped with this install. |
help [command] | Help for the CLI or one command. |
Activate Your License
To store a license key for every future run on this machine:
npx sheetxl license activate YOUR_LICENSE_KEY_HERE
Omit the key to sign in through your browser instead. In CI, set the SHEETXL_LICENSE_KEY environment variable rather than activating.
