@forwardimpact/basecamp 1.0.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +1 -1
  2. package/config/scheduler.json +18 -17
  3. package/package.json +3 -3
  4. package/src/basecamp.js +532 -259
  5. package/template/.claude/agents/chief-of-staff.md +103 -0
  6. package/template/.claude/agents/concierge.md +75 -0
  7. package/template/.claude/agents/librarian.md +59 -0
  8. package/template/.claude/agents/postman.md +73 -0
  9. package/template/.claude/agents/recruiter.md +222 -0
  10. package/template/.claude/settings.json +0 -4
  11. package/template/.claude/skills/analyze-cv/SKILL.md +267 -0
  12. package/template/.claude/skills/create-presentations/SKILL.md +2 -2
  13. package/template/.claude/skills/create-presentations/references/slide.css +1 -1
  14. package/template/.claude/skills/create-presentations/scripts/convert-to-pdf.mjs +47 -0
  15. package/template/.claude/skills/draft-emails/SKILL.md +85 -123
  16. package/template/.claude/skills/draft-emails/scripts/scan-emails.mjs +66 -0
  17. package/template/.claude/skills/draft-emails/scripts/send-email.mjs +118 -0
  18. package/template/.claude/skills/extract-entities/SKILL.md +2 -2
  19. package/template/.claude/skills/extract-entities/scripts/state.mjs +130 -0
  20. package/template/.claude/skills/manage-tasks/SKILL.md +242 -0
  21. package/template/.claude/skills/organize-files/SKILL.md +3 -3
  22. package/template/.claude/skills/organize-files/scripts/organize-by-type.mjs +105 -0
  23. package/template/.claude/skills/organize-files/scripts/summarize.mjs +84 -0
  24. package/template/.claude/skills/process-hyprnote/SKILL.md +2 -2
  25. package/template/.claude/skills/send-chat/SKILL.md +170 -0
  26. package/template/.claude/skills/sync-apple-calendar/SKILL.md +5 -5
  27. package/template/.claude/skills/sync-apple-calendar/scripts/sync.mjs +325 -0
  28. package/template/.claude/skills/sync-apple-mail/SKILL.md +6 -6
  29. package/template/.claude/skills/sync-apple-mail/scripts/parse-emlx.mjs +374 -0
  30. package/template/.claude/skills/sync-apple-mail/scripts/sync.mjs +629 -0
  31. package/template/.claude/skills/track-candidates/SKILL.md +375 -0
  32. package/template/.claude/skills/weekly-update/SKILL.md +250 -0
  33. package/template/CLAUDE.md +73 -29
  34. package/template/knowledge/Briefings/.gitkeep +0 -0
  35. package/template/.claude/skills/create-presentations/scripts/convert-to-pdf.js +0 -32
  36. package/template/.claude/skills/draft-emails/scripts/scan-emails.sh +0 -34
  37. package/template/.claude/skills/extract-entities/scripts/state.py +0 -100
  38. package/template/.claude/skills/organize-files/scripts/organize-by-type.sh +0 -42
  39. package/template/.claude/skills/organize-files/scripts/summarize.sh +0 -21
  40. package/template/.claude/skills/sync-apple-calendar/scripts/sync.py +0 -242
  41. package/template/.claude/skills/sync-apple-mail/scripts/parse-emlx.py +0 -104
  42. package/template/.claude/skills/sync-apple-mail/scripts/sync.py +0 -455
@@ -0,0 +1,267 @@
1
+ ---
2
+ name: analyze-cv
3
+ description: >
4
+ Analyze candidate CVs against the engineering career framework using
5
+ fit-pathway as the reference point. Assess skill alignment, identify track
6
+ fit (forward_deployed vs platform), estimate career level, and produce
7
+ structured assessments. Use when the user asks to evaluate a CV, compare a
8
+ candidate to a role, or assess engineering fit.
9
+ ---
10
+
11
+ # Analyze CV
12
+
13
+ Analyze a candidate's CV against the engineering career framework defined in
14
+ `fit-pathway`. Produces a structured assessment: estimated career level, track
15
+ fit, skill alignment, gaps, and a hiring recommendation. Every assessment is
16
+ grounded in the framework — no subjective impressions.
17
+
18
+ ## Trigger
19
+
20
+ Run this skill:
21
+
22
+ - When the user asks to analyze, evaluate, or assess a CV
23
+ - When a new CV is added to `knowledge/Candidates/{Name}/`
24
+ - When the user asks "is this person a fit for {role}?"
25
+ - When comparing a candidate's background against a specific job level and track
26
+
27
+ ## Prerequisites
28
+
29
+ - `fit-pathway` CLI installed (`npx fit-pathway` must work)
30
+ - A CV file (PDF or DOCX) accessible on the filesystem
31
+ - Optionally, a target role specified by the user (discipline + level + track)
32
+
33
+ ## Inputs
34
+
35
+ - CV file path (e.g. `knowledge/Candidates/{Name}/CV.pdf` or a path the user
36
+ provides)
37
+ - Target role (optional): `{discipline} {level} --track={track}`
38
+ - Existing candidate brief (if available):
39
+ `knowledge/Candidates/{Name}/brief.md`
40
+
41
+ ## Outputs
42
+
43
+ - `knowledge/Candidates/{Name}/assessment.md` — structured CV assessment
44
+ - Updated `knowledge/Candidates/{Name}/brief.md` — skills and summary enriched
45
+ from CV analysis
46
+
47
+ ---
48
+
49
+ ## Step 1: Read the CV
50
+
51
+ Read the candidate's CV file. Extract:
52
+
53
+ | Field | What to look for |
54
+ | ---------------------- | ------------------------------------------------------ |
55
+ | **Current role** | Most recent job title |
56
+ | **Years of experience**| Total and per-role tenure |
57
+ | **Technical skills** | Languages, frameworks, platforms, tools mentioned |
58
+ | **Domain experience** | Industries, business domains, customer-facing work |
59
+ | **Education** | Degrees, certifications, relevant courses |
60
+ | **Leadership signals** | Team size, mentoring, cross-team work, architecture |
61
+ | **Scope signals** | Scale of systems, user base, revenue impact |
62
+ | **Communication** | Publications, talks, open source, documentation |
63
+ | **Gender** | Pronouns, gendered titles, first name if unambiguous |
64
+
65
+ ## Step 2: Look Up the Framework Reference
66
+
67
+ Use `fit-pathway` to load the reference data for assessment.
68
+
69
+ ### If a target role is specified
70
+
71
+ ```bash
72
+ # Get the full job definition
73
+ npx fit-pathway job {discipline} {level} --track={track}
74
+
75
+ # Get the skill matrix for comparison
76
+ npx fit-pathway job {discipline} {level} --track={track} --skills
77
+ ```
78
+
79
+ ### If no target role is specified
80
+
81
+ Estimate the most likely discipline and level from the CV, then look it up:
82
+
83
+ ```bash
84
+ # See available disciplines and their tracks
85
+ npx fit-pathway discipline
86
+
87
+ # See available levels
88
+ npx fit-pathway level
89
+
90
+ # Look up the estimated role
91
+ npx fit-pathway job {discipline} {level} --track={track}
92
+ ```
93
+
94
+ **Estimation heuristics:**
95
+
96
+ | CV Signal | Likely Level |
97
+ | -------------------------------------------- | ---------------- |
98
+ | 0-2 years, junior titles, learning signals | J040 (Level I) |
99
+ | 2-5 years, mid-level titles, independent | J060 (Level II) |
100
+ | 5-8 years, senior titles, mentoring signals | J070 (Level III) |
101
+ | 8-12 years, staff/lead titles, area scope | J090 (Staff) |
102
+ | 12+ years, principal titles, org-wide impact | J100 (Principal) |
103
+
104
+ ### Track fit estimation
105
+
106
+ Use `fit-pathway` to compare tracks:
107
+
108
+ ```bash
109
+ npx fit-pathway track forward_deployed
110
+ npx fit-pathway track platform
111
+ ```
112
+
113
+ Map CV evidence to track indicators:
114
+
115
+ | Forward Deployed signals | Platform signals |
116
+ | -------------------------------------------- | ------------------------------------------- |
117
+ | Customer-facing projects | Internal tooling / shared services |
118
+ | Business domain immersion | Infrastructure / platform-as-product |
119
+ | Rapid prototyping, MVPs | Architecture, system design |
120
+ | Data integration, analytics | CI/CD, DevOps, reliability |
121
+ | Stakeholder management | Code quality, technical debt management |
122
+ | Cross-functional work | Scalability, performance engineering |
123
+ | Multiple industries or domain breadth | Deep platform ownership |
124
+
125
+ ## Step 3: Map CV to Framework Skills
126
+
127
+ For each skill in the target job's skill matrix, assess the candidate's likely
128
+ proficiency based on CV evidence:
129
+
130
+ ```bash
131
+ # Get skill detail for nuanced assessment
132
+ npx fit-pathway skill {skill_id}
133
+ ```
134
+
135
+ Use the proficiency definitions from the framework:
136
+
137
+ | Proficiency | CV Evidence |
138
+ | -------------- | -------------------------------------------------------- |
139
+ | `awareness` | Mentioned but no project evidence |
140
+ | `foundational` | Used in projects, basic application |
141
+ | `working` | Primary tool/skill in multiple roles, independent usage |
142
+ | `practitioner` | Led teams using this skill, mentored others, deep work |
143
+ | `expert` | Published, shaped org practice, industry recognition |
144
+
145
+ **Be conservative.** CVs inflate; default one level below what's claimed unless
146
+ there's concrete evidence (metrics, project details, scope indicators).
147
+
148
+ ## Step 4: Assess Behaviour Indicators
149
+
150
+ Check the CV for behaviour signals aligned with the framework:
151
+
152
+ ```bash
153
+ npx fit-pathway behaviour --list
154
+ ```
155
+
156
+ Map CV evidence to behaviours:
157
+
158
+ | Behaviour | CV Evidence |
159
+ | ---------------------------- | -------------------------------------------------- |
160
+ | Own the Outcome | End-to-end ownership, P&L impact, delivery metrics |
161
+ | Think in Systems | Architecture decisions, system-wide reasoning |
162
+ | Communicate with Precision | Technical writing, documentation, talks |
163
+ | Be Polymath Oriented | Cross-domain work, diverse tech stack |
164
+ | Don't Lose Your Curiosity | Side projects, continuous learning, certifications |
165
+
166
+ ## Step 5: Identify Gaps and Strengths
167
+
168
+ Compare the candidate's estimated skill profile against the target job:
169
+
170
+ ```bash
171
+ # If comparing progression potential
172
+ npx fit-pathway progress {discipline} {level} --track={track}
173
+ ```
174
+
175
+ Classify each skill as:
176
+
177
+ - **Strong match** — candidate meets or exceeds the expected proficiency
178
+ - **Adequate** — candidate is within one level of expected proficiency
179
+ - **Gap** — candidate is two or more levels below expected proficiency
180
+ - **Not evidenced** — CV doesn't mention this skill area
181
+
182
+ ## Step 6: Write Assessment
183
+
184
+ Create `knowledge/Candidates/{Name}/assessment.md`:
185
+
186
+ ```markdown
187
+ # CV Assessment — {Full Name}
188
+
189
+ **Assessed against:** {Discipline} {Level} — {Track}
190
+ **Date:** {YYYY-MM-DD}
191
+ **CV source:** [{filename}](./{filename})
192
+
193
+ ## Summary
194
+
195
+ {2-3 sentence summary: overall fit, key strengths, primary concerns}
196
+
197
+ ## Estimated Profile
198
+
199
+ | Dimension | Assessment |
200
+ | ---------------- | ----------------------------------------- |
201
+ | **Level** | {estimated level and confidence} |
202
+ | **Track fit** | {forward_deployed / platform / either} |
203
+ | **Discipline** | {best discipline match} |
204
+ | **Gender** | {Woman / Man / —} |
205
+
206
+ ## Skill Alignment
207
+
208
+ | Skill | Expected | Estimated | Status |
209
+ | --- | --- | --- | --- |
210
+ | {skill} | {framework level} | {CV-based estimate} | {Strong/Adequate/Gap/Not evidenced} |
211
+
212
+ ### Key Strengths
213
+ - {Strength 1 — with CV evidence}
214
+ - {Strength 2 — with CV evidence}
215
+
216
+ ### Key Gaps
217
+ - {Gap 1 — what's missing and why it matters for the role}
218
+ - {Gap 2 — what's missing and why it matters for the role}
219
+
220
+ ## Behaviour Indicators
221
+
222
+ | Behaviour | Expected Maturity | CV Evidence | Signal |
223
+ | --- | --- | --- | --- |
224
+ | {behaviour} | {maturity} | {evidence or "—"} | {Strong/Weak/None} |
225
+
226
+ ## Track Fit Analysis
227
+
228
+ {Paragraph explaining why this candidate fits forward_deployed, platform,
229
+ or could work on either. Reference specific CV evidence.}
230
+
231
+ ## Hiring Recommendation
232
+
233
+ **Recommendation:** {Proceed / Proceed with reservations / Do not proceed}
234
+
235
+ **Rationale:** {3-5 sentences grounding the recommendation in framework data.
236
+ Reference specific skill gaps or strengths and their impact on the role.}
237
+
238
+ **Interview focus areas:**
239
+ - {Area 1 — what to probe in interviews to validate}
240
+ - {Area 2 — what to probe in interviews to validate}
241
+ ```
242
+
243
+ ## Step 7: Enrich Candidate Brief
244
+
245
+ If `knowledge/Candidates/{Name}/brief.md` exists, update it with findings:
246
+
247
+ - Add or update the **Skills** section with framework skill IDs
248
+ - Update **Summary** if the CV provides better context
249
+ - Set the **Gender** field if identifiable from the CV and not already set
250
+ - Add a link to the assessment: `- [CV Assessment](./assessment.md)`
251
+
252
+ **Use precise edits — don't rewrite the entire file.**
253
+
254
+ If no brief exists, note that the `track-candidates` skill should be run first
255
+ to create the candidate profile from email threads.
256
+
257
+ ## Quality Checklist
258
+
259
+ - [ ] Assessment is grounded in `fit-pathway` framework data, not subjective
260
+ opinion
261
+ - [ ] Every skill rating cites specific CV evidence or marks "Not evidenced"
262
+ - [ ] Estimated level is conservative (one below CV claims unless proven)
263
+ - [ ] Track fit analysis references specific skill modifiers from the framework
264
+ - [ ] Gaps are actionable — they suggest interview focus areas
265
+ - [ ] Assessment file uses correct path format and links to CV
266
+ - [ ] Candidate brief updated with skill tags and assessment link
267
+ - [ ] Gender field set in both assessment and brief where identifiable
@@ -41,7 +41,7 @@ Run when the user asks to create a presentation, slide deck, or pitch deck.
41
41
  4. Include the required CSS from [references/slide.css](references/slide.css)
42
42
  5. Run the conversion script:
43
43
 
44
- node scripts/convert-to-pdf.js
44
+ node scripts/convert-to-pdf.mjs
45
45
 
46
46
  6. Tell the user: "Your presentation is ready at ~/Desktop/presentation.pdf"
47
47
 
@@ -49,7 +49,7 @@ Run when the user asks to create a presentation, slide deck, or pitch deck.
49
49
 
50
50
  The conversion script accepts optional arguments:
51
51
 
52
- node scripts/convert-to-pdf.js [input.html] [output.pdf]
52
+ node scripts/convert-to-pdf.mjs [input.html] [output.pdf]
53
53
 
54
54
  Defaults: input = `/tmp/basecamp-presentation.html`, output =
55
55
  `~/Desktop/presentation.pdf`
@@ -1,7 +1,7 @@
1
1
  /* Required CSS for HTML slide decks rendered to PDF via Playwright.
2
2
  *
3
3
  * Include this in the <style> block of /tmp/basecamp-presentation.html.
4
- * See scripts/convert-to-pdf.js for the rendering script.
4
+ * See scripts/convert-to-pdf.mjs for the rendering script.
5
5
  *
6
6
  * PDF rendering rules:
7
7
  * - No layered elements — style content directly, no separate backgrounds
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Convert HTML slides to PDF using Playwright.
4
+ *
5
+ * Renders an HTML file containing slide markup (1280x720px per slide) into a
6
+ * PDF document. Each slide is sized to exactly 1280x720 pixels with background
7
+ * colours and images preserved. Defaults to reading from /tmp and writing to
8
+ * ~/Desktop when no arguments are given.
9
+ *
10
+ * Requires: npm install playwright && npx playwright install chromium
11
+ */
12
+
13
+ import { join } from "node:path";
14
+ import { resolve } from "node:path";
15
+ import { homedir } from "node:os";
16
+
17
+ const HELP = `convert-to-pdf — render HTML slides to PDF via Playwright
18
+
19
+ Usage: node scripts/convert-to-pdf.mjs [input.html] [output.pdf] [-h|--help]
20
+
21
+ Arguments:
22
+ input.html HTML slides file (default: /tmp/basecamp-presentation.html)
23
+ output.pdf Output PDF path (default: ~/Desktop/presentation.pdf)
24
+
25
+ Requires: npm install playwright && npx playwright install chromium`;
26
+
27
+ if (process.argv.includes("-h") || process.argv.includes("--help")) {
28
+ console.log(HELP);
29
+ process.exit(0);
30
+ }
31
+
32
+ const positional = process.argv.slice(2).filter((a) => !a.startsWith("-"));
33
+ const input = positional[0] || "/tmp/basecamp-presentation.html";
34
+ const output = positional[1] || join(homedir(), "Desktop", "presentation.pdf");
35
+
36
+ const { chromium } = await import("playwright");
37
+ const browser = await chromium.launch();
38
+ const page = await browser.newPage();
39
+ await page.goto(`file://${resolve(input)}`, { waitUntil: "networkidle" });
40
+ await page.pdf({
41
+ path: output,
42
+ width: "1280px",
43
+ height: "720px",
44
+ printBackground: true,
45
+ });
46
+ await browser.close();
47
+ console.log(`Done: ${output}`);
@@ -1,57 +1,46 @@
1
1
  ---
2
2
  name: draft-emails
3
- description: Draft email responses using the knowledge base and calendar for full context on every person and conversation. Use when the user asks to draft, reply to, or respond to an email. Looks up people and organizations in the knowledge base before drafting.
3
+ description: Draft and send email responses using the knowledge base and calendar for context. Use when the user asks to draft, reply to, respond to, or send an email.
4
4
  ---
5
5
 
6
6
  # Draft Emails
7
7
 
8
- Help the user draft email responses. Uses the knowledge base and calendar for
9
- full context on every person and conversation. This is an interactive skill —
10
- the user triggers it by asking to draft or reply to emails.
8
+ Draft and send email responses. Uses the knowledge base and calendar for full
9
+ context on every person and conversation. All drafts require explicit user
10
+ approval before sending.
11
11
 
12
12
  ## Trigger
13
13
 
14
- Run when the user asks to draft, reply to, or respond to an email.
14
+ Run when the user asks to draft, reply to, respond to, or send an email.
15
15
 
16
16
  ## Prerequisites
17
17
 
18
18
  - Knowledge base populated (from `extract-entities` skill)
19
- - Synced email data in `~/.cache/fit/basecamp/apple_mail/` or
20
- `~/.cache/fit/basecamp/gmail/`
19
+ - Synced email data in `~/.cache/fit/basecamp/apple_mail/`
21
20
 
22
- ## Inputs
21
+ ## Data Locations
23
22
 
24
- - `knowledge/People/*.md` — person context
25
- - `knowledge/Organizations/*.md` organization context
26
- - `~/.cache/fit/basecamp/apple_mail/*.md` or `~/.cache/fit/basecamp/gmail/*.md`
27
- email threads
28
- - `~/.cache/fit/basecamp/apple_calendar/*.json` — calendar events (for
29
- scheduling)
30
- - `drafts/last_processed` timestamp of last processing run
31
- - `drafts/drafted` — list of drafted email IDs (one per line)
32
- - `drafts/ignored` — list of ignored email IDs (one per line)
33
-
34
- ## Outputs
35
-
36
- - `drafts/{email_id}_draft.md` — draft email files
37
- - `drafts/last_processed` — updated timestamp
38
- - `drafts/drafted` — updated with newly drafted IDs
39
- - `drafts/ignored` — updated with newly ignored IDs
23
+ | Data | Location |
24
+ | --------------- | --------------------------------------------- |
25
+ | People | `knowledge/People/*.md` |
26
+ | Organizations | `knowledge/Organizations/*.md` |
27
+ | Email threads | `~/.cache/fit/basecamp/apple_mail/*.md` |
28
+ | Calendar events | `~/.cache/fit/basecamp/apple_calendar/*.json` |
29
+ | Drafted IDs | `drafts/drafted` (one ID per line) |
30
+ | Ignored IDs | `drafts/ignored` (one ID per line) |
31
+ | Draft files | `drafts/{email_id}_draft.md` |
40
32
 
41
33
  ---
42
34
 
43
- ## Critical: Always Look Up Context First
44
-
45
- **BEFORE drafting any email, you MUST look up the person/organization in the
46
- knowledge base.**
35
+ ## Always Look Up Context First
47
36
 
48
- When the user says "draft an email to Monica" or mentions ANY person:
37
+ **BEFORE drafting any email, look up the person/organization in the knowledge
38
+ base.**
49
39
 
50
- 1. **STOP** — Do not draft anything yet
51
- 2. **SEARCH** — Look them up: `rg -l "Monica" knowledge/`
52
- 3. **READ** — Read their note: `cat "knowledge/People/Monica Smith.md"`
53
- 4. **UNDERSTAND** — Extract role, organization, relationship history, open items
54
- 5. **THEN DRAFT** — Only now draft the email, using this context
40
+ 1. **Search** — `rg -l "Name" knowledge/`
41
+ 2. **Read** — `cat "knowledge/People/Name.md"`
42
+ 3. **Understand** — Extract role, organization, relationship history, open items
43
+ 4. **Draft** — Only now draft the email, using this context
55
44
 
56
45
  ## Key Principles
57
46
 
@@ -59,55 +48,46 @@ When the user says "draft an email to Monica" or mentions ANY person:
59
48
 
60
49
  - If intent is unclear, ASK what the email should be about
61
50
  - If a person has multiple contexts, ASK which one
62
- - **WRONG:** "Here are three variants — pick one"
63
- - **RIGHT:** "I see Akhilesh is involved in Rowboat and banking. Which topic?"
64
51
 
65
- **Be decisive, not generic:**
52
+ **Be decisive:**
66
53
 
67
- - Once you know the context, draft ONE email — no multiple versions
68
- - Every draft must be personalized from knowledge base context
69
- - Infer tone and approach from context
70
-
71
- ## Processing Flow
72
-
73
- ### Step 1: Scan for New Emails
54
+ - Draft ONE email — no multiple versions
55
+ - Personalize from knowledge base context
56
+ - Match the tone of the incoming email
74
57
 
75
- Find unprocessed emails using the scan script:
58
+ **User approves before sending:**
76
59
 
77
- bash scripts/scan-emails.sh
60
+ - Always present the draft for review before sending
61
+ - Never send without explicit approval
78
62
 
79
- This outputs tab-separated `email_id<TAB>subject` for each email not yet in
80
- `drafts/drafted` or `drafts/ignored`.
63
+ ## Workflow
81
64
 
82
- ### Step 2: Parse Email
65
+ ### 1. Scan for New Emails
83
66
 
84
- Each email file is markdown with headers:
67
+ ```bash
68
+ node scripts/scan-emails.mjs
69
+ ```
85
70
 
86
- - `# Subject Line`
87
- - `**Thread ID:** <id>`
88
- - `**Message Count:** <count>`
89
- - `### From: Name <email@example.com>`
90
- - `**Date:** <date>`
71
+ Outputs tab-separated `email_id<TAB>subject` for unprocessed emails.
91
72
 
92
- ### Step 3: Classify Email
73
+ ### 2. Classify
93
74
 
94
- **IGNORE** (append ID to `drafts/ignored`):
75
+ **Ignore** (append ID to `drafts/ignored`):
95
76
 
96
77
  - Newsletters, marketing, automated notifications
97
78
  - Spam or irrelevant cold outreach
98
79
  - Outbound emails from user with no reply
99
80
 
100
- **DRAFT response for:**
81
+ **Draft response for:**
101
82
 
102
83
  - Meeting requests or scheduling
103
84
  - Personal emails from known contacts
104
- - Business inquiries
105
- - Follow-ups on existing conversations
85
+ - Business inquiries or follow-ups
106
86
  - Emails requesting information or action
107
87
 
108
- ### Step 4: Gather Context
88
+ ### 3. Gather Context
109
89
 
110
- **Knowledge Base (REQUIRED for every draft):**
90
+ **Knowledge base** (required for every draft):
111
91
 
112
92
  ```bash
113
93
  rg -l "sender_name" knowledge/
@@ -115,106 +95,88 @@ cat "knowledge/People/Sender Name.md"
115
95
  cat "knowledge/Organizations/Company Name.md"
116
96
  ```
117
97
 
118
- **Calendar (for scheduling emails):**
98
+ **Calendar** (for scheduling emails):
119
99
 
120
100
  ```bash
121
- ls ~/.cache/fit/basecamp/apple_calendar/ ~/.cache/fit/basecamp/google_calendar/ 2>/dev/null
101
+ ls ~/.cache/fit/basecamp/apple_calendar/ 2>/dev/null
122
102
  cat "$HOME/.cache/fit/basecamp/apple_calendar/event123.json"
123
103
  ```
124
104
 
125
- ### Step 5: Create Draft
105
+ ### 4. Write Draft
126
106
 
127
- Write draft to `drafts/{email_id}_draft.md`:
107
+ Save to `drafts/{email_id}_draft.md`:
128
108
 
129
109
  ```markdown
130
110
  # Draft Response
131
111
 
132
- **Original Email ID:** {id}
133
- **Original Subject:** {subject}
134
- **From:** {sender}
135
- **Date Processed:** {date}
136
-
137
- ---
138
-
139
- ## Context Used
140
- - Calendar: {relevant info or N/A}
141
- - Knowledge: {relevant notes or N/A}
112
+ **To:** recipient@example.com
113
+ **CC:** other@example.com
114
+ **Subject:** Re: {subject}
142
115
 
143
116
  ---
144
117
 
145
- ## Draft Response
146
-
147
- Subject: Re: {subject}
148
-
149
118
  {personalized draft body}
150
119
 
151
120
  ---
152
121
 
153
122
  ## Notes
154
- {why this response was crafted this way}
123
+ - **Original Email ID:** {id}
124
+ - **From:** {sender}
125
+ - **Context:** {knowledge base notes used}
155
126
  ```
156
127
 
157
- **Guidelines:**
128
+ Guidelines:
158
129
 
159
- - Draft ONE email — no multiple versions
160
- - Reference past interactions naturally
161
- - Match the tone of the incoming email
162
- - For scheduling: propose specific times from calendar
163
- - If unsure about intent, ask a clarifying question
130
+ - Draft ONE email — reference past interactions naturally
131
+ - For scheduling: propose specific times from calendar availability
132
+ - If unsure about intent, ask a clarifying question instead of drafting
133
+
134
+ ### 5. Present for Review
135
+
136
+ Show the draft to the user. Wait for explicit approval before sending. The user
137
+ may request edits — apply them and present again.
164
138
 
165
- ### Step 6: Update State
139
+ ### 6. Send
166
140
 
167
- After each email, update the state files:
141
+ After the user approves, send via Apple Mail:
168
142
 
169
143
  ```bash
170
- echo "$EMAIL_ID" >> drafts/drafted # or drafts/ignored
171
- date -u '+%Y-%m-%dT%H:%M:%SZ' > drafts/last_processed
144
+ node scripts/send-email.mjs \
145
+ --to "recipient@example.com" \
146
+ --cc "other@example.com" \
147
+ --subject "Re: Subject" \
148
+ --body "Plain text body"
172
149
  ```
173
150
 
174
- ### Step 7: Summary
151
+ Options: `--to` (required), `--cc` (optional), `--bcc` (optional), `--subject`
152
+ (required), `--body` (required, plain text only).
175
153
 
176
- ```
177
- ## Processing Summary
178
- **Emails Scanned:** X
179
- **Drafts Created:** Y
180
- **Ignored:** Z
154
+ Do NOT include an email signature — Apple Mail appends the configured signature
155
+ automatically.
181
156
 
182
- ### Drafts Created:
183
- - {id}: {subject} — {reason}
157
+ ### 7. Update State
184
158
 
185
- ### Ignored:
186
- - {id}: {subject} {reason}
159
+ ```bash
160
+ echo "$EMAIL_ID" >> drafts/drafted # or drafts/ignored
187
161
  ```
188
162
 
189
163
  ## Recruitment & Staffing Emails
190
164
 
191
- **CRITICAL: Candidates must NEVER be copied on internal emails about them.**
192
-
193
- When an email involves recruitment, staffing, or hiring:
165
+ **Candidates must NEVER be copied on internal emails about them.**
194
166
 
195
- 1. **Identify the candidate** Determine who the candidate is from the email
196
- thread and knowledge base (`knowledge/Candidates/`, `knowledge/People/`)
197
- 2. **Strip the candidate from recipients** — The draft must ONLY be addressed to
198
- internal stakeholders (hiring managers, recruiters, interview panel, etc.).
199
- The candidate’s email address must NOT appear in To, CC, or BCC
200
- 3. **Only recruiters email candidates directly** — If the email is a direct
201
- reply TO a candidate (e.g., scheduling an interview, extending an offer),
202
- flag it clearly so only the recruiter sends it. Add a note:
167
+ 1. **Identify the candidate** from the thread and knowledge base
168
+ 2. **Strip the candidate from recipients** — draft to internal stakeholders only
169
+ 3. **Direct-to-candidate emails** — flag with:
203
170
  `⚠️ RECRUITER ONLY — This email goes directly to the candidate.`
204
171
 
205
- **Examples of internal recruitment emails (candidate must NOT be copied):**
206
-
207
- - Interview feedback or debrief
208
- - Candidate evaluation or comparison
209
- - Hiring decision discussions
210
- - Compensation/offer discussions
211
- - Reference check follow-ups between colleagues
172
+ Internal recruitment emails (candidate excluded): interview feedback, candidate
173
+ evaluation, hiring decisions, compensation discussions, reference checks.
212
174
 
213
- **When in doubt:** If an email thread mentions a candidate by name and involves
214
- multiple internal recipients, treat it as internal and exclude the candidate.
175
+ **When in doubt:** If an email thread mentions a candidate and involves multiple
176
+ internal recipients, treat it as internal and exclude the candidate.
215
177
 
216
178
  ## Constraints
217
179
 
218
- - Never actually send emails only create drafts
180
+ - Never send without explicit user approval
219
181
  - Be conservative with ignore — when in doubt, create a draft
220
- - For ambiguous emails, create a draft with a note explaining the ambiguity
182
+ - For ambiguous emails, draft with a note explaining the ambiguity