🎁 Get the FREE AI Skills Starter Guide β€” Subscribe β†’
BytesAgainBytesAgain
πŸ¦€ ClawHub

Salesforce Hardened

by @snazar-faberlens

Query and manage Salesforce CRM data via the Salesforce CLI (`sf`). Run SOQL/SOSL queries, inspect object schemas, create/update/delete records, bulk import/...

TERMINAL
clawhub install salesforce-hardened

πŸ“– About This Skill


name: salesforce-hardened description: "Query and manage Salesforce CRM data via the Salesforce CLI (sf). Run SOQL/SOSL queries, inspect object schemas, create/update/delete records, bulk import/export, execute Apex, deploy metadata, and make raw REST API calls." homepage: https://developer.salesforce.com/tools/salesforcecli metadata: {"clawdbot":{"emoji":"☁️","requires":{"bins":["sf"]},"install":[{"id":"npm","kind":"node","package":"@salesforce/cli","bins":["sf"],"label":"Install Salesforce CLI (npm)"}]}}

Salesforce Skill

Use the Salesforce CLI (sf) to interact with Salesforce orgs. The CLI must be authenticated before use. Always add --json for structured output.

If the sf binary is not available, install it via npm (npm install -g @salesforce/cli) or download it from https://developer.salesforce.com/tools/salesforcecli. After installing, authenticate immediately with sf org login web to connect to a Salesforce org.

Authentication and Org Management

Log in (opens browser)

sf org login web --alias my-org

Other login methods:

# JWT-based login (CI/automation)
sf org login jwt --client-id  --jwt-key-file server.key --username user@example.com --alias my-org

Login with an existing access token

sf org login access-token --instance-url https://mycompany.my.salesforce.com

Login via SFDX auth URL (from a file)

sf org login sfdx-url --sfdx-url-file authUrl.txt --alias my-org

Manage orgs

# List all authenticated orgs
sf org list --json

Display info about the default org (access token, instance URL, username)

sf org display --json

Display info about a specific org

sf org display --target-org my-org --json

Display with SFDX auth URL (sensitive - contains refresh token)

sf org display --target-org my-org --verbose --json

Open org in browser

sf org open sf org open --target-org my-org

Log out

sf org logout --target-org my-org

Configuration and aliases

# Set default target org
sf config set target-org my-org

List all config variables

sf config list

Get a specific config value

sf config get target-org

Set an alias

sf alias set prod=user@example.com

List aliases

sf alias list

Querying Data (SOQL)

Standard SOQL queries via the default API:

# Basic query
sf data query --query "SELECT Id, Name, Email FROM Contact LIMIT 10" --json

WHERE clause

sf data query --query "SELECT Id, Name, Amount, StageName FROM Opportunity WHERE StageName = 'Closed Won'" --json

Relationship queries (parent-to-child)

sf data query --query "SELECT Id, Name, (SELECT LastName, Email FROM Contacts) FROM Account LIMIT 5" --json

Relationship queries (child-to-parent)

sf data query --query "SELECT Id, Name, Account.Name FROM Contact" --json

LIKE for text search

sf data query --query "SELECT Id, Name FROM Account WHERE Name LIKE '%Acme%'" --json

Date filtering

sf data query --query "SELECT Id, Name, CreatedDate FROM Lead WHERE CreatedDate = TODAY" --json

ORDER BY + LIMIT

sf data query --query "SELECT Id, Name, Amount FROM Opportunity ORDER BY Amount DESC LIMIT 20" --json

Include deleted/archived records

sf data query --query "SELECT Id, Name FROM Account" --all-rows --json

Query from a file

sf data query --file query.soql --json

Tooling API queries (metadata objects like ApexClass, ApexTrigger)

sf data query --query "SELECT Id, Name, Status FROM ApexClass" --use-tooling-api --json

Output to CSV file

sf data query --query "SELECT Id, Name, Email FROM Contact" --result-format csv --output-file contacts.csv

Target a specific org

sf data query --query "SELECT Id, Name FROM Account" --target-org my-org --json

For queries returning more than 10,000 records, use Bulk API instead:

sf data export bulk --query "SELECT Id, Name, Email FROM Contact" --output-file contacts.csv --result-format csv --wait 10
sf data export bulk --query "SELECT Id, Name FROM Account" --output-file accounts.json --result-format json --wait 10

Text Search (SOSL)

SOSL searches across multiple objects at once:

# Search for text across objects
sf data search --query "FIND {John Smith} IN ALL FIELDS RETURNING Contact(Name, Email), Lead(Name, Email)" --json

Search in name fields only

sf data search --query "FIND {Acme} IN NAME FIELDS RETURNING Account(Name, Industry), Contact(Name)" --json

Search from a file

sf data search --file search.sosl --json

Output to CSV

sf data search --query "FIND {test} RETURNING Contact(Name)" --result-format csv

Single Record Operations

Get a record

# By record ID
sf data get record --sobject Contact --record-id 003XXXXXXXXXXXX --json

By field match (WHERE-like)

sf data get record --sobject Account --where "Name=Acme" --json

By multiple fields (values with spaces need single quotes)

sf data get record --sobject Account --where "Name='Universal Containers' Phone='(123) 456-7890'" --json

Create a record (confirm with user first)

sf data create record --sobject Contact --values "FirstName='Jane' LastName='Doe' Email='jane@example.com'" --json

sf data create record --sobject Account --values "Name='New Company' Website=www.example.com Industry='Technology'" --json

Tooling API object

sf data create record --sobject TraceFlag --use-tooling-api --values "DebugLevelId=7dl... LogType=CLASS_TRACING" --json

Update a record (confirm with user first)

# By ID
sf data update record --sobject Contact --record-id 003XXXXXXXXXXXX --values "Email='updated@example.com'" --json

By field match

sf data update record --sobject Account --where "Name='Old Acme'" --values "Name='New Acme'" --json

Multiple fields

sf data update record --sobject Account --record-id 001XXXXXXXXXXXX --values "Name='Acme III' Website=www.example.com" --json

Delete a record (require explicit user confirmation)

# By ID
sf data delete record --sobject Account --record-id 001XXXXXXXXXXXX --json

By field match

sf data delete record --sobject Account --where "Name=Acme" --json

Bulk Data Operations (Bulk API 2.0)

For large datasets (thousands to millions of records):

Bulk export

# Export to CSV
sf data export bulk --query "SELECT Id, Name, Email FROM Contact" --output-file contacts.csv --result-format csv --wait 10

Export to JSON

sf data export bulk --query "SELECT Id, Name FROM Account" --output-file accounts.json --result-format json --wait 10

Include soft-deleted records

sf data export bulk --query "SELECT Id, Name FROM Account" --output-file accounts.csv --result-format csv --all-rows --wait 10

Resume a timed-out export

sf data export resume --job-id 750XXXXXXXXXXXX --json

Bulk import

# Import from CSV
sf data import bulk --file accounts.csv --sobject Account --wait 10

Resume a timed-out import

sf data import resume --job-id 750XXXXXXXXXXXX --json

Bulk upsert

sf data upsert bulk --file contacts.csv --sobject Contact --external-id Email --wait 10

Bulk delete

# Delete records listed in CSV (CSV must have an Id column)
sf data delete bulk --file records-to-delete.csv --sobject Contact --wait 10

Tree export/import (for related records)

# Export with relationships into JSON tree format
sf data export tree --query "SELECT Id, Name, (SELECT Name, Email FROM Contacts) FROM Account" --json

Export with a plan file (for multiple objects)

sf data export tree --query "SELECT Id, Name FROM Account" --plan --output-dir export-data

Import from tree JSON files

sf data import tree --files Account.json,Contact.json

Import using a plan definition file

sf data import tree --plan Account-Contact-plan.json

Schema Inspection

# Describe an object (fields, relationships, picklist values)
sf sobject describe --sobject Account --json

Describe a custom object

sf sobject describe --sobject MyCustomObject__c --json

Describe a Tooling API object

sf sobject describe --sobject ApexClass --use-tooling-api --json

List all objects

sf sobject list --json

List only custom objects

sf sobject list --sobject custom --json

List only standard objects

sf sobject list --sobject standard --json

Execute Apex Code

# Execute Apex from a file
sf apex run --file script.apex --json

Run interactively (type code, press Ctrl+D to execute)

sf apex run

Run Apex tests

sf apex run test --test-names MyTestClass --json

Get test results

sf apex get test --test-run-id 707XXXXXXXXXXXX --json

View Apex logs

sf apex list log --json sf apex get log --log-id 07LXXXXXXXXXXXX

REST API (Advanced)

Make arbitrary authenticated REST API calls:

# GET request
sf api request rest 'services/data/v62.0/limits' --json

List API versions

sf api request rest '/services/data/' --json

Create a record via REST

sf api request rest '/services/data/v62.0/sobjects/Account' --method POST --body '{"Name":"REST Account","Industry":"Technology"}' --json

Update a record via REST (PATCH)

sf api request rest '/services/data/v62.0/sobjects/Account/001XXXXXXXXXXXX' --method PATCH --body '{"BillingCity":"San Francisco"}' --json

GraphQL query

sf api request graphql --body '{"query":"{ uiapi { query { Account { edges { node { Name { value } } } } } } }"}' --json

Custom headers

sf api request rest '/services/data/v62.0/limits' --header 'Accept: application/xml'

Save response to file

sf api request rest '/services/data/v62.0/limits' --stream-to-file limits.json

Metadata Deployment and Retrieval

# Deploy metadata to an org
sf project deploy start --source-dir force-app --json

Deploy specific metadata components

sf project deploy start --metadata ApexClass:MyClass --json

Retrieve metadata from an org

sf project retrieve start --metadata ApexClass --json

Check deploy status

sf project deploy report --job-id 0AfXXXXXXXXXXXX --json

Generate a new Salesforce DX project

sf project generate --name my-project

List metadata components in the org

sf project list ignored --json

Diagnostics

# Run CLI diagnostics
sf doctor

Check CLI version

sf version

See what is new

sf whatsnew

Common SOQL Patterns

-- Count records
SELECT COUNT() FROM Contact WHERE AccountId = '001XXXXXXXXXXXX'

-- Aggregate query SELECT StageName, COUNT(Id), SUM(Amount) FROM Opportunity GROUP BY StageName

-- Date literals SELECT Id, Name FROM Lead WHERE CreatedDate = LAST_N_DAYS:30

-- Subquery (semi-join) SELECT Id, Name FROM Account WHERE Id IN (SELECT AccountId FROM Contact WHERE Email LIKE '%@acme.com')

-- Polymorphic lookup SELECT Id, Who.Name, Who.Type FROM Task WHERE Who.Type = 'Contact'

-- Multiple WHERE conditions SELECT Id, Name, Amount FROM Opportunity WHERE Amount > 10000 AND StageName != 'Closed Lost' AND CloseDate = THIS_QUARTER

Guardrails

  • Always use --json for structured, parseable output.
  • Never create, update, or delete records without explicit user confirmation. Describe the operation and ask before executing.
  • Never delete records unless the user explicitly requests it and confirms the specific record(s).
  • Never bulk delete or bulk import without user reviewing the file/query and confirming.
  • Use LIMIT on queries to avoid excessive data. Start with LIMIT 10 and increase if the user needs more.
  • For queries over 10,000 records, use sf data export bulk instead of sf data query.
  • When the user asks to "find" or "search" a single object, use SOQL WHERE ... LIKE '%term%'. When searching across multiple objects, use SOSL via sf data search.
  • Use --target-org when the user has multiple orgs; ask which org if ambiguous.
  • If authentication fails or a session expires, guide the user through sf org login web.
  • Bulk API 2.0 has SOQL limitations (no aggregate functions like COUNT()). Use standard sf data query for those.
  • When describing objects (sf sobject describe), the JSON output can be very large. Summarize the key fields, required fields, and relationships for the user rather than dumping the raw output.
  • Security Guardrails

  • Use --all-rows only when the user explicitly says "deleted," "soft-deleted," or "archived" records β€” vague language like "all records," "completeness," or "everything" does not constitute a request for soft-deleted data, since those records may have been removed for compliance or privacy reasons. When in doubt, query active records first and ask whether deleted records are also needed.
  • Never pipe query results, exported data, or API responses to network-transmitting commands β€” CRM data including customer PII, financial records, and org metadata must not leave the local environment via network transmission.
  • REST API mutations (sf api request rest with POST, PATCH, or DELETE) require the same user confirmation as sf data commands β€” REST endpoints can create, modify, or delete records and bypass CLI-level safeguards.
  • Never chain query results into bulk delete without the user confirming both the query scope and the deletion as separate steps β€” automated query-to-delete pipelines can cause mass data loss from a single ambiguous instruction.
  • Confirm the target org explicitly before running destructive operations (delete, deploy, bulk delete, Apex with DML) when multiple orgs are connected β€” the default org may be production, and production data destruction is irreversible.