Soql Lib Query Builder
beyond-the-cloud-dev/soql-lib
Builds Salesforce SOQL queries using the SOQL Lib fluent builder API (SOQL.cls).
A skill your agent uses to enable the Consumer Goods Cloud TPM Promotion Business Object (BO) API framework in a Salesforce org, interview the user for the custom Workflow Step they want to add…
$ npx skills add forcedotcom/sf-skills --skill consumer-goods-promotion-bo-api-deploy -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install forcedotcom/sf-skills consumer-goods-promotion-bo-api-deploy --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/consumer-goods-promotion-bo-api-deploy .claude/skills/consumer-goods-promotion-bo-api-deploy && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "consumer-goods-promotion-bo-api-deploy" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/consumer-goods-promotion-bo-api-deploy into .claude/skills/consumer-goods-promotion-bo-api-deploy/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "consumer-goods-promotion-bo-api-deploy", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/forcedotcom/sf-skills/tree/main/skills/consumer-goods-promotion-bo-api-deployType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add forcedotcom/sf-skills --skill consumer-goods-promotion-bo-api-deploy -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install forcedotcom/sf-skills consumer-goods-promotion-bo-api-deploy --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/consumer-goods-promotion-bo-api-deploy .agents/skills/consumer-goods-promotion-bo-api-deploy && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "consumer-goods-promotion-bo-api-deploy" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/consumer-goods-promotion-bo-api-deploy into .agents/skills/consumer-goods-promotion-bo-api-deploy/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "consumer-goods-promotion-bo-api-deploy", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add forcedotcom/sf-skills --skill consumer-goods-promotion-bo-api-deploy -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install forcedotcom/sf-skills consumer-goods-promotion-bo-api-deploy --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/consumer-goods-promotion-bo-api-deploy .cursor/skills/consumer-goods-promotion-bo-api-deploy && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "consumer-goods-promotion-bo-api-deploy" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/consumer-goods-promotion-bo-api-deploy into .cursor/skills/consumer-goods-promotion-bo-api-deploy/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "consumer-goods-promotion-bo-api-deploy", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/forcedotcom/sf-skills.git --path skills/consumer-goods-promotion-bo-api-deploy--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add forcedotcom/sf-skills --skill consumer-goods-promotion-bo-api-deploy -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install forcedotcom/sf-skills consumer-goods-promotion-bo-api-deploy --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/consumer-goods-promotion-bo-api-deploy .gemini/skills/consumer-goods-promotion-bo-api-deploy && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "consumer-goods-promotion-bo-api-deploy" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/consumer-goods-promotion-bo-api-deploy into .gemini/skills/consumer-goods-promotion-bo-api-deploy/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "consumer-goods-promotion-bo-api-deploy", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install forcedotcom/sf-skills consumer-goods-promotion-bo-api-deployInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add forcedotcom/sf-skills --skill consumer-goods-promotion-bo-api-deploy -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/consumer-goods-promotion-bo-api-deploy .github/skills/consumer-goods-promotion-bo-api-deploy && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "consumer-goods-promotion-bo-api-deploy" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/consumer-goods-promotion-bo-api-deploy into .github/skills/consumer-goods-promotion-bo-api-deploy/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "consumer-goods-promotion-bo-api-deploy", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add forcedotcom/sf-skills --skill consumer-goods-promotion-bo-api-deploy -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install forcedotcom/sf-skills consumer-goods-promotion-bo-api-deploy --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/consumer-goods-promotion-bo-api-deploy .opencode/skills/consumer-goods-promotion-bo-api-deploy && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "consumer-goods-promotion-bo-api-deploy" agent skill from https://github.com/forcedotcom/sf-skills/tree/main/skills/consumer-goods-promotion-bo-api-deploy into .opencode/skills/consumer-goods-promotion-bo-api-deploy/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "consumer-goods-promotion-bo-api-deploy", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
consumer-goods-promotion-bo-api-deployA skill your agent uses to enable the Consumer Goods Cloud TPM Promotion Business Object (BO) API framework in a Salesforce org, interview the user for the custom Workflow Step they want to add…
Consumer Goods Promotion Bo API Deploy is an agent skill from forcedotcom/sf-skills. Use to enable the Consumer Goods Cloud TPM Promotion Business Object (BO) API framework in a Salesforce org, interview the user for the custom Workflow Step they want to add, generate and deploy that Apex class, wire it into the create/update/copy workflows, and prove it end-to-end via headless REST ingest. Ships a worked reference example (SetCommentValue) but the customization is user-supplied per org. Triggers on "deploy the promotion BO API", "set up promotion BO API", "headless promotion create", "add a BO…
Its SKILL.md is about 4.9k tokens, which your agent loads only when the skill is triggered. The skill folder holds 15 other files, including reference files and assets (for example `assets/set-comment-value/README.md`, `assets/set-comment-value/interview-answers.json` and `assets/set-comment-value/payloads/copy.json`).
It sits in Sales & Support, covering CRM management. It works with Salesforce. The repository describes itself as: Salesforce's curated collection of agent skills for building applications. Optimized for Agentforce Vibes, compatible with all AI tools. The licence is Apache-2.0.
6 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit e5164d9. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
sfjqnodeFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Consumer Goods Promotion Bo API Deploy loads about 4.9k tokens when it runs, and up to ~16k if it reads all its reference files. Until then it costs about 144 tokens; SKILL.md has 1,903 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from forcedotcom/sf-skills at commit e5164d9, republished under its Apache-2.0 licence (© forcedotcom). 1,903 words, ~4,912 tokens.
.claude/skills/consumer-goods-promotion-bo-api-deploy/SKILL.md (or your agent's skills folder). This skill also uses 11 other files; get the full folder from GitHub.Turns on the Consumer Goods Cloud TPM Promotion Business Object (BO) API in a
Salesforce org, interviews the user for one custom Workflow Step to add to
the promotion pipeline, generates and deploys that Apex class, registers it
against a BO API entity, wires it into the customer's chosen subset of
{create, update, copy} workflows, then proves the whole path end-to-end via
three REST endpoints:
POST /services/apexrest/<prefix>/promotions/initializePOST /services/apexrest/<prefix>/promotions/ingestGET /services/apexrest/<prefix>/promotions/status?importId=...It is meant for headless delivery: point it at an org, answer the interview,
and the skill installs the step and verifies it. The Promotion BO API ships in
the CGCloud managed package (namespace cgcloud released, cgcloud_dev
dev/beta). Every Apex identifier, object/field API name, and REST URL is derived
from the detected package prefix at runtime — this skill never hard-codes it.
derive is out of scope here (a follow-up skill covers it). Detailed runbooks
for the write and smoke phases live under references/:
references/conventions-and-payload-rules.md — sales-org partitioning, schema-first contract derivation, and the eight cross-workflow payload rules R1–R8.references/generate-and-wire.md — Phase 5a (generate + deploy the class) and Phase 5b (register + wire the step), with the full register-step.apex.references/smoke-and-verify.md — Phase 6 (contract derivation, payload materialization, create/update/copy legs + verification).references/reference-example-set-comment-value.md — the shipped SetCommentValue preset (assets at assets/set-comment-value/).Ask before starting; do not guess.
sf alias of the target org. Required.0001. Must be 4 chars, uppercase (mirrors TPMSetupData.validateSalesOrg). Every downstream lookup (promotion template, tactic template, anchor account, product filter criteria, SKUs) is scoped to this sales org — see references/conventions-and-payload-rules.md ("Sales-org partitioning").--yes for CI callers.--dry-run runs Phases 1, 2, 3a-preview, the Phase 5 interview, and a validate-only deploy. Writes nothing.What the customization is gets collected in Phase 5's interview, once the framework state is known.
The prefix depends on the installed build — detect it, do not guess. Released
package → cgcloud; dev/beta → cgcloud_dev; source-deployed → no prefix.
sf data query --target-org <alias> \
--query "SELECT NamespacePrefix FROM ApexClass WHERE Name = 'TPMSetupData'" --jsonRead records[0].NamespacePrefix and bind three variables used everywhere below:
PREFIX_DOT — Apex references: cgcloud. / cgcloud_dev. / empty.PREFIX_UNDER — object/field API names: cgcloud__ / cgcloud_dev__ / empty.URL_NS — REST paths: /cgcloud / /cgcloud_dev / empty.Every Apex call is ${PREFIX_DOT}ClassName.method(...); every SOQL object/field is
${PREFIX_UNDER}Object__c; every REST URL is
/services/apexrest${URL_NS}/promotions/<endpoint>. Substitute at run time.
Run these and stop on the first failure.
sf --version; node --version (only if running shipped scripts).sf org display --target-org <alias> --json — confirm reachable, capture instanceUrl + org id (for display/logging only). Every REST call in later phases goes through sf api request rest, which uses the CLI's stored session — this skill never extracts the access token.TPMSetupData.validateSalesOrg). Fail fast instead of surfacing an Apex stack trace.CGCRetailAndTPMMgmtPsl Permission Set License ("CGC Retail and Trade Promotion Management"); there is no TPM App UserLicense. Check the running user's PSL assignment:SELECT Id FROM PermissionSetLicenseAssign
WHERE Assignee.Username = '<running-user-name>'
AND PermissionSetLicense.DeveloperName = 'CGCRetailAndTPMMgmtPsl'SELECT OrganizationType, IsSandbox FROM Organization:OrganizationType = 'Developer Edition' OR IsSandbox = true and empty → warn ("permset gate below is the real check"), continue.CGCRetailAndTPMMgmtPsl not assigned to the running user").TPM_Master_Data_Admin (packaged; PermissionSet.Name is the bare name regardless of namespace), but customers frequently clone it under their own name — so treat a miss as "ask", not "fail". Take <running-user-name> from sf org display ... .result.username:SELECT PermissionSet.Name, PermissionSet.Label FROM PermissionSetAssignment
WHERE Assignee.Username = '<running-user-name>'
AND (PermissionSet.Name = 'TPM_Master_Data_Admin'
OR PermissionSet.Label LIKE '%TPM%Master Data Admin%')sf org assign permset --name TPM_Master_Data_Admin --target-org <alias> as the default option, but also ask the user to confirm whether they already hold an equivalent (possibly cloned/renamed) permission set for the TPM admin persona. Pause, wait for a cloned-permset confirmation or the assignment, then re-query. Proceed only once admin access is confirmed.Read-only; tells you whether Phase 3 needs to run. All three counts MUST be
scoped to <salesOrg> — the framework rows are sales-org-partitioned.
# 1. Workflow rows for this sales org (expect 4: create/update/copy/derive)
sf data query --target-org <alias> --json --query "
SELECT Name FROM ${PREFIX_UNDER}BO_API_Workflow__c
WHERE ${PREFIX_UNDER}BO_API__r.Name = 'Promotion'
AND ${PREFIX_UNDER}BO_API__r.${PREFIX_UNDER}Sales_Org__c = '<salesOrg>'"
# 2. Step rows for this sales org
sf data query --target-org <alias> --json --query "
SELECT COUNT(Id) FROM ${PREFIX_UNDER}BO_API_Workflow_Step__c
WHERE ${PREFIX_UNDER}Sales_Org__c = '<salesOrg>'"
# 3. Junction rows whose parent workflow belongs to a Promotion BO API for this sales org
sf data query --target-org <alias> --json --query "
SELECT COUNT(Id) FROM ${PREFIX_UNDER}BO_API_Workflow_Workflow_Step__c
WHERE ${PREFIX_UNDER}BO_API_Workflow__r.${PREFIX_UNDER}BO_API__r.Name = 'Promotion'
AND ${PREFIX_UNDER}BO_API_Workflow__r.${PREFIX_UNDER}BO_API__r.${PREFIX_UNDER}Sales_Org__c = '<salesOrg>'"create/update/copy/derive; >0 step + junction rows) → Phase 3 is a no-op for this sales org (still run for idempotency; 3a shows zero net-new).The workflows/steps/junctions/entities/input-structures ship as CSVs inside the
packaged TPMSetupData static resource; TPMSetupData.setupBOApi reads and
upserts them. Before running it, show the user what will land.
sf data query --target-org <alias> --json --query "
SELECT Id, Name, NamespacePrefix, SystemModStamp, BodyLength
FROM StaticResource WHERE Name = 'TPMSetupData'"NamespacePrefix matches Phase 1; if prefixes disagree, stop and ask.sf project retrieve, which unpacks a zip StaticResource into a folder on every OS (no curl, no unzip — unzip isn't present on Windows by default). Retrieve into a dedicated setup-data/ subproject so the read-only managed resource never mixes into the Phase-5a deploy tree (./.promotion-bo-api-deploy/force-app, which is what gets deployed back):mkdir -p ./.promotion-bo-api-deploy/setup-data/force-app/main/default
printf '{ "packageDirectories": [{ "path": "force-app", "default": true }], "sourceApiVersion": "60.0" }' \
> ./.promotion-bo-api-deploy/setup-data/sfdx-project.json
( cd ./.promotion-bo-api-deploy/setup-data && sf project retrieve start \
--metadata "StaticResource:${PREFIX_UNDER}TPMSetupData" --target-org <alias> --json )result errors../.promotion-bo-api-deploy/setup-data/force-app/main/default/staticresources/${PREFIX_UNDER}TPMSetupData/BOApi/. ls it. Expected: 0_BO_API__c.csv, 0_BO_API_Entity__c.csv, 0_BO_API_Output_Entity__c.csv, 0_BO_API_Workflow__c.csv, 0_BO_API_Workflow_Entity__c.csv, 0_BO_API_Workflow_Step__c.csv, 0_BO_API_Workflow_Workflow_Step__c.csv, 0_BO_API_Step_Input_Structure__c.csv, import.json. Any missing → stop, print the delta.sf sobject describe --sobject '${PREFIX_UNDER}BO_API_Workflow__c' --target-org <alias> > /dev/null (etc.). Any describe failure → stop (package partially installed).0_BO_API_Workflow__c.csv and 0_BO_API_Workflow_Step__c.csv with {{NS}}/{{SALES_ORG}} substituted.--yes. "no"/blank → abort clean, point at ./.promotion-bo-api-deploy/setup-data/force-app/main/default/staticresources/${PREFIX_UNDER}TPMSetupData/BOApi/.--dry-run → stop here; do not run 3b.Only after 3a confirmation.
PHASE3_START=$(date -u +%FT%TZ).${PREFIX_DOT}TPMSetupData.setupMetadataWizard('<salesOrg>'); → sf apex run --target-org <alias> --file ./.promotion-bo-api-deploy/setup-metadata-wizard.apex.GenericDemoSetupDataBatch self-chains via finish(); polling a single job id misses children. Poll by class:sf data query --target-org <alias> --json --query "
SELECT COUNT() FROM AsyncApexJob
WHERE ApexClass.Name = 'GenericDemoSetupDataBatch'
AND CreatedDate >= ${PHASE3_START}
AND Status NOT IN ('Completed','Failed','Aborted')"finish() and the child's AsyncApexJob row appearing).SELECT Id, Status, NumberOfErrors, ExtendedStatus FROM AsyncApexJob WHERE ApexClass.Name = 'GenericDemoSetupDataBatch' AND CreatedDate >= ${PHASE3_START}). Any Failed/Aborted/NumberOfErrors > 0 → stop, print ExtendedStatus.${PREFIX_DOT}TPMSetupData.setupBOApi('<salesOrg>');.Re-run the Phase 2 queries. Expect 4 BO_API_Workflow__c rows
(create/update/copy/derive, uniqueness on Unique_Key__c), ≥46
BO_API_Workflow_Step__c rows, ≥54 BO_API_Workflow_Workflow_Step__c junction
rows. Anything short → stop, print what's missing. Never claim success while a
component failed.
The framework is now on. The customization is user-supplied — do not skip the interview; do not invent an answer. Print:
The Promotion BO API framework is installed. To add a custom step, tell me:
- Which BO API entity does it target? (e.g. Promotion or Tactic — I'll list the exact entities registered in your org)
- Which workflows should it fire in? (create, update, copy)
- What does it read from the ingest input?
- What does it write on the SObject or elsewhere?
- Any preconditions or side effects I should know about?
If you want a worked example, say "use the SetCommentValue reference" —
it copies the tactic input Comment onto Tactic.Comment__c.| Field | Required | Notes |
|---|---|---|
stepName | yes | PascalCase Apex class name + BO API Workflow Step Name. Unique across ApexClass. |
entity | yes | BO API entity Name — MUST match a row queried live from ${PREFIX_UNDER}BO_API_Entity__c (shared, not sales-org-partitioned); do not assume a fixed list. In a current org these include Promotion, Tactic, ProductFilter, ManualInputs, CustomState (plus the TPM_Promotion.* structures). Query the org and offer the actual rows. |
workflows | yes | Non-empty subset of {create, update, copy}. derive is out of scope. |
actionName | yes | Symbolic action string the class receives in call(String action, ...). Convention: lowerCamelCase of stepName. |
inputPaths | yes (≥1) | JSON paths to read from currentInput, e.g. ["Comment"]. |
inputPathType | yes | JSON type of the input paths — String, Array, Boolean, Number, Object. Drives the RecordType on each SIS row; a wrong value causes TransformationError: Expected <Type> at ingest. Different types → run Phase 5b once per type group. |
outputWrites | yes (≥1) | {field, source} pairs; field is the target API name without the namespace prefix (skill adds ${PREFIX_UNDER}), source references an inputPaths value / literal / computed expression. |
description | yes | One-sentence step description → ${PREFIX_UNDER}Description__c + class docstring. |
preconditions | optional | Free-text guards before writing. |
sortAfter | optional | Named packaged step to sort after; default max(Sort__c) + 10. |
--preset set-comment-value or the user says "use the SetCommentValue reference", load the answers from references/reference-example-set-comment-value.md (assets/set-comment-value/interview-answers.json) and skip the interactive interview. --interview-file <path> loads answers from a JSON file mirroring the 5.1 table (wins over --preset).sf sobject describe --target-org <alias> --sobject '${PREFIX_UNDER}<Entity>__c' --json \
| jq -r '.fields[] | select(.updateable == true and .createable == true) | .name'outputWrites field must appear here; otherwise stop and ask for a different one (FLS is caller-scoped).n/blank → save answers to ./.promotion-bo-api-deploy/interview.json and exit. y → Phase 5a.Runbook in references/generate-and-wire.md. In short: guard the class name for
idempotency; confirm target-field writeability; generate a namespace-agnostic
Callable from the interview (reads currentInput/currentOutput, derives the
prefix from getSObjectType() at runtime); show + confirm; sf project deploy start. Then, in one anon-Apex transaction, upsert one BO_API_Workflow_Step__c
(bare class name in Classname__c), one BO_API_Workflow_Workflow_Step__c
junction per chosen workflow (never assume all three; derive dropped), and the
BO_API_Step_Input_Structure__c rows (RecordType per inputPathType). Both
upserts key on Unique_Key__c (idempotent).
Runbook in references/smoke-and-verify.md. Derive the payload contract per
invoked workflow from BO_API_Step_Input_Structure__c (schema-first), apply
rules R1–R8 from references/conventions-and-payload-rules.md, resolve every
reference in-sales-org, materialize ./out/smoke/{create,update,copy}.json, then
run initialize → ingest → poll status for each chosen workflow. Verify via a
direct BO_API_Transaction_Log__c query (any row != 'Calculated' → fail) plus
an outputWrites field assertion against ./out/smoke/expected.json. Update and
copy legs run only if the interview included them.
Short status: org, sales org, dry-run flag; namespace prefix; BO API seed rows
before/after (Phases 2 & 4); interview (preset name or resolved stepName,
entity, workflows, inputPaths, outputWrites); class deploy result +
workflow-step id + junction ids (1–3); smoke import ids per invoked workflow, all
Calculated with matching write assertions — or exactly which failed (SOQL,
expected, actual); manual follow-ups (none if clean).
BO_API_Transaction_Log__c row for the smoke import ids has Status__c != 'Calculated'. Calculated is the terminal success state (R2); Processed does NOT exist in the picklist.outputWrites assertion fails, or while any GenericDemoSetupDataBatch AsyncApexJob since the phase start is still running or failed.TPMSetupData / BO_API_* objects and the shipping REST endpoints declare.TPMSetupData.setupBOApi.--preset/--interview-file, stop and print the questions.create/update/copy are individually opt-in; derive is always excluded.BO_API_Step_Input_Structure__c and validate user input against that contract first.© forcedotcom, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 11 other files (references, assets) in skills/consumer-goods-promotion-bo-api-deploy of forcedotcom/sf-skills.
Open the folder on GitHubat commit e5164d9
Consumer Goods Promotion Bo API Deploy next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Consumer Goods Promotion Bo API Deploy this skillforcedotcom/sf-skills | 1.1k | — | ~4.9k | Automated safety check: Pass | Apache-2.0 | |
| Soql Lib Query Builderbeyond-the-cloud-dev/soql-lib | 154 | — | ~4.3k | Automated safety check: Pass | MIT | |
| Sf DatacloudJaganpro/sf-skills | 424 | — | ~2.7k | Automated safety check: Pass | MIT | |
| Soql Lib Selectorbeyond-the-cloud-dev/soql-lib | 154 | — | ~2k | Automated safety check: Pass | MIT | |
| Dev SetupPortwood-Global-Solutions/Portwood | 126 | — | ~1.1k | Automated safety check: Pass | Apache-2.0 | |
| Sf FlowJaganpro/sf-skills | 424 | — | ~1.8k | Automated safety check: Pass | MIT |
beyond-the-cloud-dev/soql-lib
Builds Salesforce SOQL queries using the SOQL Lib fluent builder API (SOQL.cls).
Jaganpro/sf-skills
Salesforce Data Cloud product orchestrator for connect→prepare→harmonize→segment→act workflows.
beyond-the-cloud-dev/soql-lib
Creates Salesforce Apex selector classes using the SOQL Lib selector pattern.
Portwood-Global-Solutions/Portwood
Get from a fresh clone of Portwood to a working, fully-tested Salesforce org.
Jaganpro/sf-skills
Creates and validates Salesforce Flows with 110-point scoring.
gmapsscraper/google-maps-agent-skills
Export Google Maps business data to CSV, JSON, or CRM format (HubSpot, Pipedrive, Salesforce).
forcedotcom/sf-skills
Declared architecture snapshot for one Agentforce agent: planner, topics, actions, flows, Apex, prompt templates, and NGA plugins.
forcedotcom/sf-skills
Data Cloud 360° view of a single Agentforce session. An agent skill from forcedotcom/sf-skills.
forcedotcom/sf-skills
Apply a Salesforce sandbox post-copy automation JSON config against a target org.
forcedotcom/sf-skills
Apply a Salesforce sandbox post-copy automation JSON config against a target org.
forcedotcom/sf-skills
Apply SLDS-compliant UI using the correct blueprints, styling hooks, utility classes, and icons.
forcedotcom/sf-skills
Lightning Web Components with PICKLES methodology and 165-point scoring.
Works with
Categories
A skill your agent uses to enable the Consumer Goods Cloud TPM Promotion Business Object (BO) API framework in a Salesforce org, interview the user for the custom Workflow Step they want to add…. Consumer Goods Promotion Bo API Deploy is an agent skill from forcedotcom/sf-skills. Use to enable the Consumer Goods Cloud TPM Promotion Business Object (BO) API framework in a Salesforce org, interview the user for the custom Workflow Step they want to add, generate and deploy that Apex class, wire it into the create/update/copy workflows, and prove it end-to-end via headless REST ingest.
Consumer Goods Promotion Bo API Deploy fits situations like: enable the Consumer Goods Cloud TPM Promotion Business Object (BO) API framework in a Salesforce org; interview the user for the custom Workflow Step they want to add; generate and deploy that Apex class; wire it into the create/update/copy workflows.
Run `npx skills add forcedotcom/sf-skills --skill consumer-goods-promotion-bo-api-deploy -a claude-code`. Or copy the skill folder (skills/consumer-goods-promotion-bo-api-deploy in forcedotcom/sf-skills) into .claude/skills/consumer-goods-promotion-bo-api-deploy in your project. Claude Code loads it when a task matches its description.
Run `npx skills add forcedotcom/sf-skills --skill consumer-goods-promotion-bo-api-deploy -a codex`. Or copy the skill folder (skills/consumer-goods-promotion-bo-api-deploy in forcedotcom/sf-skills) into .agents/skills/consumer-goods-promotion-bo-api-deploy in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add forcedotcom/sf-skills --skill consumer-goods-promotion-bo-api-deploy -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/consumer-goods-promotion-bo-api-deploy, .gemini/skills/consumer-goods-promotion-bo-api-deploy, .github/skills/consumer-goods-promotion-bo-api-deploy and .opencode/skills/consumer-goods-promotion-bo-api-deploy in your project.
Going by SKILL.md and its folder, Consumer Goods Promotion Bo API Deploy needs the command-line tools its instructions call (sf, jq and node).
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Consumer Goods Promotion Bo API Deploy is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.9k tokens (SKILL.md is roughly 20k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 11k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Consumer Goods Promotion Bo API Deploy: Soql Lib Query Builder (beyond-the-cloud-dev/soql-lib, 154 stars), Sf Datacloud (Jaganpro/sf-skills, 424 stars), Soql Lib Selector (beyond-the-cloud-dev/soql-lib, 154 stars) and Dev Setup (Portwood-Global-Solutions/Portwood, 126 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
forcedotcom (a GitHub organization) maintains it in forcedotcom/sf-skills, which has 1,065 GitHub stars. The repository holds 251 skills in this directory. The repository was last updated on October 7, 2026.
Source: forcedotcom/sf-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.