NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Go modules · #638 by repository stars
Last release 2 days ago
30 Sep 2026
Ships on a steady schedule
a new release about every 1 weeks
Nearly every release is documented
notes for 56 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
6 years old
301 releases · first in 2020
One column per quarter.
New SLQ function `rownum()` that returns the one-indexed row number of the current record.
New SLQ function rownum() that returns the one-indexed
row number of the current record.
$ sq '.actor | rownum(), .actor_id, .first_name | order_by(.first_name)'
rownum() actor_id first_name
1 71 ADAM
2 132 ADAM
3 165 AL
sq inspect has two new flags:
--schemata: list the source's schemas
$ sq inspect @sakila/pg12 --schemata -y
- schema: information_schema
catalog: sakila
owner: sakila
- schema: public
catalog: sakila
owner: sakila
active: true
--catalogs: list the source's catalogs
$ sq inspect @sakila/pg12 --catalogs
CATALOG
postgres
sakila
sq version now honors option
format.datetime when outputting build timestamp.--exec and --query flags for sq sql were removed in
the preceding release ([v0.43.1]).
That was probably a bit hasty, especially because it's possible those flags could be reintroduced
when the query vs exec situation is figured out. So, those two flags are now restored, in
that their use won't cause an error, but they've been hidden from command help, and remain no-op.Nothing published for this version
Nothing published for this version
Nothing published for this version
Related to [#270], the output of `sq inspect` now includes the source's catalog (in JSON and YAML output formats).
sq inspect now includes the
source's catalog (in JSON and YAML output formats).sq inspect --overview.--exec and --query flags from sq sql command.[#270]: Flag `--src.schema` permits switching the source's schema (and catalog) for the duration of the command. The flag is supported for the `sq`, `
--src.schema permits switching the source's schema (and catalog)
for the duration of the command. The flag is supported for the
sq, sql
and inspect commands.catalog() and
schema() return the catalog and schema of the DB connection.unique function now has a synonym uniq.sq src --text now outputs only the handle of the active source. Previously it
also printed the driver type and short location. Instead use sq src --text --verbose to
see those details.Nothing published for this version
[#308]: Fix to allow build on 32-bit systems. Thanks @icp.
Nothing published for this version
Nothing published for this version
🐥 [#279]: The SQLite driver now has initial support for several SQLite extensions baked in, including Virtual Table and FTS5. Note that this is an ear
Nothing published for this version
sq version was missing a newline in its output.
sq version was missing a newline in its output.This release is heavily focused on improvements to Microsoft Excel support. The underlying Excel library has been changed from `tealeg/xlsx` to `qax-o
This release is heavily focused on improvements to Microsoft Excel support.
The underlying Excel library has been changed from tealeg/xlsx
to qax-os/excelize, largely because
tealeg/xlsx is no longer actively maintained. Thus, both the XLSX output writer
and the XLSX driver have been rewritten. There should be some performance
improvements, but it's also possible that the rewrite introduced bugs. If you
discover anything strange, please open an issue.
[#99]: The CSV and XLSX drivers can now handle duplicate header column names in the ingest data. For example, given a CSV file:
actor_id,first_name,actor_id
1,PENELOPE,1
2,NICK,2
The columns will be renamed to:
actor_id,first_name,actor_id_1
The renaming behavior is controlled by a new option ingest.column.rename
This new option is effectively the ingest counterpart of the existing output option
result.column.rename.
[#191]: The XLSX driver now detects header rows, like
the CSV driver already does. Thus, you now typically don't need to specify
the --ingest.header flag for Excel files. However, the option remains available
in case sq can't figure it out for a particular file.
The Excel writer has three new config options for controlling date/time output.
Note that these format strings are distinct from format.datetime
and friends, because Excel has its own format string mechanism.
format.excel.datetime: Controls datetime format, e.g. 2023-08-03 16:07:01.format.excel.date: Controls date-only format, e.g. 2023-08-03.format.excel.time: Controls time-only format, e.g. 4:07 pm.The ingest kind detectors (e.g. for CSV or XLSX)
now detect more date & time formats as kind.Datetime, kind.Date, and kind.Time.
If an error occurs when the output format is text, a stack trace is printed
to stderr when the command is executed with --verbose (-v).
There's a new option error.format that controls error output format independent
of the main format option . The error.format value must be one of text or json.
☢️ The default Excel date format has changed. Previously
the format was 11/9/89, and now it is 1989-11-09. The same applies
to datetimes, e.g. 11/9/1989 00:00:00 becomes 1989-11-09 00:00.
This change is made to reduce ambiguity and confusion.
sq uses a library
to interact with Excel files, and it seems that the library chooses a particular format
by default (11/9/89). There are several paths we could take here:
11/9/89.11/9/89.We pick the third option. The first option (locale-dependent)
is excluded because, as a general rule, we want sq to produce the same
output regardless of locale/system settings. We exclude the second option
because month/day confuses most of the world. Thus, we're left with picking a
default, and 1989-11-09 is the format used in
RFC3339 and friends.
Whether this is the correct (standard?) approach is still unclear, and
feedback is welcome. However, the user can make use of the new config options
(format.excel.datetime etc.)
to customize the format as they see fit.
The XLSX writer now outputs header rows in bold text.
☢️ The XLSX writer now outputs blob (bytes) cell data as a base64-encoded string,
instead of raw bytes.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
This release features a complete overhaul of the `join` mechanism.
This release features a complete overhaul of the join
mechanism.
[#277]: A table selector can now have an alias. This in and of itself is not particularly useful, but it's a building block for multiple joins.
$ sq '@sakila | .actor:a | .a.first_name'
New option result.column.rename that exposes a template used to rename
result set column names before display. The primary use case is to de-duplicate
columns names on a SELECT * FROM tbl1 JOIN tbl2, where tbl1 and tbl2
have clashing column names (docs).
[#157]: Previously only join (INNER JOIN) was available: now the rest of
the join types such as left_outer_join, cross_join, etc. are
implemented (docs).
☢️ [#12]: The table join mechanism has been completely overhauled. Now there's support for multiple joins. See docs.
# Previously, only a single join was possible
$ sq '.actor, .film_actor | join(.actor_id)'
# Now, an arbitrary number of joins
$ sq '.actor | join(.film_actor, .actor_id) | join(.film, .film_id)'
☢️ The alias for --jsonl (JSON Lines) has been changed to -J.
Nothing published for this version
Nothing published for this version
Bug with sq version output on Windows.
sq version output on Windows.[#263]: sq version now supports --yaml output.
sq version now supports --yaml output.sq version now outputs host OS details with --verbose, --json
and --yaml flags. The motivation behind this is bug submission: we want
to know which OS/arch the user is on. E.g. for sq version -j:{
"version": "v0.38.1",
"commit": "eedc11ec46d1f0e78628158cc6fd58850601d701",
"timestamp": "2023-06-21T11:41:34Z",
"latest_version": "v0.39.0",
"host": {
"platform": "darwin",
"arch": "arm64",
"kernel": "Darwin",
"kernel_version": "22.5.0",
"variant": "macOS",
"variant_version": "13.4"
}
}
sq inspect and sq inspect -v has been refactored
significantly, and should now be easier to work with (docs).Nothing published for this version
[#261]: The JSON writer (--json) could get deadlocked when a record contained a large amount of data, triggering an internal Flush() (which is mutex-g
--json) could get deadlocked when a record contained
a large amount of data, triggering an internal Flush() (which is mutex-guarded)
from within the mutex-guarded WriteRecords() method.Nothing published for this version
This release has significant improvements (and breaking changes) to SLQ (sq's query language).
This release has significant improvements (and breaking changes)
to SLQ (sq's query language).
☢️ [#254]: The formerly-implicit "WHERE" mechanism now requires an explicit where() function.
This, alas, is a fairly big breaking change. But it's necessary to remove an ambiguity roadblock.
See discussion in the issue.
# Previously
$ sq '.actor | .actor_id <= 2'
# Now
$ sq '.actor | where(.actor_id <= 2)'
[#256]: Column-only queries are now possible. This has the neat side effect
that sq can now be used as a calculator.
$ sq 1+2
1+2
3
You may want to use --no-header (-H) when using sq as a calculator.
$ sq -H 1+2
3
$ sq -H '(1+2)*3'
9
Literals can now be selected (docs).
$ sq '.actor | .first_name, "X":middle_name, .last_name | .[0:2]'
first_name middle_name last_name
PENELOPE X GUINESS
NICK X WAHLBERG
Lots of expressions that previously failed badly, now work.
$ sq '.actor | .first_name, (1+2):addition | .[0:2]'
first_name addition
PENELOPE 3
NICK 3
[#258]: Column aliases can now be arbitrary strings, instead of only a valid identifier.
# Previously only valid identifier allowed
$ sq '.actor | .first_name:given_name | .[0:2]'
given_name
PENELOPE
NICK
# Now, any arbitrary string can be used
$ sq '.actor | .first_name:"Given Name" | .[0:2]'
Given Name
PENELOPE
NICK
Nothing published for this version
Nothing published for this version
[#252]: Handle *uint64 returned from DB.
*uint64 returned from DB.Nothing published for this version
[#244]: Shell completion for sq add LOCATION. See docs.
sq add LOCATION. See docs.Nothing published for this version
☢️ Proprietary database functions are now invoked by prefixing the function name with an underscore. For example:
☢️ Proprietary database functions are now invoked by prefixing the function name with an underscore. For example:
# mysql "date_format" func
$ sq '@sakila/mysql | .payment | _date_format(.payment_date, "%m")'
# Postgres "date_trunc" func
$ sq '@sakila/postgres | .payment | _date_trunc("month", .payment_date)'
sq diff: Renamed --count flag to --counts as intended.
sq diff: Renamed --count flag to --counts as intended.Nothing published for this version
The major feature is the long-gestating `sq diff`.
The major feature is the long-gestating sq diff.
sq diff compares two sources, or tables.sq inspect --dbprops is a new mode that returns only the DB properties.
Relatedly, the properties mechanism is now implemented for all four supported
DB types (previously, it was only implemented for Postgres and MySQL).sq inspect -v previously returned DB properties in a field named db_variables.
This field has been renamed to db_properties. The renaming reflects the fact
that some of those properties aren't really variables in the sense that they
can be modified (e.g. DB server version or such).db_variables (now db_properties) field has
changed. Previously it was an array of {"name": "XX", "value": "YY"} values,
but now is a map, where the keys are strings, and the values can be either
a scalar (bool, int, string, etc.), or a nested value such as an array
or map. This change is made because some databases (e.g. SQLite) feature
complex data in some property values.[777 bytes] instead of dumping
the raw bytes.--tsv) no longer has a shorthand form -T. Apparently that
shorthand wasn't used much, and -T is needed elsewhere.--xml no longer has shorthand -X. And --markdown has lost alias --md.--text, --json, etc., there is now
a --format=FORMAT flag, e.g. --format=json. This will allow sq to
continue to expand the number of output formats, without needing to have
a dedicated flag for each format.sq config edit @source was failing to save any edits.Nothing published for this version
[#8]: Results can now be output in YAML.
sq config get OPT --text now prints only the value, not KEY VALUE.
If you want to see key and value, consider using --yaml, or --text --verbose.Both --markdown and the alias --md are now supported.
--markdown and the alias --md are now supported.Nothing published for this version
Fixed a minor issue where sq ls -jv and sq ls -yv produced no output if config contained no explicitly set options.
sq ls -jv and sq ls -yv produced no output
if config contained no explicitly set options.Nothing published for this version
Alas, this release has several minor breaking changes ☢️.
This release significantly overhauls sq's config mechanism ([#199]).
For an overview, see the new config docs.
Alas, this release has several minor breaking changes ☢️.
sq config ls shows config.
sq config get gets individual config option.
sq config set sets config values.
sq config edit edits config.
$EDITOR or $SQ_EDITOR.sq config location prints the location of the config dir.
--config flag is now honored globally.
Many more knobs are exposed in config.
Logging is much more configurable. There are new knobs:
$ sq config set log true
$ sq config set log.level INFO
$ sq config set log.file /var/log/sq.log
There are also equivalent flags (--log, --log.file and --log.level) and
envars (SQ_LOG, SQ_LOG_FILE and SQ_LOG_LEVEL).
Several more commands support YAML output:
The structure of sq's config file (sq.yml) has changed. The config
file is automatically upgraded when using the new version.
The default location of the sq log file has changed. The new location
is platform-dependent. Use sq config get log.file -v to view the location,
or sq config set log.file /path/to/sq.log to set it.
☢️ Envar SQ_CONFIG replaces SQ_CONFIGDIR.
☢️ Envar SQ_LOG_FILE replaces SQ_LOGFILE.
☢️ Format flag --table is renamed to --text. This is changed because while the
output is mostly in table format, sometimes it's just plain text. Thus
table was not quite accurate.
☢️ The flag to explicitly specify a driver when piping input to sq has been
renamed from --driver to --ingest.driver. This change aligns
the naming of the ingest options and reduces ambiguity.
# previously
$ cat mystery.data | sq --driver=csv '.data'
# now
$ cat mystery.data | sq --ingest.driver=csv '.data'
☢️ sq add no longer has the generic --opts x=y mechanism. This flag was
ambiguous and confusing. Instead, use explicit option flags.
# previously
$ sq add ./actor.csv --opts=header=false
# now
$ sq add ./actor.csv --ingest.header=false
☢️ The short form of the sq add --handle flag has been changed from -h to
-n. While this is not ideal, the -h shorthand is already in use everywhere
else as the short form of --header.
# previously
$ sq add ./actor.csv -h @actor
# now
$ sq add ./actor.csv -n @actor
☢️ The --pretty flag has been removed. Its only previous use was with the
json format, where if --pretty=false would output the JSON in compact form.
To better align with jq, there is now a --compact / -c flag that behaves
identically to jq.
☢️ Because of the above --compact / -c flag, the short form of the --csv
flag is changing from -c to -C. It's an unfortunate situation, but alignment
with jq's behavior is an overarching principle that justifies the change.
The headline feature is source groups. This is the biggest change to the sq CLI in some time, and should make working with lots of sources much easier
The headline feature is source groups.
This is the biggest change to the sq CLI in some time, and should
make working with lots of sources much easier.
sq now has a mechanism to group sources. A source handle can
now be scoped. For example, instead of @sakila_prod, @sakila_staging, etc,
you can use @prod/sakila, @staging/sakila. Use sq group prod to
set the active group (which sq ls respects). See docs.sq group GROUP sets the active group to GROUP.sq group returns the active group (default is /, the root group).sq ls GROUP lists the sources in GROUP.sq ls --group (or sq ls -g) lists all groups.sq mv moves/renames sources and groups.sq ls now shows the active item in a distinct color. It no longer adds
an asterisk to the active item.sq ls now sorts alphabetically when using --table format.sq ls now shows the sources in the active group only. But note that
the default active group is / (the root group), so the default behavior
of sq ls is the same as before.sq add hello.csv will now generate the handle @hello instead of @hello_csv.
On a second invocation, it will return @hello1 instead of @hello_csv_1. Why
this change? Well, with the availability of the source group mechanism, the _ character
in the handle somehow looked ugly. And more importantly, _ is a relative pain to type.sq ping has changed to support groups. Instead of sq ping --all, you can
do sq ping GROUP, e.g. sq ping /.Nothing published for this version
[#187]: For csv sources, sq will now try to auto-detect if the CSV file has a header row or not. Previously, this needed to be explicitly specified vi
[#187]: For csv sources, sq will now try to auto-detect if the CSV file
has a header row or not. Previously, this needed to be explicitly specified
via an awkward syntax:
$ sq add ./actor.csv --opts=header=true
This change makes working with CSV files significantly lower friction. A command like the below now almost always works as expected:
$ cat ./actor.csv | sq .data
Support for Excel/XLSX header detection is in [#191].
sq is now better at detecting the (data) kind of CSV fields. It now more
accurately distinguishes between Decimal and Int, and knows how to
handle Datetime.
[#189]: sq now treats CSV empty fields as NULL.
[#173]: Predefined variables via --arg flag (docs):
[#173]: Predefined variables via --arg
flag (docs):
$ sq --arg first TOM '.actor | .first_name == $first'
--md instead of --markdown for outputting Markdown.sq inspect now better handles "too many connections" situations.go.mod: Moved to jackc/pgx v5.slog logging library.Nothing published for this version
Nothing published for this version
Nothing published for this version
[#164]: Implemented unique function (docs):
[#164]: Implemented unique function (docs):
$ sq '.actor | .first_name | unique'
This is equivalent to:
SELECT DISTINCT first_name FROM actor
Implemented count_unique function (docs).
$ sq '.actor | count_unique(.first_name)'
The count function has been changed (docs)
.actor | count equivalent to SELECT COUNT(*) AS "count" FROM "actor"..actor | count(*)) is no longer supported; use the
naked version instead.Function columns are now named according to the sq token, not the SQL token.
# previous behavior
$ sq '.actor | max(.actor_id)'
max("actor_id")
200
# now
$ sq '.actor | max(.actor_id)'
max(.actor_id)
200
Nothing published for this version
[#162]: group_by now accepts function arguments.
group_by now accepts function arguments.groupby to group_by to match jq.orderby to order_by to match jq.Nothing published for this version
[#160]: Use groupby() to group results. See query guide.
groupby() to group results. See query guide.Nothing published for this version
[#158]: Use orderby() to order results. See query guide.
orderby() to order results. See query guide.Nothing published for this version
[#98]: Whitespace is now allowed in SLQ selector names. You can do @sakila | ."film actor" | ."actor id".
@sakila | ."film actor" | ."actor id".sq inspect now populates schema field in JSON for MySQL,
SQLite, and SQL Server (Postgres already worked).Your coding agent can read these notes before it upgrades. Set up the MCP server →