Salesforce-branded splash screen that displays on startup with an animated Pi + SALESFORCE wordmark and a two-column layout:
Left column:
- Animated Pi + SALESFORCE wordmark with Salesforce-blue and pastel-rainbow palettes
- Active model name and provider
- Monthly cost usage line with color-coded progress (green → orange → red)
- Optional Slack and auth-gated LLM Gateway status only when enabled/configured, plus lightweight SF CLI install/latest and Node CA certificate status
- Privacy row showing pi's anonymous-telemetry posture
(
telemetry off (sf-pi default)/(user override)/telemetry on (user override)). Driven bylib/common/privacy/state.ts— seeextensions/sf-pi-manager/README.mdfor the full decision matrix and the/sf-pi telemetrycommand surface. - Release freshness rows for SF Skills, sf-pi, and the Pi runtime. The sf-pi row also carries the bundled-extension active/total count so the splash avoids a separate redundant extension-health row.
Right column:
- Announcements panel (top of the column): maintainer notes from
the bundled
catalog/announcements.json, plus any entries from the optional remote feed and a synthetic update nudge when the installed sf-pi version is behindlatestVersion. The splash renders the top 3 active items after severity/date sorting; use/sf-pi announcementsfor full bodies and the complete list. Dismissed via/sf-pi announcements dismiss <id>, disabled entirely viaSF_PI_ANNOUNCEMENTS=offor{ "sfPi": { "announcements": false } }. - What's New panel (only after a pi-coding-agent version bump) with feature + fix bullets distilled from the bundled CHANGELOG.md
- Loaded counts (extensions, skills, prompt templates)
- Recent sessions with relative timestamps
- Recommended external pi packages (top 4 pending items), sf-pi shortcut tips, and skill-source nudges
- Community attribution
Extension loads
└─ session_start (reason="startup")
├─ setup issues / SF_PI_SAFE_START=1 → show non-blocking header + doctor nudge
├─ quietStartup=false → show overlay (any-key dismiss)
└─ quietStartup=true → show persistent header (Esc dismiss)
Dismissal triggers:
├─ Any keypress (overlay)
├─ Escape (header)
├─ agent_start (LLM responds)
└─ tool_call (agent working)
session_shutdown
└─ clear overlay/header state, reset animation flags, and unsubscribe usage-store listeners
-
Separate data collection from rendering —
splash-data.tsgathers all information,splash-component.tshandles TUI rendering. This keeps rendering pure and testable. -
Cost estimation from session files — Scans
.jsonlsession files modified this month, extractsusage.cost.totalfrom assistant messages. Approximate but zero-config. -
Extension health from the generated registry — Reads
catalog/registry.tsfor bundled extension metadata and combines it with settings.json filter state. This keeps the welcome screen aligned with the actual bundle list. -
Overlay vs header modes — Matches Pi's startup precedence rules while adding sf-pi safe start.
quietStartup: truein settings.json switches to a non-blocking header,sfPi.welcome.modecan forceauto/overlay/header/off, andSF_PI_SAFE_START=1keeps startup non-blocking so users can run/sf-pi doctor.--verbosestill forces the overlay unless safe-start is active. -
Lightweight SF CLI status — The welcome screen checks only
sf --versionplus an optional npm-registry lookup so it can showSF CLI installed · latestwithout running org/config detection. Full org/API context belongs to sf-devbar. -
Release freshness is cache-first — sf-pi release freshness reads the local package version and the bundled/cached announcements feed on first paint, then piggybacks on the deferred announcements refresh. Pi runtime freshness reads the installed pi version locally, then runs a deferred bounded
pi.devlatest-version fetch that respectsPI_OFFLINEandPI_SKIP_VERSION_CHECK. When npm release-age gating is configured, the Pi runtime row compares against the newest package version npm can currently install and renderslatest allowed [cooldown active]instead of a false update warning. Update hints render only when a newer installable version is known. -
Optional integration rows stay quiet — Slack and LLM Gateway rows are hidden unless their bundled extensions are enabled and have meaningful live status. This keeps public/external installs from seeing Salesforce-internal or unconfigured integrations as startup noise.
-
Background loading — CLI status, release freshness, Node CA certificate status, monthly usage, and remote announcements refresh asynchronously after the splash appears, so startup remains responsive while the visible rows update in place. Node CA detection is local-only and cache-first: first paint reads
sf-welcome/node-cert-status.json, then a deferred detector checksNODE_EXTRA_CA_CERTS, the sf-pi CA fixer state, LaunchAgent/shell exports, and bounded known PEM candidates without network calls, subprocesses, or recursive filesystem scans. -
Salesforce brand gradient — Uses actual Salesforce brand colors (#0070D2 blue, #01C3E2 Astro cyan, #9061F9 purple) for the Pi logo gradient.
-
Terminal-aware glyph policy — Every emoji/box icon on the splash (and in the sf-devbar bottom bar) routes through
lib/common/glyph-policy.ts. On terminals known to lack emoji font fallback (notably macOS Terminal.app, detected viaTERM_PROGRAM=Apple_Terminal), the policy swaps in ASCII equivalents (⚡→»,💰→$,📦→[], …) so users see readable status instead of?tofu. Users can override viaSF_PI_ASCII_ICONS=1/0orsfPi.asciiIcons: true|falseinsettings.json. -
Narrow-terminal single-column fallback — Below ~100 columns the splash stacks its two columns vertically so no content is truncated. Above that threshold the two-column layout grows up to 220 columns wide, filling wide terminals instead of leaving an ellipsised island.
-
Top-left anchored overlay — The splash hugs the top-left corner of the terminal with a 1-col left margin so it sits flush with pi's own prompt and bottom bar instead of floating center-screen on wide terminals.
-
Bundled Nerd Font installer — Four MesloLGM Nerd Font Mono TTFs ship under
assets/fonts/./sf-setup-fontscopies them into~/Library/Fonts(macOS) or~/.local/share/fonts(Linux) with SHA-256 verification, idempotent on repeat runs, and best-effort cache refresh viaatsutil/fc-cache. Windows users get manual install instructions. -
One-time install prompt — When the splash detects ASCII-fallback glyphs and the font isn't installed and the user hasn't been asked before,
sf-welcomeshows a singlectx.ui.confirm()dialog: "Install bundled Nerd Font?" The decision (yes or no) is persisted in~/.pi/agent/sf-welcome-state.jsonunderfontInstallDecision, so the prompt never fires again on that machine./sf-setup-fontsremains available as an explicit escape hatch.
| Event/Trigger | Condition | Result |
|---|---|---|
| session_start | reason="startup", quiet=false | Show overlay |
| session_start | reason="startup", quiet=true | Show persistent header |
| session_start | reason≠"startup" | Skip (resume, reload, fork) |
| session_start | first-ever launch | Persist current pi version, omit What's New |
| agent_start | overlay/header visible | Dismiss + persist seen pi version |
| tool_call | overlay/header visible | Dismiss + persist seen pi version |
| any keypress | overlay visible | Dismiss + persist seen pi version |
| Escape | header visible | Dismiss + persist seen pi version |
| session_shutdown | — | Clear overlay/header state and listeners |
| /sf-welcome | always | Show text summary |
| /sf-setup-fonts | always | Install bundled Nerd Font + refresh cache |
| session_start | ascii + no font + never asked | Ask once, persist answer, never re-ask |
extensions/sf-welcome/
assets/
fonts/
LICENSE ← bundled asset metadata
SOURCE.md ← bundled asset metadata
lib/
ca-bundle-nudge.ts ← implementation module
extension-health.ts ← implementation module
font-installer.ts ← implementation module
node-cert-status.ts ← implementation module
recommendations-status.ts← implementation module
release-status.ts ← implementation module
session-data.ts ← implementation module
sf-cli-status.ts ← implementation module
sf-skills-status.ts ← implementation module
splash-component.ts ← implementation module
splash-data.ts ← implementation module
startup-mode.ts ← implementation module
state-store.ts ← implementation module
types.ts ← implementation module
tests/
announcements-filter.test.ts← unit / smoke test
announcements-manifest.test.ts← unit / smoke test
announcements-orchestrator.test.ts← unit / smoke test
announcements-state.test.ts← unit / smoke test
announcements-update.test.ts← unit / smoke test
ca-bundle-nudge.test.ts ← unit / smoke test
extension-health.test.ts← unit / smoke test
font-installer.test.ts ← unit / smoke test
node-cert-status.test.ts← unit / smoke test
recommendations-status.test.ts← unit / smoke test
release-status.test.ts ← unit / smoke test
sdk-migration.test.ts ← unit / smoke test
session-data.test.ts ← unit / smoke test
sf-cli-status.test.ts ← unit / smoke test
sf-skills-status.test.ts← unit / smoke test
smoke.test.ts ← unit / smoke test
splash-privacy.test.ts ← unit / smoke test
splash-release-status.test.ts← unit / smoke test
splash-sf-skills.test.ts← unit / smoke test
splash-wordmark-shadow.test.ts← unit / smoke test
startup-mode.test.ts ← unit / smoke test
state-store.test.ts ← unit / smoke test
whats-new.test.ts ← unit / smoke test
CREDITS.md ← extension attribution
index.ts ← Pi extension entry point
manifest.json ← source-of-truth extension metadata
README.md ← human + agent walkthrough
The splash header has small script-level previews so visual tweaks can be reviewed without launching a full pi session:
node scripts/preview-pi-salesforce.mjs
node scripts/preview-sf-logo.mjs
node scripts/render-splash-header.mjsUse these only for local visual QA; runtime behavior still lives in
splash-component.ts and is covered by the tests above.
~/.pi/agent/sf-welcome-state.json records the pi-coding-agent version the
user has most recently acknowledged (via a dismissed splash). The What's New
panel appears only when the installed pi version is strictly greater than
that stored value. First-ever launches seed the file eagerly and show no
panel, so a fresh install is never noisy.
<globalAgentDir>/sf-pi/sf-welcome/pi-release-status.json caches the Pi
runtime latest-version result for 24 hours. sf-pi release freshness reuses the
announcements state/cache under <globalAgentDir>/state/sf-pi/announcements.json.
Run: npm test
- Smoke tests: Module exports, component instantiation, render output shape
- Registry alignment tests: Verifies extension health stays aligned with the generated registry
- Narrow terminal handling: Verifies graceful empty output below minimum width
- Announcements / recommendations: Verifies bundled manifest loading, merge/filter rules, and splash summaries
- Manual QA: Full visual testing in terminal with
pior the preview scripts above (overlay rendering, dismissal, animation)
Splash shows ? boxes (tofu) where glyphs should be:
Your terminal font cannot render the emoji/box glyphs and the terminal
doesn't fall back to a color emoji font. This is common on macOS
Terminal.app and some Powerlevel10k setups. Fixes:
- Run
/sf-setup-fontsto install the bundled MesloLGM Nerd Font. - Force ASCII glyphs for one session:
SF_PI_ASCII_ICONS=1 pi. - Persist in
~/.pi/agent/settings.json(or.pi/settings.json):{ "sfPi": { "asciiIcons": true } } - iTerm2 / Ghostty / WezTerm / VS Code terminals don't need any of the above — they fall back to the color emoji font on their own.
Splash feels too busy, stuck, or setup warnings are noisy:
Enable the compact header mode: "quietStartup": true in the same
settings.json, or run /sf-pi doctor fix startup. The dismissable splash is
replaced by a compact header above the prompt. Press Esc to dismiss it. For
recovery when the overlay is in the way, launch SF_PI_SAFE_START=1 pi and run
/sf-pi doctor.
You can also set sfPi.welcome.mode to auto, overlay, header, or off
in settings. Safe-start and detected setup issues prefer the non-blocking
header so users can repair the harness from inside pi.
Splash content gets truncated in a narrow terminal: Fixed — below ~100 columns the splash now stacks to a single column instead of clipping the right-hand tips panel. Above that width it grows up to 220 columns.
What's New panel shows on first run or won't go away:
The panel appears only when the installed pi version is strictly greater
than the version recorded in ~/.pi/agent/sf-welcome-state.json. First
launches seed that file so no panel shows. Delete the file to resurface
the banner, or let a future version bump supersede it.
/sf-setup-fonts says everything is already installed but the splash still shows ASCII:
The install is idempotent and verified by SHA-256. Two likely causes:
(a) your terminal is still configured to use a non-Nerd font — set it to
MesloLGM Nerd Font Mono and reopen the terminal; (b) your terminal
caches glyphs aggressively — atsutil server -shutdown on macOS or
fc-cache -f on Linux forces a refresh.
I was asked to install the font once and declined — how do I get the prompt back?
The decision is persisted in ~/.pi/agent/sf-welcome-state.json under
fontInstallDecision so we don't re-ask. Run /sf-setup-fonts directly
to install anyway, or edit that file if you want the one-time prompt
back.