Documentation
¶
Index ¶
- Constants
- func AllClientIDs() []string
- func DetectAssetType(path string, content []byte) *asset.Type
- func DetectClientFromContent(path string, content []byte) (Client, *RuleCapabilities)
- func DetectClientFromPath(path string) (Client, *RuleCapabilities)
- func HasAnyErrors(results map[string]InstallResponse) bool
- func IsImportableFile(path string) bool
- func IsInstructionFile(path string) bool
- func IsRuleFile(path string) bool
- func IsValidClientID(id string) bool
- func Register(client Client)
- type AssetBundle
- type AssetResult
- type BaseClient
- type Client
- type InstallOptions
- type InstallRequest
- type InstallResponse
- type InstallScope
- type InstalledAsset
- type InstalledSkill
- type Orchestrator
- type ParsedRule
- type Registry
- func (r *Registry) DetectAssetType(path string, content []byte) *asset.Type
- func (r *Registry) DetectClientFromContent(path string, content []byte) (Client, *RuleCapabilities)
- func (r *Registry) DetectClientFromPath(path string) (Client, *RuleCapabilities)
- func (r *Registry) DetectInstalled() []Client
- func (r *Registry) FilterByAssetType(assetType asset.Type) []Client
- func (r *Registry) Get(id string) (Client, error)
- func (r *Registry) GetAll() []Client
- func (r *Registry) GetInstructionFiles() []string
- func (r *Registry) GetRulesDirectories() []string
- func (r *Registry) IsImportableFile(path string) bool
- func (r *Registry) IsInstructionFile(path string) bool
- func (r *Registry) IsRuleContent(path string, content []byte) bool
- func (r *Registry) IsRuleFile(path string) bool
- func (r *Registry) ParseRuleFile(path string, content []byte) (*ParsedRule, error)
- func (r *Registry) Register(client Client)
- type ResultStatus
- type RuleCapabilities
- type ScopeType
- type SkillContent
- type UninstallOptions
- type UninstallRequest
- type UninstallResponse
- type VerifyResult
Constants ¶
const ( ClientIDClaudeCode = "claude-code" ClientIDCursor = "cursor" ClientIDCline = "cline" ClientIDGemini = "gemini" ClientIDGitHubCopilot = "github-copilot" ClientIDCodex = "codex" ClientIDOpenClaw = "openclaw" ClientIDKiro = "kiro" )
ClientID constants for supported AI coding clients
Variables ¶
This section is empty.
Functions ¶
func AllClientIDs ¶ added in v0.5.4
func AllClientIDs() []string
AllClientIDs returns all known client IDs
func DetectAssetType ¶ added in v0.9.0
DetectAssetType uses the global registry
func DetectClientFromContent ¶ added in v0.9.0
func DetectClientFromContent(path string, content []byte) (Client, *RuleCapabilities)
DetectClientFromContent uses the global registry
func DetectClientFromPath ¶ added in v0.9.0
func DetectClientFromPath(path string) (Client, *RuleCapabilities)
DetectClientFromPath uses the global registry
func HasAnyErrors ¶
func HasAnyErrors(results map[string]InstallResponse) bool
HasAnyErrors checks if any client installation failed
func IsImportableFile ¶ added in v0.9.0
IsImportableFile uses the global registry
func IsInstructionFile ¶ added in v0.9.0
IsInstructionFile uses the global registry
func IsRuleFile ¶ added in v0.9.0
IsRuleFile uses the global registry
func IsValidClientID ¶ added in v0.5.4
IsValidClientID checks if the given ID is a known client ID
Types ¶
type AssetBundle ¶
AssetBundle contains asset + metadata + zip data
type AssetResult ¶
type AssetResult struct {
AssetName string
Status ResultStatus
Message string
Error error
}
AssetResult represents the result of installing/uninstalling one asset
type BaseClient ¶
type BaseClient struct {
// contains filtered or unexported fields
}
BaseClient provides default implementations for common functionality
func NewBaseClient ¶
func NewBaseClient(id, displayName string, supportedTypes []asset.Type) BaseClient
NewBaseClient creates a new base client with capabilities
func (*BaseClient) DisplayName ¶
func (b *BaseClient) DisplayName() string
func (*BaseClient) ID ¶
func (b *BaseClient) ID() string
func (*BaseClient) RuleCapabilities ¶ added in v0.9.0
func (b *BaseClient) RuleCapabilities() *RuleCapabilities
RuleCapabilities returns nil by default - clients override this if they support rules
func (*BaseClient) SupportsAssetType ¶
func (b *BaseClient) SupportsAssetType(assetType asset.Type) bool
type Client ¶
type Client interface {
// Identity
ID() string // Machine name: "claude-code", "cursor", "cline"
DisplayName() string // Human name: "Claude Code", "Cursor", "Cline"
// Detection
IsInstalled() bool // Check if this client is installed/configured
GetVersion() string // Get client version (empty if not available)
// Capabilities - what asset types this client supports
SupportsAssetType(assetType asset.Type) bool
// Installation - client has FULL control over installation mechanism
// Receives all assets to install at once (batch)
InstallAssets(ctx context.Context, req InstallRequest) (InstallResponse, error)
// Uninstallation - remove assets
UninstallAssets(ctx context.Context, req UninstallRequest) (UninstallResponse, error)
// Asset operations - for MCP server support
// ListAssets returns all installed assets for a given scope
ListAssets(ctx context.Context, scope *InstallScope) ([]InstalledSkill, error)
// ReadSkill reads the content of a specific skill by name
ReadSkill(ctx context.Context, name string, scope *InstallScope) (*SkillContent, error)
// EnsureAssetSupport ensures asset infrastructure is set up for the current context.
// This is called after installation to ensure rules files, MCP servers, etc. are configured.
// For Cursor, this creates local .cursor/rules/skills.md with skills from all applicable scopes.
// Clients that don't need post-install setup can return nil.
EnsureAssetSupport(ctx context.Context, scope *InstallScope) error
// GetBootstrapOptions returns bootstrap options provided by this client.
// These are options for hooks, MCP servers, or other infrastructure the client provides.
GetBootstrapOptions(ctx context.Context) []bootstrap.Option
// GetBootstrapPath returns the path where bootstrap config is stored.
// This is used for display purposes during init.
// Returns empty string if not applicable.
GetBootstrapPath() string
// InstallBootstrap installs client infrastructure (hooks, MCP servers, etc.).
// This sets up hooks for auto-update/usage tracking and registers the sx MCP server.
// Called during installation to ensure all client infrastructure is in place.
// The opts parameter contains only the enabled bootstrap options to install.
// Clients that don't need bootstrap can return nil.
InstallBootstrap(ctx context.Context, opts []bootstrap.Option) error
// UninstallBootstrap removes client infrastructure installed by InstallBootstrap.
// This removes hooks and unregisters the sx MCP server.
// Called during full uninstall (--all flag) to clean up system infrastructure.
// The opts parameter contains only the bootstrap options to uninstall.
// Clients that don't need bootstrap can return nil.
UninstallBootstrap(ctx context.Context, opts []bootstrap.Option) error
// ShouldInstall checks if installation should proceed in hook mode.
// Returns true to proceed, false to skip.
// Called before any installation work begins.
// For clients like Cursor that fire hooks on every prompt, this enables
// tracking conversation IDs to only run install once per conversation.
ShouldInstall(ctx context.Context) (bool, error)
// VerifyAssets checks if assets are actually installed (not just tracked).
// Used by --repair mode to detect discrepancies between tracker and filesystem.
// Each client implements verification according to its own installation structure.
VerifyAssets(ctx context.Context, assets []*lockfile.Asset, scope *InstallScope) []VerifyResult
// ScanInstalledAssets scans for all installed assets of supported types.
// Used during init to detect existing assets that could be imported into the vault.
ScanInstalledAssets(ctx context.Context, scope *InstallScope) ([]InstalledAsset, error)
// GetAssetPath returns the filesystem path to an installed asset.
// Used during import to pass the asset directory to the add command.
// Returns an error for asset types that don't have a simple directory structure.
GetAssetPath(ctx context.Context, name string, assetType asset.Type, scope *InstallScope) (string, error)
// RuleCapabilities returns this client's capabilities for handling rules.
// Returns nil if the client doesn't support rules.
RuleCapabilities() *RuleCapabilities
}
Client represents an AI coding client that can have assets installed
type InstallOptions ¶
type InstallOptions struct {
Force bool // Force reinstall even if already installed
DryRun bool // Don't actually install, just validate
Verbose bool // Verbose output
}
InstallOptions contains optional installation settings
type InstallRequest ¶
type InstallRequest struct {
Assets []*AssetBundle // All assets to install (batch)
Scope *InstallScope // Where to install (global/repo/path)
Options InstallOptions // Additional options
}
InstallRequest contains everything needed for installation
type InstallResponse ¶
type InstallResponse struct {
Results []AssetResult
}
InstallResponse contains results per asset
type InstallScope ¶
type InstallScope struct {
Type ScopeType // Global, Repository, Path
RepoRoot string // Repository root (if applicable)
RepoURL string // Repository URL (if applicable)
Path string // Specific path within repo (if applicable)
}
InstallScope defines where assets should be installed
type InstalledAsset ¶ added in v0.5.4
type InstalledAsset struct {
Name string // Asset name
Description string // Asset description from metadata
Version string // Asset version
Type asset.Type // Asset type (skill, command, agent, etc.)
}
InstalledAsset represents any asset that has been installed in a client
type InstalledSkill ¶
type InstalledSkill struct {
Name string // Skill name
Description string // Skill description from metadata
Version string // Skill version
}
InstalledSkill represents a skill that has been installed
type Orchestrator ¶
type Orchestrator struct {
// contains filtered or unexported fields
}
Orchestrator coordinates installation across multiple clients
func NewOrchestrator ¶
func NewOrchestrator(registry *Registry) *Orchestrator
NewOrchestrator creates a new installation orchestrator
func (*Orchestrator) InstallToAll ¶
func (o *Orchestrator) InstallToAll(ctx context.Context, assets []*AssetBundle, scope *InstallScope, options InstallOptions) map[string]InstallResponse
InstallToAll installs assets to all detected clients concurrently
func (*Orchestrator) InstallToClients ¶
func (o *Orchestrator) InstallToClients(ctx context.Context, assets []*AssetBundle, scope *InstallScope, options InstallOptions, targetClients []Client) map[string]InstallResponse
InstallToClients installs assets to specific clients concurrently
type ParsedRule ¶ added in v0.9.0
type ParsedRule struct {
// Globs are the file patterns this rule applies to.
// This is the canonical format - clients may call this "paths", "globs", or "applyTo".
Globs []string
// Description is a short description of the rule.
Description string
// ClientFields contains client-specific fields that don't have a canonical equivalent.
// For example, Cursor's "alwaysApply" field.
ClientFields map[string]any
// ClientName is the name of the client that parsed this rule.
// Empty if no client was detected.
ClientName string
// Content is the clean markdown content without frontmatter.
Content string
}
ParsedRule is the canonical format returned by all client rule parsers. When a rule file is parsed, the client-specific frontmatter is converted to this common format, which can then be transformed back to client-specific format during installation.
func ParseRuleFile ¶ added in v0.9.0
func ParseRuleFile(path string, content []byte) (*ParsedRule, error)
ParseRuleFile uses the global registry
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry holds all registered clients
func (*Registry) DetectAssetType ¶ added in v0.9.0
DetectAssetType asks clients to determine the asset type for a path. If no client claims it, falls back to generic path/content detection.
func (*Registry) DetectClientFromContent ¶ added in v0.9.0
func (r *Registry) DetectClientFromContent(path string, content []byte) (Client, *RuleCapabilities)
DetectClientFromContent asks each client if it recognizes this content. Returns the client and its capabilities, or nil if no client matches.
func (*Registry) DetectClientFromPath ¶ added in v0.9.0
func (r *Registry) DetectClientFromPath(path string) (Client, *RuleCapabilities)
DetectClientFromPath asks each client if it owns this path. Returns the client and its capabilities, or nil if no client matches.
func (*Registry) DetectInstalled ¶
DetectInstalled returns all clients detected as installed
func (*Registry) FilterByAssetType ¶
FilterByAssetType returns clients that support the given asset type
func (*Registry) GetInstructionFiles ¶ added in v0.9.0
GetInstructionFiles returns all instruction files from all clients.
func (*Registry) GetRulesDirectories ¶ added in v0.9.0
GetRulesDirectories returns all registered rules directories.
func (*Registry) IsImportableFile ¶ added in v0.9.0
IsImportableFile checks if path can be imported as rules. This includes both rule files (e.g., .claude/rules/my-rule.md) and instruction files (e.g., CLAUDE.md).
func (*Registry) IsInstructionFile ¶ added in v0.9.0
IsInstructionFile checks if path matches any client's instruction files. Instruction files are files like CLAUDE.md or AGENTS.md that can contain multiple rule sections.
func (*Registry) IsRuleContent ¶ added in v0.9.0
IsRuleContent checks if any client recognizes this content as a rule.
func (*Registry) IsRuleFile ¶ added in v0.9.0
IsRuleFile checks if any client recognizes this path as a rule file.
func (*Registry) ParseRuleFile ¶ added in v0.9.0
func (r *Registry) ParseRuleFile(path string, content []byte) (*ParsedRule, error)
ParseRuleFile finds the right client and parses the content. If no client is detected, returns the raw content as a ParsedRule.
type ResultStatus ¶
type ResultStatus string
const ( StatusSuccess ResultStatus = "success" StatusFailed ResultStatus = "failed" StatusSkipped ResultStatus = "skipped" )
func TranslateInstallError ¶ added in v0.16.2
func TranslateInstallError(err error, successMessage string) (ResultStatus, string, error)
TranslateInstallError converts an error returned by a per-asset install handler into the AssetResult fields a client should report.
Errors that wrap hook.ErrUnsupportedEvent are translated to StatusSkipped: the hook asset is well-formed but the target client has no lifecycle event to fire it from (e.g. Gemini does not implement `pre-compact`). This is not a user error and should not contribute to the install command's exit status (HasAnyErrors only inspects Status, not Error).
The original error is preserved on the AssetResult even when the status is StatusSkipped so callers can introspect *why* the asset was skipped (for example, to aggregate unsupported-event skips into a per-client summary line, or to escalate them in `--strict` mode).
All other non-nil errors are reported as StatusFailed.
successMessage is used as result.Message when err is nil (for example, the install path or "Installed to /home/...").
type RuleCapabilities ¶ added in v0.9.0
type RuleCapabilities struct {
// ClientName is the identifier for this client (e.g., "claude-code", "cursor")
ClientName string
// RulesDirectory is where rules are stored (e.g., ".claude/rules", ".cursor/rules")
RulesDirectory string
// FileExtension is the file extension for rules (e.g., ".md", ".mdc")
FileExtension string
// InstructionFiles are files that can be parsed for rule sections (e.g., "CLAUDE.md", "AGENTS.md")
InstructionFiles []string
// MatchesPath checks if a path belongs to this client's rules
MatchesPath func(path string) bool
// MatchesContent checks if content appears to belong to this client
MatchesContent func(path string, content []byte) bool
// ParseRuleFile parses a rule file and returns the canonical format
ParseRuleFile func(content []byte) (*ParsedRule, error)
// GenerateRuleFile creates a complete rule file for this client
GenerateRuleFile func(cfg *metadata.RuleConfig, body string) []byte
// DetectAssetType determines what type of asset this file is.
// Returns nil if the client doesn't recognize the file.
// content may be nil if the file hasn't been read yet.
DetectAssetType func(path string, content []byte) *asset.Type
}
RuleCapabilities defines what a client supports for rules. Each client registers its capabilities to enable detection, parsing, and generation.
type SkillContent ¶
type SkillContent struct {
Name string // Skill name
Description string // Skill description from metadata
Version string // Skill version from metadata
Content string // Contents of SKILL.md (or configured prompt file)
BaseDir string // Directory where skill is installed (for resolving @ file references)
}
SkillContent contains the full content of a skill for MCP responses
type UninstallOptions ¶
type UninstallRequest ¶
type UninstallRequest struct {
Assets []asset.Asset
Scope *InstallScope
Options UninstallOptions
}
UninstallRequest contains assets to uninstall
type UninstallResponse ¶
type UninstallResponse struct {
Results []AssetResult
}
UninstallResponse contains results per asset
type VerifyResult ¶
type VerifyResult struct {
Asset *lockfile.Asset // The asset that was verified
Installed bool // Whether the asset is actually installed correctly
Message string // Details about what was found or missing
}
VerifyResult represents the result of verifying a single asset's installation