mirror-mind 0.35.0 → 0.36.0

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.
@@ -29,6 +29,18 @@
29
29
  // the shipped wrapper.
30
30
  // Antigravity `agy plugin install <plugin dir>` stages the plugin with its
31
31
  // agy-native layer in one step (CV21.DS7.US1, agy 1.4.2).
32
+ // Grok Build `grok plugin install <plugin dir> --trust` copies the plugin
33
+ // under `~/.grok/installed-plugins/` and enables it: its skills,
34
+ // the hooks, and the MCP server, with no prompt left to answer
35
+ // (CV21.DS10.US1, probed on grok 1.0.62). Then a link under
36
+ // `~/.grok/rules/` carries the Operating Instructions as a rule
37
+ // Grok loads in every project (~2.2k tokens by Grok's count):
38
+ // Grok shows a SessionStart hook's context on screen only and
39
+ // ignores a prompt hook's (DS12.TS4 L2/L3), so the plugin's
40
+ // session-start delivery of D13 does not reach its model. Two
41
+ // steps. The shapes not chosen -- the Claude link alone (skills,
42
+ // no hooks), a link in `~/.grok/plugins/` (loads nothing until
43
+ // a config entry is hand-written) -- are in decisions.md.
32
44
  //
33
45
  // Gemini CLI had an entry here (a skills link, then four hooks merged into
34
46
  // `~/.gemini/settings.json` by absolute path) until CV21.DS8.US1 retired the
@@ -37,7 +49,7 @@
37
49
  import { join } from "node:path";
38
50
  import { commandOnPath } from "#util/paths.ts";
39
51
 
40
- export type RuntimeName = "pi" | "claude" | "codex" | "antigravity";
52
+ export type RuntimeName = "pi" | "claude" | "codex" | "antigravity" | "grok";
41
53
 
42
54
  /**
43
55
  * The one Codex level-up command (CV21.DS4.TS6). Codex 0.163.0 has no
@@ -48,6 +60,29 @@ export type RuntimeName = "pi" | "claude" | "codex" | "antigravity";
48
60
  */
49
61
  export const CODEX_PLUGIN_ADD_COMMAND = "codex plugin add mirror-mind@mirror-mind";
50
62
 
63
+ /** Where the plugin directory lives below an installed package. */
64
+ export function pluginDirectory(root: string): string {
65
+ return join(root, "plugins/mirror-mind");
66
+ }
67
+
68
+ /**
69
+ * The one Grok level-up command (CV21.DS10.US1). Grok copies a local-path
70
+ * plugin and keys the copy by the path STRING: `grok plugin update` is a
71
+ * no-op for it (it answers "local symlink, already live" over a real copy,
72
+ * grok 1.0.62), an install over the same string is refused as already
73
+ * installed, and a differently spelt string installs a second copy beside
74
+ * the first. So the level-up is uninstall, then install with the path `init`
75
+ * printed -- a function of the root, so `diagnose` and `update` cannot spell
76
+ * it differently (the CR071 lesson at the string level).
77
+ */
78
+ export function grokPluginReinstallCommand(root: string): string {
79
+ return `grok plugin uninstall mirror-mind --confirm && ${grokPluginInstallCommand(root)}`;
80
+ }
81
+
82
+ function grokPluginInstallCommand(root: string): string {
83
+ return `grok plugin install "${pluginDirectory(root)}" --trust`;
84
+ }
85
+
51
86
  export interface RuntimeWiring {
52
87
  /** The runtime, as a person names it. */
53
88
  readonly title: string;
@@ -67,8 +102,11 @@ export const RUNTIME_WIRING: Readonly<Record<RuntimeName, RuntimeWiring>> = {
67
102
  title: "Claude Code",
68
103
  command: "claude",
69
104
  steps: [
105
+ // `mkdir -p` first: a home that has never held a personal skill has no
106
+ // ~/.claude/skills/ yet, and the link alone fails there (CV21.DS5.US2's
107
+ // route, on the extensions plugin's step; the same line, paid here).
70
108
  (root) => [
71
- `ln -s "${join(root, "plugins/mirror-mind")}" ~/.claude/skills/mirror-mind`,
109
+ `mkdir -p ~/.claude/skills && ln -s "${pluginDirectory(root)}" ~/.claude/skills/mirror-mind`,
72
110
  "(the plugin loads every session: its skills, the hooks, and the MCP server)",
73
111
  ],
74
112
  ],
@@ -86,6 +124,29 @@ export const RUNTIME_WIRING: Readonly<Record<RuntimeName, RuntimeWiring>> = {
86
124
  (root) => [`agy plugin install "${root}/plugins/mirror-mind"`],
87
125
  ],
88
126
  },
127
+ grok: {
128
+ title: "Grok Build",
129
+ command: "grok",
130
+ steps: [
131
+ // CV21.DS10.US1, probed on grok 1.0.62: one command copies the plugin
132
+ // and enables it. Consent lives in the line: what --trust activates,
133
+ // and that Grok asks nothing afterwards (Codex's note says Codex asks
134
+ // once; Grok's must say it does not).
135
+ (root) => [
136
+ grokPluginInstallCommand(root),
137
+ "(--trust activates the plugin's hooks and MCP server, and Grok does not ask again;",
138
+ "Grok keeps a copy of the plugin, so after an update `mirror runtime diagnose`",
139
+ "names the command that brings it level)",
140
+ ],
141
+ // The Operating Instructions (D13) as a home-level rule. Grok loads
142
+ // every *.md under ~/.grok/rules/ in every project, link or file.
143
+ (root) => [
144
+ `ln -s "${join(root, "AGENTS.md")}" ~/.grok/rules/mirror-mind.md`,
145
+ "(the Operating Instructions, loaded as a rule in every Grok session, in",
146
+ "every project: about 2.2k tokens per session)",
147
+ ],
148
+ ],
149
+ },
89
150
  codex: {
90
151
  title: "Codex",
91
152
  command: "codex",
@@ -100,7 +161,7 @@ export const RUNTIME_WIRING: Readonly<Record<RuntimeName, RuntimeWiring>> = {
100
161
  },
101
162
  };
102
163
 
103
- const ORDER: readonly RuntimeName[] = ["pi", "claude", "codex", "antigravity"];
164
+ const ORDER: readonly RuntimeName[] = ["pi", "claude", "codex", "antigravity", "grok"];
104
165
 
105
166
  /** The runtimes whose command is on the PATH, in display order. */
106
167
  export function detectRuntimes(
@@ -124,3 +185,74 @@ export function runtimeWiringLines(runtime: RuntimeName, root: string): string[]
124
185
  });
125
186
  return lines;
126
187
  }
188
+
189
+ // ---------------------------------------------------------------------------
190
+ // The per-home extensions plugin (CV21.DS5.US2). A Mirror home's installed
191
+ // extensions reach the four plugin runtimes as one generated plugin per home,
192
+ // `<home>/runtime/plugin/mirror-ext-<user>/`, in the canonical plugin's format
193
+ // but carrying skills only (DS5.TS1's decision). Each runtime takes it the way
194
+ // it takes the canonical plugin, and the three that copy it (Codex, agy, Grok)
195
+ // need one command per change to bring the copy level — measured in TS1.
196
+ // `mirror init` prints none of this: at init there is no extension. The
197
+ // `extensions` verbs print the step a runtime still needs, and `runtime
198
+ // diagnose` names the reinstall for a stale copy. Printing is not automating.
199
+
200
+ export interface ExtensionPluginPaths {
201
+ /** The plugin directory: linked by Claude Code, installed by agy and Grok. */
202
+ readonly dir: string;
203
+ /** The marketplace root Codex adds: the plugin's parent, carrying `.agents/plugins/marketplace.json`. */
204
+ readonly marketplace: string;
205
+ /** `mirror-ext-<user>`: the plugin's name and its marketplace's. */
206
+ readonly name: string;
207
+ }
208
+
209
+ /** The consent line printed under Grok's step: what `--trust` would activate here, which is nothing. */
210
+ export const EXTENSION_PLUGIN_GROK_TRUST_NOTE =
211
+ "(this plugin carries skills only — no hooks and no MCP server for --trust to activate)";
212
+
213
+ /** The one-time wiring per runtime; Pi takes extensions through its own catalog and needs none. */
214
+ export function extensionPluginWiringSteps(
215
+ runtime: RuntimeName,
216
+ paths: ExtensionPluginPaths,
217
+ ): string[] {
218
+ switch (runtime) {
219
+ case "claude":
220
+ // `mkdir -p` first: a home that has never held a personal skill has no
221
+ // ~/.claude/skills/ yet, and the link alone fails there (measured, US2's route).
222
+ return [`mkdir -p ~/.claude/skills && ln -s "${paths.dir}" ~/.claude/skills/${paths.name}`];
223
+ case "codex":
224
+ return [
225
+ `codex plugin marketplace add "${paths.marketplace}"`,
226
+ `codex plugin add ${paths.name}@${paths.name}`,
227
+ ];
228
+ case "antigravity":
229
+ return [`agy plugin install "${paths.dir}"`];
230
+ case "grok":
231
+ return [`grok plugin install "${paths.dir}" --trust`];
232
+ case "pi":
233
+ return [];
234
+ }
235
+ }
236
+
237
+ /**
238
+ * What brings a runtime's copy level after the plugin changed, measured in
239
+ * DS5.TS1: Codex re-adds at the same version when the marketplace serves the
240
+ * live directory; agy installs again; Grok refuses an install over the same
241
+ * path and must uninstall first. Claude Code links and has no copy.
242
+ */
243
+ export function extensionPluginReinstallCommand(
244
+ runtime: RuntimeName,
245
+ paths: ExtensionPluginPaths,
246
+ ): string | null {
247
+ switch (runtime) {
248
+ case "claude":
249
+ case "pi":
250
+ return null;
251
+ case "codex":
252
+ return `codex plugin add ${paths.name}@${paths.name}`;
253
+ case "antigravity":
254
+ return `agy plugin install "${paths.dir}"`;
255
+ case "grok":
256
+ return `grok plugin uninstall ${paths.name} --confirm && grok plugin install "${paths.dir}" --trust`;
257
+ }
258
+ }