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 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 { };