Documentation
¶
Overview ¶
Package bundle implements the canonical nSelf paid plugin bundle catalog plus install/remove orchestration with license validation, version pinning, and atomic rollback on failure (S2.T03/T04/T22).
Bundle membership is authoritative here — the source of truth that mirrors .claude/docs/sport/F06-BUNDLE-INVENTORY.md. The cmd layer must consume this package; do NOT duplicate the bundle map elsewhere.
installer.go — S2.T03: `nself bundle install <bundle>` orchestrator.
Atomicity: pre-flight ALL licenses, then install each constituent plugin sequentially via plugin.Install. On any per-plugin failure we roll back by removing every plugin we successfully installed in THIS invocation. Plugins that were already on disk before the call are left untouched.
--dry-run prints the planned actions and exits without filesystem changes. --force bypasses the license pre-flight (logged as "license-bypass"). --strict fails if any plugin in the bundle is missing from the registry
(default: skip missing with a warning).
--channel selects stable/beta/canary for version resolution (T22).
remover.go — S2.T04: `nself bundle remove <bundle>` orchestrator.
Walks the bundle's plugin list and removes each one via plugin.Remove. By default plugin data volumes are dropped; --keep-data preserves them. --dry-run prints the planned actions without touching the filesystem.
Removal proceeds in REVERSE plugin order so that a plugin earlier in the list (often a dependency of later plugins, e.g. ai before claw) is removed last. plugin.Remove's reverse-dependency check is bypassed via force=true because the operator has explicitly asked to tear down the whole bundle.
version_resolver.go — S2.T22: resolve bundle slugs + release channels into concrete plugin version pins. Reads plugins-pro/registry.json via the existing internal/plugin registry fetcher so the same fallback + cache chain (primary URL → GitHub raw → stale cache) applies.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var DisplayOrder = []string{
"nclaw", "nchat", "nfamily", "ntv", "clawde", "nsentry", "ntask", "nself-plus",
}
DisplayOrder is the canonical print order for bundle listings.
Functions ¶
func Names ¶
func Names() []string
Names returns every known bundle slug sorted alphabetically. Useful for error messages and shell completion.
func ResolveVersion ¶
ResolveVersion returns the version pin for a single plugin under the given channel. Exposed for callers that need to pin one plugin (e.g. compat-check, install --version<latest-channel>).
func UnknownBundleError ¶
UnknownBundleError formats a friendly error when a slug does not match a known bundle. Includes the sorted list of valid names as a hint.
Types ¶
type Bundle ¶
type Bundle struct {
Name string // Display name (with ɳ glyph)
Slug string // CLI-arg lowercase identifier
Price string // Human-readable price string
Description string // Optional one-line description
Plugins []string // Plugin slugs in the bundle (nil for meta-bundle)
}
Bundle describes a canonical nSelf plugin bundle.
func Get ¶
Get returns the Bundle for the given slug. The slug is case-insensitive and trimmed. Returns ok=false when the slug is unknown; callers can call Names() to render a useful error hint.
func (Bundle) IsInstallable ¶
IsInstallable reports whether the bundle can be installed via `nself bundle install`. Meta-bundles (nself-plus) and free bundles (ntask) are not installable as a unit — operators install their constituent plugins directly via `nself plugin install`.
type Channel ¶
type Channel string
Channel is a release-channel identifier (stable/beta/canary). Channels filter candidate registry entries by their PublishStatus before version selection:
stable → status in {"", "stable"}
beta → status in {"", "stable", "beta"}
canary → all installable statuses (adds "experimental")
"deprecated" and "eol" entries are never resolved by this function regardless of channel — those install paths require explicit --allow-eol acknowledgment through plugin.CheckEOLBlock, not silent bundle install.
type InstallOpts ¶
type InstallOpts struct {
DryRun bool
Force bool
Strict bool
Channel Channel
// Out is the stream to print human-facing progress messages.
// nil → os.Stderr.
Out io.Writer
// PluginDir overrides the default plugin install location. Empty → use
// the same resolution as cmd/commands/plugin.resolvePluginDir.
PluginDir string
// Config overrides the loaded project config. Optional — when nil the
// caller-loaded cfg is used by Install via cfg arg.
Config *config.Config
// contains filtered or unexported fields
}
InstallOpts captures the user-controllable knobs for bundle install.
type InstallResult ¶
type InstallResult struct {
Bundle string
Channel Channel
Planned []string // plugins planned for install (post channel + strict filter)
Skipped []string // plugins skipped because missing from registry (non-strict)
Installed []string // plugins successfully installed in this call
RolledBack []string // plugins removed during rollback after a failure
LicenseBypass bool // true when --force was used
DryRun bool
}
InstallResult captures the outcome of a bundle install for callers that need to surface details (e.g. CR/QA harness, audit logger).
func Install ¶
func Install(ctx context.Context, bundleSlug string, opts InstallOpts) (*InstallResult, error)
Install runs the bundle install flow. The returned InstallResult is populated even on error so callers (and tests) can inspect partial state.
type RemoveOpts ¶
type RemoveOpts struct {
DryRun bool
KeepData bool
// Out is the stream for human-facing progress; nil → os.Stderr.
Out io.Writer
// PluginDir overrides the default plugin location.
PluginDir string
// Config overrides the loaded project config.
Config *config.Config
// contains filtered or unexported fields
}
RemoveOpts captures the user-controllable knobs for bundle remove.
type RemoveResult ¶
type RemoveResult struct {
Bundle string
Planned []string // plugins planned for removal (post not-installed filter)
NotInstalled []string
Removed []string
Failed []string
DryRun bool
KeepData bool
}
RemoveResult captures the outcome of a bundle remove call.
func Remove ¶
func Remove(ctx context.Context, bundleSlug string, opts RemoveOpts) (*RemoveResult, error)
Remove tears down every plugin in the bundle. Plugins not currently installed are reported under NotInstalled and skipped. Per-plugin removal failures are collected in Failed and surfaced as the returned error, but removal continues for the remaining plugins rather than aborting on first failure — partial cleanup is more useful than a hung-bundle state.
type VersionPins ¶
VersionPins maps plugin slug → concrete semver version string for every installable plugin in a bundle, after channel filtering.
func ResolveBundleVersions ¶
func ResolveBundleVersions(ctx context.Context, bundleSlug string, channel Channel) (VersionPins, error)
ResolveBundleVersions returns the resolved version pins for every plugin in the given bundle, using the highest registry version that satisfies the channel filter. Returns an error for unknown bundle slugs or non-installable bundles (nself-plus, ntask).
Network behavior: delegates to plugin.FetchRegistry which respects the registry cache + fallback chain. A registry fetch failure with no stale cache returns an error; callers should respect that.