AgentStack
SKILL verified MIT Self-run

Biweekly Collector

skill-niracler-skill-biweekly-collector · by niracler

>-

No reviews yet
0 installs
10 views
0.0% view→install

Install

$ agentstack add skill-niracler-skill-biweekly-collector

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Biweekly Collector? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Biweekly Collector

收集双周记写作素材。从日记、书签、豆瓣、Telegram、日历、提醒事项、照片、RSS 精选、plrom 变更等 多个来源抓取过去 2-4 周的素材,整理成周记模板结构,供用户手写周记时参考。

这个 skill 不代写周记 — 周记的灵魂在于你自己的文字和反思。它只负责把散落各处的碎片聚合起来, 让你写的时候不遗漏重要的事。

Prerequisites

| Tool | Type | Required | Install | |------|------|----------|---------| | macOS | system | Yes | This skill requires macOS | | reminders-cli | cli | Yes | brew install keith/formulae/reminders-cli | | icalBuddy | cli | Yes | brew install ical-buddy | | curl | cli | Yes | Built-in on macOS | | git | cli | Yes | Built-in or brew install git | | PINBOARD_AUTH_TOKEN | env var | Yes | See pinboard-manager skill for setup |

> Do NOT proactively verify these tools on skill load. If a command fails due to a missing > tool, skip that data source and continue with what's available.

Key Paths

| Path | Purpose | |------|---------| | ~/Library/Mobile Documents/iCloud~md~obsidian/Documents/Note/Archives/日记(Daily)/ | Daily diary entries | | ~/Library/Mobile Documents/iCloud~md~obsidian/Documents/Note/Areas/生活(Life)/周记(Weekly)/ | Output location for 周记 (legacy) | | ~/Library/Mobile Documents/iCloud~md~obsidian/Documents/Note/Areas/生活(Life)/月记(Monthly)/ | Output location for 月记 (current) | | ~/Library/Mobile Documents/iCloud~md~obsidian/Documents/Note/templates/monthly.md | 周记 template | | ~/code/ai-dev/repos/rss-agent/output/daily/ | AI-curated RSS daily digests | | ~/code/nini-dev/repos/plrom/README.md | plrom source file (人 X 社区 X 物), has its own git repo |

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 Period and Create File

Determine Time Range

The biweekly diary covers a flexible period (2-4 weeks). Ask the user:

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

Suggest a default based on the last entry's date. Scan both Areas/生活(Life)/周记(Weekly)/ and Areas/生活(Life)/月记(Monthly)/ for the most recent entry to calculate the gap.

Determine Title

The 周记 naming convention is YYYYMM-N-title.md:

  • YYYYMM: year-month of the period's end date
  • N: the nth entry of that month (1, 2, 3...)
  • title: a short descriptive title chosen by the user

Ask the user for a title, or offer to decide later after seeing the materials.

Create Skeleton File

Create the file using the template from templates/monthly.md. The output directory can be either 周记(Weekly)/ or 月记(Monthly)/ — ask the user or accept if they specify a path directly:

---
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: Parallel Data Collection

Launch subagents for each data source concurrently. Each source is independent — if one fails, skip it and continue.

2a. Daily Diary Entries

Read each daily note within the date range from Archives/日记(Daily)/.

Extract content from three sections:

  • ## 1 title Journal → personal events, reflections, photos
  • ## 2 Work Log → skim for personal-interest items (skip formal 周报 content)
  • ## 3 Today I Learn → TIL entries, media impressions

Output format:

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

#### 3/11 (周二)
- Home Assistant Dashboard 大整理
- 看完了《迷宫饭》第二季

Preserve the user's original voice — summarize but don't rewrite. Include photo references (![[filename]] or ``) as-is.

2b. Pinboard Bookmarks

Fetch bookmarks from 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"

Format each bookmark as:

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

Group by week or by tag category if there are many.

2c. Douban Activity (RSS)

Fetch the user's Douban interest feed. Try direct feed first, fall back to 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 the RSS/Atom entries. Extract:

  • Title (作品名)
  • Category/type (书/电影/音乐/游戏)
  • Rating (if marked)
  • Short comment (if any)
  • Date

Format into the 作品 table rows:

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

If the Douban feed is unavailable or empty, note this and the user can fill manually.

2d. Telegram Channel (RSS)

Fetch the user's Telegram channel RSS:

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

The feed is standard RSS 2.0 with `` HTML bodies. Important parsing notes:

  • Title may be absent — fall back to extracting first line of `` text
  • Hashtags are inline in HTML as ` links (e.g., #pinboard, #bilibili`,

#梦, #暴论, #网易云音乐). Extract via regex for categorization.

  • pubDate is in GMT (RFC 2822). Strictly filter by date range — only include items

whose pubDate falls within the confirmed start/end dates. This is critical when the user specifies a historical range (e.g., 3/1-3/15) because the RSS feed contains recent posts that may be outside the range. Parse the date and compare before including.

  • Content types vary: bookmarked articles, video shares, personal thoughts, dream journal,

music shares, ACG content, tech observations, 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 = 70) as "this period's reading highlights".
Deduplicate against Pinboard bookmarks (same URL = already captured via Pinboard).
Also deduplicate against Telegram channel shares (same URL).

### 2h. plrom Git Diff

The plrom repo (`~/code/nini-dev/repos/plrom/`) is a standalone git repo that tracks
"人 X 社区 X 物" — the user's curated list of people, communities, and things they follow.
It auto-syncs to the blog via GitHub Actions.

Check what changed during the period:

```bash
cd ~/code/nini-dev/repos/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

If there are changes, summarize what was added/removed:

  • New people followed (技术博主, 漫画家, UP 主, etc.)
  • New communities joined
  • New tools/products/games discovered
  • Items removed or moved to 弃坑列表

The plrom page has sections: 人 (技术博主/作家/漫画家/导演/UP主/TG芳邻/播客/歌手/淘宝店主), 组织或社区, 物 (软件/硬件/游戏). This captures the user's evolving interests and discoveries.

Step 3: Organize into Template

After all data is collected, organize the materials into the skeleton file created in Step 1.

Organization Rules

  1. 生活事件 — merge diary entries + calendar events + completed reminders into a

chronological narrative scaffold. Group related events (e.g., consecutive days of a trip).

  1. 作品 table — merge Douban entries with any media mentioned in diary TIL sections.

Deduplicate by title. Keep the user's original comments when available.

  1. 文章 section — merge Pinboard bookmarks + RSS digest highlights + Telegram shares.

Deduplicate by URL. Prefer Pinboard entries (they have the user's own description). Format like historical 周记 entries: ```markdown

  • [Title](url) - one-line comment from user or AI summary

```

  1. plrom diff — present as a "discoveries" subsection showing what's new.
  1. Photos — collect all ![[image]] and `` references from diary entries.

List them in context so the user can select which to include.

What NOT to Do

  • Do NOT write the actual 周记 prose — only organize raw materials
  • Do NOT filter out events you think are unimportant — the user decides what matters
  • Do NOT merge events that happened on different days without noting both dates
  • Do NOT include formal work 周报 content (that's the weekly-report skill's domain)

Step 4: Present and Confirm

Show the user a summary of what was collected:

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

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

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

Ask if the user wants to:

  • Adjust the time range and re-collect
  • Remove certain sections
  • Add any manual notes they remembered

Write the final organized materials to the file.

Data Source Degradation

| Source unavailable | Behavior | |---|---| | Daily notes missing for some days | Use available days, note gaps | | Pinboard token not set | Skip, note "Pinboard 数据未获取" | | Douban feed empty or blocked | Try RSSHub fallback: https://rsshub.app/douban/people/niracler/interests; if still empty, leave table for manual fill | | Telegram RSS unreachable | Skip, note it | | Calendar access denied | Run icalBuddy calendars to test access; if denied, suggest ! tccutil reset Calendar | | rss-agent output missing | Skip, note "RSS 精选未找到" | | plrom repo not found | Skip plrom diff |

Common Issues

| Issue | Fix | |-------|-----| | Douban RSS returns empty | Douban may block direct RSS; try via RSSHub: https://rsshub.app/douban/people/niracler/interests | | icalBuddy calendar name mismatch | Run icalBuddy calendars to list exact names; adjust -ic filter accordingly | | Too many Pinboard results | Add tag filter or increase fromdt precision | | plrom has no commits in range | Normal — plrom updates are infrequent | | Telegram RSS has no date filter | Fetch all entries, filter by pubDate in the date range | | File already exists | Ask user: overwrite / append / use different name | | Output path: 周记 vs 月记 | User may use 月记(Monthly)/ instead of 周记(Weekly)/. Ask or accept if user specifies a path directly |

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.