gm-gc 2.0.152 → 2.0.153

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/agents/gm.md CHANGED
@@ -185,7 +185,7 @@ Server + client split:
185
185
  - `git` — version control only
186
186
  - `bun x gm-exec` — all other shell/code execution:
187
187
  - `bun x gm-exec bash [--cwd=<dir>] <cmd>` — run shell commands
188
- - `bun x gm-exec exec [--lang=<lang>] [--cwd=<dir>] [--file=<path>] <code>` — execute code (nodejs default; langs: nodejs, python, go, rust, c, cpp, java, deno, bash)
188
+ - `bun x gm-exec exec [--lang=<lang>] [--cwd=<dir>] [--file=<path>] <code>` — execute code (nodejs default; langs: nodejs, python, go, rust, c, cpp, java, deno, bash, cmd)
189
189
  - `bun x gm-exec status <task_id>` — poll status + drain output of background task
190
190
  - `bun x gm-exec sleep <task_id> [seconds]` — wait for task completion (default 30s timeout)
191
191
  - `bun x gm-exec close <task_id>` — delete background task
@@ -194,8 +194,8 @@ Server + client split:
194
194
  - Everything else is blocked
195
195
 
196
196
  **gm-exec EXEC SAFETY RULES** — prevent stray files and working directory pollution:
197
- - NEVER run `bun x gm-exec exec` without `--cwd` pointing to a safe scratch directory, not the project root. Use `--cwd=/tmp` or `--cwd=C:/Windows/Temp` for throwaway runs. Only use `--cwd=<project>` when the code explicitly needs to import from that project.
198
- - For any code longer than a single expression, use `--file=<path>` instead of inline `<code>`. Write the code to a temp file first via `bun x gm-exec exec "require('fs').writeFileSync('/tmp/run.mjs', \`...\`)"` then run `bun x gm-exec exec --file=/tmp/run.mjs`. This prevents shell quoting failures from leaking code fragments as filenames in the working directory.
197
+ - NEVER run `bun x gm-exec exec` without `--cwd` pointing to a safe scratch directory, not the project root. Use the system temp directory (`os.tmpdir()` — `/tmp` on Unix, `C:\Users\<user>\AppData\Local\Temp` on Windows) for throwaway runs. Only use `--cwd=<project>` when the code explicitly needs to import from that project.
198
+ - For any code longer than a single expression, use `--file=<path>` instead of inline `<code>`. Write the code to a temp file first via `bun x gm-exec exec "require('fs').writeFileSync(require('os').tmpdir()+'/run.mjs', \`...\`)"` then run `bun x gm-exec exec --file=<tmpdir>/run.mjs`. This prevents shell quoting failures from leaking code fragments as filenames in the working directory.
199
199
  - Single-line inline code is safe only when it contains no shell metacharacters (backticks, quotes, parens, brackets). If in doubt, use `--file`.
200
200
  - After any exec session, verify no stray files were created: `bun x gm-exec bash --cwd=<project> "git status --porcelain"` must be empty. If stray files appear, delete them before proceeding.
201
201
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm",
3
- "version": "2.0.152",
3
+ "version": "2.0.153",
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",
@@ -4,8 +4,8 @@ const fs = require('fs');
4
4
  const path = require('path');
5
5
  const { execSync } = require('child_process');
6
6
 
7
- const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || process.env.GEMINI_PROJECT_DIR || process.env.OC_PLUGIN_ROOT;
8
- const projectDir = process.env.CLAUDE_PROJECT_DIR || process.env.GEMINI_PROJECT_DIR || process.env.OC_PROJECT_DIR;
7
+ const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || process.env.GEMINI_PROJECT_DIR || process.env.OC_PLUGIN_ROOT || process.env.KILO_PLUGIN_ROOT;
8
+ const projectDir = process.env.CLAUDE_PROJECT_DIR || process.env.GEMINI_PROJECT_DIR || process.env.OC_PROJECT_DIR || process.env.KILO_PROJECT_DIR;
9
9
 
10
10
  const ensureGitignore = () => {
11
11
  if (!projectDir) return;
@@ -22,9 +22,7 @@ const ensureGitignore = () => {
22
22
  : content + '\n' + entry + '\n';
23
23
  fs.writeFileSync(gitignorePath, newContent);
24
24
  }
25
- } catch (e) {
26
- // Silently fail - not critical
27
- }
25
+ } catch (e) {}
28
26
  };
29
27
 
30
28
  ensureGitignore();
@@ -32,41 +30,24 @@ ensureGitignore();
32
30
  try {
33
31
  let outputs = [];
34
32
 
35
- // 1. Read ./start.md
36
33
  if (pluginRoot) {
37
- const startMdPath = path.join(pluginRoot, '/agents/gm.md');
34
+ const gmMdPath = path.join(pluginRoot, '/agents/gm.md');
38
35
  try {
39
- const startMdContent = fs.readFileSync(startMdPath, 'utf-8');
40
- outputs.push(startMdContent);
41
- } catch (e) {
42
- // File may not exist in this context
43
- }
36
+ const gmMdContent = fs.readFileSync(gmMdPath, 'utf-8');
37
+ outputs.push(gmMdContent);
38
+ } catch (e) {}
44
39
  }
45
40
 
46
- // 2. Add semantic code-search explanation
47
- const codeSearchContext = `## 🔍 Semantic Code Search Now Available
48
-
49
- Your prompts will trigger **semantic code search** - intelligent, intent-based exploration of your codebase.
41
+ const codeSearchContext = `## Semantic Code Search Available
50
42
 
51
- ### How It Works
52
- Describe what you need in plain language, and the search understands your intent:
53
- - "Find authentication validation" locates auth checks, guards, permission logic
54
- - "Where is database initialization?" finds connection setup, migrations, schemas
55
- - "Show error handling patterns" → discovers try/catch patterns, error boundaries
43
+ Describe what you need in plain language to search the codebase:
44
+ - "Find authentication validation" locates auth checks, guards, permission logic
45
+ - "Where is database initialization?" finds connection setup, migrations, schemas
46
+ - "Show error handling patterns" discovers try/catch patterns, error boundaries
56
47
 
57
- NOT syntax-based regex matching - truly semantic understanding across files.
58
-
59
- ### Example
60
- Instead of regex patterns, simply describe your intent:
61
- "Find where API authorization is checked"
62
-
63
- The search will find permission validations, role checks, authentication guards - however they're implemented.
64
-
65
- ### When to Use Code Search
66
- When exploring unfamiliar code, finding similar patterns, understanding integrations, or locating feature implementations across your codebase.`;
48
+ Use the code-search skill for all codebase exploration.`;
67
49
  outputs.push(codeSearchContext);
68
50
 
69
- // 3. Run mcp-thorns (bun x with npx fallback)
70
51
  if (projectDir && fs.existsSync(projectDir)) {
71
52
  try {
72
53
  let thornOutput;
@@ -97,55 +78,26 @@ When exploring unfamiliar code, finding similar patterns, understanding integrat
97
78
 
98
79
  const isGemini = process.env.GEMINI_PROJECT_DIR !== undefined;
99
80
  const isOpenCode = process.env.OC_PLUGIN_ROOT !== undefined;
81
+ const isKilo = process.env.KILO_PLUGIN_ROOT !== undefined;
100
82
 
101
83
  if (isGemini) {
102
- const result = {
103
- systemMessage: additionalContext
104
- };
105
- console.log(JSON.stringify(result, null, 2));
106
- } else if (isOpenCode) {
107
- const result = {
108
- hookSpecificOutput: {
109
- hookEventName: 'session.created',
110
- additionalContext
111
- }
112
- };
113
- console.log(JSON.stringify(result, null, 2));
84
+ console.log(JSON.stringify({ systemMessage: additionalContext }, null, 2));
85
+ } else if (isOpenCode || isKilo) {
86
+ console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'session.created', additionalContext } }, null, 2));
114
87
  } else {
115
- const result = {
116
- hookSpecificOutput: {
117
- hookEventName: 'SessionStart',
118
- additionalContext
119
- }
120
- };
121
- console.log(JSON.stringify(result, null, 2));
88
+ console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'SessionStart', additionalContext } }, null, 2));
122
89
  }
123
90
  } catch (error) {
124
91
  const isGemini = process.env.GEMINI_PROJECT_DIR !== undefined;
125
92
  const isOpenCode = process.env.OC_PLUGIN_ROOT !== undefined;
93
+ const isKilo = process.env.KILO_PLUGIN_ROOT !== undefined;
126
94
 
127
95
  if (isGemini) {
128
- console.log(JSON.stringify({
129
- systemMessage: `Error executing hook: ${error.message}`
130
- }, null, 2));
131
- } else if (isOpenCode) {
132
- console.log(JSON.stringify({
133
- hookSpecificOutput: {
134
- hookEventName: 'session.created',
135
- additionalContext: `Error executing hook: ${error.message}`
136
- }
137
- }, null, 2));
96
+ console.log(JSON.stringify({ systemMessage: `Error executing hook: ${error.message}` }, null, 2));
97
+ } else if (isOpenCode || isKilo) {
98
+ console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'session.created', additionalContext: `Error executing hook: ${error.message}` } }, null, 2));
138
99
  } else {
139
- console.log(JSON.stringify({
140
- hookSpecificOutput: {
141
- hookEventName: 'SessionStart',
142
- additionalContext: `Error executing hook: ${error.message}`
143
- }
144
- }, null, 2));
100
+ console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'SessionStart', additionalContext: `Error executing hook: ${error.message}` } }, null, 2));
145
101
  }
146
102
  process.exit(0);
147
103
  }
148
-
149
-
150
-
151
-
@@ -1,6 +1,5 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env bun
2
2
 
3
- // Skip hooks when running inside agentgui subprocess to prevent spurious injections
4
3
  if (process.env.AGENTGUI_SUBPROCESS === '1') {
5
4
  console.log(JSON.stringify({ decision: 'approve' }));
6
5
  process.exit(0);
@@ -9,13 +8,14 @@ if (process.env.AGENTGUI_SUBPROCESS === '1') {
9
8
  const { execSync } = require('child_process');
10
9
  const fs = require('fs');
11
10
  const path = require('path');
11
+ const os = require('os');
12
12
  const crypto = require('crypto');
13
13
 
14
14
  const projectDir = process.env.CLAUDE_PROJECT_DIR || process.cwd();
15
15
 
16
16
  const getCounterPath = () => {
17
17
  const hash = crypto.createHash('md5').update(projectDir).digest('hex');
18
- return path.join('/tmp', `gm-git-block-counter-${hash}.json`);
18
+ return path.join(os.tmpdir(), `gm-git-block-counter-${hash}.json`);
19
19
  };
20
20
 
21
21
  const readCounter = () => {
@@ -1,6 +1,5 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env bun
2
2
 
3
- // Skip hooks when running inside agentgui subprocess to prevent spurious injections
4
3
  if (process.env.AGENTGUI_SUBPROCESS === '1') {
5
4
  console.log(JSON.stringify({ decision: 'approve' }));
6
5
  process.exit(0);
@@ -9,8 +8,6 @@ if (process.env.AGENTGUI_SUBPROCESS === '1') {
9
8
  const fs = require('fs');
10
9
  const path = require('path');
11
10
 
12
- // Always use current working directory for .prd location
13
- // Explicitly resolve to ./.prd in the current folder
14
11
  const projectDir = process.cwd();
15
12
  const prdFile = path.resolve(projectDir, '.prd');
16
13
 
@@ -22,19 +19,15 @@ const run = () => {
22
19
  if (aborted) return { ok: true };
23
20
 
24
21
  try {
25
- // Check if .prd file exists and has content
26
22
  if (fs.existsSync(prdFile)) {
27
23
  const prdContent = fs.readFileSync(prdFile, 'utf-8').trim();
28
24
  if (prdContent.length > 0) {
29
- // .prd has content, block stopping
30
25
  return {
31
26
  ok: false,
32
27
  reason: `Work items remain in ${prdFile}. Remove completed items as they finish. Current items:\n\n${prdContent}`
33
28
  };
34
29
  }
35
30
  }
36
-
37
- // .prd doesn't exist or is empty, allow stop
38
31
  return { ok: true };
39
32
  } catch (error) {
40
33
  return { ok: true };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-gc",
3
- "version": "2.0.152",
3
+ "version": "2.0.153",
4
4
  "description": "State machine agent with hooks, skills, and automated git enforcement",
5
5
  "author": "AnEntrypoint",
6
6
  "license": "MIT",