Remove a single installed capability — a griller or a lens — from an existing project (one with a
pharn.config.json). The inverse of add: it deletes exactly that capability's directory and
drops its entry from pharn.config.json.
pharn remove <name> # e.g. pharn remove a11y
pharn remove <role>:<name> # e.g. pharn remove lens:n-plus-one
pharn remove # no arg, in a terminal: interactive multi-select pickerrm is accepted as an alias for remove.
- Reads
pharn.config.json. If none exists — or it is a pre-archetype (module) config — it exits with a hint to runpharn initfirst. - With no argument in a terminal, opens an interactive multi-select picker (grouped by role) over
the capabilities you have installed, then asks for one confirmation listing your picks. With an
argument, resolves it to one installed capability. In a non-interactive context (CI, a pipe),
no-argument
pharn removedoes not prompt — it exits with a usage error (unless nothing is installed, which is reported plainly). - Deletes each selected capability's isolated directory and drops its entry from
capabilities. - Prunes that capability's entries from
pharn.records.json, so the store never describes files that are gone.
Removal needs no network and no clone — everything is derivable from capabilities plus your
filesystem. CONSTITUTION.md, memory-bank/, and your detected archetypes are never touched.
Each capability lives in its own directory, addressed at your project's recorded layout — flat
(pharn-review/<name> for a lens, pharn-pipeline/grillers/<name> for a griller) or the same paths
under pharn/. Removal is therefore precise; siblings are never touched.
- Not installed → a no-op (nothing is written); the CLI lists the capabilities you actually have as the valid values.
- Ambiguous (a name installed in both roles, given without a role) → the CLI asks you to
disambiguate with
griller:/lens:. - Already-deleted directory → treated as done (idempotent).
--yes / -y is accepted but has no effect — capability removal has no confirmation prompt to skip.
Removing a capability also drops its entries from pharn.records.json
— the sidecar recording a hash per file pharn wrote — so nothing in it describes bytes that no longer
exist. Every other entry, and the store's skillsVersion/commit stamp, is left exactly as it was:
remove changes neither version nor commit. If the store is absent, unreadable, or stamped for a
different install state, remove leaves the file untouched rather than minting or rewriting one it
cannot verify — the same rule add follows. The removal itself proceeds either way.
If the entry's recorded source is auto — it was selected for your archetypes by
init or a prior update — remove prints a warning that the next
pharn update may re-add it if the latest resolution still selects it for your
archetypes, because update re-resolves your archetypes every run. Removing a manual entry (one you
added with add) warns nothing.
Silence is not a promise that the removal is permanent. update writes
resolve(archetypes) ∪ manual; dropping the entry removes it from the manual half, but the
resolved half is unaffected. If your archetypes still select that capability — and most capabilities
are universal, so they usually do — the next update may re-add it as auto and name it under
ADDED. remove cannot warn about this: it has no capability index and never fetches one, so it
cannot know whether your archetypes select the thing you are removing. To keep a capability out for
good, remove the archetype that selects it.
The warning is derived from the stored field alone, so remove stays offline. An entry whose source
is absent (a config predating the field) warns nothing — its provenance is genuinely unknown until
the next update infers it, and a wrong warning would be worse than none. See
capabilities[].source.