Skip to content

Package generated host packs into publishable npm plugins with a package-relative installer #252

Closed

Description

@ScriptedAlchemy

Summary

Make a plugin produced by Agent Bundle publishable as a self-contained npm package. Installing the tarball must provide the exact generated Claude, Codex, and Cursor host packs plus a package-relative install command, without requiring the source repository, a checkout path, or a project-maintained install script.

This is the missing distribution boundary between the host packs tracked by #181 and ordinary npm publishing. It does not require a reusable GitHub Action: once the package is self-contained, the repository's existing Changesets/npm/provenance flow is sufficient.

Verified gap

  • Agent Bundle currently writes generated host artifacts to the configured artifact directory while npm package outputs are built separately into dist.
  • The publishable scaffolder allowlists dist and README, so npm pack excludes the generated host packs, INSTALL.md, install.mjs, marketplace manifests, skills, hooks, MCP entries, and artifact provenance.
  • The framework install command defaults its source bundle to the current working directory; a published plugin has no package-local entrypoint that resolves its bundled host packs from import.meta.url.
  • Cargo Hauler therefore still maintains host-install documentation and a Cursor installer even though that logic is framework-generic. Its current npm manifest is private and its allowlist would not publish artifact/plugin.
  • The framework release checks prove compiler-package tarballs and local built-directory installs, but not installing a plugin from the exact tarball intended for publication after deleting its source tree.

Relationship to existing issues

This issue owns packaging those outputs into a consumer plugin's npm tarball and locating them at runtime from the installed package.

Acceptance criteria

  • A publishable plugin tarball contains every selected host pack, required executable payload, marketplace manifest, skills/hooks/MCP resources, INSTALL.md, and artifact manifest/provenance.
  • A generated package-local bin resolves the bundled artifact from import.meta.url rather than process.cwd(), then delegates to the existing Agent Bundle installer for Claude, Codex, and Cursor.
  • npm install itself performs no host mutation; installation is an explicit documented command such as npx install .
  • From an empty directory, after deleting the repository and source tree, a test installs the exact packed tarball and registers each supported host from package-local assets.
  • Generated scaffolds provide correct files, bin, and prepack/build behavior with no project-maintained host installer.
  • npm pack --json validates the full expected host-pack inventory and fails for missing, stale, or source-relative entries.
  • Package version, host-manifest version, artifact provenance, and installed version are checked for agreement.
  • The release workflow publishes the same verified tarball; no separate host-specific publishing service or reusable GitHub Action is introduced unless later evidence requires one.

Activity

  1. ScriptedAlchemy commented on Sep 2, 2026

    @ScriptedAlchemy
    OwnerAuthor

    Decision (2026-09-01): prioritized next — lane in flight; cargo-conductor #25/#26 are the first consumers.

  2. ScriptedAlchemy commented on Sep 2, 2026

    @ScriptedAlchemy
    OwnerAuthor

    Landed across four PRs, all gated locally (scoped tests + typecheck + lint, plus the real-host proofs):

    #281 — framework contract (2655ca58d)

    • Every package build with install-capable targets now emits a generated, executable, package-relative installer bin (dist/bin/<name>-install.js, or <name>.js when the package has no other bin claim on the plugin name). It resolves the bundled artifact/ root from import.meta.url — never process.cwd() or repo layout — and delegates to the existing agent-bundle install engine (installBundle). npm install itself never mutates a host; installation is the explicit npx <bin> install <host> [--scope user|project] [--json].
    • New agent-bundle prepack command: runs the release build, then npm pack --dry-run --json --ignore-scripts, and fail-closes the tarball inventory via the shared packOutputFromJson — AB7010 missing allowlisted artifacts, AB7011 stale artifact hashes vs the artifact manifest, AB7012 bin targets not shipped, AB7013 package/host-manifest/artifact version disagreement.

    #283 — empty-dir install-from-tarball proof (09ac90b0f)

    • packed-host-install-proof.test.ts at the host-install proof level: one agent-bundle prepack fixture build, one real npm pack, npm install of the exact tarball into a verified-empty consumer, source tree deleted and asserted absent, then per host the installed node_modules/.bin/<bin> install <host> --json runs. Claude Code 2.1.257 and codex-cli 0.147.0 registrations observed through the hosts' own CLIs (binary-gated with honest skips), Cursor placement schema-validated and idempotent; installed/registered versions asserted equal to the fixture package version. Wired as test:host-install:packed and into native-host-smoke.yml.

    #288 — packed-consumer regression fix (abf73be61)

    • The release-lane scaffolder matrix caught a real feat(package): package-relative host installer bins and the agent-bundle prepack inventory gate (#252) #281 regression: new URL(<non-literal>, import.meta.url) inside the shared installer runtime made Rspack synthesize a directory ContextModule in consumers that build through a tarball-installed agent-bundle, and the provenance collector correctly fail-closed (AB5000). The baked-literal URL resolution moved into the generated wrapper; regression coverage rides the packed-consumer deleted-source journey.

    #289 — scaffold adoption + release wiring (0b46b0278)

    • cli-tool and mcp-server templates ship artifact in files, the generated installer bin, and agent-bundle prepack as npm prepack; the skills-only minimal template intentionally stays unpackaged. The release matrix asserts the packed inventory (artifact manifest, all three host manifests, installer bin) from a real npm pack.
    • pnpm release = pnpm check:release && changeset publish (pack dry-run, release audit, packed release pool — including the scaffolder matrix — before any publish), and the changesets publish step sets NPM_CONFIG_PROVENANCE: true.

    One deliberate remainder, owned by the release owner rather than this issue: .changeset/config.json keeps "access": "restricted" until the final package name/scope + license decision documented in docs/preview-packages.md; the provenance publish path is wired and gated behind it.

    Downstream: cargo-conductor #25/#26 can adopt this directly — notes posted there. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions