Appearance
Check out an installed plugin and work on it
What you're doing
You already have a plugin installed on an environment — maybe you built it yourself weeks ago and lost the local source, maybe you inherited it from someone else, maybe you're fixing a real, confirmed bug in your own tenant-owned plugin. Either way you want a real local copy: something you can git diff, edit, and ship back — not a live-database patch, and not a raw dump of API responses.
Before you reach for this: if what you actually want is to extend a shipped, vendor-owned application (HCM, CRM, ...) rather than edit a plugin you own, this is the wrong page — see Extend a shipped application instead. Editing another module's own source is never the right move for a feature request, only for a confirmed bug in a plugin that's genuinely yours.
The command set
Modeled on git, on purpose — the mental model is the same one you already have:
| git | erp | what it does |
|---|---|---|
git branch / git remote -v | erp plugin list | Every plugin installed on the current env, as a readable table (pluginId, version, state, name) — pick one before cloning. --json for the raw response. |
git clone | erp plugin clone <pluginId> [--out <dir>] | A real, full local checkout — every page, menu, data service, data view, mobile nav, provider, application/module membership, and this plugin's own i18n keys it owns, written to <out>/<pluginId>/spk-assembly/metadata/... in the same on-disk shape a shipped module has. Always gets the latest version of every artifact. |
git checkout <ref> | erp plugin checkout <pluginId> --version <n> [--out <dir>] | Same full checkout as clone, but for each artifact independently, prefers version n from that artifact's own history if it has one that old, else falls back to latest. See the caveat below — this is not a single point-in-time snapshot. |
git add / git commit | plain git, inside the checked-out directory | It's a real folder now. cd <pluginId> && git init && git add . && git commit -m "..." gives you real, diffable history — no special erp command needed. |
git push | erp plugin build <dir> -o out.spk then erp plugin publish out.spk --env <name> (or erp plugin push, an alias) | Package your edited spk-assembly/ into a .spk and ship it to an environment. See Publish and upgrade a plugin. |
erp plugin pull <pluginId> (no --full) still exists separately — it's the thin form: just plugin.json + install config + install state, no artifact bodies. Useful for a quick "what version is installed, what's its manifest" check without the full fan-out clone/checkout do.
The complete example
bash
# 1. See what's there
erp plugin list
# PLUGIN ID VERSION STATE NAME
# hcm-foundation 1.0.299 installed HCM Foundation
# office-equipment 1.0.0 installed Office Equipment
# ...
# 2. Clone the one you own
erp plugin clone office-equipment
# == Checking out plugin "office-equipment" ==
# -- spk-assembly/plugin.json (version 1.0.0) --
# -- pages: 3 owned by office-equipment --
# wrote page/office-equipment-list.json (id 4021, v2)
# ...
# -- i18n --
# wrote i18n/en.json (41 keys under "office-equipment.*")
#
# == Full checkout done: 9 artifacts + plugin.json + i18n written to office-equipment/spk-assembly ==
#
# Now a real local directory — e.g.:
# cd office-equipment && git init && git add . && git commit -m "Clone of office-equipment@1.0.0"
# 3. Real git, from here on
cd office-equipment
git init && git add . && git commit -m "Clone of office-equipment@1.0.0"
# 4. Edit under spk-assembly/metadata/, commit as you go
# (e.g. spk-assembly/metadata/page/office-equipment-list.json)
git add -A && git commit -m "Add a status filter to the equipment list"
# 5. Ship it — dev first, then prod
erp plugin build . -o office-equipment-1.0.1.spk
erp plugin publish office-equipment-1.0.1.spk --env dev
# ...verify it looks right...
erp plugin publish office-equipment-1.0.1.spk --env prodWhat actually gets written
office-equipment/
├── plugin.json ← THIN pull output (manifest only, kept for compat)
├── config.json
├── installation-state.json
└── spk-assembly/ ← the real, editable, buildable tree
├── plugin.json
└── metadata/
├── page/*.json
├── menu/*.json
├── mobile_nav/*.json
├── provider/*.json
├── data_service/*.json
├── data_view/*.json
├── application/*.json ← membership rows, if this plugin owns any
├── module/*.json
├── entity/*.json ← best-effort, see caveat below
└── i18n/en.json ← only this plugin's own `<pluginId>.*` keysEvery artifact file is { name, description, metadata, definition } — the same shape erp plugin build reads when packaging a .spk.
Known limits (disclosed, not hidden)
--versionis per-artifact, not a plugin-wide snapshot.plugin.json's ownversion(e.g.1.0.299) is bumped once per.spkrelease, but each individual artifact versions independently, on its own publish cadence. There's no server-side record of "which version of every one of this plugin's 28 artifacts was live when the plugin itself was at 1.0.298" — socheckout --version 4takes artifact-levelv4wherever that artifact has one, and its latest otherwise. Good enough to inspect an older cut of one screen; not a substitute for real git tags on your own commits going forward.- Entities are best-effort. Unlike pages/menus/data-services/etc., entities have no
ownerPluginfield at all — the closest available signal is a free-textcategoryfield, matched against the plugin id. Confirmed live to hold real plugin ids for entity-heavy modules, but it's not an enforced foreign key. erp plugin validateisn't available in packaged SDK mode (needs platform build tooling not shipped in the authoring bundle) — validate what you can witherp schema validate <file> --schema <name>per file instead.
Common mistakes
- Cloning a vendor-owned plugin to "fix" a feature gap. If it's not a confirmed bug in code you own, use Extend a shipped application instead — a companion plugin, not an edit to someone else's source.
- Editing the THIN
plugin.json/config.json/installation-state.jsonfiles at the top level. Those are install-state snapshots, not build input — edit underspk-assembly/metadata/instead; that's whaterp plugin buildactually reads. - Forgetting
--env.clone/checkoutread from whatevererp env use's current environment is (or--env <name>for one call) — cloning fromprodwhen you meantdevgets you prod's live content, not a sandbox to break.
See also
- Publish and upgrade a plugin — the
build/publishhalf of this flow, in more depth. - Extend a shipped application — the right tool when you don't own the plugin's source.
- Validate and test a plugin
