Cross-org workflow¶
The reason sf-deck exists. Three real patterns that are awkward in Lightning and quick in sf-deck.
Pattern 1: dev → UAT → prod via bundles¶
The canonical change-management flow.
- Work in dev. Build the feature, collect everything into a dev project as you go.
- Bundle it.
xon the project, pick "sfdx skeleton + retrieve from org". sf-deck pulls the source from dev. - Validate against UAT.
sf-deck bundle validate --id <bundle-id> --org uat --async --json. Poll until done. - If validate passed, deploy to UAT.
sf-deck bundle deploy --id <bundle-id> --org uat --async --json. Poll. - Test the feature in UAT. sf-deck doesn't help here — go test the actual feature in the actual UAT browser session.
- Repeat 3-4 against prod. With explicit human confirmation for the safety raise + the deploy itself.
See Bundle and deploy for the verb-level walk-through.
Pattern 2: spot-check the same thing across orgs¶
You want to know "is the Account.Phone field the same in dev,
UAT, and prod?" — or "is the Shipment_Status_Change flow active
everywhere?"
The fast way is the dedicated /compare tab: pick a source org and a
target org, choose the metadata types to diff, and sf-deck lays the two
side by side so you can scan for drift. For a single field or object,
open /objects on the source org, drill in, then run the comparison
from /compare against the other org.
Pattern 3: pull data from one org, push to another¶
Records are not bundlable. To move data, use the export/import flow:
# From the source org
sf-deck soql run \
--org dev \
--query "SELECT Id, Name, Status__c FROM Shipment__c WHERE Status__c = 'In Transit'" \
--json > shipments.json
# Or use export for a nicer format
sf-deck soql export \
--org dev \
--query "SELECT Id, Name, Status__c FROM Shipment__c WHERE Status__c = 'In Transit'" \
--output shipments.csv
# Massage the data...
# Push to the target org
# (Bulk import isn't an sf-deck verb yet — use the sf CLI directly:)
sf data import bulk \
--target-org uat \
--file shipments.csv \
--sobject Shipment__c
record.create / record.update / record.delete work
per-record over both CLI and IPC, but for anything beyond ~50 rows
you want Bulk API, which is currently a sf CLI call.
Multiple sf-deck windows¶
You can run more than one sf-deck instance at a time. Each one gets:
- A unique instance number (the
◈Nbadge in the top-left) - Its own IPC socket (
~/.sf-deck/control-<N>.sock) if launched with--control
Useful for side-by-side comparison: one window pointed at dev, one at prod. Each has its own state, its own loaded project, its own chip strip.
Labels show up in the badge so you don't mix them up.
Driving multiple windows from one agent¶
The IPC controller skill walks through this. An agent can:
- Call
sf-deck instance list --jsonto discover open windows. - Pick one (by label, or by asking the user).
- Send commands to its socket: navigate, apply a chip, fire a SOQL, etc.
See Agent integration.