gm-gc 2.0.74 → 2.0.75

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm",
3
- "version": "2.0.74",
3
+ "version": "2.0.75",
4
4
  "description": "State machine agent with hooks, skills, and automated git enforcement",
5
5
  "author": "AnEntrypoint",
6
6
  "homepage": "https://github.com/AnEntrypoint/gm",
@@ -31,7 +31,7 @@ const runCodeSearch = (query, cwd) => {
31
31
  const escaped = query.replace(/"/g, '\\"').substring(0, 200);
32
32
  let out;
33
33
  try {
34
- out = execSync(`bun x codebasesearch@latest "${escaped}"`, {
34
+ out = execSync(`bun x codebasesearch "${escaped}"`, {
35
35
  encoding: 'utf-8',
36
36
  stdio: ['pipe', 'pipe', 'pipe'],
37
37
  cwd,
@@ -40,7 +40,7 @@ const runCodeSearch = (query, cwd) => {
40
40
  });
41
41
  } catch (bunErr) {
42
42
  if (bunErr.killed) return '';
43
- out = execSync(`npx -y codebasesearch@latest "${escaped}"`, {
43
+ out = execSync(`npx -y codebasesearch "${escaped}"`, {
44
44
  encoding: 'utf-8',
45
45
  stdio: ['pipe', 'pipe', 'pipe'],
46
46
  cwd,
@@ -71,7 +71,7 @@ When exploring unfamiliar code, finding similar patterns, understanding integrat
71
71
  try {
72
72
  let thornOutput;
73
73
  try {
74
- thornOutput = execSync(`bun x mcp-thorns@latest`, {
74
+ thornOutput = execSync(`bun x mcp-thorns`, {
75
75
  encoding: 'utf-8',
76
76
  stdio: ['pipe', 'pipe', 'pipe'],
77
77
  cwd: projectDir,
@@ -83,7 +83,7 @@ When exploring unfamiliar code, finding similar patterns, understanding integrat
83
83
  thornOutput = '=== mcp-thorns ===\nSkipped (3min timeout)';
84
84
  } else {
85
85
  try {
86
- thornOutput = execSync(`npx -y mcp-thorns@latest`, {
86
+ thornOutput = execSync(`npx -y mcp-thorns`, {
87
87
  encoding: 'utf-8',
88
88
  stdio: ['pipe', 'pipe', 'pipe'],
89
89
  cwd: projectDir,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-gc",
3
- "version": "2.0.74",
3
+ "version": "2.0.75",
4
4
  "description": "State machine agent with hooks, skills, and automated git enforcement",
5
5
  "author": "AnEntrypoint",
6
6
  "license": "MIT",
@@ -38,5 +38,12 @@
38
38
  ".gitignore",
39
39
  ".editorconfig",
40
40
  "CONTRIBUTING.md"
41
- ]
41
+ ],
42
+ "dependencies": {
43
+ "mcp-thorns": "latest",
44
+ "codebasesearch": "latest"
45
+ },
46
+ "scripts": {
47
+ "postinstall": "node scripts/postinstall.js"
48
+ }
42
49
  }
@@ -2,38 +2,19 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
-
6
- /**
7
- * Postinstall script for gm-cc
8
- * Implements Mode 1: Standalone .claude/ directory installation
9
- *
10
- * When installed via npm in a project:
11
- * - Copies agents/, hooks/, .mcp.json to project's .claude/
12
- * - Updates .gitignore with .gm-stop-verified
13
- * - Runs silently, never breaks npm install
14
- * - Safe to run multiple times (idempotent)
15
- */
5
+ const { execSync } = require('child_process');
16
6
 
17
7
  function isInsideNodeModules() {
18
- // Check if __dirname contains /node_modules/ in its path
19
- // Example: /project/node_modules/gm-cc/scripts
20
8
  return __dirname.includes(path.sep + 'node_modules' + path.sep);
21
9
  }
22
10
 
23
11
  function getProjectRoot() {
24
- // From /project/node_modules/gm-cc/scripts
25
- // Navigate to /project
26
- if (!isInsideNodeModules()) {
27
- return null;
28
- }
29
-
30
- // Find the node_modules parent (project root)
12
+ if (!isInsideNodeModules()) return null;
31
13
  let current = __dirname;
32
- while (current !== path.dirname(current)) { // While not at root
14
+ while (current !== path.dirname(current)) {
33
15
  current = path.dirname(current);
34
- const parent = path.dirname(current);
35
16
  if (path.basename(current) === 'node_modules') {
36
- return parent;
17
+ return path.dirname(current);
37
18
  }
38
19
  }
39
20
  return null;
@@ -43,39 +24,26 @@ function safeCopyFile(src, dst) {
43
24
  try {
44
25
  const content = fs.readFileSync(src, 'utf-8');
45
26
  const dstDir = path.dirname(dst);
46
- if (!fs.existsSync(dstDir)) {
47
- fs.mkdirSync(dstDir, { recursive: true });
48
- }
27
+ if (!fs.existsSync(dstDir)) fs.mkdirSync(dstDir, { recursive: true });
49
28
  fs.writeFileSync(dst, content, 'utf-8');
50
29
  return true;
51
30
  } catch (err) {
52
- // Silently skip errors
53
31
  return false;
54
32
  }
55
33
  }
56
34
 
57
35
  function safeCopyDirectory(src, dst) {
58
36
  try {
59
- if (!fs.existsSync(src)) {
60
- return false; // Source doesn't exist, skip
61
- }
62
-
37
+ if (!fs.existsSync(src)) return false;
63
38
  fs.mkdirSync(dst, { recursive: true });
64
- const entries = fs.readdirSync(src, { withFileTypes: true });
65
-
66
- entries.forEach(entry => {
39
+ fs.readdirSync(src, { withFileTypes: true }).forEach(entry => {
67
40
  const srcPath = path.join(src, entry.name);
68
41
  const dstPath = path.join(dst, entry.name);
69
-
70
- if (entry.isDirectory()) {
71
- safeCopyDirectory(srcPath, dstPath);
72
- } else if (entry.isFile()) {
73
- safeCopyFile(srcPath, dstPath);
74
- }
42
+ if (entry.isDirectory()) safeCopyDirectory(srcPath, dstPath);
43
+ else if (entry.isFile()) safeCopyFile(srcPath, dstPath);
75
44
  });
76
45
  return true;
77
46
  } catch (err) {
78
- // Silently skip errors
79
47
  return false;
80
48
  }
81
49
  }
@@ -84,45 +52,22 @@ function updateGitignore(projectRoot) {
84
52
  try {
85
53
  const gitignorePath = path.join(projectRoot, '.gitignore');
86
54
  const entry = '.gm-stop-verified';
87
-
88
- // Read existing content
89
- let content = '';
90
- if (fs.existsSync(gitignorePath)) {
91
- content = fs.readFileSync(gitignorePath, 'utf-8');
92
- }
93
-
94
- // Check if entry already exists
95
- if (content.includes(entry)) {
96
- return true; // Already there
97
- }
98
-
99
- // Append entry
100
- if (content && !content.endsWith('\n')) {
101
- content += '\n';
102
- }
103
- content += entry + '\n';
104
-
105
- fs.writeFileSync(gitignorePath, content, 'utf-8');
55
+ let content = fs.existsSync(gitignorePath) ? fs.readFileSync(gitignorePath, 'utf-8') : '';
56
+ if (content.includes(entry)) return true;
57
+ if (content && !content.endsWith('\n')) content += '\n';
58
+ fs.writeFileSync(gitignorePath, content + entry + '\n', 'utf-8');
106
59
  return true;
107
60
  } catch (err) {
108
- // Silently skip errors
109
61
  return false;
110
62
  }
111
63
  }
112
64
 
113
65
  function install() {
114
- // Only run if inside node_modules
115
- if (!isInsideNodeModules()) {
116
- return; // Silent exit
117
- }
118
-
66
+ if (!isInsideNodeModules()) return;
119
67
  const projectRoot = getProjectRoot();
120
- if (!projectRoot) {
121
- return; // Silent exit
122
- }
123
-
68
+ if (!projectRoot) return;
124
69
  const claudeDir = path.join(projectRoot, '.claude');
125
- const sourceDir = __dirname.replace(/[\/]scripts$/, ''); // Remove /scripts
70
+ const sourceDir = __dirname.replace(/[/\\]scripts$/, '');
126
71
 
127
72
  // Copy files
128
73
  safeCopyDirectory(path.join(sourceDir, 'agents'), path.join(claudeDir, 'agents'));
@@ -131,8 +76,26 @@ function install() {
131
76
 
132
77
  // Update .gitignore
133
78
  updateGitignore(projectRoot);
134
-
79
+
80
+ // Warm bun x cache for packages used by hooks
81
+ warmBunCache();
82
+
135
83
  // Silent success
136
84
  }
137
85
 
86
+ function warmBunCache() {
87
+ const packages = ['mcp-thorns@latest', 'codebasesearch@latest'];
88
+ for (const pkg of packages) {
89
+ try {
90
+ execSync(`bun x ${pkg} --version`, {
91
+ encoding: 'utf-8',
92
+ stdio: 'pipe',
93
+ timeout: 60000
94
+ });
95
+ } catch (e) {
96
+ // Silent - cache warming is best-effort
97
+ }
98
+ }
99
+ }
100
+
138
101
  install();