Documentation
¶
Overview ¶
Package plugins provides OCI artifact types, media types, local storage, and remote registry operations for ToolHive plugin packages.
A plugin is an OCI artifact containing a .claude-plugin/plugin.json manifest and its component directories. This package defines the constants, data structures, storage layer, packager, and registry client that the rest of the ToolHive ecosystem uses to package, push, pull, and cache plugins as OCI images.
Media Types and Constants ¶
Standard OCI media types and ToolHive-specific annotation/label keys:
// Artifact type identifies a plugin manifest plugins.ArtifactTypePlugin // "dev.toolhive.plugins.v1" // Annotations carry metadata in manifests plugins.AnnotationPluginName plugins.AnnotationPluginVersion plugins.AnnotationPluginComponents // Labels carry metadata in OCI image configs plugins.LabelPluginName plugins.LabelPluginFiles
Registry Client ¶
The Registry type implements RegistryClient for pushing and pulling plugin artifacts to/from OCI-compliant registries (GHCR, ECR, Docker Hub, etc.). It uses ORAS for registry operations and the Docker credential store for authentication by default:
reg, err := plugins.NewRegistry() // Push an artifact err = reg.Push(ctx, store, indexDigest, "ghcr.io/myorg/my-plugin:v1.0.0") // Pull an artifact digest, err := reg.Pull(ctx, store, "ghcr.io/myorg/my-plugin:v1.0.0")
Use functional options to customise behaviour:
reg, err := plugins.NewRegistry(
plugins.WithPlainHTTP(true), // for local dev registries
plugins.WithCredentialStore(myStore), // custom auth
)
Stability ¶
This package is Alpha. Breaking changes are possible between minor versions.
Index ¶
- Constants
- Variables
- func DefaultStoreRoot() string
- func ParseRequiresAnnotation(annotations map[string]string) []string
- func StoreRoot(dataHome string) string
- type ComponentInventory
- type PackageOptions
- type PackageResult
- type Packager
- type PluginConfig
- type PluginPackager
- type Registry
- type RegistryClient
- type RegistryOption
- type Store
- func (s *Store) DeleteBuild(ctx context.Context, tag string) error
- func (s *Store) DeleteTag(ctx context.Context, tag string) error
- func (s *Store) GetBlob(ctx context.Context, d digest.Digest) ([]byte, error)
- func (s *Store) GetIndex(ctx context.Context, d digest.Digest) (*ocispec.Index, error)
- func (s *Store) GetManifest(ctx context.Context, d digest.Digest) ([]byte, error)
- func (s *Store) IsIndex(ctx context.Context, d digest.Digest) (bool, error)
- func (s *Store) ListTags(ctx context.Context) ([]string, error)
- func (s *Store) PutBlob(ctx context.Context, content []byte) (digest.Digest, error)
- func (s *Store) PutManifest(ctx context.Context, content []byte) (digest.Digest, error)
- func (s *Store) Resolve(ctx context.Context, tag string) (digest.Digest, error)
- func (s *Store) Root() string
- func (s *Store) Tag(ctx context.Context, d digest.Digest, tag string) error
- func (s *Store) Target() oras.Target
Constants ¶
const ( // AnnotationPluginName is the annotation key for plugin name. AnnotationPluginName = "dev.toolhive.plugins.name" // AnnotationPluginDescription is the annotation key for plugin description. AnnotationPluginDescription = "dev.toolhive.plugins.description" // AnnotationPluginVersion is the annotation key for plugin version. AnnotationPluginVersion = "dev.toolhive.plugins.version" // AnnotationPluginLicense is the annotation key for plugin license. AnnotationPluginLicense = "dev.toolhive.plugins.license" // AnnotationPluginFiles is the annotation key for plugin files (JSON array). AnnotationPluginFiles = "dev.toolhive.plugins.files" // AnnotationPluginComponents is the annotation key for plugin component inventory (JSON object). AnnotationPluginComponents = "dev.toolhive.plugins.components" // AnnotationPluginRequires is the annotation key for plugin external dependencies (JSON array of OCI references). AnnotationPluginRequires = "dev.toolhive.plugins.requires" )
Annotation keys for plugin metadata in manifests.
const ( // LabelPluginName is the label key for plugin name. LabelPluginName = "dev.toolhive.plugins.name" // LabelPluginDescription is the label key for plugin description. LabelPluginDescription = "dev.toolhive.plugins.description" // LabelPluginVersion is the label key for plugin version. LabelPluginVersion = "dev.toolhive.plugins.version" // LabelPluginLicense is the label key for plugin license. LabelPluginLicense = "dev.toolhive.plugins.license" // LabelPluginFiles is the label key for plugin files (JSON array). LabelPluginFiles = "dev.toolhive.plugins.files" // LabelPluginComponents is the label key for plugin component inventory (JSON object). LabelPluginComponents = "dev.toolhive.plugins.components" // LabelPluginRequires is the label key for plugin external dependencies (JSON array of OCI references). LabelPluginRequires = "dev.toolhive.plugins.requires" )
Label keys for plugin metadata in OCI image config.
const (
// ArtifactTypePlugin identifies plugin artifacts in manifests.
ArtifactTypePlugin = "dev.toolhive.plugins.v1"
)
Artifact type for plugin identification.
const (
// ManifestFileName is the required manifest file name for a plugin directory.
ManifestFileName = ".claude-plugin/plugin.json"
)
Variables ¶
var ( // ErrInvalidPluginDir indicates the plugin directory is missing, not a // directory, or otherwise unsafe to read (e.g. contains path traversal). ErrInvalidPluginDir = errors.New("invalid plugin directory") // ErrPluginManifestMissing indicates .claude-plugin/plugin.json is not // present in the plugin directory. ErrPluginManifestMissing = errors.New(".claude-plugin/plugin.json missing") // ErrInvalidPluginManifest indicates the plugin manifest is malformed, // oversized, or missing required fields such as the plugin name. ErrInvalidPluginManifest = errors.New("invalid plugin manifest") // ErrTooManyFiles indicates the plugin directory exceeds the maximum // allowed number of files. ErrTooManyFiles = errors.New("too many files in plugin directory") // ErrPluginTooLarge indicates the plugin directory exceeds the maximum // allowed total size. ErrPluginTooLarge = errors.New("plugin directory too large") // ErrInvalidPluginFile indicates a per-file issue inside the plugin // directory: a symlink, a non-regular file, or an unreadable entry. ErrInvalidPluginFile = errors.New("invalid plugin file") )
Sentinel errors returned (wrapped) by the packager so callers can classify failures with errors.Is instead of matching error message strings. The underlying error message is preserved at each call site via fmt.Errorf with %w; only the classification is added.
Functions ¶
func DefaultStoreRoot ¶
func DefaultStoreRoot() string
DefaultStoreRoot returns the default store root directory using XDG base directory conventions.
func ParseRequiresAnnotation ¶
ParseRequiresAnnotation parses plugin dependency references from manifest annotations. Returns nil if the annotation is missing or invalid.
Types ¶
type ComponentInventory ¶
ComponentInventory summarizes the component types declared by a plugin.
func ParseComponentsAnnotation ¶
func ParseComponentsAnnotation(annotations map[string]string) ComponentInventory
ParseComponentsAnnotation parses plugin component inventory from manifest annotations. Returns nil if the annotation is missing or invalid.
type PackageOptions ¶
type PackageOptions struct {
// Epoch is the timestamp to use for reproducible builds.
Epoch time.Time
// Platforms specifies target platforms for the image index.
// If empty, defaults to DefaultPlatforms.
Platforms []ocispec.Platform
}
PackageOptions configures plugin packaging.
func DefaultPackageOptions ¶
func DefaultPackageOptions() PackageOptions
DefaultPackageOptions returns default packaging options. Respects SOURCE_DATE_EPOCH for reproducible builds.
type PackageResult ¶
type PackageResult struct {
IndexDigest digest.Digest
ManifestDigest digest.Digest
ConfigDigest digest.Digest
LayerDigest digest.Digest
Config *PluginConfig
Platforms []ocispec.Platform
}
PackageResult contains the result of packaging a plugin.
type Packager ¶
type Packager struct {
// contains filtered or unexported fields
}
Packager creates reproducible OCI artifacts from plugin directories.
func NewPackager ¶
NewPackager creates a new packager with the given store. Panics if store is nil.
func (*Packager) Package ¶
func (p *Packager) Package(ctx context.Context, pluginDir string, opts PackageOptions) (*PackageResult, error)
Package packages a plugin directory into an OCI artifact in the local store.
type PluginConfig ¶
type PluginConfig struct {
Name string `json:"name"`
Description string `json:"description"`
Version string `json:"version,omitempty"`
License string `json:"license,omitempty"`
Files []string `json:"files"`
Components ComponentInventory `json:"components,omitempty"`
Requires []string `json:"requires,omitempty"`
}
PluginConfig represents plugin metadata extracted from OCI image config labels.
func PluginConfigFromImageConfig ¶
func PluginConfigFromImageConfig(imgConfig *ocispec.Image) (*PluginConfig, error)
PluginConfigFromImageConfig extracts PluginConfig from OCI image config labels.
type PluginPackager ¶
type PluginPackager interface {
// Package packages a plugin directory into an OCI artifact in the local store.
Package(ctx context.Context, pluginDir string, opts PackageOptions) (*PackageResult, error)
}
PluginPackager creates OCI artifacts from plugin directories.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry provides operations for pushing and pulling plugins from OCI registries.
func NewRegistry ¶
func NewRegistry(opts ...RegistryOption) (*Registry, error)
NewRegistry creates a new registry client with the given options. By default it uses the Docker credential store for authentication.
type RegistryClient ¶
type RegistryClient interface {
// Push pushes an artifact from the local store to a remote registry.
Push(ctx context.Context, store *Store, manifestDigest digest.Digest, ref string) error
// Pull pulls an artifact from a remote registry into the local store.
Pull(ctx context.Context, store *Store, ref string) (digest.Digest, error)
}
RegistryClient provides remote OCI registry operations for plugins.
type RegistryOption ¶
type RegistryOption func(*Registry)
RegistryOption configures a Registry.
func WithCredentialStore ¶
func WithCredentialStore(store credentials.Store) RegistryOption
WithCredentialStore sets a custom credential store for registry authentication. If not provided, the default Docker credential store is used.
func WithPlainHTTP ¶
func WithPlainHTTP(enabled bool) RegistryOption
WithPlainHTTP configures whether the registry client uses plain HTTP (insecure) connections.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store provides local OCI artifact storage backed by an OCI Image Layout.
func NewStore ¶
NewStore creates a new local OCI store at the given root directory. The directory is initialized as an OCI Image Layout with blobs/, oci-layout, and index.json.
func (*Store) DeleteBuild ¶
DeleteBuild removes a tag and, if no other tag shares the same digest, deletes all associated blobs (config, layers, manifest, and index if applicable). Use DeleteTag when tag-only removal is desired and blob cleanup is not needed.
func (*Store) DeleteTag ¶
DeleteTag removes a tag from the store index without deleting the underlying blobs.
func (*Store) GetManifest ¶
GetManifest retrieves a manifest by digest.
func (*Store) PutManifest ¶
PutManifest stores a manifest and returns its digest.