Command-line interface¶
The abax command is the single entry point for every interface: the desktop GUI, the terminal UI, and a set of headless subcommands for viewing, converting, and querying spreadsheets without opening a window. This page documents every subcommand and flag, with example invocations and the output you can expect. Everything below works equally as abax … (the installed script) or python -m abax ….
See also: getting started · examples catalog · headless CLI example (a tested script you can run).
Synopsis¶
With no command, abax opens the GUI when a Qt binding is installed; if Qt is missing it opens the TUI when standard output is a terminal, and otherwise prints help. See getting-started.md for installation and the choice of Qt binding.
Global flags¶
These are parsed before any command and the first two are fast paths — they answer instantly and never import the GUI/TUI stacks or create an environment.
| Flag | Effect |
|---|---|
--version |
Print abax <version> and exit. |
--deps |
Print the optional-dependency status report (with the auto-install state and how many optional packages are present) and the config/data/cache/log directories, then exit. |
--macros PATH |
Load a macro file or directory. Repeatable. Adds its @macro commands and @register_function UDFs to every command (view, get, gui, tui, macro). |
--version¶
--deps¶
Reports each optional package as available or missing (with the fallback that kicks in when it is absent), plus external tools like pandoc, and prints the runtime directories.
$ abax --deps
optional dependencies:
[OK ] msgspec available
[-- ] openpyxl missing (fallback: ...)
[OK ] PySide6 available
...
[-- ] pandoc missing (fallback: built-in subset MathML)
config: C:\Users\you\AppData\Roaming\abax
data: C:\Users\you\AppData\Local\abax
cache: C:\Users\you\AppData\Local\abax\Cache
log: C:\Users\you\AppData\Local\abax\Logs
(The exact list and paths depend on your platform and what is installed.) See configuration.md for what each directory holds.
--macros PATH¶
# Load one macro file and one directory, then open the TUI with them available
abax --macros ./my_macros.py --macros ~/.config/abax/macros tui data.csv
Macros from CONFIG_DIR/macros/*.py are always discovered automatically; --macros adds more on top.
Commands¶
gui [file] — desktop GUI¶
Launch the Qt GUI, optionally opening a file. This is also what runs when you give no command at all.
| Argument | Description |
|---|---|
file |
Optional spreadsheet to open (.csv, .tsv, .xlsx, .abax, .json, and more). |
Requires a Qt binding (gui or gui-pyqt extra). See gui-guide.md.
tui [file] — terminal UI¶
Launch the terminal UI, optionally opening a file.
abax tui # empty workbook
abax tui data.csv # open a file
abax tui --curses # force the SSH-safe curses front-end
| Argument / flag | Description |
|---|---|
file |
Optional spreadsheet to open. |
--textual |
Force the Textual front-end. |
--curses |
Force the curses front-end. |
Two front-ends, one behaviour. There are two views over the same editor —
so every key, : command, mode, and theme below works identically in either:
- Textual (default) — the richer view, used automatically when standard output is an interactive terminal that can drive it.
- curses — the SSH-safe, low-dependency fallback that degrades to
8-colour / monochrome. abax falls back to it automatically over SSH, on a
non-interactive/dumb terminal, or when Textual isn't installed. Force it with
--curses(some terminals and remote sessions render it more reliably).
The Textual front-end also supports the mouse: click a cell to place the cursor, click-drag to make a visual selection, and wheel-scroll to move the viewport (the cursor stays put). The curses fallback remains keyboard-only.
The TUI is modal and vi-flavoured. Navigate with h/j/k/l or the arrow
keys. Key features:
| Key / command | Action |
|---|---|
Enter / i / a |
Edit the current cell. Enter also works Excel-style (from navigation it starts editing; while editing it commits and steps down a row). Esc cancels an edit (keeps the old value); Backspace deletes (works over SSH too). |
Tab (insert mode) |
Complete the function/name at the cursor: a single match inserts NAME(; several first extend to the common prefix, then successive Tabs cycle through the candidates (wrapping) — any other keystroke resets the cycle. The candidate list and an argument hint show on the status line as you type |
Tab (: line) |
Complete the command name (aliases included): a single match completes with a trailing space; several extend to the common prefix and list the candidates on the status line. :theme <partial> also completes theme names |
| Typing a formula | Every cell/range the formula references is live-highlighted in the grid as you type — per-reference colour tints in Textual (five colours cycling, one stable colour per distinct reference), a single tint in the curses fallback. A huge range costs only the visible viewport |
PageUp / PageDown / Home / End |
Page the viewport up/down; jump to the first / last used column of the row |
u / Ctrl-R |
Undo / redo (also :undo / :redo) — destructive actions checkpoint first |
:q / :q! |
Quit (:q refuses on unsaved edits; :q!/:Q! force-quit) |
:w [path] |
Write; with no path an untitled sheet saves to ./untitled_workbook.abax |
:trace [deps] [N] |
Show the current cell's precedents (or deps = dependents) as a scrollable ASCII dependency tree, up to depth N |
v / V |
Visual selection (cell range / whole rows); movement extends it, and the status line shows a live sum / count / average |
y · d / x |
In visual mode: yank the range · delete it (under an undo checkpoint) |
? |
Help overlay — a scrollable list of every key and command (also :help) |
:plot A1:A50 [B1:B50] |
Plot a sheet range as a braille chart (or :plot sin(x) -3 3 for an expression) |
:pivot rng idx col val [agg] |
Pivot / group-by a table into a new area of the sheet (:pt alias); e.g. :pivot A1:C99 A B sum |
:describe A1:A50 |
Descriptive stats (count / mean / median / stdev / min / max) in the status line; :describe full A1:A50 opens a scrollable overlay |
:!cmd |
Run a shell command; the current cell is exported as $ABAX_ACTIVE_CELL / $ABAX_SELECTION_RANGE / $ABAX_SELECTION_JSON / $ABAX_SELECTION_TSV |
:live [on\|off] |
Toggle network live data (=REST/=WEBSOCKET formulas); off by default |
:extern [on\|off] |
Toggle closed-workbook external references (=[Book.abax]Sheet1!A1); off by default |
:table [NAME] |
Name the current region as a structured table (top row = headers) so formulas can use NAME[Column]; no args lists tables |
:tasks |
List the active project's tasks (id, title, status, due) in a read-only scrollable overlay — the project on the active sheet, else the first registered one |
:critpath |
Show that project's CPM critical path — the zero-slack chain, one id title hop per row — in the same read-only overlay (a dependency cycle is reported on the status line) |
:auth HOST HEADER VALUE |
Set a session-only live-data request header for HOST (e.g. :auth api.x Authorization Bearer tok); :auth lists hosts, :noauth [HOST] clears. Never persisted |
: commands |
:w :q write/quit, :find, :rpn, :fmt, :py, :!cmd, :func, :sheet, :pivot, :describe, :trace, :live, :extern, … |
view file [--sheet NAME] — print a sheet¶
Render a spreadsheet as a plain-text table on standard output. Computed values are shown (formulas are evaluated), and columns are aligned with A, B, C … headers and 1, 2, 3 … row labels.
$ abax view data.csv
| A | B
--------------------
1 | Item | Price
2 | Apples | 3
3 | Pears | 4
4 | Cherries | 5
| Argument / flag | Description |
|---|---|
file |
Spreadsheet to open (.csv/.xlsx/.json/.abax/…). |
--sheet NAME |
Which sheet to print. Defaults to the workbook's active sheet. |
If the named sheet does not exist, abax prints no such sheet: NAME to standard error and exits with status 2. An empty sheet prints (empty).
convert src dst [--values] — convert between formats¶
Open src and save it to dst. The format is chosen entirely by the destination file extension (.csv, .tsv, .tab, .xlsx, .json, .abax, and the other formats abax supports).
$ abax convert data.csv data.xlsx
converted data.csv -> data.xlsx
$ abax convert book.xlsx out.csv
converted book.xlsx -> out.csv
| Argument / flag | Description |
|---|---|
src |
Source file to read. |
dst |
Destination file to write; its extension picks the output format. |
--values |
Write computed values instead of formulas. |
If the conversion cannot be performed — for example saving to .xlsx without the excel extra installed — abax prints the error to standard error and exits with status 3.
get file ref — one cell's value¶
Print the computed value of a single cell from the workbook's active sheet, formatted the way abax would display it.
| Argument | Description |
|---|---|
file |
Spreadsheet to open. |
ref |
An A1-style reference, e.g. B7. |
fetch url [--sheet NAME] — print a data URL as a table¶
view for a URL: download url to a temporary file, open it with the same
extension-dispatch loader every other command uses, and print the sheet as a
plain-text table. Only http, https, and ftp are accepted — file:// and
other schemes are refused so a stray URL can never quietly read a local path.
The transfer has a 30-second timeout and is abandoned past 100 MB.
The format comes from the URL path's extension when it is one abax recognises
(.csv, .tsv, .json, .jsonl, .xlsx, .parquet, .ods, .md, .xml,
.adif, .abax, …) and otherwise from the response's Content-Type (text/csv,
application/json, …; any other text/* is read as CSV). The extension wins when
both are present — servers mislabel MIME types far more often than people mistype
a filename.
$ abax fetch https://example.org/sunspots.csv
| A | B
----------------
1 | Year | Mean
2 | 2023 | 123.3
3 | 2024 | 154.8
4 | 2025 | 138.1
| Argument / flag | Description |
|---|---|
url |
http/https/ftp URL of a data file. |
--sheet NAME |
Which sheet to print — only meaningful for multi-sheet formats such as .xlsx. Defaults to the downloaded workbook's active sheet (the first one). |
Only the rendered table reaches standard output: the temporary download is deleted
as soon as the workbook has been parsed — on a bad --sheet and on a failed open
too — so fetch leaves nothing behind on disk. To keep the data, download it
yourself and run convert.
Exit codes: 0 = table printed, 2 = --sheet names a sheet the downloaded
workbook does not have, 4 = the download failed or the file type is not one
abax can open. A plain web page is the usual 4 — an HTML <table> is imported
through the GUI's File → Import web table… instead (see
gui-guide.md).
sql db query — query a SQLite database¶
Run a read-only SQL query against a SQLite file and print the result set as an
aligned table. It uses the standard library's sqlite3 driver — no optional
dependency — through the same engine.dbapi reader the GUI's database import
uses, so cells arrive formatted the way abax formats them: SQL NULL becomes an
empty cell and whole floats collapse to integers. It is a reader; the connection
is closed without a commit.
$ abax sql inventory.db "SELECT name, qty FROM stock ORDER BY qty DESC"
name qty
------ ---
pears 8
apples 5
| Argument | Description |
|---|---|
db |
Path to a .db / .sqlite file. |
query |
The SQL SELECT to run — quote it as a single shell argument. |
The query text is handed to SQLite verbatim, with no parameter binding on this
path, so build it only from values you trust. Note that sqlite3 creates a
missing database file rather than refusing it, so a typo in db normally surfaces
as a query error (no such table: …) rather than as a failure to open. PostgreSQL
and MySQL are not reachable from this subcommand — use File → Import from
database… in the GUI, which needs the optional database feature.
Exit codes: 0 = the result set was printed (a query matching no rows prints just the header line and its rule), 4 = the database could not be opened or the query failed; the message goes to standard error.
diff old new — cell-level workbook diff¶
Compare two .abax/JSON workbooks and print the per-sheet cell differences —
added (+), removed (-), and changed (~ old -> new). Output is coloured when
stdout is a terminal. Exit codes follow diff(1): 0 = identical, 1 =
differences found, 2 = error.
pipe target file — stream stdin into cells¶
Read piped text and lay it into a workbook starting at target (an anchor cell
or the top-left of a range, optionally sheet-qualified Sheet1!A1), then save
file. Columns are auto-detected (tab, else comma, else one cell per line);
force with --tsv / --csv.
profile file [--sheet NAME] [--repeat N] [--limit N] — slowest formula cells¶
Time every populated formula cell in a workbook and print them slowest-first —
the headless twin of the GUI formula profiler (same core.profile engine). Use
it to find which formulas dominate a slow recalc. --sheet restricts to one
sheet (default: all); --repeat N averages N passes for a steadier estimate on
sub-millisecond timings; --limit N caps the rows (default 20, 0 = all). Exit
codes: 0 = report printed, 2 = file can't be opened or the sheet is
unknown.
$ abax profile model.abax --limit 3
# Cell Time (ms) Formula
------------------------------------
1 Sheet1!D200 1.9420 =SUMPRODUCT(A2:A200,B2:B200)
2 Sheet1!C2 0.4110 =VLOOKUP(A2,Rates!A:B,2,0)
3 Sheet1!E2 0.0900 =C2*(1+tax)
deps — install optional dependencies¶
Install every optional dependency (the "full-fat" set: the data-science stack, Excel/Parquet I/O, the PTY terminal, and Jupyter integration), blocking with progress. Useful for headless setups where you want everything up front instead of picking features in the first-run chooser.
$ abax deps
Attempted 5 package(s): msgspec, textual, nbformat, anywidget, pyte
Optional dependencies present: 29/29
(The denominator is the size of the full-fat set, which is platform-dependent: 29
on Windows, 28 elsewhere, where the pywinpty ConPTY backend isn't needed.)
On first GUI launch abax offers these through a feature chooser — nothing is
installed unless you choose it (see
configuration.md); abax deps installs the whole
set at once and synchronously. The Qt GUI binding is not installed this way — you choose it
with pip install abax[gui]. Set ABAX_NO_AUTOINSTALL=1 (or auto_install:
false in settings) to disable automatic installation entirely.
macro list — list macros and UDFs¶
List the macros and user-defined functions that were discovered (from CONFIG_DIR/macros plus any --macros paths).
If nothing was found:
macro run NAME FILE [-o OUT] [--at A1] — run a macro¶
Open FILE, run the macro called NAME against its workbook, print any messages the macro logged, then save. By default it overwrites the input file; use -o/--output to save elsewhere.
# Run the 'totals' macro and overwrite the file
$ abax macro run totals report.abax
... any messages the macro logged ...
ran macro 'totals'; saved report.abax
# Save the result to a new file instead
$ abax macro run totals report.abax -o report_with_totals.abax
# Run a relative-recording macro anchored at cell C5
$ abax macro run my_recording data.csv --at C5
| Argument / flag | Description |
|---|---|
NAME |
The macro to run (as shown by macro list). |
FILE |
Spreadsheet to open and operate on. |
-o, --output OUT |
Save path. Defaults to overwriting the input FILE. |
--at A1 |
Anchor cell for relative macros (e.g. C5). Relative recordings offset every target and relative reference from this anchor; absolute ($) references stay put. |
If the macro is not found or fails, abax prints the error to standard error and exits with status 4.
doctor — environment health report¶
Prints a self-diagnostic: the abax version and how it was built (installed
package, zipapp, or frozen binary), Python version and platform, the
optional-dependency matrix (what's installed vs. available), the active
code-isolation level and which sandbox confinement is selected/available,
the runtime directories (config / data / cache / log) and whether each is
writable, and whether settings.json parses. It never installs anything and
never crashes when a confinement or directory is unavailable — a quick first
stop when a feature seems missing, and the most useful thing to attach to a bug
report.
$ abax doctor
abax doctor — environment health report
=======================================
abax
----
version : 0.1.20
build : installed package
location : /usr/lib/python3.13/site-packages/abax
Python & platform
python : 3.13.0 (CPython)
...
Optional dependencies
[OK] openpyxl available
[--] PyNEC missing (fallback: built-in method-of-moments solver)
...
report file [-o OUT] — export a PM report¶
Generates a project-management report (HTML or Markdown) for every project defined in the workbook. The report includes per-project status tables, task summaries, and milestone listings — the same content as Project → Export report in the GUI.
$ abax report portfolio.abax -o status.html
report written to status.html
$ abax report portfolio.abax -o status.md
report written to status.md
The output format is chosen by the file extension: .md produces Markdown,
anything else produces HTML. If -o is omitted the report is written to
report.html in the current directory. Exit code 2 when the file cannot
be opened or the workbook defines no projects.
schedule file — CPM critical path per project¶
Runs the Critical Path Method (CPM) over every project defined in the workbook
and prints, per project, the task count and the critical-path task ids/titles —
the headless twin of the GUI scheduler (same core.pm.schedule engine). Tasks
are read from each project's sheet using its stored geometry; dependencies come
from the tasks' Depends column.
$ abax schedule portfolio.abax
Alpha (4 task(s))
critical path: T1 (Design) -> T2 (Implement) -> T3 (Test)
With --write, dates proposed by the auto-scheduler are written into empty
Start/Due cells (a date you typed is never touched) and the workbook is saved
in place:
$ abax schedule portfolio.abax --write
Alpha (4 task(s))
critical path: T1 (Design) -> T2 (Implement) -> T3 (Test)
wrote 4 date cell(s)
saved portfolio.abax
Exit codes: 0 = every project scheduled, 1 = a project's tasks contain a dependency cycle (the offending loop is printed to stderr, the remaining projects are still scheduled, and nothing is saved), 2 = the file can't be opened or the workbook defines no projects.
tasks file [--project NAME] — list and validate project tasks¶
Lists every project's tasks — id, title, status, start → due, assignee — then runs a validation pass per project and reports what it finds. The exit code is the scriptable part: it is non-zero exactly when validation flags something, so the command drops straight into CI pipelines and pre-commit hooks as a project hygiene gate. Three checks are performed:
- overdue — the task's due date is before today and its status is not
done-like (
Done,Complete,Closed, … — the same detection the portfolio health roll-up uses); - missing dates — the task has no start and/or no due date;
- unknown dependency — the task's
Dependscolumn references an id that matches no task in the project.
$ abax tasks portfolio.abax
Alpha (3 task(s))
T1 Design Done 2026-06-01 -> 2026-06-05 alice
T2 Implement In progress 2026-06-08 -> 2026-06-19 bob
T3 Test Todo - -> - carol
2 problem(s):
overdue: T2 (Implement) was due 2026-06-19
missing start and due: T3 (Test)
$ echo $?
1
--project NAME restricts the listing (and the gate) to one project:
Exit codes: 0 = validation found nothing, 1 = validation found
problems (the listing is still printed to stdout), 2 = the file can't be
opened, the workbook defines no projects, or --project names an unknown
project.
notebook run FILE [-o OUT] — execute a notebook headlessly¶
Runs a Jupyter .ipynb end to end without nbclient: each code cell is
executed in order against abax's own shell (so doc, wb, cell, put, … are
bound, exactly as in the embedded console), and the computed outputs are written
back into the notebook. With no -o the notebook is executed in place.
# Execute in place (overwrites the file with results)
$ abax notebook run analysis.ipynb
executed 12 cell(s); wrote analysis.ipynb
# Write the executed copy elsewhere
$ abax notebook run analysis.ipynb -o analysis-run.ipynb
| Argument / flag | Description |
|---|---|
FILE |
The .ipynb notebook to execute. |
-o, --output OUT |
Write the executed notebook here (default: overwrite FILE). |
A cell that raises does not stop the run; its error rides back into the notebook's outputs and the summary line notes how many cells raised. See jupyter.md for the kernel and rich-display integration.
Exit codes¶
| Code | Meaning |
|---|---|
0 |
Success. |
2 |
view / fetch: the requested --sheet does not exist. |
3 |
convert: the conversion failed (e.g. a missing optional dependency). |
4 |
macro run / notebook run: the macro/notebook was not found or failed. fetch: the download failed or the file type is not one abax can open. sql: the database could not be opened or the query failed. |
See also¶
- getting-started.md — install and first-run walkthrough.
- configuration.md — settings, directories, and environment variables.
- gui-guide.md — the GUI menus, palette, and shortcuts.
- index.md — documentation home.