FX(1)
๐ FX(1) ๐
okay bestie so this is fx, from the User Commands manual โจ โ like, the whole page header is FX(1) and the manual name is literally User Commands, but we're not gonna make a whole thing of it. this is the fx page. it's the command-line JSON processing tool and it is, genuinely, iconic ๐
๐ธ NAME ๐ธ
fx โ the command-line JSON processing tool. that's it. that's the vibe. ๐ฆ
โจ SYNOPSIS โจ
fx [code ...]
so fx has two modes: cli and interactive ๐ซถ
to start interactive mode, you literally just pipe any JSON into it:
$ curl ... | fx
or you can pass a filename as the first parameter:
$ fx my.json
and if any argument was passed, fx will apply it and print to stdout. simple as that ๐
๐ฅ DESCRIPTION ๐ฅ
start interactive mode by not passing any arguments at all:
$ curl ... | fx
or by passing a filename as the first argument:
$ fx data.json
pass a few JSON files at once, why not:
$ cat foo.json bar.json baz.json | fx .message
use the full power of JavaScript (not me being obsessed with a one-liner):
$ curl ... | fx '.filter(x => x.startsWith("a"))'
get access to all lodash (or ramda, etc) methods by using a .fxrc file:
$ curl ... |
> fx '_.groupBy("commit.committer.name")' '_.mapValues(_.size)'
update JSON using the spread operator, main character energy:
$ echo '{"count": 0}' | fx '{...this, count: 1}'
{
"count": 1
}
extract values from maps:
$ fx commits.json | fx .[].author.name
print formatted JSON to stdout:
$ curl ... | fx .
pipe a JSON logs stream into fx:
$ kubectl logs ... -f | fx .message
and bestie. try this one. just trust me:
$ fx --life
๐ง USAGE ๐ง
๐ ANONYMOUS FUNCTION
use an anonymous function as the reducer, which gets the JSON and processes it:
$ echo '{"foo": [{"bar": "value"}]}' | fx 'x => x.foo[0].bar'
value
๐ BINDING
if you don't pass an anonymous function param => ..., your code gets automatically transformed into an anonymous function. and you can get access to the JSON through the this keyword:
$ echo '{"foo": [{"bar": "value"}]}' | fx 'this.foo[0].bar'
value
๐ DOT
it's possible to omit the this keyword entirely:
$ echo '{"foo": [{"bar": "value"}]}' | fx .foo[0].bar
value
and if a single dot is passed, the input JSON gets formatted but is otherwise unaltered:
$ echo '{"foo": "bar"}' | fx .
{
"foo": "bar"
}
๐ MAP
one of the frequent operations is mapping some function over an array โ for example, extracting some values. say you have:
[
{
"author": {
"name": "antonmedv"
}
},
{...},
...
]
and we want to collect the names of each object in the array. we can do it by mapping an anonymous function:
$ cat ... | fx '.map(x => x.author.name)'
or we can do the exact same thing with jq(1)-like syntax:
$ cat ... | fx .[].author.name
[
"antonmedv",
...
]
note that [] can also be applied to map object values ๐
$ echo '{"foo": 1, "bar": 2}' | fx .[]
[1, 2]
๐ CHAINING
you can pass any number of anonymous functions for reducing the JSON:
$ echo '{"foo": [{"bar": "value"}]}' |
> fx 'x => x.foo' 'this[0]' 'this.bar'
value
๐ UPDATING
you can update existing JSON using the spread operator:
$ echo '{"count": 0}' | fx '{...this, count: 1}'
{
"count": 1
}
๐ EDIT-IN-PLACE
fx provides a function save which will save everything in place and return the saved object. lowkey important: this function can only be used with a filename as the first argument to the fx command ๐ซถ
usage:
$ fx data.json '{...this, count: this.count+1}' save .count
๐ USING PACKAGES
use any npm package by installing it globally:
$ npm install -g lodash
$ cat package.json |
> fx 'require("lodash").keys(this.dependencies)'
๐ FORMATTING ๐
if you need output other than JSON (for example, arguments for xargs), just don't return anything from the reducer. an undefined value is printed into stderr by default ๐
echo '[]' | fx 'void 0'
undefined
echo '[1,2,3]' |
fx 'this.forEach(x => console.log(+x))' 2>/dev/null |
xargs echo
1 2 3
โญ STREAMING MODE โญ
fx supports line-delimited JSON and concatenated JSON streaming ๐ฆ
$ kubectl logs ... | fx .message
note that if an object lacks a message field, undefined will be printed to stderr. this is actually useful โ it's how you see that you're skipping some objects. but if you want to hide them, just redirect stderr to /dev/null ๐
๐ FILTERING
sometimes it's necessary to omit some messages in a JSON stream, or select only specified log messages. for this purpose, fx has special helpers select/filter โ pass a function into it to select/filter JSON messages:
$ kubectl logs ... |
> fx 'select(x => x.status == 500)' .message
$ kubectl logs ... |
> fx 'filter(x => x.status < 499)' .message
and if filter/select are overridden in .fxrc, you're still able to access them with a prefix: std.select(cb) or std.filter(cd) ๐ซถ
๐ธ FILES ๐ธ
๐๏ธ USING .fxrc ๐๏ธ
Okay bestie, first up: create .fxrc in your $HOME directory, and use it to require any packages or define global functions. Itโs giving setup era โจ.
For example, you can access all the lodash methods without the _ prefix. Put this in your .fxrc file:
Object.assign(global, require('lodash/fp'))
And now youโll be able to call all lodash methods. For example, see whoโs been committing to react recently:
curl 'https://api.github.com/repos/facebook/react/commits?per_page=100' |
fx 'groupBy("commit.author.name")' 'mapValues(size)' toPairs \
'sortBy(1)' reverse 'take(10)' fromPairs
See the ENVIRONMENT section.
๐ฎ QUERY LANGUAGE ๐ฎ
If you want to use a query language, for example jsonata, you can use a helper function like this:
global.jsonata = expr => require('jsonata')(expr).evaluate
And use it like this:
curl ... |
fx 'jsonata("$sum(Order.Product.(Price * Quantity))")'
Instead, you can create this alias in your .bashrc file:
alias jsonata='FX_APPLY=jsonata fx'
And now all code arguments to jsonata will be passed through the jsonata helper. And now you can use it like this:
curl ... | jsonata '$sum(Order.Product.(Price * Quantity))'
๐ฎ INTERACTIVE MODE ๐ฎ
Click on fields to expand or collapse the JSON tree, and use the mouse wheel to scroll the view ๐ฑ๏ธ.
Here are the commands available in interactive mode:
- q or Esc or Ctrl+c โ Exit
- up or k โ Move cursor up
- left or h โ Collapse
- right or l โ Expand
- Shift+right or L โ Expand all under cursor
- Shift+left or K โ Collapse all under cursor
- e โ Expand all
- E โ Collapse all
- g โ Scroll to top
- G โ Scroll to bottom
- . โ Edit filter
- / โ Search
- n โ Find next
- p โ Exit and print JSON to stdout
- P โ Exit and print fully expanded JSON to stdout
These commands are available when editing the filter:
- Enter โ Apply filter
- Ctrl+u โ Clear filter
- Ctrl+w โ Delete last part
- up/down โ Select autocomplete
๐ SEARCHING ๐
Press / and type a regexp pattern to search in the current JSON. Search works with the currently applied filter ๐.
Examples of a pattern and the corresponding regexp:
- Pattern
/appleโ RegExp/apple/ig - Pattern
/apple/+uโ RegExp/apple/ - Pattern
/apple/u+wโ RegExp/apple/u - Pattern
\w+โ RegExp/\w+/ig
โ๏ธ SELECTING TEXT โ๏ธ
You might find that you literally canโt just select text in fx. Thatโs because all mouse events get redirected to stdin. To be able to select again, you need to tell your terminal not to do that. You can do it by holding special keys while selecting:
- Option+Mouse โ iTerm2, Hyper
- Fn+Mouse โ Terminal.app
- Shift+Mouse โ Linux
Note: you can press p/P to print everything to stdout and select in there.
๐ง MEMORY USAGE ๐ง
You may find that sometimes, on really big JSON files, fx prints an error message like this:
FATAL ERROR: JavaScript heap out of memory
V8 limits memory usage to around 2 GB by default. You can increase the limit by putting this line in your .profile:
export NODE_OPTIONS='--max-old-space-size=8192'
๐ ENVIRONMENT ๐
To be able to require global modules, make sure you have the correct NODE_PATH env variable.
๐ EXAMPLES ๐
โจ BASIC EXAMPLES โจ
$ echo '{"key": "value"}' | fx 'x => x.key'
value
$ echo '{"key": "value"}' | fx .key
value
$ echo '[1,2,3]' | fx 'this.map(x => x * 2)'
[2, 4, 6]
$ echo '{"items": ["one", "two"]}' | fx 'this.items' 'this[1]'
two
$ echo '{"count": 0}' | fx '{...this, count: 1}'
{"count": 1}
$ echo '{"foo": 1, "bar": 2}' | fx ?
["foo", "bar"]
๐ฆ OTHER EXAMPLES ๐ฆ
Convert object to array:
$ cat package.json | fx 'Object.keys(this.dependencies)'
Or by two functions:
$ cat package.json | fx .dependencies Object.keys
By the way, fx has a shortcut for Object.keys. The previous example can be rewritten as:
$ cat package.json | fx .dependencies ?
๐ SEE ALSO ๐
Thatโs the whole page, bestie! ๐ซถ The source/version is FX(1) and the date is February 2021 โ iconic, no cap ๐
โจ.
๐ฆ where this page comes from
- epel 9: fx 20.0.2-17.el9 ยท MIT and OFL
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms