simeji/jid
{ "createdAt": "2016-06-06T14:28:53Z", "defaultBranch": "master", "description": "json incremental digger", "fullName": "simeji/jid", "homepage": null, "language": "Go", "name": "jid", "pushedAt": "2026-07-04T13:24:05Z", "stargazersCount": 7133, "topics": [ "cli", "go", "golang", "jid", "json", "tool" ], "updatedAt": "2026-07-12T17:26:27Z", "url": "https://github.com/simeji/jid"}Json Incremental Digger
It’s a very simple tool. You can drill down JSON interactively by using filtering queries like jq.
Suggestion, Auto completion, and JMESPath support provide a comfortable JSON exploration experience.
Drill-down navigation
Section titled “Drill-down navigation”Interactively navigate JSON using dot-path queries. Tab-complete fields, cycle through candidates, and see the matching key highlighted in the JSON view in real time.
JMESPath expressions
Section titled “JMESPath expressions”Use pipes, wildcards, and built-in functions directly in the filter. Function candidates are shown with usage hints and argument templates are filled in automatically.
Installation
Section titled “Installation”- [With HomeBrew (for macOS)]!(#with-homebrew-for-macos)
- [With MacPorts (for macOS)]!(#with-macports-for-macos)
- [With pkg (for FreeBSD)]!(#with-pkg-for-freebsd)
- [With scoop (for Windows)]!(#with-scoop-for-windows)
- [Other package management system]!(#other-package-management-systems)
- [Simply use “jid” command]!(#simply-use-jid-command)
- [Build]!(#build)
With HomeBrew (for macOS)
Section titled “With HomeBrew (for macOS)”brew install jidWith MacPorts (for macOS)
Section titled “With MacPorts (for macOS)”sudo port install jidWith pkg (for FreeBSD)
Section titled “With pkg (for FreeBSD)”pkg install jidWith scoop (for Windows)
Section titled “With scoop (for Windows)”scoop install jidOther package management systems
Section titled “Other package management systems”Jid can install by package management systems of below OS.
Simply use “jid” command
Section titled “Simply use “jid” command”If you simply want to use jid command, please download binary from below.
https://github.com/simeji/jid/releases
go install github.com/simeji/jid/cmd/jid@latestQuick start
Section titled “Quick start”- [simple json example]!(#simple-json-example)
- [simple json example2]!(#simple-json-example2)
- [with initial query]!(#with-initial-query)
- [with curl]!(#with-curl)
simple json example
Section titled “simple json example”Please execute the below command.
echo '{"aa":"2AA2","bb":{"aaa":[123,"cccc",[1,2]],"c":321}}'| jidthen, jid will be running.
You can dig JSON data incrementally.
When you enter .bb.aaa[2], you will see the following.
[Filter]> .bb.aaa[2][ 1, 2]Then, you press Enter key and output [1,2] and exit.
simple json example2
Section titled “simple json example2”echo '{"info":{"date":"2016-10-23","version":1.0},"users":[{"name":"simeji","uri":"https://github.com/simeji","id":1},{"name":"simeji2","uri":"https://example.com/simeji","id":2},{"name":"simeji3","uri":"https://example.com/simeji3","id":3}],"userCount":3}}'|jidWith a initial query
Section titled “With a initial query”First argument of jid is initial query.
(Use JSON same as [Demo]!(#demo))
with curl
Section titled “with curl”Sample for using RDAP data.
curl -s http://rdg.afilias.info/rdap/domain/example.info | jidLoad JSON from a file
Section titled “Load JSON from a file”jid < file.jsonKeymaps
Section titled “Keymaps”| key | description |
|---|---|
TAB / CTRL + I | Show available items and choose them (cycles forward); highlights the matching key in the JSON view |
Shift + TAB | Cycle candidates backward / decrement array index |
CTRL + W | Delete one JMESPath segment backward (e.g. .id → [0] → func(@) → pipe) |
CTRL + U | Delete whole query |
CTRL + X | Toggle function description display (visible when function candidates are shown) |
CTRL + F / Right Arrow (:arrow_right:) | Move cursor a character to the right |
CTRL + B / Left Arrow (:arrow_left:) | Move cursor a character to the left |
CTRL + A | To the first character of the ‘Filter’ |
CTRL + E | To the end of the ‘Filter’ |
CTRL + J | Scroll json buffer 1 line downwards |
CTRL + K | Scroll json buffer 1 line upwards |
CTRL + G | Scroll json buffer to bottom |
CTRL + T | Scroll json buffer to top |
CTRL + N | Scroll json buffer ‘Page Down’ |
CTRL + P | Scroll json buffer ‘Page Up’ |
CTRL + L | Change view mode whole json or keys (only object) |
ESC | Hide a candidate box |
| Up Arrow | Navigate to previous query in history |
| Down Arrow | Navigate to next query in history |
Option
Section titled “Option”| option | description |
|---|---|
| First argument ($1) | Initial query |
| -h | print a help |
| -help | print a help |
| -version | print the version and exit |
| -q | Output query mode (for jq) |
| -M | monochrome output mode |
Configuration
Section titled “Configuration”jid can be configured via a TOML file located at:
| OS | Path |
|---|---|
| macOS | ~/Library/Application Support/jid/config.toml |
| Linux | ~/.config/jid/config.toml |
| Windows | %AppData%\jid\config.toml |
Example config.toml
Section titled “Example config.toml”[history]path = "~/.jid_history" # custom history file pathmax_size = 1000 # number of entries to keep
[keybindings]history_prev = "up" # navigate to older queryhistory_next = "down" # navigate to newer queryscroll_down = "ctrl+j"scroll_up = "ctrl+k"scroll_to_bottom = "ctrl+g"scroll_to_top = "ctrl+t"scroll_page_down = "ctrl+n"scroll_page_up = "ctrl+p"toggle_keymode = "ctrl+l"delete_line = "ctrl+u"delete_word = "ctrl+w"cursor_left = "ctrl+b"cursor_right = "ctrl+f"cursor_to_start = "ctrl+a"cursor_to_end = "ctrl+e"toggle_func_help = "ctrl+x"candidate_next = "tab" # cycle candidates forwardcandidate_prev = "ctrl+p" # cycle candidates backward (additional key; Shift+Tab always works)quit = "ctrl+q" # exit jid (used when exit_on_enter = false)
[behavior]exit_on_enter = true # set to false to prevent accidental exit on EnterNote: Shift+Tab (
\x1b[Z) is a fixed terminal escape sequence and always triggers backward cycling regardless ofcandidate_prev.
Preventing accidental exit on Enter
Section titled “Preventing accidental exit on Enter”By default, pressing Enter exits jid and prints the current result. If you find yourself accidentally exiting, set exit_on_enter = false in config.toml:
[behavior]exit_on_enter = falseWhen disabled, Enter only confirms a candidate selection. Use Ctrl+Q (or your configured quit key) to exit.
Supported key strings
Section titled “Supported key strings”ctrl+a … ctrl+z, up, down, left, right, tab, enter, esc, backspace, home, end, pgup, pgdn, delete, f1 … f12
Query History
Section titled “Query History”Queries are saved automatically on Enter. The history file path follows the same OS convention as the config file (e.g. ~/Library/Application Support/jid/history on macOS) unless overridden in config.toml.
JMESPath Support
Section titled “JMESPath Support”jid supports JMESPath expressions in addition to the traditional dot-path notation.
JMESPath mode is automatically activated when the query contains pipe (|), wildcards ([*]), filter expressions ([?), or function calls.
JMESPath Query Examples
Section titled “JMESPath Query Examples”. traditional: show root JSON.users traditional: navigate to users field.users[0].name traditional: array index + field access
.users[*].name wildcard projection: extract name from every user.users[*].address.city nested wildcard projection.users[*].<Tab> show field candidates from array elements
. | keys(@) pipe: list root object keys.users | length(@) pipe: count users array.users | sort_by(@, &name) pipe: sort users by name field.users | reverse(@) pipe: reverse the array
.[1] | to_array(@)[0].id chained pipe with indexing. | to_array(@)[0] wrap root in array and index
.users[*].name | [0] project names then indexWildcard Projection + Array Index
Section titled “Wildcard Projection + Array Index”After a wildcard projection like .game_indices[*].version, the result is an array.
Use [N] to navigate into it — jid automatically rewrites to pipe form internally:
.game_indices[*] → field candidates: game_index, version.game_indices[*].version → shows array of version objects; suggests [.game_indices[*].version[0] → first version object {name, url}.game_indices[*].version[0].name → first version's name.game_indices[*].version[0] | keys(@) → keys of first version object.game_indices[*].version[0] | keys(@) | sort(@) → sorted keysNote: In standard JMESPath,
[*].field[0]applies[0]to each projected element rather than the projected array, producing[]. jid detects this pattern and transparently rewrites it to[*].field | [0]so[0]indexes the array.
Function Candidates
Section titled “Function Candidates”When you type | after a field, jid shows available JMESPath functions filtered by the type of the preceding expression:
| Input type | Suggested functions |
|---|---|
| Array | avg, contains, join, length, map, max, max_by, min, min_by, not_null, reverse, sort, sort_by, sum, to_array, to_string, type |
| Object | keys, length, merge, not_null, to_array, to_string, type, values |
| String | contains, ends_with, length, not_null, reverse, starts_with, to_array, to_number, to_string, type |
| Number | abs, ceil, floor, not_null, to_array, to_string, type |
A usage description is shown below the candidate list (toggle with Ctrl+X).
Candidate Key Highlighting
Section titled “Candidate Key Highlighting”The matching JSON key is highlighted in yellow and the view auto-scrolls to it in two situations:
- While typing — as soon as the query narrows down to a single candidate (e.g. typing
.nawhen onlynamematches), the corresponding key is highlighted immediately, before pressingTab. - While cycling with
Tab/Shift+Tab— the key for each selected candidate is highlighted as you cycle through the list.
In both cases, if the key is outside the visible area the JSON view scrolls to bring it into view. Only the key at the correct nesting level is highlighted — nested keys with the same name are ignored.
Function Argument Templates
Section titled “Function Argument Templates”When a function candidate is confirmed, the arguments are automatically filled in and the cursor is placed at the right position:
| Function | Inserted as | Cursor position |
|---|---|---|
contains | contains(@, '') | inside '' |
ends_with | ends_with(@, '') | inside '' |
starts_with | starts_with(@, '') | inside '' |
join | join('', @) | inside '' (separator) |
sort_by | sort_by(@, &field) | on field placeholder |
max_by | max_by(@, &field) | on field placeholder |
min_by | min_by(@, &field) | on field placeholder |
map | map(&expr, @) | on expr placeholder |
Placeholder text is shown in cyan. Typing any character replaces the entire placeholder.
&field Candidate Completion
Section titled “&field Candidate Completion”For functions that take a &field argument (sort_by, max_by, min_by, map),
jid automatically shows the available field names from the base array as soon as the
&field template is inserted:
.stats | sort_by(@, &field) → field names shown: base_stat effort stat.stats | sort_by(@, &b → filtered: base_stat.stats | sort_by(@, &base_stat) → confirmed; expression evaluates normally- Tab / Shift+Tab cycles through field candidates; cursor stays between
&and) - Typing filters candidates by the partial name after
& - Enter or Tab (when only one candidate) confirms the selection
- Ctrl+W deletes the field name but keeps
&(e.g.&base_stat)→&)
Wildcard Projection Navigation
Section titled “Wildcard Projection Navigation”After a wildcard expression like .game_indices[*], jid shows the field names of the array elements as candidates:
.game_indices[*] → candidates: game_index, version.game_indices[*].<Tab> → same candidates (trailing dot still shows fields).game_indices[*].v<Tab> → filtered: version.game_indices[*].version → shows array result; suggests [ for index navigation.game_indices[*].version[0] → first version object; candidates: name, urlCtrl+W in JMESPath Mode
Section titled “Ctrl+W in JMESPath Mode”Ctrl+W removes one segment at a time from the end of a JMESPath expression:
.[3] | to_array(@)[0].id →(Ctrl+W)→ .[3] | to_array(@)[0].[3] | to_array(@)[0] →(Ctrl+W)→ .[3] | to_array(@).[3] | to_array(@) →(Ctrl+W)→ .[3] |.[3] | →(Ctrl+W)→ .[3]Inside a function call, the &field argument is treated as one unit and & is preserved:
.stats | max_by(@, &base_stat) →(Ctrl+W)→ .stats | max_by(@, &.stats | max_by(@, & →(Ctrl+W)→ .stats |