@uehaj/sys1grep 0.5.0-next.0 → 0.5.0-next.1
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.
- package/README.ja.md +156 -29
- package/README.md +164 -36
- package/docs/sentence.svg +1 -1
- package/package.json +1 -1
- package/sys1grep.mjs +742 -149
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ and applies a threshold.
|
|
|
14
14
|
./sys1grep -n -e "customer is angry or frustrated" tickets.txt
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
[](https://uehaj.github.io/
|
|
17
|
+
[](https://uehaj.github.io/jev-semgrep/)
|
|
18
18
|
|
|
19
19
|
<sub>▶ Click the demo, or open <a href="https://uehaj.github.io/sys1grep/">uehaj.github.io/sys1grep</a>, for the full demo on the landing page.</sub>
|
|
20
20
|
|
|
@@ -134,8 +134,7 @@ as a plain regex, with no request at all. It prefilters its AND term: only the l
|
|
|
134
134
|
ever ask that term's meanings, so a cheap regex in front of a meaning cuts both the bill and the wait. A line is sent
|
|
135
135
|
only if some term's regexes all hold for it (a term with no regex holds for every line), so with
|
|
136
136
|
`-e '/re/' -a A -e B` a line without `re` is still sent, asked `B` only. A query of regex terms alone
|
|
137
|
-
sends nothing,
|
|
138
|
-
break; use `--sentence=rules` to stay offline. Anything that isn't shaped like `/…/flags` is still a meaning, so
|
|
137
|
+
sends nothing, even with `--unit=sentence-by-jev`: the rules alone then decide where wrapped lines join. Anything that isn't shaped like `/…/flags` is still a meaning, so
|
|
139
138
|
`-e '/etc 以下のファイルを変更している'` (no closing `/`) is unaffected; a meaning that really starts
|
|
140
139
|
and ends with `/` can be written with a leading space to dodge the regex reading.
|
|
141
140
|
|
|
@@ -172,24 +171,49 @@ $ ./sys1grep -o -n -e '/[A-Z]+-\d+/' -a 'the ticket is still open' notes.txt #
|
|
|
172
171
|
Every line sent to Jev costs money and time, so the cheapest line is the one never sent. From the widest cut
|
|
173
172
|
to the narrowest:
|
|
174
173
|
|
|
175
|
-
- **Which files.** `-r` skips `.git`, `node_modules`, binary files, likely secrets
|
|
176
|
-
[`git sys1grep`](#as-a-git-subcommand-git-sys1grep) searches
|
|
177
|
-
(file-name globs) and `--changed-within` (`30m`, `7d`, `today`,
|
|
178
|
-
A meaning that restricts itself to a language or a time of change
|
|
179
|
-
[Scope from the meaning](#scope-from-the-meaning).
|
|
174
|
+
- **Which files.** `-r` skips `.git`, `node_modules`, binary files, likely secrets, generated files (source maps,
|
|
175
|
+
minified JS/CSS, lock files) and what git ignores; [`git sys1grep`](#as-a-git-subcommand-git-sys1grep) searches
|
|
176
|
+
tracked files only. `--include` / `--exclude` (file-name globs) and `--changed-within` (`30m`, `7d`, `today`,
|
|
177
|
+
`this-week`, a date) narrow them further. A meaning that restricts itself to a language or a time of change
|
|
178
|
+
narrows them by itself: see [Scope from the meaning](#scope-from-the-meaning).
|
|
180
179
|
- **Which lines.** A [regex term](#regex-terms) is matched locally, and only the lines it holds for are asked
|
|
181
|
-
its AND term's meanings. Blank lines are never sent.
|
|
180
|
+
its AND term's meanings. Blank lines are never sent. Only the first `-M`/`--max-columns` characters of a line
|
|
181
|
+
(default 2000, 8000 with `-z`) are sent: it is still searched and judged, just not past that cutoff.
|
|
182
182
|
- **How many times.** [`--dedup`](#one-line-per-template---dedup) judges one line per template: lines that
|
|
183
183
|
differ only in ids, numbers, times or paths share one answer.
|
|
184
|
-
- **Check before paying.** `--dry-run` sends nothing and prints the
|
|
185
|
-
every request with its questions. Its last line estimates the input
|
|
186
|
-
(`~3178 input tokens, ~$0.000133`; within about 10%). `-i` shows the
|
|
187
|
-
after `y`.
|
|
184
|
+
- **Check before paying.** `--dry-run` sends nothing and prints the settings the search would run with, the
|
|
185
|
+
files, how many lines each would send and every request with its questions. Its last line estimates the input
|
|
186
|
+
tokens and, for TypeSafe itself, the price (`~3178 input tokens, ~$0.000133`; within about 10%). `-i` shows the
|
|
187
|
+
same totals on the terminal and sends only after `y`.
|
|
188
|
+
Before the bulk of requests, every target is sized (`--max-filesize`, default 10M); one over it is skipped
|
|
189
|
+
outright, like `rg`'s own `--max-filesize`, named on stderr (`-y` does not affect it). A `.gz` is sized
|
|
190
|
+
decompressed (zlib stops at the limit, so an oversized one is never inflated in full). stdin is sized once it
|
|
191
|
+
is read (it is already in memory), and skipped the same way if it is over; a `--cached` or `<tree>:` target
|
|
192
|
+
is a blob rather than a file, sized from its content (already read in one `git cat-file --batch` call, not a
|
|
193
|
+
fresh git process per blob); `-g`'s commits stay out of this, since each is already bounded by `-M` when it
|
|
194
|
+
is sent. The input about to be sent is priced too (`--max-cost`,
|
|
195
|
+
default 1 USD); over it, one question asks to continue on the terminal, `-y` answers it yes, and without a
|
|
196
|
+
terminal it is exit 2 (this applies with `-q` too — scripts pass `-y`).
|
|
188
197
|
|
|
189
198
|
```sh
|
|
190
199
|
$ sys1grep --dry-run -r --include='*.log' --changed-within=today -e '/ERROR|FATAL/' -a 'a customer is affected' logs/
|
|
191
200
|
```
|
|
192
201
|
|
|
202
|
+
`--verbose` (or `--dry-run`) also shows *where* a setting that was not typed on the command line came from
|
|
203
|
+
(`SYS1GREP_OPTS`, an environment variable, `~/.config/sys1grep/.env`, or a preset's default), so a result that
|
|
204
|
+
surprises you can be traced back to its source. The key's value never appears, only which option or variable
|
|
205
|
+
supplied it:
|
|
206
|
+
|
|
207
|
+
```sh
|
|
208
|
+
$ SYS1GREP_OPTS='--level strict' sys1grep --verbose -e "the API key is read from a file" .
|
|
209
|
+
sys1grep: endpoint api.typesafe.ai/v1/systemone (default), model jev-latest (default)
|
|
210
|
+
sys1grep: key: SYS1GREP_API_KEY (~/.config/sys1grep/.env)
|
|
211
|
+
sys1grep: SYS1GREP_OPTS: --level strict
|
|
212
|
+
sys1grep: options: --level strict (SYS1GREP_OPTS) = -t 0.7 -T 0.3, --chunk 30, -j 8, scope on, -M 2000, --max-filesize 10M, --max-cost 1
|
|
213
|
+
sys1grep: file ./a.py: 120 lines, 120 to send
|
|
214
|
+
…
|
|
215
|
+
```
|
|
216
|
+
|
|
193
217
|
## Install
|
|
194
218
|
|
|
195
219
|
Two ways to use it: as a command-line tool (this section), or as a Claude Code skill
|
|
@@ -381,11 +405,18 @@ tests/tickets/sub/b.txt
|
|
|
381
405
|
```
|
|
382
406
|
|
|
383
407
|
`-r` walks directories in sorted order and skips `.git`, `node_modules`, `.ssh`, `.aws`, `.gnupg`, `.kube`,
|
|
384
|
-
`.docker`, binary files (a NUL byte in the first 8 KB, or a PDF; UTF-16 with a BOM is read as text)
|
|
408
|
+
`.docker`, binary files (a NUL byte in the first 8 KB, or a PDF; UTF-16 with a BOM is read as text), files
|
|
385
409
|
that usually hold secrets (`.env*`, `.netrc`, `.npmrc`, `.pypirc`, `.pgpass`, `.git-credentials`, `*.pem`,
|
|
386
|
-
`*.key`, `*.p12`, `*.pfx`, `*.jks`, `*.keystore`, `id_rsa*` and friends; names compared without case)
|
|
410
|
+
`*.key`, `*.p12`, `*.pfx`, `*.jks`, `*.keystore`, `id_rsa*` and friends; names compared without case) and
|
|
411
|
+
generated files (`*.map`, `*.min.js`, `*.min.css`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`,
|
|
412
|
+
`Cargo.lock`, `poetry.lock`, `composer.lock`, `Gemfile.lock`, `go.sum`). **Every line that is searched is sent
|
|
413
|
+
to the TypeSafe API**, so point `-r` at a directory
|
|
387
414
|
you mean to scan. Inside a git repository, `-r` also skips what git ignores (`.gitignore`, `.git/info/exclude`, the
|
|
388
415
|
global excludes file), so build output and local files stay home; a tracked file is searched even if it matches.
|
|
416
|
+
A file named `*.gz` (a rotated log: `app.log.1.gz`) is read decompressed, as `zgrep` does, and printed by its
|
|
417
|
+
name on disk (`app.log.1.gz:12:...`); `--include='*.gz'` picks those, the binary sniff sees the decompressed
|
|
418
|
+
bytes, a gzipped secret (`private.key.gz`) is skipped like the plain one, and a corrupt `.gz` is an unreadable file.
|
|
419
|
+
Only gzip, only by the name.
|
|
389
420
|
A file named explicitly on the command line is always searched, even if it matches the skip list or is ignored;
|
|
390
421
|
so is a directory that git ignores, when you name it (`sys1grep -r -e ... dist`). `-l` prints each
|
|
391
422
|
matching file once, in the order matches are found, and works with or without `-r`. `-c` prints the number of
|
|
@@ -453,6 +484,25 @@ applies even to tracked files. `--include`, `--exclude` and `--changed-within` f
|
|
|
453
484
|
by a pathspec included. `--changed-within` reads the working tree's modification times, not git history: right after
|
|
454
485
|
a clone or a checkout, every file it wrote counts as just changed. For help use `git sys1grep -h`: git takes `--help` itself and looks for a man page.
|
|
455
486
|
|
|
487
|
+
`--cached`, `--untracked` and a `<tree>...` choose what is searched instead of the working tree, as `git grep` has
|
|
488
|
+
them (only one of the three at a time):
|
|
489
|
+
|
|
490
|
+
```sh
|
|
491
|
+
$ git sys1grep --cached -e "a retry is attempted" # staged, uncommitted changes included
|
|
492
|
+
$ git sys1grep --untracked -e "a retry is attempted" # tracked files plus untracked ones (.gitignore still applies)
|
|
493
|
+
$ git sys1grep -n -e "a retry is attempted" main v0.3.1 -- '*.py'
|
|
494
|
+
main:src/job.py:42: retry(job, times=3)
|
|
495
|
+
v0.3.1:src/job.py:40: retry(job)
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
A `<tree>` (a branch, tag, commit or `@{u}`) is any argument before `--` that resolves as a revision; several may
|
|
499
|
+
be given, searched in the order given, each line prefixed with the name as typed (`@{u}:path`, not the branch it
|
|
500
|
+
resolves to). `--changed-within` needs the working tree: a blob (`--cached`, a `<tree>`) has no mtime of its own.
|
|
501
|
+
A `<tree>`'s own pathspec takes a glob too, same as elsewhere in sys1grep (`git diff-tree` against the empty
|
|
502
|
+
tree, not `git ls-tree`'s own literal/directory-prefix match); `--include` / `--exclude` (by name) still work.
|
|
503
|
+
**An old `<tree>` can hold a secret an ordinary file once carried and was later removed from**: the skip list
|
|
504
|
+
drops files by name only, not by what changed since.
|
|
505
|
+
|
|
456
506
|
### Everything that is *not* something
|
|
457
507
|
|
|
458
508
|
```sh
|
|
@@ -480,15 +530,15 @@ Matching records are printed NUL-terminated too, so pipe them through `tr '\0' '
|
|
|
480
530
|
File names (`-l`) and counts (`-c`) stay on newlines, as they do in grep. With `-z`, `-n` numbers records,
|
|
481
531
|
`-A` / `-B` / `-C` count neighbouring records, and `--chunk` counts records per request.
|
|
482
532
|
|
|
483
|
-
### One sentence at a time (`--sentence
|
|
533
|
+
### One sentence at a time (`--unit=sentence-by-*`)
|
|
484
534
|
|
|
485
|
-
`--sentence` judges each sentence instead of each line. The output is still lines, as in grep: every line a
|
|
535
|
+
`--unit=sentence-by-jev` (or `sentence-by-rule`, below) judges each sentence instead of each line. The output is still lines, as in grep: every line a
|
|
486
536
|
matching sentence touches is printed, and on a terminal the sentence itself is in bold yellow (a regex match inside it, in grep's bold red).
|
|
487
537
|
Wrapped lines are joined before splitting, so a sentence that runs over several lines is judged as one.
|
|
488
538
|
[`tests/prose.txt`](tests/prose.txt) wraps an English paragraph and a Japanese one:
|
|
489
539
|
|
|
490
540
|
```sh
|
|
491
|
-
$ ./sys1grep -n --sentence -e "the author admits they made a mistake" tests/prose.txt
|
|
541
|
+
$ ./sys1grep -n --unit=sentence-by-jev -e "the author admits they made a mistake" tests/prose.txt
|
|
492
542
|
1:I should have checked the input
|
|
493
543
|
2:before shipping, and that was my
|
|
494
544
|
3:mistake. Next time I will add a test
|
|
@@ -500,14 +550,14 @@ The sentence starts on line 1 and ends at `mistake.` on line 3; only that part i
|
|
|
500
550
|
On a terminal, with both meanings and `-C 3` for context, the colors show where each sentence starts and ends
|
|
501
551
|
inside a line: lines 3 and 9 are colored only up to the end of the matching sentence, and lines 4-7 are context (`-`):
|
|
502
552
|
|
|
503
|
-

|
|
553
|
+

|
|
504
554
|
|
|
505
555
|
`-o` prints only the matching sentences, one per line, as `grep -o` prints only the matching part.
|
|
506
556
|
`-n` then gives the line where the sentence starts. Japanese is joined without a space, as are Chinese,
|
|
507
557
|
Thai, Lao, Khmer, Myanmar and Tibetan, which do not put spaces between words:
|
|
508
558
|
|
|
509
559
|
```sh
|
|
510
|
-
$ ./sys1grep -n -o --sentence -e "the author admits they made a mistake" -e "customer is asking for a refund" tests/prose.txt
|
|
560
|
+
$ ./sys1grep -n -o --unit=sentence-by-jev -e "the author admits they made a mistake" -e "customer is asking for a refund" tests/prose.txt
|
|
511
561
|
1:I should have checked the input before shipping, and that was my mistake.
|
|
512
562
|
8:先週買った掃除機が初日から動かないので返金してほしいです。
|
|
513
563
|
```
|
|
@@ -515,20 +565,20 @@ $ ./sys1grep -n -o --sentence -e "the author admits they made a mistake" -e "cus
|
|
|
515
565
|
Without `-o`, `-c` counts lines and `-A` / `-B` / `-C` count lines, as usual. With `-o` they count sentences.
|
|
516
566
|
With `-z`, each record is split on its own and matching records are printed whole.
|
|
517
567
|
|
|
518
|
-
Jev finds a matching sentence inside a long line on its own, so `--sentence` is not needed for accuracy.
|
|
568
|
+
Jev finds a matching sentence inside a long line on its own, so `--unit=sentence-by-jev` is not needed for accuracy.
|
|
519
569
|
Use it to see which sentence matched, to get the sentences with `-o`, and when AND should hold within one
|
|
520
570
|
sentence: the expression is evaluated per sentence. For the same reason `-v X` alone prints every line
|
|
521
|
-
with at least one sentence that is not X; to find lines that are not X as a whole, leave `--
|
|
571
|
+
with at least one sentence that is not X; to find lines that are not X as a whole, leave `--unit` at `line`.
|
|
522
572
|
|
|
523
573
|
Japanese and Chinese entries often end without `。`: a chat message, a support ticket, a memo line. Joining
|
|
524
|
-
them would glue separate entries into one "sentence". So
|
|
525
|
-
`--sentence
|
|
574
|
+
them would glue separate entries into one "sentence". So with
|
|
575
|
+
`--unit=sentence-by-jev` sys1grep asks Jev about each unpunctuated break next to a script written without word
|
|
526
576
|
spaces: "does this line break end a sentence or entry, or is it a wrap inside a sentence?" It sends 30 lines
|
|
527
577
|
per request with one yes/no per break, and keeps the lines apart when the answer is 0.7 or more. On
|
|
528
578
|
[`tests/corpus.txt`](tests/corpus.txt) this keeps the four one-line Japanese tickets apart, so
|
|
529
|
-
`--sentence` finds the same refund requests (lines 14 and 18) as a line-by-line search, where the rules alone
|
|
579
|
+
`--unit=sentence-by-jev` finds the same refund requests (lines 14 and 18) as a line-by-line search, where the rules alone
|
|
530
580
|
merged the tickets and missed line 18. The extra requests cost about as much as one more meaning; use
|
|
531
|
-
`--sentence
|
|
581
|
+
`--unit=sentence-by-rule` to skip them. Breaks between English lines are never asked: joining them keeps a space,
|
|
532
582
|
and the full stop still ends the sentence.
|
|
533
583
|
|
|
534
584
|
Where a newline cannot be inside a sentence, lines are not joined: at a blank line, next to brackets or
|
|
@@ -538,6 +588,38 @@ own. Sentences are cut by `Intl.Segmenter` ([Unicode UAX #29](https://unicode.or
|
|
|
538
588
|
which splits at `.` `!` `?` `。` `!` `?` but also after abbreviations such as `Mr.`. Logs are not prose:
|
|
539
589
|
consecutive log lines that start with a letter, such as `WARN ...` after `ERROR ...`, get joined.
|
|
540
590
|
|
|
591
|
+
### One function at a time (`--unit=function`)
|
|
592
|
+
|
|
593
|
+
In code the question is usually about a function ("retries on network failure"), and one line of it rarely
|
|
594
|
+
says so. `--unit=function` judges each function and prints its lines, with `-n` giving file line numbers:
|
|
595
|
+
|
|
596
|
+
```sh
|
|
597
|
+
$ ./sys1grep -n --unit=function -e "retries on network failure" src/net.js
|
|
598
|
+
src/net.js:3:async function fetchWithRetry(url) {
|
|
599
|
+
src/net.js:4: for (let i = 0; i < 5; i++) {
|
|
600
|
+
src/net.js:5: try { return await fetch(url); }
|
|
601
|
+
src/net.js:6: catch { await sleep(2 ** i * 100); }
|
|
602
|
+
src/net.js:7: }
|
|
603
|
+
src/net.js:8:}
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
A function runs from a funcname line to the line before the next one, as `git grep -W` finds it; lines
|
|
607
|
+
before the first funcname line are one unit, and blank lines at a function's end are not printed. The
|
|
608
|
+
funcname lines are git's: the `diff=<driver>` attribute in `.gitattributes`, then `diff.<driver>.xfuncname`
|
|
609
|
+
in git config. Without one, sys1grep has its own rule for JavaScript/TypeScript (a top-level `function`,
|
|
610
|
+
`class`, or `const` / `let` / `var` bound to a function) and Python (`def` / `class`, nested ones too); a decorator line (`@retry`) starts
|
|
611
|
+
the function it decorates. Otherwise it uses git's default: a line starting with a letter, `_` or `$`. git's own builtin drivers
|
|
612
|
+
(`diff=python` and so on) are not read, so a driver without an `xfuncname` falls back the same way:
|
|
613
|
+
|
|
614
|
+
```sh
|
|
615
|
+
$ printf '*.go diff=golang\n' >> .gitattributes
|
|
616
|
+
$ git config diff.golang.xfuncname '^(func|type)[[:space:]]'
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
`-M` defaults to 8000 characters here, as with `-z`; a longer function is judged on its first 8000.
|
|
620
|
+
`--chunk` counts functions, `-A`/`-B`/`-C` and `-c` count lines, as with the sentence units. `-z`, `-g` and
|
|
621
|
+
`-o` are refused.
|
|
622
|
+
|
|
541
623
|
### One line per template (`--dedup`)
|
|
542
624
|
|
|
543
625
|
Cost is proportional to the text sent, and machine-generated logs are mostly one skeleton with a different
|
|
@@ -561,7 +643,7 @@ could change a match, and those kinds are kept apart (one of the two requests ab
|
|
|
561
643
|
Measured on real logs, with nothing kept: a 43,071-line system log folds into 550 templates (1.2% of the
|
|
562
644
|
bytes), `install.log` to 21.1%, a Claude Code transcript (jsonl) only to 56.8%. It is for machine-generated
|
|
563
645
|
logs; prose has no shared skeleton, and a meaning that reads a timestamp folds almost nothing. With `-z` or
|
|
564
|
-
`--sentence
|
|
646
|
+
`--unit=sentence-by-*` the records or sentences fold instead of lines.
|
|
565
647
|
|
|
566
648
|
After a search, the summary line says what the folding saved: `(2 folded by --dedup, ~235 input tokens /
|
|
567
649
|
~$0.000010 saved, 21%)` above. It estimates what the folded lines would have cost as requests of their own and subtracts
|
|
@@ -589,15 +671,44 @@ The expensive model reads only what Jev kept. Asking why `./.env` is no longer r
|
|
|
589
671
|
`git log` (168 commits), Claude's input fell from 22,059 tokens to 1,356, the total cost with Jev's from
|
|
590
672
|
$0.094 to $0.013, with the same answer (#69). It pays when the answer sits in a few lines.
|
|
591
673
|
|
|
592
|
-
- The matching lines leave the machine a second time, to Anthropic.
|
|
674
|
+
- The matching lines leave the machine a second time, to Anthropic (or whatever TOOL talks to).
|
|
593
675
|
- `-n`, `-A/-B/-C`, `-p` and file names go in as they would print; colors never do. No match runs nothing (exit 1).
|
|
594
|
-
- `SYS1GREP_SUMMARIZER` picks the TOOL of a bare `--summarize
|
|
676
|
+
- `SYS1GREP_SUMMARIZER` picks the TOOL of a bare `--summarize`, `SYS1GREP_SUMMARIZER_MODEL` its model.
|
|
595
677
|
- `-q`, `-l` and `-c` print no lines, so they cannot be combined with it.
|
|
678
|
+
- The answer is plain text: an LLM that is not told writes Markdown, noise on a terminal, so plain is asked for.
|
|
679
|
+
`--summarize-format=markdown` or `=html` asks for those instead (`… --summarize-format=html … > summary.html`).
|
|
680
|
+
The answer prints as it comes, unchecked. In `SYS1GREP_OPTS` it is a standing preference, ignored without `--summarize`.
|
|
596
681
|
- With `--dedup`, the TOOL gets what Jev got: each template's representative once, marked `(×N like it)`,
|
|
597
682
|
not every line its answer was reused for.
|
|
598
683
|
- More than 200 KB (about 50k tokens) is not sent at all: exit 2, with the size, before the TOOL is paid.
|
|
599
684
|
It is never cut short, since a summary of the first part would read as a summary of all of it.
|
|
600
685
|
|
|
686
|
+
`--summarize-prompt=TEXT` adds your own instruction after the fixed one (how long, what to focus on):
|
|
687
|
+
|
|
688
|
+
```sh
|
|
689
|
+
$ sys1grep -r -n --summarize --summarize-prompt="3 lines or fewer, just which file to fix" \
|
|
690
|
+
-e "the API key is read from a file" .
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
It needs `--summarize`; empty TEXT is the same as leaving it out. It comes after the `--summarize-format` sentence,
|
|
694
|
+
so TEXT can override the format.
|
|
695
|
+
|
|
696
|
+
Other TOOLs:
|
|
697
|
+
|
|
698
|
+
```sh
|
|
699
|
+
$ sys1grep --summarize=llm -e "..." FILE # Simon Willison's llm, tools off (no -T given)
|
|
700
|
+
$ sys1grep --summarize=pi -e "..." FILE # pi --print --no-tools --no-session ...
|
|
701
|
+
$ SYS1GREP_SUMMARIZER_MODEL=qwen3.5:9b sys1grep --summarize=ollama -e "..." FILE
|
|
702
|
+
$ SYS1GREP_SUMMARIZER_MODEL=some-id sys1grep --summarize=lmstudio -e "..." FILE # model id from GET /v1/models
|
|
703
|
+
$ SYS1GREP_SUMMARIZER_MODEL=some-id sys1grep --summarize=http://localhost:8080/v1 -e "..." FILE # llama.cpp, vLLM, LocalAI, a gateway
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
`ollama` and `lmstudio` talk to a local OpenAI-compatible server (`POST /v1/chat/completions`) by `fetch`, no
|
|
707
|
+
CLI: the matching lines never leave the machine a second time. A plain `http(s)://` URL is any other
|
|
708
|
+
OpenAI-compatible server. All three need `SYS1GREP_SUMMARIZER_MODEL`: none has a default model.
|
|
709
|
+
`SYS1GREP_SUMMARIZER_API_KEY` goes as `Authorization: Bearer` to a URL TOOL only (never `SYS1GREP_API_KEY`,
|
|
710
|
+
which is Jev's). `OLLAMA_HOST` moves ollama's host, as it does for the `ollama` CLI itself.
|
|
711
|
+
|
|
601
712
|
## Use it from Claude Code
|
|
602
713
|
|
|
603
714
|
There is a Claude Code skill that runs sys1grep for you: describe what you are looking for in plain words
|
|
@@ -651,7 +762,11 @@ usage: sys1grep [OPTION]... -e MEANING|-Q QUESTION [-a MEANING] [-v MEANING]...
|
|
|
651
762
|
-T THRESH negative threshold: "not X" when probability < THRESH (overrides --level)
|
|
652
763
|
with -t 0.6 -T 0.3 a line at 0.3..0.6 matches neither X nor not-X
|
|
653
764
|
-r recurse into directories (current directory when FILE is omitted);
|
|
654
|
-
skips .git, node_modules, binary files, likely secrets and what git ignores
|
|
765
|
+
skips .git, node_modules, binary files, likely secrets, generated files and what git ignores
|
|
766
|
+
--cached git sys1grep only: search the index instead of the working tree, as git grep --cached
|
|
767
|
+
--untracked git sys1grep only: also search untracked files (.gitignore still applies), as git grep --untracked
|
|
768
|
+
<tree>... git sys1grep only: a branch, tag, commit or @{u} before -- searches that revision's tree
|
|
769
|
+
instead, as git grep does; output is prefixed <tree>: with the name as typed
|
|
655
770
|
--include=GLOB, --exclude=GLOB with -r and git sys1grep, only files whose name matches GLOB, or not
|
|
656
771
|
(with -r a file named on the command line is always searched; git sys1grep's pathspecs are filtered)
|
|
657
772
|
--changed-within=WHEN with -r and git sys1grep, only files modified within 30m / 2h / 7d / 2w, since a date
|
|
@@ -670,13 +785,26 @@ usage: sys1grep [OPTION]... -e MEANING|-Q QUESTION [-a MEANING] [-v MEANING]...
|
|
|
670
785
|
on ambiguous lines, not just speed
|
|
671
786
|
-j N concurrent requests (default 8)
|
|
672
787
|
-n print line numbers
|
|
673
|
-
|
|
674
|
-
--
|
|
675
|
-
|
|
788
|
+
--unit=UNIT the unit of judgement: line (default), zero, sentence-by-jev, sentence-by-rule or function
|
|
789
|
+
-z, --null-data --unit=zero: judge NUL-terminated records instead of lines, and print them NUL-terminated (see "Records that span several lines" above);
|
|
790
|
+
with --unit=sentence-by-*, each record is split into sentences
|
|
791
|
+
--unit=sentence-by-jev|sentence-by-rule judge each sentence instead of each line (see "One sentence at a time" above)
|
|
792
|
+
--unit=function judge each function and print its lines (see "One function at a time" above)
|
|
793
|
+
-o with --unit=sentence-by-*, print only the matching sentences
|
|
676
794
|
-p print each meaning's probability at the end of the line
|
|
677
|
-
--dry-run send nothing; print the
|
|
795
|
+
--dry-run send nothing; print the settings the search would run with (and their source, when not the
|
|
796
|
+
command line), each file searched and each request with its questions
|
|
678
797
|
--verbose print the same to stderr while searching
|
|
679
798
|
-i, --interactive show what --dry-run would send, and search only after y on the terminal
|
|
799
|
+
-M NUM, --max-columns=NUM send at most the first NUM characters of a line (or record, with -z); still
|
|
800
|
+
searched and judged, just not past that cutoff (default 2000, 8000 with -z)
|
|
801
|
+
--max-filesize=SIZE size every target first (K/M/G, default 10M); over it, skip it outright, like rg's own
|
|
802
|
+
--max-filesize (-y does not affect it). stdin is sized once read, and skipped the same way if
|
|
803
|
+
it is over; a --cached / <tree>: target is a blob, sized from its content; -g's commits stay
|
|
804
|
+
out of this (each is already bounded by -M when sent)
|
|
805
|
+
--max-cost=USD price the input about to be sent; over it (default 1), ask to continue on the terminal; -y
|
|
806
|
+
answers yes without asking; no terminal and the limit exceeded is exit 2, unchanged by -q
|
|
807
|
+
(scripts pass -y); -i already asks unconditionally and earlier, so this does not ask again
|
|
680
808
|
--dedup judge one line per template and reuse its answer for the rest (see "One line per template" above)
|
|
681
809
|
--color[=WHEN] auto (default: color when stdout is a terminal) / always / never; bare --color means auto
|
|
682
810
|
file and line number use grep's colors; with -p, probabilities are
|
|
@@ -766,14 +894,14 @@ fmt -w 100000 essay.txt | sys1grep -n -e "the author admits they made a mistake"
|
|
|
766
894
|
|
|
767
895
|
Each output line is then a whole paragraph, and `-n` counts the lines of `fmt`'s output, not of the file.
|
|
768
896
|
`fmt` puts a space where it joins two Japanese lines; Jev reads through it. To judge sentences across
|
|
769
|
-
wrapped lines you need neither: `--sentence` already joins them.
|
|
897
|
+
wrapped lines you need neither: `--unit=sentence-by-jev` already joins them.
|
|
770
898
|
|
|
771
899
|
### How do I search a JSONL chat log one message at a time?
|
|
772
900
|
|
|
773
901
|
Take the text out with `jq` and end each message with NUL, then judge records with `-z`:
|
|
774
902
|
|
|
775
903
|
```sh
|
|
776
|
-
jq -j '.content + "\u0000"' chat.jsonl | sys1grep -z -n --sentence -e "the customer is asking for a refund" | tr '\0' '\n'
|
|
904
|
+
jq -j '.content + "\u0000"' chat.jsonl | sys1grep -z -n --unit=sentence-by-jev -e "the customer is asking for a refund" | tr '\0' '\n'
|
|
777
905
|
```
|
|
778
906
|
|
|
779
907
|
Adjust `.content` to where your log keeps the text. Each message becomes one record, so a sentence never
|
package/docs/sentence.svg
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<svg xmlns="http://www.w3.org/2000/svg" width="808" height="240" font-family="SFMono-Regular,Menlo,Consolas,monospace" font-size="13">
|
|
2
2
|
<rect width="100%" height="100%" rx="6" fill="#1e1e2e"/>
|
|
3
|
-
<text x="16" y="29" xml:space="preserve"><tspan fill="#cdd6f4">$ sys1grep -n --sentence -C 3 --color \</tspan></text>
|
|
3
|
+
<text x="16" y="29" xml:space="preserve"><tspan fill="#cdd6f4">$ sys1grep -n --unit=sentence-by-jev -C 3 --color \</tspan></text>
|
|
4
4
|
<text x="16" y="49" xml:space="preserve"><tspan fill="#cdd6f4"> -e "the author admits they made a mistake" -e "customer is asking for a refund" tests/prose.txt</tspan></text>
|
|
5
5
|
<text x="16" y="69" xml:space="preserve"><tspan fill="#8ce99a">1</tspan><tspan fill="#66d9e8">:</tspan><tspan fill="#ffd43b" font-weight="700">I should have checked the input</tspan></text>
|
|
6
6
|
<text x="16" y="89" xml:space="preserve"><tspan fill="#8ce99a">2</tspan><tspan fill="#66d9e8">:</tspan><tspan fill="#ffd43b" font-weight="700">before shipping, and that was my</tspan></text>
|
package/package.json
CHANGED