{"id":13442278,"url":"https://github.com/borkdude/jet","last_synced_at":"2025-04-11T20:37:37.419Z","repository":{"id":40921396,"uuid":"197630288","full_name":"borkdude/jet","owner":"borkdude","description":"CLI to transform between JSON, EDN, YAML and Transit using Clojure","archived":false,"fork":false,"pushed_at":"2024-10-03T17:03:58.000Z","size":354,"stargazers_count":695,"open_issues_count":10,"forks_count":42,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-04-04T00:03:48.601Z","etag":null,"topics":["cli","clojure","converter","edn","graalvm","json","transit","yaml"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/borkdude.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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},"funding":{"github":"borkdude"}},"created_at":"2019-07-18T17:30:47.000Z","updated_at":"2025-03-30T00:45:51.000Z","dependencies_parsed_at":"2024-01-14T03:48:17.796Z","dependency_job_id":"7aa5da4d-15aa-4a0f-8484-b2e887635713","html_url":"https://github.com/borkdude/jet","commit_stats":{"total_commits":263,"total_committers":28,"mean_commits":9.392857142857142,"dds":0.1368821292775665,"last_synced_commit":"1b126c051fb858708f30eca6d57eaded172d79b2"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/borkdude%2Fjet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/borkdude%2Fjet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/borkdude%2Fjet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/borkdude%2Fjet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/borkdude","download_url":"https://codeload.github.com/borkdude/jet/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248477970,"owners_count":21110608,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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","clojure","converter","edn","graalvm","json","transit","yaml"],"created_at":"2024-07-31T03:01:43.832Z","updated_at":"2025-04-11T20:37:37.394Z","avatar_url":"https://github.com/borkdude.png","language":"Clojure","readme":"\u003cimg src=\"logo/logo-300dpi.png\" width=\"140px\"\u003e\n\n[![CircleCI](https://circleci.com/gh/borkdude/jet/tree/master.svg?style=shield)](https://circleci.com/gh/borkdude/jet/tree/master)\n[![Clojars Project](https://img.shields.io/clojars/v/borkdude/jet.svg)](https://clojars.org/borkdude/jet)\n[![cljdoc badge](https://cljdoc.org/badge/borkdude/jet)](https://cljdoc.org/d/borkdude/jet/CURRENT)\n\nCLI to transform between [JSON](https://www.json.org/), [EDN](https://github.com/edn-format/edn), [YAML](https://yaml.org/) and [Transit](https://github.com/cognitect/transit-format) using Clojure.\n\n## Quickstart\n\n``` shellsession\n$ bash \u003c \u003c(curl -s https://raw.githubusercontent.com/borkdude/jet/master/install)\n$ echo '{:a 1}' | jet --to json\n{\"a\":1}\n```\n\n## Rationale\n\nThis is a command line tool to transform between JSON, EDN and Transit using\nClojure. It runs as a GraalVM binary with fast startup time which makes it\nsuited for shell scripting. It may seem familiar to users of `jq`.\n\n## Installation\n\n### Brew\n\nLinux and macOS binaries are provided via brew.\n\nInstall:\n\n    brew install borkdude/brew/jet\n\nUpgrade:\n\n    brew upgrade jet\n\n### Windows\n\nOn Windows you can install using [scoop](https://scoop.sh/) and the\n[scoop-clojure](https://github.com/littleli/scoop-clojure) bucket.\n\n### ASDF\n\njet can be installed with [asdf version manager](https://asdf-vm.com).\nMore information on the [plugin page](https://github.com/rynkowsg/asdf-jet).\n\n### Installer script\n\nInstall via the installer script:\n\n``` shellsession\n$ bash \u003c(curl -s https://raw.githubusercontent.com/borkdude/jet/master/install)\n```\n\nBy default this will install into `/usr/local/bin`. To change this, provide the directory name:\n\n``` shellsession\n$ bash \u003c(curl -s https://raw.githubusercontent.com/borkdude/jet/master/install) /tmp\n```\n\n### Download\n\nYou may also download a binary from [Github](https://github.com/borkdude/jet/releases).\n\n### JVM\n\n#### Leiningen\n\nThis tool can also be used via the JVM. If you use leiningen, you can put the\nfollowing in your `.lein/profiles`:\n\n``` clojure\n{:user\n {:dependencies [[borkdude/jet \"0.4.23\"]]\n  :aliases {\"jet\" [\"run\" \"-m\" \"jet.main\"]}}}\n```\n\nAnd then call `jet` like:\n\n``` shellsession\n$ echo '[\"^ \",\"~:a\",1]' | lein jet --from transit --to edn\n{:a 1}\n```\n\n#### Deps.edn\n\nIn `deps.edn`:\n\n``` clojure\n:jet {:deps {borkdude/jet {:mvn/version \"0.4.23\"}}\n      :exec-fn jet.main/exec\n      :main-opts [\"-m\" \"jet.main\"]}\n```\n\nYou can use both the `-M` and `-X` style invocation, whichever you prefer:\n\n``` clojure\n$ echo '[1 2 3]' | clj -M:jet --colors --func '#(-\u003e % first inc)'\n2\n\n$ echo '[1 2 3]' | clj -X:jet :colors true :thread-last '\"(map inc)\"'\n(2 3 4)\n```\n\nOr install jet as a clj tool:\n\n``` clojure\n$ clojure -Ttools install-latest :lib io.github.borkdude/jet :as jet\n\n$ echo '[1 2 3]' | clj -Tjet exec :colors true :func '\"#(-\u003e % first inc)\"'\n2\n```\n\n## Usage\n\n`jet` supports the following options:\n\n``` shell\n  -i, --from            [ edn | transit | json | yaml ] defaults to edn.\n  -o, --to              [ edn | transit | json | yaml ] defaults to edn.\n  -t, --thread-last                                     implicit thread last\n  -T, --thread-first                                    implicit thread first\n  -f, --func                                            a single-arg Clojure function, or a path to a file that contains a function, that transforms input.\n      --no-pretty                                       disable pretty printing\n  -k, --keywordize      [ \u003ckey-fn\u003e ]                    if present, keywordizes JSON/YAML keys. The default transformation function is keyword unless you provide your own.\n      --colors          [ auto | true | false]          use colored output while pretty-printing. Defaults to auto.\n      --edn-reader-opts                                 options passed to the EDN reader.\n      --no-commas                                       remove commas from EDN\n  -c, --collect                                         given separate values, collects them in a vector.\n  -h, --help                                            print this help text.\n  -v, --version                                         print the current version of jet.\n  -q, --query                                           DEPRECATED, prefer -t, -T or -f. Given a jet-lang query, transforms input.\n```\n\nTransform EDN using `--thread-last`, `--thread-first` or `--func`.\n\nExamples:\n\n``` shellsession\n$ echo '{\"a\": 1}' | jet --from json --to edn\n{\"a\" 1}\n\n$ echo '{\"a\": 1}' | jet -i json --keywordize -o edn\n{:a 1}\n\n$ echo '{\"my key\": 1}' | jet -i json -k '#(keyword (str/replace % \" \" \"_\"))' -o edn\n{:my_key 1}\n\n$ echo '{\"anApple\": 1}' | jet -i json -k '#(-\u003e % csk/-\u003ekebab-case keyword)' -o edn\n{:an-apple 1}\n\n$ echo '{\"a\": 1}' | jet -i json -o yaml\na: 1\n\n$ echo '{\"a\": 1}' | jet -i json -o transit\n[\"^ \",\"a\",1]\n\n$ echo '{:a {:b {:c 1}}}' | jet --thread-last ':a :b :c'\n1\n\n$ echo '{:a {:b {:c 1}}}' | jet --func '#(-\u003e % :a :b :c)'\n1\n\n$ echo '{:a {:b {:c [1 2]}}}' | jet -t ':a :b :c (map inc)'\n(2 3)\n\n$ cat /tmp/fn.clj\n#(-\u003e % :a :b :c)\n$ echo '{:a {:b {:c 1}}}' | jet --func /tmp/fn.clj\n1\n\n$ echo '{:a {:a 1}}' | ./jet -t '(s/transform [s/MAP-VALS s/MAP-VALS] inc)'\n{:a {:a 2}}\n```\n\n## Raw output\n\nGet raw output from query rather than wrapped in quotes:\n\n```shellsession\n$ echo '{\"a\": \"hello there\"}' | jet --from json --keywordize -t \":a\" --to edn\n\"hello there\"\n\n$ echo '{\"a\": \"hello there\"}' | jet --from json --keywordize -t \":a symbol\" --to edn\nhello there\n```\n\nor simply use `println` to get rid of the quotes:\n\n``` clojure\n$ echo '{\"a\": \"hello there\"}' | jet --from json --keywordize -t \":a println\" --to edn\nhello there\n```\n\n## Data readers\n\nYou can enable data readers by passing options to `--edn-reader-opts`:\n\n``` shell\n$ echo '#foo{:a 1}' | jet --edn-reader-opts '{:default tagged-literal}'\n#foo {:a 1}\n$ echo '#foo{:a 1}' | jet --edn-reader-opts \"{:readers {'foo (fn [x] [:foo x])}}\"\n[:foo {:a 1}]\n```\n\nSee this [blog](https://insideclojure.org/2018/06/21/tagged-literal/) by Alex Miller for more information on the `tagged-literal` function.\n\nSince jet 0.0.14 `--edn-reader-opts` defaults to `{:default tagged-literal}`.\n\n## Streaming\n\nJet supports streaming over multiple values, without reading the entire input\ninto memory:\n\n``` shellsession\n$ echo '{\"a\": 1} {\"a\": 1}' | jet --from json --keywordize -t ':a' --to edn\n1\n1\n```\n\nWhen you want to collect multiple values into a vector, you can use `--collect`:\n\n``` shellsession\n$ echo '{\"a\": 1} {\"a\": 1}' | lein jet --from json --keywordize --collect --to edn\n[{:a 1} {:a 1}]\n```\n\n## Specter\n\nAs of version `0.2.18` the [specter](https://github.com/redplanetlabs/specter) library is available in `--func`, `--thread-first` and `--thread-last`:\n\n``` clojure\n$ echo '{:a {:a 1}}' | ./jet -t '(s/transform [s/MAP-VALS s/MAP-VALS] inc)'\n{:a {:a 2}}\n```\n\n## Base64\n\nTo encode and decode base64 you can use `base64/encode` and `base64/decode`.\n\n## Jet utility functions\n\nIn the `jet` namespace, the following utilities are available:\n\n### `paths`\n\nReturn all paths (and sub-paths) in maps and vectors. Each result is a map of `:path` and `:val` (via `get-in`).\n\n``` clojure\n$ echo '{:a {:b [1 2 3 {:x 2}] :c {:d 3}}}' | jet -t '(jet/paths)'\n[{:path [:a], :val {:b [1 2 3 {:x 2}], :c {:d 3}}}\n {:path [:a :b], :val [1 2 3 {:x 2}]}\n {:path [:a :c], :val {:d 3}}\n {:path [:a :b 0], :val 1}\n {:path [:a :b 1], :val 2}\n {:path [:a :b 2], :val 3}\n {:path [:a :b 3], :val {:x 2}}\n {:path [:a :b 3 :x], :val 2}\n {:path [:a :c :d], :val 3}]\n```\n\n### `when-pred`\n\nGiven a predicate, return predicate that returns the given argument when\npredicate was truthy. In case of an exception during the predicate call, catches\nand returns `nil`.\n\nThe following returns all paths for which the leafs are odd numbers:\n\n``` clojure\n$ echo '{:a {:b [1 2 3 {:x 2}] :c {:d 3}}}' | jet -t '(jet/paths) (filter (comp (jet/when-pred odd?) :val)) (mapv :path)'\n[[:a :b 0] [:a :b 2] [:a :c :d]]\n```\n\n## Emacs integration\n\nSometimes it's useful to reformat REPL output in Emacs to make it more\nreadable, copy to clipboard or just pretty-print to another buffer.\nAll of that is avaiable in the [jet.el](https://github.com/ericdallo/jet.el) package.\n\n## Vim integration\n\nTo convert data in vim buffers, you can select the data you want to convert in visual mode,\nthen invoke `jet` by typing for example `:'\u003c,'\u003e!jet -k --from json` (vim will insert the \n`'\u003c,'\u003e` for you as you type).\n\n## Test\n\nTest the JVM version:\n\n    script/test\n\nTest the native version:\n\n    JET_TEST_ENV=native script/test\n\n## Build\n\nYou will need leiningen and GraalVM.\n\n    script/compile\n\n## License\n\nCopyright © 2019-2023 Michiel Borkent\n\nDistributed under the EPL License, same as Clojure. See LICENSE.\n","funding_links":["https://github.com/sponsors/borkdude"],"categories":["Clojure","clojure"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fborkdude%2Fjet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fborkdude%2Fjet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fborkdude%2Fjet/lists"}