Files
qqq-cli/packages/cli
james.maesandClaude Fable 5.1 4bd62b7c1f feat(cli): add qqq print list and qqq print text
print list prints a table list of the whole result of the criteria (up to
10,000 rows) or one page, in the column order given, with paper and
orientation options; print text prints a file or stdin as a monospace
document. Both pick and remember the printer as print does and follow the
job.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-01 06:53:28 -06:00
..

@qrun-io/qqq-cli

qqq, the command-line client for QQQ applications. It talks to a QQQ server only through the UI API (/qqq/v1), the same API the web UI uses, so every app, table, field, process and extension comes from the server's metadata: one CLI for any QQQ application.

This npm package is the CLI only. The full-screen terminal UI (qqq ui) ships in the single-file qqq binaries (curl installer, Homebrew, Scoop or the GitHub releases); run from this package, qqq ui says where to get it.

Install

The package is published to GitHub Packages, which needs a GitHub token with read:packages even for public packages:

echo "@qrun-io:registry=https://npm.pkg.github.com" >> ~/.npmrc
npm login --registry=https://npm.pkg.github.com      # once, with that token
npm install -g @qrun-io/qqq-cli
qqq --version

Requires Node.js 20 or later. Without Node, use a binary: curl -fsSL https://raw.githubusercontent.com/QRun-IO/qqq-cli/main/scripts/install.sh | sh, brew install qrun-io/tap/qqq, or scoop bucket add qrun https://github.com/QRun-IO/scoop-bucket; scoop install qqq.

Quick start

Against the QQQ sample server on http://localhost:8077 (MOCK authentication):

$ qqq login --server http://localhost:8077 --profile sample
Signed in to http://localhost:8077 (mock authentication) as profile "sample"; sign-in kept in the macos-keychain.

$ qqq table query person -w "id <= 3" --fields id,firstName,lastName
Id  First Name  Last Name
--  ----------  ---------
1   Avery       Sample
2   Blair       Sample
3   Casey       Sample
(3 records; filter: id LESS_THAN_OR_EQUALS 3)
qqq whoami                                           # the user, server, UI API version and extensions
qqq home                                             # what you may open, with the command for each
qqq table get person 1                               # one record, by section
qqq table query person -g "(firstName = Avery OR firstName = Blair) AND birthDate > now(-40y)"
qqq table create pet --set name=Pixel --set personId=2 --set speciesId=Dog
qqq table export person -w "id <= 5" --order -id --fields id,firstName,email -o people.xlsx
qqq alerts get-inbox --columns id,severity,title    # extension lists print as sub-tables
qqq process run greetInteractive -r 1,2 -v greetingPrefix=Hi
qqq api getTableMetaData --path tableName=person -Q 'fields.*.label'
qqq doctor                                           # connection, sign-in and terminal checks

Commands

qqq <noun> <verb> [arguments] [options]; qqq <noun> --help lists the verbs and qqq <noun> <verb> --help the options.

Noun Verbs
table list, describe, query, count, stats, get, create, copy, update, delete, export, children, download, variants, columns, actions, bulk-insert, bulk-edit, bulk-delete, apis, api-doc, api-call, developer, widget-form
process list, describe, run (every step screen, async jobs with progress, Ctrl-C cancels on the server)
home, find, apps, search, tail, whoami landing page, command palette, app homes, global search, live event stream, current user
report, saved-report, saved-view, share, bulk-profile, audit, widget, script, job, prefs, help-search reports, saved reports, saved views, sharing, bulk-load mappings, audits, widgets as text, scripts, jobs, preferences, help
api <operationId> any UI API operation by id
extensions, esb, collab, health, alerts, ... one noun per extension, run when the server has it installed
login, logout, config, cache, completion, doctor sign-in, profiles and settings, the metadata cache, shell completion (bash, zsh, fish, PowerShell), checks

Global options, anywhere on the line: --server <url>, -p, --profile <name>, -O, --output json|table|text|csv|yaml, --json, -Q, --query <jmespath>, --fields <names>, -y, --yes, --utc, --trace. Output is a table on a terminal and JSON in a pipe; extension results print their scalars as key/value rows and each list as a sub-table fitted to the terminal (--columns chooses, --json shows everything).

Flag convention: -o, --out <file> is the output file on every command that writes one; the sort is --order <field...> (prefix - for descending; no short form). Until 1.1, -o still sorts on table query, saved-view save and saved-report preview/set, with a deprecation note.

Exit codes: 0 ok, 1 error, 2 usage or bad filter, 3 auth, 4 server unreachable or rate limited, 5 not found, 6 validation, 70 server error, 130 interrupted.

Sign-in

Server authentication What qqq login does
OAUTH2, AUTH_0 OAuth2 device-authorization grant (RFC 8628); --browser uses the authorization code with PKCE on a loopback redirect. Tokens are refreshed before they expire; qqq logout --provider-logout revokes them at the provider.
TABLE_BASED --username <user>; the password is asked for, or read from QQQ_PASSWORD.
MOCK, FULLY_ANONYMOUS a server session from POST /qqq/v1/manageSession.

Sign-ins are stored per profile in the OS keyring (macOS Keychain, Secret Service on Linux, DPAPI on Windows), or in a 0600 file with QQQ_KEYRING=file. QQQ_TOKEN overrides the stored sign-in with a bearer token, for scripts and CI.

Configuration and environment

Variable Effect
QQQ_SERVER, QQQ_PROFILE the server or profile when --server / --profile are not given
QQQ_TOKEN a bearer token instead of the stored sign-in
QQQ_PASSWORD the TABLE_BASED password, instead of a prompt
QQQ_OUTPUT the default output format
QQQ_KEYRING=file keep sign-ins in a 0600 file instead of the OS keyring
QQQ_CONFIG_DIR, QQQ_STATE_DIR, QQQ_CACHE_DIR profiles and settings (~/.config/qqq), histories (~/.local/state/qqq), metadata cache (~/.cache/qqq)
QQQ_EXTENSION_CHECK=off skip the installed-extension check (for a mock server)

Use it as a library

The package also exports the program, so a tool can run CLI command lines in-process (the terminal UI's : line does this):

import { runCli } from '@qrun-io/qqq-cli/program'

let out = ''
const code = await runCli(['table', 'count', 'person', '-w', 'id <= 3', '-O', 'json'], {
  stdout: (text) => { out += text },
  stderr: (text) => process.stderr.write(text),
})
console.log(code, JSON.parse(out))   // 0 { count: 3 }

runCli uses the same profiles and sign-ins as qqq; prompts are off, so pass every value or --yes. createProgram() returns the commander program itself. For building a client of your own, use @qrun-io/qqq-core and @qrun-io/qqq-ui-api-client directly.

Compatibility and versions

  • Servers: UI API 1.6.0 up to, not including, 2.0 (QQQ 4.1.0-RC.15 or later). qqq --version prints the supported range and qqq doctor checks the server.
  • The CLI follows semver. Its workspace dependencies (@qrun-io/qqq-core, @qrun-io/qqq-ui-api-client, @qrun-io/qqq-ui-api-conformance) are pinned exactly and released together with it.

More

Apache-2.0