@forwardimpact/basecamp 2.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.
- package/config/scheduler.json +5 -0
- package/package.json +1 -1
- package/src/basecamp.js +288 -57
- package/template/.claude/agents/chief-of-staff.md +6 -2
- package/template/.claude/agents/concierge.md +2 -3
- package/template/.claude/agents/librarian.md +4 -6
- package/template/.claude/agents/recruiter.md +222 -0
- package/template/.claude/settings.json +0 -4
- package/template/.claude/skills/analyze-cv/SKILL.md +267 -0
- package/template/.claude/skills/create-presentations/SKILL.md +2 -2
- package/template/.claude/skills/create-presentations/references/slide.css +1 -1
- package/template/.claude/skills/create-presentations/scripts/convert-to-pdf.mjs +47 -0
- package/template/.claude/skills/draft-emails/SKILL.md +85 -123
- package/template/.claude/skills/draft-emails/scripts/scan-emails.mjs +66 -0
- package/template/.claude/skills/draft-emails/scripts/send-email.mjs +118 -0
- package/template/.claude/skills/extract-entities/SKILL.md +2 -2
- package/template/.claude/skills/extract-entities/scripts/state.mjs +130 -0
- package/template/.claude/skills/manage-tasks/SKILL.md +242 -0
- package/template/.claude/skills/organize-files/SKILL.md +3 -3
- package/template/.claude/skills/organize-files/scripts/organize-by-type.mjs +105 -0
- package/template/.claude/skills/organize-files/scripts/summarize.mjs +84 -0
- package/template/.claude/skills/process-hyprnote/SKILL.md +2 -2
- package/template/.claude/skills/send-chat/SKILL.md +170 -0
- package/template/.claude/skills/sync-apple-calendar/SKILL.md +5 -5
- package/template/.claude/skills/sync-apple-calendar/scripts/sync.mjs +325 -0
- package/template/.claude/skills/sync-apple-mail/SKILL.md +6 -6
- package/template/.claude/skills/sync-apple-mail/scripts/parse-emlx.mjs +374 -0
- package/template/.claude/skills/sync-apple-mail/scripts/sync.mjs +629 -0
- package/template/.claude/skills/track-candidates/SKILL.md +375 -0
- package/template/.claude/skills/weekly-update/SKILL.md +250 -0
- package/template/CLAUDE.md +63 -40
- package/template/.claude/skills/create-presentations/scripts/convert-to-pdf.js +0 -32
- package/template/.claude/skills/draft-emails/scripts/scan-emails.sh +0 -34
- package/template/.claude/skills/extract-entities/scripts/state.py +0 -100
- package/template/.claude/skills/organize-files/scripts/organize-by-type.sh +0 -42
- package/template/.claude/skills/organize-files/scripts/summarize.sh +0 -21
- package/template/.claude/skills/sync-apple-calendar/scripts/sync.py +0 -242
- package/template/.claude/skills/sync-apple-mail/scripts/parse-emlx.py +0 -104
- package/template/.claude/skills/sync-apple-mail/scripts/sync.py +0 -455
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: track-candidates
|
|
3
|
+
description: Scan synced email threads for recruitment candidates, extract structured profiles, and create/update notes in knowledge/Candidates/. Use when the user asks to track candidates, process recruitment emails, or update the hiring pipeline.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Track Candidates
|
|
7
|
+
|
|
8
|
+
Scan synced email threads from `~/.cache/fit/basecamp/apple_mail/` for
|
|
9
|
+
recruitment candidates. Extract structured candidate profiles and create/update
|
|
10
|
+
notes in `knowledge/Candidates/`. This builds a local, searchable recruitment
|
|
11
|
+
pipeline from scattered email threads.
|
|
12
|
+
|
|
13
|
+
## Trigger
|
|
14
|
+
|
|
15
|
+
Run this skill:
|
|
16
|
+
|
|
17
|
+
- When the user asks to track, process, or update candidates
|
|
18
|
+
- When the user asks about recruitment pipeline status
|
|
19
|
+
- After `sync-apple-mail` has pulled new threads
|
|
20
|
+
|
|
21
|
+
## Prerequisites
|
|
22
|
+
|
|
23
|
+
- Synced email data in `~/.cache/fit/basecamp/apple_mail/` (from
|
|
24
|
+
`sync-apple-mail`)
|
|
25
|
+
- User identity configured in `USER.md`
|
|
26
|
+
|
|
27
|
+
## Inputs
|
|
28
|
+
|
|
29
|
+
- `~/.cache/fit/basecamp/apple_mail/*.md` — synced email threads
|
|
30
|
+
- `~/.cache/fit/basecamp/apple_mail/attachments/` — CV/resume attachments
|
|
31
|
+
- `~/.cache/fit/basecamp/state/graph_processed` — tracks processed files (shared
|
|
32
|
+
with `extract-entities`)
|
|
33
|
+
- `USER.md` — user identity for self-exclusion
|
|
34
|
+
|
|
35
|
+
## Outputs
|
|
36
|
+
|
|
37
|
+
- `knowledge/Candidates/{Full Name}/brief.md` — candidate profile note
|
|
38
|
+
- `knowledge/Candidates/{Full Name}/CV.pdf` — local copy of CV (or `CV.docx`)
|
|
39
|
+
- `~/.cache/fit/basecamp/state/graph_processed` — updated with processed threads
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Before Starting
|
|
44
|
+
|
|
45
|
+
1. Read `USER.md` to get the user's name, email, and domain.
|
|
46
|
+
2. Find new/changed email files to process:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
node .claude/skills/extract-entities/scripts/state.mjs check
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
This outputs one file path per line for all source files that are new or
|
|
53
|
+
changed. Filter this list to only `apple_mail/*.md` files — calendar events are
|
|
54
|
+
not relevant for candidate tracking.
|
|
55
|
+
|
|
56
|
+
**Process in batches of 10 files per run.**
|
|
57
|
+
|
|
58
|
+
## Step 0: Build Candidate Index
|
|
59
|
+
|
|
60
|
+
Scan existing candidate notes to avoid duplicates:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
ls -d knowledge/Candidates/*/
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Each candidate has their own directory at `knowledge/Candidates/{Name}/`
|
|
67
|
+
containing standardized files:
|
|
68
|
+
|
|
69
|
+
- `brief.md` — the candidate profile note
|
|
70
|
+
- `CV.pdf` (or `CV.docx`) — local copy of CV (if available)
|
|
71
|
+
|
|
72
|
+
For each existing note, read the header fields (Name, Role, Source, Status) to
|
|
73
|
+
build a mental index of known candidates.
|
|
74
|
+
|
|
75
|
+
Also scan `knowledge/People/`, `knowledge/Organizations/`, and
|
|
76
|
+
`knowledge/Projects/` to resolve recruiter names, agency orgs, and project
|
|
77
|
+
links.
|
|
78
|
+
|
|
79
|
+
## Step 1: Identify Recruitment Emails
|
|
80
|
+
|
|
81
|
+
For each new/changed email thread, determine if it contains candidate
|
|
82
|
+
information. Look for these signals:
|
|
83
|
+
|
|
84
|
+
### CV/Resume Attachments
|
|
85
|
+
|
|
86
|
+
Check `~/.cache/fit/basecamp/apple_mail/attachments/{thread_id}/` for PDF or
|
|
87
|
+
DOCX files with candidate names in filenames.
|
|
88
|
+
|
|
89
|
+
### Recruiter Sender Domains
|
|
90
|
+
|
|
91
|
+
Emails from known recruitment agency domains. Map sender domains to
|
|
92
|
+
organizations using `knowledge/Organizations/` — look for notes tagged as
|
|
93
|
+
recruitment agencies.
|
|
94
|
+
|
|
95
|
+
If no known agencies exist yet, use sender patterns as hints:
|
|
96
|
+
|
|
97
|
+
- Multiple candidates presented by the same sender
|
|
98
|
+
- Structured profile formatting (rate, availability, skills)
|
|
99
|
+
- Forwarding candidate CVs on behalf of others
|
|
100
|
+
|
|
101
|
+
### Profile Presentation Patterns
|
|
102
|
+
|
|
103
|
+
Look for structured candidate descriptions containing:
|
|
104
|
+
|
|
105
|
+
- "Rate:" or rate/cost information
|
|
106
|
+
- "Availability:" or notice period
|
|
107
|
+
- "English:" or language level
|
|
108
|
+
- "Location:" or country/city
|
|
109
|
+
- Candidate name + role formatting (e.g. "Staff Software Engineer")
|
|
110
|
+
- "years of experience" or "YoE"
|
|
111
|
+
- Skills/tech stack listings
|
|
112
|
+
|
|
113
|
+
### Interview Scheduling
|
|
114
|
+
|
|
115
|
+
- "schedule a call", "schedule an interview"
|
|
116
|
+
- "first interview", "second interview", "technical interview"
|
|
117
|
+
- "interview slot", "available for a call"
|
|
118
|
+
|
|
119
|
+
### Follow-up on Existing Candidates
|
|
120
|
+
|
|
121
|
+
Threads that mention a candidate already in `knowledge/Candidates/` by name —
|
|
122
|
+
these update pipeline status.
|
|
123
|
+
|
|
124
|
+
**Skip threads that don't match any signal.** Not all email threads are
|
|
125
|
+
recruitment-related.
|
|
126
|
+
|
|
127
|
+
## Step 2: Extract Candidate Data
|
|
128
|
+
|
|
129
|
+
For each candidate found in a recruitment email, extract:
|
|
130
|
+
|
|
131
|
+
| Field | Source | Required |
|
|
132
|
+
| ----------------- | ------------------------------------------------- | ------------------- |
|
|
133
|
+
| **Name** | Filename, email body, CV | Yes |
|
|
134
|
+
| **Role** | Email body, CV | Yes |
|
|
135
|
+
| **Rate** | Email body (e.g. "$120/hr", "€80/h") | If available |
|
|
136
|
+
| **Availability** | Email body (e.g. "1 month notice", "immediately") | If available |
|
|
137
|
+
| **English** | Email body (e.g. "B2", "Upper-intermediate") | If available |
|
|
138
|
+
| **Location** | Email body, CV | If available |
|
|
139
|
+
| **Source agency** | Sender domain → Organization | Yes |
|
|
140
|
+
| **Recruiter** | Email sender or CC'd recruiter | Yes |
|
|
141
|
+
| **CV path** | Attachment directory | If available |
|
|
142
|
+
| **Skills** | Email body, CV | If available |
|
|
143
|
+
| **Gender** | Name, pronouns, recruiter context | If identifiable |
|
|
144
|
+
| **Summary** | Email body, CV | Yes — 2-3 sentences |
|
|
145
|
+
|
|
146
|
+
### Determining Gender
|
|
147
|
+
|
|
148
|
+
Record the candidate's gender when identifiable from the email or CV:
|
|
149
|
+
|
|
150
|
+
- Pronouns used by the recruiter ("she is available", "her CV attached")
|
|
151
|
+
- Gendered titles ("Ms.", "Mrs.", "Mr.")
|
|
152
|
+
- First name when culturally unambiguous
|
|
153
|
+
|
|
154
|
+
Record as `Woman`, `Man`, or `—` (unknown). When uncertain, use `—` — never
|
|
155
|
+
guess. This field supports pool diversity tracking; it has **no bearing** on
|
|
156
|
+
hiring decisions or assessment criteria.
|
|
157
|
+
|
|
158
|
+
### Determining Source and Recruiter
|
|
159
|
+
|
|
160
|
+
- Map sender email domain to an organization in `knowledge/Organizations/`.
|
|
161
|
+
- The person who sent or forwarded the candidate profile is the recruiter. Look
|
|
162
|
+
them up in `knowledge/People/` and link with `[[People/Name]]`.
|
|
163
|
+
- If the organization or recruiter doesn't exist yet, create notes for them.
|
|
164
|
+
|
|
165
|
+
### CV Attachment Path
|
|
166
|
+
|
|
167
|
+
Check for attachments:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
ls ~/.cache/fit/basecamp/apple_mail/attachments/{thread_id}/
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Match CV files to candidates by name similarity in the filename. Copy the CV
|
|
174
|
+
into the candidate's directory with a standardized name:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
mkdir -p "knowledge/Candidates/{Full Name}"
|
|
178
|
+
cp "~/.cache/fit/basecamp/apple_mail/attachments/{thread_id}/{filename}" \
|
|
179
|
+
"knowledge/Candidates/{Full Name}/CV.pdf"
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Use `CV.pdf` for PDF files and `CV.docx` for Word documents. The `## CV` link in
|
|
183
|
+
the brief uses a relative path: `./CV.pdf`.
|
|
184
|
+
|
|
185
|
+
## Step 3: Determine Pipeline Status
|
|
186
|
+
|
|
187
|
+
Assign a status based on the email context:
|
|
188
|
+
|
|
189
|
+
| Status | Signal |
|
|
190
|
+
| ------------------ | ----------------------------------------------------- |
|
|
191
|
+
| `new` | CV/profile received, no response yet |
|
|
192
|
+
| `screening` | Under review, questions asked about the candidate |
|
|
193
|
+
| `first-interview` | First interview scheduled or completed |
|
|
194
|
+
| `second-interview` | Second interview scheduled or completed |
|
|
195
|
+
| `offer` | Offer extended |
|
|
196
|
+
| `hired` | Accepted and onboarding |
|
|
197
|
+
| `rejected` | Explicitly passed on ("not a fit", "pass", "decline") |
|
|
198
|
+
| `on-hold` | Paused, waiting on notice period, or deferred |
|
|
199
|
+
|
|
200
|
+
**Default to `new`** if no response signals are found. Read the full thread
|
|
201
|
+
chronologically to determine the most recent status.
|
|
202
|
+
|
|
203
|
+
### Status Advancement Signals
|
|
204
|
+
|
|
205
|
+
Look for these patterns in the hiring manager's replies:
|
|
206
|
+
|
|
207
|
+
- "let's schedule" / "set up an interview" → `first-interview`
|
|
208
|
+
- "second round" / "follow-up interview" → `second-interview`
|
|
209
|
+
- "not what we're looking for" / "pass" → `rejected`
|
|
210
|
+
- "extend an offer" / "make an offer" → `offer`
|
|
211
|
+
- "they've accepted" / "start date" → `hired`
|
|
212
|
+
- "put on hold" / "come back to later" → `on-hold`
|
|
213
|
+
- No response to profile → remains `new`
|
|
214
|
+
|
|
215
|
+
## Step 4: Build Pipeline Timeline
|
|
216
|
+
|
|
217
|
+
Extract a chronological timeline from the thread:
|
|
218
|
+
|
|
219
|
+
```markdown
|
|
220
|
+
## Pipeline
|
|
221
|
+
- **2026-01-29**: Profile shared by {Recruiter} ({Agency})
|
|
222
|
+
- **2026-02-03**: {Recruiter} followed up asking about scheduling
|
|
223
|
+
- **2026-02-10**: {Hiring Manager} requested first interview
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Each entry: `**{date}**: {what happened}` — one line per meaningful event.
|
|
227
|
+
Include who did what. Skip noise (signature blocks, disclaimers, forwarded
|
|
228
|
+
headers).
|
|
229
|
+
|
|
230
|
+
## Step 5: Write Candidate Note
|
|
231
|
+
|
|
232
|
+
### For NEW candidates
|
|
233
|
+
|
|
234
|
+
Create the candidate directory and note:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
mkdir -p "knowledge/Candidates/{Full Name}"
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Then create `knowledge/Candidates/{Full Name}/brief.md`:
|
|
241
|
+
|
|
242
|
+
```markdown
|
|
243
|
+
# {Full Name}
|
|
244
|
+
|
|
245
|
+
## Info
|
|
246
|
+
**Role:** {role title}
|
|
247
|
+
**Rate:** {rate or "—"}
|
|
248
|
+
**Availability:** {availability or "—"}
|
|
249
|
+
**English:** {level or "—"}
|
|
250
|
+
**Location:** {location or "—"}
|
|
251
|
+
**Gender:** {Woman / Man / —}
|
|
252
|
+
**Source:** [[Organizations/{Agency}]] via [[People/{Recruiter Name}]]
|
|
253
|
+
**Status:** {pipeline status}
|
|
254
|
+
**First seen:** {date profile was shared, YYYY-MM-DD}
|
|
255
|
+
**Last activity:** {date of most recent thread activity, YYYY-MM-DD}
|
|
256
|
+
|
|
257
|
+
## Summary
|
|
258
|
+
{2-3 sentences: role, experience level, key strengths}
|
|
259
|
+
|
|
260
|
+
## CV
|
|
261
|
+
- [CV.pdf](./CV.pdf)
|
|
262
|
+
|
|
263
|
+
## Connected to
|
|
264
|
+
- [[Organizations/{Agency}]] — sourced by
|
|
265
|
+
- [[People/{Recruiter}]] — recruiter
|
|
266
|
+
|
|
267
|
+
## Pipeline
|
|
268
|
+
- **{date}**: {event}
|
|
269
|
+
|
|
270
|
+
## Skills
|
|
271
|
+
{comma-separated skill tags}
|
|
272
|
+
|
|
273
|
+
## Notes
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
If a CV attachment exists, **copy it into the candidate directory** before
|
|
277
|
+
writing the note.
|
|
278
|
+
|
|
279
|
+
If no CV attachment exists, omit the `## CV` section entirely.
|
|
280
|
+
|
|
281
|
+
### For EXISTING candidates
|
|
282
|
+
|
|
283
|
+
Read `knowledge/Candidates/{Full Name}/brief.md`, then apply targeted edits:
|
|
284
|
+
|
|
285
|
+
- Update **Status** if it has advanced
|
|
286
|
+
- Update **Last activity** date
|
|
287
|
+
- Add new **Pipeline** entries at the bottom (chronological order)
|
|
288
|
+
- Update **Rate**, **Availability**, or other fields if new information is
|
|
289
|
+
available
|
|
290
|
+
- Add new **Skills** if mentioned
|
|
291
|
+
|
|
292
|
+
**Use precise edits — don't rewrite the entire file.**
|
|
293
|
+
|
|
294
|
+
## Step 5b: Capture Key Insights
|
|
295
|
+
|
|
296
|
+
After writing or updating candidate notes, check whether any **high-signal
|
|
297
|
+
observations** belong in `knowledge/Candidates/Insights.md`. This is a shared
|
|
298
|
+
file for cross-candidate strategic thinking.
|
|
299
|
+
|
|
300
|
+
**Add an insight only when:**
|
|
301
|
+
|
|
302
|
+
- A candidate may be better suited for a **different role** than the one they
|
|
303
|
+
applied for
|
|
304
|
+
- A candidate stands out as a **strong match** for a specific team or leader
|
|
305
|
+
- There's a meaningful **comparison between candidates** (e.g. complementary
|
|
306
|
+
strengths, overlapping profiles)
|
|
307
|
+
- A hiring decision or trade-off needs to be **remembered across sessions**
|
|
308
|
+
|
|
309
|
+
**Do NOT add:**
|
|
310
|
+
|
|
311
|
+
- Per-candidate status updates (that's what `brief.md` is for)
|
|
312
|
+
- Generic strengths/weaknesses already captured in interview notes
|
|
313
|
+
- Anything that only matters within a single candidate's context
|
|
314
|
+
|
|
315
|
+
Format: one bullet per insight under `## Placement Notes`, with
|
|
316
|
+
`[[Candidates/Name/brief|Name]]` links and relevant people/org backlinks.
|
|
317
|
+
|
|
318
|
+
## Step 6: Ensure Bidirectional Links
|
|
319
|
+
|
|
320
|
+
After writing candidate notes, verify links go both ways:
|
|
321
|
+
|
|
322
|
+
| If you add... | Then also add... |
|
|
323
|
+
| ------------------------ | ------------------------------------------- |
|
|
324
|
+
| Candidate → Organization | Organization → Candidate |
|
|
325
|
+
| Candidate → Recruiter | Recruiter → Candidate (in Activity section) |
|
|
326
|
+
| Candidate → Project | Project → Candidate (in People section) |
|
|
327
|
+
|
|
328
|
+
Use absolute paths: `[[Candidates/Name/brief|Name]]`,
|
|
329
|
+
`[[Organizations/Agency]]`, `[[People/Recruiter]]`.
|
|
330
|
+
|
|
331
|
+
**Important:** Only add backlinks to Organization/People/Project notes if they
|
|
332
|
+
don't already reference the candidate. Check before editing.
|
|
333
|
+
|
|
334
|
+
## Step 7: Update Graph State
|
|
335
|
+
|
|
336
|
+
After processing each email thread, mark it as processed:
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
node .claude/skills/extract-entities/scripts/state.mjs update "{file_path}"
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
This uses the same state file as `extract-entities`, so threads processed here
|
|
343
|
+
won't be re-scanned by either skill (unless the file changes).
|
|
344
|
+
|
|
345
|
+
## Step 8: Tag Skills with Framework IDs
|
|
346
|
+
|
|
347
|
+
When a candidate's email or CV mentions technical skills, map them to the
|
|
348
|
+
engineering framework using `fit-pathway`:
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
npx fit-pathway skill --list
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Use framework skill IDs (e.g. `data_integration`, `full_stack_development`,
|
|
355
|
+
`architecture_and_design`) in the **Skills** section of the candidate brief
|
|
356
|
+
instead of free-form tags. This enables consistent cross-candidate comparison.
|
|
357
|
+
|
|
358
|
+
If a candidate has a CV attachment, flag them for the `analyze-cv` skill which
|
|
359
|
+
produces a full framework-aligned assessment.
|
|
360
|
+
|
|
361
|
+
## Quality Checklist
|
|
362
|
+
|
|
363
|
+
- [ ] Scanned all new/changed email threads for recruitment signals
|
|
364
|
+
- [ ] Extracted all candidates found (check attachment directories too)
|
|
365
|
+
- [ ] Each candidate has a complete note with all available fields
|
|
366
|
+
- [ ] CV paths are correct and point to actual files
|
|
367
|
+
- [ ] Pipeline status reflects the latest thread activity
|
|
368
|
+
- [ ] Timeline entries are in chronological order
|
|
369
|
+
- [ ] Used `[[absolute/path]]` links throughout
|
|
370
|
+
- [ ] Bidirectional links are consistent
|
|
371
|
+
- [ ] Graph state updated for all processed threads
|
|
372
|
+
- [ ] No duplicate candidate notes created
|
|
373
|
+
- [ ] Key strategic insights added to `Insights.md` where warranted
|
|
374
|
+
- [ ] Skills tagged using framework skill IDs where possible
|
|
375
|
+
- [ ] Gender field populated where identifiable (Woman / Man / —)
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: weekly-update
|
|
3
|
+
description: Generate or refresh a weekly priorities document. Pulls from task boards, recent activity, and calendar to create a point-in-time snapshot. Use when the user asks to update their weekly, prep for the week, or on a Monday morning schedule.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Weekly Update
|
|
7
|
+
|
|
8
|
+
Generate or refresh a weekly priorities document in
|
|
9
|
+
`knowledge/Weeklies/{Person Name}/`. Each weekly is a point-in-time snapshot —
|
|
10
|
+
created at the start of the week, updated as priorities shift, and closed out
|
|
11
|
+
with a retrospective at end-of-week.
|
|
12
|
+
|
|
13
|
+
## Trigger
|
|
14
|
+
|
|
15
|
+
Run this skill:
|
|
16
|
+
|
|
17
|
+
- When the user asks to update their weekly or prep for the week
|
|
18
|
+
- Monday mornings (scheduled)
|
|
19
|
+
- When the user asks to review someone's weekly
|
|
20
|
+
- End-of-week to fill in accomplishments and retrospective
|
|
21
|
+
|
|
22
|
+
## Prerequisites
|
|
23
|
+
|
|
24
|
+
- `knowledge/Weeklies/` directory exists
|
|
25
|
+
- `knowledge/Tasks/{Person Name}.md` exists (task board — see `manage-tasks`
|
|
26
|
+
skill)
|
|
27
|
+
- Calendar data in `~/.cache/fit/basecamp/apple_calendar/`
|
|
28
|
+
- User identity configured in `USER.md`
|
|
29
|
+
|
|
30
|
+
## Inputs
|
|
31
|
+
|
|
32
|
+
- `knowledge/Tasks/{Person Name}.md` — current task board
|
|
33
|
+
- `knowledge/People/{Person Name}.md` — recent activity, context
|
|
34
|
+
- `~/.cache/fit/basecamp/apple_calendar/*.json` — calendar events for the week
|
|
35
|
+
- Previous weekly document (if exists) — for continuity and carry-forward
|
|
36
|
+
|
|
37
|
+
## Outputs
|
|
38
|
+
|
|
39
|
+
- `knowledge/Weeklies/{Person Name}/{YYYY}-W{WW}.md` — the weekly document
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Weekly Document Format
|
|
44
|
+
|
|
45
|
+
```markdown
|
|
46
|
+
# {YYYY}-W{WW} — {Person Name}
|
|
47
|
+
|
|
48
|
+
> {Focus statement: one sentence summarizing the week's theme}
|
|
49
|
+
|
|
50
|
+
## Priorities
|
|
51
|
+
|
|
52
|
+
- [ ] Priority one — [[Projects/Name]]
|
|
53
|
+
- [ ] Priority two
|
|
54
|
+
- [x] Completed priority
|
|
55
|
+
|
|
56
|
+
## Key Meetings
|
|
57
|
+
|
|
58
|
+
- **Monday**: Meeting title with [[People/Name]] — purpose
|
|
59
|
+
- **Wednesday**: Meeting title — purpose
|
|
60
|
+
|
|
61
|
+
## Blockers
|
|
62
|
+
|
|
63
|
+
- Waiting on X from [[People/Name]]
|
|
64
|
+
|
|
65
|
+
## Accomplishments
|
|
66
|
+
|
|
67
|
+
- Completed X
|
|
68
|
+
- Shipped Y
|
|
69
|
+
|
|
70
|
+
## Retrospective
|
|
71
|
+
|
|
72
|
+
- **Went well:** ...
|
|
73
|
+
- **Didn't go as planned:** ...
|
|
74
|
+
- **Carry forward:** ...
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Key conventions:**
|
|
78
|
+
|
|
79
|
+
- **Week numbers:** ISO 8601 (e.g., `2026-W08`)
|
|
80
|
+
- **Priorities:** Top 3-7 items pulled from the task board
|
|
81
|
+
- **Key Meetings:** Substantive meetings only (skip recurring standups)
|
|
82
|
+
- **Retrospective:** Filled at end-of-week only
|
|
83
|
+
- **All backlinks** use absolute paths: `[[People/Name]]`, `[[Projects/Name]]`,
|
|
84
|
+
`[[Tasks/Name]]`
|
|
85
|
+
|
|
86
|
+
## Before Starting
|
|
87
|
+
|
|
88
|
+
1. Read `USER.md` to identify the user.
|
|
89
|
+
2. Determine the target person (default: current user from `USER.md`).
|
|
90
|
+
3. Calculate the current ISO week number and date range:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Current ISO week
|
|
94
|
+
date +%G-W%V
|
|
95
|
+
|
|
96
|
+
# Monday and Friday of current week (macOS)
|
|
97
|
+
date -v-mon +%Y-%m-%d
|
|
98
|
+
date -v+fri +%Y-%m-%d
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
4. Check if a weekly already exists for this week:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
ls "knowledge/Weeklies/{Person Name}/" 2>/dev/null
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
5. Determine the mode:
|
|
108
|
+
- **No existing weekly:** Create new (start-of-week)
|
|
109
|
+
- **Existing weekly:** Update (mid-week or end-of-week)
|
|
110
|
+
|
|
111
|
+
## Step 1: Gather Context
|
|
112
|
+
|
|
113
|
+
### 1a. Read the task board
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
cat "knowledge/Tasks/{Person Name}.md"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Extract:
|
|
120
|
+
|
|
121
|
+
- `## In Progress` tasks → top priorities (already being worked on)
|
|
122
|
+
- `## Open` tasks with `high` priority or near due dates → candidate priorities
|
|
123
|
+
- `## Blocked` tasks → blockers section
|
|
124
|
+
- `## Recently Done` tasks completed this week → accomplishments
|
|
125
|
+
|
|
126
|
+
### 1b. Read recent activity
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
cat "knowledge/People/{Person Name}.md"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Look at the `## Activity` section for entries from this week. These inform
|
|
133
|
+
accomplishments and provide context for the focus statement.
|
|
134
|
+
|
|
135
|
+
### 1c. Read calendar for the week
|
|
136
|
+
|
|
137
|
+
Find events falling within the Monday–Friday range:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
ls ~/.cache/fit/basecamp/apple_calendar/
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Read each calendar event and filter by date. Extract:
|
|
144
|
+
|
|
145
|
+
- Meeting title
|
|
146
|
+
- Attendees (resolve to `[[People/Name]]` where possible)
|
|
147
|
+
- Time/day
|
|
148
|
+
- Description or agenda (if present)
|
|
149
|
+
|
|
150
|
+
Filter out:
|
|
151
|
+
|
|
152
|
+
- All-day placeholder events with no attendees ("Block", "OOO", "Focus time")
|
|
153
|
+
- Declined events
|
|
154
|
+
- Cancelled events
|
|
155
|
+
|
|
156
|
+
### 1d. Read previous weekly (if exists)
|
|
157
|
+
|
|
158
|
+
Check for last week's document:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
ls "knowledge/Weeklies/{Person Name}/" | sort | tail -1
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
If it exists, read it to:
|
|
165
|
+
|
|
166
|
+
- Carry forward any `[ ]` unchecked priorities
|
|
167
|
+
- Note retrospective items that affect this week
|
|
168
|
+
- Maintain continuity of ongoing themes
|
|
169
|
+
|
|
170
|
+
## Step 2: Generate or Update
|
|
171
|
+
|
|
172
|
+
### Creating a new weekly (start of week)
|
|
173
|
+
|
|
174
|
+
1. **Focus:** Synthesize from highest-priority tasks and key meetings. What's
|
|
175
|
+
the main theme? Write one sentence.
|
|
176
|
+
2. **Priorities:** Pull from task board:
|
|
177
|
+
- All `## In Progress` items first
|
|
178
|
+
- Then `high` priority `## Open` items
|
|
179
|
+
- Then items with due dates this week
|
|
180
|
+
- Carry forward incomplete priorities from last week
|
|
181
|
+
- Cap at 5-7 items. If more exist, prioritize ruthlessly.
|
|
182
|
+
3. **Key Meetings:** From calendar. Format as
|
|
183
|
+
`**{Day}**: {title} with [[People/Name]] — {purpose}`. Look up attendees in
|
|
184
|
+
knowledge base to add context about purpose.
|
|
185
|
+
4. **Blockers:** From task board's `## Blocked` section. Include what's needed
|
|
186
|
+
and from whom.
|
|
187
|
+
5. **Accomplishments:** Leave empty (or pre-fill with anything completed Monday
|
|
188
|
+
morning).
|
|
189
|
+
6. **Retrospective:** Leave empty.
|
|
190
|
+
|
|
191
|
+
### Updating an existing weekly (mid-week)
|
|
192
|
+
|
|
193
|
+
1. Re-read the task board for changes since the weekly was last updated.
|
|
194
|
+
2. Mark completed priorities as `[x]`.
|
|
195
|
+
3. Add new priorities that emerged (append to the list).
|
|
196
|
+
4. Update blockers — remove resolved ones, add new ones.
|
|
197
|
+
5. Add accomplishments as they happen.
|
|
198
|
+
6. Do NOT touch the retrospective mid-week.
|
|
199
|
+
|
|
200
|
+
### End-of-week update
|
|
201
|
+
|
|
202
|
+
1. Final pass on priorities — mark all completed items `[x]`.
|
|
203
|
+
2. Fill in accomplishments from the full week's activity (task board + People
|
|
204
|
+
note activity log).
|
|
205
|
+
3. Write a brief retrospective:
|
|
206
|
+
- What went well?
|
|
207
|
+
- What didn't go as planned?
|
|
208
|
+
- What carries forward to next week?
|
|
209
|
+
4. Note any unchecked priorities — these will carry forward to next week's
|
|
210
|
+
document.
|
|
211
|
+
|
|
212
|
+
## Step 3: Write the Document
|
|
213
|
+
|
|
214
|
+
### New weekly
|
|
215
|
+
|
|
216
|
+
Ensure the person's subdirectory exists:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
mkdir -p "knowledge/Weeklies/{Person Name}"
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Write the full document to: `knowledge/Weeklies/{Person Name}/{YYYY}-W{WW}.md`
|
|
223
|
+
|
|
224
|
+
### Existing weekly
|
|
225
|
+
|
|
226
|
+
Use the Edit tool for targeted updates — mark items complete, add new entries,
|
|
227
|
+
fill sections. Do NOT rewrite the entire file.
|
|
228
|
+
|
|
229
|
+
## Step 4: Cross-reference
|
|
230
|
+
|
|
231
|
+
After writing:
|
|
232
|
+
|
|
233
|
+
- If new priorities were identified that aren't on the task board, add them to
|
|
234
|
+
the task board (the task board is canonical, the weekly references it).
|
|
235
|
+
- If blockers were resolved, update the task board accordingly.
|
|
236
|
+
- The weekly is a **snapshot that references** the task board — the task board
|
|
237
|
+
is the source of truth for task status.
|
|
238
|
+
|
|
239
|
+
## Quality Checklist
|
|
240
|
+
|
|
241
|
+
- [ ] ISO week number and date range are correct
|
|
242
|
+
- [ ] Focus statement reflects the actual week theme (not generic)
|
|
243
|
+
- [ ] Priorities pulled from task board (not invented)
|
|
244
|
+
- [ ] Priorities capped at 5-7 items
|
|
245
|
+
- [ ] Key meetings pulled from calendar (not guessed)
|
|
246
|
+
- [ ] Meeting attendees resolved to `[[People/Name]]` where known
|
|
247
|
+
- [ ] Blockers match task board's blocked items
|
|
248
|
+
- [ ] Previous week's carry-forward items included
|
|
249
|
+
- [ ] All backlinks use absolute paths
|
|
250
|
+
- [ ] Retrospective only filled at end-of-week
|