Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>Salesforce Data TreecipeNew to Visual Studio Code? Get it now.
Salesforce Data Treecipe

Salesforce Data Treecipe

Salesforce-Data-Treecipe

|
132 installs
| (0) | Free
source-fidelity driven development, pairs well with cumulus-ci
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Salesforce-Data-Treecipe

Salesforce-Data-Treecipe is a Visual Studio Code extension designed to streamline the process of generating production-like data during development in order to support building Quality in.

This extension auto-generates a recipe yaml file based on the running, local project structure. Said differently, what is already in the "source" for the project.

From the generated "Fake-Data Generating YAML Files", additional commands can be used following the recipe generation to build Collections API datasets that can be committed and reused as needed.

Users have two choices of "Fake Data" implementations:

  • faker-js - Can handle simple to complicated data generation and uploads
  • snowfakery - All of the above and way more for advanced data generation scenarios

Table of Contents

  • Prerequisites for Snowfakery
  • VS Code Extension Installation
  • "How To" YouTube Walkthroughs:
  • Get started by walking through the below commands
    • 1. Salesforce Treecipe: Initiate Configuration File
      • How It Works:
      • Corresponding Video:
    • 2. Salesforce Treecipe: Generate Treecipe
      • Prerequisite:
      • Corresponding Video:
    • 3. Salesforce Treecipe: Run Faker by Recipe
      • Corresponding Video:
    • 4. Salesforce Treecipe: Insert Data Set by Directory
    • 5. Salesforce Treecipe: Generate Picklist Dependency Tests
    • 6. Salesforce Treecipe: Run Picklist Dependency Check
    • 7. Salesforce Treecipe: Open Picklist Dependency Explorer
    • 8. Salesforce Treecipe: Update Picklist Dependency Metadata from Specs
    • 9. Salesforce Treecipe: Open Recipe Cockpit (preview)
  • VIDEO WALKTHROUGHS
    • Initiate Treecipe Configuration with expected Objects directory
    • Generate Treecipe based on treecipe.config.jcon (keep an eye out for OOTB fields and "REMOVE ME" lines)
    • Run Snowfakery by existing recipe yaml file
    • Insert Data Set by Directory
  • Troubleshooting, Exception Handling, and Reporting Bugs
    • Video Walkthrough:
  • Contributing
  • License
  • Install Snowfakery CLI
    • Snowfakery CLI Installation and Usage
      • Overview
      • Prerequisites
      • Installation
      • Verify the Installation
      • Usage (Without Salesforce Data Treecipe Extension)
      • Uninstalling Snowfakery

Prerequisites for Snowfakery

If using snowfakery as Faker service instead of faker-js.

"faker-js" can be natively installed with VS Code extensions and does not require machine setup steps.

  1. Install Snowfakery CLI

VS Code Extension Installation

  1. Open Visual Studio Code.
  2. Go to the Extensions panel and search for Salesforce-Data-Treecipe.
  3. Click Install.

"How To" YouTube Walkthroughs:

  • Salesforce Data Treecipe Initiation, Setup, and Simple Account and Contact Example in VS Code:

Get started by walking through the below commands

Note: press Ctrl+Shift+P (or Cmd+Shift+P on macOS) to open the Command Palette.

  1. Initiate Configuration File
  2. Generate Treecipe
  3. Run Snowfakery by Recipe(Treecipe) to create FakeDataSet
  4. Insert Data Set by Directory
  5. Generate Picklist Dependency Tests
  6. Run Picklist Dependency Check
  7. Open Picklist Dependency Explorer
  8. Update Picklist Dependency Metadata from Specs

Note: Select Faker Implementation is also available from the Command Palette at any time to switch between the faker-js and snowfakery backends.


1. Salesforce Treecipe: Initiate Configuration File

This command initiates the creation of a configuration file that is required before using other features of the extension.

The command creates a root directory folder called "treecipe" and within it a configuration file called "treecipe.config.json".

This file is auto generated based on the field configurations detailed selection made when prompted "Select objects directory".

The end result treecipe.config.json file is expected to look like the below:

  • salesforceObjectsPath - will vary based on selected directory in your VS Code workspace
  • dataFakerService - can be 'snowfakery' or 'faker-js'
{
    "salesforceObjectsPath": "./force-app/main/default/objects/",
    "dataFakerService": "faker-js"
}

How It Works:

  • Select "Salesforce Treecipe: Initiate Configuration File" from the command palette.
  • You will be prompted to type the source directory in your codebase where Salesforce objects are stored in source format. Begin typing the folder and the directories will auto-filter to match directories based on the entered text.

Once the configuration file is generated, you can begin using the Generate Treecipe command.

Optional: customRelationshipMappings

When Salesforce metadata is pulled down, a lookup field on a custom object sometimes arrives without a <referenceTo> tag. Treecipe cannot tell what that field points at, so the object is left out of the relationship tree and ends up in the wrong Treecipe file with the wrong insertion order.

Add an optional customRelationshipMappings property to treecipe.config.json to resolve those fields by hand. Each key is "ObjectApiName.FieldApiName" and each value is the parent object's API name:

{
    "salesforceObjectsPath": "./force-app/main/default/objects/",
    "dataFakerService": "faker-js",
    "customRelationshipMappings": {
        "CustomObject__c.Primary_Contact__c": "Contact",
        "Order__c.Related_Account__c": "Account"
    }
}
  • The property is optional — leave it out entirely and Treecipe behaves exactly as before.
  • A mapping is only consulted when the field's own <referenceTo> tag is missing. Metadata always wins.
  • These entries extend the built-in lookup map (currently the single entry AccountId → Account); they never replace it.
  • A key without exactly one dot separator ("CustomObject__cPrimary_Contact__c", "Too.Many.Dots__c") is ignored, and an entry with an empty parent value is skipped. A typo is silently skipped rather than failing the run — if an object is still landing in the wrong tree, check the key spelling first.

Corresponding Video:

https://github.com/jdschleicher/Salesforce-Data-Treecipe/blob/main/README.md#initiate-treecipe-configuration-with-expected-objects-directory


2. Salesforce Treecipe: Generate Treecipe

This command generates a Treecipe, a structured representation of your Salesforce data, based on your treecipe configuration and the objects directory it is pointed to.

It parses the "salesforceObjectsPath" directory path that was provided when running the "Initiate Configuration File" command above, and then generates a yaml file of objects and associated fields found in that directory.

As part of this yaml file generation there are some items to be aware of:

  • "TODO" items: Review sections marked with "TODO" before generating fake data. These mark areas that need clarification or input.
  • Handling of field files without xml markup: OOTB fields (e.g., AccountNumber, Name) lack XML detail. Some (like Name) need faker values manually added.
  • Record Type Picklist, Dependent Picklist, Multiselect Picklist Selections: Object folders are parsed to detect record types and relevant picklist faker options.

NOTE:

If this command is run before "Initiate Configuration File" is completed, a warning will appear in VS Code prompting to run it.

Prerequisite:

  • Generate Treecipe requires a valid configuration file and selected Salesforce objects directory.

Corresponding Video:

https://github.com/jdschleicher/Salesforce-Data-Treecipe/blob/main/README.md#generate-treecipe-based-on-treecipeconfigjcon--keep-an-eye-out-for-ootb-fields-and-remove-me-lines-


3. Salesforce Treecipe: Run Faker by Recipe

This command prompts the user to select an existing recipe(Treecipe) file to generate fake data from.

With the selection made, the snowfakery CLI will execute against the yaml file and produce json structured, production-like data which is then converted for usage with Salesforce Collection Api

Corresponding Video:

https://github.com/jdschleicher/Salesforce-Data-Treecipe/blob/main/README.md#run-snowfakery-by-existing-recipe-yaml-file


4. Salesforce Treecipe: Insert Data Set by Directory

This command prompts the user for the following items:

  1. Select a pre-existing "dataset" directory with expected Collections-Api structure files

  2. Enter name of already locally authenticated Salesforce alias (DO NOT USE PRODUCTION ORG!!!)

  3. Select "ALL OR NONE" option.

    • "false" keeps successfully inserted records
    • "true" rolls back all inserted records

5. Salesforce Treecipe: Generate Picklist Dependency Tests

This command generates an Apex test class that asserts your picklist dependencies still exist in an org, so a dependency an admin later rewires is caught by a failing test instead of surfacing as a confusing Collections API error at data-load time.

Prerequisite: "Initiate Configuration File" must have been run, and the workspace must be a Salesforce DX project with an sfdx-project.json.

The command:

  1. Walks the salesforceObjectsPath from treecipe.config.json
  2. Emits one spec per picklist field that declares a controllingField, derived from the valueSettings in its field metadata
  3. Writes one SDTPLDSpecs_<Object>.cls per object that has dependent picklists, each holding one spec method per dependent picklist on that object
  4. Writes SDTPLDSpecs.cls, an aggregator whose all() pulls in every per-object class. Callers depend on the aggregator, so a per-object class appearing or disappearing as your metadata changes does not ripple outwards
  5. Writes SDTPLDSpecsTest.cls, an @IsTest class with one test method per object that asserts that object's specs against the org the test runs in, plus a guard method that fails when the spec registry is empty
  6. Scaffolds the Apex validation framework classes it depends on (SDTPicklistDependencySpec, SDTPicklistDependencyValidator, SDTSchemaPicklistDependencySource, and supporting classes) into a SDTPicklistDependencyFramework subfolder, if they are not already present. Keeping them in their own directory separates the six files you did not write from the generated contract you do engage with, and makes them removable in one action — Salesforce resolves ApexClass by the enclosing classes directory and walks nested folders, so the layout deploys identically
  7. Writes <packageDir>/main/default/testSuites/SDTPicklistDependencyTests.testSuite-meta.xml, an Apex test suite registering SDTPLDSpecsTest. The suite is the stable handle a CI pipeline, Setup and this extension all address, so nothing has to hard-code the generated class name. If the file already exists, members you added yourself are kept — regeneration adds the generated class, it never resets the file
  8. Writes treecipe/PicklistDependencySpecs/manifest.json, a machine-readable description of everything it just generated — built from the same model as the Apex, in the same run, so the two cannot disagree

The spec manifest

The manifest records, per object, the generated class name and file path and the test method name; per field, the spec method name, controlling field, upstream field and every expectation with a stable key; plus when it was generated, by which version, which objects directory was scanned, and every field that was skipped and why.

Open Picklist Dependency Explorer renders this file rather than re-reading your source metadata, which is what makes the panel's rows and your generated tests the same thing rather than two derivations that can drift.

It lives under treecipe/ rather than beside the .cls files deliberately: a .json inside a Salesforce package directory is not valid metadata, and would be picked up by sf project deploy and fail the deploy of the classes it describes. Commit it alongside the generated Apex.

The generated Apex is meant to be read

Each per-object class opens by naming the object's dependent picklists and the controlling field for each, and every spec method is preceded by a comment stating its combinations in plain language:

/**
 * Region__c depends on Country__c.
 *
 * Combinations:
 *   "Canada" unlocks Ontario, Quebec -- and must not unlock Baja, East, West
 *   "USA" unlocks East, West -- and must not unlock Baja, Ontario, Quebec
 */
public static SDTPicklistDependencySpec specFor_Account_Region_c() {

The comment and the assertions below it are built from one model, so they cannot describe different things — which is the point: reading the generated spec should beat clicking through the Salesforce dependency matrix UI.

What each spec asserts

Every controlling value gets two assertions, which together catch drift in both directions:

Emitted line Catches
expectAtLeast('USA', new List<String>{ 'Ohio', 'Texas' }) A value removed from the combination
expectNotAllowed('USA', new List<String>{ 'Ontario' }) A value that drifted into the combination
expectNone('Antarctica') A controlling value that must unlock nothing gaining values

The forbidden list is the complement: every value the dependent field declares that this controlling value does not unlock. That is deliberately weaker than expectExactly — a value an admin legitimately adds to the field after generation is tolerated, while a value moving into the wrong bucket still fails. Tightening a line to expectExactly is a deliberate edit — note that regenerating overwrites the file, so hand edits are lost.

Record type scoped specs

A record type assigns its own subset of picklist values to the controlling and dependent fields, so the combinations reachable through one record type are narrower than what the field itself declares. Where an object has a recordTypes/ directory, the per-object class gets those narrowed combinations too, alongside the field-level ones. The sample below shows the shape of what is emitted rather than metadata you should expect to see:

public static SDTPicklistDependencySpec specFor_Dependency_Example_c_Neighborhood_c_recordType_Cleveland_Only() {
    return SDTPicklistDependencySpec.forRecordType('Dependency_Example__c', 'Neighborhood__c', 'Cleveland_Only')
            .controlledBy('City__c')
            .expectAtLeast('cle', new List<String>{ 'ohiocity', 'tremont' })
            .expectNotAllowed('cle', new List<String>{ 'willowick' })
            .expectUnavailable('eastlake');
}
  • The controlling values are the field's, intersected with what the record type assigns to the controlling field; the unlocked values are intersected with what it assigns to the dependent field
  • A controlling value the record type does assign but whose unlocked values it assigns none of becomes expectNone — it must exist under that record type and unlock nothing
  • A controlling value the record type does not assign becomes expectUnavailable — under that record type the value is absent rather than empty, and expectNone would demand it exist
  • A field the record type's XML never mentions is treated as unassigned for that record type, not as fully assigned: the combination is skipped and reported as a warning, and the field-level spec still covers the field
  • The scoped specs are collected by recordTypeSpecs() on the per-object class and SDTPLDSpecs.allRecordTypeScoped() on the aggregator

They are not asserted by SDTPLDSpecsTest, and that is deliberate. Apex Schema describe returns picklist values without any record type filtering, so the describe-backed source cannot answer a record-type-scoped spec — it rejects one outright rather than checking it against the whole field and reporting a scope it never verified as green. The scoped specs deploy with the rest of the contract and are ready for an ISDTPicklistDependencySource that can read record-type-filtered values; until then they are a captured contract, not a running one. An object with no recordTypes/ directory generates exactly what it did before.

Chained dependencies

Where a dependent picklist is itself the controlling field of another (Country__c → State__c → City__c), the generated spec for the lower link carries a dependsOn naming the spec above it:

public static SDTPicklistDependencySpec specFor_Chain_Example_c_City_c() {
    return SDTPicklistDependencySpec.forField('Chain_Example__c', 'City__c')
            .controlledBy('State__c')
            .dependsOn(specFor_Chain_Example_c_State_c())
            .expectAtLeast('Ohio', new List<String>{ 'Cleveland', 'Columbus' })
            .expectNotAllowed('Ohio', new List<String>{ 'Austin', 'Toronto' });
}

When the upstream spec fails, the break is reported once where it actually is, and the downstream spec reports a single UPSTREAM_FAILURE naming the spec to fix first — rather than repeating the same describe mismatch for every dependent below it.

Notes:

  • A field with a controllingField but no valueSettings markup is reported as a warning and skipped; the rest of the run continues
  • A record type that assigns no values to the controlling or the dependent field of a dependency is reported the same way, and only that combination is skipped
  • If no dependent picklists are found, an informational message is shown and no file is written
  • If the generated classes already exist, you are prompted before they are overwritten
  • A per-object class left over from an object that no longer declares a dependent picklist is removed and named in the summary, so the org stops asserting a contract your metadata no longer describes
  • Upgrading from 2.12.x–2.14.x: the Apex classes were unprefixed then. If a PicklistDependencyFramework folder or an SFTreecipePicklistDependencySpecs.cls is still in your project, the command warns and names what to delete — locally and in any org you deployed them to. Nothing is deleted for you

The generated assertions read the org's real metadata. Schema describe is not isolated by @IsTest, so no test setup data and no SeeAllData are involved.

End-to-end in one command

After generating, the command offers to deploy and run the tests against an org right away. Accept it and you are prompted for the target org, the classes are deployed, the tests run, and the results land in the output channel and the treecipe directory — generation through to verified results without leaving the command.

The offer comes after generation rather than before, because generating is useful on its own: reviewing what changed, or working without an org to hand, needs the files and nothing else. Dismissing the prompt leaves you with a completed generation, not a cancelled command.

This path always deploys, unlike "Run Picklist Dependency Check" below, which deploys only when the test class is missing. The classes were just rewritten, so the org copy is stale by definition — a conditional deploy would run yesterday's contract against today's metadata.

Once generated, you can also run the check any time with "Run Picklist Dependency Check" below, and browse the structure it generated with the Explorer.

Once the classes are in your org

Everything above is the VS Code side. For the org side — what each deployed class is, how to read a generated spec against the Field Dependencies grid in Setup — including which argument is which, and how a record-type-scoped spec differs from the field-level one — how to run the tests from Setup or the Developer Console, how to trigger a failure on purpose to prove the gate works, and how to decide whether to fix the org or regenerate the specs — see the Picklist Dependency In-Org Guide. It is written for an admin or developer looking at SDTPLDSpecsTest in an org, and assumes nothing about this extension.


6. Salesforce Treecipe: Run Picklist Dependency Check

This command deploys and runs the generated picklist dependency tests against an org and reports the result in VS Code.

Prerequisite: "Generate Picklist Dependency Tests" must have been run, and the Salesforce CLI (sf) must be installed with at least one authorized org.

The command:

  1. Lists your authenticated orgs and prompts you to pick the target
  2. Checks whether the SDTPicklistDependencyTests suite in that org still contains SDTPLDSpecsTest, and offers to deploy if it does not — nothing is deployed without explicit confirmation. Membership is what is checked rather than the suite's existence: a suite whose member class was deleted still exists, and running it would pass having asserted nothing
  3. Runs the suite with sf apex run test --suite-names SDTPicklistDependencyTests
  4. Writes a per-method report to the Picklist Dependency Check output channel and shows a pass/fail summary notification
  5. Saves the results into treecipe/PicklistDependencyResults/check-<org>-<timestamp>/ as results.json and report.md

A failing method names the object, field, controlling value, and the specific missing values.

Notes:

  • If no orgs are authenticated, you are told how to authorize one rather than shown an empty picker
  • Declining the deploy prompt exits cleanly and deploys nothing
  • The output channel is cleared on each run, so what you see always belongs to the run that just finished
  • Because the channel is cleared, every run is also written to disk under treecipe/PicklistDependencyResults/ — one timestamped folder per run, so results stay committable and diffable between runs. Passing runs are saved too, not only failures

7. Salesforce Treecipe: Open Picklist Dependency Explorer

This command opens a read-only visual view of your picklist dependency structure. It answers "which controlling value unlocks what" without you reading generated Apex or a markdown dump.

It is a picture of the structure, and only that. The panel reads no check results: no pass/fail badges, no status filter, no last-run banner, and no links into a generated .cls or a run's report.md. Whether your org still agrees with the structure is what "Run Picklist Dependency Check" answers, and it reports that in its own output channel and report.

Prerequisite: run Generate Picklist Dependency Tests first. The panel renders the spec manifest that command writes, so what you see is exactly what your generated tests assert. No org, no CLI and no check run are required — and if you have not generated yet, the panel offers a metadata preview instead (see below).

The command:

  1. Reads treecipe/PicklistDependencySpecs/manifest.json — the machine-readable description of the specs that were generated — and builds the dependency structure from it: object → controlling field → controlling value → the values it unlocks, and the values it must not unlock. Your source metadata is not re-walked, so a panel row always corresponds to a spec method that exists
  2. Renders chained dependencies as a connected graph — a field controlled by another dependent picklist is nested under it rather than repeated as a flat row
  3. Lists any field the generator skipped as its own row marked not covered, with the reason — rather than leaving it out, where it would be indistinguishable from a field with no dependency
  4. Clicking any combination reveals the generating field's source XML path, with a Reveal in Explorer action that opens the .field-meta.xml, and a Copy reference action
  5. Nests each record type's narrowed combinations under the field they narrow, collapsed until you open them — the same dependency as the record type actually exposes it

The panel names no Apex. Which class or spec method was generated is not a fact about a dependency, so it is not on screen — it is in manifest.json and in the generated .cls files themselves.

Finding your way around a large org:

A toolbar sits above the structure:

  • Find object, field or controlling value matches on object, field, controlling field, record type, and the controlling value heading every combination row — everything the panel actually shows you, and nothing it does not. Searching for a field name reaches the object holding it, so you do not have to know which object that was; searching for Canada reaches every object with a row that says what Canada unlocks — and when exactly one object matches, it opens by itself. The values a combination unlocks are not matched: a value is findable where it is a controller, which in a chain means one level down. A value only a dropped row carried is not matched either — the haystack is rebuilt from what survived the ceiling, so a match always has a row on screen to show for it
  • Contents lists every section and object the panel is showing, and scrolls to any of them
  • Expand all / Collapse all, bounded at 25 visible objects — past that the panel asks for a narrower filter rather than freezing

Filtering only ever hides rows. Nothing about a row is recomputed, and nothing is inferred from a row being hidden.

Copy reference on any combination copies its stable key — Object__c.Field__c [RecordType] @ Controlling Value — and pasting that back into the find box reopens exactly that combination. It is stable across re-renders, so it is something you can put in a review comment or a ticket.

Notes:

  • The panel is a VS Code webview — no local HTTP server, no open port, no extra runtime dependency. Its content security policy allows only the extension's own inline style and script, so it loads nothing from the network
  • Built as you open it. An object's rows are built when you expand it, not when the panel loads, and the model itself is bounded: at most 250 objects, 25 dependent picklists per object, 200 combinations per field, 25 record type scopes per field, 200 declared values per field, and 20,000 rendered combinations in total. Anything the ceiling drops is counted and stated in a notice at the top. What survives a cap is whatever the manifest declares first — the same order on every axis, so the same manifest always truncates to the same rows and a row you cannot find was cut rather than moved. Dependency chains are capped whole rather than field by field, so an object can show more dependent picklists than the per-object limit suggests; the notice says so. The one exception keeps an object carrying a skipped field past the cap, since that is the only row nothing asserts
  • Where a field declares more values than the panel renders, the "must not unlock" list is withheld rather than shortened — a complement drawn against a partial list would understate what the spec forbids, and the row says so
  • It follows your active color theme, light, dark or high contrast
  • No org, no CLI, no check run? None of them is involved. The panel renders from manifest.json on disk and nothing else, so it works the same in a fresh clone as in a workspace that runs the check nightly
  • Not generated yet? You get a message naming the generate command, plus a "Preview from metadata (not generated)" action. The preview scans your source metadata exactly as previous versions did, and banners every row as read straight off the XML rather than from a generated manifest
  • A corrupt manifest.json? The parse failure is reported and the same preview is offered — never a blank panel
  • Metadata changed since you generated? The panel says so in a banner naming the generate command, and keeps showing what the generated Apex actually asserts. It never silently re-derives the structure from metadata your tests have not been regenerated against
  • No dependent picklists at all? You get an empty state naming the objects directory that was scanned
  • Record-type-scoped rows are the same dependency, narrowed. Each scope says so beside its own rows rather than relying on a note elsewhere in the panel, and a value the record type does not assign is shown as not available rather than as unlocking nothing, which is a different claim
  • Scoped combinations are counted separately in the header (N combination(s) + M record-type-scoped), because a record type narrows a field-level dependency rather than adding one of its own
  • Commit manifest.json alongside your generated .cls files. It is the record of what was generated, and reviewing it as a diff shows dependency changes in the same commit as the Apex that asserts them

8. Salesforce Treecipe: Update Picklist Dependency Metadata from Specs

This command runs opposite to Generate. It reads your generated Apex specs — including whatever you edited into them — and reconciles your source metadata to match, so you can deploy the change and watch a failing dependency check go green.

Prerequisite: Generate Picklist Dependency Tests must have been run, so there are specs to read.

Why it exists. The check tells you Account.Region__c @ cle: missing [plant]. That failure is indexed by controlling value; your metadata is indexed by dependent value. So unlocking plant under cle means editing the plant block — nowhere near where the message points. That transpose is what this command does for you.

The command:

  1. Reads every generated SDTPLDSpecs_<Object>.cls and parses the specs back out
  2. Transposes each one into the valueSettings shape your metadata stores
  3. Shows you every pair it would add or remove, in the words the failure used — cle unlocks plant — before writing anything
  4. Writes only if you approve; declining leaves every file untouched
  5. Offers to deploy the changed files to an org. Declining says explicitly that the changes are in your working tree and were not deployed

Notes:

  • Your spec's silences are respected. A spec asserts what a controlling value must unlock and what it must not. Anything it names neither way — and any controlling value it never mentions — it makes no claim about, and the command leaves it alone. expectNone and expectExactly are the exception: both state their list completely, so anything else under that controlling value is removed
  • Your formatting survives. Only the valueSettings region and, where needed, valueSetDefinition are rewritten. The XML declaration, indentation, unrelated markup and trailing newline are preserved. Both <valueSettings> layouts are supported and whichever your file uses is kept
  • Reconciling twice changes nothing the second time, and after a writeback, running Generate produces byte-identical Apex — the two directions agree
  • The controlling field is reconciled too. A valueSettings entry can only name a controlling value the controlling picklist actually offers, so when a spec asserts a value that field does not declare, it is added to that field's own valueSetDefinition in the same run — otherwise the write would describe a combination nobody can reach, and you would find out on deploy
  • A global-value-set-backed field can be rewired, but adding a new value is refused with a message naming the set to add it to first. The shared .globalValueSet-meta.xml is never edited — its blast radius reaches every field pointing at it. The same rule applies to a controlling field
  • An orphaning cascade — removing a value that is itself another picklist's controlling field — names the downstream field and skips that field. Every unaffected field still writes
  • A spec class that cannot be parsed aborts naming the file and writes nothing. An unparseable class is never treated as "this object has no dependencies"
  • Record-type-scoped specs are not written back. A record type narrows what it exposes; applying that to valueSettings would assert the narrowing against every record type

9. Salesforce Treecipe: Open Recipe Cockpit (preview)

A panel for browsing a generated recipe: every object, every field, the field's type and the faker expression behind it, with a filter and one-click jumps into the recipe file.

Prerequisite: Generate Treecipe must have been run at least once. With no generated run the panel says so and names that command.

It is a preview. The first time you run it in a workspace, a warning asks you to opt in. The switch is salesforce-data-treecipe.recipeCockpitEnabled, written for this workspace only, and you can turn it off in Settings. What is built and what is still missing is tracked under the recipe-cockpit label. It can describe the recipe's objects in an org you choose; comparing the recipe with that org field by field is the next part and is not here yet.

How it works:

  • It reads what Generate Treecipe already wrote. Every run leaves a treecipeObjectsWrapper-<timestamp>.json next to its recipe files under treecipe/GeneratedRecipes/. The panel reads that file rather than re-parsing your metadata, and opens on the latest run
  • Switch runs from the selector next to the filter box. Each run is labelled with when it was generated (UTC) and which faker backend wrote it
  • Filter narrows fields as you type. It matches field names, labels, types, controlling fields and faker expressions. Typing an object's name shows all of its fields. An object with nothing matching stays listed, collapsed and marked no matching fields, so a filter never looks like missing data
  • Click an object or field name to open the recipe .yml at that exact line
  • Fields that only the recipe file carries are shown too. Standard-field mappings such as Account.Name, and the record type line, are written straight into the recipe and are not in the wrapper file. They appear marked read from the recipe file
  • Describe in an org… lists every org the Salesforce CLI has authorized (sf org login web adds one) and describes each object of the recipe on screen in the org you pick. A summary line and each object's header show how many fields the org has for it, or why it could not be described. Describes are cached for the VS Code session, so asking again for the same org does not call the API again

VIDEO WALKTHROUGHS

Initiate Treecipe Configuration with expected Objects directory

https://github.com/user-attachments/assets/f8401f28-a04c-4abc-a56f-c860cce96dee

Generate Treecipe based on treecipe.config.jcon (keep an eye out for OOTB fields and "REMOVE ME" lines)

https://github.com/user-attachments/assets/fd127b55-d434-4a73-9d65-cf4172fbce6f

Run Snowfakery by existing recipe yaml file

https://github.com/user-attachments/assets/d7dfcf70-70f8-4ce3-b254-280e2bbb0b7d

Insert Data Set by Directory

https://github.com/user-attachments/assets/a0491f86-9360-4450-afae-f71fe07dbc21


Troubleshooting, Exception Handling, and Reporting Bugs

See below for troubleshooting when specific commands are not working:

  • Salesforce Treecipe - Generate Treecipe - generateRecipeFromConfigurationDetail:

    • Ensure "Initiate Configuration File" was successfully run
    • Ensure path in treecipe.config.json uses forward-slashes
    • Ensure "defaultFakerService" is set to "snowfakery"
  • Salesforce Treecipe: Initiate Configuration File - initiateTreecipeConfigurationSetup:

    • Ensure expected project directory was selected

NOTE:

All commands are wrapped in try-catch and will prompt a "Report a Bug" dialog. This generates a GitHub Issue template with a stack trace.

Video Walkthrough:

https://github.com/user-attachments/assets/dff4a3cb-e244-4959-9dec-dcf094f713c2


Contributing

This project and codebase will be open-sourced shortly :)


License

This extension is licensed under the MIT License.


Install Snowfakery CLI

Snowfakery CLI Installation and Usage

Overview

Snowfakery is a tool for generating synthetic data. This document provides instructions for installing and using the Snowfakery CLI on any operating system.

Prerequisites

  • Python 3.8+ is required:

    python --version
    

    https://www.python.org/downloads/

  • pip (Python package manager): https://pip.pypa.io/en/stable/installation/

Installation

pip install snowfakery

Verify the Installation

snowfakery --version

Usage (Without Salesforce Data Treecipe Extension)

snowfakery generate <path_to_your_snowfakery_recipe>

Official documentation: https://snowfakery.readthedocs.io/

Uninstalling Snowfakery

pip uninstall snowfakery
  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft