plugins

package
v0.0.25 Latest Latest
Warning

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

Go to latest
Published: Jun 23, 2026 License: Apache-2.0 Imports: 29 Imported by: 0

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

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

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

View Source
const (
	// ArtifactTypePlugin identifies plugin artifacts in manifests.
	ArtifactTypePlugin = "dev.toolhive.plugins.v1"
)

Artifact type for plugin identification.

View Source
const (
	// ManifestFileName is the required manifest file name for a plugin directory.
	ManifestFileName = ".claude-plugin/plugin.json"
)

Variables

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

func ParseRequiresAnnotation(annotations map[string]string) []string

ParseRequiresAnnotation parses plugin dependency references from manifest annotations. Returns nil if the annotation is missing or invalid.

func StoreRoot

func StoreRoot(dataHome string) string

StoreRoot returns the plugins store root within the given data home directory. This is the injectable, testable form. For the standard XDG location, use DefaultStoreRoot.

Types

type ComponentInventory

type ComponentInventory map[string]int

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

func NewPackager(store *Store) *Packager

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.

func (*Registry) Pull

func (r *Registry) Pull(ctx context.Context, store *Store, ref string) (digest.Digest, error)

Pull pulls a plugin artifact from a remote registry to the local store. Returns the digest of the pulled artifact (index or manifest).

func (*Registry) Push

func (r *Registry) Push(ctx context.Context, store *Store, artifactDigest digest.Digest, ref string) error

Push pushes a plugin artifact from the local store to a remote registry. The digest can be either an index digest or a manifest digest.

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

func NewStore(root string) (*Store, error)

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

func (s *Store) DeleteBuild(ctx context.Context, tag string) error

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

func (s *Store) DeleteTag(ctx context.Context, tag string) error

DeleteTag removes a tag from the store index without deleting the underlying blobs.

func (*Store) GetBlob

func (s *Store) GetBlob(ctx context.Context, d digest.Digest) ([]byte, error)

GetBlob retrieves a blob by digest.

func (*Store) GetIndex

func (s *Store) GetIndex(ctx context.Context, d digest.Digest) (*ocispec.Index, error)

GetIndex retrieves and parses an image index by digest.

func (*Store) GetManifest

func (s *Store) GetManifest(ctx context.Context, d digest.Digest) ([]byte, error)

GetManifest retrieves a manifest by digest.

func (*Store) IsIndex

func (s *Store) IsIndex(ctx context.Context, d digest.Digest) (bool, error)

IsIndex checks if the content at the given digest is an image index.

func (*Store) ListTags

func (s *Store) ListTags(ctx context.Context) ([]string, error)

ListTags returns all tags in the store.

func (*Store) PutBlob

func (s *Store) PutBlob(ctx context.Context, content []byte) (digest.Digest, error)

PutBlob stores a blob and returns its digest.

func (*Store) PutManifest

func (s *Store) PutManifest(ctx context.Context, content []byte) (digest.Digest, error)

PutManifest stores a manifest and returns its digest.

func (*Store) Resolve

func (s *Store) Resolve(ctx context.Context, tag string) (digest.Digest, error)

Resolve resolves a tag to a manifest digest.

func (*Store) Root

func (s *Store) Root() string

Root returns the store root directory.

func (*Store) Tag

func (s *Store) Tag(ctx context.Context, d digest.Digest, tag string) error

Tag associates a tag with a manifest digest.

func (*Store) Target

func (s *Store) Target() oras.Target

Target returns the underlying oras.Target for direct use by registry operations.

Directories

Path Synopsis
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.

Jump to

Keyboard shortcuts

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