whygit 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 +39 -47
- package/README.zh-CN.md +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
<div align="center">
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
3
|
# whygit
|
|
4
4
|
|
|
5
5
|
**Git blame tells you *who*. whygit tells you *why*.**
|
|
6
6
|
|
|
7
7
|
Point it at any repository. It turns the reasons already buried in git history
|
|
8
|
-
into answers you and your coding agent can cite
|
|
8
|
+
into answers you and your coding agent can cite 鈥?file, line, commit, author, date.
|
|
9
9
|
|
|
10
10
|
[](https://www.npmjs.com/package/whygit)
|
|
11
11
|
[](https://github.com/carefreebit/whygit/actions/workflows/ci.yml)
|
|
@@ -13,19 +13,19 @@ into answers you and your coding agent can cite — file, line, commit, author,
|
|
|
13
13
|
[](LICENSE)
|
|
14
14
|
[](#give-it-to-your-agent)
|
|
15
15
|
|
|
16
|
-
[
|
|
16
|
+
[涓枃](README.zh-CN.md) 路 [Quickstart](#quickstart) 路 [Commands](#commands) 路 [Agents](#give-it-to-your-agent) 路 [How it works](#how-it-works)
|
|
17
17
|
|
|
18
18
|
</div>
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
22
22
|
<p align="center">
|
|
23
|
-
<img src="docs/demo.svg" alt="whygit why "cookie jar" in a terminal" width="900">
|
|
23
|
+
<img src="https://raw.githubusercontent.com/carefreebit/whygit/main/docs/demo.svg" alt="whygit why "cookie jar" in a terminal" width="900">
|
|
24
24
|
</p>
|
|
25
25
|
|
|
26
|
-
<p align="center"><sub>Real output: <code>whygit why "cookie jar"</code> on <code>psf/requests</code>
|
|
26
|
+
<p align="center"><sub>Real output: <code>whygit why "cookie jar"</code> on <code>psf/requests</code> 鈥?4,884 commits indexed in 3s, answered in 21ms.</sub></p>
|
|
27
27
|
|
|
28
|
-
That answer existed all along
|
|
28
|
+
That answer existed all along 鈥?in a commit body from 2015 that nobody has read since.
|
|
29
29
|
whygit found it in 21 milliseconds, without an LLM, an API key, or a network call.
|
|
30
30
|
|
|
31
31
|
## The problem
|
|
@@ -38,7 +38,7 @@ redundant. A guard that seems paranoid. A `sleep(2)` that looks like laziness.
|
|
|
38
38
|
- LLM summaries of history **invent plausible reasons**. In a codebase, a plausible
|
|
39
39
|
wrong reason is worse than no reason.
|
|
40
40
|
- Coding agents are the worst affected: they rewrite the guard, delete the retry, and
|
|
41
|
-
the bug comes back six months later
|
|
41
|
+
the bug comes back six months later 鈥?because nothing told them the line was load-bearing.
|
|
42
42
|
|
|
43
43
|
whygit reads what your repository already wrote down, extracts the sentences that
|
|
44
44
|
actually explain a decision, and makes them retrievable in the two places that matter:
|
|
@@ -68,7 +68,7 @@ it is incremental: new commits are picked up automatically on the next run.
|
|
|
68
68
|
| `whygit why <words>` | Why does this behaviour exist? Ranked decisions with citations. |
|
|
69
69
|
| `whygit why <file>:<line>` | Why is *this line* still here? Blame + the decision behind it + how much of that change is still alive. |
|
|
70
70
|
| `whygit story <file>` | The biography of one file: birth, commits per year, the chapters that mattered, who kept it alive. |
|
|
71
|
-
| `whygit cursed` | Ranked risk map: churn
|
|
71
|
+
| `whygit cursed` | Ranked risk map: churn 脳 fix density 脳 author spread 脳 freshness. Read before refactoring. |
|
|
72
72
|
| `whygit whylog --write` | Generate `WHYLOG.md`: load-bearing decisions + cursed files, in Markdown. |
|
|
73
73
|
| `whygit check --base origin/main` | CI gate: what fraction of newly added lines trace to a commit that said why. |
|
|
74
74
|
| `whygit mcp` | MCP server over stdio for Claude Code, Cursor, Codex, and any MCP client. |
|
|
@@ -83,30 +83,30 @@ Every command takes `--json` for scripting, and `--cwd <path>` to point at anoth
|
|
|
83
83
|
$ whygit why src/requests/models.py:120
|
|
84
84
|
|
|
85
85
|
1. basics working
|
|
86
|
-
2012-12-15
|
|
86
|
+
2012-12-15 路 366e8e84 路 Kenneth Reitz 路 change
|
|
87
87
|
line 120 is 78 lines of this change, still in HEAD
|
|
88
88
|
|
|
89
89
|
2. Add hasattr checks for remaining protocol isinstance checks (#7505)
|
|
90
|
-
2026-06-09
|
|
90
|
+
2026-06-09 路 6f66281a 路 change
|
|
91
91
|
```
|
|
92
92
|
|
|
93
93
|
The line itself is unremarkable. What matters is that 78 lines around it are still
|
|
94
|
-
the original 2012 change
|
|
94
|
+
the original 2012 change 鈥?so the surrounding shape is load-bearing, not incidental.
|
|
95
95
|
|
|
96
96
|
### `story <file>`
|
|
97
97
|
|
|
98
98
|
```console
|
|
99
99
|
$ whygit story src/requests/models.py
|
|
100
100
|
|
|
101
|
-
born 2011-05-14
|
|
101
|
+
born 2011-05-14 路 package refactor
|
|
102
102
|
|
|
103
|
-
2011
|
|
104
|
-
2012
|
|
105
|
-
2013
|
|
103
|
+
2011 鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅路路路路路路 217
|
|
104
|
+
2012 鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅 254
|
|
105
|
+
2013 鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅路路路路路路路路路路路路路路路路路路路路路路路路路路 86
|
|
106
106
|
...
|
|
107
107
|
|
|
108
|
-
717 commits
|
|
109
|
-
|
|
108
|
+
717 commits 路 202 authors 路 154 fixes 路 0 TODO markers
|
|
109
|
+
鈹€鈹€鈹€ the plot 鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€
|
|
110
110
|
|
|
111
111
|
2015-04-06 Copy a PreparedRequest's CookieJar reliably
|
|
112
112
|
By adding _copy_cookie_jar we can reliably copy cookie jars so that we
|
|
@@ -119,12 +119,12 @@ $ whygit story src/requests/models.py
|
|
|
119
119
|
```console
|
|
120
120
|
$ whygit cursed
|
|
121
121
|
|
|
122
|
-
1 src/requests/models.py
|
|
123
|
-
2 src/requests/sessions.py
|
|
124
|
-
3 tests/test_requests.py
|
|
122
|
+
1 src/requests/models.py 鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅 8.1 717 commits 路 202 authors 路 154 fixes
|
|
123
|
+
2 src/requests/sessions.py 鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻埪? 7.5 334 commits 路 110 authors 路 79 fixes
|
|
124
|
+
3 tests/test_requests.py 鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅鈻堚枅路路 7.2 366 commits 路 104 authors 路 76 fixes
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
-
Not a code-quality judgement
|
|
127
|
+
Not a code-quality judgement 鈥?a map of where history is dense enough that a
|
|
128
128
|
confident rewrite is likely to be wrong.
|
|
129
129
|
|
|
130
130
|
## Give it to your agent
|
|
@@ -159,18 +159,17 @@ Before changing a line you do not understand, call `why_line` (MCP: whygit).
|
|
|
159
159
|
If a past decision contradicts your plan, say so before editing.
|
|
160
160
|
```
|
|
161
161
|
|
|
162
|
-
### WHYLOG.md
|
|
162
|
+
### WHYLOG.md 鈥?history your agent reads without being asked
|
|
163
163
|
|
|
164
164
|
`whygit whylog --write` produces a Markdown file that is small enough to live in a
|
|
165
165
|
repo and specific enough to change a decision:
|
|
166
166
|
|
|
167
|
-
- **Load-bearing decisions**
|
|
168
|
-
- **The cursed files**
|
|
169
|
-
- **House rule**
|
|
167
|
+
- **Load-bearing decisions** 鈥?ranked, each with the verbatim reason, date, commit, author, and the files it touches.
|
|
168
|
+
- **The cursed files** 鈥?a table of where history is thickest.
|
|
169
|
+
- **House rule** 鈥?the one-line convention (`WHY: ...`) that makes future commits explain themselves.
|
|
170
170
|
|
|
171
171
|
It is generated from git, never hand-edited, and it diffs cleanly in review.
|
|
172
|
-
Commit it, and every agent that starts in the repo gets the context for free
|
|
173
|
-
no MCP required.
|
|
172
|
+
Commit it, and every agent that starts in the repo gets the context for free 鈥?no MCP required.
|
|
174
173
|
|
|
175
174
|
### CI gate
|
|
176
175
|
|
|
@@ -185,25 +184,18 @@ It is a nudge, not a linter: the fix is one sentence in the commit body.
|
|
|
185
184
|
|
|
186
185
|
```text
|
|
187
186
|
git log (two passes: metadata + numstat)
|
|
188
|
-
|
|
189
|
-
▼
|
|
190
|
-
signals: strip trailers, drop bot noise, de-duplicate squash-merge subjects,
|
|
187
|
+
鈹? 鈻? signals: strip trailers, drop bot noise, de-duplicate squash-merge subjects,
|
|
191
188
|
keep sentences that contain a reason ("because", "so that", "to avoid",
|
|
192
|
-
"
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
ranking: BM25 × confidence × churn × recency × fix-density × noise penalties
|
|
199
|
-
│
|
|
200
|
-
├── whygit why / story / cursed (terminal)
|
|
201
|
-
├── whygit whylog (WHYLOG.md)
|
|
202
|
-
└── whygit mcp (agents)
|
|
189
|
+
"鐢变簬", "閬垮厤", "鍥炴粴" ...)
|
|
190
|
+
鈹? 鈻? SQLite .git/whygit/index.db commits 路 files 路 decisions 路 FTS5 路 risk
|
|
191
|
+
鈹? 鈻? ranking: BM25 脳 confidence 脳 churn 脳 recency 脳 fix-density 脳 noise penalties
|
|
192
|
+
鈹? 鈹溾攢鈹€ whygit why / story / cursed (terminal)
|
|
193
|
+
鈹溾攢鈹€ whygit whylog (WHYLOG.md)
|
|
194
|
+
鈹斺攢鈹€ whygit mcp (agents)
|
|
203
195
|
```
|
|
204
196
|
|
|
205
197
|
**What a "decision" is:** a commit whose message contains a sentence explaining a
|
|
206
|
-
choice. whygit does not interpret that sentence
|
|
198
|
+
choice. whygit does not interpret that sentence 鈥?it quotes it. If the message says
|
|
207
199
|
nothing, the decision has low confidence and ranks below the ones that do.
|
|
208
200
|
|
|
209
201
|
**Why it can be fast:** the whole index is built from two `git log` passes, and
|
|
@@ -211,13 +203,13 @@ queries run against FTS5 in the same process. On a laptop, 4,884 commits index i
|
|
|
211
203
|
~3 seconds and a query takes ~20 ms. No network, no model, no cache to warm.
|
|
212
204
|
|
|
213
205
|
**What it will not do:** invent a reason, summarise code, or judge quality. If the
|
|
214
|
-
history is silent, whygit says so
|
|
206
|
+
history is silent, whygit says so 鈥?silence is a finding too.
|
|
215
207
|
|
|
216
208
|
## Compared to
|
|
217
209
|
|
|
218
210
|
| | Answers "why" | Cites the source | Works offline | Agent-native |
|
|
219
211
|
| --- | :---: | :---: | :---: | :---: |
|
|
220
|
-
| `git blame` | no |
|
|
212
|
+
| `git blame` | no | 鈥?| yes | no |
|
|
221
213
|
| `git log` | only if you already know where to look | yes | yes | no |
|
|
222
214
|
| LLM-generated docs | sometimes | rarely | no | partly |
|
|
223
215
|
| **whygit** | **yes** | **yes (sha + file + line)** | **yes** | **yes (MCP + WHYLOG.md)** |
|
|
@@ -246,7 +238,7 @@ index under `.git/`. History is read-only.
|
|
|
246
238
|
- Rationale can only be as good as commit messages. whygit makes silence visible; it cannot fill it.
|
|
247
239
|
- Very large histories (500k+ commits) index in minutes, not seconds.
|
|
248
240
|
- Renames are followed by path, not by content similarity: a file moved twice may have two histories.
|
|
249
|
-
- The ranking is heuristic. It is tuned to prefer cited reasons over churn, and it will still be wrong sometimes
|
|
241
|
+
- The ranking is heuristic. It is tuned to prefer cited reasons over churn, and it will still be wrong sometimes 鈥?each result shows its citations so you can check.
|
|
250
242
|
|
|
251
243
|
## Contributing
|
|
252
244
|
|
|
@@ -257,7 +249,7 @@ npm run lint
|
|
|
257
249
|
node bin/whygit.js why "..." --cwd /path/to/any/repo
|
|
258
250
|
```
|
|
259
251
|
|
|
260
|
-
Issues and PRs welcome
|
|
252
|
+
Issues and PRs welcome 鈥?especially real-world ranking failures. Paste the query, the
|
|
261
253
|
repo, and what should have ranked first.
|
|
262
254
|
|
|
263
255
|
## License
|
|
@@ -271,6 +263,6 @@ MIT. See [LICENSE](LICENSE).
|
|
|
271
263
|
If whygit saved you from deleting a load-bearing line, a star helps the next person
|
|
272
264
|
find it.
|
|
273
265
|
|
|
274
|
-
**[
|
|
266
|
+
**[猸?Star whygit](https://github.com/carefreebit/whygit)**
|
|
275
267
|
|
|
276
268
|
</div>
|
package/README.zh-CN.md
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
---
|
|
21
21
|
|
|
22
22
|
<p align="center">
|
|
23
|
-
<img src="docs/demo.svg" alt="whygit why "cookie jar" 终端演示" width="900">
|
|
23
|
+
<img src="https://raw.githubusercontent.com/carefreebit/whygit/main/docs/demo.svg" alt="whygit why "cookie jar" 终端演示" width="900">
|
|
24
24
|
</p>
|
|
25
25
|
|
|
26
26
|
<p align="center"><sub>真实输出:在 <code>psf/requests</code> 上执行 <code>whygit why "cookie jar"</code> —— 4,884 个 commit 索引 3 秒,回答 21 毫秒。</sub></p>
|