Command Line¶
Octa doubles as a small command-line tool. With no flags it launches the GUI; with one of the action flags it performs that action against a file and exits.
octa # launch GUI (empty window)
octa file1.csv file2.json # launch GUI, open both files in tabs
octa --schema data.parquet # action: print schema
octa --head data.csv -n 50 # action: first 50 rows
octa --tail data.csv -n 50 # action: last 50 rows
octa --sample data.csv -n 50 --seed 1 # reproducible random sample
octa --convert in.csv out.parquet
octa --sql data.parquet -q 'SELECT count(*) FROM data'
octa --sql sales.parquet --sql-table customers=customers.csv \
-q 'SELECT c.name, SUM(s.amount) FROM data s JOIN customers c ON s.cid=c.cid GROUP BY c.name'
octa --export-schema data.parquet -t snowflake
octa --compare-schemas v1.parquet v2.parquet
octa --diff v1.parquet v2.parquet
octa --describe data.parquet
octa --validate-schema data.parquet --expect-schema expected.json
octa --unique-columns users.csv --max-combo 2
octa --mcp # MCP server on stdio
octa --completions zsh # shell completion script on stdout
The action flags are mutually exclusive, so pick one per invocation. Trailing file arguments are ignored (with a warning) when an action flag is set.
Cloud objects as input¶
Anywhere a FILE argument is accepted, you can pass a cloud object URL
instead. No extra flag is involved: the path is recognised and read.
The object is downloaded to a temporary file and read as usual.
Credentials come from a saved connection covering the URL, otherwise from
the ambient chain (AWS_* variables, a cached SSO session, az login,
Google application default credentials).
Cloud objects are read-only here: output still goes to a local path. See Cloud storage.
The same flags work identically across every distribution channel:
a plain binary off the releases page, an install.sh install, the
AUR package, or an AppImage. The AppImage is just the binary in a
self-contained bundle; invoke it directly:
A freshly downloaded AppImage has no permission to run yet, so give it
one first with chmod 750 Octa-*-x86_64.AppImage. See
Installation.
Available actions¶
Grouped by job. Every action has its own page; the man page lists every flag in one place.
Look at a file¶
| Flag | Description | Reference |
|---|---|---|
--schema FILE |
Print column name + type as a table | → --schema |
--head FILE [-n N] |
Print the first N rows (default 20) | → --head |
--tail FILE [-n N] |
Print the last N rows (default 20) | → --tail |
--sample FILE [-n N] [--seed S] |
Print a reproducible random N-row sample | → --sample |
--describe FILE |
One-shot snapshot: format + schema + sample | → --describe |
--unique-columns FILE |
Find PK candidates (singles + combos) | → --unique-columns |
Convert and export¶
| Flag | Description | Reference |
|---|---|---|
--convert IN OUT |
Convert between formats | → --convert |
--export-schema FILE [-t T] |
Render the schema as DDL / model / struct | → --export-schema |
--partition-by COL --out-dir DIR FILE |
One file per distinct column value | → --partition-by |
--batch-convert --to EXT --out-dir DIR FILE... |
Convert many files into one format | → --batch-convert |
--to-workbook OUT.xlsx FILE... |
Write several files as one workbook | → guide |
SQL, databases and APIs¶
| Flag | Description | Reference |
|---|---|---|
--sql FILE -q '<query>' |
Run a SQL query against a file | → --sql |
--sync-sql FILE --sync-table T --sync-on COLS |
Generate the SQL that would sync a table | → databases |
--db-tables --db CONN |
List a live connection's schemas and tables | → databases |
--db-query SQL --db CONN |
Run SQL on a live database server | → databases |
--db-write-table SCHEMA.TABLE --db CONN FILE |
Write a file into a live database table | → databases |
--db-copy SCHEMA.TABLE --db CONN --db-copy-to CONN |
Copy a table server to server | → databases |
--db-export SCHEMA --db CONN --out-dir DIR |
Export a schema's tables to files | → databases |
--api CONNECTION |
Read a saved REST/JSON API endpoint | → api endpoints |
Cloud storage and connections¶
| Flag | Description | Reference |
|---|---|---|
--cloud-ls URL |
List a bucket or prefix | → cloud storage |
--cloud-get URL --out PATH |
Download one cloud object | → cloud storage |
--cloud-put PATH --to URL |
Upload a local file | → cloud storage |
--cloud-copy URL --to URL |
Copy an object or prefix, across clouds too | → cloud storage |
--cloud-move URL --to URL |
Copy then delete the source | → cloud storage |
--cloud-delete URL |
Delete an object or prefix | → cloud storage |
--list-connections |
List saved cloud and database connections | → connections |
--add-connection SPEC |
Add or replace a saved connection | → connections |
--remove-connection NAME |
Delete a saved connection and its secret | → connections |
Clean and protect¶
| Flag | Description | Reference |
|---|---|---|
--test-data FILE [...] |
Shareable test data shaped like the input | → --test-data |
--shapes FILE --shapes-column COL |
What a column's values look like | → --shapes |
--anonymize SPEC FILE |
Mask / scramble columns per a JSON spec | → --anonymize |
--dedupe FILE |
Remove duplicate rows | → --dedupe |
--impute COL=STRATEGY FILE |
Fill missing cells in a column | → --impute |
--hash-columns COL,COL FILE |
Add a hash column (MD5 / SHA) | → --hash-columns |
--outliers FILE |
Flag numeric outlier cells | → --outliers |
--detect-pii FILE |
Find likely personal-data columns | → --detect-pii |
--check FILE --rules RULES.toml |
Check values against a rules file | → --check |
Combine and split¶
| Flag | Description | Reference |
|---|---|---|
--check-references PARENT --parent-column COL |
Orphan child rows (exit 1 = orphans found) | → --check-references |
--merge FILE FILE [...] |
Merge versions (exit 1 = conflicts open) | → --merge |
--lookups FILE [--lookups-min N] |
Columns that always follow another column | → --lookups |
--spatial-join FILE --spatial-layer FILE... |
Join by location (inside / nearest) | → --spatial-join |
--union FILE --union-file FILE |
Stack files into one table | → --union |
--join FILE --join-file FILE --join-on COLS |
Join files on key columns | → --join |
--relationships DIR |
Rank how the tables in a folder connect | → --relationships |
--harmonise-schema DIR --out-dir DIR |
Rewrite a folder to one common schema | → guide |
--fuzzy-join FILE --fuzzy-join-file FILE |
Join on similarity rather than equality | → --fuzzy-join |
Analyse¶
| Flag | Description | Reference |
|---|---|---|
--overlaps FILE |
Overlapping time spans (exit 1 = found) | → --overlaps |
--forecast FILE --forecast-x COL --forecast-y COL |
Holt-Winters forecast with ranges | → --forecast |
--resample COL --value-cols COLS FILE |
Group rows into time buckets and aggregate | → --resample |
--rolling COL --order-by COL --window N FILE |
Rolling aggregate over the previous N rows | → --rolling |
--report OUT.html FILE |
Write a self-contained profiling report | → --report |
Compare¶
| Flag | Description | Reference |
|---|---|---|
--compare-schemas A B |
Diff the schemas of two files | → --compare-schemas |
--compare-distributions FILE --dist-column COL |
Do two columns look like one population? | → --compare-distributions |
--diff A B |
Row-level diff: rows unique to each file | → --diff |
--compare-folders A B [C ...] |
Which files differ between folders (exit 1) | → --compare-folders |
--cell-history FILE --history-column COL ... |
Commits that changed one cell (Git) | → --cell-history |
--validate-schema FILE --expect-schema SCHEMA |
Validate against JSON Schema (exit 1 = drift) | → --validate-schema |
--schema-drift DIR |
Which files in a folder disagree on columns | → --schema-drift |
--drift-report A B |
How two versions of one dataset differ | → --drift-report |
Automate and set up¶
| Flag | Description | Reference |
|---|---|---|
--recipe RECIPE FILE |
Replay a GUI recipe (exit 1 = step skipped) | → --recipe |
--mcp |
Start the MCP server | → MCP guide |
--completions SHELL |
Print a shell completion script to stdout | → completions |
--export-schema also has the short alias -e.
Global options¶
These apply across actions (where they make sense):
| Flag | Applies to | Default | Meaning |
|---|---|---|---|
-f, --format FORMAT |
--schema, --head, --tail, --sample, --sql, --compare-schemas, --diff, --describe, --validate-schema, --unique-columns |
tsv |
Output format: tsv, json, or csv. Ignored by --convert, --export-schema, and --mcp. |
-n, --lines N |
--head, --tail, --sample |
20 |
Number of rows to print / sample. |
--seed N |
--sample |
0 |
RNG seed for --sample; same seed + file yields the same sample. |
-q, --query QUERY |
--sql |
(required) | Required for --sql. The query string; reference the file as data. |
--sql-table NAME=PATH |
--sql |
(none) | Register an extra file as a workspace table named NAME. Repeatable. Any supported format. |
--sql-attach ALIAS=PATH |
--sql |
(none) | ATTACH a DuckDB or SQLite database under ALIAS. Repeatable. |
--sql-write-to PATH |
--sql |
(none) | Persist the SELECT result to a DuckDB / SQLite file instead of printing it. Requires --sql-write-table. |
--sql-write-table TABLE |
--sql-write-to |
(required) | Target table name for --sql-write-to. |
--sql-write-schema NAME |
--sql-write-to |
main |
Target schema (DuckDB only). Leave unset or main for SQLite. |
--sql-write-mode MODE |
--sql-write-to |
create |
create, replace, or append. |
-t, --target TARGET |
--export-schema |
postgres |
Schema-export target: postgres, mysql, sqlite, databricks, snowflake, pydantic, typescript, json-schema, rust. |
--table-a NAME |
--compare-schemas |
(no value) | Specific table on FILE_A (multi-table sources only). |
--table-b NAME |
--compare-schemas |
(no value) | Specific table on FILE_B (multi-table sources only). |
--table NAME |
--validate-schema, --describe, --unique-columns |
(no value) | Specific table on FILE (multi-table sources). |
--expect-schema FILE |
--validate-schema |
(required) | Path to the expected JSON Schema. Required by --validate-schema. |
--sample-rows N |
--describe |
5 |
Sample-row count for the preview. Clamped to [0, 100]. |
--diff-db CONN |
--diff |
(no value) | Compare against a live database table instead of a second file. Names a saved connection. |
--diff-db-table TABLE |
--diff-db |
(required) | Table on that connection, as SCHEMA.TABLE or CATALOG.SCHEMA.TABLE. |
--compression CODEC |
--convert, --batch-convert |
(settings) | Parquet codec: uncompressed, snappy, zstd, gzip, lz4. Ignored by other targets. |
--row-group-size N |
--convert, --batch-convert |
(settings) | Rows per Parquet row group. |
--deep |
--describe |
off | Also report the file's physical layout: row groups, compression, encodings, column statistics. Parquet only. |
--max-combo N |
--unique-columns |
1 |
Max combo size to test (clamped to [1, 3]). |
--rows N|all |
--schema, --head, --convert, --sql |
2,000,000 |
Override the streaming initial-load row cap for this invocation. Pass a number (commas / underscores OK) or all to load every row. |
-h, --help |
always | (no value) | Print the full help text (with worked examples) and exit. -h and --help produce the same long-form output. |
--version |
always | (no value) | Print the Octa version and exit. |
--stream |
--sql |
off | Let DuckDB scan the file where it lies instead of loading its rows, so an aggregate covers every row of a file larger than memory. Other actions say it does not apply. |
Output formatting¶
The -f / --format flag controls the output format for every action
that prints a table:
| Value | Format | Notes |
|---|---|---|
tsv (default) |
Tab-separated values | Most shell tools (awk, column, sort) parse TSV natively |
json |
JSON array of {column: value} objects |
Pretty-printed; numeric / boolean cells keep their native type |
csv |
RFC 4180 CSV | Fields with comma / quote / newline are properly quoted |
octa --schema data.parquet # TSV
octa --schema data.parquet -f json # JSON
octa --schema data.parquet -f csv # CSV
The format flag applies to --schema, --head, and --sql.
--convert chooses the output format from the extension of the
output path; --export-schema emits source code chosen by -t; -f
has no effect for either.
Help output¶
octa --help # full reference with worked examples
octa -h # same: Octa wires both flags to the long-form output
The help text includes worked examples for every action, so
octa --help is a good first stop if you forget a flag.
Exit codes¶
0on success.1on any error: invalid arguments, file-not-found, read / parse failure, conversion target rejected, etc.1also as a deliberate signal, for the actions built to gate a pipeline:--validate-schemawhen the schema drifted,--schema-driftwhen the files disagree,--harmonise-schemawhen a file was refused,--batch-convertwhen an input failed,--drift-reportwhen a--fail-ongate was breached, and--checkon any failing or unrunnable rule.
Errors are written to stderr; tabular output goes to stdout.
This means you can safely pipe Octa's output through jq, awk,
xsv, etc. without errors corrupting the data stream.
Man page¶
Two consumption paths for the same content:
- In a terminal:
man octaafter installing Octa viainstall.sh, the AUR (octa/octa-bin), or the Linux release tarball. The release pipeline runsasciidoctorto render the page andinstall.shdrops it into$PREFIX/share/man/man1/octa.1. See Installation for details. - On this site: the Man Page page mirrors the same content as Markdown, with cross-links to the rest of the docs.
The canonical source is
docs/cli/octa.1.adoc
(AsciiDoc). To render it manually:
Progress on long runs¶
The actions that work through many items report progress on stderr, on one line that rewrites itself:
--batch-convert, --harmonise-schema and --partition-by count items and
show an ETA once the first one is done. --db-copy has no total to count
against (knowing it would mean a COUNT(*) scan before the copy starts), so it
reports the running row count instead, and only on the universal lane: a
Postgres-to-Postgres copy runs as a single statement inside DuckDB, which
either finishes or does not.
The line is written only when stderr is a terminal. Redirect stderr, or run in CI, and you get exactly the summary lines you always got, with no carriage returns in the log. Nothing about stdout changes either way, so a pipeline still receives clean data.
Using octa in a pipeline¶
- means standard input where a file is expected, and standard output as the
--convert target:
# Read from a pipe; the format is worked out from the bytes, not a file name
curl -s https://example.org/sales.csv | octa --schema -
# Query without writing a file at all
cat sales.csv | octa --sql - -q "SELECT city, SUM(amount) FROM data GROUP BY city"
# Convert on the way through
cat sales.csv | octa --convert - - --to json | jq '.[0]'
--to is required when writing to -, because a pipe has no file name to
infer a format from. Counts and notes go to stderr, so the next command in the
pipeline receives exactly the data.
Piped input is buffered to a temporary file first. Every reader needs to seek
(a Parquet footer sits at the end of the file), so a pipe cannot be handed
straight to one. That is the honest cost of -: a pipe bigger than the
temporary filesystem will fail.
See also¶
- The dedicated
--schema,--head,--convert,--sql,--export-schema,--compare-schemas,--describe,--validate-schema, and--unique-columnspages cover each action in detail. - Man page reference is a single-page, terminal-style
reference matching
man octa. - MCP server guide for
--mcp. - Common tasks for chained-CLI examples (CSV → Parquet pipelines, JSON-line filtering, etc.).