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@versionwith 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.
--lockedreplays 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 initgit-ignores it for new projects, andembr patchprints a tip when an existing project hasn't.- Neither
.ember-patch/nor the stripped[patches]table is ever published; thepatches/folder ships with your package only if the manifest'sincludes/excludeslet it (harmless, but excludable).