jevprune 0.1.0 → 0.1.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.md +98 -143
- package/dist/cli.js +1107 -1020
- package/dist/index.d.ts +15 -5
- package/dist/index.js +356 -102
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,161 +1,77 @@
|
|
|
1
1
|
# jevprune
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Built for coding agents that run `npm test`, `cargo build`, `pytest` or `docker compose up` and push thousands of lines into their context. Line relevance is decided per line by [Jev](https://typesafe.ai), TypeSafe's model, with a fixed set of lines kept before Jev sees anything: the last 40 lines, every error signature, and the lines around it.
|
|
3
|
+
jevprune filters long command output for coding agents using a task description. Retained lines keep their original text and order.
|
|
6
4
|
|
|
7
5
|
## Install
|
|
8
6
|
|
|
7
|
+
Requires Node.js 22 or later. Jev selection also requires an early-access TypeSafe API key. Without one, jevprune keeps the first 40 lines, the last 40 lines, and every error line with the 3 lines around it. Keys come from the waitlist at [typesafe.ai](https://typesafe.ai).
|
|
8
|
+
|
|
9
9
|
```sh
|
|
10
10
|
npm install -g jevprune
|
|
11
|
-
export TYPESAFE_API_KEY=...
|
|
11
|
+
export TYPESAFE_API_KEY=...
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
Line relevance is decided per line by [Jev](https://typesafe.ai), TypeSafe's model. For Jev-selected runs, jevprune sends the task, command, and candidate output lines to the TypeSafe API. Blank lines and lines kept by deterministic rules are not sent.
|
|
15
|
+
|
|
16
|
+
## Quick start
|
|
15
17
|
|
|
16
18
|
```sh
|
|
17
|
-
|
|
18
|
-
claude plugin install jevprune@jevprune
|
|
19
|
+
jevprune run --task "fix the failing auth test" -- npm test
|
|
19
20
|
```
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
`run` executes the command with the given arguments (no shell), captures stdout and stderr in arrival order, prints the kept lines and exits with the command's exit code. For a pipeline or a redirect, use `-- bash -c '...'`.
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
```sh
|
|
25
|
+
jevprune select --task "find the slow build step" --file build.log
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`select` prunes a local file or stdin and exits 0 when it processes the input successfully. It cannot read or preserve the producer's exit status, so use `run` when exit status matters.
|
|
29
|
+
|
|
30
|
+
A pruned run ends with a footer that carries its run ID, and every collapse marker carries a line range. Print a range back:
|
|
24
31
|
|
|
25
32
|
```sh
|
|
26
|
-
jevprune run --task "fix the failing auth test" -- npm test
|
|
27
|
-
npm test 2>&1 | jevprune select --task "fix the failing auth test"
|
|
28
33
|
jevprune show <run-id> --lines 120-531
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```sh
|
|
29
37
|
jevprune gain
|
|
30
38
|
```
|
|
31
39
|
|
|
32
|
-
`
|
|
40
|
+
`gain` totals locally recorded input and output lines and estimates the removed output tokens.
|
|
33
41
|
|
|
34
|
-
The task comes from `--task`, else `JEVPRUNE_TASK`, else
|
|
42
|
+
The task comes from `--task`, else `JEVPRUNE_TASK`, else, when the plugin rewrite hook supplies a transcript, the first prompt of the session, else the command itself.
|
|
35
43
|
|
|
36
44
|
## Demo
|
|
37
45
|
|
|
38
46
|

|
|
39
47
|
|
|
40
|
-
The
|
|
48
|
+
The demo filters a saved test log, then retrieves omitted lines from its saved run. Run IDs are generated locally. The first task is a `select` run over a saved failure log; `run` passes a failed command's output through in full.
|
|
41
49
|
|
|
42
|
-
|
|
43
|
-
jevprune select --task "fix the failing auth test" --command "npm test" --file test/fixtures/npm-test.log
|
|
44
|
-
```
|
|
50
|
+
Run the demo from a source checkout:
|
|
45
51
|
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
[jevprune: 456 lines dropped, run mu6ln7nv-3cb9, lines 55-510]
|
|
50
|
-
✓ src/auth/login.test.ts > login > merges a stale session 3ms
|
|
51
|
-
✓ src/auth/login.test.ts > login > clears unicode input 3ms
|
|
52
|
-
✓ src/auth/login.test.ts > login > ignores the previous state 2ms
|
|
53
|
-
× src/auth/login.test.ts > login > rejects an expired session token 14ms
|
|
54
|
-
✓ src/auth/login.test.ts > login > updates the locale 3ms
|
|
55
|
-
✓ src/auth/login.test.ts > login > keeps the default value 3ms
|
|
56
|
-
✓ src/auth/login.test.ts > login > computes a network failure 18ms
|
|
57
|
-
[jevprune: 724 lines dropped, run mu6ln7nv-3cb9, lines 518-1241]
|
|
58
|
-
stderr | src/notifications/push.test.ts > push > paginates duplicate entries
|
|
59
|
-
Warning: An update to Form inside a test was not wrapped in act(...).
|
|
60
|
-
[jevprune: 1696 lines dropped, run mu6ln7nv-3cb9, lines 1244-2939]
|
|
61
|
-
✓ src/components/toast.test.ts > toast > restores a stale session 5ms
|
|
62
|
-
✓ src/components/toast.test.ts > toast > ignores a negative quantity 9ms
|
|
63
|
-
✓ src/components/toast.test.ts > toast > emits an empty input 9ms
|
|
64
|
-
✓ src/components/toast.test.ts > toast > emits an unknown id 12ms
|
|
65
|
-
✓ src/components/toast.test.ts > toast > formats the previous state 1ms
|
|
66
|
-
✓ src/components/toast.test.ts > toast > filters the cached result 4ms
|
|
67
|
-
✓ src/components/toast.test.ts > toast > ignores a network failure 18ms
|
|
68
|
-
✓ src/components/toast.test.ts > toast > clears a large payload 18ms
|
|
69
|
-
✓ src/components/toast.test.ts > toast > merges a partial update 0ms
|
|
70
|
-
✓ src/components/toast.test.ts > toast > clears leading whitespace 7ms
|
|
71
|
-
✓ src/components/toast.test.ts > toast > filters a stale session 25ms
|
|
72
|
-
✓ src/components/toast.test.ts > toast > returns a negative quantity 12ms
|
|
73
|
-
|
|
74
|
-
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
|
|
75
|
-
|
|
76
|
-
FAIL src/auth/login.test.ts > login > rejects an expired session token
|
|
77
|
-
AssertionError: expected 200 to be 401 // Object.is equality
|
|
78
|
-
|
|
79
|
-
- Expected
|
|
80
|
-
+ Received
|
|
81
|
-
|
|
82
|
-
- 401
|
|
83
|
-
+ 200
|
|
84
|
-
|
|
85
|
-
❯ src/auth/login.test.ts:88:29
|
|
86
|
-
86| const response = await login({ token: expiredToken });
|
|
87
|
-
87|
|
|
88
|
-
88| expect(response.status).toBe(401);
|
|
89
|
-
| ^
|
|
90
|
-
89| expect(response.body.error).toBe("session expired");
|
|
91
|
-
90| });
|
|
92
|
-
|
|
93
|
-
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
Test Files 1 failed | 94 passed (95)
|
|
97
|
-
Tests 1 failed | 2914 passed (2915)
|
|
98
|
-
Start at 09:12:04
|
|
99
|
-
Duration 41.20s (transform 4.11s, setup 1.62s, collect 12.30s, tests 33.94s, environment 9.81s)
|
|
100
|
-
|
|
101
|
-
jevprune: 2,979 → 54 lines, full output ~/.jevprune/runs/mu6ln7nv-3cb9.log
|
|
52
|
+
```sh
|
|
53
|
+
git clone https://github.com/ibrahemid/jevprune.git
|
|
54
|
+
cd jevprune
|
|
102
55
|
```
|
|
103
56
|
|
|
104
57
|
```sh
|
|
58
|
+
jevprune select --task "fix the failing auth test" --command "npm test" --file test/fixtures/npm-test.log
|
|
105
59
|
jevprune select --task "why is the build slow" --command "npm test" --file test/fixtures/npm-test.log
|
|
106
60
|
```
|
|
107
61
|
|
|
108
|
-
Lines 53 to 78 of the 347 it printed, and the footer:
|
|
109
|
-
|
|
110
|
-
```
|
|
111
|
-
✓ src/billing/refunds.test.ts > refunds > rejects a negative quantity 12ms
|
|
112
|
-
✓ src/billing/refunds.test.ts > refunds > clears a stale session 1170ms
|
|
113
|
-
[jevprune: 4 lines dropped, run mu6ln5j9-4968, lines 844-847]
|
|
114
|
-
✓ src/billing/refunds.test.ts > refunds > keeps an empty input 1282ms
|
|
115
|
-
✓ src/billing/refunds.test.ts > refunds > updates a trailing slash 1083ms
|
|
116
|
-
✓ src/billing/refunds.test.ts > refunds > ignores an empty input 2ms
|
|
117
|
-
✓ src/billing/refunds.test.ts > refunds > sorts an expired token 7ms
|
|
118
|
-
✓ src/billing/refunds.test.ts > refunds > sorts a missing field 2216ms
|
|
119
|
-
✓ src/billing/refunds.test.ts > refunds > renders a network failure 25ms
|
|
120
|
-
✓ src/billing/refunds.test.ts > refunds > parses an expired token 1904ms
|
|
121
|
-
✓ src/billing/refunds.test.ts > refunds > merges an empty input 7ms
|
|
122
|
-
✓ src/billing/refunds.test.ts > refunds > parses the sort order 1013ms
|
|
123
|
-
[jevprune: 9 lines dropped, run mu6ln5j9-4968, lines 857-865]
|
|
124
|
-
✓ src/hooks/use-form.test.ts > use-form > keeps a network failure 1610ms
|
|
125
|
-
✓ src/hooks/use-form.test.ts > use-form > paginates a partial update 2095ms
|
|
126
|
-
✓ src/hooks/use-form.test.ts > use-form > keeps the cached result 2512ms
|
|
127
|
-
✓ src/hooks/use-form.test.ts > use-form > parses the locale 466ms
|
|
128
|
-
✓ src/hooks/use-form.test.ts > use-form > updates a stale session 2ms
|
|
129
|
-
✓ src/hooks/use-form.test.ts > use-form > merges a negative quantity 1ms
|
|
130
|
-
✓ src/hooks/use-form.test.ts > use-form > restores an empty input 2073ms
|
|
131
|
-
✓ src/hooks/use-form.test.ts > use-form > filters a missing field 2203ms
|
|
132
|
-
[jevprune: 4 lines dropped, run mu6ln5j9-4968, lines 874-877]
|
|
133
|
-
✓ src/hooks/use-form.test.ts > use-form > paginates the previous state 483ms
|
|
134
|
-
[jevprune: 8 lines dropped, run mu6ln5j9-4968, lines 879-886]
|
|
135
|
-
✓ src/hooks/use-form.test.ts > use-form > validates a large payload 1372ms
|
|
136
|
-
[jevprune: 6 lines dropped, run mu6ln5j9-4968, lines 888-893]
|
|
137
|
-
```
|
|
138
|
-
|
|
139
62
|
```
|
|
63
|
+
jevprune: 2,979 → 54 lines, full output ~/.jevprune/runs/mu6ln7nv-3cb9.log
|
|
140
64
|
jevprune: 2,979 → 347 lines, full output ~/.jevprune/runs/mu6ln5j9-4968.log
|
|
141
65
|
```
|
|
142
66
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
```sh
|
|
146
|
-
jevprune show mu6ln7nv-3cb9 --lines 55-57
|
|
147
|
-
```
|
|
67
|
+
In these recorded runs, the auth task kept 54 of 2,979 lines and the timing task kept 347. Use the run ID and line range printed by a local run to retrieve omitted output while its log is retained.
|
|
148
68
|
|
|
149
|
-
|
|
150
|
-
[deprecation] `fetchJson` is deprecated, use `http.get` instead
|
|
151
|
-
|
|
152
|
-
✓ src/api/errors.test.ts > errors > merges the sort order 3ms
|
|
153
|
-
```
|
|
69
|
+
[Full demo output](https://github.com/ibrahemid/jevprune/blob/main/docs/demo-output.md).
|
|
154
70
|
|
|
155
|
-
##
|
|
71
|
+
## How selection and recovery work
|
|
156
72
|
|
|
157
73
|
1. 60 lines or fewer: everything, untouched, no request made.
|
|
158
|
-
2.
|
|
74
|
+
2. `run` passes through all output when its command exits non-zero or receives a signal. `select` does not know the producer's exit status, so it can prune a failure log.
|
|
159
75
|
3. Otherwise, before Jev: the last 40 lines, every line matching an error signature (`FAIL`, `error:`, `AssertionError`, `Traceback`, stack frames, `exited with code`, and similar), and the 3 lines on each side of it. Repeated identical signature lines count once.
|
|
160
76
|
4. The remaining lines go to Jev in windows, one yes/no question per line: is this line needed for the task? Lines scoring at or above the threshold (default 0.3) are kept.
|
|
161
77
|
5. Dropped runs shorter than 3 lines are kept. Longer ones collapse into one marker:
|
|
@@ -170,27 +86,36 @@ The last line of the output is the footer:
|
|
|
170
86
|
jevprune: 3,104 → 88 lines, exit 0, full output ~/.jevprune/runs/m1xk2p7a-3f9c.log
|
|
171
87
|
```
|
|
172
88
|
|
|
173
|
-
|
|
89
|
+
jevprune preserves every retained command line byte-for-byte and in its original order. It inserts only collapse markers and a footer.
|
|
174
90
|
|
|
175
|
-
|
|
91
|
+
A dropped line may have mattered. When a line you expect is missing, run `show` on the marker's range before concluding it is absent. When the footer includes `full output <path>`, `jevprune show <id> --lines A-B` prints that saved range exactly. If the footer says `full output was not saved`, dropped ranges cannot be recovered. Retention deletes the oldest saved runs once either limit in the configuration table is reached, so an older run can become unavailable.
|
|
176
92
|
|
|
177
|
-
|
|
93
|
+
A missing or rejected key, a rate limit, an outage, a timeout or a malformed answer does not fail the command. jevprune keeps the deterministic set plus the first 40 and last 40 lines and says so in the footer:
|
|
178
94
|
|
|
179
|
-
|
|
95
|
+
```
|
|
96
|
+
jevprune: fallback (Jev unavailable: timeout), 3,104 → 83 lines, exit 0, full output ~/.jevprune/runs/<id>.log
|
|
97
|
+
```
|
|
180
98
|
|
|
181
|
-
|
|
99
|
+
Input over the size limit takes the same selection with no Jev request, and its footer names the limit rather than an unavailable Jev:
|
|
182
100
|
|
|
183
101
|
```
|
|
184
|
-
jevprune: fallback (
|
|
102
|
+
jevprune: fallback (output over 16777216 bytes), 51,234 → 83 lines, exit 0, full output ~/.jevprune/runs/<id>.log
|
|
185
103
|
```
|
|
186
104
|
|
|
187
105
|
## Claude Code plugin
|
|
188
106
|
|
|
189
|
-
|
|
107
|
+
```sh
|
|
108
|
+
claude plugin marketplace add ibrahemid/jevprune
|
|
109
|
+
claude plugin install jevprune@jevprune
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The plugin bundles a skill and an optional Bash rewrite hook. Both call the globally installed `jevprune` binary. Without the binary, commands run as before.
|
|
190
113
|
|
|
191
|
-
The
|
|
114
|
+
The skill is the default path. It tells the agent to call `jevprune run --task "<task>" -- <command>` itself, so the user sees and approves the exact command that runs and nothing is rewritten after approval. It is still a different command from a bare `npm test`: a rule like `Bash(npm test:*)` does not match it, so the wrapped run needs its own approval. `Bash(jevprune run:*)` approves any command run through the wrapper.
|
|
192
115
|
|
|
193
|
-
Set `"autoWrap":
|
|
116
|
+
The rewrite hook is off by default. Set `"autoWrap": true` in `~/.jevprune/config.json` to turn it on. A `PreToolUse` hook then rewrites the command to `jevprune run --hook --transcript <path> -- bash -c '<command>'`. `bash -c` keeps pipelines, redirects and quoting as the agent wrote them; jevprune only owns capture and selection. Permission rules are matched against the rewritten command, so rules such as `Bash(npm test:*)` stop matching: an interactive session prompts for each wrapped command, and a headless run can be denied.
|
|
117
|
+
|
|
118
|
+
The hook leaves a command alone when it is already wrapped, runs in the background, ends with `&`, changes shell state (`cd`, `export`, `source`, `.`, `unset`, `alias`, `set`, `eval`, `exec`, `pushd`, `popd`), starts an interactive program (`vim`, `less`, `ssh`, `sudo`, `top`, `tmux`, `claude`, and similar), starts a REPL or shell with no arguments (`python`, `node`, `bash`, `psql`, `gh`), runs `docker exec` or `docker run` with a terminal flag, follows a file with `tail -f`, or starts with an allowlisted prefix (`cd`, `ls`, `pwd`, `echo`, `git status`, `git add`, `git commit`, `git log`, `git diff --stat`, `which`, `mkdir`, `touch`, `true`, `test`, `[`).
|
|
194
119
|
|
|
195
120
|
## Configuration
|
|
196
121
|
|
|
@@ -207,50 +132,80 @@ Set `"autoWrap": false` in `~/.jevprune/config.json` to turn the rewrite off. Th
|
|
|
207
132
|
| `windowTokens` | `25000` | estimated token budget per Jev request |
|
|
208
133
|
| `windowTimeoutMs` | `10000` | per-window timeout before fallback |
|
|
209
134
|
| `concurrency` | `4` | Jev requests in flight |
|
|
210
|
-
| `maxPruneBytes` | `16777216` | larger
|
|
211
|
-
| `retention.maxRuns` | `200` | saved runs
|
|
212
|
-
| `retention.maxBytes` | `268435456` |
|
|
213
|
-
| `autoWrap` | `
|
|
135
|
+
| `maxPruneBytes` | `16777216` | bytes (16 MiB); larger input gets no Jev request, and is pruned by head and tail unless `run` passes a failed or non-UTF-8 command's output through |
|
|
136
|
+
| `retention.maxRuns` | `200` | maximum saved runs before the oldest are deleted |
|
|
137
|
+
| `retention.maxBytes` | `268435456` | maximum saved-run bytes (256 MiB) before the oldest are deleted |
|
|
138
|
+
| `autoWrap` | `false` | when true, the plugin hook rewrites Bash commands |
|
|
214
139
|
| `allowlist` | see above | command prefixes the plugin never wraps |
|
|
215
140
|
|
|
141
|
+
Either retention limit can delete a run that a marker still refers to.
|
|
142
|
+
|
|
216
143
|
Environment: `TYPESAFE_API_KEY`, `TYPESAFE_BASE_URL`, `JEVPRUNE_TASK`, `JEVPRUNE_HOME` (default `~/.jevprune`).
|
|
217
144
|
|
|
218
145
|
The defaults were set on real outputs from one machine (a vitest run, a Next.js build, a docker compose startup, a pytest run, a cargo build). They are a starting point.
|
|
219
146
|
|
|
220
147
|
## Library
|
|
221
148
|
|
|
149
|
+
A global CLI install does not make the import available to a project, so install it there:
|
|
150
|
+
|
|
151
|
+
```sh
|
|
152
|
+
npm install jevprune
|
|
153
|
+
```
|
|
154
|
+
|
|
222
155
|
```ts
|
|
156
|
+
import { readFile } from "node:fs/promises";
|
|
223
157
|
import { pruneOutput } from "jevprune";
|
|
224
158
|
|
|
159
|
+
const output = await readFile("build.log", "utf8");
|
|
160
|
+
|
|
225
161
|
const result = await pruneOutput({
|
|
226
162
|
text: output,
|
|
227
163
|
task: "fix the failing auth test",
|
|
228
164
|
command: "npm test",
|
|
229
165
|
exitCode: 0,
|
|
230
166
|
});
|
|
231
|
-
|
|
232
|
-
result.
|
|
233
|
-
result.
|
|
234
|
-
result.
|
|
167
|
+
|
|
168
|
+
result.kept; // exact retained text with collapse markers
|
|
169
|
+
result.dropped; // [{ from, to, count }]
|
|
170
|
+
result.runId; // selection identifier
|
|
171
|
+
result.logPath; // defined only when a recoverable run log was saved
|
|
172
|
+
result.footer; // status text, separate from kept
|
|
173
|
+
result.mode; // "fast-path" | "passthrough" | "jev" | "fallback"
|
|
174
|
+
result.linesIn; // lines read
|
|
175
|
+
result.linesOut; // lines in kept
|
|
176
|
+
result.fallbackReason; // fallback mode only: { kind: "unavailable", detail } or { kind: "size-limit", maxBytes }
|
|
235
177
|
```
|
|
236
178
|
|
|
237
|
-
|
|
179
|
+
| input | effect |
|
|
180
|
+
|---|---|
|
|
181
|
+
| `text` | the output to prune |
|
|
182
|
+
| `task` | the task the kept lines have to serve |
|
|
183
|
+
| `command` | supplies selection context |
|
|
184
|
+
| `exitCode` | a non-zero code passes the output through, unless the input is over `maxPruneBytes`; omitted or `null` means unknown and can be pruned |
|
|
185
|
+
| `client` | a supplied Jev client; `null` disables API selection, so eligible output uses the fallback |
|
|
186
|
+
| `config` | overrides the loaded configuration values |
|
|
187
|
+
| `env` | controls configuration and the default client |
|
|
188
|
+
| `save` | `false` disables the run store |
|
|
189
|
+
|
|
190
|
+
The four modes: `fast-path` for output within `fastPathLines`, `passthrough` for a failed command or non-UTF-8 output, `jev` for an API-selected run, `fallback` when Jev was unavailable or the input was over `maxPruneBytes`. `fast-path` and `save: false` return a `runId` with no `logPath`, and `jevprune show` cannot read those runs.
|
|
191
|
+
|
|
192
|
+
`pruneStream` has the same contract with `stream` replacing `text`. It holds only the head and the tail in memory, and with the run store enabled it streams the whole input there, so a stream over `maxPruneBytes` is pruned by head and tail and `show` still prints any dropped range. `FakeJevClient` is exported for tests.
|
|
238
193
|
|
|
239
|
-
## Limits
|
|
194
|
+
## Limits and data handling
|
|
240
195
|
|
|
241
|
-
-
|
|
242
|
-
-
|
|
196
|
+
- Saved runs and metadata are stored under `~/.jevprune`. The data sent to the TypeSafe API is listed under Install.
|
|
197
|
+
- `select` exits 0 when it processes its input. It cannot report the exit status of the command that produced that input.
|
|
243
198
|
- Needs an early-access TypeSafe key. Without one, every pruned run is the head-and-tail fallback.
|
|
244
|
-
-
|
|
245
|
-
-
|
|
199
|
+
- Selection sends several requests for a long output and spends input tokens on the TypeSafe account that issued the key.
|
|
200
|
+
- `run` takes an executable and arguments, no shell string. Use `bash -c '...'` for pipelines, which is what the rewrite hook does.
|
|
201
|
+
- Input over 16 MiB gets no Jev request. It is pruned by head and tail, except in `run`, where a failed command's output, or output that is not valid UTF-8, is printed in full from the saved run log; when that log could not be saved, the footer says `full output was not saved` and the printed output is incomplete.
|
|
246
202
|
- Output that is not valid UTF-8 passes through untouched.
|
|
247
|
-
- Everything jevprune saves stays under `~/.jevprune`. The task text is stored there with each run and nowhere else.
|
|
248
203
|
|
|
249
|
-
##
|
|
204
|
+
## Alternatives
|
|
250
205
|
|
|
251
|
-
- [fast-jev-compaction](https://github.com/tamaratran/fast-jev-compaction)
|
|
206
|
+
- [fast-jev-compaction](https://github.com/tamaratran/fast-jev-compaction) selects conversation content during compaction. jevprune selects lines from each command as it finishes, and also works as a CLI or library. The tools can be used together.
|
|
252
207
|
- [RTK](https://github.com/rtk-ai/rtk) filters output with rules written per tool. jevprune has no per-tool rules; the task decides.
|
|
253
|
-
- [Squeez](https://github.com/KRLabsOrg/squeez) selects task-relevant lines with a
|
|
208
|
+
- [Squeez](https://github.com/KRLabsOrg/squeez) selects task-relevant lines with a 2B model, in Python, running locally or on a server. jevprune selects through the TypeSafe API and prints dropped ranges back from its run store.
|
|
254
209
|
|
|
255
210
|
## License
|
|
256
211
|
|