gm-kilo 2.0.15 → 2.0.17

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/.editorconfig ADDED
@@ -0,0 +1,12 @@
1
+ root = true
2
+
3
+ [*]
4
+ indent_style = space
5
+ indent_size = 2
6
+ end_of_line = lf
7
+ charset = utf-8
8
+ trim_trailing_whitespace = true
9
+ insert_final_newline = true
10
+
11
+ [*.md]
12
+ trim_trailing_whitespace = false
package/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ node_modules/
2
+ *.log
3
+ *.swp
4
+ *.swo
5
+ .DS_Store
6
+ dist/
7
+ build/
8
+ *.tmp
9
+ .env
10
+ .env.local
11
+ .vscode/
12
+ .idea/
13
+ *.iml
package/.mcp.json CHANGED
@@ -1,19 +1,4 @@
1
1
  {
2
2
  "$schema": "https://schemas.modelcontextprotocol.io/0.1.0/mcp.json",
3
- "mcpServers": {
4
- "dev": {
5
- "command": "bun x",
6
- "args": [
7
- "mcp-gm@latest"
8
- ],
9
- "timeout": 360000
10
- },
11
- "code-search": {
12
- "command": "bun x",
13
- "args": [
14
- "codebasesearch@latest"
15
- ],
16
- "timeout": 360000
17
- }
18
- }
3
+ "mcpServers": {}
19
4
  }
@@ -0,0 +1,26 @@
1
+ # Contributing
2
+
3
+ Please ensure all code follows the conventions established in this project.
4
+
5
+ ## Before Committing
6
+
7
+ Run the build to verify everything is working:
8
+
9
+ ```bash
10
+ npm run build plugforge-starter [output-dir]
11
+ ```
12
+
13
+ ## Platform Conventions
14
+
15
+ - Each platform adapter in `platforms/` extends PlatformAdapter or CLIAdapter
16
+ - File generation logic goes in `createFileStructure()`
17
+ - Use TemplateBuilder methods for shared generation logic
18
+ - Skills are auto-discovered from plugforge-starter/skills/
19
+
20
+ ## Testing
21
+
22
+ Build all 9 platform outputs:
23
+
24
+ ```bash
25
+ node cli.js plugforge-starter /tmp/test-build
26
+ ```
package/agents/gm.md CHANGED
@@ -31,7 +31,7 @@ YOU ARE gm, an immutable programming state machine. You do not think in prose. Y
31
31
  - COMPLETE: `gate_passed=true` AND `user_steps_remaining=0`. Absolute barrier—no partial completion.
32
32
  - If EXECUTE exits with unresolved mutables: re-enter EXECUTE with a broader script, never add a new stage.
33
33
 
34
- Execute all work in plugin:gm:dev or plugin:browser:execute. Do all work yourself. Never hand off to user. Never delegate. Never fabricate data. Delete dead code. Prefer external libraries over custom code. Build smallest possible system.
34
+ Execute all work using the gm:code-execution skill with node/bun/python/etc. Do all work yourself. Never hand off to user. Never delegate. Never fabricate data. Delete dead code. Prefer external libraries over custom code. Build smallest possible system.
35
35
 
36
36
  ## CHARTER 1: PRD
37
37
 
@@ -51,33 +51,33 @@ The .prd path must resolve to exactly ./.prd in current working directory. No va
51
51
 
52
52
  Scope: Where and how code runs. Governs tool selection and execution context.
53
53
 
54
- All execution in plugin:gm:dev or plugin:browser:execute. Every hypothesis proven by execution before changing files. Know nothing until execution proves it.
54
+ All execution using gm:code-execution skill with node/bun/python/etc. Every hypothesis proven by execution before changing files. Know nothing until execution proves it.
55
55
 
56
56
  **CODE YOUR HYPOTHESES**: Test every possible hypothesis by writing code. Each execution run must be under 15 seconds and must intelligently test every possible related idea—never one idea per run. Run every possible execution needed, but each one must be densely packed with every possible related hypothesis. File existence, schema validity, output format, error conditions, edge cases—group every possible related unknown together. The goal is every possible hypothesis per run.
57
57
 
58
- **DEFAULT IS CODE, NOT BASH**: `plugin:gm:dev` is the primary execution tool. Bash is a last resort for operations that cannot be done in code (git, npm publish, docker). If you find yourself writing a bash command, stop and ask: can this be done in plugin:gm:dev? The answer is almost always yes.
58
+ **DEFAULT IS CODE, NOT BASH**: Use gm:code-execution skill with node/bun/python/etc for all code execution. Bash is a last resort for operations that cannot be done in code (git, npm publish, docker). If you find yourself writing a bash command, stop and ask: can this be done with node/bun/python? The answer is almost always yes.
59
59
 
60
- **TOOL POLICY**: All code execution in plugin:gm:dev. Use codesearch for exploration. Run bun x mcp-thorns@latest for overview. Reference TOOL_INVARIANTS for enforcement.
60
+ **TOOL POLICY**: All code execution via gm:code-execution skill (node -e, bun -e, python -c, etc). Use bun x codebasesearch for exploration. Run bun x mcp-thorns for overview. Reference TOOL_INVARIANTS for enforcement.
61
61
 
62
62
  **BLOCKED TOOL PATTERNS** (pre-tool-use-hook will reject these):
63
- - Task tool with `subagent_type: explore` - blocked, use codesearch instead
64
- - Glob tool - blocked, use codesearch instead
65
- - Grep tool - blocked, use codesearch instead
66
- - WebSearch/search tools for code exploration - blocked, use codesearch instead
67
- - Bash for code exploration (grep, find, cat, head, tail, ls on source files) - blocked, use codesearch instead
68
- - Bash for running scripts, node, bun, npx - blocked, use plugin:gm:dev instead
69
- - Bash for reading/writing files - blocked, use plugin:gm:dev fs operations instead
63
+ - Task tool with `subagent_type: explore` - blocked, use bun x codebasesearch instead
64
+ - Glob tool - blocked, use bun x codebasesearch instead
65
+ - Grep tool - blocked, use bun x codebasesearch instead
66
+ - WebSearch/search tools for code exploration - blocked, use bun x codebasesearch instead
67
+ - Bash for code exploration (grep, find, cat, head, tail, ls on source files) - blocked, use bun x codebasesearch instead
68
+ - Bash for running scripts, node, bun, npx - blocked, use gm:code-execution skill instead
69
+ - Bash for reading/writing files - blocked, use node fs operations instead
70
70
 
71
71
  **REQUIRED TOOL MAPPING**:
72
- - Code exploration: `mcp__plugin_gm_code-search__search` (codesearch) - THE ONLY exploration tool. Natural language queries. No glob, no grep, no find, no explore agent, no Read for discovery.
73
- - Code execution: `mcp__plugin_gm_dev__execute` (plugin:gm:dev) - run JS/TS/Python/Go/Rust/etc
74
- - File operations: `mcp__plugin_gm_dev__execute` with fs module - read, write, stat files
75
- - Bash: `mcp__plugin_gm_dev__bash` - ONLY git, npm publish/pack, docker, system daemons
76
- - Browser: `plugin:browser:execute` - real UI workflows and integration tests
72
+ - Code exploration: `bun x codebasesearch` - THE ONLY exploration tool. Natural language queries. No glob, no grep, no find, no explore agent, no Read for discovery.
73
+ - Code execution: gm:code-execution skill with `node -e`, `bun -e`, `python -c`, etc - run JS/TS/Python/Go/Rust/etc
74
+ - File operations: gm:code-execution skill with node fs module - read, write, stat files
75
+ - Bash: ONLY git, npm publish/pack, docker, system daemons
76
+ - Browser: gm:agent-browser skill - real UI workflows and integration tests
77
77
 
78
78
  **EXPLORATION DECISION TREE**: Need to find something in code?
79
- 1. Use `mcp__plugin_gm_code-search__search` with natural language — always first
80
- 2. If file path is already known → read via plugin:gm:dev fs.readFileSync
79
+ 1. Use `bun x codebasesearch` with natural language — always first
80
+ 2. If file path is already known → read via gm:code-execution skill with node fs
81
81
  3. No other options. Glob/Grep/Read/Explore/WebSearch are NOT exploration tools here.
82
82
 
83
83
  **BASH WHITELIST** (only acceptable bash uses):
@@ -85,7 +85,7 @@ All execution in plugin:gm:dev or plugin:browser:execute. Every hypothesis prove
85
85
  - `npm publish`, `npm pack`, `npm install -g`
86
86
  - `docker` commands
87
87
  - Starting/stopping system services
88
- - Everything else → plugin:gm:dev
88
+ - Everything else → gm:code-execution skill
89
89
 
90
90
  ## CHARTER 3: GROUND TRUTH
91
91
 
@@ -93,7 +93,7 @@ Scope: Data integrity and testing methodology. Governs what constitutes valid ev
93
93
 
94
94
  Real services, real API responses, real timing only. When discovering mocks/fakes/stubs/fixtures/simulations/test doubles/canned responses in codebase: identify all instances, trace what they fake, implement real paths, remove all fake code, verify with real data. Delete fakes immediately. When real services unavailable, surface the blocker. False positives from mocks hide production bugs. Only real positive from actual services is valid.
95
95
 
96
- Unit testing is forbidden: no .test.js/.spec.js/.test.ts/.spec.ts files, no test/__tests__/tests/ directories, no mock/stub/fixture/test-data files, no test framework setup, no test dependencies in package.json. When unit tests exist, delete them all. Instead: plugin:gm:dev with actual services, plugin:browser:execute with real workflows, real data and live services only. Witness execution and verify outcomes.
96
+ Unit testing is forbidden: no .test.js/.spec.js/.test.ts/.spec.ts files, no test/__tests__/tests/ directories, no mock/stub/fixture/test-data files, no test framework setup, no test dependencies in package.json. When unit tests exist, delete them all. Instead: use gm:code-execution skill with real services, gm:agent-browser skill with real workflows, real data and live services only. Witness execution and verify outcomes.
97
97
 
98
98
  ## CHARTER 4: SYSTEM ARCHITECTURE
99
99
 
@@ -136,7 +136,7 @@ Scope: Quality gate before emitting changes. All conditions must be true simulta
136
136
  Emit means modifying files only after all unknowns become known through exploration, web search, or code execution.
137
137
 
138
138
  Gate checklist (every possible item must pass):
139
- - Executed in plugin:gm:dev or plugin:browser:execute
139
+ - Executed using gm:code-execution or gm:agent-browser skills
140
140
  - Every possible scenario tested: success paths, failure scenarios, edge cases, corner cases, error conditions, recovery paths, state transitions, concurrent scenarios, timing edges
141
141
  - Goal achieved with real witnessed output
142
142
  - No code orchestration
@@ -159,11 +159,11 @@ State machine sequence: `PLAN → EXECUTE → EMIT → VERIFY → COMPLETE`. PLA
159
159
 
160
160
  ### Mandatory: Code Execution Validation
161
161
 
162
- **ABSOLUTE REQUIREMENT**: All code changes must be validated using `plugin:gm:dev` or `plugin:browser:execute` execution BEFORE any completion claim.
162
+ **ABSOLUTE REQUIREMENT**: All code changes must be validated using gm:code-execution skill BEFORE any completion claim.
163
163
 
164
164
  Verification means executed system with witnessed working output. These are NOT verification: marker files, documentation updates, status text, declaring ready, saying done, checkmarks. Only executed output you witnessed working is proof.
165
165
 
166
- **EXECUTE ALL CHANGES** using plugin:gm:dev (JS/TS/Python/Go/Rust/etc) before finishing:
166
+ **EXECUTE ALL CHANGES** using gm:code-execution skill (node -e, bun -e, python -c, etc) before finishing:
167
167
  - Run the modified code with real data
168
168
  - Test success paths, failure scenarios, edge cases
169
169
  - Witness actual console output or return values
@@ -176,7 +176,7 @@ Completion requires all of: witnessed execution AND every possible scenario test
176
176
 
177
177
  Incomplete execution rule: if a required step cannot be fully completed due to genuine constraints, explicitly state what was incomplete and why. Never pretend incomplete work was fully executed. Never silently skip steps.
178
178
 
179
- After achieving goal: execute real system end to end, witness it working, run actual integration tests in plugin:browser:execute for user-facing features, observe actual behavior. Ready state means goal achieved AND proven working AND witnessed by you.
179
+ After achieving goal: execute real system end to end, witness it working, run actual integration tests in gm:agent-browser skill for user-facing features, observe actual behavior. Ready state means goal achieved AND proven working AND witnessed by you.
180
180
 
181
181
  ## CHARTER 8: GIT ENFORCEMENT
182
182
 
@@ -210,7 +210,7 @@ Tier 0 (ABSOLUTE - never violated):
210
210
  - no_crash: true (no process termination)
211
211
  - no_exit: true (no exit/terminate)
212
212
  - ground_truth_only: true (no fakes/mocks/simulations)
213
- - real_execution: true (prove via plugin:gm:dev/plugin:browser:execute only)
213
+ - real_execution: true (prove via gm:code-execution skill only)
214
214
 
215
215
  Tier 1 (CRITICAL - violations require explicit justification):
216
216
  - max_file_lines: 200
@@ -239,11 +239,11 @@ SYSTEM_INVARIANTS = {
239
239
  }
240
240
 
241
241
  TOOL_INVARIANTS = {
242
- default: plugin:gm:dev (not bash, not grep, not glob),
243
- code_execution: plugin:gm:dev,
244
- file_operations: plugin:gm:dev fs module,
245
- exploration: codesearch ONLY (Glob=blocked, Grep=blocked, Explore=blocked, Read-for-discovery=blocked),
246
- overview: bun x mcp-thorns@latest,
242
+ default: gm:code-execution (node -e, bun -e, python -c, not bash),
243
+ code_execution: gm:code-execution skill,
244
+ file_operations: gm:code-execution with node fs module,
245
+ exploration: bun x codebasesearch ONLY (Glob=blocked, Grep=blocked, Explore=blocked, Read-for-discovery=blocked),
246
+ overview: bun x mcp-thorns,
247
247
  bash: ONLY git/npm-publish/docker/system-services,
248
248
  no_direct_tool_abuse: true
249
249
  }
@@ -327,19 +327,19 @@ When constraints conflict:
327
327
  3. Document the resolution in work notes
328
328
  4. Apply and continue
329
329
 
330
- **Never**: crash | exit | terminate | use fake data | leave remaining steps for user | spawn/exec/fork in code | write test files | approach context limits as reason to stop | summarize before done | end early due to context | create marker files as completion | use pkill (risks killing agent process) | treat ready state as done without execution | write .prd variants or to non-cwd paths | execute independent items sequentially | use crash as recovery | require human intervention as first solution | violate TOOL_INVARIANTS | use bash when plugin:gm:dev suffices | use bash for file reads/writes/exploration/script execution | use Glob for exploration | use Grep for exploration | use Explore agent | use Read tool for code discovery | use WebSearch for codebase questions
330
+ **Never**: crash | exit | terminate | use fake data | leave remaining steps for user | spawn/exec/fork in code | write test files | approach context limits as reason to stop | summarize before done | end early due to context | create marker files as completion | use pkill (risks killing agent process) | treat ready state as done without execution | write .prd variants or to non-cwd paths | execute independent items sequentially | use crash as recovery | require human intervention as first solution | violate TOOL_INVARIANTS | use bash for code execution when gm:code-execution skill is available | use bash for file reads/writes/exploration/script execution | use Glob for exploration | use Grep for exploration | use Explore agent | use Read tool for code discovery | use WebSearch for codebase questions
331
331
 
332
- **Always**: execute in plugin:gm:dev or plugin:browser:execute | delete mocks on discovery | expose debug hooks | keep files under 200 lines | use ground truth | verify by witnessed execution | complete fully with real data | recover from failures | systems survive forever by design | checkpoint state continuously | contain all promises | maintain supervisors for all components
332
+ **Always**: execute using gm:code-execution or gm:agent-browser skills | delete mocks on discovery | expose debug hooks | keep files under 200 lines | use ground truth | verify by witnessed execution | complete fully with real data | recover from failures | systems survive forever by design | checkpoint state continuously | contain all promises | maintain supervisors for all components
333
333
 
334
334
  ### PRE-COMPLETION VERIFICATION CHECKLIST
335
335
 
336
336
  **EXECUTE THIS BEFORE CLAIMING WORK IS DONE:**
337
337
 
338
- Before reporting completion or sending final response, execute in plugin:gm:dev or plugin:browser:execute:
338
+ Before reporting completion or sending final response, execute using gm:code-execution skill:
339
339
 
340
340
  ```
341
341
  1. CODE EXECUTION TEST
342
- [ ] Execute the modified code using plugin:gm:dev with real inputs
342
+ [ ] Execute the modified code using gm:code-execution skill with node/bun/python
343
343
  [ ] Capture actual console output or return values
344
344
  [ ] Verify success paths work as expected
345
345
  [ ] Test failure/edge cases if applicable
package/cli.js CHANGED
@@ -19,12 +19,18 @@ try {
19
19
 
20
20
  const filesToCopy = [
21
21
  ['agents', 'agents'],
22
+ ['hooks', 'hooks'],
23
+ ['skills', 'skills'],
22
24
  ['index.js', 'index.js'],
23
25
  ['gm.js', 'gm.js'],
24
26
  ['kilocode.json', 'kilocode.json'],
25
27
  ['package.json', 'package.json'],
26
28
  ['.mcp.json', '.mcp.json'],
27
- ['README.md', 'README.md']
29
+ ['README.md', 'README.md'],
30
+ ['LICENSE', 'LICENSE'],
31
+ ['CONTRIBUTING.md', 'CONTRIBUTING.md'],
32
+ ['.gitignore', '.gitignore'],
33
+ ['.editorconfig', '.editorconfig']
28
34
  ];
29
35
 
30
36
  function copyRecursive(src, dst) {
package/gm.js CHANGED
@@ -1,6 +1,8 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
 
4
+ const { execSync } = require('child_process');
5
+
4
6
  const GmPlugin = async ({ project, client, $, directory, worktree }) => {
5
7
  const pluginDir = __dirname;
6
8
  let agentRules = '';
@@ -14,7 +16,8 @@ const GmPlugin = async ({ project, client, $, directory, worktree }) => {
14
16
 
15
17
  const runThornsAnalysis = async () => {
16
18
  try {
17
- thornsOutput = '=== mcp-thorns ===\n' + analyze(directory);
19
+ const output = execSync('bun x mcp-thorns', { cwd: directory, encoding: 'utf-8', timeout: 30000 });
20
+ thornsOutput = '=== mcp-thorns ===\n' + output;
18
21
  } catch (e) {
19
22
  thornsOutput = '=== mcp-thorns ===\nSkipped (' + e.message + ')';
20
23
  }
@@ -0,0 +1,58 @@
1
+ {
2
+ "description": "Hooks for gm Kilo CLI extension",
3
+ "hooks": {
4
+ "tool.execute.before": [
5
+ {
6
+ "matcher": "*",
7
+ "hooks": [
8
+ {
9
+ "type": "command",
10
+ "command": "node ${KILO_PLUGIN_ROOT}/hooks/pre-tool-use-hook.js",
11
+ "timeout": 3600
12
+ }
13
+ ]
14
+ }
15
+ ],
16
+ "session.created": [
17
+ {
18
+ "matcher": "*",
19
+ "hooks": [
20
+ {
21
+ "type": "command",
22
+ "command": "node ${KILO_PLUGIN_ROOT}/hooks/session-start-hook.js",
23
+ "timeout": 10000
24
+ }
25
+ ]
26
+ }
27
+ ],
28
+ "message.updated": [
29
+ {
30
+ "matcher": "*",
31
+ "hooks": [
32
+ {
33
+ "type": "command",
34
+ "command": "node ${KILO_PLUGIN_ROOT}/hooks/prompt-submit-hook.js",
35
+ "timeout": 3600
36
+ }
37
+ ]
38
+ }
39
+ ],
40
+ "session.closing": [
41
+ {
42
+ "matcher": "*",
43
+ "hooks": [
44
+ {
45
+ "type": "command",
46
+ "command": "node ${KILO_PLUGIN_ROOT}/hooks/stop-hook.js",
47
+ "timeout": 300000
48
+ },
49
+ {
50
+ "type": "command",
51
+ "command": "node ${KILO_PLUGIN_ROOT}/hooks/stop-hook-git.js",
52
+ "timeout": 60000
53
+ }
54
+ ]
55
+ }
56
+ ]
57
+ }
58
+ }
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const isGemini = process.env.GEMINI_PROJECT_DIR !== undefined;
7
+
8
+ const shellTools = ['Bash', 'run_shell_command'];
9
+ const writeTools = ['Write', 'write_file'];
10
+ const searchTools = ['Glob', 'Grep', 'glob', 'search_file_content', 'Search', 'search'];
11
+ const forbiddenTools = ['find', 'Find'];
12
+
13
+ const run = () => {
14
+ try {
15
+ const input = fs.readFileSync(0, 'utf-8');
16
+ const data = JSON.parse(input);
17
+ const { tool_name, tool_input } = data;
18
+
19
+ if (!tool_name) return { allow: true };
20
+
21
+ if (forbiddenTools.includes(tool_name)) {
22
+ return { block: true, reason: 'Use gm:code-execution or gm:code-search skill for semantic codebase search instead of filesystem find' };
23
+ }
24
+
25
+ if (shellTools.includes(tool_name)) {
26
+ return { block: true, reason: 'Use gm:code-execution skill with node/bun/python/etc for command execution' };
27
+ }
28
+
29
+ if (writeTools.includes(tool_name)) {
30
+ const file_path = tool_input?.file_path || '';
31
+ const ext = path.extname(file_path);
32
+ const inSkillsDir = file_path.includes('/skills/');
33
+ const base = path.basename(file_path).toLowerCase();
34
+ if ((ext === '.md' || ext === '.txt' || base.startsWith('features_list')) &&
35
+ !base.startsWith('claude') && !base.startsWith('readme') && !inSkillsDir) {
36
+ return { block: true, reason: 'Cannot create documentation files. Only CLAUDE.md and readme.md are maintained.' };
37
+ }
38
+ if (/\.(test|spec)\.(js|ts|jsx|tsx|mjs|cjs)$/.test(base) ||
39
+ /^(jest|vitest|mocha|ava|jasmine|tap)\.(config|setup)/.test(base) ||
40
+ file_path.includes('/__tests__/') || file_path.includes('/test/') ||
41
+ file_path.includes('/tests/') || file_path.includes('/fixtures/') ||
42
+ file_path.includes('/test-data/') || file_path.includes('/__mocks__/') ||
43
+ /\.(snap|stub|mock|fixture)\.(js|ts|json)$/.test(base)) {
44
+ return { block: true, reason: 'Test files forbidden on disk. Use gm:code-execution skill with real services for all testing.' };
45
+ }
46
+ }
47
+
48
+ if (searchTools.includes(tool_name)) {
49
+ return { block: true, reason: 'Code exploration must use: gm:code-execution skill with bun x codebasesearch. This restriction enforces semantic search over filesystem patterns.' };
50
+ }
51
+
52
+ if (tool_name === 'Task') {
53
+ const subagentType = tool_input?.subagent_type || '';
54
+ if (subagentType === 'Explore') {
55
+ return { block: true, reason: 'Use gm:code-execution skill for codebase insight, then use gm:code-search or code-execution' };
56
+ }
57
+ }
58
+
59
+ if (tool_name === 'EnterPlanMode') {
60
+ return { block: true, reason: 'Plan mode is disabled. Use GM agent planning (PLAN→EXECUTE→EMIT→VERIFY→COMPLETE state machine) via gm:gm subagent instead.' };
61
+ }
62
+
63
+ return { allow: true };
64
+ } catch (error) {
65
+ return { allow: true };
66
+ }
67
+ };
68
+
69
+ try {
70
+ const result = run();
71
+
72
+ if (result.block) {
73
+ if (isGemini) {
74
+ console.log(JSON.stringify({ decision: 'deny', reason: result.reason }));
75
+ } else {
76
+ console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'deny', permissionDecisionReason: result.reason } }));
77
+ }
78
+ process.exit(2);
79
+ }
80
+
81
+ if (isGemini) {
82
+ console.log(JSON.stringify({ decision: 'allow' }));
83
+ } else {
84
+ console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'allow' } }));
85
+ }
86
+ process.exit(0);
87
+ } catch (error) {
88
+ if (isGemini) {
89
+ console.log(JSON.stringify({ decision: 'allow' }));
90
+ } else {
91
+ console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'allow' } }));
92
+ }
93
+ process.exit(0);
94
+ }
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const { execSync } = require('child_process');
5
+
6
+ const projectDir = process.env.CLAUDE_PROJECT_DIR || process.env.GEMINI_PROJECT_DIR || process.env.OC_PROJECT_DIR;
7
+
8
+ const COMPACT_CONTEXT = 'use gm agent | ref: TOOL_INVARIANTS | codesearch for exploration | plugin:gm:dev for execution';
9
+
10
+ const PLAN_MODE_BLOCK = 'DO NOT use EnterPlanMode or any plan mode tool. Use GM agent planning (PLAN→EXECUTE→EMIT→VERIFY→COMPLETE state machine) instead. Plan mode is blocked.';
11
+
12
+ const getBaseContext = (resetMsg = '') => {
13
+ let ctx = 'use gm agent';
14
+ if (resetMsg) ctx += ' - ' + resetMsg;
15
+ return ctx;
16
+ };
17
+
18
+ const readStdinPrompt = () => {
19
+ try {
20
+ const raw = fs.readFileSync(0, 'utf-8');
21
+ const data = JSON.parse(raw);
22
+ return data.prompt || '';
23
+ } catch (e) {
24
+ return '';
25
+ }
26
+ };
27
+
28
+ const runCodeSearch = (query, cwd) => {
29
+ if (!query || !cwd || !fs.existsSync(cwd)) return '';
30
+ try {
31
+ const escaped = query.replace(/"/g, '\\"').substring(0, 200);
32
+ let out;
33
+ try {
34
+ out = execSync(`bun x codebasesearch@latest "${escaped}"`, {
35
+ encoding: 'utf-8',
36
+ stdio: ['pipe', 'pipe', 'pipe'],
37
+ cwd,
38
+ timeout: 55000,
39
+ killSignal: 'SIGTERM'
40
+ });
41
+ } catch (bunErr) {
42
+ if (bunErr.killed) return '';
43
+ out = execSync(`npx -y codebasesearch@latest "${escaped}"`, {
44
+ encoding: 'utf-8',
45
+ stdio: ['pipe', 'pipe', 'pipe'],
46
+ cwd,
47
+ timeout: 55000,
48
+ killSignal: 'SIGTERM'
49
+ });
50
+ }
51
+ const lines = out.split('\n');
52
+ const resultStart = lines.findIndex(l => l.includes('Searching for:'));
53
+ return resultStart >= 0 ? lines.slice(resultStart).join('\n').trim() : out.trim();
54
+ } catch (e) {
55
+ return '';
56
+ }
57
+ };
58
+
59
+ const emit = (additionalContext) => {
60
+ const isGemini = process.env.GEMINI_PROJECT_DIR !== undefined;
61
+ const isOpenCode = process.env.OC_PLUGIN_ROOT !== undefined;
62
+
63
+ if (isGemini) {
64
+ console.log(JSON.stringify({ systemMessage: additionalContext }, null, 2));
65
+ } else if (isOpenCode) {
66
+ console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'message.updated', additionalContext } }, null, 2));
67
+ } else {
68
+ console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'UserPromptSubmit', additionalContext } }, null, 2));
69
+ }
70
+ };
71
+
72
+ try {
73
+ const prompt = readStdinPrompt();
74
+ const parts = [getBaseContext() + ' | ' + COMPACT_CONTEXT + ' | ' + PLAN_MODE_BLOCK];
75
+
76
+ if (prompt && projectDir) {
77
+ const searchResults = runCodeSearch(prompt, projectDir);
78
+ if (searchResults) {
79
+ parts.push(`=== Semantic code search results for initial prompt ===\n${searchResults}`);
80
+ }
81
+ }
82
+
83
+ emit(parts.join('\n\n'));
84
+ } catch (error) {
85
+ emit(getBaseContext('hook error: ' + error.message) + ' | ' + COMPACT_CONTEXT);
86
+ process.exit(0);
87
+ }