Help us shape the future of Go! Take the 2026 Go Developer Survey

registry

package
v0.2.4 Latest Latest
Warning

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

Go to latest
Published: Aug 9, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package registry implements the client side of the rysh agent registry (design 005): install .md agents / loops / recipes / humanoids into a project's .rysh/ tree, reproducibly (lockfile) and with install-time consent (declared tools / channels / env are shown before anything is written).

Format is open, service is private (npm model). This package is the open client. The manifest is `rysh.pkg.yaml` (YAML for consistency with the rest of rysh's config; the design's TOML sketch is translated to YAML here).

Index

Constants

View Source
const DefaultIndexURL = "https://packages.rysh.ai/registry/index.json"

DefaultIndexURL is where the first-party index lives. Overridable via config (`registry.url`) or RYSH_REGISTRY_URL so a company can host its own.

View Source
const IndexSchemaVersion = 1

IndexSchemaVersion is the format this client speaks.

View Source
const LockFile = "rysh.lock"

LockFile is the reproducibility lockfile, written under .rysh/.

View Source
const ManifestFile = "rysh.pkg.yaml"

ManifestFile is the per-package manifest name.

Variables

This section is empty.

Functions

func AbsoluteURL

func AbsoluteURL(indexURL, artifactURL string) string

AbsoluteURL resolves a possibly-relative artifact URL against the index URL, so a whole registry can be relocated by moving the directory.

func InstallName

func InstallName(pkgName string) string

InstallName is the on-disk directory name for a (possibly namespaced) package name: "@rysh/code-reviewer" → "code-reviewer".

func IsNamespaced

func IsNamespaced(spec string) bool

IsNamespaced reports whether spec looks like `@ns/name[@version]` rather than a path or URL.

func RenderIndexHTML

func RenderIndexHTML(idx *Index) ([]byte, error)

RenderIndexHTML renders the browsable landing page for an index.

func Sha256Hex

func Sha256Hex(data []byte) string

Sha256Hex returns "sha256:<hex>" over data.

func SplitSpec

func SplitSpec(spec string) (name, version string, err error)

SplitSpec parses `@ns/name` or `@ns/name@version`. The version separator is the LAST '@', since the name itself starts with one.

func TypeDir

func TypeDir(t string) (string, error)

TypeDir maps a package type to its .rysh subdirectory.

Types

type Index

type Index struct {
	// SchemaVersion lets a future format change be rejected loudly by an old
	// client instead of being silently mis-parsed.
	SchemaVersion int                     `json:"schema_version"`
	Generated     string                  `json:"generated,omitempty"`
	Packages      map[string]IndexPackage `json:"packages"`
}

Index is the published catalogue. Versions are keyed by exact semver string; resolution picks the highest by numeric comparison, so "0.10.0" > "0.9.0" rather than sorting lexically.

func FetchIndex

func FetchIndex(indexURL string, timeout time.Duration) (*Index, error)

FetchIndex retrieves and validates the index document.

func (*Index) Outdated

func (idx *Index) Outdated(l *Lock) []UpdateCandidate

Outdated compares the lockfile against the index and returns the installed packages the index publishes a strictly newer version of, sorted by name. Only namespaced installs participate: a package installed from a local dir or ad-hoc tarball has no index identity to update from.

func (*Index) Resolve

func (idx *Index) Resolve(spec string) (name, version string, v IndexVersion, err error)

Resolve maps `@ns/name[@version]` to a concrete artifact. An empty version selects the highest published one.

func (*Index) Search

func (idx *Index) Search(query string) []SearchResult

Search returns the packages whose name or description contains query (case-insensitive; empty query matches everything), sorted by name, each with its highest published version.

type IndexPackage

type IndexPackage struct {
	Description string                  `json:"description,omitempty"`
	Type        string                  `json:"type,omitempty"` // agent|loop|recipe|humanoid
	Versions    map[string]IndexVersion `json:"versions"`
}

IndexPackage is one named package and its published versions.

type IndexVersion

type IndexVersion struct {
	// URL is the tarball. Relative values resolve against the index URL, so a
	// mirror can be moved wholesale without rewriting every entry.
	URL string `json:"url"`
	// Checksum is sha256:… over the tarball bytes. Verified before the archive
	// is opened — see ResolveSpec's caller.
	Checksum string `json:"checksum"`
}

IndexVersion points at one artifact.

type Lock

type Lock struct {
	Packages map[string]LockEntry `yaml:"packages"`
}

Lock is the .rysh/rysh.lock document (name → entry).

func LoadLock

func LoadLock(ryshDir string) (*Lock, error)

LoadLock reads the lockfile from ryshDir (empty lock if absent).

func (*Lock) InstalledNames

func (l *Lock) InstalledNames() []string

InstalledNames returns the sorted set of installed package names.

func (*Lock) Save

func (l *Lock) Save(ryshDir string) error

Save writes the lockfile deterministically (map keys are sorted by yaml.v3).

type LockEntry

type LockEntry struct {
	Version   string `yaml:"version"`
	Type      string `yaml:"type"`
	Checksum  string `yaml:"checksum"`
	Path      string `yaml:"path"`
	Installed string `yaml:"installed"`
}

LockEntry records an installed package for reproducibility.

type Manifest

type Manifest struct {
	Name             string   `yaml:"name"`              // e.g. "@rysh/code-reviewer"
	Version          string   `yaml:"version"`           // semver
	Type             string   `yaml:"type"`              // agent|loop|recipe|humanoid
	Description      string   `yaml:"description"`       // one-liner for search/index page
	Entry            string   `yaml:"entry"`             // primary file, e.g. "SKILL.md"
	MinRysh          string   `yaml:"min_rysh"`          // minimum rysh version
	Checksum         string   `yaml:"checksum"`          // sha256:... over Entry
	DeclaresTools    []string `yaml:"declares_tools"`    // tools the skill uses
	DeclaresChannels []string `yaml:"declares_channels"` // humanoid channels
	DeclaresEnv      []string `yaml:"declares_env"`      // ${ENV} vars referenced
	Signature        string   `yaml:"signature"`         // detached sig (verified namespaces)
}

Manifest describes a package (open spec).

func InstallFromDir

func InstallFromDir(srcDir, ryshDir string, opts Options) (*Manifest, []string, error)

InstallFromDir installs the package rooted at srcDir into ryshDir, returning the manifest and any warnings. It verifies the entry checksum, refuses a sensitive/unsigned package unless Force, and updates the lockfile.

func InstallFromIndex

func InstallFromIndex(artifactURL, expectedChecksum, ryshDir string, opts Options) (*Manifest, []string, error)

InstallFromIndex downloads an indexed artifact, verifies its digest, and only then unpacks it.

The ordering is the point. InstallFromTarball streams the response straight into extractTarGz, so by the time anything could be checked the archive has already been written to disk. For a registry install the index checksum is the only thing standing between "a name" and "code in ~/.rysh", so the bytes are buffered, hashed, compared, and discarded on mismatch — nothing is extracted from an artifact that failed verification.

A missing checksum in the index is refused rather than warned about: an unverifiable artifact from a name-based install is exactly the case where a warning would be clicked through.

func InstallFromTarball

func InstallFromTarball(src, ryshDir string, opts Options) (*Manifest, []string, error)

InstallFromTarball downloads/opens a .tar.gz (URL or local path), extracts it to a temp dir, and installs it. The archive must contain the manifest at its root (or in a single top-level directory).

func ParseManifest

func ParseManifest(data []byte) (*Manifest, error)

ParseManifest parses and validates a manifest.

func (*Manifest) ConsentSummary

func (m *Manifest) ConsentSummary() string

ConsentSummary renders the declared capabilities for an install-time prompt.

func (*Manifest) Sensitive

func (m *Manifest) Sensitive() bool

Sensitive reports whether a package requests high-trust capabilities that warrant explicit confirmation: it wants to commit code or read secrets.

The Signature field deliberately does NOT downgrade this. Nothing in rysh verifies signatures yet, so treating a non-empty signature string as "trusted tier" let any attacker-authored manifest skip the consent gate by writing an arbitrary value — a malicious package got a weaker check than an honest one. Until signature verification exists (design 005 G3), every package is graded on its declared capabilities alone.

type Options

type Options struct {
	Yes   bool // proceed past the consent prompt non-interactively
	Force bool // proceed despite sensitive/unsigned/checksum warnings
}

Options controls an install.

type SearchResult

type SearchResult struct {
	Name        string
	Latest      string
	Type        string
	Description string
}

SearchResult is one `rysh search` hit.

type UpdateCandidate

type UpdateCandidate struct {
	Name      string
	Installed string
	Latest    string
	Artifact  IndexVersion
}

UpdateCandidate is one installed package with a newer published version.

Jump to

Keyboard shortcuts

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