No description
Find a file
Charles Kelsoe aebec603c4 Feature: per-feed deterministic cleanup (link-host + trim rules)
Strip promotional clutter from note bodies by LINK TARGET and structure, never by
body wording (so rules survive rewording). Per-feed link-host list (e.g.
buymeacoffee.com, substack.com/app, /subscribe) removes short CTA/footer blocks;
an optional trim-after-last-horizontal-rule drops a trailing footer region. Long
real paragraphs that merely cite such a link are preserved. Rules apply at import
and via a new 'Clean up imported notes' command that re-cleans existing notes with
frontmatter untouched. cleanup.ts is pure + idempotent. +32 tests (323 total).
2026-06-14 17:34:05 -04:00
.github Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
__tests__ Feature: per-feed deterministic cleanup (link-host + trim rules) 2026-06-14 17:34:05 -04:00
scripts Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
.editorconfig Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
.gitignore Wave A: leaf modules (logger, pacer, paywall, dismiss, index, note-writer) 2026-06-14 14:11:12 -04:00
.npmrc Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
add-feed-modal.ts Fix add-feed Save button doing nothing 2026-06-14 16:16:47 -04:00
CHANGELOG.md Release 0.3.0: Substack archive backfill 2026-06-14 17:19:56 -04:00
cleanup.ts Feature: per-feed deterministic cleanup (link-host + trim rules) 2026-06-14 17:34:05 -04:00
CONTRIBUTING.md Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
debug-logger.ts Wave A: leaf modules (logger, pacer, paywall, dismiss, index, note-writer) 2026-06-14 14:11:12 -04:00
dismiss-store.ts Wave A: leaf modules (logger, pacer, paywall, dismiss, index, note-writer) 2026-06-14 14:11:12 -04:00
duplicate-prompt-modal.ts Phase 5: apply adversarial-review fixes 2026-06-14 15:26:45 -04:00
esbuild.config.mjs Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
eslint.config.mts Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
feed-picker-modal.ts Phase 5: apply adversarial-review fixes 2026-06-14 15:26:45 -04:00
feed-resolver.ts Phase 5: apply adversarial-review fixes 2026-06-14 15:26:45 -04:00
feed-source.ts Feature: Substack archive backfill (load older than the RSS window) 2026-06-14 17:18:56 -04:00
feed-xml.ts Wave B: XML parser, HTML-to-Markdown converter, feed resolver 2026-06-14 14:32:39 -04:00
fetch-pacer.ts Wave A: leaf modules (logger, pacer, paywall, dismiss, index, note-writer) 2026-06-14 14:11:12 -04:00
folder-suggest.ts Wave D: import services and UI shell 2026-06-14 15:01:59 -04:00
html-converter.ts Converter: strip Substack app-install / subscribe / CTA clutter 2026-06-14 16:27:53 -04:00
image-downloader.ts Phase 5: apply adversarial-review fixes 2026-06-14 15:26:45 -04:00
import-modal.ts Feature: Substack archive backfill (load older than the RSS window) 2026-06-14 17:18:56 -04:00
import-runner.ts Feature: per-feed deterministic cleanup (link-host + trim rules) 2026-06-14 17:34:05 -04:00
jest.config.cjs Add jest test harness: obsidian mock + moduleNameMapper wiring 2026-06-14 14:03:11 -04:00
LICENSE Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
main.ts Feature: per-feed deterministic cleanup (link-host + trim rules) 2026-06-14 17:34:05 -04:00
manifest.json Release 0.3.0: Substack archive backfill 2026-06-14 17:19:56 -04:00
media-downloader.ts Feature: per-feed media (audio/video) download 2026-06-14 16:59:44 -04:00
note-writer.ts Feature: per-feed media (audio/video) download 2026-06-14 16:59:44 -04:00
package-lock.json Release 0.3.0: Substack archive backfill 2026-06-14 17:19:56 -04:00
package.json Release 0.3.0: Substack archive backfill 2026-06-14 17:19:56 -04:00
paywall-detector.ts Wave A: leaf modules (logger, pacer, paywall, dismiss, index, note-writer) 2026-06-14 14:11:12 -04:00
PRIVACY.md Docs: MVP-accurate README, PRIVACY, SECURITY 2026-06-14 14:40:39 -04:00
README.md Docs: MVP-accurate README, PRIVACY, SECURITY 2026-06-14 14:40:39 -04:00
SECURITY.md Docs: MVP-accurate README, PRIVACY, SECURITY 2026-06-14 14:40:39 -04:00
settings-tab.ts Feature: per-feed deterministic cleanup (link-host + trim rules) 2026-06-14 17:34:05 -04:00
settings.ts Feature: per-feed deterministic cleanup (link-host + trim rules) 2026-06-14 17:34:05 -04:00
source-common.ts Feature: Substack archive backfill (load older than the RSS window) 2026-06-14 17:18:56 -04:00
source-generic.ts Feature: Substack archive backfill (load older than the RSS window) 2026-06-14 17:18:56 -04:00
source-substack.ts Feature: Substack archive backfill (load older than the RSS window) 2026-06-14 17:18:56 -04:00
styles.css Feature: Substack archive backfill (load older than the RSS window) 2026-06-14 17:18:56 -04:00
tsconfig.json Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
turndown-plugin-gfm.d.ts Wave B: XML parser, HTML-to-Markdown converter, feed resolver 2026-06-14 14:32:39 -04:00
types.d.ts Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
ui-helpers.ts Wave D: import services and UI shell 2026-06-14 15:01:59 -04:00
vault-index.ts Wave A: leaf modules (logger, pacer, paywall, dismiss, index, note-writer) 2026-06-14 14:11:12 -04:00
version-bump.mjs Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
versions.json Release 0.3.0: Substack archive backfill 2026-06-14 17:19:56 -04:00

RSS Importer

CI Release GitHub Downloads GitHub Stars Obsidian License Latest Release

Import articles and podcasts from RSS, Atom, and Substack feeds into your vault as Markdown notes, organized by source feed and deduplicated by note identity.

It is an importer, not a reader. It writes notes you own and then gets out of the way.

Features

  • Multiple sources. Add any RSS, Atom, or podcast feed. Substack publications are first-class: paste a @handle, a subdomain, a custom domain, or a post URL and the plugin resolves it to the right feed.
  • One folder per feed. Each feed imports into its own destination folder. Reorganize the notes into subfolders however you like; the plugin still finds them.
  • Never re-imports. Each note carries a stable identity in its frontmatter. Moving or renaming a note does not cause a duplicate on the next import.
  • Three-state item list. Every item shows as imported, dismissed, or available. Dismiss items you are not interested in; dismissing is reversible.
  • Clean Markdown. Article HTML is converted to tidy Markdown (headings, lists, tables, code blocks, captions), with subscribe and share widgets stripped.
  • Images your way. Link to the original image URLs, or download images into your vault.
  • Podcasts. Podcast items import as notes from the show notes with a link to the episode audio.

Usage

  1. Open Settings → RSS Importer and add a feed under Feeds. Paste a feed URL or a Substack handle, click Resolve to preview it, pick a destination folder, and save.
  2. Run the Import command (or the ribbon icon) to open the import window.
  3. Select the items you want and import them. A summary reports what was created, skipped, or failed.

Installation

  1. Open Obsidian settings.
  2. Navigate to Community plugins.
  3. Click Browse.
  4. Search for RSS Importer.
  5. Click Install, then Enable.

Manual installation

  1. Download main.js, manifest.json, and styles.css from the latest release.
  2. Create a folder named rss-importer in your vault's .obsidian/plugins/ directory.
  3. Copy the downloaded files into this folder.
  4. Reload Obsidian.
  5. Enable RSS Importer in Settings → Community plugins.

BRAT (optional, for pre-release testing)

BRAT lets power users install pre-release builds before they reach the marketplace.

  1. Install the BRAT plugin from Community Plugins.
  2. Open BRAT settings and click Add Beta Plugin.
  3. Enter: https://github.com/ckelsoe/obsidian-rss-importer
  4. Enable RSS Importer in Settings → Community plugins.

Development

See CONTRIBUTING.md for setup, quality gates, and conventions.

License

MIT. See LICENSE.