Problem
matter fabric remove @1 only deletes the device from the local store — the device itself is never notified and keeps its fabric credentials. This means:
- The device still thinks it belongs to our fabric and won't enter commissioning mode for re-pairing.
- A factory reset on the device is required before it can be commissioned again.
- The equivalent chip-tool command (
chip-tool pairing unpair 1) sends RemoveFabric over CASE before deleting locally.
Proposed Solution
Add a top-level matter decommission command that mirrors matter commission:
What it should do
- Establish a CASE session to the device (reuse daemon session if available).
- Determine the fabric index — read the device's
OperationalCredentials.Fabrics attribute to find the entry matching our fabric ID, then extract its FabricIndex.
- Send
RemoveFabric (0x0A) on the OperationalCredentials cluster (endpoint 0) with the resolved fabric index.
- On success — delete the node from the local store and evict the cached CASE session.
- Print confirmation — e.g.
Decommissioned "Kitchen Light" (@1) — device fabric data removed.
Clarify fabric remove as local-only
Make the behavioral difference explicit:
matter fabric remove @1 # local-only: deletes from store, device is NOT notified
matter decommission @1 # proper decommission: sends RemoveFabric, then deletes from store
Consider adding a warning to fabric remove output: "Note: the device was not notified. Use matter decommission to fully remove."
Edge cases
- Device unreachable — prompt the user: "Device is not responding. Remove from local store anyway? (y/N)". With
--force, skip the prompt and delete locally.
- RemoveFabric rejected — the device may return
STATUS_CODE_INVALID_COMMAND if the fabric index is wrong. Surface the error clearly with a suggestion to retry.
- Last fabric on device — after RemoveFabric, the device re-enters commissioning mode automatically (per spec). No special handling needed, but mention it in the output.
Flags
| Flag |
Short |
Description |
--force |
-f |
Remove from local store even if the device is unreachable |
Relevant Code
| File |
What it does |
cli/fabric.go:190-247 |
Current fabric remove — local-only delete, good template |
cli/device.go:112-126 |
deleteNode() — routes through daemon or direct store |
cli/cluster.go:603-696 |
invokeCommand() — generic cluster command invocation |
internal/clusters/operationalcredentials/cluster.go:35,138-140 |
CmdRemoveFabric (0x0A) and RemoveFabricRequest — defined but never invoked |
internal/secure/case.go:554-618 |
EstablishCASE() — needed to authenticate before RemoveFabric |
internal/daemon/server.go:340-356 |
handleDeleteNode() — evicts cached session on delete |
Out of Scope
- Bulk decommission (all devices at once) —
fabric reset covers the local side; bulk RemoveFabric can come later.
- Removing our fabric from a device we don't control (requires admin privileges on that device's fabric).
Problem
matter fabric remove @1only deletes the device from the local store — the device itself is never notified and keeps its fabric credentials. This means:chip-tool pairing unpair 1) sendsRemoveFabricover CASE before deleting locally.Proposed Solution
Add a top-level
matter decommissioncommand that mirrorsmatter commission:What it should do
OperationalCredentials.Fabricsattribute to find the entry matching our fabric ID, then extract itsFabricIndex.RemoveFabric(0x0A) on the OperationalCredentials cluster (endpoint 0) with the resolved fabric index.Decommissioned "Kitchen Light" (@1) — device fabric data removed.Clarify
fabric removeas local-onlyMake the behavioral difference explicit:
Consider adding a warning to
fabric removeoutput: "Note: the device was not notified. Usematter decommissionto fully remove."Edge cases
--force, skip the prompt and delete locally.STATUS_CODE_INVALID_COMMANDif the fabric index is wrong. Surface the error clearly with a suggestion to retry.Flags
--force-fRelevant Code
cli/fabric.go:190-247fabric remove— local-only delete, good templatecli/device.go:112-126deleteNode()— routes through daemon or direct storecli/cluster.go:603-696invokeCommand()— generic cluster command invocationinternal/clusters/operationalcredentials/cluster.go:35,138-140CmdRemoveFabric(0x0A) andRemoveFabricRequest— defined but never invokedinternal/secure/case.go:554-618EstablishCASE()— needed to authenticate before RemoveFabricinternal/daemon/server.go:340-356handleDeleteNode()— evicts cached session on deleteOut of Scope
fabric resetcovers the local side; bulk RemoveFabric can come later.