git-jev-stage 0.1.0

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.
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "git-jev-stage",
3
+ "owner": { "name": "Ibrahem" },
4
+ "plugins": [
5
+ {
6
+ "name": "git-jev-stage",
7
+ "source": "./",
8
+ "description": "Stage the diff hunks that match a sentence."
9
+ }
10
+ ]
11
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "git-jev-stage",
3
+ "description": "Stage the diff hunks that match a sentence.",
4
+ "version": "0.1.0",
5
+ "author": {
6
+ "name": "Ibrahem"
7
+ },
8
+ "license": "MIT",
9
+ "keywords": ["git", "staging", "hunks", "typesafe", "jev"]
10
+ }
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ibrahem
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.
package/README.md ADDED
@@ -0,0 +1,114 @@
1
+ # git-jev-stage
2
+
3
+ Stage the hunks that match a sentence.
4
+
5
+ ```sh
6
+ git jev-stage "only the auth fix and its tests"
7
+ ```
8
+
9
+ ![demo](docs/demo.gif)
10
+
11
+ A working tree holds an auth fix, a CSS tweak and a `console.log` left over from debugging. One sentence stages the fix and its test; the rest stays unstaged.
12
+
13
+ ```
14
+ $ git jev-stage "only the auth fix and its tests"
15
+ M src/auth/login.ts
16
+ + 5072ba1e @@ -1,12 +1,13 @@ include 1.00 exclude 0.00 mixed 0.00
17
+ - 404a01a6 @@ -16,9 +17,10 @@ export async function refresh(req, res) { include 0.02 exclude 0.96 mixed 0.02
18
+ M src/styles/app.css
19
+ - 045da610 @@ -1,2 +1,2 @@ include 0.00 exclude 1.00 mixed 0.00
20
+ M test/auth.test.ts
21
+ + 1ff4dc6f @@ -1,5 +1,9 @@ include 0.97 exclude 0.00 mixed 0.03
22
+ will stage: 2 hunks, 2 files (+6 -1)
23
+ stage 2 hunks in 2 files? [y/N] y
24
+ staged 2 hunks in 2 files
25
+ $ git status --short
26
+ MM src/auth/login.ts
27
+ M src/styles/app.css
28
+ M test/auth.test.ts
29
+ ```
30
+
31
+ Then `git commit`, and `git jev-stage "the css change"` for the next one.
32
+
33
+ ## Install
34
+
35
+ ```sh
36
+ npm install -g git-jev-stage
37
+ export TYPESAFE_API_KEY=... # early-access key from typesafe.ai
38
+ ```
39
+
40
+ Git 2.30 or newer, Node 22 or newer. The key is also read from the nearest `.env` file between the current directory and the repository root.
41
+
42
+ ## How it works
43
+
44
+ 1. **Snapshot.** `git diff` from the index to the working tree, with fixed flags (`--binary --full-index --no-renames --unified=6`), parsed byte for byte into hunks. Each hunk gets an id from its path and bytes. HEAD, the index bytes and the diff are hashed.
45
+ 2. **One question per hunk.** Every hunk goes to [Jev](https://typesafe.ai) as a `choice` question with three options: `include` (every changed line belongs to the sentence), `exclude` (none does), `mixed` (some do). The sentence and the neighboring hunks of the same file travel along as context. Large diffs are split into windows under a token budget and sent concurrently.
46
+ 3. **Policy.** `include` or `exclude` with confidence at or above `--threshold` (default 0.6) is taken as is. Anything else, including a missing or malformed answer, is `mixed`.
47
+ 4. **Plan, then confirm.** The plan prints before anything changes. Each `mixed` hunk is shown and asked about: the whole hunk goes in or stays out. Lines are never split.
48
+ 5. **Atomic staging.** The selected hunks become one patch. It is applied to a private copy of the index with `git apply --cached --check` and then `git apply --cached`, the copy is verified, `index.lock` is taken, HEAD, the index bytes and the full diff are checked against the snapshot, and the copy is renamed into place. If anything moved in between, nothing is staged and the command exits 3.
49
+
50
+ The working tree is never written. No commit is made, no message is generated.
51
+
52
+ ## Flags
53
+
54
+ | Flag | Effect |
55
+ |---|---|
56
+ | `--exclude "<sentence>"` | Lines matching this sentence never belong. |
57
+ | `--dry-run` | Print the plan and the patch that would be staged. No prompts, no changes. |
58
+ | `--yes` | Skip the confirmation. `mixed` hunks stay unstaged and are listed. |
59
+ | `--json` | One JSON document on stdout, plan on stderr. Stages only with `--yes`. |
60
+ | `--threshold 0.6` | Confidence needed to take `include` or `exclude` as given. |
61
+ | `--no-color` | Plain output. `NO_COLOR` works too. |
62
+
63
+ Exit codes: 0 done or nothing to stage, 1 error, 2 usage, 3 the snapshot went stale or the index is locked. Git routes `git jev-stage --help` to a man page; use `git-jev-stage --help`.
64
+
65
+ ## For coding agents
66
+
67
+ ```sh
68
+ git jev-stage "the auth fix" --json --yes
69
+ ```
70
+
71
+ The document lists every hunk with its `id`, `header`, `text`, `decision`, `source`, `confidence` and `probabilities`, plus `applied`, `stagedHunkIds` and `mixedHunkIds`. An agent stages the mixed ones itself or leaves them.
72
+
73
+ Claude Code plugin:
74
+
75
+ ```sh
76
+ claude plugin marketplace add ibrahemid/git-jev-stage
77
+ claude plugin install git-jev-stage@git-jev-stage
78
+ ```
79
+
80
+ Other agents: `npx skills add ibrahemid/git-jev-stage`. The skill is `skills/git-jev-stage/SKILL.md`.
81
+
82
+ ## Library
83
+
84
+ ```ts
85
+ import { planSelection, applySelection } from "git-jev-stage";
86
+
87
+ const plan = await planSelection({ cwd, intent: "the auth fix" });
88
+ const includeIds = [...plan.decisions.values()]
89
+ .filter((decision) => decision.decision === "include")
90
+ .map((decision) => decision.hunkId);
91
+ await applySelection(plan, { includeIds });
92
+ ```
93
+
94
+ `planSelection` never mutates. `applySelection` stages exactly the ids it is given. Pass `provider: new FakeProvider(script)` in tests; the same validator runs on scripted and real answers.
95
+
96
+ ## Limits
97
+
98
+ - Hunks are git's, cut with 6 lines of context. A hunk with wanted and unwanted lines is `mixed`, and is staged whole or not at all.
99
+ - Binary, symlink and submodule changes stop the run with an error naming the paths. Stage or stash those first. A submodule that is only dirty is ignored.
100
+ - Empty new files and mode-only changes are listed as skipped; stage them with `git add`. Staging any hunk of a file also stages that file's mode change.
101
+ - Hunks in different windows of a large diff do not see each other.
102
+ - If HEAD, the index or the working tree changes between the plan and your answer, nothing is staged and the command exits 3. Run it again.
103
+ - The sentence and the hunk text are sent to api.typesafe.ai. Nothing is written to disk except the index.
104
+ - Without a key the command asks about every hunk by hand, like `git add -p` with the sentence on screen.
105
+
106
+ ## Neighbors
107
+
108
+ - `git add -p`: same granularity, one hunk at a time, no sentence.
109
+ - [git-surgeon](https://github.com/raine/git-surgeon): stages explicit hunk ids and line ranges. Built for agents that already know which lines they want.
110
+ - [VibeGit](https://github.com/kklemon/vibegit): groups a whole working tree into commits with an LLM. git-jev-stage answers one narrower question and never commits.
111
+
112
+ ## License
113
+
114
+ MIT