jsonseek 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. jsonseek-0.1.0/LICENSE +21 -0
  2. jsonseek-0.1.0/MANIFEST.in +9 -0
  3. jsonseek-0.1.0/PKG-INFO +588 -0
  4. jsonseek-0.1.0/README.md +557 -0
  5. jsonseek-0.1.0/README_ZH.md +556 -0
  6. jsonseek-0.1.0/pyproject.toml +53 -0
  7. jsonseek-0.1.0/setup.cfg +4 -0
  8. jsonseek-0.1.0/setup.py +15 -0
  9. jsonseek-0.1.0/skills/jsonseek/SKILL.md +285 -0
  10. jsonseek-0.1.0/skills/jsonseek/references/commands.md +221 -0
  11. jsonseek-0.1.0/skills/jsonseek/references/path-syntax.md +67 -0
  12. jsonseek-0.1.0/src/jsonseek/__init__.py +3 -0
  13. jsonseek-0.1.0/src/jsonseek/cli.py +162 -0
  14. jsonseek-0.1.0/src/jsonseek/commands/__init__.py +14 -0
  15. jsonseek-0.1.0/src/jsonseek/commands/add_cmd.py +148 -0
  16. jsonseek-0.1.0/src/jsonseek/commands/append_cmd.py +116 -0
  17. jsonseek-0.1.0/src/jsonseek/commands/concat_cmd.py +73 -0
  18. jsonseek-0.1.0/src/jsonseek/commands/cutline_cmd.py +45 -0
  19. jsonseek-0.1.0/src/jsonseek/commands/del_cmd.py +182 -0
  20. jsonseek-0.1.0/src/jsonseek/commands/extend_cmd.py +80 -0
  21. jsonseek-0.1.0/src/jsonseek/commands/extract_cmd.py +57 -0
  22. jsonseek-0.1.0/src/jsonseek/commands/fields_cmd.py +59 -0
  23. jsonseek-0.1.0/src/jsonseek/commands/get_cmd.py +42 -0
  24. jsonseek-0.1.0/src/jsonseek/commands/ls_cmd.py +45 -0
  25. jsonseek-0.1.0/src/jsonseek/commands/query_cmd.py +58 -0
  26. jsonseek-0.1.0/src/jsonseek/commands/replaceline_cmd.py +57 -0
  27. jsonseek-0.1.0/src/jsonseek/commands/set_cmd.py +153 -0
  28. jsonseek-0.1.0/src/jsonseek/commands/shape_cmd.py +146 -0
  29. jsonseek-0.1.0/src/jsonseek/detect.py +57 -0
  30. jsonseek-0.1.0/src/jsonseek/errors.py +23 -0
  31. jsonseek-0.1.0/src/jsonseek/formatters.py +260 -0
  32. jsonseek-0.1.0/src/jsonseek/io/__init__.py +0 -0
  33. jsonseek-0.1.0/src/jsonseek/io/encoding.py +83 -0
  34. jsonseek-0.1.0/src/jsonseek/io/json_file.py +122 -0
  35. jsonseek-0.1.0/src/jsonseek/io/jsonl_file.py +154 -0
  36. jsonseek-0.1.0/src/jsonseek/io/rewrite.py +60 -0
  37. jsonseek-0.1.0/src/jsonseek/patch/__init__.py +0 -0
  38. jsonseek-0.1.0/src/jsonseek/patch/array_ops.py +22 -0
  39. jsonseek-0.1.0/src/jsonseek/patch/locator.py +101 -0
  40. jsonseek-0.1.0/src/jsonseek/patch/object_ops.py +24 -0
  41. jsonseek-0.1.0/src/jsonseek/path_parser.py +136 -0
  42. jsonseek-0.1.0/src/jsonseek/types.py +65 -0
  43. jsonseek-0.1.0/src/jsonseek/value_utils.py +98 -0
  44. jsonseek-0.1.0/src/jsonseek/walkers/__init__.py +0 -0
  45. jsonseek-0.1.0/src/jsonseek/walkers/field_scan.py +59 -0
  46. jsonseek-0.1.0/src/jsonseek/walkers/query_scan.py +140 -0
  47. jsonseek-0.1.0/src/jsonseek/walkers/tree_walk.py +48 -0
  48. jsonseek-0.1.0/src/jsonseek.egg-info/PKG-INFO +588 -0
  49. jsonseek-0.1.0/src/jsonseek.egg-info/SOURCES.txt +84 -0
  50. jsonseek-0.1.0/src/jsonseek.egg-info/dependency_links.txt +1 -0
  51. jsonseek-0.1.0/src/jsonseek.egg-info/entry_points.txt +2 -0
  52. jsonseek-0.1.0/src/jsonseek.egg-info/top_level.txt +1 -0
  53. jsonseek-0.1.0/tests/create_broken_jsons.py +32 -0
  54. jsonseek-0.1.0/tests/data/__init__.py +1 -0
  55. jsonseek-0.1.0/tests/data/bad_bytes_utf8.json +1 -0
  56. jsonseek-0.1.0/tests/data/bad_json_syntax.json +1 -0
  57. jsonseek-0.1.0/tests/data/enc_ascii.json +1 -0
  58. jsonseek-0.1.0/tests/data/enc_garbage.json +1 -0
  59. jsonseek-0.1.0/tests/data/enc_gbk.json +1 -0
  60. jsonseek-0.1.0/tests/data/enc_utf16.json +0 -0
  61. jsonseek-0.1.0/tests/data/enc_utf8.json +1 -0
  62. jsonseek-0.1.0/tests/data/enc_utf8bom.json +1 -0
  63. jsonseek-0.1.0/tests/data/gbk_with_fake_bom.json +1 -0
  64. jsonseek-0.1.0/tests/data/mixed_enc_utf8_gbk.json +1 -0
  65. jsonseek-0.1.0/tests/data/null_byte_json.json +0 -0
  66. jsonseek-0.1.0/tests/data/test_broken.json +7 -0
  67. jsonseek-0.1.0/tests/data/test_broken.jsonl +3 -0
  68. jsonseek-0.1.0/tests/data/test_company.json +25 -0
  69. jsonseek-0.1.0/tests/data/test_data.json +41 -0
  70. jsonseek-0.1.0/tests/data/test_data.jsonl +5 -0
  71. jsonseek-0.1.0/tests/data/test_garbled.json +4 -0
  72. jsonseek-0.1.0/tests/data/test_multi_error.json +8 -0
  73. jsonseek-0.1.0/tests/data/test_multi_error.jsonl +5 -0
  74. jsonseek-0.1.0/tests/data/test_path.json +8 -0
  75. jsonseek-0.1.0/tests/data/test_products.jsonl +3 -0
  76. jsonseek-0.1.0/tests/data/test_valid.json +7 -0
  77. jsonseek-0.1.0/tests/test_concat.py +140 -0
  78. jsonseek-0.1.0/tests/test_fields_json.py +34 -0
  79. jsonseek-0.1.0/tests/test_fields_jsonl.py +34 -0
  80. jsonseek-0.1.0/tests/test_patch_json.py +87 -0
  81. jsonseek-0.1.0/tests/test_patch_jsonl.py +63 -0
  82. jsonseek-0.1.0/tests/test_path_parser.py +82 -0
  83. jsonseek-0.1.0/tests/test_query_json.py +37 -0
  84. jsonseek-0.1.0/tests/test_query_jsonl.py +26 -0
  85. jsonseek-0.1.0/tests/test_shape_json.py +46 -0
  86. jsonseek-0.1.0/tests/test_shape_jsonl.py +30 -0
jsonseek-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 lo2589
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,9 @@
1
+ include README.md
2
+ include README_ZH.md
3
+ include LICENSE
4
+ include pyproject.toml
5
+ recursive-include skills *.md
6
+ recursive-include src/jsonseek *.py
7
+ recursive-include tests *.py
8
+ recursive-include tests/data *.json
9
+ recursive-include tests/data *.jsonl
@@ -0,0 +1,588 @@
1
+ Metadata-Version: 2.4
2
+ Name: jsonseek
3
+ Version: 0.1.0
4
+ Summary: Query and patch JSON/JSONL files from the command line
5
+ Author: lo2589
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/lo2589/jsonseek
8
+ Project-URL: Repository, https://github.com/lo2589/jsonseek
9
+ Project-URL: Issues, https://github.com/lo2589/jsonseek/issues
10
+ Keywords: json,jsonl,cli,json-query,json-patch,jsonl-tools
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Topic :: Software Development
24
+ Classifier: Topic :: Utilities
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.8
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Dynamic: license-file
30
+ Dynamic: requires-python
31
+
32
+ # JSONSEEK
33
+
34
+ > **A JSON/JSONL navigation and partial manipulation tool for developers and coding agents.**
35
+ >
36
+ > Core purpose: Reduce token waste from LLMs reading entire large JSON files. Use `shape`/`fields`/`query` to locate, then `get`/`set`/`add`/`del`/`append` for partial operations.
37
+ >
38
+ > Supports structural understanding, field summaries, partial querying, and partial modification for both JSON and JSONL.
39
+ >
40
+ > Supports bug detection and partial fixes for both JSON and JSONL.
41
+ ---
42
+
43
+ ## Why JSON Deserves a Dedicated Tool
44
+
45
+ JSON is the de facto standard for modern data exchange. From ML experiment logs, API configs, application log streams, to microservice registries and crawler data stores, JSON/JSONL is everywhere:
46
+
47
+ - **ML Experiment Tracking**: Training parameters, metric curves, and model configs all live in JSON — a single experiment directory can easily reach tens of MB
48
+ - **API/Microservice Configs**: Service discovery, routing rules, and environment variables are often managed as JSON configs
49
+ - **Logs & Event Streams**: Structured logs (JSONL) are easier to query than plain text, but file sizes grow extremely fast
50
+ - **Data Exchange**: Frontend-backend communication, inter-service RPC, and crawler output — JSON is the most common format
51
+
52
+ The problem: **The larger the JSON file, the more expensive it is for LLMs and developers to process**. `cat`-ing a 10MB JSON into context burns millions of tokens; even human developers suffer when searching for a field in thousands of lines of nested structure.
53
+
54
+ **JSONSEEK solves this** — by replacing full reads with partial operations, and manual scanning with structured queries. For coding agents and developers who frequently handle JSON/JSONL, this tool is worth a look.
55
+
56
+ ---
57
+
58
+ ## Why Use JSONSEEK (For Coding Agents)
59
+
60
+ When facing a 10MB JSON file, `cat`-ing the entire file into context is catastrophic token waste. JSONSEEK lets you:
61
+
62
+ 1. **Understand structure first** — `shape` for the skeleton, `fields` for the field list, without reading content
63
+ 2. **Locate targets next** — `query` to search keywords, `ls` to see child nodes at a layer, `get` to fetch specific values
64
+ 3. **Modify partially last** — `set`/`add`/`del`/`append` only where needed
65
+
66
+ ### Token Savings Estimate
67
+
68
+ | File Size | Operation | Full Read | JSONSEEK Output | Savings |
69
+ |---|---|---|---|---|
70
+ | 100KB config JSON | `shape` | ~25K tokens | ~100 tokens | **99%+** |
71
+ | 100KB config JSON | `fields` | ~25K tokens | ~300 tokens | **98%+** |
72
+ | 100KB config JSON | `get` single value | ~25K tokens | ~10 tokens | **99%+** |
73
+ | 100KB config JSON | `query` hits a few | ~25K tokens | ~100 tokens | **99%+** |
74
+ | 10MB log JSONL | `shape` sampling | ~2.5M tokens | ~200 tokens | **99.9%+** |
75
+ | 10MB log JSONL | `query` hits dozens | ~2.5M tokens | ~1K tokens | **99.9%+** |
76
+
77
+ > Rough estimate: 1 token ≈ 4 bytes of English text. Actual ratios vary by content and tokenizer, but the order of magnitude holds — **the larger the file, the more dramatic the savings**.
78
+
79
+ **Typical agent workflow:**
80
+
81
+ ```bash
82
+ # Step 1: Understand structure (zero content read, metadata only)
83
+ jsonseek shape config.json # See depth, array sizes
84
+ jsonseek fields config.json # See all field names and types
85
+
86
+ # Step 2: Locate target (read only matching parts)
87
+ jsonseek query config.json api_key # Find where api_key is
88
+ jsonseek get config.json services[0].endpoint
89
+
90
+ # Step 3: Partial modification (write only target path)
91
+ jsonseek set config.json services[0].endpoint "https://new.api.com"
92
+ jsonseek del config.json services[0].deprecated_field
93
+ ```
94
+
95
+ ---
96
+
97
+ ## Installation
98
+
99
+ ```bash
100
+ pip install -e .
101
+ jsonseek --version # JSONSEEK 0.1.0
102
+ ```
103
+
104
+ Requires Python >= 3.8. Cross-platform support for Windows / macOS / Linux.
105
+
106
+ ---
107
+
108
+ ## Global Options
109
+
110
+ The following options apply to most commands:
111
+
112
+ | Option | Description |
113
+ |--------|-------------|
114
+ | `--output {pretty,json}` | Output format; `json` is machine-readable |
115
+ | `--backup` | Create `.bak` backup before writing |
116
+ | `--dry-run` | Preview changes without actually writing |
117
+ | `--kind {json,jsonl}` | Force file type (auto-detect by default) |
118
+ | `--encoding ENCODING` | Force file encoding (auto-detect by default) |
119
+ | `--context N` | Show N lines of context around target line (JSONL only, default 2) |
120
+
121
+ ---
122
+
123
+ ## Command Cheatsheet (Agent Mode)
124
+
125
+ ### Read-Only Commands (Safe, will not modify files)
126
+
127
+ | Command | Purpose | Agent Scenario |
128
+ |---|---|---|
129
+ | `shape FILE` | Display JSON skeleton tree | First look at an unknown JSON, quickly grasp structure |
130
+ | `fields FILE [KEYWORD]` | List all fields and types | Find field names, see type distribution, filter by keyword |
131
+ | `ls FILE [PATH]` | List child nodes at a path | Browse JSON like `ls` on directories |
132
+ | `get FILE PATH` | Get value at a path | Precisely read a single value, avoid full load |
133
+ | `query FILE TERM` | Search keys or values | Find where a config item is |
134
+ | `extract PATTERN PATH` | Batch extract values at same path | Grab the same field from multiple config files |
135
+ | `concat PATTERN` | Merge multiple JSONs into JSONL | Batch format conversion, data aggregation |
136
+
137
+ ### Write Commands (Will modify files, `--backup` recommended)
138
+
139
+ | Command | Purpose | Agent Scenario |
140
+ |---|---|---|
141
+ | `set FILE PATH VALUE` | Set value | Modify config items, update URLs, change numbers |
142
+ | `add FILE PATH VALUE` | Add new key to object | Add new config fields |
143
+ | `del FILE PATH` | Delete key or array element | Clean up deprecated fields |
144
+ | `append FILE PATH VALUE` | Append single element to array (JSON) | Add a new item to a list |
145
+ | `extend FILE PATH VALUE` | Batch append to array (JSON) | Add multiple elements to a list at once |
146
+ | `append FILE VALUE` | Append record (JSONL) | Add a record to end of JSONL |
147
+
148
+ ### Repair Commands
149
+
150
+ | Command | Purpose |
151
+ |---------|---------|
152
+ | `cutline FILE LINE` | Extract a specific line to stdout or temp file |
153
+ | `replaceline FILE LINE [CONTENT]` | Replace a specific line |
154
+
155
+ ---
156
+
157
+ ## Command Parameters
158
+
159
+ ### `shape`
160
+
161
+ ```bash
162
+ jsonseek shape FILE [--max-depth N] [--array-mode {sample,full}] [--sample-size N]
163
+ ```
164
+
165
+ | Parameter | Description |
166
+ |-----------|-------------|
167
+ | `--max-depth N` | Maximum traversal depth |
168
+ | `--array-mode {sample,full}` | Array traversal mode; `sample` (default) or `full` |
169
+ | `--sample-size N` | Number of records to sample for JSONL (default 100) |
170
+
171
+ ### `fields`
172
+
173
+ ```bash
174
+ jsonseek fields FILE [KEYWORD] [--top]
175
+ ```
176
+
177
+ | Parameter | Description |
178
+ |-----------|-------------|
179
+ | `KEYWORD` | Optional, filter field names |
180
+ | `--top` | Show only top-level fields |
181
+
182
+ ### `ls`
183
+
184
+ ```bash
185
+ jsonseek ls FILE [PATH]
186
+ ```
187
+
188
+ ### `get`
189
+
190
+ ```bash
191
+ jsonseek get FILE PATH
192
+ ```
193
+
194
+ ### `query`
195
+
196
+ ```bash
197
+ jsonseek query FILE TERM [--case-sensitive] [--exact] [--match-mode {key,value,both}] [--max-results N] [--record-id-field FIELD] [--preview-field FIELD]
198
+ ```
199
+
200
+ | Parameter | Description |
201
+ |-----------|-------------|
202
+ | `--case-sensitive` | Case-sensitive matching |
203
+ | `--exact` | Exact match (default is substring) |
204
+ | `--match-mode {key,value,both}` | Match key, value, or both (default both) |
205
+ | `--max-results N` | Limit number of results |
206
+ | `--record-id-field FIELD` | Use this field as record ID in JSONL output |
207
+ | `--preview-field FIELD` | Also show preview of this field in JSONL output |
208
+
209
+ ### `set`
210
+
211
+ ```bash
212
+ jsonseek set FILE PATH VALUE [--create-missing] [--from-file FILE]
213
+ ```
214
+
215
+ | Parameter | Description |
216
+ |-----------|-------------|
217
+ | `--create-missing` | Auto-create missing intermediate paths |
218
+ | `--from-file FILE` | Read value from file (avoids shell quoting issues) |
219
+
220
+ ### `add`
221
+
222
+ ```bash
223
+ jsonseek add FILE PATH VALUE [--create-missing] [--from-file FILE]
224
+ ```
225
+
226
+ Same parameters as `set`.
227
+
228
+ ### `del`
229
+
230
+ ```bash
231
+ jsonseek del FILE PATH [-y]
232
+ ```
233
+
234
+ | Parameter | Description |
235
+ |-----------|-------------|
236
+ | `-y`, `--yes` | Skip confirmation prompt |
237
+
238
+ ### `append`
239
+
240
+ ```bash
241
+ # JSON: append to array
242
+ jsonseek append FILE ARRAY_PATH VALUE
243
+
244
+ # JSONL: append record at root
245
+ jsonseek append FILE VALUE
246
+ ```
247
+
248
+ ### `extend`
249
+
250
+ ```bash
251
+ jsonseek extend FILE ARRAY_PATH JSON_ARRAY
252
+ ```
253
+
254
+ ### `extract`
255
+
256
+ ```bash
257
+ jsonseek extract PATTERN PATH [--include-missing] [--output {pretty,json}]
258
+ ```
259
+
260
+ | Parameter | Description |
261
+ |-----------|-------------|
262
+ | `--include-missing` | Include files where path is missing (default skip) |
263
+
264
+ ### `concat`
265
+
266
+ ```bash
267
+ jsonseek concat PATTERN [-o OUTPUT] [--no-sort]
268
+ ```
269
+
270
+ | Parameter | Description |
271
+ |-----------|-------------|
272
+ | `-o, --output-file OUTPUT` | Output file (default stdout) |
273
+ | `--no-sort` | Preserve glob order (default sort by filename) |
274
+
275
+ ### `cutline`
276
+
277
+ ```bash
278
+ jsonseek cutline FILE LINE [--save-temp]
279
+ ```
280
+
281
+ | Parameter | Description |
282
+ |-----------|-------------|
283
+ | `--save-temp` | Save to temp file and return path |
284
+
285
+ ### `replaceline`
286
+
287
+ ```bash
288
+ jsonseek replaceline FILE LINE [CONTENT] [--from-file FILE]
289
+ ```
290
+
291
+ | Parameter | Description |
292
+ |-----------|-------------|
293
+ | `--from-file FILE` | Read replacement content from file |
294
+
295
+ ---
296
+
297
+ ## `--dry-run` Preview
298
+
299
+ All write commands support `--dry-run` to preview changes before applying them.
300
+
301
+ **JSON preview:**
302
+
303
+ ```bash
304
+ $ jsonseek set config.json services[2].endpoint "https://new.api.com" --dry-run
305
+ [DRY-RUN] Before: services[2].endpoint = "https://old.api.com"
306
+ [DRY-RUN] After: services[2].endpoint = "https://new.api.com"
307
+ (Dry run, no changes made)
308
+ ```
309
+
310
+ **JSONL preview (with line-number context):**
311
+
312
+ ```bash
313
+ $ jsonseek set logs.jsonl '[15].level' "WARNING" --dry-run
314
+ [DRY-RUN] Before:
315
+ >>>15: {"level":"ERROR","msg":"connection failed"} [TO BE MODIFIED]
316
+ 14: {"level":"INFO","msg":"ok"}
317
+
318
+ [DRY-RUN] After:
319
+ >>>15: {"level":"WARNING","msg":"connection failed"} [MODIFIED]
320
+ 14: {"level":"INFO","msg":"ok"}
321
+ (Dry run, no changes made)
322
+ ```
323
+
324
+ **Machine-readable output (`--output json`):**
325
+
326
+ ```bash
327
+ $ jsonseek set config.json services[2].endpoint "https://new.api.com" \
328
+ --dry-run --output json
329
+ {"ok":true,"dry_run":true,"path":"services[2].endpoint",
330
+ "before":"https://old.api.com","after":"https://new.api.com"}
331
+ ```
332
+
333
+ Operation tags:
334
+ - `[TO BE MODIFIED]` / `[MODIFIED]`
335
+ - `[TO BE DELETED]` / (line removed)
336
+ - `[APPENDED]`
337
+
338
+ ---
339
+
340
+ ## Path Syntax
341
+
342
+ ```bash
343
+ # Dot-separated
344
+ jsonseek get data.json meta.settings.timeout
345
+
346
+ # Bracket keys (supports string keys)
347
+ jsonseek get data.json meta[settings][timeout]
348
+ jsonseek get data.json users[0][name]
349
+
350
+ # Array indices
351
+ jsonseek get data.json items[0][1]
352
+
353
+ # JSONL record selector
354
+ jsonseek get data.jsonl '[0].name'
355
+ jsonseek get data.jsonl 'records[12].payload.diff'
356
+ jsonseek set data.jsonl '[0].age' 30
357
+ ```
358
+
359
+ Rules:
360
+ - `[number]` → Array index (`[0]`, `[12]`)
361
+ - `[string]` → Object key (`[name]`, `[key-1]`)
362
+ - Consecutive brackets chain directly: `a[b][c]`
363
+
364
+ ---
365
+
366
+ ## JSON vs JSONL Quick Reference
367
+
368
+ | | JSON | JSONL |
369
+ |---|---|---|
370
+ | Reading | Load entire file into memory | Stream line by line |
371
+ | `shape` | Full tree | Sample first N records |
372
+ | `fields` | Count occurrences | Coverage (record coverage rate) |
373
+ | `get`/`ls` | Parse `path` directly | Path must start with `[N].` or `records[N].` |
374
+ | `set`/`add`/`del` | Direct patch in-memory tree | Full file rewrite (atomic replacement) |
375
+ | `append` | Append inside array | Append record at root level |
376
+
377
+ ---
378
+
379
+ ## Agent Practical Examples
380
+
381
+ ### Scenario 1: Explore Unknown Config JSON
382
+
383
+ ```bash
384
+ jsonseek shape config.json
385
+ # (root)
386
+ # services
387
+ # services[*] (object) [5]
388
+ # services[*].name
389
+ # services[*].endpoint
390
+ # services[*].timeout
391
+ # database
392
+ # database.host
393
+ # database.port
394
+
395
+ jsonseek fields config.json
396
+ # services types=array paths=1
397
+ # name types=string paths=5
398
+ # endpoint types=string paths=5
399
+ # timeout types=integer paths=5
400
+ # database types=object paths=1
401
+ # host types=string paths=1
402
+ # port types=integer paths=1
403
+
404
+ jsonseek query config.json production
405
+ # services[2].name [value] 'production'
406
+
407
+ jsonseek get config.json services[2].endpoint
408
+ # https://prod.api.example.com
409
+ ```
410
+
411
+ ### Scenario 2: Batch Modify JSONL
412
+
413
+ ```bash
414
+ jsonseek shape logs.jsonl
415
+ # (root)
416
+ # timestamp (string)
417
+ # level (string)
418
+ # message (string)
419
+
420
+ jsonseek query logs.jsonl ERROR --max-results 5
421
+ # message [value] 'connection failed' record=12 line=15
422
+
423
+ # Change level of record 12 to warning
424
+ jsonseek set logs.jsonl '[12].level' "warning"
425
+
426
+ # Delete record 100
427
+ jsonseek del logs.jsonl '[100]'
428
+
429
+ # Append new record
430
+ jsonseek append logs.jsonl '{"timestamp":"2024-01-01","level":"info","message":"started"}'
431
+ ```
432
+
433
+ ### Scenario 3: Precise Partial Modification (Avoid Full Read)
434
+
435
+ ```bash
436
+ # Don't do this: cat 10MB.json | feed to LLM for analysis
437
+ # Do this instead:
438
+ jsonseek get large.json data[0].metrics.cpu_usage
439
+ # 42.5
440
+
441
+ jsonseek set large.json data[0].metrics.cpu_usage 45.0
442
+ ```
443
+
444
+ ### Scenario 4: Batch Extract and Array Extension
445
+
446
+ ```bash
447
+ # Batch extract same field from multiple experiment records
448
+ jsonseek extract "experiments/*/metrics.json" training.loss --output json
449
+ # [{"file":"exp1/metrics.json","value":0.12,"ok":true}, ...]
450
+
451
+ # Append multiple elements to array at once (extend unpacks array and appends one by one)
452
+ jsonseek extend data.json tags '["urgent", "review"]'
453
+ # Equivalent to sequentially appending "urgent" and "review"
454
+ ```
455
+
456
+ ### Scenario 5: Merge Multiple JSONs into JSONL
457
+
458
+ ```bash
459
+ # Convert all JSON experiment records in directory to single JSONL
460
+ jsonseek concat "experiments/*/result.json" -o combined.jsonl
461
+ # combined.jsonl:
462
+ # {"experiment":"exp1","accuracy":0.95}
463
+ # {"experiment":"exp2","accuracy":0.92}
464
+
465
+ # Default sorted by filename; add --no-sort to preserve original order
466
+ jsonseek concat "logs/*.json" --no-sort -o logs.jsonl
467
+ ```
468
+
469
+ ### Scenario 6: Large File Debug and Error Fix
470
+
471
+ When JSON files are corrupted or have syntax errors, JSONSEEK can precisely locate problematic lines, and together with the temp file method enables safe fixes:
472
+
473
+ ```bash
474
+ # Step 1: Discover errors (auto-locate to line)
475
+ jsonseek shape broken.jsonl
476
+ # Error: Found 2 invalid lines in broken.jsonl:
477
+ # Line 5: {"id": 5, "broken
478
+ # Error: Unterminated string starting at
479
+ # Line 12: {"id": 12, "another}
480
+ # Error: Unterminated string starting at
481
+
482
+ # Step 2: Extract problematic line to temp file
483
+ jsonseek cutline broken.jsonl 5 --save-temp
484
+ # C:\Users\...\tmpXXXX.jsonline
485
+
486
+ # Step 3: Fix temp file with Python (bypass PowerShell quoting issues)
487
+ python -c "open(r'C:\Users\...\tmpXXXX.jsonline','w',encoding='utf-8').write('{\"id\": 5, \"name\": \"fixed\"}')"
488
+
489
+ # Step 4: Replace back into original file
490
+ jsonseek replaceline broken.jsonl 5 --from-file C:\Users\...\tmpXXXX.jsonline
491
+
492
+ # Step 5: Verify fix
493
+ jsonseek shape broken.jsonl
494
+ # (root)
495
+ # id (integer)
496
+ # name (string)
497
+ ```
498
+
499
+ **Debug Scenario Token Savings Comparison:**
500
+
501
+ | Scenario | Traditional (Full Read) | JSONSEEK Way | Savings |
502
+ |-----|---------------------|---------------|------|
503
+ | Locate syntax error in 10MB JSONL | Read full ~2.5M tokens | shape output ~200 tokens | **99.99%** |
504
+ | Fix line 5 of corrupted JSONL | Read context + modify ~500K tokens | cutline + replaceline ~1K tokens | **99.8%** |
505
+ | Batch fix N errors | N × context reads | N × (cutline + replaceline) | **~99%** |
506
+
507
+ ---
508
+
509
+ ## Windows PowerShell: Query via CLI, Write via Python API
510
+
511
+ On Windows PowerShell, **read-only commands** (`shape`, `fields`, `get`, `query`, `ls`, `extract`, `concat`) work fine via CLI. However, **write commands** (`set`, `add`, `del`, `append`, `extend`, `replaceline`) are problematic because PowerShell strips double quotes from JSON strings, causing complex values to fail.
512
+
513
+ > **Recommendation for Windows:** Use CLI for all read/query operations. Use Python API for all write/modify operations.
514
+
515
+ ### Python API (Recommended for Writes on Windows)
516
+
517
+ ```python
518
+ import sys
519
+ sys.path.insert(0, 'src')
520
+ from jsonseek.commands.set_cmd import set_value
521
+ from jsonseek.commands.add_cmd import add_value
522
+ from jsonseek.commands.del_cmd import del_value
523
+ from jsonseek.commands.replaceline_cmd import replace_line
524
+
525
+ # Safe on Windows — no shell quoting issues
526
+ set_value('data.json', 'path', {"key": "value"})
527
+ add_value('data.json', 'items', ["item1", "item2"])
528
+ del_value('data.json', 'path')
529
+ replace_line('data.jsonl', 5, '{"id": 5, "fixed": true}')
530
+ ```
531
+
532
+ ### Fallback: Temp File Method
533
+
534
+ If you must use CLI for writes on Windows, use `--from-file` to avoid passing JSON strings on the command line:
535
+
536
+ ```powershell
537
+ # For set/add with complex values
538
+ echo '{"key": "value"}' > tmp.json
539
+ jsonseek set data.json path --from-file tmp.json
540
+
541
+ # For cutline/replaceline workflow
542
+ jsonseek cutline broken.jsonl 5 --save-temp
543
+ # C:\Users\...\tmpXXXX.jsonline
544
+ # Edit the temp file, then:
545
+ jsonseek replaceline broken.jsonl 5 --from-file C:\Users\...\tmpXXXX.jsonline
546
+ ```
547
+
548
+ No quoting issues on macOS/Linux bash or Windows CMD.
549
+
550
+ ---
551
+
552
+ ## Project Structure
553
+
554
+ ```
555
+ src/jsonseek/
556
+ cli.py # CLI entry point
557
+ types.py # Core data types
558
+ errors.py # Exceptions
559
+ detect.py # File type detection
560
+ formatters.py # Output formatting (pretty/json), incl. patch preview
561
+ path_parser.py # Path parsing (supports . / [] mixed)
562
+ value_utils.py # Type inference and input coercion
563
+ io/ # File I/O (json, jsonl, rewrite, encoding)
564
+ walkers/ # Tree traversal (shape, fields, query)
565
+ patch/ # Patch operations (locator, object/array ops)
566
+ commands/ # Command handlers (14 subcommands)
567
+ tests/ # Unit tests (53 cases)
568
+ ```
569
+
570
+ ---
571
+
572
+ ## Roadmap
573
+
574
+ - [x] JSON read/write and patch
575
+ - [x] JSONL streaming scan and rewrite
576
+ - [x] `--output json` machine-readable output
577
+ - [x] `--dry-run` preview modifications
578
+ - [x] Windows / macOS / Linux cross-platform support
579
+ - [x] Large file error location and fix (cutline/replaceline)
580
+ - [x] Python API methods (set_value/add_value/del_value)
581
+ - [x] PowerShell temp file bypass solution
582
+ - [ ] Claude Code / Cursor / OpenAI-compatible coding workflows plugin integration
583
+
584
+ ---
585
+
586
+ ## License
587
+
588
+ MIT