mvc-kit 2.1.0 → 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/README.md CHANGED
@@ -21,16 +21,12 @@ mvc-kit ships with built-in context for AI coding assistants — stays in sync w
21
21
 
22
22
  ```bash
23
23
  npx mvc-kit-setup # Set up all agents
24
+ npx mvc-kit-setup claude # Claude Code only
24
25
  npx mvc-kit-setup cursor # Cursor only
25
26
  npx mvc-kit-setup copilot # GitHub Copilot only
26
27
  ```
27
28
 
28
- **Claude Code** — load directly as a plugin (no file copying, auto-updates):
29
- ```bash
30
- claude --plugin-dir node_modules/mvc-kit/agent-config/claude-code
31
- ```
32
-
33
- Skills: `/mvc-kit:guide` (framework reference), `/mvc-kit:scaffold <type> <Name>` (code generation), `/mvc-kit:review <path>` (pattern review).
29
+ **Claude Code** — installs `.claude/rules/` and `.claude/commands/`. Auto-updates on subsequent `npm install`/`npm update`.
34
30
 
35
31
  **Cursor** — writes `.cursorrules`. **Copilot** — writes `.github/copilot-instructions.md`. Both use idempotent markers, safe to re-run.
36
32
 
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { existsSync } from 'node:fs';
4
+ import { resolve, join, dirname } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = dirname(__filename);
9
+
10
+ // INIT_CWD is set by npm/yarn/pnpm during lifecycle scripts — points to the project root
11
+ const projectRoot = process.env.INIT_CWD;
12
+
13
+ if (!projectRoot) {
14
+ process.exit(0);
15
+ }
16
+
17
+ // Detect self-install (developing mvc-kit itself) — skip
18
+ const ownPackageRoot = resolve(__dirname, '../..');
19
+ if (resolve(projectRoot) === ownPackageRoot) {
20
+ process.exit(0);
21
+ }
22
+
23
+ // If the developer previously opted in (files exist), auto-update them
24
+ const rulesFile = join(projectRoot, '.claude', 'rules', 'mvc-kit.md');
25
+
26
+ if (existsSync(rulesFile)) {
27
+ try {
28
+ const { installClaude } = await import('../lib/install-claude.mjs');
29
+ installClaude(projectRoot);
30
+ console.log('');
31
+ console.log(' mvc-kit — Claude Code rules updated');
32
+ console.log('');
33
+ } catch {
34
+ // Never break npm install
35
+ }
36
+ } else {
37
+ console.log('');
38
+ console.log(' mvc-kit — AI agent setup available');
39
+ console.log(' Run: npx mvc-kit-setup');
40
+ console.log('');
41
+ }
@@ -4,6 +4,7 @@ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
4
4
  import { join, dirname, resolve } from 'node:path';
5
5
  import { fileURLToPath } from 'node:url';
6
6
  import { createInterface } from 'node:readline';
7
+ import { installClaude } from '../lib/install-claude.mjs';
7
8
 
8
9
  const __filename = fileURLToPath(import.meta.url);
9
10
  const __dirname = dirname(__filename);
@@ -22,7 +23,7 @@ function printUsage() {
22
23
  Usage: npx mvc-kit-setup [targets...] [options]
23
24
 
24
25
  Targets:
25
- claude Set up Claude Code plugin (prints usage instructions)
26
+ claude Install Claude Code rules and commands into .claude/
26
27
  cursor Copy mvc-kit rules to .cursorrules
27
28
  copilot Copy mvc-kit instructions to .github/copilot-instructions.md
28
29
  all Set up all targets (default)
@@ -77,18 +78,17 @@ async function confirm(message) {
77
78
  // ─── Target Handlers ──────────────────────────────────────
78
79
 
79
80
  function setupClaude() {
80
- const pluginDir = join(AGENT_CONFIG_DIR, 'claude-code');
81
+ const { files } = installClaude(PROJECT_DIR);
81
82
 
82
83
  console.log('\n Claude Code');
83
84
  console.log(' ───────────');
84
- console.log(' The mvc-kit plugin is loaded directly from node_modules.');
85
- console.log(' No file copying needed — it updates automatically with npm update.\n');
86
- console.log(' To use, start Claude Code with the --plugin-dir flag:\n');
87
- console.log(` claude --plugin-dir ${pluginDir}\n`);
88
- console.log(' Skills available:');
89
- console.log(' /mvc-kit:guide — Framework reference (auto-loaded)');
90
- console.log(' /mvc-kit:scaffold — Scaffold classes and components');
91
- console.log(' /mvc-kit:review — Review code for pattern adherence\n');
85
+ console.log(' Installed (updates automatically on npm install/update):\n');
86
+ for (const f of files) {
87
+ console.log(` ${f}`);
88
+ }
89
+ console.log('');
90
+ console.log(' Commands: /project:mvc-kit-scaffold, /project:mvc-kit-review');
91
+ console.log(' Reference: Auto-loaded via .claude/rules/mvc-kit.md\n');
92
92
  }
93
93
 
94
94
  async function setupCursor(force) {
@@ -207,8 +207,7 @@ async function main() {
207
207
  await setupCopilot(force);
208
208
  }
209
209
 
210
- console.log('Done! To keep rules in sync after npm update, re-run:');
211
- console.log(' npx mvc-kit-setup\n');
210
+ console.log('Done!\n');
212
211
  }
213
212
 
214
213
  main().catch((err) => {
@@ -0,0 +1,87 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
2
+ import { join, dirname } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+ const SKILLS_DIR = join(__dirname, '..', 'claude-code', 'skills');
8
+
9
+ const AUTO_HEADER = '<!-- Auto-generated by mvc-kit. Updated on npm install/update. Do not edit. -->\n\n';
10
+
11
+ function stripFrontmatter(content) {
12
+ const match = content.match(/^---\n[\s\S]*?\n---\n([\s\S]*)$/);
13
+ return match ? match[1].trim() : content.trim();
14
+ }
15
+
16
+ function ensureDir(dir) {
17
+ if (!existsSync(dir)) {
18
+ mkdirSync(dir, { recursive: true });
19
+ }
20
+ }
21
+
22
+ /**
23
+ * Install Claude Code integration files into a project's .claude/ directory.
24
+ *
25
+ * Creates:
26
+ * .claude/rules/mvc-kit.md — Framework reference (always loaded in context)
27
+ * .claude/commands/mvc-kit-scaffold.md — Scaffold command (/project:mvc-kit-scaffold)
28
+ * .claude/commands/mvc-kit-review.md — Review command (/project:mvc-kit-review)
29
+ *
30
+ * @param {string} projectRoot — Absolute path to the consuming project's root
31
+ * @returns {{ files: string[] }} — List of created/updated file paths (relative to projectRoot)
32
+ */
33
+ export function installClaude(projectRoot) {
34
+ const claudeDir = join(projectRoot, '.claude');
35
+ const rulesDir = join(claudeDir, 'rules');
36
+ const commandsDir = join(claudeDir, 'commands');
37
+
38
+ ensureDir(rulesDir);
39
+ ensureDir(commandsDir);
40
+
41
+ const files = [];
42
+
43
+ // 1. Rules file — framework reference (always loaded in context)
44
+ const guideSkill = readFileSync(join(SKILLS_DIR, 'guide', 'SKILL.md'), 'utf-8');
45
+ const guideBody = stripFrontmatter(guideSkill)
46
+ // Remove the "Supporting Files" section — replaced by "Detailed Reference" below
47
+ .replace(/\n## Supporting Files[\s\S]*$/, '');
48
+
49
+ const rulesContent = AUTO_HEADER + guideBody + `
50
+
51
+ ## Detailed Reference
52
+
53
+ For complete API details, patterns, and anti-patterns, read the files in:
54
+ \`node_modules/mvc-kit/agent-config/claude-code/skills/guide/\`
55
+
56
+ - \`api-reference.md\` — Full API reference for all classes and hooks
57
+ - \`patterns.md\` — Prescribed patterns with code examples
58
+ - \`anti-patterns.md\` — Anti-patterns to reject with fixes
59
+ `;
60
+
61
+ writeFileSync(join(rulesDir, 'mvc-kit.md'), rulesContent, 'utf-8');
62
+ files.push('.claude/rules/mvc-kit.md');
63
+
64
+ // 2. Scaffold command
65
+ const scaffoldSkill = readFileSync(join(SKILLS_DIR, 'scaffold', 'SKILL.md'), 'utf-8');
66
+ const scaffoldBody = stripFrontmatter(scaffoldSkill)
67
+ .replace(
68
+ 'Read the template file from `templates/<type>.md` in this skill directory.',
69
+ 'Read the template file from `node_modules/mvc-kit/agent-config/claude-code/skills/scaffold/templates/<type>.md`.'
70
+ );
71
+
72
+ writeFileSync(join(commandsDir, 'mvc-kit-scaffold.md'), AUTO_HEADER + scaffoldBody, 'utf-8');
73
+ files.push('.claude/commands/mvc-kit-scaffold.md');
74
+
75
+ // 3. Review command
76
+ const reviewSkill = readFileSync(join(SKILLS_DIR, 'review', 'SKILL.md'), 'utf-8');
77
+ const reviewBody = stripFrontmatter(reviewSkill)
78
+ .replaceAll(
79
+ '`checklist.md`',
80
+ '`node_modules/mvc-kit/agent-config/claude-code/skills/review/checklist.md`'
81
+ );
82
+
83
+ writeFileSync(join(commandsDir, 'mvc-kit-review.md'), AUTO_HEADER + reviewBody, 'utf-8');
84
+ files.push('.claude/commands/mvc-kit-review.md');
85
+
86
+ return { files };
87
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mvc-kit",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "Zero-magic, class-based reactive ViewModel library",
5
5
  "type": "module",
6
6
  "main": "./dist/mvc-kit.cjs",
@@ -40,6 +40,7 @@
40
40
  "dev": "vite",
41
41
  "dev:fullapp": "vite --config examples/react/FullApp/vite.config.ts",
42
42
  "build": "rm -rf dist && tsc -p tsconfig.build.json && vite build",
43
+ "postinstall": "node agent-config/bin/postinstall.mjs",
43
44
  "test": "vitest run",
44
45
  "test:watch": "vitest"
45
46
  },