Documentation
¶
Overview ¶
Package agentx provides coding agent detection, hook management, and configuration.
agentx is a helper library for understanding how to extend the feature set of coding agents. It provides a unified interface for:
- Detecting which coding agent is currently running
- Understanding each agent's capabilities and configuration options
- Installing hooks and integrations for supported agents
- Managing agent-specific configuration paths (user and project level)
- Identifying context files each agent supports (CLAUDE.md, .cursorrules, etc.)
Supported agents: Claude Code, Cursor, Windsurf, GitHub Copilot, Aider, Cody, Continue, Code Puppy, Kiro, OpenCode, Goose, and Amp.
This package is designed to be standalone with no ox-specific dependencies, making it suitable for use by other tools that need coding agent integration.
Usage:
import (
"github.com/sageox/ox/pkg/agentx"
_ "github.com/sageox/ox/pkg/agentx/setup" // registers default agents
)
// Detect the current agent
if agentx.IsAgentContext() {
agent := agentx.CurrentAgent()
fmt.Printf("Running in %s\n", agent.Name())
fmt.Printf("Context files: %v\n", agent.ContextFiles())
}
Attribution ¶
This package is developed and maintained by SageOx (https://sageox.ai). If you use this package, please give credit to SageOx.
Index ¶
- Constants
- Variables
- func BuildEventPhaseMap() map[string]EventPhaseMap
- func CompareVersions(a, b string) bool
- func ContentHash(content []byte) string
- func ExtractCommandHash(content []byte) string
- func ExtractStampVersion(content []byte) string
- func IsAgentContext() bool
- func IsCommandStale(existing []byte, cmd CommandFile) bool
- func OrchestratorType() string
- func RequireAgent(commandName string) string
- func ShouldWriteCommand(existing []byte, cmd CommandFile, overwrite bool) bool
- func StampedContent(content []byte, version string) []byte
- type Agent
- type AgentConfig
- type AgentDetector
- type AgentExtensions
- type AgentIdentity
- type AgentRole
- type AgentSession
- type AgentType
- type Capabilities
- type CommandFile
- type CommandManager
- type Detector
- type Environment
- type EventHooks
- type EventPhaseMap
- type HookAction
- type HookConfig
- type HookEvent
- type HookInput
- type HookManager
- type HookRule
- type HookSupportEntry
- type LifecycleEventMapper
- type MCPServerConfig
- type MockEnvironment
- func (e *MockEnvironment) CacheDir() (string, error)
- func (e *MockEnvironment) ConfigDir() (string, error)
- func (e *MockEnvironment) DataDir() (string, error)
- func (e *MockEnvironment) Exec(ctx context.Context, name string, args ...string) ([]byte, error)
- func (e *MockEnvironment) FileExists(path string) bool
- func (e *MockEnvironment) GOOS() string
- func (e *MockEnvironment) GetEnv(key string) string
- func (e *MockEnvironment) HomeDir() (string, error)
- func (e *MockEnvironment) IsDir(path string) bool
- func (e *MockEnvironment) LookPath(name string) (string, error)
- func (e *MockEnvironment) LookupEnv(key string) (string, bool)
- func (e *MockEnvironment) ReadFile(path string) ([]byte, error)
- type Phase
- type Registry
- type SystemEnvironment
- func (e *SystemEnvironment) CacheDir() (string, error)
- func (e *SystemEnvironment) ConfigDir() (string, error)
- func (e *SystemEnvironment) DataDir() (string, error)
- func (e *SystemEnvironment) Exec(ctx context.Context, name string, args ...string) ([]byte, error)
- func (e *SystemEnvironment) FileExists(path string) bool
- func (e *SystemEnvironment) GOOS() string
- func (e *SystemEnvironment) GetEnv(key string) string
- func (e *SystemEnvironment) HomeDir() (string, error)
- func (e *SystemEnvironment) IsDir(path string) bool
- func (e *SystemEnvironment) LookPath(name string) (string, error)
- func (e *SystemEnvironment) LookupEnv(key string) (string, bool)
- func (e *SystemEnvironment) ReadFile(path string) ([]byte, error)
Constants ¶
const CommandHashPrefix = "<!-- ox-hash: "
CommandHashPrefix is the marker used to stamp command files with a content hash and CLI version. Format: <!-- ox-hash: <hash> ver: <version> --> Files are only rewritten when content changes AND the writing version is >= installed.
Variables ¶
var AllPhases = []Phase{ PhaseStart, PhaseEnd, PhaseBeforeTool, PhaseAfterTool, PhasePrompt, PhaseStop, PhaseCompact, }
AllPhases is the ordered list of canonical lifecycle phases for matrix display.
var DefaultRegistry = NewRegistry()
DefaultRegistry is the global registry with all supported agents.
var SupportedAgents = []AgentType{ AgentTypeClaudeCode, AgentTypeCursor, AgentTypeWindsurf, AgentTypeCopilot, AgentTypeAider, AgentTypeCody, AgentTypeContinue, AgentTypeCodePuppy, AgentTypeKiro, AgentTypeOpenCode, AgentTypeCodex, AgentTypeGoose, AgentTypeAmp, AgentTypeCline, AgentTypeDroid, AgentTypeOpenClaw, AgentTypeConductor, }
SupportedAgents is the canonical list of coding agents and orchestrators that agentx supports.
Functions ¶
func BuildEventPhaseMap ¶ added in v0.3.0
func BuildEventPhaseMap() map[string]EventPhaseMap
BuildEventPhaseMap builds a map from AGENT_ENV alias → (native event → phase) by iterating all registered agents that implement LifecycleEventMapper. The returned map uses AGENT_ENV aliases as keys (e.g., "claude-code"), not AgentType slugs (e.g., "claude").
func CompareVersions ¶
CompareVersions returns true if version a is strictly older than version b. Uses simple semver comparison (major.minor.patch).
func ContentHash ¶
ContentHash returns the first 12 characters of the SHA-256 hex digest of content.
func ExtractCommandHash ¶
ExtractCommandHash extracts the content hash from a stamped command file. Returns empty string if no hash stamp is found.
func ExtractStampVersion ¶
ExtractStampVersion extracts the CLI version from a stamped command file. Returns empty string if no version is found in the stamp.
func IsAgentContext ¶
func IsAgentContext() bool
IsAgentContext returns true if running inside any coding agent. This is a convenience function using the default registry.
func IsCommandStale ¶
func IsCommandStale(existing []byte, cmd CommandFile) bool
IsCommandStale determines whether an installed command file is outdated compared to expected content. Returns false for user-managed files (no stamp) and files installed by a newer version (downgrade guard).
func OrchestratorType ¶ added in v0.2.0
func OrchestratorType() string
OrchestratorType returns the type string of the detected orchestrator, or empty string if none detected.
func RequireAgent ¶
RequireAgent returns an error message if not running in an agent context. Returns empty string if in agent context.
func ShouldWriteCommand ¶
func ShouldWriteCommand(existing []byte, cmd CommandFile, overwrite bool) bool
ShouldWriteCommand determines whether a command file should be written. existing is the current file content on disk (nil if the file doesn't exist). Returns true if the file should be written, false if it should be skipped.
Decision logic:
- File doesn't exist → write
- File exists + overwrite=false → skip
- File exists + no hash stamp → skip (user-managed)
- Hash matches → skip (content identical)
- Hash differs + installed version is newer → skip (downgrade guard)
- Otherwise → write
func StampedContent ¶
StampedContent returns the command content with a hash+version stamp prepended. Format: <!-- ox-hash: <12-char-hash> ver: <version> -->
Types ¶
type Agent ¶
type Agent interface {
AgentIdentity
AgentDetector
AgentConfig
AgentExtensions
AgentSession
}
Agent represents a coding agent with full detection and configuration capabilities. It embeds all focused interfaces for complete agent functionality.
When defining functions that work with agents, prefer using the narrowest interface that meets your needs:
- AgentIdentity: when you only need type, name, or URL
- AgentDetector: when you need to check if agent is running/installed
- AgentConfig: when you need configuration paths
- AgentExtensions: when you need hooks
- AgentSession: when you need session identification
- Agent: when you need full functionality or storage/registry
func CurrentAgent ¶
func CurrentAgent() Agent
CurrentAgent returns the currently detected coding agent, or nil if none.
func CurrentOrchestrator ¶ added in v0.2.0
func CurrentOrchestrator() Agent
CurrentOrchestrator returns the currently detected orchestrator, or nil if none.
type AgentConfig ¶
type AgentConfig interface {
// UserConfigPath returns the user-level configuration directory (e.g., ~/.claude)
UserConfigPath(env Environment) (string, error)
// ProjectConfigPath returns the project-level configuration directory (e.g., .claude/)
// Returns empty string if the agent doesn't support project-level config
ProjectConfigPath() string
// ContextFiles returns the list of context/instruction files this agent supports
// Examples: CLAUDE.md, AGENTS.md, .cursorrules, .windsurfrules
ContextFiles() []string
// SupportsXDGConfig returns true if the agent stores user config in XDG-compliant
// locations (~/.config/app/) rather than home directory dotfiles (~/.app/).
// XDG Base Directory Specification is the preferred standard for config locations.
// See: https://specifications.freedesktop.org/basedir-spec/latest/
SupportsXDGConfig() bool
}
AgentConfig provides configuration path information. Use this interface when you need to locate agent configuration files.
type AgentDetector ¶
type AgentDetector interface {
// Detect checks if this agent is currently running
Detect(ctx context.Context, env Environment) (bool, error)
// IsInstalled checks if this agent is installed on the system.
// Detection methods vary by agent: binary in PATH, config directory exists,
// application bundle present (macOS), etc.
IsInstalled(ctx context.Context, env Environment) (bool, error)
// DetectVersion attempts to determine the installed version of this agent.
// Returns empty string if version cannot be determined (best-effort).
// Strategies vary by agent: CLI --version, reading package.json, etc.
DetectVersion(ctx context.Context, env Environment) string
}
AgentDetector provides agent detection capabilities. Use this interface when you need to check if an agent is running or installed.
type AgentExtensions ¶
type AgentExtensions interface {
// Capabilities returns what features this agent supports
Capabilities() Capabilities
// HookManager returns the hook manager for this agent, or nil if hooks not supported
HookManager() HookManager
// CommandManager returns the command manager for this agent, or nil if custom commands not supported
CommandManager() CommandManager
}
AgentExtensions provides hook and command management capabilities. Use this interface when you need to work with agent extensions.
type AgentIdentity ¶
type AgentIdentity interface {
// Type returns the agent type slug
Type() AgentType
// Name returns the human-readable agent name
Name() string
// URL returns the official project URL (typically GitHub repo)
URL() string
// Role returns whether this is a coding agent or an orchestrator
Role() AgentRole
}
AgentIdentity provides basic agent identification. Use this interface when you only need to identify an agent without needing detection or configuration capabilities.
type AgentRole ¶ added in v0.2.0
type AgentRole string
AgentRole distinguishes agents from orchestrators. Agents are coding tools (Claude Code, Cursor); orchestrators launch and manage agents (OpenClaw, Conductor, Gas Town).
type AgentSession ¶ added in v0.3.0
type AgentSession interface {
// SupportsSession returns true if this agent has a native session/thread
// concept. True means the agent CAN provide a session ID, even if one
// isn't available right now (e.g., agent not running, env var not set).
SupportsSession() bool
// SessionID returns the agent's native session identifier from the
// environment. Returns empty string if not currently available.
// For hook-based agents without a dedicated env var, this returns ""
// and the caller should use HookInput.SessionID instead.
SessionID(env Environment) string
}
AgentSession provides access to the agent's native session identifier. Agents that support sessions (most hook-based agents) return true from SupportsSession. The actual session ID may come from an environment variable (e.g., CLAUDE_CODE_SESSION_ID, CODEX_THREAD_ID) or from hook stdin JSON (HookInput.SessionID, handled separately).
type AgentType ¶
type AgentType string
AgentType identifies a coding agent or orchestrator.
const ( AgentTypeUnknown AgentType = "" AgentTypeClaudeCode AgentType = "claude" AgentTypeCursor AgentType = "cursor" AgentTypeWindsurf AgentType = "windsurf" AgentTypeCopilot AgentType = "copilot" AgentTypeAider AgentType = "aider" AgentTypeCody AgentType = "cody" AgentTypeContinue AgentType = "continue" AgentTypeCodePuppy AgentType = "code-puppy" AgentTypeKiro AgentType = "kiro" AgentTypeOpenCode AgentType = "opencode" AgentTypeCodex AgentType = "codex" AgentTypeGoose AgentType = "goose" AgentTypeAmp AgentType = "amp" AgentTypeCline AgentType = "cline" AgentTypeDroid AgentType = "droid" AgentTypeCustom AgentType = "custom" // Orchestrators AgentTypeOpenClaw AgentType = "openclaw" AgentTypeConductor AgentType = "conductor" )
func ResolveAgentENV ¶ added in v0.3.0
ResolveAgentENV resolves an AGENT_ENV string to an AgentType. Returns AgentTypeUnknown if not found.
type Capabilities ¶
type Capabilities struct {
// Hooks indicates the agent supports hook installation
Hooks bool
// MCPServers indicates the agent supports MCP server configuration
MCPServers bool
// SystemPrompt indicates the agent supports custom system instructions
SystemPrompt bool
// ProjectContext indicates the agent reads project context files (CLAUDE.md, etc.)
ProjectContext bool
// CustomCommands indicates the agent supports custom slash commands
CustomCommands bool
// MinVersion is the minimum agent version required for full feature support (future)
MinVersion string
}
Capabilities describes what features a coding agent supports. This allows tools to adapt their behavior based on agent capabilities.
type CommandFile ¶
type CommandFile struct {
// Name is the filename (e.g., "ox-status.md")
Name string
// Content is the file content (without stamp; stamp is added on write)
Content []byte
// Version is the ox version that ships this command.
// Used as a downgrade guard: an older binary won't overwrite commands
// installed by a newer binary.
Version string
}
CommandFile represents a custom slash command to install.
func ReadCommandFiles ¶
func ReadCommandFiles(fsys fs.FS, dir string) ([]CommandFile, error)
ReadCommandFiles reads .md files from an fs.FS directory into CommandFile slices. Useful for converting go:embed filesystems into CommandFile arrays for installation.
type CommandManager ¶
type CommandManager interface {
// Install writes command files to the agent's command directory.
// When overwrite is false, existing files are skipped entirely (safe for init).
// When overwrite is true, existing files are replaced only if content differs (safe for doctor).
// Returns the list of filenames that were written.
Install(ctx context.Context, projectRoot string, commands []CommandFile, overwrite bool) ([]string, error)
// Uninstall removes command files matching the prefix from the command directory.
// Returns the list of filenames that were removed.
Uninstall(ctx context.Context, projectRoot string, prefix string) ([]string, error)
// Validate checks which expected files are missing or stale in the command directory.
// Returns missing filenames and stale filenames (content differs from expected).
Validate(ctx context.Context, projectRoot string, commands []CommandFile) (missing []string, stale []string, err error)
// CommandDir returns the path to the command directory for a project.
CommandDir(projectRoot string) string
}
CommandManager handles custom slash command installation for agents.
type Detector ¶
type Detector interface {
// Detect identifies the active coding agent (RoleAgent), returning nil if none detected.
// Orchestrators are excluded — use DetectOrchestrator for those.
Detect(ctx context.Context) (Agent, error)
// DetectOrchestrator returns the active orchestrator (RoleOrchestrator), or nil.
// This is independent of Detect() which returns the coding agent.
DetectOrchestrator(ctx context.Context) (Agent, error)
// DetectAll returns all detected agents and orchestrators
DetectAll(ctx context.Context) ([]Agent, error)
// DetectByType checks if a specific agent type is active
DetectByType(ctx context.Context, agentType AgentType) (bool, error)
}
Detector identifies which coding agent(s) and orchestrator(s) are currently active.
func NewDetector ¶
func NewDetector() Detector
NewDetector creates a detector with the default registry.
func NewDetectorWithEnv ¶
func NewDetectorWithEnv(env Environment) Detector
NewDetectorWithEnv creates a detector with a custom environment.
type Environment ¶
type Environment interface {
// GetEnv retrieves an environment variable value
GetEnv(key string) string
// LookupEnv retrieves an environment variable and reports if it exists
LookupEnv(key string) (string, bool)
// HomeDir returns the user's home directory
HomeDir() (string, error)
// ConfigDir returns the XDG config directory
ConfigDir() (string, error)
// DataDir returns the XDG data directory
DataDir() (string, error)
// CacheDir returns the XDG cache directory
CacheDir() (string, error)
// GOOS returns the operating system name
GOOS() string
// LookPath searches for an executable in PATH
LookPath(name string) (string, error)
// FileExists checks if a file or directory exists
FileExists(path string) bool
// IsDir checks if a path is a directory
IsDir(path string) bool
// Exec runs a command and returns its stdout output.
// Returns error if the command fails or is not found.
Exec(ctx context.Context, name string, args ...string) ([]byte, error)
// ReadFile reads a file and returns its contents.
ReadFile(path string) ([]byte, error)
}
Environment provides access to system environment for agent detection. This abstraction enables testing without real file system access.
func NewSystemEnvironment ¶
func NewSystemEnvironment() Environment
NewSystemEnvironment creates a new system environment.
type EventHooks ¶
EventHooks maps lifecycle events to their hook rules. This is the structure used in settings.json under the "hooks" key.
type EventPhaseMap ¶ added in v0.3.0
EventPhaseMap maps an agent's native hook events to canonical lifecycle phases.
type HookAction ¶
type HookAction struct {
// Type is the action type. Currently only "command" is supported.
Type string `json:"type"`
// Command is the shell command to execute. Receives tool context via stdin as JSON.
// Exit code 2 from PreToolUse/PermissionRequest hooks denies the action.
Command string `json:"command"`
}
HookAction defines what happens when a hook triggers.
type HookConfig ¶
type HookConfig struct {
// SourcePath is the path to hook source files (templates, commands)
SourcePath string
// MCPServers are MCP server configurations to add
MCPServers map[string]MCPServerConfig
// SystemInstructions are custom instructions for the agent
SystemInstructions string
// EventHooks are lifecycle event hooks to install (PreToolUse, PostToolUse, etc.)
// See HookEvent constants for available events.
EventHooks EventHooks
// Merge indicates whether to merge with existing config (true) or replace (false)
Merge bool
}
HookConfig represents hook configuration for installation.
type HookEvent ¶
type HookEvent string
HookEvent represents a coding agent lifecycle event that can trigger hooks. Each agent has its own native event names (e.g., Claude's "SessionStart" vs Cursor's "sessionStart" vs Windsurf's "pre_read_code"). Use the agent-specific constants below, or the canonical constants for events shared across agents.
const ( HookEventSessionStart HookEvent = "SessionStart" HookEventSessionEnd HookEvent = "SessionEnd" HookEventPreToolUse HookEvent = "PreToolUse" HookEventPostToolUse HookEvent = "PostToolUse" HookEventUserPromptSubmit HookEvent = "UserPromptSubmit" HookEventPermissionRequest HookEvent = "PermissionRequest" HookEventStop HookEvent = "Stop" HookEventSubagentStop HookEvent = "SubagentStop" HookEventPreCompact HookEvent = "PreCompact" )
Canonical hook events shared across multiple agents. Agents may use these exact strings or their own native names.
const ( CursorEventSessionStart HookEvent = "sessionStart" CursorEventSessionEnd HookEvent = "sessionEnd" CursorEventPreToolUse HookEvent = "preToolUse" CursorEventPostToolUse HookEvent = "postToolUse" CursorEventPostToolUseFailure HookEvent = "postToolUseFailure" CursorEventSubagentStart HookEvent = "subagentStart" CursorEventSubagentStop HookEvent = "subagentStop" CursorEventBeforeShellExecution HookEvent = "beforeShellExecution" CursorEventAfterShellExecution HookEvent = "afterShellExecution" CursorEventBeforeMCPExecution HookEvent = "beforeMCPExecution" CursorEventAfterMCPExecution HookEvent = "afterMCPExecution" CursorEventBeforeReadFile HookEvent = "beforeReadFile" CursorEventAfterFileEdit HookEvent = "afterFileEdit" CursorEventBeforeSubmitPrompt HookEvent = "beforeSubmitPrompt" CursorEventPreCompact HookEvent = "preCompact" CursorEventStop HookEvent = "stop" CursorEventAfterAgentResponse HookEvent = "afterAgentResponse" CursorEventAfterAgentThought HookEvent = "afterAgentThought" )
Cursor-specific hook events. Reference: https://cursor.com/docs/agent/hooks
const ( WindsurfEventPreReadCode HookEvent = "pre_read_code" WindsurfEventPostReadCode HookEvent = "post_read_code" WindsurfEventPreWriteCode HookEvent = "pre_write_code" WindsurfEventPostWriteCode HookEvent = "post_write_code" WindsurfEventPreRunCommand HookEvent = "pre_run_command" WindsurfEventPostRunCommand HookEvent = "post_run_command" WindsurfEventPreMCPToolUse HookEvent = "pre_mcp_tool_use" WindsurfEventPostMCPToolUse HookEvent = "post_mcp_tool_use" WindsurfEventPreUserPrompt HookEvent = "pre_user_prompt" WindsurfEventPostCascadeResponse HookEvent = "post_cascade_response" WindsurfEventPostCascadeResponseWithTranscript HookEvent = "post_cascade_response_with_transcript" WindsurfEventPostSetupWorktree HookEvent = "post_setup_worktree" )
Windsurf-specific hook events. Reference: https://docs.windsurf.com/windsurf/cascade/hooks
const ( KiroEventPromptSubmit HookEvent = "PromptSubmit" KiroEventAgentStop HookEvent = "AgentStop" KiroEventPreToolUse HookEvent = "PreToolUse" // same as canonical KiroEventPostToolUse HookEvent = "PostToolUse" // same as canonical KiroEventFileCreate HookEvent = "FileCreate" KiroEventFileSave HookEvent = "FileSave" KiroEventFileDelete HookEvent = "FileDelete" KiroEventPreTaskExecution HookEvent = "PreTaskExecution" KiroEventPostTaskExecution HookEvent = "PostTaskExecution" KiroEventManualTrigger HookEvent = "ManualTrigger" )
Kiro-specific hook events. Reference: https://kiro.dev/docs/hooks/types/
const ( ClineEventTaskStart HookEvent = "TaskStart" ClineEventTaskResume HookEvent = "TaskResume" ClineEventTaskCancel HookEvent = "TaskCancel" ClineEventTaskComplete HookEvent = "TaskComplete" ClineEventPreToolUse HookEvent = "PreToolUse" // same as canonical ClineEventPostToolUse HookEvent = "PostToolUse" // same as canonical ClineEventUserPromptSubmit HookEvent = "UserPromptSubmit" ClineEventPreCompact HookEvent = "PreCompact" )
Cline-specific hook events. Reference: https://docs.cline.bot/features/hooks
const ( CopilotEventSessionStart HookEvent = "sessionStart" CopilotEventSessionEnd HookEvent = "sessionEnd" CopilotEventUserPromptSubmitted HookEvent = "userPromptSubmitted" CopilotEventPreToolUse HookEvent = "preToolUse" CopilotEventPostToolUse HookEvent = "postToolUse" CopilotEventErrorOccurred HookEvent = "errorOccurred" )
GitHub Copilot hook events. Reference: https://docs.github.com/en/copilot/reference/hooks-configuration
const ( AmpEventToolPreExecute HookEvent = "tool:pre-execute" AmpEventToolPostExecute HookEvent = "tool:post-execute" )
Amp-specific hook events. Reference: https://ampcode.com/news/hooks
const ( OpenCodeEventSessionCreated HookEvent = "session.created" OpenCodeEventSessionCompacted HookEvent = "session.compacted" OpenCodeEventSessionDeleted HookEvent = "session.deleted" OpenCodeEventSessionError HookEvent = "session.error" OpenCodeEventSessionIdle HookEvent = "session.idle" OpenCodeEventSessionStatus HookEvent = "session.status" OpenCodeEventSessionUpdated HookEvent = "session.updated" OpenCodeEventToolExecuteBefore HookEvent = "tool.execute.before" OpenCodeEventToolExecuteAfter HookEvent = "tool.execute.after" OpenCodeEventFileEdited HookEvent = "file.edited" OpenCodeEventPermissionAsked HookEvent = "permission.asked" OpenCodeEventPermissionReplied HookEvent = "permission.replied" OpenCodeEventMessageUpdated HookEvent = "message.updated" OpenCodeEventCommandExecuted HookEvent = "command.executed" )
OpenCode-specific hook events (plugin system). Reference: https://opencode.ai/docs/plugins/
const (
DroidEventNotification HookEvent = "Notification"
)
Droid-specific hook events (Factory). Reference: https://docs.factory.ai/reference/hooks-reference
type HookInput ¶ added in v0.3.0
type HookInput struct {
SessionID string `json:"session_id"`
HookEventName string `json:"hook_event_name"`
Source string `json:"source,omitempty"` // session start/end source (startup, resume, clear, compact)
Trigger string `json:"trigger,omitempty"` // compact trigger (manual, auto)
ToolName string `json:"tool_name,omitempty"`
ToolInput json.RawMessage `json:"tool_input,omitempty"`
ToolResponse json.RawMessage `json:"tool_response,omitempty"`
ToolError string `json:"error,omitempty"`
// RawBytes is the original stdin payload, preserved for faithful passthrough
// to subprocesses. Not serialized to JSON — used internally only.
RawBytes []byte `json:"-"`
}
HookInput is the generalized stdin JSON payload from any coding agent's hook system. Agents pipe event context to hook commands via stdin as JSON. This struct captures the common fields across agents (Claude Code, Cursor, Windsurf, Cline, etc.).
Not all fields are present for every event — tool fields only appear for tool events, Source only for session start/end, etc.
RawBytes preserves the original stdin bytes for faithful passthrough to subprocesses. This avoids losing unknown/agent-specific fields during re-serialization.
func ReadHookInput ¶ added in v0.3.0
ReadHookInput reads and parses hook input JSON from the given reader. Returns nil if the reader is empty or doesn't contain valid JSON. Use with os.Stdin in production; pass any io.Reader for testing.
Reads up to maxHookInputSize (256KB) to accommodate large tool payloads. Uses io.ReadAll (with a limit) to handle fragmented pipe reads correctly.
func ReadHookInputFromStdin ¶ added in v0.3.0
func ReadHookInputFromStdin() *HookInput
ReadHookInputFromStdin reads hook input from os.Stdin, returning nil if stdin is a terminal (not a pipe) or doesn't contain valid JSON. This is the standard entry point for CLI hook commands.
Note: On some Windows terminal environments, the pipe detection via os.ModeCharDevice may not be reliable. In those cases, this returns nil and the hook proceeds without parsed input.
type HookManager ¶
type HookManager interface {
// Install installs hooks for the agent
Install(ctx context.Context, config HookConfig) error
// Uninstall removes installed hooks
Uninstall(ctx context.Context) error
// IsInstalled checks if hooks are installed
IsInstalled(ctx context.Context) (bool, error)
// Validate validates the current hook configuration
Validate(ctx context.Context) error
}
HookManager handles hook installation and management for an agent.
type HookRule ¶
type HookRule struct {
// Matcher is a tool name pattern (e.g., "Bash", "Edit|Write", "*" for all).
// Only applies to PreToolUse, PostToolUse, and PermissionRequest events.
Matcher string `json:"matcher,omitempty"`
// Hooks are the actions to execute when this rule matches.
Hooks []HookAction `json:"hooks"`
}
HookRule defines when and how a hook triggers. Rules use matchers to filter which tools activate the hook.
type HookSupportEntry ¶ added in v0.3.0
type HookSupportEntry struct {
AgentType AgentType
AgentName string
Phases map[Phase][]HookEvent // phase → native event names (may have multiple)
}
HookSupportEntry represents one agent's lifecycle hook support. Phases maps each canonical phase to the agent's native event name.
func HookSupportMatrix ¶ added in v0.3.0
func HookSupportMatrix() []HookSupportEntry
HookSupportMatrix returns the hook support matrix for all registered agents that implement LifecycleEventMapper. Each entry shows which phases the agent supports and the native event name for each phase.
type LifecycleEventMapper ¶ added in v0.3.0
type LifecycleEventMapper interface {
// EventPhases returns the mapping from this agent's native events to canonical phases.
EventPhases() EventPhaseMap
// AgentENVAliases returns the AGENT_ENV values that identify this agent in hook commands.
// The first value is the canonical/preferred alias used in hook installation.
// Example: Claude Code returns ["claude-code", "claudecode", "claude"].
AgentENVAliases() []string
}
LifecycleEventMapper is implemented by agents that support lifecycle hooks. It maps the agent's native hook events to canonical lifecycle phases, enabling ox to handle events generically across different coding agents.
type MCPServerConfig ¶
type MCPServerConfig struct {
Command string `json:"command"`
Args []string `json:"args,omitempty"`
Env map[string]string `json:"env,omitempty"`
}
MCPServerConfig represents an MCP server configuration.
type MockEnvironment ¶
type MockEnvironment struct {
EnvVars map[string]string
Home string
Config string
Data string
Cache string
OS string
HomeError error
ExecOutputs map[string][]byte // keyed by command name
ExecErrors map[string]error // keyed by command name
Files map[string][]byte // keyed by file path
PathBinaries map[string]string // keyed by binary name → path
ExistingFiles map[string]bool // keyed by path
ExistingDirs map[string]bool // keyed by path
}
MockEnvironment is a test implementation of Environment.
func NewMockEnvironment ¶
func NewMockEnvironment(envVars map[string]string) *MockEnvironment
NewMockEnvironment creates a mock environment for testing.
func (*MockEnvironment) CacheDir ¶
func (e *MockEnvironment) CacheDir() (string, error)
func (*MockEnvironment) ConfigDir ¶
func (e *MockEnvironment) ConfigDir() (string, error)
func (*MockEnvironment) DataDir ¶
func (e *MockEnvironment) DataDir() (string, error)
func (*MockEnvironment) FileExists ¶
func (e *MockEnvironment) FileExists(path string) bool
func (*MockEnvironment) GOOS ¶
func (e *MockEnvironment) GOOS() string
func (*MockEnvironment) GetEnv ¶
func (e *MockEnvironment) GetEnv(key string) string
func (*MockEnvironment) HomeDir ¶
func (e *MockEnvironment) HomeDir() (string, error)
func (*MockEnvironment) IsDir ¶
func (e *MockEnvironment) IsDir(path string) bool
type Phase ¶ added in v0.3.0
type Phase string
Phase represents a canonical agent lifecycle moment. Phases are agent-agnostic — each agent maps its native events to these phases.
const ( PhaseStart Phase = "start" // session began PhaseEnd Phase = "end" // session ending PhaseBeforeTool Phase = "before_tool" // tool about to execute PhaseAfterTool Phase = "after_tool" // tool just completed PhasePrompt Phase = "prompt" // user submitted a prompt PhaseStop Phase = "stop" // agent finished responding PhaseCompact Phase = "compact" // context about to be compacted )
type Registry ¶
type Registry interface {
// Register adds an agent to the registry
Register(agent Agent) error
// Get retrieves an agent by type
Get(agentType AgentType) (Agent, bool)
// List returns all registered agents
List() []Agent
// Detector returns a detector for registered agents
Detector() Detector
}
Registry manages available agents and provides detection.
type SystemEnvironment ¶
type SystemEnvironment struct{}
SystemEnvironment implements Environment using the real system.
func (*SystemEnvironment) CacheDir ¶
func (e *SystemEnvironment) CacheDir() (string, error)
func (*SystemEnvironment) ConfigDir ¶
func (e *SystemEnvironment) ConfigDir() (string, error)
func (*SystemEnvironment) DataDir ¶
func (e *SystemEnvironment) DataDir() (string, error)
func (*SystemEnvironment) FileExists ¶
func (e *SystemEnvironment) FileExists(path string) bool
func (*SystemEnvironment) GOOS ¶
func (e *SystemEnvironment) GOOS() string
func (*SystemEnvironment) GetEnv ¶
func (e *SystemEnvironment) GetEnv(key string) string
func (*SystemEnvironment) HomeDir ¶
func (e *SystemEnvironment) HomeDir() (string, error)
func (*SystemEnvironment) IsDir ¶
func (e *SystemEnvironment) IsDir(path string) bool
func (*SystemEnvironment) LookPath ¶
func (e *SystemEnvironment) LookPath(name string) (string, error)
Directories
¶
| Path | Synopsis |
|---|---|
|
Package config provides configuration path resolution for agentx.
|
Package config provides configuration path resolution for agentx. |
|
Package hooks provides hook management for coding agents.
|
Package hooks provides hook management for coding agents. |
|
Package setup provides initialization for the agentx package.
|
Package setup provides initialization for the agentx package. |