Salesforce reports
A collection of practical Claude Code skills — multi-LLM evaluation, domain management, planning, writing quality, and pair-session patterns. MIT licensed.
npx -y skills add eprouveze/claude-skills --skill salesforce-reportsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Create, clone, read, run, and delete Salesforce Reports from the command line via the Analytics REST API, driven by the Salesforce CLI (`sf`). Org-agnostic — works against any org you've authed with `sf`. Includes a `--setup` flow (installs the sf CLI if missing, saves a default org/API version, and an optional Global Company filter for GAM roles). Use when the user says "create a Salesforce report", "clone a report", "generate a report via sf CLI", "list/run/delete reports", "report API", or "Analytics REST reports".
SKILL.md
8.7 KB, ~2.1k tokens by cl100k_base, as published. Nobody here has run it
Salesforce Reports
Manage Salesforce Reports (the analytics object, not deploy/package "report" status
commands) from the CLI. There is no native sf report create command — report CRUD lives
in the Analytics REST API (/services/data/vXX.0/analytics/reports). This skill wraps
that API through sf api request rest, which is the only path that authenticates correctly
with the CLI's (masked) access token.
Everything routes through one script: scripts/sfreport.sh.
Quick start
S=~/.claude/skills/salesforce-reports/scripts/sfreport.sh
"$S" setup --org org62 # installs sf CLI if missing, saves config, checks auth
"$S" list # all reports you can see
"$S" types # report types (the 'type' you pass to create)
"$S" get <id> --describe # a report's metadata (filters, columns, format)
"$S" run <id> # run synchronously, return rows
"$S" clone --from <id> --name "Copy of X" # most reliable way to create a report
"$S" create --type <apiName> --name "New" \
--column <api> --filter '<col> <op> <value>' --group <api> # report with columns/filters
"$S" delete <id> --yes # delete (HTTP 204 on success)
"$S" --help # full reference
The script picks its target org from: --org flag → saved config (setup) → the sf CLI's
configured target-org.
Setup
sfreport.sh setup is the front door:
- sf CLI presence. If
sfis missing, setup offers to install it (npm → Homebrew → yarn, whichever is present). Non-interactively it installs without prompting. - Default org + API version. Saved to
~/.config/claude-skills/salesforce-reports.envso you don't repeat--orgevery call. API version defaults to62.0(Analytics REST is stable there). - Auth check. Confirms the Analytics REST endpoint is reachable; on failure it prints
the
sf org login webcommand to run. - Global Company filter (GAM roles only — optional). See below.
Non-interactive form for scripts/CI:
"$S" setup --org myorg --api 62.0 --check-only # check, don't write config
"$S" setup --org myorg --global-company "NTT, Inc." --gc-column Account.Global_Company__c
Global Company filter (GAM roles)
A Global Account Manager scopes reports to a single global parent account. This skill can re-point that filter on any clone so you don't hand-edit metadata:
"$S" clone --from <id> --name "NTT Pipeline" \
--gc "NTT, Inc." --gc-column Account.Global_Company__c
Configure a default once at setup (GLOBAL_COMPANY + GC_COLUMN_DEFAULT) and every clone
inherits it; override per-call with --gc / --gc-column. Resolution order for the value:
--gc arg → $GLOBAL_COMPANY (env or saved config).
This is GAM-specific. Any other role can ignore it entirely — leave both blank at setup and the skill never touches report filters. To discover the right column on a report:
"$S" get <id> --describe | python3 -c \
'import sys,json;[print(f["column"]) for f in json.load(sys.stdin)["reportMetadata"]["reportFilters"]]'
How creation actually works
Two create paths, in order of reliability:
-
Clone (recommended).
POST /analytics/reports?cloneId=<id>with the source report's fullreportMetadata(renamed). The skill fetches/describe, renames, optionally re-points the Global Company filter, and POSTs. This always yields a working report with columns and groupings already in place. -
Create with metadata.
POST /analytics/reportswith areportMetadatanaming areportType. Usetypesto find a validreportTypeapi name, andget <existing> --describeto discover that type's valid column / filter / grouping api names. The skill accepts:--column <api>(repeatable) →detailColumns--filter '<col> <operator> <value>'(repeatable) →reportFilters; the value is the remainder of the string, so spaces/commas are fine (--filter 'StageName equals Closed Won'). Operators:equals,notEqual,lessThan,greaterThan,contains,startsWith, etc.--group <api>(repeatable) →groupingsDown(required forSUMMARY/MATRIX)--boolean-filter '<expr>'→reportBooleanFilter(e.g.'1 AND (2 OR 3)')--gc <value> --gc-column <api>→ adds the GAM Global Company equals-filter With no--column, create still produces an empty stub. Clone remains the easiest path when you want to start from an existing report's full layout.
"$S" create --type Opportunity --name "My Q3 Pipeline" --format SUMMARY \ --column StageName --column Amount --column CloseDate \ --filter 'StageName equals Closed Won' --filter 'Amount greaterThan 50000' \ --group StageName
Known gotchas
- Clone still needs a metadata body.
POST ...?cloneId=<id>with a bare{}returnsBAD_REQUEST: "there is no metadata". You must POST the fullreportMetadata. The skill handles this by fetching/describefirst. sf api request restDELETE is finicky. A plain-X DELETEerrorsNo 'mode' found in 'body' entry;-b ''and--body '{...}'don't help; an object-shapedheadererrorskeyValPair.map is not a function. The working form (used internally) is-f <envelope.json>withheaderas an array of"k:v"strings andbody: {"mode":"raw","raw":""}.- Don't curl with the CLI token.
sf org display [--verbose]returns a masked 54-char access token; curl with it givesINVALID_AUTH_HEADER. Always go throughsf api request rest, which authenticates internally. - API version. Defaults to
62.0. The CLI's default data API may be higher (e.g. 67.0) but Analytics REST report CRUD is verified on 62.0; bump with--apionly if you've tested.
Anti-patterns
sf data delete record --sobject Report— fails withINSUFFICIENT_ACCESS_OR_READONLYeven when the Analytics DELETE succeeds; the SObject path enforces different rights. Delete reports via the Analytics endpoint (sfreport.sh delete).- Hardcoding an org alias. The skill is org-agnostic; pass
--orgor save one viasetup. Don't bakeorg62into callers. - Treating
sf commands | grep reporthits as report CRUD. Those are package/deploy status commands (package version report,project deploy report). Unrelated. - Bare-create then expecting data. A
createwithout columns is empty by design — clone when you want a usable report.
Validated patterns
- Clone → verify returned 18-char Id → use/delete. Verified on org62: create HTTP 200,
delete HTTP 204, post-delete
get→NOT_FOUND. setup --check-onlyas a CI/pre-flight gate before any report automation.- GAM scoping by re-pointing one
reportFiltersentry on clone, rather than rebuilding the report — preserves columns, groupings, and report type.
Self-improvement
This skill ships with a lightweight feedback loop (learnings.md). Adopt or ignore — the
skill works without it.
Trigger a review when:
- The user corrects a created/cloned report's filter, name, or scope (strongest signal — log immediately; 2–3 corrections on the same theme → promote to the body).
- The sf CLI changes its body/auth handling (e.g. the DELETE envelope bug gets fixed — the
case-delete-envelope.shgolden case is the canary). - A new Analytics REST behavior or error code surfaces.
learnings.mdcrosses ~100 bullets (consolidation time).- The skill mis-triggers or fails to trigger.
Consolidation pass (5–10 min, weekly or threshold-driven): each learnings.md entry gets one
fate — apply (merge into Known gotchas / Anti-patterns / Validated patterns), capture
(leave in the log), or dismiss (delete). Bump last-consolidated: in frontmatter. Golden
cases that previously passed and now fail are the loudest signal to consolidate early.
Golden cases live in golden/ — run ORG=<sandbox> golden/run-all.sh before changing the
script.
What ships with it: 8 files
26.3 KB alongside SKILL.md, 6 of them executable
golden/
- case-create-delete-roundtrip.shruns1.2 KB
- case-delete-envelope.shruns1.0 KB
- case-list.shruns500 B
- case-setup-check.shruns511 B
- README.md1.5 KB
- run-all.shruns543 B
scripts/
- sfreport.shruns17.8 KB
- learnings.md3.2 KB