gm-copilot-cli 2.0.204 → 2.0.206

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.204
3
+ version: 2.0.206
4
4
  description: State machine agent with hooks, skills, and automated git enforcement
5
5
  author: AnEntrypoint
6
6
  repository: https://github.com/AnEntrypoint/gm-copilot-cli
@@ -7,6 +7,7 @@ const { execSync, spawnSync } = require('child_process');
7
7
 
8
8
  const isGemini = process.env.GEMINI_PROJECT_DIR !== undefined;
9
9
  const IS_WIN = process.platform === 'win32';
10
+ const projectDir = process.env.CLAUDE_PROJECT_DIR || process.env.GEMINI_PROJECT_DIR || process.env.OC_PROJECT_DIR || process.env.KILO_PROJECT_DIR;
10
11
 
11
12
  // ─── Local tool management ────────────────────────────────────────────────────
12
13
  const TOOLS_DIR = path.join(os.homedir(), '.claude', 'gm-tools');
package/index.html CHANGED
@@ -18,7 +18,7 @@
18
18
  <script type="module">
19
19
  import { createElement as h, applyDiff, Fragment } from "webjsx";
20
20
  const PLATFORM_NAME="Copilot CLI",PLATFORM_TYPE="CLI Tool",PLATFORM_TYPE_COLOR="#3b82f6";
21
- const DESCRIPTION="State machine agent with hooks, skills, and automated git enforcement",VERSION="2.0.204";
21
+ const DESCRIPTION="State machine agent with hooks, skills, and automated git enforcement",VERSION="2.0.206";
22
22
  const GITHUB_URL="https://github.com/AnEntrypoint/gm-copilot-cli",BADGE_LABEL="copilot-cli";
23
23
  const FEATURES=[{"title":"State Machine","desc":"Immutable PLAN→EXECUTE→EMIT→VERIFY→COMPLETE phases with full mutable tracking"},{"title":"Semantic Search","desc":"Natural language codebase exploration via codesearch skill — no grep needed"},{"title":"Hooks","desc":"Pre-tool, session-start, prompt-submit, and stop hooks for full lifecycle control"},{"title":"Agents","desc":"gm, codesearch, and websearch agents pre-configured and ready to use"},{"title":"MCP Integration","desc":"Model Context Protocol server support built in"},{"title":"Auto-Recovery","desc":"Supervisor hierarchy ensures the system never crashes"}],INSTALL_STEPS=[{"desc":"Install via GitHub CLI","cmd":"gh extension install AnEntrypoint/gm-copilot-cli"},{"desc":"Restart your terminal — activates automatically"}];
24
24
  const CURRENT_PLATFORM="gm-copilot-cli";
package/manifest.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  name: gm
2
- version: 2.0.204
2
+ version: 2.0.206
3
3
  description: State machine agent with hooks, skills, and automated git enforcement
4
4
  author: AnEntrypoint
5
5
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-copilot-cli",
3
- "version": "2.0.204",
3
+ "version": "2.0.206",
4
4
  "description": "State machine agent with hooks, skills, and automated git enforcement",
5
5
  "author": "AnEntrypoint",
6
6
  "license": "MIT",
@@ -0,0 +1,180 @@
1
+ ---
2
+ name: create-lang-plugin
3
+ description: Create a lang/ plugin that wires any CLI tool or language runtime into gm-cc — adds exec:<id> dispatch, optional LSP diagnostics, and optional prompt context injection. Zero hook configuration required.
4
+ ---
5
+
6
+ # CREATE LANG PLUGIN
7
+
8
+ A lang plugin is a single CommonJS file at `<projectDir>/lang/<id>.js`. gm-cc's hooks auto-discover it — no hook editing, no settings changes. The plugin gets three integration points: **exec dispatch**, **LSP diagnostics**, and **context injection**.
9
+
10
+ ## PLUGIN SHAPE
11
+
12
+ ```js
13
+ 'use strict';
14
+ module.exports = {
15
+ id: 'mytool', // must match filename: lang/mytool.js
16
+ exec: {
17
+ match: /^exec:mytool/, // regex tested against full "exec:mytool\n<code>" string
18
+ run(code, cwd) { // returns string or Promise<string>
19
+ // ...
20
+ }
21
+ },
22
+ lsp: { // optional — synchronous only
23
+ check(fileContent, cwd) { // returns Diagnostic[] synchronously
24
+ // ...
25
+ }
26
+ },
27
+ extensions: ['.ext'], // optional — file extensions lsp.check applies to
28
+ context: `=== mytool ===\n...` // optional — string or () => string
29
+ };
30
+ ```
31
+
32
+ ```ts
33
+ type Diagnostic = { line: number; col: number; severity: 'error'|'warning'; message: string };
34
+ ```
35
+
36
+ ## HOW IT WORKS
37
+
38
+ - **`exec.run`** is called in a child process (30s timeout) when Claude writes `exec:mytool\n<code>`. Output is returned as `exec:mytool output:\n\n<result>`. Async is fine here.
39
+ - **`lsp.check`** is called synchronously in the hook process on each prompt submit — must NOT be async. Use `execFileSync` or `spawnSync`.
40
+ - **`context`** is injected into every prompt's `additionalContext` (truncated to 2000 chars) and into the session-start context.
41
+ - **`match`** regex is tested against the full command string `exec:mytool\n<code>` — keep it simple: `/^exec:mytool/`.
42
+
43
+ ## STEP 1 — IDENTIFY THE TOOL
44
+
45
+ Answer these before writing any code:
46
+
47
+ 1. What is the tool's CLI name or npm package? (`gdlint`, `tsc`, `deno`, `ruff`, ...)
48
+ 2. How do you run a single expression/snippet? (`tool eval <expr>`, `tool -e <code>`, HTTP POST, ...)
49
+ 3. How do you run a file? (`tool run <file>`, `tool <file>`, ...)
50
+ 4. Does it have a lint/check mode? What does its output format look like?
51
+ 5. What file extensions does it apply to?
52
+ 6. Is the game/server running required, or does it work headlessly?
53
+
54
+ ## STEP 2 — IMPLEMENT exec.run
55
+
56
+ Pattern for **HTTP eval** (tool has a running server):
57
+
58
+ ```js
59
+ const http = require('http');
60
+ function httpPost(port, urlPath, body) {
61
+ return new Promise((resolve, reject) => {
62
+ const data = JSON.stringify(body);
63
+ const req = http.request(
64
+ { hostname: '127.0.0.1', port, path: urlPath, method: 'POST',
65
+ headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) } },
66
+ (res) => { let raw = ''; res.on('data', c => raw += c); res.on('end', () => { try { resolve(JSON.parse(raw)); } catch { resolve({ raw }); } }); }
67
+ );
68
+ req.setTimeout(8000, () => { req.destroy(); reject(new Error('timeout')); });
69
+ req.on('error', reject);
70
+ req.write(data); req.end();
71
+ });
72
+ }
73
+ ```
74
+
75
+ Pattern for **file-based execution** (write temp file, run headlessly):
76
+
77
+ ```js
78
+ const fs = require('fs');
79
+ const os = require('os');
80
+ const path = require('path');
81
+ const { execFileSync } = require('child_process');
82
+
83
+ function runFile(code, cwd) {
84
+ const tmp = path.join(os.tmpdir(), `plugin_${Date.now()}.ext`);
85
+ fs.writeFileSync(tmp, code);
86
+ try {
87
+ return execFileSync('mytool', ['run', tmp], { cwd, encoding: 'utf8', timeout: 10000 });
88
+ } finally {
89
+ try { fs.unlinkSync(tmp); } catch (_) {}
90
+ }
91
+ }
92
+ ```
93
+
94
+ **Distinguish single expression vs multi-line** when both modes exist:
95
+
96
+ ```js
97
+ function isSingleExpr(code) {
98
+ return !code.trim().includes('\n') && !/\b(func|def|fn |class|import)\b/.test(code);
99
+ }
100
+ ```
101
+
102
+ ## STEP 3 — IMPLEMENT lsp.check (if applicable)
103
+
104
+ Must be **synchronous**. Parse the tool's stderr/stdout for diagnostics:
105
+
106
+ ```js
107
+ const { spawnSync } = require('child_process');
108
+ const fs = require('fs');
109
+ const os = require('os');
110
+ const path = require('path');
111
+
112
+ function check(fileContent, cwd) {
113
+ const tmp = path.join(os.tmpdir(), `lsp_${Math.random().toString(36).slice(2)}.ext`);
114
+ try {
115
+ fs.writeFileSync(tmp, fileContent);
116
+ const r = spawnSync('mytool', ['check', tmp], { encoding: 'utf8', cwd });
117
+ const output = r.stdout + r.stderr;
118
+ return output.split('\n').reduce((acc, line) => {
119
+ const m = line.match(/^.+:(\d+):(\d+):\s+(error|warning):\s+(.+)$/);
120
+ if (m) acc.push({ line: parseInt(m[1]), col: parseInt(m[2]), severity: m[3], message: m[4].trim() });
121
+ return acc;
122
+ }, []);
123
+ } catch (_) {
124
+ return [];
125
+ } finally {
126
+ try { fs.unlinkSync(tmp); } catch (_) {}
127
+ }
128
+ }
129
+ ```
130
+
131
+ Common output patterns to parse:
132
+ - `file:line:col: error: message` → standard
133
+ - `file:line: E001: message` → gdlint style (`E`=error, `W`=warning)
134
+ - JSON output → `JSON.parse(r.stdout).errors.map(...)`
135
+
136
+ ## STEP 4 — WRITE context STRING
137
+
138
+ Describe what `exec:<id>` does and when to use it. This appears in every prompt. Keep it under 300 chars:
139
+
140
+ ```js
141
+ context: `=== mytool exec: support ===
142
+ exec:mytool
143
+ <expression or code block>
144
+
145
+ Runs via <how>. Use for <when>.`
146
+ ```
147
+
148
+ ## STEP 5 — WRITE THE FILE
149
+
150
+ File goes at `lang/<id>.js` in the project root. The `id` field must match the filename (without `.js`).
151
+
152
+ Verify after writing:
153
+
154
+ ```
155
+ exec:nodejs
156
+ const p = require('/abs/path/to/lang/mytool.js');
157
+ console.log(p.id, typeof p.exec.run, p.exec.match.toString());
158
+ ```
159
+
160
+ Then test dispatch:
161
+
162
+ ```
163
+ exec:mytool
164
+ <a simple test expression>
165
+ ```
166
+
167
+ If it returns `exec:mytool output:` → working. If it errors → fix `exec.run`.
168
+
169
+ ## CONSTRAINTS
170
+
171
+ - `exec.run` may be async — it runs in a child process with a 30s timeout
172
+ - `lsp.check` must be synchronous — no Promises, no async/await
173
+ - Plugin must be CommonJS (`module.exports = { ... }`) — no ES module syntax
174
+ - No persistent processes — `exec.run` must complete and exit cleanly
175
+ - `id` must match the filename exactly
176
+ - First match wins — if multiple plugins could match, make `match` specific
177
+
178
+ ## EXAMPLE — gdscript plugin (reference implementation)
179
+
180
+ See `C:/dev/godot-kit/lang/gdscript.js` for a complete working example combining HTTP eval (single expressions via port 6009) with headless file execution fallback, synchronous gdlint LSP, and a context string.
package/tools.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm",
3
- "version": "2.0.204",
3
+ "version": "2.0.206",
4
4
  "description": "State machine agent with hooks, skills, and automated git enforcement",
5
5
  "tools": [
6
6
  {