tend-cli 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.
- package/LICENSE +21 -0
- package/README.md +95 -0
- package/configs/default.eslint.config.mjs +47 -0
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +1754 -0
- package/dist/config-B5rO-fvz.js +1745 -0
- package/dist/index.d.ts +1274 -0
- package/dist/index.js +87 -0
- package/package.json +67 -0
- package/prompts/fix.md +29 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 tend-cli contributors
|
|
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,95 @@
|
|
|
1
|
+
# tend
|
|
2
|
+
|
|
3
|
+
> Tend your code now so it never becomes an overgrown mess.
|
|
4
|
+
|
|
5
|
+
An open-source CLI that audits a JS/TS repo with established scanners, then fixes the
|
|
6
|
+
findings with parallel AI sessions in a safe **scan → fix → re-scan** loop. It never
|
|
7
|
+
commits — fixes are left as uncommitted edits for you to review.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx tend-cli # snapshot → audit → fix loop → report (changed files)
|
|
11
|
+
npx tend-cli --all # fix the entire backlog, not just changed files
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Why
|
|
15
|
+
|
|
16
|
+
Every team already has scanners. What they don't have is the time to act on 200
|
|
17
|
+
findings. tend closes the loop: **deterministic detection → AI fix → deterministic
|
|
18
|
+
verification**. Machines find and check; the model only does the edit. The worst case
|
|
19
|
+
is "tend changed nothing," never "tend broke your code."
|
|
20
|
+
|
|
21
|
+
## What it runs
|
|
22
|
+
|
|
23
|
+
| Category | Tools | Action |
|
|
24
|
+
|----------|-------|--------|
|
|
25
|
+
| AI fix loop | `eslint`+`sonarjs`, `knip`, `jscpd`, `semgrep` | findings fed to AI sessions |
|
|
26
|
+
| Deterministic | `osv-scanner` | dependency version bumps, no AI |
|
|
27
|
+
| Report-and-halt | `gitleaks` | secrets surfaced loudly, never AI-touched; exit non-zero |
|
|
28
|
+
|
|
29
|
+
**`eslint`+`sonarjs`, `knip`, and `jscpd` ship with tend** (bundled deps, resolved from tend's
|
|
30
|
+
own install) — they work with zero setup. eslint+sonarjs runs via the ESLint Node API in one of
|
|
31
|
+
three modes, picked automatically:
|
|
32
|
+
|
|
33
|
+
| Your project | tend runs |
|
|
34
|
+
|--------------|-----------|
|
|
35
|
+
| no eslint config | **tend's config** — eslint recommended + sonarjs recommended (TS/JSX parsed, no tsconfig needed) |
|
|
36
|
+
| eslint config, no sonarjs | **your config + sonarjs layered on top** — your rules *and* sonarjs in one pass |
|
|
37
|
+
| eslint config with sonarjs | **your config, untouched** |
|
|
38
|
+
|
|
39
|
+
For `knip` and `jscpd`: tend uses **your project's installed version if you have one** (and that
|
|
40
|
+
tool auto-loads your `knip.json` / `.jscpd.json` from the repo root), otherwise it falls back to
|
|
41
|
+
tend's bundled copy. So if you already use them, tend runs *your* setup; if not, it just works.
|
|
42
|
+
|
|
43
|
+
The native tools — `semgrep`, `osv-scanner`, `gitleaks` — can't be npm deps; install those
|
|
44
|
+
yourself (`brew install …`). tend skips any missing scanner with a hint and errors only if none
|
|
45
|
+
of the six are present.
|
|
46
|
+
|
|
47
|
+
## Safety
|
|
48
|
+
|
|
49
|
+
- **In-place edits** on your actual files — no worktrees, no branches.
|
|
50
|
+
- A **silent snapshot** (tracked + untracked) is taken first as an invisible restore point.
|
|
51
|
+
- Every fix passes a gate — **anti-suppression · anti-regression · `tsc` · tests** — or it's
|
|
52
|
+
reverted atomically (code + its sibling test together).
|
|
53
|
+
- Tests are the behavior oracle: a fix may edit a test, but a **teeth check** rejects any
|
|
54
|
+
edit that no longer fails on the old code.
|
|
55
|
+
|
|
56
|
+
## Commands
|
|
57
|
+
|
|
58
|
+
| Command | What it does |
|
|
59
|
+
|---------|--------------|
|
|
60
|
+
| `tend` / `tend run` | snapshot → audit → fix loop → report |
|
|
61
|
+
| `tend diff` | show only the tool's edits (your own changes filtered out) |
|
|
62
|
+
| `tend undo` | restore the pre-run snapshot exactly |
|
|
63
|
+
| `tend show <id>` | full detail on one finding (attempts, flow path, docs) |
|
|
64
|
+
| `tend retry <id>` | re-attempt a stubborn finding with a larger budget |
|
|
65
|
+
|
|
66
|
+
## Config (zero-config by default)
|
|
67
|
+
|
|
68
|
+
`cosmiconfig` discovery (`.tendrc`, `tend.config.js`, a `tend` key in `package.json`, …):
|
|
69
|
+
|
|
70
|
+
```jsonc
|
|
71
|
+
{
|
|
72
|
+
"maxSessions": 4,
|
|
73
|
+
"maxLoops": 5,
|
|
74
|
+
"perIssueBudget": 3,
|
|
75
|
+
"teethCheck": true,
|
|
76
|
+
"includeTests": false,
|
|
77
|
+
"model": "sonnet",
|
|
78
|
+
"effort": "high"
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
CLI flags (`--max-loops`, `--max-sessions`, `--model`, `--effort`, `--all`) override the config
|
|
83
|
+
file. `model` is an alias (`sonnet` default, `opus`, `haiku`) or a full model id (e.g.
|
|
84
|
+
`claude-opus-4-8`); `effort` is the reasoning effort (`low | medium | high | xhigh | max`,
|
|
85
|
+
unset → claude's default). Both are passed straight to `claude -p`.
|
|
86
|
+
|
|
87
|
+
## Output
|
|
88
|
+
|
|
89
|
+
A live `listr2` task tree while running, a machine-readable `.tend/report.json`, and a
|
|
90
|
+
final summary that groups remaining issues by **why** tend couldn't fix them, ordered by
|
|
91
|
+
urgency: secrets → security → couldn't-fix → needs-review.
|
|
92
|
+
|
|
93
|
+
## License
|
|
94
|
+
|
|
95
|
+
MIT
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// tend's default config, used only when the target project has NO eslint config of its own:
|
|
2
|
+
// eslint's recommended rules + eslint-plugin-sonarjs recommended (bugs + code smells), with
|
|
3
|
+
// TS/JSX syntax parsing but NO type information (no tsconfig needed → fast).
|
|
4
|
+
// Plugins resolve relative to THIS file → from tend's own node_modules.
|
|
5
|
+
import js from "@eslint/js";
|
|
6
|
+
import tseslint from "typescript-eslint";
|
|
7
|
+
import sonarjs from "eslint-plugin-sonarjs";
|
|
8
|
+
import globals from "globals";
|
|
9
|
+
|
|
10
|
+
export default [
|
|
11
|
+
js.configs.recommended,
|
|
12
|
+
{
|
|
13
|
+
files: ["**/*.{js,mjs,cjs,jsx,ts,mts,cts,tsx}"],
|
|
14
|
+
languageOptions: {
|
|
15
|
+
parser: tseslint.parser, // syntactic only — no parserOptions.project → no type-checking cost
|
|
16
|
+
parserOptions: { ecmaFeatures: { jsx: true } },
|
|
17
|
+
// Declare the standard runtime environments so `no-undef` doesn't flag platform
|
|
18
|
+
// globals (process, console, fetch, crypto, setTimeout, AbortSignal, …).
|
|
19
|
+
globals: { ...globals.node, ...globals.browser, ...globals.es2024 },
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
files: ["**/*.{ts,mts,cts,tsx}"],
|
|
24
|
+
plugins: { "@typescript-eslint": tseslint.plugin },
|
|
25
|
+
rules: {
|
|
26
|
+
// On TypeScript, `no-undef` is redundant (the compiler already detects undefined
|
|
27
|
+
// symbols) and—run without type info—false-positives on lib/global types like
|
|
28
|
+
// `AbortSignal`. typescript-eslint's own guidance is to disable it for TS files.
|
|
29
|
+
"no-undef": "off",
|
|
30
|
+
// The core `no-unused-vars` rule reports incorrect errors on TS-only constructs
|
|
31
|
+
// (type-only imports, overload signatures, etc.), so typescript-eslint documents
|
|
32
|
+
// disabling it in favor of its TS-aware replacement. Underscore-prefixed names are
|
|
33
|
+
// the conventional "intentionally unused" signal.
|
|
34
|
+
"no-unused-vars": "off",
|
|
35
|
+
"@typescript-eslint/no-unused-vars": [
|
|
36
|
+
"warn",
|
|
37
|
+
{
|
|
38
|
+
argsIgnorePattern: "^_",
|
|
39
|
+
varsIgnorePattern: "^_",
|
|
40
|
+
caughtErrorsIgnorePattern: "^_",
|
|
41
|
+
destructuredArrayIgnorePattern: "^_",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
sonarjs.configs.recommended,
|
|
47
|
+
];
|
package/dist/bin.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|