Daily ML/AI paper + blog digest. Cron → fetch arXiv & RSS → Claude Code categorizes and writes notes → Slack digest.
git clone https://github.com/layer6ai-labs/paper-ingest.git
cd paper-ingest
./setup.sh # installs deps, captures your Slack webhook, prints a crontab lineThen do one manual bash scripts/run_ingest.sh before adding the printed cron line.
The detailed manual walkthrough (and per-step verification) is in Quickstart below.
Syncthing / Obsidian users: if you clone this into a Syncthing-synced vault, add
path/to/paper-ingest/.gitto the vault's.stignoreso Syncthing never replicates git internals (that can corrupt the repo). The generatednotes/are gitignored and stay local.
-
Install Python deps (only third-party dep is
feedparserandpyyaml):uv pip install --user feedparser pyyaml # or: pipx install feedparser pyyaml / pip install --user feedparser pyyaml -
Slack webhook:
echo "https://hooks.slack.com/services/XXX/YYY/ZZZ" > ~/.config/paper-ingest/slack_webhook chmod 600 ~/.config/paper-ingest/slack_webhook
-
Curate
config/feeds.yaml— the seed list is a starting point. Replace<handle>placeholders, comment out anything you don't want. -
Verify pieces independently before letting cron run it:
# A. Fetchers python3 scripts/fetch_arxiv.py python3 scripts/fetch_feeds.py ls -lh ~/.cache/paper-ingest/ # B. Claude step interactively (no -p) the first time so you can watch it claude "$(cat prompts/ingest.md)" # inspect: notes/$(date +%Y-%m-%d)/_summary.md and a sample per-paper note # C. Slack post in isolation python3 scripts/post_slack.py # D. Full wrapper end-to-end bash scripts/run_ingest.sh # E. Cron sanity — run with cron's environment to catch PATH issues env -i HOME=$HOME PATH=/home/barry/miniconda3/bin:/home/barry/.local/bin:/usr/local/bin:/usr/bin:/bin \ /bin/bash -lc '$HOME/Documents/Obsidian/projects/paper-ingest/scripts/run_ingest.sh'
-
Install cron (after a successful manual run). The PATH must include both miniconda (for
python3+feedparser/pyyaml) and~/.local/bin(forclaude):PATH=/home/barry/miniconda3/bin:/home/barry/.local/bin:/usr/local/bin:/usr/bin:/bin 30 6 * * * /bin/bash -lc '$HOME/Documents/Obsidian/projects/paper-ingest/scripts/run_ingest.sh' >> $HOME/.cache/paper-ingest/cron.log 2>&1
Verify the binaries are reachable under cron's environment with the dry-run command at the bottom of "Verify pieces independently". If
claudeorpython3aren't found, either fix PATH in the crontab or hardcode absolute paths insiderun_ingest.sh.
projects/paper-ingest/
├── scripts/ fetch_arxiv.py, fetch_feeds.py, post_slack.py, run_ingest.sh
├── prompts/ ingest.md — the headless Claude prompt
├── config/ feeds.yaml, arxiv_categories.yaml
└── notes/ YYYY-MM-DD/<category>/<slug>.md (generated)
~/.cache/paper-ingest/ arxiv.json, feeds.json, seen_*.json, slack_summary.txt, run-*.log
~/.config/paper-ingest/ slack_webhook (mode 600)
- Persistent dedup:
seen_arxiv.jsonandseen_feeds.jsonlive in~/.cache/paper-ingest/. Deleting them re-ingests everything within the 36h freshness window. - RSSHub flakiness: public
rsshub.appinstances rate-limit aggressively. If a URL stops working, swap it; the fetcher already tolerates per-feed failures. For long-term Twitter/X reliability, self-host RSSHub on a small VPS. - First-run advice: invoke
claudeinteractively (no-p) on the first run to watch what it writes. Once happy, switch torun_ingest.sh. - Watch the first 3 days before walking away — RSS edge cases (republished GUIDs, redirects, charset issues) only surface across runs.
| Symptom | Likely cause |
|---|---|
arxiv.json empty but no error |
All papers older than 36h cutoff — fine on quiet days. |
| Cron run silent, no notes written | claude not on cron's PATH; hardcode absolute path in run_ingest.sh. |
| Slack post fails | Check ~/.config/paper-ingest/slack_webhook is readable and the URL is current. |
Notes have category unknown/ |
Prompt couldn't classify — usually low-signal items; review and tighten prompt categories. |
feedparser ImportError |
Reinstall deps for the Python interpreter cron uses. head -1 scripts/fetch_arxiv.py shows the shebang. |