tcsetup 1.2.0 → 1.3.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # tcsetup
2
2
 
3
- Bootstrap a new project with the full TC toolchain in one command.
3
+ Bootstrap and update a project with the full TC toolchain in one command.
4
4
 
5
5
  ## What it installs
6
6
 
@@ -9,21 +9,43 @@ Bootstrap a new project with the full TC toolchain in one command.
9
9
  | 1 | [BMAD Method](https://github.com/bmad-code-org/BMAD-METHOD) | `npx bmad-method install` |
10
10
  | 2 | [Spec Kit](https://github.com/github/spec-kit) | `specify init --here --ai claude` |
11
11
  | 3 | [Agreement System](https://github.com/tcanaud/agreement-system) | `npx agreement-system init --yes` |
12
- | 4 | [Mermaid Workbench](https://github.com/tcanaud/mermaid-workbench) | `npx mermaid-workbench init` |
12
+ | 4 | [ADR System](https://github.com/tcanaud/adr-system) | `npx adr-system init --yes` |
13
+ | 5 | [Mermaid Workbench](https://github.com/tcanaud/mermaid-workbench) | `npx mermaid-workbench init` |
14
+ | 6 | [Feature Lifecycle](https://github.com/tcanaud/feature-lifecycle) | `npx feature-lifecycle init --yes` |
13
15
 
14
16
  ## Usage
15
17
 
18
+ ### Init (onboard a new project)
19
+
16
20
  ```bash
17
21
  npx tcsetup
22
+ # or explicitly:
23
+ npx tcsetup init
24
+ ```
25
+
26
+ ### Update (refresh an existing project)
27
+
28
+ ```bash
29
+ npx tcsetup update
30
+ ```
31
+
32
+ Detects which tools are installed (by marker directories), updates their npm packages to latest, runs each tool's update command to refresh commands/templates, and refreshes tcsetup's own Claude Code command files. User data is never touched.
33
+
34
+ ### Help
35
+
36
+ ```bash
37
+ npx tcsetup help
18
38
  ```
19
39
 
20
- ### Skip specific steps
40
+ ### Skip specific steps (init only)
21
41
 
22
42
  ```bash
23
43
  npx tcsetup --skip-bmad
24
44
  npx tcsetup --skip-speckit
25
45
  npx tcsetup --skip-agreements
46
+ npx tcsetup --skip-adr
26
47
  npx tcsetup --skip-mermaid
48
+ npx tcsetup --skip-lifecycle
27
49
  ```
28
50
 
29
51
  Multiple flags can be combined:
package/bin/cli.js CHANGED
@@ -1,24 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { execSync } from "node:child_process";
4
- import { argv } from "node:process";
5
- import { readFileSync, mkdirSync, copyFileSync, existsSync } from "node:fs";
3
+ import { argv, exit } from "node:process";
4
+ import { readFileSync } from "node:fs";
6
5
  import { fileURLToPath } from "node:url";
7
6
  import { dirname, join } from "node:path";
7
+ import { install } from "../src/installer.js";
8
+ import { update } from "../src/updater.js";
8
9
 
9
10
  const __dirname = dirname(fileURLToPath(import.meta.url));
10
11
  const { version } = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf8"));
11
12
 
12
- const flags = argv.slice(2);
13
+ const command = argv[2];
14
+ const flags = argv.slice(3);
13
15
 
14
16
  const HELP = `
15
- tcsetup — Bootstrap a project with the full TC toolchain.
17
+ tcsetup v${version} — Bootstrap and update the TC toolchain.
16
18
 
17
19
  Usage:
18
- npx tcsetup Run all setup steps
20
+ npx tcsetup Run all setup steps (same as init)
21
+ npx tcsetup init Install the full TC toolchain
22
+ npx tcsetup update Update all installed TC tools to latest
19
23
  npx tcsetup help Show this help message
20
24
 
21
- Options:
25
+ Options (init):
22
26
  --skip-bmad Skip BMAD Method install
23
27
  --skip-speckit Skip Spec Kit init
24
28
  --skip-agreements Skip Agreement System init
@@ -27,84 +31,28 @@ Options:
27
31
  --skip-lifecycle Skip Feature Lifecycle Tracker init
28
32
  `;
29
33
 
30
- if (flags.includes("help") || flags.includes("--help") || flags.includes("-h")) {
31
- console.log(HELP);
32
- process.exit(0);
33
- }
34
-
35
- const steps = [
36
- {
37
- name: "BMAD Method",
38
- flag: "--skip-bmad",
39
- cmd: "npx bmad-method install",
40
- },
41
- {
42
- name: "Spec Kit",
43
- flag: "--skip-speckit",
44
- cmd: "specify init --here --ai claude",
45
- },
46
- {
47
- name: "Agreement System",
48
- flag: "--skip-agreements",
49
- cmd: "npx agreement-system init --yes",
50
- },
51
- {
52
- name: "ADR System",
53
- flag: "--skip-adr",
54
- cmd: "npx adr-system init --yes",
55
- },
56
- {
57
- name: "Mermaid Workbench",
58
- flag: "--skip-mermaid",
59
- cmd: "npx mermaid-workbench init",
60
- },
61
- {
62
- name: "Feature Lifecycle Tracker",
63
- flag: "--skip-lifecycle",
64
- cmd: "npx feature-lifecycle init --yes",
65
- },
66
- ];
67
-
68
- console.log(`\n tcsetup v${version}\n`);
69
-
70
- let current = 0;
71
- const total = steps.filter((s) => !flags.includes(s.flag)).length;
72
-
73
- for (const step of steps) {
74
- if (flags.includes(step.flag)) {
75
- console.log(` [skip] ${step.name} (${step.flag})\n`);
76
- continue;
77
- }
78
-
79
- current++;
80
- console.log(` [${current}/${total}] ${step.name}`);
81
- console.log(` > ${step.cmd}\n`);
82
-
83
- try {
84
- execSync(step.cmd, { stdio: "inherit" });
85
- console.log();
86
- } catch (err) {
87
- console.error(`\n ⚠ ${step.name} failed (exit code ${err.status}).`);
88
- console.error(` Continuing with remaining steps...\n`);
89
- }
90
- }
91
-
92
- // ── Install Claude Code commands ──────────────────────
93
- const commandsSource = join(__dirname, "..", "commands");
94
- const commandsDest = join(process.cwd(), ".claude", "commands");
95
-
96
- if (existsSync(commandsSource)) {
97
- const commandFiles = ["tcsetup.onboard.md", "feature.workflow.md"];
98
- mkdirSync(commandsDest, { recursive: true });
99
- for (const file of commandFiles) {
100
- const src = join(commandsSource, file);
101
- const dest = join(commandsDest, file);
102
- if (existsSync(src)) {
103
- copyFileSync(src, dest);
104
- console.log(` [cmd] Installed .claude/commands/${file}`);
34
+ switch (command) {
35
+ case "init":
36
+ install(flags);
37
+ break;
38
+ case "update":
39
+ update(flags);
40
+ break;
41
+ case "help":
42
+ case "--help":
43
+ case "-h":
44
+ console.log(HELP);
45
+ break;
46
+ case undefined:
47
+ install([]);
48
+ break;
49
+ default:
50
+ // Flags without subcommand (e.g., npx tcsetup --skip-bmad) → treat as init
51
+ if (command.startsWith("-")) {
52
+ install(argv.slice(2));
53
+ } else {
54
+ console.error(` Unknown command: ${command}\n`);
55
+ console.log(HELP);
56
+ exit(1);
105
57
  }
106
- }
107
- console.log();
108
58
  }
109
-
110
- console.log(" Done! Project setup complete.\n");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tcsetup",
3
- "version": "1.2.0",
3
+ "version": "1.3.1",
4
4
  "type": "module",
5
5
  "description": "Bootstrap a new project with BMAD, Spec Kit, Agreement System, and Mermaid Workbench in one command.",
6
6
  "bin": {
@@ -22,6 +22,7 @@
22
22
  },
23
23
  "files": [
24
24
  "bin/",
25
+ "src/",
25
26
  "commands/"
26
27
  ],
27
28
  "engines": {
@@ -0,0 +1,86 @@
1
+ import { execSync } from "node:child_process";
2
+ import { readFileSync, mkdirSync, copyFileSync, existsSync } from "node:fs";
3
+ import { fileURLToPath } from "node:url";
4
+ import { dirname, join } from "node:path";
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ const { version } = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf8"));
8
+
9
+ const steps = [
10
+ {
11
+ name: "BMAD Method",
12
+ flag: "--skip-bmad",
13
+ cmd: "npx bmad-method install",
14
+ },
15
+ {
16
+ name: "Spec Kit",
17
+ flag: "--skip-speckit",
18
+ cmd: "specify init --here --ai claude",
19
+ },
20
+ {
21
+ name: "Agreement System",
22
+ flag: "--skip-agreements",
23
+ cmd: "npx agreement-system init --yes",
24
+ },
25
+ {
26
+ name: "ADR System",
27
+ flag: "--skip-adr",
28
+ cmd: "npx adr-system init --yes",
29
+ },
30
+ {
31
+ name: "Mermaid Workbench",
32
+ flag: "--skip-mermaid",
33
+ cmd: "npx mermaid-workbench init",
34
+ },
35
+ {
36
+ name: "Feature Lifecycle Tracker",
37
+ flag: "--skip-lifecycle",
38
+ cmd: "npx feature-lifecycle init --yes",
39
+ },
40
+ ];
41
+
42
+ export function install(flags = []) {
43
+ console.log(`\n tcsetup v${version}\n`);
44
+
45
+ let current = 0;
46
+ const total = steps.filter((s) => !flags.includes(s.flag)).length;
47
+
48
+ for (const step of steps) {
49
+ if (flags.includes(step.flag)) {
50
+ console.log(` [skip] ${step.name} (${step.flag})\n`);
51
+ continue;
52
+ }
53
+
54
+ current++;
55
+ console.log(` [${current}/${total}] ${step.name}`);
56
+ console.log(` > ${step.cmd}\n`);
57
+
58
+ try {
59
+ execSync(step.cmd, { stdio: "inherit" });
60
+ console.log();
61
+ } catch (err) {
62
+ console.error(`\n ⚠ ${step.name} failed (exit code ${err.status}).`);
63
+ console.error(` Continuing with remaining steps...\n`);
64
+ }
65
+ }
66
+
67
+ // ── Install Claude Code commands ──────────────────────
68
+ const commandsSource = join(__dirname, "..", "commands");
69
+ const commandsDest = join(process.cwd(), ".claude", "commands");
70
+
71
+ if (existsSync(commandsSource)) {
72
+ const commandFiles = ["tcsetup.onboard.md", "feature.workflow.md"];
73
+ mkdirSync(commandsDest, { recursive: true });
74
+ for (const file of commandFiles) {
75
+ const src = join(commandsSource, file);
76
+ const dest = join(commandsDest, file);
77
+ if (existsSync(src)) {
78
+ copyFileSync(src, dest);
79
+ console.log(` [cmd] Installed .claude/commands/${file}`);
80
+ }
81
+ }
82
+ console.log();
83
+ }
84
+
85
+ console.log(" Done! Project setup complete.\n");
86
+ }
package/src/updater.js ADDED
@@ -0,0 +1,116 @@
1
+ import { execSync } from "node:child_process";
2
+ import { existsSync, mkdirSync, copyFileSync, readFileSync } from "node:fs";
3
+ import { fileURLToPath } from "node:url";
4
+ import { dirname, join } from "node:path";
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ const { version } = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf8"));
8
+
9
+ const TOOLS = [
10
+ {
11
+ name: "ADR System",
12
+ marker: ".adr",
13
+ pkg: "adr-system",
14
+ cmd: "npx adr-system update",
15
+ },
16
+ {
17
+ name: "Agreement System",
18
+ marker: ".agreements",
19
+ pkg: "agreement-system",
20
+ cmd: "npx agreement-system update",
21
+ },
22
+ {
23
+ name: "Feature Lifecycle",
24
+ marker: ".features",
25
+ pkg: "feature-lifecycle",
26
+ cmd: "npx feature-lifecycle update",
27
+ },
28
+ {
29
+ name: "Mermaid Workbench",
30
+ marker: ["_bmad/modules/mermaid-workbench", ".bmad/modules/mermaid-workbench"],
31
+ pkg: "mermaid-workbench",
32
+ cmd: "npx mermaid-workbench init",
33
+ },
34
+ ];
35
+
36
+ const COMMAND_FILES = ["tcsetup.onboard.md", "feature.workflow.md"];
37
+
38
+ function isInstalled(marker, projectRoot) {
39
+ if (Array.isArray(marker)) {
40
+ return marker.some((m) => existsSync(join(projectRoot, m)));
41
+ }
42
+ return existsSync(join(projectRoot, marker));
43
+ }
44
+
45
+ export function update(flags = []) {
46
+ const projectRoot = process.cwd();
47
+
48
+ console.log(`\n tcsetup update v${version}\n`);
49
+
50
+ // ── Detect installed tools ────────────────────────────
51
+ console.log(" Detecting installed tools...\n");
52
+
53
+ const detected = TOOLS.filter((tool) => isInstalled(tool.marker, projectRoot));
54
+
55
+ if (detected.length === 0) {
56
+ console.log(" No TC tools detected. Run `npx tcsetup` to onboard first.\n");
57
+ return;
58
+ }
59
+
60
+ for (const tool of detected) {
61
+ console.log(` ✓ ${tool.name}`);
62
+ }
63
+ console.log();
64
+
65
+ // ── Update npm packages ───────────────────────────────
66
+ const pkgs = detected.map((t) => `${t.pkg}@latest`).join(" ");
67
+ console.log(` [1/3] Updating npm packages...`);
68
+ console.log(` > npm install ${pkgs}\n`);
69
+
70
+ try {
71
+ execSync(`npm install ${pkgs}`, { stdio: "inherit" });
72
+ console.log();
73
+ } catch (err) {
74
+ console.error(`\n ⚠ npm install failed (exit code ${err.status}).`);
75
+ console.error(` Continuing with sub-tool updates...\n`);
76
+ }
77
+
78
+ // ── Call sub-tool updates ─────────────────────────────
79
+ console.log(` [2/3] Running sub-tool updates...\n`);
80
+
81
+ for (const tool of detected) {
82
+ console.log(` > ${tool.cmd}`);
83
+ try {
84
+ execSync(tool.cmd, { stdio: "inherit" });
85
+ console.log();
86
+ } catch (err) {
87
+ console.error(`\n ⚠ ${tool.name} update failed (exit code ${err.status}).`);
88
+ console.error(` Continuing with remaining tools...\n`);
89
+ }
90
+ }
91
+
92
+ // ── Refresh tcsetup commands ──────────────────────────
93
+ console.log(` [3/3] Refreshing tcsetup commands...\n`);
94
+
95
+ const commandsSource = join(__dirname, "..", "commands");
96
+ const commandsDest = join(projectRoot, ".claude", "commands");
97
+
98
+ mkdirSync(commandsDest, { recursive: true });
99
+
100
+ for (const file of COMMAND_FILES) {
101
+ const src = join(commandsSource, file);
102
+ const dest = join(commandsDest, file);
103
+ if (existsSync(src)) {
104
+ copyFileSync(src, dest);
105
+ console.log(` update .claude/commands/${file}`);
106
+ }
107
+ }
108
+ console.log();
109
+
110
+ // ── Summary ───────────────────────────────────────────
111
+ console.log(` Done! Updated ${detected.length} tool${detected.length === 1 ? "" : "s"}:`);
112
+ for (const tool of detected) {
113
+ console.log(` - ${tool.name}`);
114
+ }
115
+ console.log();
116
+ }