handlers

package
v1.3.2 Latest Latest
Warning

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

Go to latest
Published: May 27, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// GlobalConfigDir is the OpenCode global config directory, relative to home.
	GlobalConfigDir = ".config/opencode"

	// ProjectConfigDir is the OpenCode project-scoped config directory.
	ProjectConfigDir = ".opencode"

	// ConfigFile is the OpenCode config filename (lives at the root of
	// either GlobalConfigDir or the project). OpenCode also accepts a
	// JSONC variant — use ConfigFilePath to pick whichever exists on
	// disk rather than joining this constant directly.
	ConfigFile = "opencode.json"

	// ConfigFileJSONC is the JSONC variant OpenCode also accepts.
	ConfigFileJSONC = "opencode.jsonc"
)

Configuration directories for OpenCode.

View Source
const (
	DirSkills     = "skills"
	DirCommands   = "commands"
	DirAgents     = "agent"
	DirRules      = "rules"
	DirMCPServers = "mcp-servers"
)

Asset subdirectory names under an OpenCode config directory.

View Source
const (
	DefaultSkillPromptFile   = "SKILL.md"
	DefaultCommandPromptFile = "COMMAND.md"
	DefaultAgentPromptFile   = "AGENT.md"
	DefaultRulePromptFile    = "RULE.md"
)

Default prompt filenames.

Variables

SkillOps provides directory-based operations for OpenCode skills. OpenCode discovers skills natively from <config>/skills/<name>/SKILL.md.

Functions

func AddInstruction

func AddInstruction(configPath, path string) error

AddInstruction appends path to opencode.json's `instructions` array if it isn't already present. If the path is already registered, the config file is left untouched (no $schema injection, no key reordering) so repeated no-op installs don't churn the user's file.

func AddMCPServer

func AddMCPServer(configPath, name string, entry map[string]any) error

AddMCPServer adds or updates an entry in opencode.json under the mcp key.

func ConfigFilePath

func ConfigFilePath(dir string) string

ConfigFilePath returns the opencode config path to read or write under dir. If only opencode.jsonc exists (a supported OpenCode variant), that path is returned so sx doesn't silently create a second opencode.json next to the user's existing config. Otherwise it returns the .json path — which is also the path used when neither file exists yet.

func MCPServerEntryFromBootstrap

func MCPServerEntryFromBootstrap(cfg *bootstrap.MCPServerConfig) map[string]any

MCPServerEntryFromBootstrap renders a bootstrap.MCPServerConfig into the JSON shape OpenCode expects under the `mcp.<name>` key. Bootstrap MCPs are always local processes (bootstrap doesn't model remote URLs).

func RemoveInstruction

func RemoveInstruction(configPath, path string) error

RemoveInstruction removes path from opencode.json's `instructions` array. If the config file doesn't exist or the path isn't registered, this is a no-op and the file is left untouched.

func RemoveMCPServer

func RemoveMCPServer(configPath, name string) error

RemoveMCPServer removes the named entry from opencode.json. If the config file doesn't exist or the entry isn't there, this is a no-op and the file is left untouched — so a stray uninstall doesn't materialize a config or rewrite an existing one just to inject $schema / reorder keys.

func WriteOpenCodeConfig

func WriteOpenCodeConfig(path string, config *OpenCodeConfig) error

WriteOpenCodeConfig writes opencode.json, preserving unknown fields and adding the $schema reference if it isn't already present. Top-level keys are written in a stable order — $schema first, then instructions, then mcp, then any remaining preserved keys sorted alphabetically — so repeated installs/uninstalls don't churn the file's git diff.

Types

type AgentHandler

type AgentHandler struct {
	// contains filtered or unexported fields
}

AgentHandler installs OpenCode agents as markdown files. OpenCode loads agents from <config>/agent/<name>.md (and also from the plural `agents/` directory, but agent/ is canonical per the built-in customize-opencode skill).

func NewAgentHandler

func NewAgentHandler(meta *metadata.Metadata) *AgentHandler

NewAgentHandler creates a new OpenCode agent handler.

func (*AgentHandler) Install

func (h *AgentHandler) Install(ctx context.Context, zipData []byte, targetBase string) error

Install writes the agent markdown file to <targetBase>/agent/<name>.md.

func (*AgentHandler) Remove

func (h *AgentHandler) Remove(ctx context.Context, targetBase string) error

Remove deletes the agent markdown file from <targetBase>/agent/.

func (*AgentHandler) VerifyInstalled

func (h *AgentHandler) VerifyInstalled(targetBase string) (bool, string)

VerifyInstalled returns whether the agent markdown file exists.

type CommandHandler

type CommandHandler struct {
	// contains filtered or unexported fields
}

CommandHandler installs custom slash commands into OpenCode. OpenCode loads commands as markdown files from <config>/commands/<name>.md.

func NewCommandHandler

func NewCommandHandler(meta *metadata.Metadata) *CommandHandler

NewCommandHandler creates a new OpenCode command handler.

func (*CommandHandler) Install

func (h *CommandHandler) Install(ctx context.Context, zipData []byte, targetBase string) error

Install writes the command markdown file to <targetBase>/commands/<name>.md.

func (*CommandHandler) Remove

func (h *CommandHandler) Remove(ctx context.Context, targetBase string) error

Remove deletes the command markdown file from <targetBase>/commands/.

func (*CommandHandler) VerifyInstalled

func (h *CommandHandler) VerifyInstalled(targetBase string) (bool, string)

VerifyInstalled returns whether the command markdown file exists.

type Handler

type Handler interface {
	Install(ctx context.Context, zipData []byte, targetBase string) error
	Remove(ctx context.Context, targetBase string) error
	VerifyInstalled(targetBase string) (bool, string)
}

Handler is the interface implemented by all OpenCode asset handlers.

func NewHandler

func NewHandler(assetType asset.Type, meta *metadata.Metadata) (Handler, error)

NewHandler returns the appropriate handler for the given asset type. The rule handler is constructed with an empty register path here because this constructor is used by verify, which only checks file presence. Use NewRuleHandler directly with a register path for install/remove.

type MCPHandler

type MCPHandler struct {
	// contains filtered or unexported fields
}

MCPHandler installs MCP server entries into OpenCode's opencode.json. Packaged servers extract files into <targetBase>/mcp-servers/<name>/ and register an absolute-path command; config-only servers only modify the JSON config.

func NewMCPHandler

func NewMCPHandler(meta *metadata.Metadata) *MCPHandler

NewMCPHandler creates a new MCP handler.

func (*MCPHandler) Install

func (h *MCPHandler) Install(ctx context.Context, zipData []byte, targetBase string) error

Install registers the MCP server in opencode.json, extracting files first for packaged servers.

func (*MCPHandler) Remove

func (h *MCPHandler) Remove(ctx context.Context, targetBase string) error

Remove removes the MCP entry from opencode.json and cleans up any extracted packaged-server files.

func (*MCPHandler) VerifyInstalled

func (h *MCPHandler) VerifyInstalled(targetBase string) (bool, string)

VerifyInstalled reports whether the MCP server is registered (and, for packaged servers, whether the extracted directory is on disk).

type OpenCodeConfig

type OpenCodeConfig struct {
	MCP          map[string]any
	Instructions []string
	Other        map[string]any
}

OpenCodeConfig is a minimal view of opencode.json that we care about. Unknown top-level fields are preserved in Other so writes don't drop them. WriteOpenCodeConfig also injects a `$schema` reference if the config doesn't already have one, so newly-materialized files are valid against the OpenCode JSON schema out of the box.

func ReadOpenCodeConfig

func ReadOpenCodeConfig(path string) (*OpenCodeConfig, error)

ReadOpenCodeConfig reads opencode.json (or returns an empty config if the file doesn't exist yet). Supports JSONC. If the file is present but the top-level `mcp` or `instructions` keys carry the wrong JSON type (e.g. a string where an object/array is expected), this returns a typed error rather than silently dropping the value — otherwise the next WriteOpenCodeConfig would clobber the user's data without warning. A JSON null at either key is treated as absent (the JSON convention).

type RuleHandler

type RuleHandler struct {
	// contains filtered or unexported fields
}

RuleHandler installs rules into OpenCode. OpenCode reads rule files through the top-level `instructions` array in opencode.json, so a rule install both materializes the markdown content at <config>/rules/<name>.md and registers that path in opencode.json. Repo-scoped installs register a path relative to the project root; global installs register an absolute path under ~/.config/opencode.

func NewRuleHandler

func NewRuleHandler(meta *metadata.Metadata, registerPath string) *RuleHandler

NewRuleHandler creates a new OpenCode rule handler. registerPath is the string that should be written into opencode.json's `instructions` array; pass the absolute path for global installs or a path relative to the config file's directory for project installs.

func (*RuleHandler) Install

func (h *RuleHandler) Install(ctx context.Context, zipData []byte, targetBase string) error

Install writes the rule markdown to <targetBase>/rules/<name>.md and adds the configured registerPath to opencode.json's instructions array.

func (*RuleHandler) Remove

func (h *RuleHandler) Remove(ctx context.Context, targetBase string) error

Remove deletes the rule file and unregisters its instructions entry.

func (*RuleHandler) VerifyInstalled

func (h *RuleHandler) VerifyInstalled(targetBase string) (bool, string)

VerifyInstalled returns whether the rule file exists on disk. We don't also check the instructions registration because the verify caller may not know the exact register path the original install used (absolute vs. relative depends on scope at install time), but the file's presence under <config>/rules/<name>.md is a stable signal owned by sx.

type SkillHandler

type SkillHandler struct {
	// contains filtered or unexported fields
}

SkillHandler installs skills into an OpenCode config directory.

func NewSkillHandler

func NewSkillHandler(meta *metadata.Metadata) *SkillHandler

NewSkillHandler creates a new OpenCode skill handler.

func (*SkillHandler) Install

func (h *SkillHandler) Install(ctx context.Context, zipData []byte, targetBase string) error

Install extracts the skill into <targetBase>/skills/<name>/.

func (*SkillHandler) Remove

func (h *SkillHandler) Remove(ctx context.Context, targetBase string) error

Remove deletes the skill directory.

func (*SkillHandler) VerifyInstalled

func (h *SkillHandler) VerifyInstalled(targetBase string) (bool, string)

VerifyInstalled checks if the skill is installed with the expected version.

Jump to

Keyboard shortcuts

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