deprecated-tracker 2.2.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.
- package/.pre-commit-hooks.yaml +23 -0
- package/CHANGELOG.md +281 -0
- package/LICENSE +21 -0
- package/README.md +121 -0
- package/bin/deprecated-tracker.js +14 -0
- package/docs/CLI.md +208 -0
- package/out/cli.js +535 -0
- package/package.json +211 -0
package/docs/CLI.md
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# Deprecated Tracker CLI
|
|
2
|
+
|
|
3
|
+
A headless `deprecated-tracker` binary for CI, Git hooks and coding agents.
|
|
4
|
+
It ships with the npm package, not with the VS Code extension.
|
|
5
|
+
|
|
6
|
+
## CI: the ratchet
|
|
7
|
+
|
|
8
|
+
Detecting deprecated code in CI is a solved problem — `@typescript-eslint` already fails a build when it finds any. That is rarely useful on a codebase that already has hundreds of them, because the only way to go green is to fix everything at once.
|
|
9
|
+
|
|
10
|
+
The `deprecated-tracker` CLI does the other thing: it records today's count as a **baseline** and fails only when the number **rises**. Debt becomes something a team ratchets down instead of a wall it can never clear.
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm run build # produces out/cli.js
|
|
14
|
+
node bin/deprecated-tracker.js --update-baseline # commit the baseline file
|
|
15
|
+
node bin/deprecated-tracker.js # exits 1 only if the count went up
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
| Option | Effect |
|
|
19
|
+
|---|---|
|
|
20
|
+
| `--files <file...>` | Scan only these files; everything after is a path |
|
|
21
|
+
| `--staged` | Ask git for the staged files, for hook managers that pass none |
|
|
22
|
+
| `--changed` | Everything uncommitted: staged, unstaged and untracked. For pre-push hooks and coding agents — `--staged` is the one for pre-commit |
|
|
23
|
+
| `--whole-files` | With `--files`, `--staged` or `--changed`, scan the whole file and ratchet it per-file instead of reporting only changed lines |
|
|
24
|
+
| `--root <dir>` | Project root, so paths can follow `--files` |
|
|
25
|
+
| `--baseline <file>` | Baseline location (default `.deprecated-tracker-baseline.json`) |
|
|
26
|
+
| `--update-baseline` | Record the current counts and exit 0 |
|
|
27
|
+
| `--max-new <n>` | Allow a deliberate increase of `n` |
|
|
28
|
+
| `--fail-on-any` | Ignore the baseline; fail if anything is found |
|
|
29
|
+
| `--format text\|json\|sarif\|markdown` | Report shape (default `text`). `markdown` is a table to paste into a PR comment |
|
|
30
|
+
| `--output <file>` | Write the report to a file instead of stdout |
|
|
31
|
+
| `--annotate github\|azure` | Emit inline CI annotations for files that rose |
|
|
32
|
+
| `--quiet`, `--help`, `--version` | — |
|
|
33
|
+
|
|
34
|
+
Exit codes: **0** at or below the baseline · **1** above it · **2** bad usage or unreadable baseline · **3** the scan failed.
|
|
35
|
+
|
|
36
|
+
## GitHub Actions
|
|
37
|
+
|
|
38
|
+
```yaml
|
|
39
|
+
- run: npm ci && npm run build
|
|
40
|
+
- run: node bin/deprecated-tracker.js --annotate github --format sarif --output deprecated.sarif
|
|
41
|
+
- uses: github/codeql-action/upload-sarif@v3
|
|
42
|
+
if: always()
|
|
43
|
+
with:
|
|
44
|
+
sarif_file: deprecated.sarif
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Azure Pipelines
|
|
48
|
+
|
|
49
|
+
```yaml
|
|
50
|
+
- script: npm ci && npm run build
|
|
51
|
+
- script: node bin/deprecated-tracker.js --annotate azure
|
|
52
|
+
displayName: Deprecation ratchet
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Pre-commit hooks
|
|
56
|
+
|
|
57
|
+
The same binary gates a commit, and works with every popular Git hooks manager. It scans only the staged files and, by default, reports only the lines that commit actually wrote — so touching a legacy file is free, and adding a deprecated call to it is not.
|
|
58
|
+
|
|
59
|
+
Hook managers split into two kinds, and there is a flag for each:
|
|
60
|
+
|
|
61
|
+
- **They pass the staged paths** — lint-staged, lefthook's `{staged_files}`, the `pre-commit` framework. Use **`--files`**; everything after it is read as a path.
|
|
62
|
+
- **They just run a command** — simple-git-hooks, a bare `.husky/pre-commit`, a raw `.git/hooks/pre-commit`. Use **`--staged`** and the CLI asks git itself.
|
|
63
|
+
|
|
64
|
+
**husky + lint-staged**
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
# .husky/pre-commit
|
|
68
|
+
npx lint-staged
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
// .lintstagedrc
|
|
73
|
+
{ "src/**/*.{ts,tsx,js,jsx}": "deprecated-tracker --files" }
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**lefthook**
|
|
77
|
+
|
|
78
|
+
```yaml
|
|
79
|
+
# lefthook.yml
|
|
80
|
+
pre-commit:
|
|
81
|
+
commands:
|
|
82
|
+
deprecated-tracker:
|
|
83
|
+
glob: "*.{ts,tsx,js,jsx}"
|
|
84
|
+
run: npx deprecated-tracker --files {staged_files}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**simple-git-hooks**
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
// package.json
|
|
91
|
+
{ "simple-git-hooks": { "pre-commit": "npx deprecated-tracker --staged" } }
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**pre-commit (pre-commit.com)**
|
|
95
|
+
|
|
96
|
+
```yaml
|
|
97
|
+
# .pre-commit-config.yaml
|
|
98
|
+
repos:
|
|
99
|
+
- repo: https://github.com/milad-hub/deprecated-tracker
|
|
100
|
+
rev: v2.1.0
|
|
101
|
+
hooks:
|
|
102
|
+
- id: deprecated-tracker
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**A plain hook, no manager**
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
# .git/hooks/pre-commit
|
|
109
|
+
npx deprecated-tracker --staged
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
A non-zero exit stops the commit:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
src/orders/cart.ts
|
|
116
|
+
31:4 Uses deprecated getCart — use useCart() instead
|
|
117
|
+
|
|
118
|
+
FAIL — 1 deprecated item(s) on the lines you changed
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**Two rules to choose between:**
|
|
122
|
+
|
|
123
|
+
- **Changed lines (default).** Fails only when a deprecated item sits on a line this commit wrote. No baseline file, nothing to maintain. It will not notice that adding `@deprecated` to a function has stranded call sites on unchanged lines — that is what the full scan and the CI ratchet are for.
|
|
124
|
+
- **`--whole-files`.** Scans each staged file completely and fails only when a file holds **more** than the baseline records for it. Catches the stranded-call-site case within the staged files, at the cost of keeping `.deprecated-tracker-baseline.json` committed and refreshed. With no baseline present it passes, for the same reason a first CI run does.
|
|
125
|
+
|
|
126
|
+
`--update-baseline` is refused alongside `--files` / `--staged`: writing a baseline from a handful of staged files would record zero for every file the run never looked at and quietly wipe the project's history.
|
|
127
|
+
|
|
128
|
+
**Two details that make it safe to drop into any of the above:**
|
|
129
|
+
|
|
130
|
+
- **Non-scannable paths are ignored.** A broad glob — `"*"` is a common lint-staged setting — hands over stylesheets, JSON and markdown. Only `.ts`, `.tsx`, `.js` and `.jsx` reach the scanner.
|
|
131
|
+
- **An empty staged set passes without scanning.** If nothing scannable is staged, the run prints `No staged files to scan.` and exits 0. It never falls back to scanning the whole project, which inside a hook would be both slow and the wrong verdict. Under `--format json` / `--format sarif` it emits an empty document instead of that sentence, so a parser is never handed prose.
|
|
132
|
+
|
|
133
|
+
**Worth knowing before you wire it up:**
|
|
134
|
+
|
|
135
|
+
- **A first run with no baseline passes** and tells you to record one. Failing a repo over debt it already had is the behaviour this tool exists to avoid.
|
|
136
|
+
- **When the count falls the run passes** and prints how stale the baseline is. Re-run with `--update-baseline` on a merge to your default branch to lock the gain in.
|
|
137
|
+
- **The gate is the total, not per-file.** Removing five in one file and adding five in another passes. Per-file counts still decide which files get annotated.
|
|
138
|
+
- **Custom tags and method ignores come from the config file, not the editor.** The editor's live in VS Code workspace storage, which nothing headless can read. Put `customTags` and `ignoreMethods` in `.deprecatedtrackerrc` (or the `deprecatedTracker` key in `package.json`) and the CLI honours them — that is the only route for a project that never installs the extension. `excludePatterns` is how you ignore whole files.
|
|
139
|
+
- **A rejected config key warns on stderr and the run continues.** A typo must not fail a commit, but it must not be invisible either.
|
|
140
|
+
|
|
141
|
+
## For AI coding agents
|
|
142
|
+
|
|
143
|
+
Claude Code, Codex, Cursor and anything else that can run a command can use the same CLI to check its own edits. Point `--files` at what it just wrote and read the JSON off stdout:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
npx deprecated-tracker --files src/a.ts src/b.ts --format json
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"passed": false,
|
|
152
|
+
"total": 1,
|
|
153
|
+
"items": [
|
|
154
|
+
{ "name": "oldApi", "kind": "usage", "file": "src/a.ts",
|
|
155
|
+
"line": 12, "character": 10, "reason": "Use newApi instead" }
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
- **Unstaged edits are covered.** A file with no staged hunks is read as entirely changed, so everything in it is reported — nothing needs staging or committing first.
|
|
161
|
+
- **`items[].reason`** carries the `@deprecated` text, usually the replacement instruction. That is the field to act on.
|
|
162
|
+
- **Exit code is the verdict, not an error:** `1` means findings. An agent that treats any non-zero exit as a crash will misread it.
|
|
163
|
+
- Drop `--files` and pass a path to scan the whole project; add `--fail-on-any` to ignore the baseline.
|
|
164
|
+
|
|
165
|
+
## As an MCP server
|
|
166
|
+
|
|
167
|
+
Shelling out works, but registering the scanner as an MCP server gives the agent
|
|
168
|
+
the verbs by name, a schema for each, structured results instead of parsed
|
|
169
|
+
stdout, and calls that do not each trip a shell-command approval.
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
npx deprecated-tracker mcp install # every agent found, project scope
|
|
173
|
+
npx deprecated-tracker mcp install --agent codex --scope user
|
|
174
|
+
npx deprecated-tracker mcp uninstall # same flags, same targets
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
| Tool | What it does |
|
|
178
|
+
|---|---|
|
|
179
|
+
| `scan_project` | Scan a whole project. Optional `root`. |
|
|
180
|
+
| `scan_changes` | Scan staged, unstaged and untracked work. Optional `whole_files`. |
|
|
181
|
+
| `scan_files` | Scan an explicit `files` list — use it straight after editing. |
|
|
182
|
+
|
|
183
|
+
Each returns the same shape as `--format json`, plus `passed` and the baseline
|
|
184
|
+
comparison, so there is one machine contract to learn rather than two. A failed
|
|
185
|
+
scan comes back as a tool error, never as a dead server.
|
|
186
|
+
|
|
187
|
+
**Where the registration goes:**
|
|
188
|
+
|
|
189
|
+
| Agent | `--scope project` | `--scope user` |
|
|
190
|
+
|---|---|---|
|
|
191
|
+
| `claude-code` | `.mcp.json` at the repo root | `mcpServers` in `~/.claude.json` |
|
|
192
|
+
| `codex` | `.codex/config.toml` in the repo | `~/.codex/config.toml` |
|
|
193
|
+
|
|
194
|
+
Project scope is the default: it gets committed, so the whole team has the tool
|
|
195
|
+
after a clone. `uninstall` removes only from the scope you name — cleaning up a
|
|
196
|
+
project never touches a user-level registration.
|
|
197
|
+
|
|
198
|
+
The agent's own CLI (`claude mcp add`, `codex mcp add`) is used when it is on
|
|
199
|
+
PATH; otherwise the config file is edited directly, merging rather than
|
|
200
|
+
replacing. Two things to expect afterwards:
|
|
201
|
+
|
|
202
|
+
- **Restart the agent** before it sees the server.
|
|
203
|
+
- **Claude Code asks you to approve a project-scoped server** the first time,
|
|
204
|
+
deliberately — a cloned repo should not be able to launch processes on your
|
|
205
|
+
machine. Run `/mcp` if you miss the prompt.
|
|
206
|
+
|
|
207
|
+
To run the server by hand, `deprecated-tracker mcp` speaks JSON-RPC over stdio.
|
|
208
|
+
stdout carries protocol frames only; warnings and diagnostics go to stderr.
|