qo [cue-oh] noun.
- Abbreviation for "Query & Out".
- The peace of mind obtained by filtering data with SQL instead of complex syntax.
qo is a minimalist TUI that lets you query JSON, CSV, and TSV files using SQL.
"Query" what you need, and get it "Out" to the pipeline.
- Muscle Memory: Use the SQL syntax you've known for years.
- Pipeline Native: Reads from
stdin, writes tostdout. - Interactive: Don't guess the query. See the result, then hit Enter.
brew install kiki-ki/tap/qocurl -sfL https://raw.githubusercontent.com/kiki-ki/go-qo/main/install.sh | shgo install github.com/kiki-ki/go-qo/cmd/qo@latestqo reads from both file arguments and standard input (stdin).
# Interactive mode (Open TUI)
cat x.json | qo
qo x.json y.json
# Non-interactive mode (Direct output)
cat x.json | qo -q "SELECT * FROM tmp WHERE id > 100"
qo -q "SELECT * FROM x JOIN y ON x.id = y.x_id" x.json y.json"TUI mode works seamlessly with pipes. Explore data interactively, then pass the result to other tools.
# Fetch JSON API > Filter interactively with qo > Format with jq
curl -s https://api.github.com/repos/kiki-ki/go-qo/commits | qo | jq '.[].sha'
# Explore > Filter > Compress
cat large.json | qo | gzip > filtered.json.gzUse SQL to analyze structured data.
# Filter error logs
cat app.log | qo -q "SELECT timestamp, message FROM tmp WHERE level = 'error'"
# Aggregate sales by region
qo -i csv sales.csv -o csv -q "SELECT region, SUM(amount) FROM sales GROUP BY region"Transform between various formats.
qo -o csv data.json -q "SELECT id, name FROM data" # JSON β CSV
qo -i csv -o json users.csv -q "SELECT * FROM users" # CSV β JSON
qo -o jsonl data.json -q "SELECT * FROM data" # JSON β JSON Lines
qo -i csv --no-header raw.csv -q "SELECT col1, col2 FROM raw" # Headerless CSV| Flag | Short | Default | Description |
|---|---|---|---|
--input |
-i |
json | Input format: json, csv, tsv ("json" includes "jsonl") |
--output |
-o |
json | Output format: json, jsonl, csv, tsv, table |
--query |
-q |
Run SQL query directly (Skip TUI) | |
--no-header |
Treat first row as data, not header (CSV/TSV only) |
| Key | Mode | Action |
|---|---|---|
Tab |
ALL | Switch between Query/Table mode |
Esc / Ctrl+C |
ALL | Quit (Output nothing) |
Enter |
QUERY | Output result to stdout and Exit |
β β / j k |
TABLE | Scroll rows |
β β / h l |
TABLE | Scroll columns |
qo uses SQLite as its SQL engine. All queries follow SQLite syntax and support its built-in functions.
Use SQLite's json_extract() function to access nested fields in JSON data.
# Sample data: [{"user": {"name": "Alice", "age": 30}}, {"user": {"name": "Bob", "age": 25}}]
# Extract nested fields
qo data.json -q "SELECT json_extract(user, '$.name') AS name FROM data"
# Filter by nested value
qo data.json -q "SELECT * FROM data WHERE json_extract(user, '$.age') > 25"For more details, see SQLite JSON Functions.
| Category | Library |
|---|---|
| TUI Framework | Bubble Tea |
| Styling | Lip Gloss |
| CLI | Cobra |
| SQL Engine | modernc.org/sqlite (Pure Go, CGO-free) |
MIT