{
  "schemaVersion": 1,
  "updatedAt": "2026-10-15",
  "contracts": [
    {
      "harness": "claude-code",
      "surface": "hooks",
      "eventReference": {
        "urlTemplate": "https://code.claude.com/docs/en/hooks#{anchor}",
        "anchorTransform": "lowercase"
      },
      "configuration": [
        "~/.claude/settings.json",
        ".claude/settings.json",
        ".claude/settings.local.json",
        "managed settings",
        "plugin hooks/hooks.json",
        "skill frontmatter",
        "subagent frontmatter",
        "plugin.json hooks key"
      ],
      "evidence": ["claude-hooks-docs"],
      "events": [
        {
          "name": "SessionStart",
          "phase": "session.start",
          "control": ["context", "environment"],
          "notes": ["Only command and mcp_tool handlers run, and mcp_tool is skipped at launch."]
        },
        {
          "name": "Setup",
          "phase": "session.setup",
          "control": ["environment"],
          "notes": [
            "Fires only with --init-only, or --init/--maintenance in -p mode; JSON output, including additionalContext, is discarded.",
            "Only command and mcp_tool handlers run, and mcp_tool is skipped."
          ]
        },
        {
          "name": "InstructionsLoaded",
          "phase": "context.instructions",
          "control": ["observe"]
        },
        {
          "name": "UserPromptSubmit",
          "phase": "prompt.before",
          "control": ["block", "context"]
        },
        {
          "name": "UserPromptExpansion",
          "phase": "prompt.expansion.before",
          "control": ["block", "context"]
        },
        {
          "name": "MessageDisplay",
          "phase": "message.display",
          "control": ["mutate"],
          "notes": [
            "displayContent changes only what is shown on screen; the transcript and what Claude sees keep the original."
          ]
        },
        {
          "name": "PreToolUse",
          "phase": "tool.before",
          "control": ["allow", "deny", "ask", "defer", "mutate", "context"],
          "notes": [
            "defer works only in -p mode and for a single tool call per turn.",
            "A hook that times out does not block unless the handler sets onFailure: \"block\"."
          ],
          "reference": "https://code.claude.com/docs/en/hooks#pretooluse-input"
        },
        {
          "name": "PermissionRequest",
          "phase": "permission.request",
          "control": ["allow", "deny", "mutate", "permission-update", "stop"],
          "notes": [
            "Exit code 2 is not honoured; deny with decision.behavior. updatedInput applies only when allowing."
          ],
          "reference": "https://code.claude.com/docs/en/hooks#permissionrequest-input"
        },
        {
          "name": "PermissionDenied",
          "phase": "permission.denied",
          "control": ["retry"],
          "notes": ["Fires only in auto mode; retry is ignored for denials without a verdict."]
        },
        {
          "name": "PostToolUse",
          "phase": "tool.after.success",
          "control": ["context", "mutate", "annotate"],
          "notes": [
            "decision: \"block\" does not undo the tool; it adds the reason next to the result.",
            "updatedToolOutput and updatedMCPToolOutput replace the output Claude sees."
          ]
        },
        {
          "name": "PostToolUseFailure",
          "phase": "tool.after.failure",
          "control": ["context"]
        },
        {
          "name": "PostToolBatch",
          "phase": "tool.batch.after",
          "control": ["context", "stop"]
        },
        {
          "name": "Notification",
          "phase": "notification",
          "control": ["observe"]
        },
        {
          "name": "SubagentStart",
          "phase": "subagent.start",
          "control": ["context"]
        },
        {
          "name": "SubagentStop",
          "phase": "subagent.stop",
          "control": ["block", "context"]
        },
        {
          "name": "TaskCreated",
          "phase": "task.create",
          "control": ["block"]
        },
        {
          "name": "TaskCompleted",
          "phase": "task.complete",
          "control": ["block", "stop"]
        },
        {
          "name": "Stop",
          "phase": "turn.stop",
          "control": ["block", "context"]
        },
        {
          "name": "StopFailure",
          "phase": "turn.failure",
          "control": ["observe"]
        },
        {
          "name": "TeammateIdle",
          "phase": "teammate.idle",
          "control": ["block", "stop"]
        },
        {
          "name": "ConfigChange",
          "phase": "config.change",
          "control": ["block"],
          "notes": ["Changes to policy settings cannot be blocked."]
        },
        {
          "name": "CwdChanged",
          "phase": "cwd.change",
          "control": ["environment"],
          "notes": [
            "No matcher. Variables written to CLAUDE_ENV_FILE are cleared at the next CwdChanged."
          ]
        },
        {
          "name": "DirectoryAdded",
          "phase": "workspace.directory.add",
          "control": ["context"],
          "notes": [
            "For /add-dir the hook's systemMessage reaches Claude as context on the next turn; for repository-root registration it only reaches the debug log."
          ]
        },
        {
          "name": "FileChanged",
          "phase": "file.change",
          "control": ["environment"]
        },
        {
          "name": "WorktreeCreate",
          "phase": "worktree.create",
          "control": ["delegate"],
          "notes": [
            "Provider operation: the hook creates the worktree and returns its path (command hooks on stdout, HTTP hooks in hookSpecificOutput.worktreePath)."
          ]
        },
        {
          "name": "WorktreeRemove",
          "phase": "worktree.remove",
          "control": ["delegate"],
          "notes": [
            "Provider operation: the hook performs removal; this is not a notification hook.",
            "Fires only for worktrees a WorktreeCreate hook created."
          ]
        },
        {
          "name": "PreCompact",
          "phase": "compaction.before",
          "control": ["block"]
        },
        {
          "name": "PostCompact",
          "phase": "compaction.after",
          "control": ["observe"]
        },
        {
          "name": "Elicitation",
          "phase": "mcp.elicitation.before",
          "control": ["handle", "deny", "cancel"]
        },
        {
          "name": "ElicitationResult",
          "phase": "mcp.elicitation.after",
          "control": ["mutate", "deny", "cancel"]
        },
        {
          "name": "PreModelSwitch",
          "phase": "model.switch.before",
          "control": ["allow", "deny", "ask"],
          "notes": [
            "Runs only for switches a user or client requested (/model, the model picker, /config, fast mode, SDK set_model); automatic fallback and resume restores reach PostModelSwitch only.",
            "The matcher is compared against the canonical target model name; when no canonical name resolves, every PreModelSwitch hook runs regardless of matcher.",
            "A hook timeout blocks the switch, unlike PreToolUse. Outside interactive /model, ask is treated as a refusal."
          ]
        },
        {
          "name": "PostModelSwitch",
          "phase": "model.switch.after",
          "control": ["context"],
          "notes": [
            "Also runs for automatic fallback, opusplan plan-mode transitions, and model restoration on resume, but not for a one-turn fallback-chain substitution.",
            "Cannot block. Output is delivered with the next request; only the last switch's output is delivered when several switches precede that request."
          ]
        },
        {
          "name": "SessionEnd",
          "phase": "session.end",
          "control": ["observe"]
        }
      ],
      "handlerTypes": [
        {
          "type": "command",
          "support": "supported"
        },
        {
          "type": "http",
          "support": "supported"
        },
        {
          "type": "mcp_tool",
          "support": "supported"
        },
        {
          "type": "prompt",
          "support": "supported",
          "notes": ["Only for tool, permission, prompt, stop and task events."]
        },
        {
          "type": "agent",
          "support": "experimental"
        }
      ],
      "notes": [
        "onFailure: \"block\" on a command or HTTP hook makes a failed or timed-out hook block the action (2.1.295 and later).",
        "Plugin mods are a separate JavaScript hook surface with their own events and are not recorded here."
      ]
    },
    {
      "harness": "codex",
      "surface": "hooks",
      "eventReference": {
        "urlTemplate": "https://learn.chatgpt.com/docs/hooks#{anchor}",
        "anchorTransform": "lowercase"
      },
      "configuration": [
        "~/.codex/hooks.json",
        "~/.codex/config.toml",
        "<repo>/.codex/hooks.json",
        "<repo>/.codex/config.toml",
        "managed requirements.toml",
        "plugin hooks/hooks.json or .codex-plugin/plugin.json hooks"
      ],
      "evidence": [
        "codex-hooks-docs",
        "codex-hooks-events-0-162-1",
        "codex-hooks-output-0-162-1",
        "codex-hooks-handlers-0-162-1"
      ],
      "events": [
        {
          "name": "SessionStart",
          "phase": "session.start",
          "control": ["context", "stop"]
        },
        {
          "name": "SessionEnd",
          "phase": "session.end",
          "control": ["observe"],
          "notes": ["Main thread only; advisory and always synchronous."]
        },
        {
          "name": "UserPromptSubmit",
          "phase": "prompt.before",
          "control": ["block", "context"]
        },
        {
          "name": "PreToolUse",
          "phase": "tool.before",
          "control": ["deny", "mutate", "context"],
          "notes": [
            "permissionDecision ask, and allow without updatedInput, fail the hook run; the tool call proceeds.",
            "Covers shell, apply_patch, MCP and local function tools, not hosted tools such as web search."
          ]
        },
        {
          "name": "PermissionRequest",
          "phase": "permission.request",
          "control": ["allow", "deny"],
          "notes": ["Any deny wins. updatedInput, updatedPermissions and interrupt fail closed."]
        },
        {
          "name": "PostToolUse",
          "phase": "tool.after.success",
          "control": ["replace", "context"],
          "notes": [
            "decision: \"block\" or continue: false replaces the tool result with the feedback and continues; side effects are not undone.",
            "Also runs after shell commands that exit non-zero."
          ]
        },
        {
          "name": "PreCompact",
          "phase": "compaction.before",
          "control": ["stop"],
          "notes": ["continue: false ends the turn before compacting."]
        },
        {
          "name": "PostCompact",
          "phase": "compaction.after",
          "control": ["stop"],
          "notes": ["continue: false ends the turn after compacting."]
        },
        {
          "name": "SubagentStart",
          "phase": "subagent.start",
          "control": ["context"]
        },
        {
          "name": "SubagentStop",
          "phase": "subagent.stop",
          "control": ["followup", "stop"]
        },
        {
          "name": "Stop",
          "phase": "turn.stop",
          "control": ["followup", "stop"],
          "notes": [
            "decision: \"block\" queues a continuation prompt; continue: false from any hook takes precedence."
          ]
        },
        {
          "name": "Interrupt",
          "phase": "turn.interrupt",
          "control": ["observe"],
          "evidence": ["codex-hooks-interrupt-source"],
          "notes": [
            "Runs when you interrupt an active turn on the main thread; not for subagents. The matcher is ignored.",
            "Can only emit a system message; it cannot prevent or reverse the interruption."
          ]
        }
      ],
      "notes": [
        "Matching hooks are launched concurrently, so one hook cannot stop another from starting.",
        "Project hooks load only in a trusted project, and every non-managed hook must also be reviewed and trusted by its hash.",
        "Background (async) hooks cannot block, approve or rewrite the triggering operation.",
        "OpenAI describes tool hooks as a guardrail, not a complete enforcement boundary."
      ],
      "handlerTypes": [
        {
          "type": "command",
          "support": "supported"
        },
        {
          "type": "mcp_tool",
          "support": "supported"
        },
        {
          "type": "prompt",
          "support": "skipped"
        },
        {
          "type": "agent",
          "support": "skipped"
        }
      ]
    },
    {
      "harness": "cursor-agent",
      "surface": "hooks",
      "eventReference": {
        "urlTemplate": "https://cursor.com/docs/hooks#{anchor}",
        "anchorTransform": "lowercase"
      },
      "configuration": [
        "~/.cursor/hooks.json",
        "<project>/.cursor/hooks.json",
        "enterprise hooks.json (/Library/Application Support/Cursor, /etc/cursor, C:\\ProgramData\\Cursor)",
        "team hooks (dashboard)",
        "plugin hooks/hooks.json or .cursor-plugin/plugin.json hooks",
        "Claude Code settings.json hooks (third-party configs, on by default)",
        "self-hosted worker --on-session-start / --on-session-end"
      ],
      "evidence": ["cursor-hooks-docs"],
      "events": [
        {
          "name": "sessionStart",
          "phase": "session.start",
          "control": ["context", "environment"],
          "notes": ["Fire-and-forget; continue:false does not block session creation."]
        },
        {
          "name": "sessionEnd",
          "phase": "session.end",
          "control": ["observe"]
        },
        {
          "name": "workspaceOpen",
          "phase": "workspace.open",
          "control": ["extend"],
          "notes": ["Returns pluginPaths to load; fires on every workspace folder change."]
        },
        {
          "name": "beforeSubmitPrompt",
          "phase": "prompt.before",
          "control": ["block"],
          "notes": [
            "Cursor's 2.4 changelog mentions modifying prompts, but the hooks reference documents no output field for it."
          ]
        },
        {
          "name": "preToolUse",
          "phase": "tool.before",
          "control": ["allow", "deny", "mutate"],
          "notes": ["ask is accepted by the schema but not enforced for preToolUse."]
        },
        {
          "name": "postToolUse",
          "phase": "tool.after.success",
          "control": ["context", "mutate"],
          "notes": ["Output can be replaced only for MCP tools."]
        },
        {
          "name": "postToolUseFailure",
          "phase": "tool.after.failure",
          "control": ["context"],
          "notes": ["Also fires on timeouts and permission denials."]
        },
        {
          "name": "beforeShellExecution",
          "phase": "shell.before",
          "control": ["allow", "deny", "ask"],
          "reference": "https://cursor.com/docs/hooks#beforeshellexecution-beforemcpexecution"
        },
        {
          "name": "afterShellExecution",
          "phase": "shell.after",
          "control": ["observe"]
        },
        {
          "name": "beforeMCPExecution",
          "phase": "mcp.before",
          "control": ["allow", "deny", "ask"],
          "notes": ["Cursor recommends failClosed: true for security-critical MCP hooks."],
          "reference": "https://cursor.com/docs/hooks#beforeshellexecution-beforemcpexecution"
        },
        {
          "name": "afterMCPExecution",
          "phase": "mcp.after",
          "control": ["observe"]
        },
        {
          "name": "beforeReadFile",
          "phase": "file.read.before",
          "control": ["allow", "deny"]
        },
        {
          "name": "afterFileEdit",
          "phase": "file.edit.after",
          "control": ["observe"]
        },
        {
          "name": "beforeTabFileRead",
          "phase": "tab.file.read.before",
          "control": ["allow", "deny"],
          "notes": ["Tab completions only, not the agent."]
        },
        {
          "name": "afterTabFileEdit",
          "phase": "tab.file.edit.after",
          "control": ["observe"],
          "notes": ["Tab completions only, not the agent."]
        },
        {
          "name": "subagentStart",
          "phase": "subagent.start",
          "control": ["allow", "deny"],
          "notes": ["ask is treated as deny."]
        },
        {
          "name": "subagentStop",
          "phase": "subagent.stop",
          "control": ["followup"],
          "notes": ["The follow-up is used only when the subagent completed."]
        },
        {
          "name": "preCompact",
          "phase": "compaction.before",
          "control": ["observe"],
          "notes": ["Cannot block or modify compaction; can show a message to the user."]
        },
        {
          "name": "afterAgentResponse",
          "phase": "agent.response.after",
          "control": ["observe"]
        },
        {
          "name": "afterAgentThought",
          "phase": "agent.thought.after",
          "control": ["observe"]
        },
        {
          "name": "stop",
          "phase": "turn.stop",
          "control": ["followup"],
          "notes": ["loop_limit caps follow-ups (default 5)."]
        }
      ],
      "notes": [
        "Permission hooks block when output is invalid JSON or does not match the schema; crashes, timeouts and other exit codes fail open unless the hook sets failClosed: true.",
        "When several hooks answer, deny beats ask and ask beats allow.",
        "Sources run in priority order enterprise, team, project, user; project hooks run only in trusted workspaces.",
        "Cloud agents run only command hooks and skip sessionStart, sessionEnd, workspaceOpen, MCP and Tab hooks; no hooks run during early read-only turns."
      ],
      "handlerTypes": [
        {
          "type": "command",
          "support": "supported"
        },
        {
          "type": "prompt",
          "support": "supported",
          "notes": ["Not run by cloud agents or self-hosted workers."]
        }
      ]
    },
    {
      "harness": "opencode",
      "surface": "plugin-events",
      "eventReference": {
        "urlTemplate": "https://opencode.ai/docs/plugins/#{anchor}",
        "groups": {
          "command.": "command-events",
          "file.": "file-events",
          "installation.": "installation-events",
          "lsp.": "lsp-events",
          "message.": "message-events",
          "permission.": "permission-events",
          "server.": "server-events",
          "session.": "session-events",
          "shell.": "shell-events",
          "tool.": "tool-events",
          "tui.": "tui-events"
        }
      },
      "configuration": [
        "~/.config/opencode/opencode.json plugin",
        "<project>/opencode.json plugin",
        "~/.config/opencode/plugins (or plugin)",
        ".opencode/plugins (or plugin)"
      ],
      "evidence": [
        "opencode-plugins-docs",
        "opencode-plugin-tests",
        "opencode-1-19-0-plugin-hooks",
        "opencode-1-19-0-events",
        "opencode-1-19-0-plugin-event-filter"
      ],
      "events": [
        {
          "name": "command.executed",
          "phase": "command.after",
          "control": ["observe"]
        },
        {
          "name": "file.edited",
          "phase": "file.edit.after",
          "control": ["observe"]
        },
        {
          "name": "file.watcher.updated",
          "phase": "file.watch.update",
          "control": ["observe"]
        },
        {
          "name": "installation.updated",
          "phase": "installation.update",
          "control": ["observe"],
          "notes": ["Source suggests it is not delivered to plugin event handlers."]
        },
        {
          "name": "lsp.client.diagnostics",
          "phase": "lsp.diagnostics",
          "control": ["observe"],
          "notes": ["Listed in the docs, but 1.19.0 never emits it."],
          "availability": "documented-not-emitted"
        },
        {
          "name": "lsp.updated",
          "phase": "lsp.update",
          "control": ["observe"]
        },
        {
          "name": "message.part.removed",
          "phase": "message.part.remove",
          "control": ["observe"]
        },
        {
          "name": "message.part.updated",
          "phase": "message.part.update",
          "control": ["observe"]
        },
        {
          "name": "message.removed",
          "phase": "message.remove",
          "control": ["observe"]
        },
        {
          "name": "message.updated",
          "phase": "message.update",
          "control": ["observe"]
        },
        {
          "name": "permission.asked",
          "phase": "permission.request",
          "control": ["observe"]
        },
        {
          "name": "permission.replied",
          "phase": "permission.reply",
          "control": ["observe"]
        },
        {
          "name": "server.connected",
          "phase": "server.connect",
          "control": ["observe"],
          "notes": ["Source suggests it is not delivered to plugin event handlers."]
        },
        {
          "name": "session.created",
          "phase": "session.start",
          "control": ["observe"]
        },
        {
          "name": "session.compacted",
          "phase": "compaction.after",
          "control": ["observe"]
        },
        {
          "name": "session.deleted",
          "phase": "session.delete",
          "control": ["observe"]
        },
        {
          "name": "session.diff",
          "phase": "session.diff",
          "control": ["observe"]
        },
        {
          "name": "session.error",
          "phase": "session.error",
          "control": ["observe"]
        },
        {
          "name": "session.idle",
          "phase": "session.idle",
          "control": ["observe"],
          "notes": ["Deprecated in favour of session.status."]
        },
        {
          "name": "session.status",
          "phase": "session.status",
          "control": ["observe"]
        },
        {
          "name": "session.updated",
          "phase": "session.update",
          "control": ["observe"]
        },
        {
          "name": "todo.updated",
          "phase": "todo.update",
          "control": ["observe"],
          "notes": ["Still emitted by 1.19.0 but no longer on the live docs page."],
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6845"
        },
        {
          "name": "shell.env",
          "phase": "shell.environment",
          "control": ["environment"],
          "notes": ["A named hook function, not a bus event."]
        },
        {
          "name": "tool.execute.before",
          "phase": "tool.before",
          "control": ["mutate", "block"],
          "notes": ["A named hook function, not a bus event."]
        },
        {
          "name": "tool.execute.after",
          "phase": "tool.after",
          "control": ["mutate"],
          "notes": ["A named hook function, not a bus event."]
        },
        {
          "name": "tui.prompt.append",
          "phase": "tui.prompt",
          "control": ["observe"]
        },
        {
          "name": "tui.command.execute",
          "phase": "tui.command",
          "control": ["observe"]
        },
        {
          "name": "tui.toast.show",
          "phase": "tui.toast",
          "control": ["observe"]
        },
        {
          "name": "chat.message",
          "phase": "prompt.before",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/plugin/src/index.ts#L234",
          "notes": ["Can change the incoming message and its parts."]
        },
        {
          "name": "chat.params",
          "phase": "provider.request.before",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/plugin/src/index.ts#L247",
          "notes": ["Temperature, topP, topK, max tokens and provider options."]
        },
        {
          "name": "chat.headers",
          "phase": "provider.headers.before",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/plugin/src/index.ts#L257"
        },
        {
          "name": "command.execute.before",
          "phase": "prompt.expansion.before",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/plugin/src/index.ts#L262",
          "notes": ["Can change the parts a command sends."]
        },
        {
          "name": "tool.definition",
          "phase": "tool.definition",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/plugin/src/index.ts#L334",
          "notes": ["Changes the description and parameters sent to the model."]
        },
        {
          "name": "permission.ask",
          "phase": "permission.request",
          "control": ["allow", "deny", "ask"],
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/plugin/src/index.ts#L261",
          "availability": "declared-not-triggered",
          "notes": ["Declared in the plugin API but never called in 1.19.0."]
        },
        {
          "name": "experimental.chat.messages.transform",
          "phase": "model.context.before",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/plugin/src/index.ts#L282",
          "notes": ["Experimental."]
        },
        {
          "name": "experimental.chat.system.transform",
          "phase": "system.prompt.build",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/plugin/src/index.ts#L291",
          "notes": ["Experimental."]
        },
        {
          "name": "experimental.session.compacting",
          "phase": "compaction.before",
          "control": ["context", "replace"],
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/plugin/src/index.ts#L305",
          "notes": ["Experimental.", "Can add context to, or replace, the compaction prompt."]
        },
        {
          "name": "experimental.compaction.autocontinue",
          "phase": "compaction.after",
          "control": ["decision"],
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/plugin/src/index.ts#L316",
          "notes": ["Experimental.", "enabled: false skips the automatic continue turn."]
        },
        {
          "name": "experimental.text.complete",
          "phase": "message.text.end",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/plugin/src/index.ts#L327",
          "notes": ["Experimental.", "Runs once per completed text part."]
        },
        {
          "name": "experimental.provider.small_model",
          "phase": "model.select",
          "control": ["replace"],
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/plugin/src/index.ts#L297",
          "notes": ["Experimental.", "Chooses the small model."]
        },
        {
          "name": "config",
          "phase": "config.load",
          "control": ["observe"],
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/plugin/src/index.ts#L225",
          "notes": ["Receives the loaded configuration."]
        },
        {
          "name": "dispose",
          "phase": "plugin.dispose",
          "control": ["observe"],
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/plugin/src/index.ts#L223",
          "notes": ["Added in 1.15.11."]
        },
        {
          "name": "catalog.updated",
          "phase": "catalog.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6181"
        },
        {
          "name": "global.disposed",
          "phase": "server.shutdown",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L7050"
        },
        {
          "name": "installation.update-available",
          "phase": "installation.available",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6704"
        },
        {
          "name": "integration.connection.updated",
          "phase": "integration.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6173"
        },
        {
          "name": "integration.updated",
          "phase": "integration.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6165"
        },
        {
          "name": "mcp.browser.open.failed",
          "phase": "mcp.auth.failure",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6899"
        },
        {
          "name": "mcp.tools.changed",
          "phase": "mcp.tools.change",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6891"
        },
        {
          "name": "message.part.delta",
          "phase": "message.part.delta",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6658"
        },
        {
          "name": "models-dev.refreshed",
          "phase": "catalog.refresh",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6157"
        },
        {
          "name": "permission.v2.asked",
          "phase": "permission.request",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6728"
        },
        {
          "name": "permission.v2.replied",
          "phase": "permission.reply",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6744"
        },
        {
          "name": "plugin.added",
          "phase": "plugin.add",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6754"
        },
        {
          "name": "project.directories.updated",
          "phase": "project.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6762"
        },
        {
          "name": "project.updated",
          "phase": "project.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6919"
        },
        {
          "name": "pty.created",
          "phase": "pty.create",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6779"
        },
        {
          "name": "pty.deleted",
          "phase": "pty.delete",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6804"
        },
        {
          "name": "pty.exited",
          "phase": "pty.exit",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6795"
        },
        {
          "name": "pty.updated",
          "phase": "pty.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6787"
        },
        {
          "name": "question.asked",
          "phase": "question.ask",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6951"
        },
        {
          "name": "question.rejected",
          "phase": "question.reject",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6975"
        },
        {
          "name": "question.replied",
          "phase": "question.reply",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6965"
        },
        {
          "name": "question.v2.asked",
          "phase": "question.ask",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6812"
        },
        {
          "name": "question.v2.rejected",
          "phase": "question.reject",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6836"
        },
        {
          "name": "question.v2.replied",
          "phase": "question.reply",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6826"
        },
        {
          "name": "reference.updated",
          "phase": "reference.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6720"
        },
        {
          "name": "server.instance.disposed",
          "phase": "server.shutdown",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L3189"
        },
        {
          "name": "tui.session.select",
          "phase": "tui.session.select",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L3011"
        },
        {
          "name": "vcs.branch.updated",
          "phase": "vcs.branch.change",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L6992"
        },
        {
          "name": "workspace.failed",
          "phase": "workspace.failure",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L7008"
        },
        {
          "name": "workspace.ready",
          "phase": "workspace.open",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L7000"
        },
        {
          "name": "workspace.status",
          "phase": "workspace.status",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L7016"
        },
        {
          "name": "worktree.failed",
          "phase": "worktree.failure",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L7034"
        },
        {
          "name": "worktree.ready",
          "phase": "worktree.create",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/sdk/js/src/v2/gen/types.gen.ts#L7025"
        }
      ],
      "notes": [
        "opencode-ai 1.x, checked at 1.19.0. Plugins are in-process functions returning named hooks plus an event handler for bus events.",
        "Named hooks receive (input, output) and change behaviour by mutating output; throwing from a hook makes the operation fail.",
        "The event handler only receives events for the plugin's own directory. The 1.x session.next.* engine events are not recorded."
      ],
      "variant": "1.x",
      "default": false
    },
    {
      "harness": "opencode",
      "variant": "2.x",
      "default": true,
      "surface": "plugin-hooks",
      "configuration": [
        "~/.config/opencode/opencode.jsonc plugins",
        "./opencode.jsonc plugins",
        "./.opencode/opencode.jsonc plugins",
        ".opencode/plugins (or plugin)",
        "~/.config/opencode/plugins",
        "cli.json (CLI-only plugins)"
      ],
      "evidence": [
        "opencode-v2-plugins-docs",
        "opencode-2-0-29-session-hooks",
        "opencode-2-0-29-events"
      ],
      "eventReference": {
        "urlTemplate": "https://opencode.ai/v2/docs/build/plugins/#{anchor}",
        "anchorTransform": "identity"
      },
      "notes": [
        "@opencode/cli 2.x, checked at 2.0.28. 1.x plugins do not run in 2.x.",
        "Plugins register hooks per domain with ctx.<domain>.hook(name, callback); each callback receives one mutable event. Hooks run in plugin order.",
        "Transforms are synchronous edits to registered definitions, replayed in registration order.",
        "Events are read with ctx.event.subscribe() and can only be observed."
      ],
      "events": [
        {
          "name": "session.prompt",
          "phase": "prompt.before",
          "control": ["mutate", "block"],
          "reference": "https://opencode.ai/v2/docs/build/plugins/#prompt-admission",
          "notes": ["Throwing stops prompt admission."]
        },
        {
          "name": "session.context",
          "phase": "model.context.before",
          "control": ["mutate"],
          "reference": "https://opencode.ai/v2/docs/build/plugins/#model-requests",
          "notes": ["System prompt, messages, tools and options for agent requests."]
        },
        {
          "name": "session.compaction",
          "phase": "compaction.before",
          "control": ["mutate", "replace"],
          "reference": "https://opencode.ai/v2/docs/build/plugins/#hooks",
          "notes": ["Setting result skips the model call."]
        },
        {
          "name": "session.generate",
          "phase": "provider.request.before",
          "control": ["mutate", "replace"],
          "reference": "https://opencode.ai/v2/docs/build/plugins/#model-requests"
        },
        {
          "name": "session.title",
          "phase": "session.info.change",
          "control": ["mutate", "replace"],
          "reference": "https://opencode.ai/v2/docs/build/plugins/#model-requests",
          "notes": ["Setting result supplies the title."]
        },
        {
          "name": "session.model.request",
          "phase": "provider.headers.before",
          "control": ["mutate"],
          "reference": "https://opencode.ai/v2/docs/build/plugins/#model-requests",
          "notes": ["Headers and raw settings; can be scoped to one provider."]
        },
        {
          "name": "session.http.request",
          "phase": "provider.request.before",
          "control": ["mutate", "replace"],
          "reference": "https://opencode.ai/v2/docs/build/plugins/#native-http"
        },
        {
          "name": "session.http.response",
          "phase": "provider.response.after",
          "control": ["mutate", "replace"],
          "reference": "https://opencode.ai/v2/docs/build/plugins/#native-http"
        },
        {
          "name": "session.experimental.ws.handshake",
          "phase": "provider.request.before",
          "control": ["mutate"],
          "reference": "https://opencode.ai/v2/docs/build/plugins/#native-http",
          "notes": ["Experimental."]
        },
        {
          "name": "session.experimental.ws.send",
          "phase": "provider.request.before",
          "control": ["mutate"],
          "reference": "https://opencode.ai/v2/docs/build/plugins/#native-http",
          "notes": ["Experimental."]
        },
        {
          "name": "session.experimental.ws.receive",
          "phase": "provider.response.after",
          "control": ["mutate"],
          "reference": "https://opencode.ai/v2/docs/build/plugins/#native-http",
          "notes": ["Experimental."]
        },
        {
          "name": "session.retry",
          "phase": "turn.retry",
          "control": ["retry", "decision"],
          "reference": "https://opencode.ai/v2/docs/build/plugins/#retry-policy",
          "notes": ["Overrides the retry decision for a provider failure."]
        },
        {
          "name": "permission.evaluate",
          "phase": "permission.request",
          "control": ["allow", "deny", "ask", "annotate"],
          "reference": "https://opencode.ai/v2/docs/build/plugins/#permissions-1",
          "notes": ["An explicitly configured deny is final and does not invoke the hook."]
        },
        {
          "name": "shell.create.before",
          "phase": "shell.before",
          "control": ["mutate", "environment"],
          "reference": "https://opencode.ai/v2/docs/build/plugins/#shell",
          "notes": ["Can change the command, working directory, timeout, shell and environment."]
        },
        {
          "name": "tool.execute.before",
          "phase": "tool.before",
          "control": ["mutate", "block"],
          "reference": "https://opencode.ai/v2/docs/build/plugins/#tools-1",
          "notes": ["Throwing blocks the tool."]
        },
        {
          "name": "tool.execute.after",
          "phase": "tool.after",
          "control": ["mutate"],
          "reference": "https://opencode.ai/v2/docs/build/plugins/#tools-1",
          "notes": ["Receives completed or error status."]
        },
        {
          "name": "aisdk.sdk",
          "phase": "provider.request.before",
          "control": ["replace"],
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/plugin/src/promise/aisdk.ts#L5-L18",
          "availability": "source-only",
          "notes": ["Supplies the AI SDK provider instance."]
        },
        {
          "name": "aisdk.language",
          "phase": "provider.request.before",
          "control": ["replace"],
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/plugin/src/promise/aisdk.ts#L5-L18",
          "availability": "source-only",
          "notes": ["Supplies the language model instance."]
        },
        {
          "name": "agent.transform",
          "phase": "agent.definition",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/plugin/src/promise/agent.ts#L15",
          "availability": "source-only"
        },
        {
          "name": "command.transform",
          "phase": "command.definition",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/plugin/src/promise/command.ts#L24",
          "availability": "source-only"
        },
        {
          "name": "integration.transform",
          "phase": "integration.definition",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/plugin/src/promise/integration.ts#L95",
          "availability": "source-only"
        },
        {
          "name": "mcp.transform",
          "phase": "mcp.definition",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/plugin/src/promise/mcp.ts#L15",
          "availability": "source-only"
        },
        {
          "name": "model.transform",
          "phase": "model.definition",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/plugin/src/promise/model.ts#L26"
        },
        {
          "name": "provider.transform",
          "phase": "provider.definition",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/plugin/src/promise/provider.ts#L31"
        },
        {
          "name": "reference.transform",
          "phase": "reference.definition",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/plugin/src/promise/reference.ts#L13",
          "availability": "source-only"
        },
        {
          "name": "skill.transform",
          "phase": "skill.definition",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/plugin/src/promise/skill.ts#L15",
          "availability": "source-only"
        },
        {
          "name": "tool.transform",
          "phase": "tool.definition",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/plugin/src/promise/tool.ts#L67",
          "availability": "source-only"
        },
        {
          "name": "websearch.transform",
          "phase": "websearch.definition",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/plugin/src/promise/websearch.ts#L15",
          "availability": "source-only"
        },
        {
          "name": "worktree.transform",
          "phase": "worktree.definition",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/plugin/src/promise/worktree.ts#L21",
          "availability": "source-only"
        },
        {
          "name": "vcs.transform",
          "phase": "vcs.definition",
          "control": ["mutate"],
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/plugin/src/promise/vcs.ts#L37",
          "availability": "source-only"
        },
        {
          "name": "location.shutdown",
          "phase": "server.shutdown",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1410"
        },
        {
          "name": "models-dev.refreshed",
          "phase": "catalog.refresh",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1419"
        },
        {
          "name": "credential.updated",
          "phase": "credential.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1428"
        },
        {
          "name": "credential.switched",
          "phase": "credential.switch",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1437"
        },
        {
          "name": "integration.updated",
          "phase": "integration.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1446"
        },
        {
          "name": "provider.updated",
          "phase": "provider.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1455"
        },
        {
          "name": "model.updated",
          "phase": "model.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1464"
        },
        {
          "name": "agent.updated",
          "phase": "agent.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1473"
        },
        {
          "name": "session.created",
          "phase": "session.start",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L2110"
        },
        {
          "name": "session.agent.selected",
          "phase": "agent.select",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L953"
        },
        {
          "name": "session.model.selected",
          "phase": "model.select",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L963"
        },
        {
          "name": "session.moved",
          "phase": "session.move",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L973"
        },
        {
          "name": "session.renamed",
          "phase": "session.info.change",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L983"
        },
        {
          "name": "session.metadata.updated",
          "phase": "session.info.change",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L993"
        },
        {
          "name": "session.permissions",
          "phase": "permission.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L2133"
        },
        {
          "name": "session.viewed",
          "phase": "session.view",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1003"
        },
        {
          "name": "session.usage.updated",
          "phase": "usage.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1482"
        },
        {
          "name": "session.deleted",
          "phase": "session.delete",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1013"
        },
        {
          "name": "session.forked",
          "phase": "session.fork.after",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1023"
        },
        {
          "name": "session.inbox.delivered",
          "phase": "inbox.deliver",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1039"
        },
        {
          "name": "session.inbox.enqueued",
          "phase": "inbox.enqueue",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L2403"
        },
        {
          "name": "session.inbox.cancelled",
          "phase": "inbox.cancel",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1051"
        },
        {
          "name": "session.inbox.delivery.changed",
          "phase": "inbox.delivery.change",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1061"
        },
        {
          "name": "session.execution.started",
          "phase": "agent.start",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1071"
        },
        {
          "name": "session.execution.succeeded",
          "phase": "agent.end",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1081"
        },
        {
          "name": "session.execution.failed",
          "phase": "turn.failure",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1091"
        },
        {
          "name": "session.execution.interrupted",
          "phase": "turn.interrupt",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1101"
        },
        {
          "name": "session.instructions.updated",
          "phase": "context.instructions",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1111"
        },
        {
          "name": "session.synthetic",
          "phase": "message.synthetic",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1121"
        },
        {
          "name": "session.skill.activated",
          "phase": "skill.activate",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1131"
        },
        {
          "name": "session.shell.started",
          "phase": "shell.start",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1141"
        },
        {
          "name": "session.shell.ended",
          "phase": "shell.after",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1151"
        },
        {
          "name": "session.step.started",
          "phase": "step.start",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1165"
        },
        {
          "name": "session.step.streamed",
          "phase": "step.stream",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1182"
        },
        {
          "name": "session.step.ended",
          "phase": "step.end",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1192"
        },
        {
          "name": "session.step.failed",
          "phase": "step.failure",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1212"
        },
        {
          "name": "session.text.started",
          "phase": "message.text.start",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1233"
        },
        {
          "name": "session.text.delta",
          "phase": "message.text.delta",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1491"
        },
        {
          "name": "session.text.ended",
          "phase": "message.text.end",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1243"
        },
        {
          "name": "session.reasoning.started",
          "phase": "reasoning.start",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1259"
        },
        {
          "name": "session.reasoning.delta",
          "phase": "reasoning.delta",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1500"
        },
        {
          "name": "session.reasoning.ended",
          "phase": "reasoning.end",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1274"
        },
        {
          "name": "session.tool.input.started",
          "phase": "tool.input.start",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1290"
        },
        {
          "name": "session.tool.input.delta",
          "phase": "tool.input.delta",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1509"
        },
        {
          "name": "session.tool.input.ended",
          "phase": "tool.input.end",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1300"
        },
        {
          "name": "session.tool.called",
          "phase": "tool.execution.start",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1310"
        },
        {
          "name": "session.tool.progress",
          "phase": "tool.execution.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1518"
        },
        {
          "name": "session.tool.success",
          "phase": "tool.after.success",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1850"
        },
        {
          "name": "session.tool.failed",
          "phase": "tool.after.failure",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1868"
        },
        {
          "name": "session.retry.scheduled",
          "phase": "turn.retry",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1327"
        },
        {
          "name": "session.compaction.started",
          "phase": "compaction.before",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1343"
        },
        {
          "name": "session.compaction.delta",
          "phase": "compaction.delta",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1527"
        },
        {
          "name": "session.compaction.ended",
          "phase": "compaction.after",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L2036"
        },
        {
          "name": "session.compaction.failed",
          "phase": "compaction.failure",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1353"
        },
        {
          "name": "session.revert.staged",
          "phase": "revert.stage",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1370"
        },
        {
          "name": "session.revert.cleared",
          "phase": "revert.clear",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1380"
        },
        {
          "name": "session.revert.committed",
          "phase": "revert.commit",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1390"
        },
        {
          "name": "filesystem.changed",
          "phase": "file.change",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1536"
        },
        {
          "name": "reference.updated",
          "phase": "reference.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1545"
        },
        {
          "name": "permission.asked",
          "phase": "permission.request",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1554"
        },
        {
          "name": "permission.replied",
          "phase": "permission.reply",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1572"
        },
        {
          "name": "plugin.updated",
          "phase": "plugin.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1581"
        },
        {
          "name": "project.updated",
          "phase": "project.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1590"
        },
        {
          "name": "worktree.updated",
          "phase": "worktree.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1608"
        },
        {
          "name": "worktree.resolved",
          "phase": "worktree.resolve",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1617"
        },
        {
          "name": "command.updated",
          "phase": "command.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1627"
        },
        {
          "name": "config.updated",
          "phase": "config.change",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1636"
        },
        {
          "name": "skill.updated",
          "phase": "skill.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1645"
        },
        {
          "name": "pty.created",
          "phase": "pty.create",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1937"
        },
        {
          "name": "pty.updated",
          "phase": "pty.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1946"
        },
        {
          "name": "pty.exited",
          "phase": "pty.exit",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1654"
        },
        {
          "name": "pty.deleted",
          "phase": "pty.delete",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1663"
        },
        {
          "name": "persistent-pty.added",
          "phase": "pty.persist.add",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1955"
        },
        {
          "name": "persistent-pty.removed",
          "phase": "pty.persist.remove",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1672"
        },
        {
          "name": "shell.created",
          "phase": "shell.create",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1681"
        },
        {
          "name": "shell.exited",
          "phase": "shell.exit",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1690"
        },
        {
          "name": "shell.deleted",
          "phase": "shell.delete",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1699"
        },
        {
          "name": "form.created",
          "phase": "form.create",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L2475"
        },
        {
          "name": "form.replied",
          "phase": "form.reply",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1979"
        },
        {
          "name": "form.cancelled",
          "phase": "form.cancel",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1708"
        },
        {
          "name": "websearch.updated",
          "phase": "websearch.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1717"
        },
        {
          "name": "session.status",
          "phase": "session.status",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1726"
        },
        {
          "name": "session.idle",
          "phase": "session.idle",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1735"
        },
        {
          "name": "tui.prompt.append",
          "phase": "tui.prompt",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1744"
        },
        {
          "name": "tui.command.execute",
          "phase": "tui.command",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1753"
        },
        {
          "name": "tui.toast.show",
          "phase": "tui.toast",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1782"
        },
        {
          "name": "tui.session.select",
          "phase": "tui.session.select",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1796"
        },
        {
          "name": "installation.updated",
          "phase": "installation.update",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1805"
        },
        {
          "name": "installation.update-available",
          "phase": "installation.available",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1814"
        },
        {
          "name": "vcs.branch.updated",
          "phase": "vcs.branch.change",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1823"
        },
        {
          "name": "mcp.status.changed",
          "phase": "mcp.status.change",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1832"
        },
        {
          "name": "mcp.resources.changed",
          "phase": "mcp.resources.change",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L1841"
        },
        {
          "name": "server.connected",
          "phase": "server.connect",
          "control": ["observe"],
          "availability": "source-only",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/client/src/promise/generated/types.ts#L871"
        }
      ]
    },
    {
      "harness": "pi",
      "surface": "extension-events",
      "eventReference": {
        "urlTemplate": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#{anchor}",
        "anchorTransform": "identity"
      },
      "configuration": [
        "~/.pi/agent/extensions",
        ".pi/extensions",
        "settings.json extensions",
        "packages",
        "--extension/-e"
      ],
      "evidence": ["pi-extension-events-1-2-0"],
      "events": [
        {
          "name": "project_trust",
          "phase": "project.trust",
          "control": ["decision"],
          "notes": [
            "The first handler answering yes or no wins; only user-level and -e extensions can answer."
          ],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1597"
        },
        {
          "name": "resources_discover",
          "phase": "resources.discover",
          "control": ["extend"],
          "notes": ["Returns extra skill, prompt and theme paths, accumulated across handlers."],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1599"
        },
        {
          "name": "session_start",
          "phase": "session.start",
          "control": ["observe"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1602"
        },
        {
          "name": "session_info_changed",
          "phase": "session.info.change",
          "control": ["observe"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1603"
        },
        {
          "name": "session_before_switch",
          "phase": "session.switch.before",
          "control": ["cancel"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1605"
        },
        {
          "name": "session_before_fork",
          "phase": "session.fork.before",
          "control": ["cancel", "mutate"],
          "notes": ["Besides cancelling, can only skip conversation restore."],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1609"
        },
        {
          "name": "session_before_compact",
          "phase": "compaction.before",
          "control": ["cancel", "replace"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1613"
        },
        {
          "name": "session_compact",
          "phase": "compaction.after",
          "control": ["observe"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1616"
        },
        {
          "name": "session_compact_failed",
          "phase": "compaction.failure",
          "control": ["observe"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1617"
        },
        {
          "name": "session_before_tree",
          "phase": "session.tree.before",
          "control": ["cancel", "replace", "mutate"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1621"
        },
        {
          "name": "session_tree",
          "phase": "session.tree.after",
          "control": ["observe"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1624"
        },
        {
          "name": "session_shutdown",
          "phase": "session.end",
          "control": ["observe"],
          "notes": ["Fires on quit, reload, new, resume and fork."],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1618"
        },
        {
          "name": "input",
          "phase": "prompt.before",
          "control": ["mutate", "handle"],
          "notes": ["Transforms chain; handled short-circuits."],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1664"
        },
        {
          "name": "before_agent_start",
          "phase": "agent.before",
          "control": ["context", "mutate", "replace"],
          "notes": [
            "Returning systemPrompt replaces the whole system prompt. Since 1.2.0 also fires for triggered extension messages."
          ],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1639"
        },
        {
          "name": "agent_start",
          "phase": "agent.start",
          "control": ["observe"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1642"
        },
        {
          "name": "agent_end",
          "phase": "agent.end",
          "control": ["observe"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1643"
        },
        {
          "name": "agent_settled",
          "phase": "agent.settled",
          "control": ["observe"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1648"
        },
        {
          "name": "turn_start",
          "phase": "turn.start",
          "control": ["observe"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1651"
        },
        {
          "name": "turn_end",
          "phase": "turn.end",
          "control": ["context", "followup"],
          "notes": ["Can append entries and request one more provider call."],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1652"
        },
        {
          "name": "message_start",
          "phase": "message.start",
          "control": ["observe"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1653"
        },
        {
          "name": "message_update",
          "phase": "message.update",
          "control": ["observe"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1654"
        },
        {
          "name": "message_end",
          "phase": "message.end",
          "control": ["replace"],
          "notes": ["The replacement must keep the message role."],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1655"
        },
        {
          "name": "context",
          "phase": "model.context.before",
          "control": ["mutate"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1625"
        },
        {
          "name": "before_provider_headers",
          "phase": "provider.headers.before",
          "control": ["mutate"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1635"
        },
        {
          "name": "before_provider_request",
          "phase": "provider.request.before",
          "control": ["replace"],
          "notes": [
            "Each returned payload replaces the request and is passed to the next handler."
          ],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1632"
        },
        {
          "name": "after_provider_response",
          "phase": "provider.response.after",
          "control": ["observe"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1636"
        },
        {
          "name": "tool_execution_start",
          "phase": "tool.execution.start",
          "control": ["observe"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1656"
        },
        {
          "name": "tool_execution_update",
          "phase": "tool.execution.update",
          "control": ["observe"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1657"
        },
        {
          "name": "tool_execution_end",
          "phase": "tool.execution.end",
          "control": ["observe"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1658"
        },
        {
          "name": "tool_call",
          "phase": "tool.before",
          "control": ["block", "mutate"],
          "notes": [
            "Mutating event.input patches arguments without re-validation. The first block wins; a thrown error blocks the tool."
          ],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1661"
        },
        {
          "name": "tool_result",
          "phase": "tool.after",
          "control": ["mutate"],
          "notes": ["Handlers compose; each sees earlier changes."],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1662"
        },
        {
          "name": "thinking_level_select",
          "phase": "thinking.select",
          "control": ["observe"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1660"
        },
        {
          "name": "model_select",
          "phase": "model.select",
          "control": ["observe"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1659"
        },
        {
          "name": "agent_before_settle",
          "phase": "turn.stop",
          "control": ["context", "followup"],
          "notes": [
            "The last point at which a handler can append entries and request one more provider call."
          ],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1645"
        },
        {
          "name": "context_with_system",
          "phase": "model.context.before",
          "control": ["mutate", "replace"],
          "notes": [
            "Runs after every context handler, on the full transcript including system messages."
          ],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1626"
        },
        {
          "name": "provider_stream_event",
          "phase": "provider.stream",
          "control": ["observe"],
          "notes": ["Handlers are awaited in stream order, so a slow handler delays the stream."],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1637"
        },
        {
          "name": "cache_warming_decision",
          "phase": "cache.warm",
          "control": ["decision"],
          "notes": ["Returns warm or stop; the last handler that answers wins."],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1628"
        },
        {
          "name": "mcp_servers_change",
          "phase": "mcp.servers.change",
          "control": ["handle"],
          "notes": [
            "Handling it makes the extension responsible for connecting registered servers."
          ],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1619"
        },
        {
          "name": "user_bash",
          "phase": "user.shell.before",
          "control": ["replace", "delegate", "block"],
          "notes": [
            "User ! and !! commands, not the agent's bash tool. The first handler to answer wins; a failure blocks the command."
          ],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1663"
        },
        {
          "name": "ui_prompt_start",
          "phase": "ui.prompt.start",
          "control": ["observe"],
          "notes": ["Pi starts waiting on a blocking extension prompt."],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1649"
        },
        {
          "name": "ui_prompt_end",
          "phase": "ui.prompt.end",
          "control": ["observe"],
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/extensions/types.ts#L1650"
        }
      ],
      "notes": [
        "In-process TypeScript extension events, run in extension load order; extensions run with full user permissions.",
        "pi's documentation names its extension type definitions as the event reference.",
        "Project extensions load only after the project is trusted."
      ]
    }
  ]
}
