What it does
A saved Salesforce pipeline report shows where things stand. The Monday question is different: what changed since last week, and which of those changes should worry anyone. This skill reads open opportunities grouped by stage and forecast category, then reads OpportunityHistory for the last seven days to find the deals that advanced, slipped a close date or dropped out of Commit.
It is written for sales managers who run a weekly pipeline call and would rather spend it on the deals than on rebuilding the stage by forecast category matrix in a spreadsheet.
How it works
1Total open pipeline
Run
SELECT StageName, ForecastCategoryName, COUNT(Id) n, SUM(Amount) total FROM Opportunity WHERE IsClosed = false AND CloseDate = THIS_FISCAL_QUARTER GROUP BY StageName, ForecastCategoryNamewithsf data query --query "..." --jsonor the RESTqueryresource. Drop theCloseDatefilter if the team reviews all open pipeline, not just this quarter.2Read last week's changes
SELECT OpportunityId, Opportunity.Name, Opportunity.Owner.Name, StageName, ForecastCategory, Amount, CloseDate, CreatedDate FROM OpportunityHistory WHERE CreatedDate = LAST_N_DAYS:7 ORDER BY OpportunityId, CreatedDate. Each row is the opportunity as it stood after a change; compare it with the row before (query older history for that opportunity when the window holds only one).- 3
3Sort the movement
Classify each change: stage forward or back (by
SortOrderfromOpportunityStage), forecast category into or out of Commit, close date pushed past the quarter end (a slip), amount changed by more than 10%, or Closed Lost. - 4
4Write the report
Total open pipeline and its change since last Monday, the stage by forecast category table with totals, up to 8 movers with owner and amount, and the slipped deals last.
Post it to the board
With
BRIEFKIN_TOKENset, the agent sends the result as one card that updates in place every run. Without it, you get the report in the chat.
What you get
- Open pipeline for the quarter and the change since last Monday.
- Stage by forecast category: the amount in each cell, with row and column totals.
- Movers: stage moves, forecast category changes and Closed Lost deals, with owner and amount.
- Slipped: deals whose close date moved out of the quarter.
- The two deals to discuss first on the call.
Install and run it
Pick your agent, where the data comes from and how to schedule it; the commands below follow.
Install the skill
One command. It puts the SKILL.md in ~/.claude/skills and in ~/.agents/skills, which Codex, Cursor, Gemini CLI, Copilot CLI and OpenCode read too.
shell
curl -fsSL https://briefkin.dev/skills/salesforce-pipeline-report/install | shRun it
Ask Claude Code:
prompt
Run the salesforce-pipeline-report skillOr paste the prompt instead of installing:
prompt
Using SOQL on my Salesforce org, give me open pipeline for this fiscal quarter grouped by StageName and ForecastCategoryName (count and sum of Amount), as a stage by forecast category table with totals. Then read OpportunityHistory rows created in the last 7 days and tell me which opportunities moved stage (forward or back), changed forecast category, were closed lost, or had their CloseDate pushed out of the quarter, with owner and amount. Compare the total with last Monday if you can. Finish with the two deals I should discuss first and why.Put it on a schedule
Mondays at 7:30, from cron on any machine where Claude Code is signed in:
crontab
30 7 * * 1 claude -p "Run the salesforce-pipeline-report skill"Add it with
crontab -e. A laptop asleep at that time runs it when it wakes if you use launchd or Task Scheduler instead; GitHub Actions works for the API route.Send it to your board
Connect Briefkin once with
curl -fsSL https://briefkin.dev/install | shand every run lands on your board as a stat tile. How setup works
View the SKILL.mdRaw file
SKILL.md---
name: salesforce-pipeline-report
description: "Monday mornings: open Salesforce pipeline by stage and forecast category, the deals that moved or slipped last week, and the change in total. Use when the user asks for this, or when it runs on a schedule."
---
# Salesforce weekly pipeline report
Monday mornings: open Salesforce pipeline by stage and forecast category, the deals that moved or slipped last week, and the change in total.
A saved Salesforce pipeline report shows where things stand. The Monday question is different: what changed since last week, and which of those changes should worry anyone. This skill reads open opportunities grouped by stage and forecast category, then reads `OpportunityHistory` for the last seven days to find the deals that advanced, slipped a close date or dropped out of Commit.
It is written for sales managers who run a weekly pipeline call and would rather spend it on the deals than on rebuilding the stage by forecast category matrix in a spreadsheet.
## Two ways to get the data
Use the API or MCP route when you have an MCP server, a CLI or an API token for the app. Otherwise, if you can drive a browser the user is signed in to (Claude in Chrome, a Playwright or Chrome DevTools MCP server), use the browser route. Say which one you used.
## Route A: API or MCP server
### What you need
- A Salesforce user who can see the whole team's opportunities and their OpportunityHistory.
- SOQL access: the `sf` CLI logged in once with `sf org login web`, a Salesforce connector, or an access token and instance URL in `SF_ACCESS_TOKEN` and `SF_INSTANCE_URL`.
If something is missing, say what and stop; do not invent numbers.
### Steps
1. **Total open pipeline** (Salesforce): Run `SELECT StageName, ForecastCategoryName, COUNT(Id) n, SUM(Amount) total FROM Opportunity WHERE IsClosed = false AND CloseDate = THIS_FISCAL_QUARTER GROUP BY StageName, ForecastCategoryName` with `sf data query --query "..." --json` or the REST `query` resource. Drop the `CloseDate` filter if the team reviews all open pipeline, not just this quarter.
2. **Read last week's changes** (Salesforce): `SELECT OpportunityId, Opportunity.Name, Opportunity.Owner.Name, StageName, ForecastCategory, Amount, CloseDate, CreatedDate FROM OpportunityHistory WHERE CreatedDate = LAST_N_DAYS:7 ORDER BY OpportunityId, CreatedDate`. Each row is the opportunity as it stood after a change; compare it with the row before (query older history for that opportunity when the window holds only one).
3. **Sort the movement**: Classify each change: stage forward or back (by `SortOrder` from `OpportunityStage`), forecast category into or out of Commit, close date pushed past the quarter end (a slip), amount changed by more than 10%, or Closed Lost.
4. **Write the report**: Total open pipeline and its change since last Monday, the stage by forecast category table with totals, up to 8 movers with owner and amount, and the slipped deals last.
## Route B: the browser
### What you need
- Signed in to Salesforce as a user with the Run Reports permission and visibility of the whole team's opportunities, such as a manager above them in the role hierarchy.
If something is missing, say what and stop; do not invent numbers.
### Steps
Start at https://login.salesforce.com/. The user is signed in already; never type passwords or codes, and ask if a sign-in page appears.
1. **Sign in to your org**: Salesforce has no shared report URL: after sign-in you land on your own My Domain (`https://<company>.lightning.force.com`). Open the **Reports** tab from the App Launcher.
2. **Build the stage by forecast category matrix**: Click **New Report**, report type **Opportunities**. Filters: **Show Me** All opportunities, **Close Date** **Current FQ**, **Opportunity Status** Open. Group rows by **Stage** and columns by **Forecast Category**, add **Amount** with **Sum**, then **Run**. The subtotals are the table; the grand total is open pipeline. Save it so next Monday is one click.
3. **Read last week's changes**: A second report with the **Opportunity History** report type, filtered on **Last Modified Date** **Last 7 days**, shows one row per change with **From Stage**, **To Stage**, Amount, Close Date and Forecast Category. Add Opportunity Owner and sort by Opportunity Name.
4. **Sort the movement**: Classify each row as a stage move forward or back (by the order of your sales process), Commit in or out, a close date pushed past quarter end (a slip), an amount change over 10%, or Closed Lost. Compare the total with the number you saved last Monday.
5. **Write the report**: Open pipeline and its change, the matrix with totals, up to 8 movers with owner and amount, the slipped deals last, and the two deals to raise first.
Note: Report previews show up to 2,000 rows; with more history rows, use **Export** with Details Only as CSV. The Opportunity History report type records stage, amount, probability, forecast category and close date changes, the same source as the API route. If the Opportunity Status filter is missing, add Closed equals False instead.
## The report
- **Open pipeline** for the quarter and the change since last Monday.
- **Stage by forecast category**: the amount in each cell, with row and column totals.
- **Movers**: stage moves, forecast category changes and Closed Lost deals, with owner and amount.
- **Slipped**: deals whose close date moved out of the quarter.
- The two deals to discuss first on the call.
## Post it to Briefkin
When `BRIEFKIN_TOKEN` is set, or `~/.config/briefkin/env` exists (the installer from https://briefkin.dev/docs writes it), also send the result to the user's Briefkin board as one card. Keep the `item_key` the same on every run so the card updates in place, use a new `event_id` per run, and put today's real numbers in place of the example ones. If the request fails, say so once and carry on.
```bash
[ -n "${BRIEFKIN_TOKEN:-}" ] || . ~/.config/briefkin/env
curl -sS -X POST "${BRIEFKIN_URL:-https://briefkin.dev}/v1/events" \
-H "authorization: Bearer $BRIEFKIN_TOKEN" \
-H "content-type: application/json" \
-d @- <<'JSON'
{
"v": 1,
"event_id": "salesforce-pipeline-report/<date of this run, e.g. 2026-10-16>",
"item_key": "salesforce-pipeline-report",
"project": "Acme",
"source": "Salesforce weekly pipeline report skill",
"kind": "metric",
"title": "Open pipeline $2.41M, down 3% on last week",
"metric": {
"label": "Open pipeline",
"value": 2410000,
"prefix": "$",
"better": "higher",
"period_start": "<start of the period, ISO 8601>",
"period_end": "<end of the period, ISO 8601>"
},
"glance": {
"type": "Grid",
"props": {
"columns": 3
},
"children": [
{
"type": "Stat",
"props": {
"label": "Commit",
"value": "$740k",
"tone": "ok"
}
},
{
"type": "Stat",
"props": {
"label": "Best case",
"value": "$610k"
}
},
{
"type": "Stat",
"props": {
"label": "Pipeline",
"value": "$1.06M"
}
}
]
},
"widget": [
{
"type": "Table",
"props": {
"columns": [
"Stage",
"Pipeline",
"Best case",
"Commit",
"Total"
],
"align": [
"left",
"right",
"right",
"right",
"right"
],
"rows": [
[
"Qualification",
"$420k",
"$0",
"$0",
"$420k"
],
[
"Needs Analysis",
"$380k",
"$90k",
"$0",
"$470k"
],
[
"Proposal/Price Quote",
"$260k",
"$330k",
"$120k",
"$710k"
],
[
"Negotiation/Review",
"$0",
"$190k",
"$620k",
"$810k"
],
[
"Total",
"$1.06M",
"$610k",
"$740k",
"$2.41M"
]
]
}
},
{
"type": "Table",
"props": {
"columns": [
"Opportunity",
"Owner",
"Amount",
"What changed"
],
"align": [
"left",
"left",
"right",
"left"
],
"rows": [
[
"Contoso EMEA rollout",
"Lena",
"$180k",
"Proposal → Negotiation, now Commit"
],
[
"Northwind analytics add-on",
"Priya",
"$64k",
"Needs Analysis → Proposal"
],
[
"Adatum platform",
"Sam",
"$120k",
"Commit → Best case"
],
[
"Litware seats",
"Theo",
"$48k",
"Closed Lost: budget frozen"
],
[
"Fabrikam renewal",
"Marco",
"$95k",
"Close date Nov 28 → Jan 15 (slipped)"
]
]
}
},
{
"type": "Callout",
"props": {
"text": "$95k slipped out of the quarter: Fabrikam moved its close date to January.",
"tone": "warn"
}
}
],
"size": "md"
}
JSON
```
Widgets come from the Briefkin catalog (https://briefkin.dev/v1/catalog). Without a token, just give the user the report.
Set `period_start` and `period_end` to the window the number covers: the tile names it from them ("Last 7 days", "Today", "This month"). For a count right now (open items, a balance), send `"period_label": ""` so no period shows; for another name, send it as `period_label` (at most 24 characters).
## Run it on a schedule
Suggested: Mondays at 7:30 (`30 7 * * 1`). From cron, with the agent signed in on that machine:
```bash
30 7 * * 1 claude -p "Run the salesforce-pipeline-report skill"
# Codex: codex exec, Gemini CLI: gemini -p, Copilot CLI: copilot -p, OpenCode: opencode run
```
Or use the agent's own scheduler (Claude Code routines, Codex automations, Claude or ChatGPT scheduled tasks): https://briefkin.dev/skills/salesforce-pipeline-report#schedule
Source: https://briefkin.dev/skills/salesforce-pipeline-report
What your agent needs
A Salesforce user who can see the whole team's opportunities and their OpportunityHistory.
SOQL access: the
sfCLI logged in once withsf org login web, a Salesforce connector, or an access token and instance URL inSF_ACCESS_TOKENandSF_INSTANCE_URL.
Connecting Salesforce
- Salesforce Hosted MCP Servers. Salesforce runs MCP servers for your org; in Setup under MCP Servers, activate the read-only SObject Reads server and copy its URL. To use it from Claude, create an External Client App with OAuth (scopes
mcp_apiandrefresh_token, callbackhttps://claude.ai/api/mcp/auth_callback) and add the URL as a custom connector (server reference). - The
sfCLI. Log in once withsf org login web --alias prod, then runsf data query --query "SELECT Name, StageName, Amount, CloseDate FROM Opportunity WHERE IsClosed = false" --target-org prod --json. Salesforce's DX MCP server (npx @salesforce/mcp) reuses the same CLI login for local agents. - REST API with OAuth. An External Client App with the
apiandrefresh_tokenscopes; the skill readsSF_INSTANCE_URLandSF_ACCESS_TOKEN(or a refresh token) and calls the query endpoint.
SObject Reads and SOQL never write, but the user's permissions are the real limit: run reports as an integration user whose permission set grants Read on Opportunity, Account, Lead and Case and nothing else.
Questions
Does it follow our fiscal quarters?
THIS_FISCAL_QUARTER uses the fiscal year defined in Setup under Fiscal Year. With a standard fiscal year that matches calendar quarters; with a custom one it follows your own periods.
Why does an opportunity appear in history with no stage move?
Salesforce adds an OpportunityHistory row when the stage, amount, probability, forecast category or close date changes. The skill reports a close date pushed past the quarter as a slip and amount changes over 10% as movers; smaller edits are left out.
Do I need Briefkin to use the Salesforce weekly pipeline report skill?
No. The skill runs with your own agent and gives you the report in the chat. With a Briefkin token set, each run also posts it to your board as a stat tile, so you can glance at it instead of asking again.
Which agents can run it?
Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot CLI, OpenCode, Windsurf and Amp all read SKILL.md files. The install command puts it in ~/.claude/skills and ~/.agents/skills, where they look. ChatGPT, the Claude app and Grok take the prompt instead. Pick your agent under "Install and run it" and the commands change to match.
Can it work without an API or MCP server, from my browser?
Yes. Switch the data source to "Your browser" and the steps change to the Salesforce pages themselves: the agent opens login.salesforce.com in a browser you are signed in to and reads the numbers off the page. Claude Code, Codex, Cursor, Claude app and ChatGPT can drive a browser out of the box; Gemini CLI, Copilot CLI and OpenCode need a Playwright or Chrome DevTools MCP server first. It is slower than the API and needs you signed in, so it suits a report you run by hand or from a scheduler on your own computer.