{"id":23243094,"url":"https://github.com/clux/lq","last_synced_at":"2026-02-27T21:35:21.465Z","repository":{"id":191813664,"uuid":"685161097","full_name":"clux/lq","owner":"clux","description":"jq compatible yq/tq implementation in rust","archived":false,"fork":false,"pushed_at":"2026-01-01T14:05:26.000Z","size":229,"stargazers_count":43,"open_issues_count":11,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-01-14T11:38:32.597Z","etag":null,"topics":["cli","jq","toml","tq","yaml","yq"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/clux.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["clux"]}},"created_at":"2023-08-30T16:36:09.000Z","updated_at":"2026-01-01T14:05:30.000Z","dependencies_parsed_at":"2023-10-01T16:32:53.145Z","dependency_job_id":"b8b6b33c-f1aa-4472-b78c-d080b1dc2d53","html_url":"https://github.com/clux/lq","commit_stats":{"total_commits":162,"total_committers":3,"mean_commits":54.0,"dds":"0.12962962962962965","last_synced_commit":"1689c74c2c9d608ec72c89bcde15256222c8ca60"},"previous_names":["clux/yq","clux/lq"],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/clux/lq","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clux%2Flq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clux%2Flq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clux%2Flq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clux%2Flq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/clux","download_url":"https://codeload.github.com/clux/lq/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clux%2Flq/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29915345,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T19:37:42.220Z","status":"ssl_error","status_checked_at":"2026-02-27T19:37:41.463Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","jq","toml","tq","yaml","yq"],"created_at":"2024-12-19T06:09:39.773Z","updated_at":"2026-02-27T21:35:21.449Z","avatar_url":"https://github.com/clux.png","language":"Rust","funding_links":["https://github.com/sponsors/clux"],"categories":[],"sub_categories":[],"readme":"# lq - low overhead yq/tq/jq cli\n[![CI](https://github.com/clux/lq/actions/workflows/release.yml/badge.svg)](https://github.com/clux/lq/actions/workflows/release.yml)\n[![Crates.io](https://img.shields.io/crates/v/lq.svg)](https://crates.io/crates/lq)\n[![dependency status](https://deps.rs/repo/github/clux/lq/status.svg)](https://deps.rs/repo/github/clux/lq)\n\nA lightweight and portable [jq](https://jqlang.github.io/jq/) style cli for doing jq queries/filters/maps/transforms on **YAML**/**TOML**/**JSON** documents by converting to **JSON** and passing data to `jq`. Output is raw `jq` output which can optionally be mapped to TOML or YAML.\n\n## Installation\n\nVia cargo:\n\n```sh\ncargo install lq\n```\n\nor download a prebuilt from [releases](https://github.com/clux/lq/releases) either manually, or via [binstall](https://github.com/cargo-bins/cargo-binstall):\n\n```sh\ncargo binstall lq\n```\n\n**Note**: Requires `jq`.\n\n## Why / Why Not\n\n### jq compatibility\n\n- arbitrary `jq` usage on any input format (yaml/toml/json) by going through json and jq\n- [same syntax](https://jqlang.github.io/jq/manual/), same filters, types, operators, conditionals, regexes, assignment, modules, etc\n- matches `jq`'s cli interface (only some extra input/output format controlling flags)\n- supports `jq` output formatters such as `-c`, `-r`, and `-j` (compact, raw, joined output resp)\n\n### Extra Features\n\n- supports __multidoc yaml__ input, handles [yaml merge keys](https://yaml.org/type/merge.html) (expanding tags)\n- supports __multidoc__ document splitting into expression based filenames\n- supports __in-place edits__ of documents\n- maintains __key order__ even while roundtripping between formats\n- reads from __stdin xor file__ (file if last arg is a file)\n- filetype format inference when passing files\n- quick input/output flags: `-y` (YAML out) or `-t` (TOML out), `-T` (TOML in), `-J` (JSON in)\n\n### Portable yq replacement\n\n- ~[1MB](https://github.com/clux/lq/releases/latest) in binary (for small CI images / [binstalled ci actions](https://github.com/cargo-bins/cargo-binstall#faq))\n- 99% replacement of [python-yq](https://kislyuk.github.io/yq/) (with `yq` named/linked to `lq`)\n\n### Limitations\n\n- Shells out to `jq` (not standalone - [for now](https://github.com/clux/lq/issues/64))\n- Expands [YAML tags](https://yaml.org/spec/1.2-old/spec.html#id2764295) (input is [singleton mapped](https://docs.rs/serde_yaml/latest/serde_yaml/with/singleton_map/index.html) -\u003e [recursively](https://docs.rs/serde_yaml/latest/serde_yaml/with/singleton_map_recursive/index.html), then [merged](https://docs.rs/serde_yaml/latest/serde_yaml/value/enum.Value.html#method.apply_merge)) - so tags are [not preserved](https://github.com/clux/lq/issues/12) in the output\n- Does not preserve indentation (unsupported in [serde_yaml](https://github.com/dtolnay/serde-yaml/issues/337))\n- Halts on [duplicate keys](https://github.com/clux/lq/issues/14) in the input document\n- Formats require a [serde implementation](https://serde.rs/#data-formats).\n- Limited format support. No XML/CSV/RON support (or other more exotic formats). [KDL wanted](https://github.com/clux/lq/issues/56).\n\n## Usage\n\n### YAML\nUse as [jq](https://jqlang.github.io/jq/tutorial/) either via stdin:\n\n```sh\n$ lq '.[3].kind' -r \u003c test/deploy.yaml\nService\n\n$ lq -y '.[3].metadata' \u003c test/deploy.yaml\nlabels:\n  app: controller\nname: controller\nnamespace: default\n```\n\nor from a file arg (at the end):\n\n```sh\n$ lq '.[3].kind' -r test/deploy.yaml\n$ lq -y '.[3].metadata' test/deploy.yaml\n```\n\n### TOML\n\nInfers input format from extension, or set explicitly via `-T` or `--input=toml`.\n\n```sh\n$ lq '.package.categories[]' -r Cargo.toml\ncommand-line-utilities\nparsing\n```\n\nconvert jq output back into toml (`-t`):\n\n```sh\n$ lq -t '.package.metadata' Cargo.toml\n[binstall]\nbin-dir = \"lq-{ target }/{ bin }{ format }\"\npkg-url = \"{ repo }/releases/download/{ version }lq-{ target }{ archive-suffix }\"\n```\n\nconvert jq output to yaml (`-y`) and set explicit toml input when using stdin (`-T`):\n\n```sh\n$ lq -Ty '.dependencies.clap' \u003c Cargo.toml\nfeatures:\n- cargo\n- derive\nversion: 4.4.2\n```\n\njq style compact output:\n\n```sh\n$ lq '.profile' -c Cargo.toml\n{\"release\":{\"lto\":true,\"panic\":\"abort\",\"strip\":\"symbols\"}}\n```\n\nTo shortcut passing input formats, you can add `alias tq='lq --input=toml'` in your `.bashrc` / `.zshrc` (etc).\n\n### JSON Input\n\nInfers input format from extension, or set explicitly via `-J` or `--input=json`.\n\n```sh\n$ lq -Jy '.ingredients | keys' \u003c test/guacamole.json\n- avocado\n- coriander\n- cumin\n- garlic\n- lime\n- onions\n- pepper\n- salt\n- tomatoes\n```\n\nUsing JSON input is kind of like talking to `jq` directly, with the benefit that you can change output formats, or do inplace edits.\n\n### Formats\nDefault is going from `yaml` input to `jq` output to allow further pipes into `jq`.\n\n- **Input** flags are **upper case** :: `-J` json input, `-T` toml input (shorthands for `--input=FORMAT`)\n- **Output** flags are **lower case** :: `-y` yaml output, `-t` toml output (shorthands for `--output=FORMAT`)\n\nEx;\n- `lq` :: yaml -\u003e jq output\n- `lq -t` :: yaml -\u003e toml\n- `lq -y`  :: yaml -\u003e yaml\n- `lq -Tt` :: toml -\u003e toml\n- `lq -Jy` :: json -\u003e yaml\n- `jq -Ty` :: toml -\u003e yaml\n- `jq -Jt` :: json -\u003e toml\n\nOutput formatting such as `-y` for YAML or `-t` for TOML will require the output from `jq` to be parseable json.\nIf you pass on `-r`,`-c` or `-c` for raw/compact output, then this output may not be parseable as json.\n\n### Advanced Features\nTwo things you cannot do in `jq`:\n\n#### Multidoc Splits\nSplit a bundle of yaml files into a yaml file per Kubernetes `.metadata.name` key:\n\n```sh\nmkdir -p crds\ncurl -sSL https://github.com/prometheus-operator/prometheus-operator/releases/download/v0.82.1/stripped-down-crds.yaml \\\n  | lq . -y --split '\"crds/\" + (.metadata.name) + \".yaml\"'\n```\n\n#### In Place Edits\nPatch a json file ([without multiple pipes](https://github.com/jqlang/jq/issues/105)):\n\n```sh\nlq -i '.SKIP_HOST_UPDATE=true' ~/.config/discord/settings.json\n```\n\n### Advanced jq\nAny weird things you can do with `jq` works. Some common (larger) examples:\n\n#### Selects\n\nSelect on yaml multidoc:\n\n```sh\n$ lq '.[] | select(.kind == \"Deployment\") | .spec.template.spec.containers[0].ports[0].containerPort' test/deploy.yaml\n8000\n```\n\nEscaping keys with slashes etc in them:\n\n```sh\nlq '.updates[] | select(.[\"package-ecosystem\"] == \"cargo\") | .groups' .github/dependabot.yml\n```\n\n#### Modules\nYou can import [jq modules](https://jqlang.github.io/jq/manual/#modules) e.g. [k.jq](https://github.com/clux/lq/blob/main/test/modules/k.jq):\n\n```sh\n$ lq 'include \"k\"; .[] | gvk' -r -L$PWD/test/modules \u003c test/deploy.yaml\nv1.ServiceAccount\nrbac.authorization.k8s.io/v1.ClusterRole\nrbac.authorization.k8s.io/v1.ClusterRoleBinding\nv1.Service\napps/v1.Deployment\n```\n\n### Debug Logs\n\nThe project respects `RUST_LOG` when set, and sends these diagnostic logs to stderr:\n\n```sh\n$ RUST_LOG=debug lq '.version' test/circle.yml\n2023-09-18T23:17:04.533055Z DEBUG lq: args: Args { input: Yaml, output: Jq, yaml_output: false, toml_output: false, in_place: false, jq_query: \".version\", file: Some(\"test/circle.yml\"), compact_output: false, raw_output: false, join_output: false, modules: None }\n2023-09-18T23:17:04.533531Z DEBUG lq: found 1 documents\n2023-09-18T23:17:04.533563Z DEBUG lq: input decoded as json: {\"definitions\":{\"filters\":{\"on_every_commit\":{\"tags\":{\"only\":\"/.*/\"}},\"on_tag\":{\"branches\":{\"ignore\":\"/.*/\"},\"tags\":{\"only\":\"/v[0-9]+(\\\\.[0-9]+)*/\"}}},\"steps\":[{\"step\":{\"command\":\"chmod a+w . \u0026\u0026 cargo build --release\",\"name\":\"Build binary\"}},{\"step\":{\"command\":\"rustc --version; cargo --version; rustup --version\",\"name\":\"Version information\"}}]},\"jobs\":{\"build\":{\"docker\":[{\"image\":\"clux/muslrust:stable\"}],\"environment\":{\"IMAGE_NAME\":\"lq\"},\"resource_class\":\"xlarge\",\"steps\":[\"checkout\",{\"run\":{\"command\":\"rustc --version; cargo --version; rustup --version\",\"name\":\"Version information\"}},{\"run\":{\"command\":\"chmod a+w . \u0026\u0026 cargo build --release\",\"name\":\"Build binary\"}},{\"run\":\"echo versions\"}]},\"release\":{\"docker\":[{\"image\":\"clux/muslrust:stable\"}],\"resource_class\":\"xlarge\",\"steps\":[\"checkout\",{\"run\":{\"command\":\"rustc --version; cargo --version; rustup --version\",\"name\":\"Version information\"}},{\"run\":{\"command\":\"chmod a+w . \u0026\u0026 cargo build --release\",\"name\":\"Build binary\"}},{\"upload\":{\"arch\":\"x86_64-unknown-linux-musl\",\"binary_name\":\"${IMAGE_NAME}\",\"source\":\"target/x86_64-unknown-linux-musl/release/${IMAGE_NAME}\",\"version\":\"${CIRCLE_TAG}\"}}]}},\"version\":2.1,\"workflows\":{\"my_flow\":{\"jobs\":[{\"build\":{\"filters\":{\"tags\":{\"only\":\"/.*/\"}}}},{\"release\":{\"filters\":{\"branches\":{\"ignore\":\"/.*/\"},\"tags\":{\"only\":\"/v[0-9]+(\\\\.[0-9]+)*/\"}}}}]},\"version\":2}}\n2023-09-18T23:17:04.533650Z DEBUG lq: jq args: [\".version\"]\n2023-09-18T23:17:04.538606Z DEBUG lq: jq stdout: 2.1\n\n2.1\n```\n\n### lq as yq\nBecause yaml is the default input language, you __can__ use it as your top level `yq` executable with a symlink or alias:\n\n```sh\n# globally make yq be lq\nln -s $(which lq) /usr/local/bin/yq\n\n# alias yq to lq in shell environment only\nalias yq=lq\n```\n\nIt is mostly compatible with `python-yq` (which uses `jq` syntax) but differs from go yq (which invents its own syntax).\n\n(This use-case was the first use-case for this tool, i.e. to get rid of heavy python deps in CI images)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclux%2Flq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclux%2Flq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclux%2Flq/lists"}