SuperAPI AI Directory

biweekly-collector

General & other

View repository

Updated 10-16 02:31

About this skill

Biweekly Journal Material Collector

Collect material for writing biweekly journals. Gather material from the past 2-4 weeks from multiple sources such as diary, bookmarks, Douban, Telegram, calendar, reminders, photos, RSS selections, plrom changes, etc., and organize it into a weekly journal template structure for the user to reference when writing the weekly journal by hand.

This skill does not write the weekly journal for the user. The core of a weekly journal is the author's own words and reflections. This only aggregates scattered material to reduce omissions during writing.

Prerequisites

Tool Type Required Installation Method
macOS System Yes This skill only supports macOS
reminders-cli CLI Yes brew install keith/formulae/reminders-cli
icalBuddy CLI Yes brew install ical-buddy
curl CLI Yes Built into macOS
Git CLI Yes Built into the system or run brew install git
PINBOARD_AUTH_TOKEN Environment Variable Yes After logging in to Pinboard, obtain it in Settings → Password

Do not proactively check these tools when loading the skill. When a command fails due to a missing tool, skip the corresponding data source and continue using the remaining available data.

Key Paths

Path Purpose
~/Library/Mobile Documents/iCloud~md~obsidian/Documents/Note/Archives/日记(Daily)/ Daily diary
~/Library/Mobile Documents/iCloud~md~obsidian/Documents/Note/Areas/生活(Life)/周记(Weekly)/ Legacy weekly journal output directory
~/Library/Mobile Documents/iCloud~md~obsidian/Documents/Note/Areas/生活(Life)/月记(Monthly)/ Current monthly journal output directory
~/Library/Mobile Documents/iCloud~md~obsidian/Documents/Note/templates/monthly.md Weekly journal template
RSS summary directory (discovered at runtime) AI-filtered RSS daily summaries
~/code/plrom/README.md plrom "person × community × object" source files, using a separate Git repository

Workflow Overview

┌──────────────────────────────────────────────────────────────┐
│           biweekly-collector 完整流程(~15-20min)              │
└──────────────────────────────────────────────────────────────┘

  ┌──────────────────┐
  │ 用户触发素材收集   │
  └──────┬───────────┘
         │
         ▼
  ┌────────────────────────────────────┐
  │ 1. 确认时间范围 + 创建文件  (~2min) │
  └──────┬─────────────────────────────┘
         │
         ▼
  ┌─────────────────────────────────────────────┐
  │ 2. 并行数据收集(subagent)      (~5-8min)   │
  │    ┌─ 日记条目提取                           │
  │    ├─ Pinboard 书签                          │
  │    ├─ 豆瓣动态 (RSS)                         │
  │    ├─ Telegram 频道 (RSS)                    │
  │    ├─ Apple Calendar 事件                    │
  │    ├─ Apple Reminders 完成项                 │
  │    ├─ RSS 精选摘要                           │
  │    └─ plrom git diff                         │
  └──────┬──────────────────────────────────────┘
         │
         ▼
  ┌────────────────────────────────────┐
  │ 3. 整理素材到模板结构      (~3min)  │
  └──────┬─────────────────────────────┘
         │
         ▼
  ┌────────────────────────────────────┐
  │ 4. 展示 + 用户确认写入     (~3min)  │
  └──────┬─────────────────────────────┘
         │
         ▼
      ┌──────┐
      │ 完成  │
      └──────┘

Step 1: Confirm the period and create the file

Determine the time range

A biweekly journal may cover 2-4 weeks. Ask the user:

Claude: 「这次周记要覆盖什么时间段?」
        建议:3/10 - 3/23(两周)
        或者你可以指定其他范围(最短两周,最长一个月)

Suggest a default range based on the date of the previous entry. Scan Areas/生活(Life)/周记(Weekly)/ and Areas/生活(Life)/月记(Monthly)/, and calculate the interval based on the most recent entry.

Determine the title

The weekly journal filename uses YYYYMM-N-title.md:

  • YYYYMM: the year and month of the period end date.
  • N: which entry of the month it is, starting from 1.
  • title: the short descriptive title chosen by the user.

Ask for the title, or decide after reviewing the material.

Create the skeleton file

Use templates/monthly.md to create the file. The output directory can be 周记(Weekly)/ or 月记(Monthly)/; ask the user, or directly use the path specified by the user:

---
aliases:
tags:
  - 周记
date: {start_date}
modified: {today}
---

> {用户稍后填写的开场白}

## 关于现实生活的记录

> [!info]
> 我所有的周记或许并没有谎言,起码没有主动撒谎的部分。但其中的内容可能都具有某种倾向性,例如隐藏了某些未言明的黑暗成分,或者说是选择性的表达。

<!-- 以下是收集到的素材,请根据这些素材手写正文 -->

### 素材:生活事件与日记摘要

{collected_diary_materials}

### 素材:日历事件

{collected_calendar_events}

### 素材:当前提醒事项(个人相关)

{collected_reminders}

### 素材:plrom 变更

{collected_plrom_diff}

## 👀 还看了什么

### 📚 🎬 📺 作品

| 作品 & 产品名 | 媒介 | 进度 | 打分 | 吐槽 |
| -------- | --- | --- | --- | --- |
{collected_douban_entries}

### 🌐 文章

{collected_articles}

### 素材:RSS 精选回顾

{collected_rss_digests}

### 素材:Telegram 频道分享

{collected_telegram_posts}

## 后记

<!-- 这里是你的个人反思空间 -->

Step 2: Collect data in parallel

Start a subagent in parallel for each data source. The data sources are independent of each other; if a source fails, skip it and continue.

2a: Daily diary

Read Archives/日记(Daily)/ every diary entry within the date range.

Extract content from three sections:

  • ## 1 title Journal: personal events, reflections, and photos.
  • ## 2 Work Log: browse content related to personal interests, skipping formal weekly reports.
  • ## 3 Today I Learn: TIL and thoughts on works.

Output format:

#### 3/10 (周一)
- 在图书馆看了《断舍离》
- 跟朋友 L 约了羽毛球

#### 3/11 (周二)
- 家庭自动化 Dashboard 大整理
- 看完了《迷宫饭》第二季

Preserve the user's original tone; only organize the summary, do not rewrite. Photo references ![[filename]] or ![](url) are kept as-is.

2b: Pinboard bookmarks

Retrieve bookmarks within the date range:

curl -s "https://api.pinboard.in/v1/posts/all?auth_token=$PINBOARD_AUTH_TOKEN&format=json&fromdt={start_date}T00:00:00Z&todt={end_date}T23:59:59Z"

Each bookmark uses the following format:

- [Title](url) - {description if any} `{tags}`

When there are many, group them by week or tag.

2c: Douban activity (RSS)

Retrieve the user's Douban interest activity. First access the direct feed; if that fails, use RSSHub:

# Try direct feed first
curl -s "https://www.douban.com/feed/people/niracler/interests"
# If empty or blocked, use RSSHub
curl -s "https://rsshub.app/douban/people/niracler/interests"

Parse RSS or Atom entries and extract:

  • Title (work name)
  • Type (book, movie, music, or game)
  • Rating (if present)
  • Short review (if present)
  • Date

Organize into work table rows:

| 《作品名》 | 电影 | 100% | 8 | 用户的短评 |

If the Douban feed is unavailable or empty, mark that situation and have the user supplement it manually.

2d: Telegram channel (RSS)

Retrieve the user's Telegram channel RSS:

curl -s "https://tg.niracler.com/rss.xml"

The feed uses standard RSS 2.0, and the body is <content:encoded> HTML. When parsing, note:

  • Title may be missing: use the first line of the <content:encoded> text instead.
  • Hashtags are inside the HTML: they appear as <a href="/search/..."> links, for example #pinboard、 #bilibili、#梦、#暴论、#网易云音乐. Use regular expressions to extract and classify them.
  • pubDate uses GMT (RFC 2822): must strictly filter by date range, keeping only entries whose pubDate falls within the confirmed start and end dates. This is especially important when handling historical ranges such as 3/1 to 3/15, because the feed may contain the latest content outside the range. Dates must be parsed and compared before adding an entry.
  • Content types are not fixed: includes saved articles, video shares, personal thoughts, dream records, music shares, ACG content, technical observations, and life updates.

Use a script to filter strictly:

# Fetch and filter Telegram RSS by date range
curl -s "https://tg.niracler.com/rss.xml" | python3 -c "
import sys, xml.etree.ElementTree as ET
from email.utils import parsedate_to_datetime
from datetime import datetime, timezone

start = datetime({start_year}, {start_month}, {start_day}, tzinfo=timezone.utc)
end = datetime({end_year}, {end_month}, {end_day}, 23, 59, 59, tzinfo=timezone.utc)

tree = ET.parse(sys.stdin)
for item in tree.findall('.//item'):
    pub = item.find('pubDate')
    if pub is not None:
        dt = parsedate_to_datetime(pub.text)
        if start <= dt <= end:
            title = item.find('title')
            link = item.find('link')
            print(f'{dt.strftime(\"%m/%d\")} | {title.text if title is not None and title.text else \"(untitled)\"} | {link.text}')
"

Classify by hashtag as much as possible:

#### 文章分享 (#pinboard)
- [Article title](url) - user's comment

#### 随想 (#暴论)
- 3/15: "some thought..."

#### 其他
- 3/12: 新电脑到了

2e: Apple Calendar events

Use icalBuddy to query events within the date range:

icalBuddy -sd -ic "Personal,Learn&Create" \
  eventsFrom:{start_date} to:{end_date}

Key parameters:

  • -sd: group by date.
  • -ic "Personal,Learn&Create": include only personal calendars, skip Work and Scheduled Reminders; reminders are collected separately by reminders-cli.
  • The output includes the event summary, calendar name, time range, and notes.

The output is already grouped by date. Keep personal events such as gatherings, appointments, travel, and hobbies; skip recurring work meetings.

Use icalBuddy calendars to list available calendar names.

2f: Apple Reminders

Query current reminders to understand what the user is paying attention to and planning:

reminders show-all

This command returns incomplete reminders in all lists, including due dates and notes. For a monthly journal, current reminders are more valuable than completed reminders, as they can reflect life goals, relationship maintenance, recurring habits, follow-up plans, and learning milestones.

Keep only personal lists such as "Life", "Health", "Relationships", "Reading", and "Reminders"; skip purely work items, for example 内部项目:接口切换。

2g: RSS daily digest

In ~/code/*/ , find the repository named rss-agent , then read the AI- filtered daily digest under output/daily/ . If the repository is not found, skip this source and do not try the old nested repository path.

Read the existing YYYY-MM-DD.md. Each summary contains:

  • AI-rated articles with Chinese summaries, scored 0–100.
  • 4 “Core Recommendations” and 3 “Broaden Your Horizons”.
  • For each article: title, source, score, rationale, category, and personal relevance.

Extract articles with a score of at least 70 as the reading highlights for this issue. Deduplicate by URL against Pinboard bookmarks and Telegram channel shares; keep only one entry per identical URL.

2h: plrom Git diff

plrom repository ~/code/plrom/ is a standalone Git repository that records the “people × communities × things” the user follows, and automatically syncs to the blog via GitHub Actions.

Check changes within the period:

cd ~/code/plrom
git log --since="{start_date}" --until="{end_date}" --oneline
# If there are commits, get the diff
FIRST_COMMIT=$(git log --since="{start_date}" --format="%H" --reverse | head -1)
if [ -n "$FIRST_COMMIT" ]; then
  git diff "$FIRST_COMMIT"^..HEAD -- README.md
fi

When changes exist, organize the additions and removals:

  • Newly followed people, such as tech bloggers, manga artists, and UP creators.
  • Newly joined communities.
  • Newly discovered tools, products, or games.
  • Items that have been removed or moved to the abandoned list.

The plrom page contains three sections: “People (tech bloggers, writers, manga artists, directors, UP creators, TG neighbors, podcasters, singers, Taobao shop owners)”, “Organizations or Communities”, and “Things (software, hardware, games)”, used to record changes in interests and discoveries.

Step 3: Organize by Template

After data collection is complete, organize the material into the skeleton file created in Step 1.

Organization Rules

  1. Life Events: Merge diary entries, Calendar events, and completed reminders, and form a narrative skeleton in chronological order. Related events such as consecutive days of travel should be grouped together.

  2. Works Table: Merge works mentioned in Douban entries and diary TILs, deduplicate by title, and preserve the user's original wording as much as possible.

  3. Articles Section: Merge Pinboard bookmarks, selected RSS summaries, and Telegram shares, deduplicating by URL. Prioritize retaining Pinboard entries that include user descriptions, following the format of historical weekly journals:

    - [标题](url) - 用户的一句话评论或 AI 摘要
    
  4. plrom diff: Display new additions as the “New Discoveries” subsection.

  5. Photos: Collect the ![[image]] and ![](url) references in the diary, list them together with context for the user to choose from.

Prohibitions

  • Do not write the body of the weekly journal on the user's behalf; only organize the raw material.
  • Do not filter out “unimportant” events based on agent judgment; importance is decided by the user.
  • When merging events from different dates, their respective dates must be preserved.
  • Do not include formal work weekly report content; that content belongs to weekly-report.

Step 4: Display and Confirm

Display a summary of the collection results:

素材收集完成!以下是各来源的数量统计:

📔 日记条目: 12 天有内容
📌 Pinboard 书签: 8 条
🎬 豆瓣动态: 3 部作品
📱 Telegram 分享: 15 条
📅 日历事件: 6 个
✅ 完成的提醒: 9 项
📰 RSS 精选: 22 篇(去重后 17 篇)
🔄 plrom 变更: +3 新增, -1 移除

已写入文件:Areas/生活(Life)/月记(Monthly)/202603-title.md
你可以在 Obsidian 中打开这个文件,在素材基础上写你的周记。

Ask whether it is necessary to:

  • Adjust the time range and collect again.
  • Delete some sections.
  • Add manual records that were just remembered.

Write the confirmed structured material to a file.

Data Source Fallback

Unavailable Data Source Handling Method
Diary missing for some dates Use the existing dates and mark the gaps
Pinboard token not set Skip and mark “Pinboard data not retrieved”
Douban feed is empty or blocked Try RSSHub; if it is still empty, keep the table for manual filling
Telegram RSS inaccessible Skip and mark
Calendar access denied Use icalBuddy calendars to test, and suggest running tccutil reset Calendar
Missing rss-agent output Skip, and mark "RSS selection not found"
plrom repository not found Skip plrom diff

FAQ

Issue Handling
Douban RSS is empty Douban may block direct RSS; use https://rsshub.app/douban/people/niracler/interests
icalBuddy calendar name mismatch Run icalBuddy calendars to get the exact name, and adjust the -ic filter condition
Too many Pinboard results Add tag filtering or increase the fromdt precision
plrom has no commits in the period This is normal; plrom updates infrequently
Telegram RSS has no date filtering Fetch all entries, then filter the date range by pubDate
File already exists Ask whether to overwrite, append, or use another name
Weekly and monthly output paths differ The user may use 月记(Monthly)/; ask or use the path directly specified by the user