agentx

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 10, 2026 License: MIT Imports: 12 Imported by: 0

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

View Source
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

AllPhases is the ordered list of canonical lifecycle phases for matrix display.

View Source
var DefaultRegistry = NewRegistry()

DefaultRegistry is the global registry with all supported agents.

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

func CompareVersions(a, b string) bool

CompareVersions returns true if version a is strictly older than version b. Uses simple semver comparison (major.minor.patch).

func ContentHash

func ContentHash(content []byte) string

ContentHash returns the first 12 characters of the SHA-256 hex digest of content.

func ExtractCommandHash

func ExtractCommandHash(content []byte) string

ExtractCommandHash extracts the content hash from a stamped command file. Returns empty string if no hash stamp is found.

func ExtractStampVersion

func ExtractStampVersion(content []byte) string

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

func RequireAgent(commandName string) string

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

func StampedContent(content []byte, version string) []byte

StampedContent returns the command content with a hash+version stamp prepended. Format: <!-- ox-hash: <12-char-hash> ver: <version> -->

Types

type Agent

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).

const (
	// RoleAgent is a coding agent that directly invokes ox commands.
	RoleAgent AgentRole = "agent"

	// RoleOrchestrator launches and manages coding agents.
	RoleOrchestrator AgentRole = "orchestrator"
)

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

func ResolveAgentENV(agentEnv string) AgentType

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

type EventHooks map[HookEvent][]HookRule

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

type EventPhaseMap map[HookEvent]Phase

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

func ReadHookInput(r io.Reader) *HookInput

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) Exec added in v0.2.0

func (e *MockEnvironment) Exec(ctx context.Context, name string, args ...string) ([]byte, 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

func (*MockEnvironment) LookPath

func (e *MockEnvironment) LookPath(name string) (string, error)

func (*MockEnvironment) LookupEnv

func (e *MockEnvironment) LookupEnv(key string) (string, bool)

func (*MockEnvironment) ReadFile added in v0.2.0

func (e *MockEnvironment) ReadFile(path string) ([]byte, error)

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.

func NewRegistry

func NewRegistry() Registry

NewRegistry creates a new empty agent registry.

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) Exec added in v0.2.0

func (e *SystemEnvironment) Exec(ctx context.Context, name string, args ...string) ([]byte, 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)

func (*SystemEnvironment) LookupEnv

func (e *SystemEnvironment) LookupEnv(key string) (string, bool)

func (*SystemEnvironment) ReadFile added in v0.2.0

func (e *SystemEnvironment) ReadFile(path string) ([]byte, 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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL