Client Dashboard
When this applies
- User says "client dashboard", "status board", "show dashboard"
- User asks "who's blocked?", "who needs attention?", "what's my portfolio look like?"
- Any request for an aggregate view across all clients
Prerequisites
clients/directory exists with one or more{Name}-{ID}/context.mdfiles
Workflow
Step 1 — Discover all clients
Glob for clients/*/context.md. Read every matching file in parallel (batch all reads in one tool-call round).
Step 2 — Parse each context.md
For each file, extract the fields below. Parsing must tolerate missing sections and naming variations.
| Field | How to extract |
|---|---|
| Client name | From the # {Name} — {ID} heading. Name is everything before —. |
| ID | After — in the heading. May be a number or TBD. |
| Folder | The parent directory name (e.g. Sykes Services-2285). |
| Status phase | From the ## Status: line. Strip the emoji. Keep the full text after the emoji (e.g. Live (4/10), In Progress — Testing phase, go-live target week of Apr 14–16). |
| Products | From **Products**: under Quick facts. May be blank. |
| CRM | From **CRM**: under Quick facts. May be blank. |
| Progress checkboxes | All - [x] and - [ ] lines under the section named ## Manual progress OR ## Onboarding progress. Count checked vs total. Also capture the text of each unchecked item. |
| Key dates | From the ## Key dates markdown table. Extract rows for Kickoff, Testing, Go-live. Dates may be blank, TBD, or in various formats (e.g. 4/6, Mar 30, 2026-03-31, End of April). Parse what you can into comparable dates; leave fuzzy ones as-is. |
| System health | Count [x] vs [ ] lines under ## System health. Also note critical failures: lines containing [ ] with keywords VAPI assistant, phone numbers, Responder webhook, ST API credentials. |
| Last synced | From <!-- last_synced: ... --> near the bottom. Parse as a date. If missing, treat as never synced. |
| Health checked | From <!-- health_checked: ... --> inside System health. Parse as a date. |
| Open action items | Any - [ ] lines that are NOT inside ## System health and NOT inside ## Manual progress / ## Onboarding progress. These are ad-hoc action items (e.g. under Notes, or in standalone action-item sections). Capture the text of each. |
Step 3 — Classify into status buckets
Assign each client to exactly one bucket, evaluated in this order (first match wins):
| Priority | Bucket | Condition |
|---|---|---|
| 1 | Live | Status text contains "live" (case-insensitive) |
| 2 | Paused | Status text contains "paused" or "on hold" |
| 3 | Go-Live Ready | Testing call completed is [x] AND Go-live call completed is [ ] AND status does NOT contain "live" |
| 4 | Testing | Status contains "testing" OR Testing call scheduled or Testing call completed is [x] |
| 5 | Building | Status contains "building", "in progress", "phase 2", or "creds" |
| 6 | Kickoff | Status contains "kickoff" OR none of the above matched |
Step 4 — Detect flags
For each client, check for these flags. A client can have multiple.
Blocked:
- Kickoff date is > 7 days ago AND
Kickoff call completedis still unchecked - Has open action items assigned to the client contact (pattern:
- [ ] {Name}:where Name is NOT "Ivan") — these are waiting on the client - System health has critical failures for their current phase:
- Building or later: no VAPI assistant, no phone numbers, no Responder webhook
- Testing or later: no employee contacts, no transfer destinations
Overdue:
- A Key dates row (Testing or Go-live) has a parseable date before today AND the corresponding progress checkbox (
Testing call completedorGo-live call completed) is still unchecked - Go-live target date mentioned in the status line is before today
Stale data:
last_syncedis missing or more than 3 days before today
Action items:
- Has any open action items (the ad-hoc ones from Step 2) — note count
Step 5 — Render the dashboard
Print the dashboard directly to the user as markdown. Use this structure:
# Client Dashboard — {today's date, e.g. Apr 11, 2026}
**Portfolio:** {total} clients | {live count} live | {in-progress count} in progress | {kickoff count} in kickoff
Then render each non-empty bucket as a section, in this order: Live, Go-Live Ready, Testing, Building / In Progress, Kickoff, Paused.
For Live clients:
## Live ({count})
| Client | ID | Products | Go-live date | Status |
|--------|-----|----------|-------------|--------|
| Sykes Services | 2285 | Responder | 4/10 | Handoff pending |
Status column: note if handed off, or any open items remaining.
For Go-Live Ready clients:
## Go-Live Ready ({count})
| Client | ID | Products | Go-live target | Progress | Flags |
|--------|-----|----------|---------------|----------|-------|
| Quality Pro | 2343 | Responder | Apr 14–16 | 4/7 | 4 action items |
For Testing clients:
## Testing ({count})
| Client | ID | Products | Testing date | Progress | Flags |
|--------|-----|----------|-------------|----------|-------|
For Building / In Progress clients:
## Building ({count})
| Client | ID | Products | Next milestone | Progress | Flags |
|--------|-----|----------|---------------|----------|-------|
Progress column: {checked}/{total} from progress checkboxes.
Next milestone: the first unchecked progress item.
Flags: comma-separated list of flags from Step 4 (e.g. stale, blocked on client).
For Kickoff clients:
## Kickoff ({count})
| Client | ID | Products | Kickoff date | Progress | Flags |
|--------|-----|----------|-------------|----------|-------|
For Paused clients:
## Paused ({count})
| Client | ID | Reason |
|--------|-----|--------|
Skip empty buckets — don't render a section if no clients fall into it.
After the bucket tables, render an attention summary:
---
### Needs attention
List clients that have ANY flag (blocked, overdue, action items, or stale), one bullet per client:
- **{Client}-{ID}**: {comma-separated reasons}
If no clients need attention, print: All clients on track.
Then:
### Stale data (not synced in 3+ days)
- {Client}-{ID}: last synced {date}
If none are stale, omit this section.
Step 6 — Offer follow-up actions
After rendering the dashboard, offer:
- Sync stale clients — "Want me to sync the stale clients?" (runs
sync {client}for each) - Drill into a client — "Want details on any specific client?"
- Prep for next call — "Want me to prep you for your next upcoming call?"
Important rules
- Read-only. Never modify any
context.mdfile. - Show the full board. Don't summarize or truncate — the user wants the complete picture.
- Be concise in flag descriptions. Use short phrases like
stale,blocked on client,overdue: testing,4 action items. - Sort within buckets by urgency: clients with flags first, then alphabetically.
- Handle edge cases gracefully:
- If a client has no System health section (e.g. pre-team clients with TBD ID), skip health-based flags for them.
- If Key dates are blank or
TBD, skip overdue detection for those milestones. - If Products or CRM are blank, show
—in the table cell. - If a date format is ambiguous or unparseable, show it as-is and skip date comparisons for it.
- No auto-sync. Don't trigger the client-auto-sync rule while reading files for the dashboard. Just read and aggregate. (The auto-sync rule normally fires when reading a single client's context.md during focused work — the dashboard is a bulk read for aggregation purposes.)