digest
Generate a themed weekly digest from Obsidian ReadItLater bookmarks. Use this skill when the user runs /readitlater-digest:digest or asks to process bookmarks, create a reading digest, summarize saved articles, or consolidate ReadItLater files. Also trigger on cron/loop invocations targeting bookmark processing.
What this skill does
# ReadItLater Weekly Digest
Generate a themed digest from unprocessed Obsidian ReadItLater bookmarks. Designed for automated runs via cron or `/loop`.
## Configuration
Read settings from `.claude/readitlater-digest.local.md`. If it doesn't exist, prompt the user to create one using the template below, then stop.
**Required settings** (YAML frontmatter):
| Field | Default | Description |
|-------|---------|-------------|
| `vault_path` | `/Volumes/Verbatim-Vi560-Media/Development/notes/scratchpad` | Obsidian vault root |
| `inbox_folder` | `ReadItLater` | Folder where ReadItLater saves bookmarks |
| `digest_folder` | `Digests` | Folder for generated digests |
| `archive_folder` | `<inbox_folder>/Archive` | Where processed bookmarks get moved (default: `<inbox_folder>/Archive`) |
Derived paths:
- `db_path` = `<vault_path>/.readitlater-digest.db`
- `inbox_path` = `<vault_path>/<inbox_folder>`
- `digest_path` = `<vault_path>/<digest_folder>`
- `archive_path` = `<vault_path>/<archive_folder>` (default: `<inbox_path>/Archive`)
**If `archive_folder` is not set**, derive it as `<inbox_folder>/Archive`.
## Resolving `bun`
Before running any script, resolve the bun executable once:
```bash
BUN=$(command -v bun 2>/dev/null || echo "$HOME/.bun/bin/bun")
```
Use `$BUN` in place of `bun` throughout all subsequent script invocations. This prevents silent failures in cron/non-interactive shells where `.zshrc` is not sourced.
## Pipeline
Run these steps in order. If `--dry-run` is passed as an argument, stop after Step 2 and report what would be digested.
### Step 0: Pre-check for existing digest
Before starting the pipeline, check whether a digest already exists for the current week:
```bash
sqlite3 "<db_path>" \
"SELECT id, file_path FROM digests WHERE week_start = '<week_start>' AND week_end = '<week_end>'"
```
If a row is returned, **abort immediately** and report: "A digest already exists for <week_start> to <week_end>: <file_path>. Pass --force to regenerate." Do not proceed unless the user explicitly confirms.
### Step 1: Initialize database and validate paths
```bash
$BUN run ${CLAUDE_PLUGIN_ROOT}/scripts/init-db.ts --db-path "<db_path>"
```
This is idempotent — safe to run every time.
Also ensure the archive path exists:
```bash
mkdir -p "<archive_path>"
```
### Step 2: Scan inbox for new bookmarks
```bash
$BUN run ${CLAUDE_PLUGIN_ROOT}/scripts/scan-bookmarks.ts \
--inbox-path "<inbox_path>" \
--db-path "<db_path>"
```
The script outputs JSON with `new`, `duplicates`, `already_tracked`, and `errors` fields.
If there are **zero new + zero unprocessed** bookmarks, report "No unprocessed bookmarks" and stop. Do not generate an empty digest.
If `--dry-run`, print the scan results and stop here.
### Step 3: Read and enrich bookmark content
1. Query the database or use the scan output to identify all `unprocessed` bookmarks.
2. **Batch-read all bookmark files in one pass** — run a single shell command to read all inbox markdown files at once rather than one file per invocation:
```bash
cat "<inbox_path>"/*.md "<inbox_path>"/**/*.md 2>/dev/null
```
Or use the Read tool on each file in a single parallel batch rather than sequentially.
3. **Classify bookmarks before enrichment.** After reading, separate bookmarks into two groups:
- **Resolvable**: file body has ≥50 words of content (excluding frontmatter), or has a fetchable URL that returns content.
- **Unresolvable**: fewer than 50 words of body content AND the URL is a short-link, mobile redirect, or returns no extractable content (e.g., TikTok, Reddit mobile, Google share links). Mark these for the appendix (see Step 4).
4. **Content enrichment** — for resolvable bookmarks that are thin (<200 words), enrich using this sequence:
a. **Check qurl first**: `qurl get "<url>"` — if exit 0, use the returned content directly and skip `WebFetch`.
b. **Fetch if not cached**: fetch with `WebFetch`. If the fetch fails or returns little content, treat as unresolvable.
c. **Index after fetch**: `echo "<fetched_content>" | qurl add "<url>" --source readitlater --tags "<inferred_topic>"`.
Run fetches and qurl checks concurrently where possible.
5. Extract **substantially more content** per bookmark than a bare summary — capture key arguments, notable quotes, specific data points, and the author's main thesis. The goal is enough material to write informed editorial commentary, not just a blurb.
### Step 4: Cluster by theme and find the narrative
1. Analyze all **resolvable** bookmarks together and identify **3-7 natural themes**:
- Themes should be specific and descriptive (e.g., "Agentic Engineering Patterns & Multi-Agent Architectures" not "AI")
- A bookmark can appear in multiple themes if it genuinely spans topics
- Group stragglers under a casual catch-all section (e.g., "Quick Saves", "Miscellaneous") at the end
2. **Unresolvable bookmarks** are collected separately and appended as an "Unresolvable Links" section (see template below). Do not attempt to write editorial commentary for these — a single sentence noting the link is sufficient.
3. **Find the throughline.** Identify the overarching narrative that connects the week's themes — a single sentence or idea that ties the reading together. This becomes the digest title and opening paragraph.
### Step 5: Generate the digest note
Determine week boundaries (default: Monday-Sunday of the current week, or use `--week YYYY-MM-DD` to specify the Monday).
**Week label accuracy**: The `week` frontmatter field reflects the calendar week boundaries used to select bookmarks (e.g., `2026-03-30 to 2026-04-05`). Additionally, include a `date_range` field showing the actual span of bookmark `date_saved` values (e.g., `2026-03-24 to 2026-03-29`). If bookmarks span multiple weeks, use the most recent Monday-Sunday as `week` but always set `date_range` to the actual bookmark dates.
Write the digest to: `<digest_path>/Digest — <week_start> to <week_end>.md`
**Template:**
```markdown
---
type: digest
date_generated: <ISO date>
week: <week_start> to <week_end>
date_range: <earliest_bookmark_date> to <latest_bookmark_date>
bookmark_count: <count>
themes:
- <theme 1>
- <theme 2>
---
# <Creative Title>
<Opening paragraph: 2-4 sentences establishing the throughline — what connected this week's reading, why it matters, and the editorial lens.>
## <Theme Name — evocative, not just descriptive>
<Editorial prose weaving multiple bookmarks into a narrative. Link to sources inline using [display text](url) markdown links. Discuss, compare, and comment on the articles rather than listing them. Each paragraph should read like a newsletter essay — opinionated, specific, and useful. Mention what's interesting, what's surprising, what connects to other reads. If a bookmark's content was thin or inaccessible, acknowledge it naturally in the prose (e.g., "though the full content wasn't extractable from the bookmark").>
<Continue with more paragraphs as needed for the theme. Multiple bookmarks per paragraph when they relate.>
## <Next Theme>
...
## <Catch-all section: "Quick Saves" or similar>
<Brief mentions of bookmarks that don't warrant full commentary but are worth noting. One or two sentences each, still in prose form.>
## Unresolvable Links
<Include this section only if there were unresolvable bookmarks. List each as a bullet with title and URL. No editorial commentary — just the link.>
- [<title>](<url>)
- ...
---
<Closing reflection: 1-2 sentences reflecting on the week's reading as a whole — a parting thought, not a summary.>
*Generated by ReadItLater Digest*
```
**Writing style rules:**
- **Editorial voice**: Write as a thoughtful reader sharing what they found interesting, not a summarization engine. Use first person sparingly ("my favorite", "what strikes me").
- **Inline links**: Use `[display text](url)` markdown links woven into sentences — never structured link blocks.
- **No per-bookmaRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.