Documentation menu

Commands

embr patch

Last updated August 24, 2026

embr patch <scope>/<name>[@version] [--force]
embr patch commit <scope>/<name>[@version]
embr patch remove <scope>/<name>[@version]

Edit a dependency's source and keep the edit across installs. When a package has a bug you can fix but no release you can wait for, patch it: the fix lives in your repository as a plain diff, and every later embr install re-applies it. pnpm's patch/patch-commit and pesde's [patches] are the models. Requires git on PATH.

The workflow#

embr patch chief/traits            # 1. extract a working copy
# edit .ember-patch/chief_traits@0.2.0/ ...
embr patch commit chief/traits     # 2. save the edit as a patch
embr install                       # 3. apply it

embr patch <name> extracts a pristine copy of the package's published bytes into .ember-patch/scope_name@version/ and hands you the path. The version comes from the lockfile when one exists (no network), or a fresh resolution otherwise; the package must be a dependency of this project. If a working copy already exists, --force replaces it with fresh published bytes.

embr patch commit <name> diffs your edits against the published state, writes patches/scope_name@version.patch, records it under [patches] in ember.toml, and deletes the working copy. New files you created are included, and the diff is binary-safe, so image or model assets survive the round trip. An untouched working copy commits nothing and is kept. Commit the patches/ folder — it is part of the repository.

embr patch remove <name> drops the [patches] entry and deletes the patch file. Without @version the name must match exactly one entry; several matches list themselves and ask for the version.

The [patches] table#

[patches]
"chief/traits@0.2.0" = "patches/chief_traits@0.2.0.patch"
  • Keys are scope/name@version with an exact version — a patch is a claim about one published archive, and a range would make "which bytes" depend on resolution.
  • Values are repo-relative paths. Absolute paths and .. escapes are refused, so installs stay reproducible for everyone who clones the repository.
  • Only the installing project's table applies — a dependency's own [patches] is never consulted, and publish strips the table from the packed manifest, same as [overrides].
  • Workspace members can't be patched — edit their source directly, that is what workspaces are for.

What you are editing#

The working copy is the archive as published, not the installed folder. Ember's install-time transforms — Rojo project mirroring, instance require rewriting, nested link files — run after the patch is applied, so a patch keeps working when those transforms change, and the working copy won't be byte-identical to what sits in packages/<env>/.ember/.

How install applies patches#

  • Patches attach to the resolved graph before anything downloads, and every [patches] key must land exactly. A key naming a package that is no longer a dependency, resolved to a different version, or that covers only some environment roots is a hard error, not a skipped patch — an unapplied patch could be someone's security fix.
  • The patch is applied to the freshly extracted tree with git apply; a patch that no longer applies is a hard error naming the package, the file, and git's own message.
  • The lockfile records each patch's file and a hash of its bytes. --locked replays exactly that, and errors if the file is missing or has changed since it was locked. Editing a patch file also busts the fast path, so the next install re-applies for real.

Patch keys pin an exact version. When the dependency resolves to a new version — a ^ requirement picking up a release, or you bumping the requirement — install fails with the mismatch rather than silently dropping your fix. Re-do the patch against the new version (embr patch, re-apply your edit, embr patch commit) or embr patch remove it.

Housekeeping#

  • .ember-patch/ is scratch space: embr init git-ignores it for new projects, and embr patch prints a tip when an existing project hasn't.
  • Neither .ember-patch/ nor the stripped [patches] table is ever published; the patches/ folder ships with your package only if the manifest's includes/excludes let it (harmless, but excludable).