@benjaminthomas/spec-driven-dev 1.13.1 → 1.14.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/README.md CHANGED
@@ -75,7 +75,8 @@ and you can change any answer as you go. It asks how the project is organised (o
75
75
  or several repos that change together), your tracker, branches and commit style, where specs live
76
76
  and whether your team shares them, then looks through the code and saves the project memory
77
77
  ([details below](#project-setup-your-teams-rules)). If Claude Code or Codex is installed, the
78
- installer offers to open it with "run spec-setup" already typed in.
78
+ installer asks "Open Claude Code in soreto-shopify to set up your project?" (with your folder's name)
79
+ and opens it with "run spec-setup" already typed in.
79
80
 
80
81
  **3. Then run each stage in order.** You can type the slash command or just say the
81
82
  words in quotes.
@@ -272,8 +273,9 @@ a build output. Committing it would cause merge conflicts between branches. `doc
272
273
  it's committed.
273
274
 
274
275
  When `risk.enabled` is on, the skills use it:
275
- - `spec-investigate` digs into high and critical files in the change surface (past fix commits,
276
- dependents) and lists them as **Risk Hotspots**;
276
+ - `spec-investigate` always looks up the files in the change surface, digs into high and critical
277
+ ones (past fix commits, dependents), and lists them as **Risk Hotspots**, or says it checked and
278
+ found none;
277
279
  - `spec-create` raises those tasks one tier and requires a test aimed at each file's past failure
278
280
  pattern;
279
281
  - `spec-implement`'s reviewer and `spec-review` check those tests and read the risky files line
@@ -644,6 +646,7 @@ spec-driven-dev doctor # check .spec-driven.yml again
644
646
  spec-driven-dev status # list unfinished specs and each one's next step
645
647
  spec-driven-dev context --areas=billing # print the project memory (index, or chosen areas)
646
648
  spec-driven-dev settings # switch GitRisk, run-through and sharing from a menu
649
+ spec-driven-dev uninstall # remove the skills, plugin and cache (--all: settings too)
647
650
  spec-driven-dev risk # GitRisk: score files from git history → specs/context/risk.md
648
651
  spec-driven-dev risk-eval --tickets=tickets.md # compare agent behaviour with the risk signal on vs off
649
652
  # (--runs=3 --arms=on --timeout=20 --model=sonnet)
@@ -717,6 +720,23 @@ Each skill becomes a tool that returns its instructions, and supporting files ar
717
720
 
718
721
  ---
719
722
 
723
+ ### Uninstall
724
+
725
+ ```bash
726
+ npx @benjaminthomas/spec-driven-dev@latest uninstall
727
+ ```
728
+
729
+ It lists everything an install put on your machine (the skills in each AI tool, the Claude Code
730
+ plugin, the npx download cache), then removes it after one confirmation. Your other skills stay.
731
+
732
+ - **Kept by default:** your `.spec-driven.yml` settings file. Add `--all` to remove it and the
733
+ workspace registry (`~/.spec-driven/`) too.
734
+ - **Never touched:** specs, `CONTEXT.md`, `team-repos.yml` and your code. They're your team's work.
735
+ Delete them yourself if you want them gone.
736
+ - **In scripts or with `!` in Claude Code:** add `--yes`, since there's no terminal to confirm in.
737
+ - **Plugin installs:** `/plugin uninstall ticket-to-pr@spec-driven-dev` in Claude Code, if the
738
+ command can't do it for you.
739
+
720
740
  ## Compatibility
721
741
 
722
742
  | Skill | Claude Code | Codex CLI | Cursor | Antigravity | Notes |
@@ -802,7 +822,7 @@ plugin/evals/ `claude plugin eval` cases
802
822
  1. Increase `version` in both `package.json` and `plugin/.claude-plugin/plugin.json` (the check fails if
803
823
  they differ).
804
824
  2. Add a `CHANGELOG.md` entry, then commit and push.
805
- 3. Tag the release and push the tag: `git tag v1.13.1 && git push origin v1.13.1`.
825
+ 3. Tag the release and push the tag: `git tag v1.14.0 && git push origin v1.14.0`.
806
826
  4. Watch the **publish** run in the repo's Actions tab. When it's green, the new version is on
807
827
  npm. Claude Code plugin users get it from the marketplace once the commit is on `main`.
808
828
 
package/bin/cli.mjs CHANGED
@@ -4,6 +4,7 @@
4
4
  //
5
5
  // spec-driven-dev install the skills, then hand over to your AI tool ("run spec-setup")
6
6
  // spec-driven-dev setup scripted setup for CI: needs --yes or answer flags (people: say "run spec-setup")
7
+ // spec-driven-dev uninstall remove the skills (all tools), the Claude Code plugin and the download cache; --all also removes the settings file
7
8
  // spec-driven-dev doctor check .spec-driven.yml against the real repos (exit 1 on problems)
8
9
  // spec-driven-dev status list specs with unfinished work and each one's "Resume here" next step
9
10
  // spec-driven-dev context print specs/CONTEXT.md; --areas=billing,api prints only those area files
@@ -39,7 +40,7 @@ const args = process.argv.slice(2);
39
40
  const flag = (n) => args.includes(`--${n}`);
40
41
  const opt = (n) => args.find((a) => a.startsWith(`--${n}=`))?.split("=")[1];
41
42
  const command = args.find((a) => !a.startsWith("-")) || "install";
42
- const YES = flag("yes") || flag("y") || !process.stdin.isTTY || ["doctor", "status", "context", "risk", "risk-eval", "setup"].includes(command);
43
+ const YES = flag("yes") || flag("y") || !process.stdin.isTTY || ["doctor", "status", "context", "risk", "risk-eval", "setup"].includes(command) || (command === "uninstall" && flag("yes"));
43
44
  const DIR = path.resolve(opt("dir") || process.cwd());
44
45
 
45
46
  // Colour only for a person at a terminal; pipes, CI and NO_COLOR get plain text (and the tests stay plain).
@@ -893,6 +894,45 @@ async function settings() {
893
894
  }
894
895
  }
895
896
 
897
+ // Finds everything an install put on this machine and removes it after one confirmation.
898
+ // Specs, CONTEXT.md and code are never touched: they're the team's work, not part of the install.
899
+ async function uninstall() {
900
+ const found = [];
901
+ const ours = (d) => ALL_SKILLS.map((s) => path.join(d, s)).filter((f) => fs.existsSync(path.join(f, "SKILL.md")));
902
+ const dirs = [...new Set(Object.values(TOOLS).flatMap((t) => [path.join(HOME, t.global), path.join(DIR, t.project)]))];
903
+ for (const d of dirs) { const f = ours(d); if (f.length) found.push({ what: `${f.length} skills in ${d}`, paths: f }); }
904
+ const plugins = readJson(path.join(HOME, ".claude/plugins/installed_plugins.json"));
905
+ const pluginIds = Object.keys(plugins?.plugins || plugins || {}).filter((k) => /^(ticket-to-pr|spec-driven-dev)@/.test(k));
906
+ for (const id of pluginIds) found.push({ what: `Claude Code plugin ${id}`, plugin: id });
907
+ const npx = path.join(HOME, ".npm", "_npx");
908
+ for (const c of subdirs(npx)) if (fs.existsSync(path.join(npx, c, "node_modules", "@benjaminthomas", "spec-driven-dev")) && process.platform !== "win32")
909
+ found.push({ what: `npx download cache ${path.join(npx, c)}`, paths: [path.join(npx, c)] });
910
+ const config = findConfig(DIR);
911
+ const reg = readRegistry();
912
+ if (flag("all")) {
913
+ if (config) found.push({ what: `settings file ${config}`, paths: [config], config });
914
+ if (fs.existsSync(path.join(HOME, ".spec-driven"))) found.push({ what: `workspace registry ${path.join(HOME, ".spec-driven")}`, paths: [path.join(HOME, ".spec-driven")] });
915
+ }
916
+ step(1, "Uninstall spec-driven-dev", ink.red);
917
+ if (!found.length) { console.log("✓ Nothing to remove: no skills, plugin or cache from spec-driven-dev were found."); return; }
918
+ console.log("Found:\n" + found.map((f) => ` • ${f.what}`).join("\n"));
919
+ if (!flag("all") && (config || Object.keys(reg).length)) console.log(` Kept: your settings file${config ? ` (${config})` : ""}. Add --all to remove it too.`);
920
+ console.log(" Never touched: specs, CONTEXT.md and your code.");
921
+ if (!process.stdin.isTTY && !flag("yes")) { console.log("Nothing removed. To remove the above, run: spec-driven-dev uninstall --yes"); return; }
922
+ if (!flag("yes") && !(await askConfirm("Remove everything listed above?", false))) { console.log("Nothing removed."); return; }
923
+ for (const f of found) {
924
+ if (f.plugin) {
925
+ let ok = false;
926
+ if (onPath("claude")) try { execFileSync("claude", ["plugin", "uninstall", f.plugin], { stdio: "ignore" }); ok = true; } catch {}
927
+ console.log(ok ? `✓ Removed ${f.what}` : `• Remove the plugin in Claude Code: /plugin uninstall ${f.plugin}`);
928
+ continue;
929
+ }
930
+ for (const p of f.paths) fs.rmSync(p, { recursive: true, force: true });
931
+ console.log(`✓ Removed ${f.what}`);
932
+ }
933
+ console.log("Done. Reinstall any time with: npx @benjaminthomas/spec-driven-dev@latest");
934
+ }
935
+
896
936
  // Silent unless something is unfinished, so it's cheap to run at the start of a session.
897
937
  function status() {
898
938
  const file = findConfig(DIR);
@@ -923,6 +963,7 @@ try {
923
963
  else if (command === "context") context();
924
964
  else if (command === "risk") risk();
925
965
  else if (command === "settings") await settings();
966
+ else if (command === "uninstall") await uninstall();
926
967
  else if (command === "risk-eval") await riskEvalCmd();
927
968
  else if (command === "install") {
928
969
  if (HANDOFF) console.log("No interactive terminal (for example a \"!\" command in Claude Code), so the skills go to the AI tools it finds, for this project.\n");
@@ -930,7 +971,7 @@ try {
930
971
  if (tools.length && !flag("no-setup")) await handOver(tools);
931
972
  } else if (SETUP_IN_AGENT) handOver([], true);
932
973
  else if (command === "setup") await setup();
933
- else throw new Error(`Unknown command "${command}" — use install (default), setup, settings, doctor, status, context, risk, or risk-eval`);
974
+ else throw new Error(`Unknown command "${command}" — use install (default), setup, settings, uninstall, doctor, status, context, risk, or risk-eval`);
934
975
  if (command === "setup" && !SETUP_IN_AGENT) console.log('\nNext: in your AI tool, say "investigate <ticket>" or "create a spec".');
935
976
  } catch (e) {
936
977
  console.error(`✗ ${e.message}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@benjaminthomas/spec-driven-dev",
3
- "version": "1.13.1",
3
+ "version": "1.14.0",
4
4
  "description": "Spec-driven AI development workflow (investigate → spec → implement → verify → review → ship) as Agent Skills for Claude Code, Cursor, Codex CLI and Antigravity.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ticket-to-pr",
3
- "version": "1.13.1",
3
+ "version": "1.14.0",
4
4
  "description": "Parallel-batch spec-driven feature workflow (spec-setup, spec-investigate, spec-create, spec-implement, spec-verify, spec-review, spec-checkpoint, spec-ship) plus a portable SEO/GEO operations skill (generative-seo) for any codebase.",
5
5
  "author": {
6
6
  "name": "Benjamin Thomas",