diff --git a/plugins/lfg/bin/lfg-mcp.ts b/plugins/lfg/bin/lfg-mcp.ts
index b33ba7e..b7de204 100644
--- a/plugins/lfg/bin/lfg-mcp.ts
+++ b/plugins/lfg/bin/lfg-mcp.ts
@@ -14,7 +14,7 @@ const PLUGIN_ROOT = resolve(import.meta.dir, "..")
 const TOOLS: readonly McpTool[] = [
   { name: "status", description: "Show the local lfg lazycodex adapter installer status.", inputSchema: emptySchema() },
   { name: "doctor", description: "Check the minimal lfg lazycodex adapter installer.", inputSchema: emptySchema() },
-  { name: "lazycodex", description: "Return the lazycodex-ai install plan or status.", inputSchema: actionSchema(["install", "status"]) },
+  { name: "lazycodex", description: "Return the lazycodex-ai install plan/status or explicitly run the installer.", inputSchema: actionSchema(["install", "status"], true) },
   { name: "setup", description: "Return the non-mutating lazycodex-ai setup install plan.", inputSchema: actionSchema(["install-plan", "show"]) },
 ]
 
@@ -58,7 +58,7 @@ async function callTool(params: JsonRecord): Promise<JsonRecord> {
   if (name === "doctor") return textResult(await runLfgJson(["doctor"]))
   if (name === "lazycodex") {
     const action = typeof args.action === "string" ? args.action : "status"
-    if (action === "install") return textResult(await runLfgJson(["lazycodex", "install"]))
+    if (action === "install") return textResult(await runLfgJson(args.run === true ? ["lazycodex", "install", "--run"] : ["lazycodex", "install"]))
     if (action === "status") return textResult(await runLfgJson(["lazycodex", "status"]))
   }
   if (name === "setup") {
@@ -129,8 +129,10 @@ function emptySchema(): JsonRecord {
   return { type: "object", additionalProperties: false, properties: {} }
 }
 
-function actionSchema(actions: readonly string[]): JsonRecord {
-  return { type: "object", additionalProperties: false, properties: { action: { type: "string", enum: [...actions] } } }
+function actionSchema(actions: readonly string[], run = false): JsonRecord {
+  const properties: JsonRecord = { action: { type: "string", enum: [...actions] } }
+  if (run) properties.run = { type: "boolean" }
+  return { type: "object", additionalProperties: false, properties }
 }
 
 function asJsonRecord(value: unknown): JsonRecord {
diff --git a/plugins/lfg/bin/lfg.test.ts b/plugins/lfg/bin/lfg.test.ts
index 295c8c6..22420be 100644
--- a/plugins/lfg/bin/lfg.test.ts
+++ b/plugins/lfg/bin/lfg.test.ts
@@ -1,5 +1,5 @@
 import { describe, expect, test } from "bun:test"
-import { mkdir, mkdtemp, readFile, writeFile } from "node:fs/promises"
+import { chmod, mkdir, mkdtemp, readFile, writeFile } from "node:fs/promises"
 import { tmpdir } from "node:os"
 import { join } from "node:path"
 
@@ -15,21 +15,67 @@ describe("lfg CLI", () => {
   })
 
   test("reports lazycodex adapter install command and target", async () => {
-    const result = await runLfg(["--json", "lazycodex", "install"])
+    const home = await mkdtemp(join(tmpdir(), "lfg-home."))
+    const result = await runLfg(["--json", "lazycodex", "install"], { HOME: home })
     expect(result.exitCode).toBe(0)
     expect(result.json).toMatchObject({
       ok: true,
+      status: "planned",
       role: "lazycodex_adapter_installer",
       adapterPackage: "lazycodex-ai",
       installerCommand: "npx lazycodex-ai install",
+      executed: false,
       grokBuildUse: true,
-      adapterRoot: expect.stringContaining(join(".grok", "installed-plugins", "0-1-0-ff47fdd7")),
-      adapterManifest: expect.stringContaining(join(".codex-plugin", "plugin.json")),
+      lfgIsPlugin: false,
+      grokSurfaces: {
+        customModelConfig: expect.stringContaining(join(".grok", "config.toml")),
+        globalAgentRoot: expect.stringContaining(join(".grok", "agents")),
+        projectAgentRoot: expect.stringContaining(join(".grok", "agents")),
+        acpCommand: "grok agent stdio",
+        globalPluginRoot: expect.stringContaining(join(".grok", "plugins")),
+        projectPluginRoot: expect.stringContaining(join(".grok", "plugins")),
+        userMcpConfig: expect.stringContaining(join(".grok", "config.toml")),
+        projectMcpConfig: expect.stringContaining(join(".grok", "config.toml")),
+        projectRootMcpConfig: expect.stringContaining(".mcp.json"),
+      },
+      verificationCommands: expect.arrayContaining(["grok models", "grok inspect --json", "grok plugin list --json"]),
     })
+    expect(JSON.stringify(result.json)).not.toContain("installed-plugins/0-1-0-ff47fdd7")
     expect(JSON.stringify(result.json)).not.toContain("Grok plugin")
     expect(JSON.stringify(result.json)).not.toContain("grok_plugin")
   })
 
+  test("runs lazycodex installer through npx when explicitly requested", async () => {
+    const fakeBin = await makeFakeNpx(0)
+    const result = await runLfg(["--json", "lazycodex", "install", "--run"], { PATH: `${fakeBin}:${process.env.PATH ?? ""}` })
+
+    expect(result.exitCode).toBe(0)
+    expect(result.json).toMatchObject({
+      ok: true,
+      status: "installed",
+      executed: true,
+      installerCommand: "npx lazycodex-ai install",
+      installerArgs: ["lazycodex-ai", "install"],
+      exitCode: 0,
+    })
+    expect(JSON.stringify(result.json)).toContain("fake lazycodex install")
+  })
+
+  test("reports npx installer failure", async () => {
+    const fakeBin = await makeFakeNpx(7)
+    const result = await runLfg(["--json", "lazycodex", "install", "--run"], { PATH: `${fakeBin}:${process.env.PATH ?? ""}` })
+
+    expect(result.exitCode).toBe(1)
+    expect(result.json).toMatchObject({
+      ok: false,
+      status: "install_failed",
+      executed: true,
+      installerCommand: "npx lazycodex-ai install",
+      exitCode: 7,
+    })
+    expect(JSON.stringify(result.json)).toContain("fake lazycodex failure")
+  })
+
   test("status and setup describe lfg as adapter installer not plugin", async () => {
     const status = await runLfg(["--json", "status"])
     expect(status.exitCode).toBe(0)
@@ -83,6 +129,18 @@ describe("lfg CLI", () => {
 
     expect(result.exitCode).toBe(0)
     expect(result.json).toMatchObject({
+      grokSurfaces: {
+        customModelConfig: expect.stringContaining(join(".grok", "config.toml")),
+        globalAgentRoot: expect.stringContaining(join(".grok", "agents")),
+        projectAgentRoot: expect.stringContaining(join(".grok", "agents")),
+        acpCommand: "grok agent stdio",
+        globalPluginRoot: expect.stringContaining(join(".grok", "plugins")),
+        projectPluginRoot: expect.stringContaining(join(".grok", "plugins")),
+        userMcpConfig: expect.stringContaining(join(".grok", "config.toml")),
+        projectMcpConfig: expect.stringContaining(join(".grok", "config.toml")),
+        projectRootMcpConfig: expect.stringContaining(".mcp.json"),
+      },
+      verificationCommands: expect.arrayContaining(["grok models", "grok inspect --json", "grok plugin list --json"]),
       adapter: {
         found: true,
         root: adapterRoot,
@@ -92,6 +150,21 @@ describe("lfg CLI", () => {
       },
     })
   })
+
+  test("detects grok installed lazycodex adapter when primary plugin path is absent", async () => {
+    const home = await mkdtemp(join(tmpdir(), "lfg-home."))
+    const adapterRoot = await makeAdapterRoot(join(home, ".grok", "installed-plugins", "0-1-0-ff47fdd7"))
+    const result = await runLfg(["--json", "lazycodex", "status"], { HOME: home })
+
+    expect(result.exitCode).toBe(0)
+    expect(result.json).toMatchObject({
+      adapter: {
+        found: true,
+        root: adapterRoot,
+        manifest: join(adapterRoot, ".codex-plugin", "plugin.json"),
+      },
+    })
+  })
 })
 
 async function runLfg(args: readonly string[], env: Readonly<Record<string, string>> = {}): Promise<{ readonly exitCode: number; readonly json: unknown }> {
@@ -100,11 +173,19 @@ async function runLfg(args: readonly string[], env: Readonly<Record<string, stri
   return { exitCode, json: JSON.parse(stdout) as unknown }
 }
 
-async function makeAdapterRoot(): Promise<string> {
-  const root = await mkdtemp(join(tmpdir(), "lfg-lazycodex-adapter."))
-  await mkdir(join(root, ".codex-plugin"), { recursive: true })
-  await mkdir(join(root, "skills"), { recursive: true })
-  await writeFile(join(root, ".codex-plugin", "plugin.json"), `${JSON.stringify({ name: "lazycodex", version: "0.1.0" })}\n`)
-  await writeFile(join(root, ".mcp.json"), `${JSON.stringify({ mcpServers: {} })}\n`)
-  return root
+async function makeAdapterRoot(root = ""): Promise<string> {
+  const adapterRoot = root || (await mkdtemp(join(tmpdir(), "lfg-lazycodex-adapter.")))
+  await mkdir(join(adapterRoot, ".codex-plugin"), { recursive: true })
+  await mkdir(join(adapterRoot, "skills"), { recursive: true })
+  await writeFile(join(adapterRoot, ".codex-plugin", "plugin.json"), `${JSON.stringify({ name: "lazycodex", version: "0.1.0" })}\n`)
+  await writeFile(join(adapterRoot, ".mcp.json"), `${JSON.stringify({ mcpServers: {} })}\n`)
+  return adapterRoot
+}
+
+async function makeFakeNpx(exitCode: number): Promise<string> {
+  const bin = await mkdtemp(join(tmpdir(), "lfg-fake-npx."))
+  const body = exitCode === 0 ? "echo fake lazycodex install: $*" : "echo fake lazycodex failure: $* >&2"
+  await writeFile(join(bin, "npx"), `#!/usr/bin/env bash\n${body}\nexit ${exitCode}\n`)
+  await chmod(join(bin, "npx"), 0o755)
+  return bin
 }
diff --git a/plugins/lfg/bin/lfg.ts b/plugins/lfg/bin/lfg.ts
index d2512a7..b41b46e 100644
--- a/plugins/lfg/bin/lfg.ts
+++ b/plugins/lfg/bin/lfg.ts
@@ -1,20 +1,13 @@
 #!/usr/bin/env bun
-import { existsSync } from "node:fs"
 import { access, stat } from "node:fs/promises"
-import { homedir } from "node:os"
 import { join, resolve } from "node:path"
 import { commandPath, SUPPORTED_COMMANDS, unsupportedCommand } from "./lfg-command"
+import { detectLazycodexAdapter, grokSurfaces, grokVerificationCommands } from "./lfg-grok"
+import { LAZYCODEX_INSTALLER_COMMAND, runLazycodexInstaller } from "./lfg-installer"
 import { isRecord, readJson, readJsonObject, type JsonObject } from "./lfg-json"
 
 type LfgEnv = { readonly root: string; readonly data: string; readonly stateDir: string; readonly launcher: string }
-type ParsedArgs = { readonly json: boolean; readonly positional: readonly string[] }
-type LazycodexAdapter = {
-  readonly found: boolean
-  readonly root: string
-  readonly manifest: string
-  readonly mcpConfig: string
-  readonly skillsDir: string
-}
+type ParsedArgs = { readonly json: boolean; readonly run: boolean; readonly positional: readonly string[] }
 
 const STATE_SCHEMA_VERSION = 2
 
@@ -39,7 +32,7 @@ async function dispatch(args: ParsedArgs): Promise<unknown> {
   }
   if (command === "lazycodex") {
     if (!subcommand || subcommand === "status") return lazycodexStatus()
-    if (subcommand === "install") return lazycodexInstallPlan()
+    if (subcommand === "install") return args.run ? runLazycodexInstaller() : lazycodexInstallPlan()
   }
   if (command === "setup") {
     if (!subcommand || subcommand === "install-plan") return setupInstallPlan()
@@ -105,9 +98,11 @@ function lazycodexStatus(): JsonObject {
     role: "lazycodex_adapter_installer",
     adapterPackage: "lazycodex-ai",
     purpose: "Install lazycodex Codex adapter for grok-build",
-    primaryAction: "npx lazycodex-ai install",
+    primaryAction: LAZYCODEX_INSTALLER_COMMAND,
     grokBuildUse: true,
     lfgIsPlugin: false,
+    grokSurfaces: grokSurfaces(),
+    verificationCommands: grokVerificationCommands(),
     adapter: detectLazycodexAdapter(),
     install: lazycodexInstallPlan(),
   }
@@ -121,17 +116,20 @@ function lazycodexInstallPlan(): JsonObject {
     command: "lazycodex install",
     role: "lazycodex_adapter_installer",
     adapterPackage: "lazycodex-ai",
-    installerCommand: "npx lazycodex-ai install",
+    installerCommand: LAZYCODEX_INSTALLER_COMMAND,
+    executed: false,
     mutatesGlobalConfig: false,
     grokBuildUse: true,
     lfgIsPlugin: false,
     adapterRoot: adapter.root,
     adapterManifest: adapter.manifest,
+    grokSurfaces: grokSurfaces(),
+    verificationCommands: grokVerificationCommands(),
     adapter,
     steps: [
-      { id: "run_npm_installer", status: "pending", text: "Run npx lazycodex-ai install." },
-      { id: "use_lazycodex_adapter", status: "pending", text: `Use lazycodex adapter from ${adapter.root} when running grok-build.` },
-      { id: "verify_lazycodex_adapter", status: "pending", text: "Confirm the lazycodex adapter exposes .codex-plugin/plugin.json, .mcp.json, and skills/." },
+      { id: "run_npm_installer", status: "pending", text: `Run ${LAZYCODEX_INSTALLER_COMMAND}.` },
+      { id: "use_lazycodex_adapter", status: "pending", text: "Use lazycodex through Grok custom model, agent/persona, ACP, plugin, or MCP config surfaces when running grok-build." },
+      { id: "verify_lazycodex_adapter", status: "pending", text: "Confirm Grok can see lazycodex with grok models, grok inspect --json, and plugin commands where applicable." },
     ],
   }
 }
@@ -145,7 +143,7 @@ async function setupInstallPlan(): Promise<JsonObject> {
     updatedAt: utcNow(),
     purpose: "Install lazycodex Codex adapter for grok-build",
     steps: installSteps.map((step, index) => ({ id: index + 1, key: isRecord(step) ? step.id : undefined, status: isRecord(step) ? step.status : undefined, text: isRecord(step) ? step.text : undefined })),
-    lazycodex: { adapterPackage: install.adapterPackage, mutatesGlobalConfig: false, installerCommand: install.installerCommand, lfgIsPlugin: false, adapterRoot: install.adapterRoot },
+    lazycodex: { adapterPackage: install.adapterPackage, mutatesGlobalConfig: false, installerCommand: install.installerCommand, lfgIsPlugin: false, adapterRoot: install.adapterRoot, grokSurfaces: install.grokSurfaces },
   }
   return record
 }
@@ -181,8 +179,8 @@ function resolveLfgEnv(): LfgEnv {
 }
 
 function parseArgs(argv: readonly string[]): ParsedArgs {
-  const positional = argv.filter((arg) => arg !== "--json")
-  return { json: argv.includes("--json"), positional }
+  const positional = argv.filter((arg) => arg !== "--json" && arg !== "--run")
+  return { json: argv.includes("--json"), run: argv.includes("--run"), positional }
 }
 
 function emit(value: unknown, json: boolean): void {
@@ -201,24 +199,6 @@ function help(): string {
   return ["lfg - lazycodex Codex adapter installer", "", "Commands:", ...SUPPORTED_COMMANDS.map((command) => `  lfg ${command}`)].join("\n")
 }
 
-function detectLazycodexAdapter(): LazycodexAdapter {
-  const root = lazycodexAdapterRoot()
-  const manifest = join(root, ".codex-plugin", "plugin.json")
-  const mcpConfig = join(root, ".mcp.json")
-  const skillsDir = join(root, "skills")
-  return {
-    found: existsSync(manifest),
-    root,
-    manifest,
-    mcpConfig,
-    skillsDir,
-  }
-}
-
-function lazycodexAdapterRoot(): string {
-  return resolve(process.env.LAZYCODEX_ADAPTER_ROOT ?? join(homedir(), ".grok", "installed-plugins", "0-1-0-ff47fdd7"))
-}
-
 async function readPluginVersion(env: LfgEnv): Promise<string | null> {
   const manifest = await readJsonObject(join(env.root, "package.json"))
   return typeof manifest.version === "string" ? manifest.version : null
diff --git a/plugins/lfg/skills/lazycodex/SKILL.md b/plugins/lfg/skills/lazycodex/SKILL.md
index 8eee55b..b402265 100644
--- a/plugins/lfg/skills/lazycodex/SKILL.md
+++ b/plugins/lfg/skills/lazycodex/SKILL.md
@@ -15,12 +15,25 @@ The local helper commands are:
 
 ```sh
 lfg lazycodex install
+lfg lazycodex install --run
 lfg lazycodex status
 lfg setup install-plan
 ```
 
-The default adapter root for grok-build is:
+Use `lfg lazycodex install` for a non-mutating plan. Use `lfg lazycodex install --run` only when you want the helper to execute:
 
 ```sh
-~/.grok/installed-plugins/0-1-0-ff47fdd7
+npx lazycodex-ai install
 ```
+
+After installation, verify lazycodex through the Grok surfaces that apply to the installed adapter:
+
+```sh
+grok models
+grok inspect --json
+grok plugin list --json
+```
+
+Grok may expose lazycodex as a custom model in `~/.grok/config.toml`, an agent/persona under `~/.grok/agents` or `.grok/agents`, ACP mode through `grok agent stdio`, MCP config, or a plugin under `~/.grok/plugins`.
+
+Do not describe this helper as a Grok plugin. It also does not own a runtime.
