diff --git a/README.md b/README.md
index c017a9f..bd58746 100644
--- a/README.md
+++ b/README.md
@@ -56,8 +56,8 @@ curl ... | fx .
### Reducers
-Write reducers in your favorite language: [JavaScript](docs/reducers.md#node) (default),
-[Python](docs/reducers.md#python), or [Ruby](docs/reducers.md#ruby).
+Write reducers in your favorite language: [JavaScript](doc/doc.md#reducers) (default),
+[Python](doc/doc.md#python), or [Ruby](doc/doc.md#ruby).
```bash
export FX_LANG=node
@@ -76,7 +76,7 @@ fx data.json 'x.to_a.map {|x| x[1]}'
## Documentation
-See full [documentation](https://github.com/antonmedv/fx/blob/master/DOCS.md).
+See full [documentation](doc/doc.md).
## Themes
@@ -87,8 +87,8 @@ to `9`:
export FX_THEME=9
```
-
+
## License
-[MIT](https://github.com/antonmedv/fx/blob/master/LICENSE)
+[MIT](LICENSE)
diff --git a/doc/doc.md b/doc/doc.md
new file mode 100644
index 0000000..4e52a17
--- /dev/null
+++ b/doc/doc.md
@@ -0,0 +1,192 @@
+# Documentation
+
+`fx` can work in two modes: as reducer or interactive.
+To start interactive mode pipe any JSON into `fx`:
+
+```sh
+$ curl ... | fx
+```
+
+Or you can pass a filename as the first parameter:
+
+```sh
+$ fx data.json
+```
+
+## Reducers
+
+If any additional arguments was passed, fx converts it to a function which takes
+JSON as argument named `x`.
+
+By default, fx uses builtin JavaScript VM ([goja](https://github.com/dop251/goja)),
+but fx also can be used with [node](#node), [python](#python), or [ruby](#ruby).
+
+### JavaScript
+
+```sh
+FX_LANG=js
+```
+
+An example of anonymous function used as reducer:
+```sh
+$ echo '{"foo": [{"bar": "value"}]}' | fx 'x => x.foo[0].bar'
+value
+```
+
+The same reducer function can be simplified to:
+
+```sh
+$ echo '{"foo": [{"bar": "value"}]}' | fx 'x.foo[0].bar'
+value
+```
+
+Each argument treated as a reducer function.
+
+```sh
+$ echo '{"foo": [{"bar": "value"}]}' | fx 'x.foo' 'x[0]' 'x.bar'
+value
+```
+
+Update JSON using the spread operator:
+
+```sh
+$ echo '{"name": "fx", "count": 0}' | fx '{...this, count: 1}'
+{
+ "name": "fx",
+ "count": 1
+}
+```
+
+### Dot
+
+Fx supports simple JS-like syntax for accessing data, which can be used with any
+`FX_LANG`.
+
+```sh
+$ echo '{"foo": [{"bar": "value"}]}' | fx .foo[0].bar
+value
+```
+
+### .fxrc.js
+
+Create _.fxrc.js_ file in `$HOME` directory, and define some useful functions.
+
+```js
+// .fxrc.js
+function upper(s) {
+ return s.toUpperCase()
+}
+```
+
+```sh
+$ cat data.json | fx .name upper
+ANTON
+```
+
+### Node
+
+```sh
+FX_LANG=node
+```
+
+### Npm packages
+
+Use any npm package by installing it globally. Create _.fxrc.js_ file in `$HOME`
+directory, and require any packages or define global functions.
+
+For example, access all lodash methods without `_` prefix.
+
+Put next line your _.fxrc.js_ file:
+
+```js
+Object.assign(global, require('lodash/fp'))
+```
+
+And now you will be able to call all lodash methods. For example, see who's been committing to react recently:
+
+```sh
+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
+```
+
+> To be able to require global modules make sure you have correct `NODE_PATH` env variable.
+> ```sh
+> export NODE_PATH=`npm root -g`
+> ```
+
+The _.fxrc.js_ file supports both: import and require.
+
+```js
+import 'zx/globals'
+const _ = require('lodash')
+```
+
+> With you want to use _.fxrc.js_ for both `FX_LANG=js` and `FX_LANG=node`,
+> separate parts by `// nodejs:` comment:
+> ```js
+> function upper(s) {
+> return s.toUpperCase()
+> }
+> // nodejs:
+> import 'zx/globals'
+> const _ = require('lodash')
+> ```
+
+### Python
+
+```sh
+FX_LANG=python
+```
+Or
+```sh
+FX_LANG=python3
+```
+
+Example:
+
+```sh
+fx data.json '[x["age"] + i for i in range(10)]'
+```
+
+### Ruby
+
+```sh
+FX_LANG=ruby
+```
+
+Example:
+
+```sh
+fx data.json 'x.to_a.map {|x| x[1]}'
+```
+
+## Streaming mode
+
+`fx` supports line-delimited JSON streaming and concatenated JSON streaming.
+
+```sh
+$ kubectl logs ... | fx .message
+```
+
+## Interactive mode
+
+Type `?` to see full list of available shortcuts while in interactive mode.
+
+### Search
+
+Press `/` and type regexp pattern to search in current JSON.
+Search is performed on internal representation of the JSON without newlines.
+
+Type `n` to jump to next result, and `N` to previous.s
+
+### Selecting text
+
+You can't just select text in fx. This is due the fact that all mouse events are
+redirected to stdin. To be able to select again you need instruct your terminal
+not to do it. This can be done by holding special keys while selecting:
+
+| Key | Terminal |
+|------------------|---------------|
+| `Option`+`Mouse` | iTerm2, Hyper |
+| `Fn`+`Mouse` | Terminal.app |
+| `Shift`+`Mouse` | Linux |
diff --git a/docs/images/preview.png b/doc/images/preview.png
similarity index 100%
rename from docs/images/preview.png
rename to doc/images/preview.png
diff --git a/docs/images/themes.png b/doc/images/themes.png
similarity index 100%
rename from docs/images/themes.png
rename to doc/images/themes.png
diff --git a/docs/reducers.md b/docs/reducers.md
deleted file mode 100644
index ce648be..0000000
--- a/docs/reducers.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# Reducers
-
-Fx takes a few arguments after the file name, and converts them to a reducer.
-
-## Node
-
-Access all lodash (or ramda, etc) methods by using [.fxrc](#using-fxrc) file.
-
-```bash
-$ fx data.json 'groupBy("commit.committer.name")' 'mapValues(_.size)'
-```
-
-## Python
-
-TODO
-
-## Ruby
-
-TODO