@trieungoctam/vibekit 1.0.4 → 1.0.5

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/bin/vibekit.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { program } from 'commander';
3
3
  import { initCommand } from '../src/commands/init.js';
4
+ import { updateCommand } from '../src/commands/update.js';
4
5
 
5
6
  program
6
7
  .name('vibekit')
@@ -15,4 +16,9 @@ program
15
16
  .option('--force', 'Overwrite existing files')
16
17
  .action(initCommand);
17
18
 
19
+ program
20
+ .command('update')
21
+ .description('Update VibeKit to latest version')
22
+ .action(updateCommand);
23
+
18
24
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trieungoctam/vibekit",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Unified IDE configuration - setup rules/skills directly in your repo",
5
5
  "type": "module",
6
6
  "bin": {
@@ -13,9 +13,9 @@
13
13
  * Requires: graphviz (dot) installed on system
14
14
  */
15
15
 
16
- const fs = require('fs');
17
- const path = require('path');
18
- const { execSync } = require('child_process');
16
+ const fs = require("fs");
17
+ const path = require("path");
18
+ const { execSync } = require("child_process");
19
19
 
20
20
  function extractDotBlocks(markdown) {
21
21
  const blocks = [];
@@ -38,12 +38,12 @@ function extractDotBlocks(markdown) {
38
38
  function extractGraphBody(dotContent) {
39
39
  // Extract just the body (nodes and edges) from a digraph
40
40
  const match = dotContent.match(/digraph\s+\w+\s*\{([\s\S]*)\}/);
41
- if (!match) return '';
41
+ if (!match) return "";
42
42
 
43
43
  let body = match[1];
44
44
 
45
45
  // Remove rankdir (we'll set it once at the top level)
46
- body = body.replace(/^\s*rankdir\s*=\s*\w+\s*;?\s*$/gm, '');
46
+ body = body.replace(/^\s*rankdir\s*=\s*\w+\s*;?\s*$/gm, "");
47
47
 
48
48
  return body.trim();
49
49
  }
@@ -54,7 +54,10 @@ function combineGraphs(blocks, skillName) {
54
54
  // Wrap each subgraph in a cluster for visual grouping
55
55
  return ` subgraph cluster_${i} {
56
56
  label="${block.name}";
57
- ${body.split('\n').map(line => ' ' + line).join('\n')}
57
+ ${body
58
+ .split("\n")
59
+ .map((line) => " " + line)
60
+ .join("\n")}
58
61
  }`;
59
62
  });
60
63
 
@@ -63,19 +66,19 @@ function combineGraphs(blocks, skillName) {
63
66
  compound=true;
64
67
  newrank=true;
65
68
 
66
- ${bodies.join('\n\n')}
69
+ ${bodies.join("\n\n")}
67
70
  }`;
68
71
  }
69
72
 
70
73
  function renderToSvg(dotContent) {
71
74
  try {
72
- return execSync('dot -Tsvg', {
75
+ return execSync("dot -Tsvg", {
73
76
  input: dotContent,
74
- encoding: 'utf-8',
75
- maxBuffer: 10 * 1024 * 1024
77
+ encoding: "utf-8",
78
+ maxBuffer: 10 * 1024 * 1024,
76
79
  });
77
80
  } catch (err) {
78
- console.error('Error running dot:', err.message);
81
+ console.error("Error running dot:", err.message);
79
82
  if (err.stderr) console.error(err.stderr.toString());
80
83
  return null;
81
84
  }
@@ -83,24 +86,24 @@ function renderToSvg(dotContent) {
83
86
 
84
87
  function main() {
85
88
  const args = process.argv.slice(2);
86
- const combine = args.includes('--combine');
87
- const skillDirArg = args.find(a => !a.startsWith('--'));
89
+ const combine = args.includes("--combine");
90
+ const skillDirArg = args.find((a) => !a.startsWith("--"));
88
91
 
89
92
  if (!skillDirArg) {
90
- console.error('Usage: render-graphs.js <skill-directory> [--combine]');
91
- console.error('');
92
- console.error('Options:');
93
- console.error(' --combine Combine all diagrams into one SVG');
94
- console.error('');
95
- console.error('Example:');
96
- console.error(' ./render-graphs.js ../subagent-driven-development');
97
- console.error(' ./render-graphs.js ../subagent-driven-development --combine');
93
+ console.error("Usage: render-graphs.js <skill-directory> [--combine]");
94
+ console.error("");
95
+ console.error("Options:");
96
+ console.error(" --combine Combine all diagrams into one SVG");
97
+ console.error("");
98
+ console.error("Example:");
99
+ console.error(" ./render-graphs.js ../subagent-driven-development");
100
+ console.error(" ./render-graphs.js ../subagent-driven-development --combine");
98
101
  process.exit(1);
99
102
  }
100
103
 
101
104
  const skillDir = path.resolve(skillDirArg);
102
- const skillFile = path.join(skillDir, 'SKILL.md');
103
- const skillName = path.basename(skillDir).replace(/-/g, '_');
105
+ const skillFile = path.join(skillDir, "SKILL.md");
106
+ const skillName = path.basename(skillDir).replace(/-/g, "_");
104
107
 
105
108
  if (!fs.existsSync(skillFile)) {
106
109
  console.error(`Error: ${skillFile} not found`);
@@ -109,25 +112,27 @@ function main() {
109
112
 
110
113
  // Check if dot is available
111
114
  try {
112
- execSync('which dot', { encoding: 'utf-8' });
115
+ execSync("which dot", { encoding: "utf-8" });
113
116
  } catch {
114
- console.error('Error: graphviz (dot) not found. Install with:');
115
- console.error(' brew install graphviz # macOS');
116
- console.error(' apt install graphviz # Linux');
117
+ console.error("Error: graphviz (dot) not found. Install with:");
118
+ console.error(" brew install graphviz # macOS");
119
+ console.error(" apt install graphviz # Linux");
117
120
  process.exit(1);
118
121
  }
119
122
 
120
- const markdown = fs.readFileSync(skillFile, 'utf-8');
123
+ const markdown = fs.readFileSync(skillFile, "utf-8");
121
124
  const blocks = extractDotBlocks(markdown);
122
125
 
123
126
  if (blocks.length === 0) {
124
- console.log('No ```dot blocks found in', skillFile);
127
+ console.log("No ```dot blocks found in", skillFile);
125
128
  process.exit(0);
126
129
  }
127
130
 
128
- console.log(`Found ${blocks.length} diagram(s) in ${path.basename(skillDir)}/SKILL.md`);
131
+ console.log(
132
+ `Found ${blocks.length} diagram(s) in ${path.basename(skillDir)}/SKILL.md`,
133
+ );
129
134
 
130
- const outputDir = path.join(skillDir, 'diagrams');
135
+ const outputDir = path.join(skillDir, "diagrams");
131
136
  if (!fs.existsSync(outputDir)) {
132
137
  fs.mkdirSync(outputDir);
133
138
  }
@@ -146,7 +151,7 @@ function main() {
146
151
  fs.writeFileSync(dotPath, combined);
147
152
  console.log(` Source: ${skillName}_combined.dot`);
148
153
  } else {
149
- console.error(' Failed to render combined diagram');
154
+ console.error(" Failed to render combined diagram");
150
155
  }
151
156
  } else {
152
157
  // Render each separately
@@ -0,0 +1,124 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import chalk from 'chalk';
5
+ import { execSync } from 'child_process';
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+ const VIBEKIT_ROOT = path.resolve(__dirname, '../../');
10
+
11
+ export async function updateCommand(options) {
12
+ const targetDir = process.cwd();
13
+
14
+ console.log(chalk.blue('\nšŸ”„ VibeKit Update\n'));
15
+
16
+ // Check if .vibekit exists
17
+ const vibekitDir = path.join(targetDir, '.vibekit');
18
+ if (!fs.existsSync(vibekitDir)) {
19
+ console.log(chalk.red('VibeKit not initialized. Run `vibekit init` first.'));
20
+ return;
21
+ }
22
+
23
+ console.log(chalk.gray('Checking for updates...'));
24
+
25
+ try {
26
+ // Get current version
27
+ const currentPkg = fs.readJsonSync(path.join(VIBEKIT_ROOT, 'package.json'));
28
+ console.log(chalk.gray(`Current version: ${currentPkg.version}`));
29
+
30
+ // Check latest version on npm
31
+ let latestVersion;
32
+ try {
33
+ latestVersion = execSync('npm view @trieungoctam/vibekit version', { encoding: 'utf-8' }).trim();
34
+ console.log(chalk.gray(`Latest version: ${latestVersion}`));
35
+ } catch (e) {
36
+ console.log(chalk.yellow('Could not check npm registry, updating from local...'));
37
+ }
38
+
39
+ // Update folders
40
+ console.log(chalk.blue('\nšŸ“ Updating files...'));
41
+
42
+ const folders = ['skills', 'agents', 'hooks', 'rules'];
43
+ for (const folder of folders) {
44
+ const src = path.join(VIBEKIT_ROOT, folder);
45
+ const dst = path.join(vibekitDir, folder);
46
+ if (fs.existsSync(src)) {
47
+ fs.removeSync(dst);
48
+ fs.copySync(src, dst);
49
+ console.log(chalk.gray(` āœ“ ${folder}/`));
50
+ }
51
+ }
52
+
53
+ // Update .claude/skills if exists
54
+ const claudeDir = path.join(targetDir, '.claude');
55
+ if (fs.existsSync(claudeDir)) {
56
+ const claudeSkillsDir = path.join(claudeDir, 'skills');
57
+ const claudeAgentsDir = path.join(claudeDir, 'agents');
58
+
59
+ fs.removeSync(claudeSkillsDir);
60
+ fs.copySync(path.join(VIBEKIT_ROOT, 'skills'), claudeSkillsDir);
61
+ console.log(chalk.gray(' āœ“ .claude/skills/'));
62
+
63
+ fs.removeSync(claudeAgentsDir);
64
+ fs.copySync(path.join(VIBEKIT_ROOT, 'agents'), claudeAgentsDir);
65
+ console.log(chalk.gray(' āœ“ .claude/agents/'));
66
+ }
67
+
68
+ // Update .cursor if exists
69
+ const cursorDir = path.join(targetDir, '.cursor');
70
+ if (fs.existsSync(cursorDir)) {
71
+ const cursorRulesDir = path.join(cursorDir, 'rules');
72
+ const cursorSkillsDir = path.join(cursorDir, 'skills');
73
+
74
+ fs.removeSync(cursorRulesDir);
75
+ fs.copySync(path.join(VIBEKIT_ROOT, 'rules'), cursorRulesDir);
76
+ console.log(chalk.gray(' āœ“ .cursor/rules/'));
77
+
78
+ fs.removeSync(cursorSkillsDir);
79
+ fs.copySync(path.join(VIBEKIT_ROOT, 'skills'), cursorSkillsDir);
80
+ console.log(chalk.gray(' āœ“ .cursor/skills/'));
81
+ }
82
+
83
+ // Update .codex if exists
84
+ const codexDir = path.join(targetDir, '.codex');
85
+ if (fs.existsSync(codexDir)) {
86
+ const codexAgentsDir = path.join(codexDir, 'agents');
87
+ const codexSkillsDir = path.join(codexDir, 'skills');
88
+
89
+ fs.removeSync(codexAgentsDir);
90
+ fs.copySync(path.join(VIBEKIT_ROOT, 'agents'), codexAgentsDir);
91
+ console.log(chalk.gray(' āœ“ .codex/agents/'));
92
+
93
+ fs.removeSync(codexSkillsDir);
94
+ fs.copySync(path.join(VIBEKIT_ROOT, 'skills'), codexSkillsDir);
95
+ console.log(chalk.gray(' āœ“ .codex/skills/'));
96
+ }
97
+
98
+ // Update .opencode if exists
99
+ const opencodeDir = path.join(targetDir, '.opencode');
100
+ if (fs.existsSync(opencodeDir)) {
101
+ const opencodeRulesDir = path.join(opencodeDir, 'rules');
102
+ const opencodeSkillsDir = path.join(opencodeDir, 'skills');
103
+
104
+ fs.removeSync(opencodeRulesDir);
105
+ fs.copySync(path.join(VIBEKIT_ROOT, 'rules'), opencodeRulesDir);
106
+ console.log(chalk.gray(' āœ“ .opencode/rules/'));
107
+
108
+ fs.removeSync(opencodeSkillsDir);
109
+ fs.copySync(path.join(VIBEKIT_ROOT, 'skills'), opencodeSkillsDir);
110
+ console.log(chalk.gray(' āœ“ .opencode/skills/'));
111
+ }
112
+
113
+ console.log(chalk.green('\nāœ… VibeKit updated!\n'));
114
+
115
+ if (latestVersion && latestVersion !== currentPkg.version) {
116
+ console.log(chalk.yellow(`New version available: ${latestVersion}`));
117
+ console.log(chalk.gray('Run: npm install -g @trieungoctam/vibekit@latest'));
118
+ }
119
+
120
+ } catch (error) {
121
+ console.log(chalk.red(`Update failed: ${error.message}`));
122
+ process.exit(1);
123
+ }
124
+ }