cq parses a COBOL copybook and either prints the record layout (byte
offset and length of every field) or decodes fixed-length EBCDIC records —
for example a dataset streamed from z/OS through your Zowe config — into
JSON. A built-in jq (-q) covers most filtering; pipe into real jq for
anything else.
Compa/z (binary compaz) is the terminal browser: navigate z/OSMF data
sets and PDS/PDSE members, and view records raw or through the same copybook
parser, as a table or JSON. Press ? inside it for the keymap.
$ cq -c CUSTOMER.cpy # layout: offset/length of each field
$ cq -c CUSTOMER.cpy -d customer.bin # decode records to a JSON array
$ cq --copybook-dsn "HQ.COPYLIB(CUSTOMER)" --data-dsn "HQ.CUSTOMER.DATA"
$ cq -q 'select(.BALANCE < 0)' -c CUSTOMER.cpy -d customer.bin
$ cq -where DTAR107-SALE -c DTAR107.cbl -d sales.bin
$ compazOn Windows, install from winget:
$ winget install Tannex.cq
$ winget install Tannex.compazOr download the archive for your platform from the
latest release — cq_VERSION_OS_ARCH
for the CLI, compaz_VERSION_OS_ARCH for the browser (Linux/macOS/Windows,
amd64/arm64). Extract and put the binary on your PATH.
Or install with Go, pinned to a release tag:
$ go install github.com/Tannex/cq@vX.Y.Z
$ go install github.com/Tannex/cq/cmd/compaz@vX.Y.Zgo install …@main gives the unstable development build — prefer tags.
cq [flags] (-c COPYBOOK | --copybook-dsn DSN[(MEMBER)])
[-d DATA | --data-dsn DSN | DATA]
One copybook source (-c local file, or --copybook-dsn fetched through
Zowe) and optionally one data source (-d file/-/stdin, a trailing DATA
argument, or --data-dsn streamed in binary). Omit the data source for
layout output. Records are fixed-length, derived from the copybook; pass
-lrecl if physical records carry trailing padding.
| Flag | Default | Meaning |
|---|---|---|
-c |
— | local copybook file |
--copybook-dsn |
— | copybook data set or PDS member, fetched through Zowe |
-d |
— | data file to decode (- for stdin) |
--data-dsn |
— | data set streamed in binary through Zowe |
-codepage |
Zowe profile encoding, else cp037 |
EBCDIC codepage (cp037, cp277, cp1047, cp1140, cp1142; ascii/latin1 for testing) |
-format |
auto |
copybook source format: fixed (cols 7–72), free, auto |
-record |
first | which 01-level record to decode |
-q |
— | jq expression (full jq via gojq) |
-r |
off | with -q, print raw strings instead of JSON |
-where |
— | keep only records matching a level-88 condition; !/not negates; repeat to AND |
-max |
all | decode at most N records |
-pretty |
off | indent JSON output |
-fillers |
off | include FILLER fields |
-lrecl |
layout size | physical record length, when larger than the layout |
--verbose |
off | debug logging to stderr |
--version |
— | print version and exit |
Layout: one JSON object per 01-level record, fields[] with
name/offset/length/kind (text, zoned, packed, binary,
float, edited, group) and occurs on arrays. Level-88 names appear
under conditions with their VALUE/THRU literals.
Decode: one JSON object per record, copybook field order. Numeric
fields become JSON numbers (decimal point applied); PIC X trims trailing
spaces; OCCURS become arrays; groups nest.
-q runs per record while decoding (. is one record; results stream,
one per line — no buffering) or against the layout document in layout mode.
COBOL names with dashes need .["CUST-NAME"] (- is subtraction in jq).
-where filters on level-88 condition names straight from the
copybook, before any JSON is built — -where DTAR107-SALE instead of
remembering TRANS-TYPE = 1. Combines with -q (filter first, then query).
Not yet supported: conditions inside OCCURS tables.
Shares cq's Zowe session, TLS settings, and cq/config.json — no separate
config. Run cq config to edit it.
$ compaz
$ compaz --demo # offline sample datasets and jobsLaunch compaz without configuration flags. It uses your Zowe profiles for credentials and encoding; choose profiles and data set prefixes in the browser. The last applied data set prefix is restored on the next launch for the same profile, connection, and user. Prefixes applied from favorites are remembered too. Missing or unreadable saved state falls back to the usual user-based default; demo mode does not read or write these preferences.
Press c in a records view to load a copybook or manage data set/member mappings.
Copybooks belong to the current data set/member; an unmapped target opens raw.
In the jq popup, Up/Down recalls submitted queries and restores your unfinished draft after the newest entry. Recalled queries remain editable; Enter runs them. History survives reopening and restarts through the existing local event log. Up/Down navigates completions when that menu is open; Page Up/Page Down scrolls results.
The popup evaluates each query against one array of decoded records from the
whole data set/member. length, unique, sorting, and grouping therefore operate
across all successfully decoded records. Raw records are cached in a temporary
file for repeated queries; each run decodes that file into memory. Decoded
objects, aggregate operations, and retained result text can use substantially
more RAM than the raw data, so memory use still grows with the input and output.
Every z/OSMF list/read request is capped at 2× the visible rows; cached rows
persist per screen so paging back never refetches. e opens a sequential
data set or PDS member for editing; Ctrl-S conditionally saves and fails
cleanly on a stale copy (Ctrl-R reloads). Browsing itself never writes.
--help and --version are informational commands.
J from the data set screen opens the jobs view: list, drill into a job's
spool files, and read spool/JCL content — read-only, same session. z/OSMF's
jobs API has no pagination cursor, so the job and spool file lists are
single bounded snapshots rather than incrementally fetched like data sets.
Not yet supported: submit, cancel, purge, hold, release.
Both binaries connect to z/OSMF directly (no Node/npm) using your existing
Zowe team configuration and OS credential store — the same one Zowe CLI and
Zowe Explorer use. Global and project-level zowe.config.json /
zowe.config.user.json, profile precedence, ZOWE_OPT_* env overrides, and
secure credential storage (Keychain/Credential Manager/libsecret) all work
as expected.
HTTPS verifies the server certificate unless the profile sets
rejectUnauthorized: false. Not yet supported: Zowe V1 profiles, Imperative
credential-manager plugins, client-certificate auth.
cq/compaz are an independent project, not affiliated with or endorsed by
The Linux Foundation or Zowe. Zowe® is a registered trademark of The Linux
Foundation.
Resolved recursively through an ordered dsnSearchPath in cq/config.json
(cq config creates/opens it):
{ "dsnSearchPath": ["HQL.CPY.SRC", "HQL.COB.SRC"] }The same search runs for --copybook-dsn itself if z/OSMF 404s it. Lookups
are parallel (8 in flight) and cached per run; the first library in the list
that has the member wins. REPLACING/OF/IN clauses are rejected
explicitly.
# Peek at the first few records of a big dataset
$ cq -max 5 -pretty --copybook-dsn "HQ.COPYLIB(CUSTOMER)" --data-dsn "HQ.CUSTOMER.DATA"
# Download once, slice locally many times
$ zowe zos-files download data-set "HQ.CUSTOMER.DATA" --binary --file customer.bin
$ cq -r -q '.["CUST-NAME"]' -c CUSTOMER.cpy -d customer.binDon't pipe zowe zos-files view data-set --binary into cq — it can alter
packed/binary bytes. Use --data-dsn, or download --binary --file first.
- Levels 01–49/77, FILLER, level-88, level-66 RENAMES (skipped)
PICX/A/9/S/V/P and numeric-edited picturesUSAGEDISPLAY, COMP/COMP-4/COMP-5/BINARY, COMP-3/PACKED-DECIMAL, COMP-1/COMP-2 (IBM hex float not yet)REDEFINES,SYNC,SIGN LEADING/TRAILING [SEPARATE]OCCURS, includingOCCURS ... DEPENDING ONas the trailing field- Recursive
COPY MEMBER.via Zowe DSN search paths - Fixed and free source format, auto-detected
Not yet: multiple/non-trailing OCCURS DEPENDING ON, IBM hex float,
USAGE POINTER/INDEX, PIC N, RDW-prefixed (VB) files.
Codepages: cp037 (default), cp277, cp1047, cp1140, cp1142 — matched loosely
(IBM-277, ibm277, 277). Others are a 256-entry table away; open an
issue.
testdata/copybooks/cb2xml/ are unmodified fixtures from
cb2xml (LGPL-2.1), used to cross-check
field offsets. See SOURCES.md there for origins and license text.
Compa/z benchmarks generate 10,000 and 100,000 mixed COBOL records (192 bytes
each), including nested groups, OCCURS, packed decimals, and 20-digit integers.
They measure cached-file decoding, jq evaluation, and result serialization;
host downloads and UI rendering are excluded. Fixtures and expected aggregate
results are defined in internal/compaz/query_benchmark_test.go.
go test ./internal/compaz -run '^$' -bench 'Benchmark(DecodeQueryValue|QueryArrayFile)' -benchmem -benchtime=200ms -count=3
# Peak process RAM on Linux, excluding compilation:
go test -c -o /tmp/cq-query.test ./internal/compaz
/usr/bin/time -v /tmp/cq-query.test -test.run='^$' -test.bench='^BenchmarkQueryArrayFile$/^100000$/^count$' -test.benchtime=1xB/op reports cumulative allocations per query, not peak RAM. Maximum resident
set size includes fixture setup and the Go runtime; compare isolated runs with
the same Go version, hardware, and fixture.
$ git tag -a v1.2.3 -m "v1.2.3"
$ git push origin v1.2.3CI builds cq/compaz archives for all targets, generates one checksum
file, and publishes a GitHub release.