Ejection and merging
Transfer an eligible artifact to application ownership while retaining a reviewable path for upstream changes.
Ejection is the final customization option after configuration and replacing a runtime seam. It moves one eligible source artifact from package ownership to application ownership without disconnecting it from future upstream review.
Before ejecting
Use the smallest change that satisfies the application:
- Configure the package through its public options.
- Replace an explicit bridge or adapter seam.
- Eject only when neither boundary can represent the required behavior.
Security-critical artifacts cannot be ejected. Signature verification, token validation, and similar package guarantees must remain package-managed so fixes arrive through version updates.
Select an artifact
npx playstack eject @playstack/example --target=example-source --dry-run
npx playstack eject @playstack/example --target=example-sourceThe package manifest must declare the artifact as ejectable. The CLI verifies the published hash, writes the application-owned target, saves the installed upstream base beneath .playstack/base, and records the relationship in .playstack/ejected.json.
After ejection, edit the application target normally. Do not edit the saved base; it exists solely to support deterministic three-way merges.
Reconcile an upstream change
npx playstack merge example-source
npx playstack merge --allA merge compares three inputs:
| Input | Ownership |
|---|---|
| Saved base | The exact upstream source present when the artifact was ejected or last merged. |
| Application target | The repository's current, application-owned implementation. |
| New upstream | The source shipped by the newly installed package version. |
A clean merge updates the application target and advances the saved base. An unchanged upstream produces no write.
Conflict behavior
Conflicts never overwrite the application target with unresolved markers. The CLI writes a conflict report under .playstack/conflicts and returns the unsafe-conflict exit code so a human can review the competing changes.
When merging more than two ejected artifacts with --all, the CLI defaults to a dry run to avoid applying a large unreviewed ownership change at once.
Updates and security
playstack doctor --check reports when an ejected artifact's upstream hash has changed. Security-tagged upstream changes are called out distinctly.
playstack update attempts safe three-way merges after updating installed packages. In pull-request mode, package and managed changes form the primary branch, clean ejected merges form a dependent review branch, and each conflict receives a separate draft branch. Conflict markers are never committed.
Read Updates and CI before automating this workflow.