What it is
Jaewoo's Desk is a local desktop sales-intelligence workspace that produces and accumulates sales strategy through AI collaboration. It is not a chat app — it is a space that turns read-only Salesforce (CRM) data and external news into per-account analysis and strategy, saved as durable assets.
Every figure comes from live CRM (SOQL) or a pre-computed fact. No guessing or fabrication; anything uncertain is marked "needs confirmation."
A team of specialist agents (Sales · Renewal · Tableau · Verifiers) cross-checks each other to produce deep briefings and strategy.
Conversations are ephemeral; outputs (briefings, reports) are permanent — they stack per account and can be revisited.
The target user is a single Tableau Account Executive (focused on manufacturing & auto-parts). The whole book of business — existing customers + whitespace — is managed regardless of whether an opportunity exists.
Architecture
Three layers — data, AI, and presentation — on top of Electron's 3-process model.
Accuracy backbone — double fact-check
In deep mode the orchestrator delegates to specialists, then data-verifier (re-checks figures against CRM source) and audit-verifier (audits logic and evidence) cross-verify every claim. Only what passes verification reaches the user.
Speed design
Every CLI run pays an MCP cold-start (~35s), so interactive turns get absolute priority and background syncs are serialized. Numbers and lists are computed by JS (not the LLM) and injected into the prompt → no re-fetching, no hallucination.
Code structure
Vanilla JS ESM, no framework or bundler. Each file has a clear responsibility.
| File | Responsibility |
|---|---|
| main/main.js | Window lifecycle · IPC handlers · security harness (egress allowlist) · boot |
| main/agent-runtime.js | Claude CLI spawn · fast/deep modes · timeouts · interactive priority |
| main/agents.js | 8 specialist + 2 verifier personas · shared rules (Tableau-only · PII · fiscal quarter) |
| main/queries.js | SOQL builders + CRM response mappers (single source of truth) |
| main/db.js | SQLite schema + accessors |
| main/news.js | News collector (single-host https, no key required) |
| renderer/app.js | All view rendering · agent queue · coverage · Customer 360 · charts (~7,600 lines) |
| renderer/lib/*.js | Data modules · 3D modules (territory/office/renewal) · utils |
| renderer/styles/ | tokens.css (design tokens) · app.css |
| scripts/harness-*.mjs | Static checks (400+ regex assertions) · visual capture |
Data contract (SQLite)
sessions · messages · reports · territory · opty · license · account_detail · agent_cache · external_intel · renewal_fresh · opty_seen · activity_log
Each CRM cache table tracks freshness via synced_at and uses a cache-first → live re-fetch (stale-while-revalidate) pattern.
Invariants
Constraints upheld on every change — the basis of security and accuracy.
- PII No Email/Phone in SOQL. Contacts limited to Name/Title/Department. CRM read-only deep links only.
- No web Agents cannot WebFetch/WebSearch (that was the exfiltration channel). External info comes only from the out-of-band news collector.
- Tableau-only An opty must have BOTH #ECS AND #JW in its name. Renewals and licenses are Tableau products only — no mixing other solutions.
- Concurrency ≤ 2 Triple-parallel was the root cause of past timeouts. Interactive work keeps priority.
- Auth Subscription-based Claude CLI. No metered ANTHROPIC_API_KEY.
Screenshots
Below are real captures of the demo running the actual renderer on synthetic data — not mockups, but the same code the installed app runs.