Ranchero-Software/NetNewsWire
RSS reader for macOS and iOS.
Single-maintainer risk — review before adopting
worst of 4 axestop contributor handles 99% of recent commits; no tests detected…
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 1w ago
- ✓2 active contributors
- ✓MIT licensed
Show 4 more →Show less
- ⚠Small team — 2 contributors active in recent commits
- ⚠Single-maintainer risk — top contributor 99% of recent commits
- ⚠No CI workflows detected
- ⚠No test directory detected
What would change the summary?
- →Use as dependency Mixed → Healthy if: diversify commit ownership (top <90%); add a test suite
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/ranchero-software/netnewswire)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/ranchero-software/netnewswire on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: Ranchero-Software/NetNewsWire
Generated by RepoPilot · 2026-05-10 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/Ranchero-Software/NetNewsWire shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Single-maintainer risk — review before adopting
- Last commit 1w ago
- 2 active contributors
- MIT licensed
- ⚠ Small team — 2 contributors active in recent commits
- ⚠ Single-maintainer risk — top contributor 99% of recent commits
- ⚠ No CI workflows detected
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live Ranchero-Software/NetNewsWire
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/Ranchero-Software/NetNewsWire.
What it runs against: a local clone of Ranchero-Software/NetNewsWire — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in Ranchero-Software/NetNewsWire | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 40 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of Ranchero-Software/NetNewsWire. If you don't
# have one yet, run these first:
#
# git clone https://github.com/Ranchero-Software/NetNewsWire.git
# cd NetNewsWire
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of Ranchero-Software/NetNewsWire and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "Ranchero-Software/NetNewsWire(\\.git)?\\b" \\
&& ok "origin remote is Ranchero-Software/NetNewsWire" \\
|| miss "origin remote is not Ranchero-Software/NetNewsWire (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "Mac/AppDelegate.swift" \\
&& ok "Mac/AppDelegate.swift" \\
|| miss "missing critical file: Mac/AppDelegate.swift"
test -f "Mac/MainWindow/MainWindowController.swift" \\
&& ok "Mac/MainWindow/MainWindowController.swift" \\
|| miss "missing critical file: Mac/MainWindow/MainWindowController.swift"
test -f "Mac/MainWindow/Detail/DetailWebViewController.swift" \\
&& ok "Mac/MainWindow/Detail/DetailWebViewController.swift" \\
|| miss "missing critical file: Mac/MainWindow/Detail/DetailWebViewController.swift"
test -f "Intents/AddWebFeedIntentHandler.swift" \\
&& ok "Intents/AddWebFeedIntentHandler.swift" \\
|| miss "missing critical file: Intents/AddWebFeedIntentHandler.swift"
test -f "Mac/AppDefaults.swift" \\
&& ok "Mac/AppDefaults.swift" \\
|| miss "missing critical file: Mac/AppDefaults.swift"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 40 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~10d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/Ranchero-Software/NetNewsWire"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
NetNewsWire is a free, open-source RSS/Atom/JSON Feed reader for macOS and iOS that syncs feeds across Apple platforms. It parses and displays RSS, Atom, JSON Feed, and RSS-in-JSON formats in a three-pane interface (feeds sidebar, timeline, article detail view) with support for starred articles, read/unread states, and multiple sync services. Dual-platform monolith: Mac/ directory contains macOS-specific UI (storyboards, XIBs, AppDelegate.swift), iOS code likely mirrors this elsewhere, Intents/ holds Siri shortcuts (Intents.intentdefinition), AppleScript/ contains automation scripts, and core feed parsing logic likely shared between platforms. Preferences, UI, and feed handling are split by platform with shared data models and sync infrastructure.
👥Who it's for
macOS and iOS users who want a privacy-respecting, ad-free feed reader with no subscription fees; open-source contributors interested in Apple platform development (Swift, Objective-C) and RSS feed aggregation; Ranchero Software maintainers building a community-driven news reader.
🌱Maturity & risk
Actively developed and production-ready: the codebase is substantial (2.9M lines of Swift), has structured release cycles with appcasts (netnewswire-release.xml, netnewswire-beta.xml), ships to App Store (AppStore/NetNewsWire7/ directory with versioned screenshots), and maintains a public discourse forum. It's past v6+ and actively maintained, though as a community-driven open-source project, release velocity depends on volunteer contributors.
Low technical risk for consumers, moderate for contributors: the codebase is monolithic rather than modular (single Xcode project), requires developer certificate setup (DeveloperSettings.xcconfig complexity), and the onboarding document (CLAUDE.md present but content unknown) suggests some tribal knowledge. The contributing policy requires pre-approval before PRs, which can slow community contributions. No obvious abandonment signals.
Active areas of work
Active releases flowing through beta and stable appcasts; recent version bumps to NetNewsWire 7.x; maintaining AppStore listings with dark/light mode screenshots for 6.1" phones, Max displays, and iPad. Siri Intents framework integration (AddWebFeedIntentHandler.swift) suggests ongoing feature expansion. No visible current PR or milestone data in file list, check GitHub issues/pulls directly.
🚀Get running
git clone https://github.com/Ranchero-Software/NetNewsWire.git
cd NetNewsWire
chmod +x setup.sh
./setup.sh
# OR manually: create ../SharedXcodeSettings/DeveloperSettings.xcconfig
# Then open NetNewsWire.xcodeproj in Xcode and build
Daily commands:
Open NetNewsWire.xcodeproj in Xcode, select Mac or iOS scheme, press Cmd+R to build and run. No npm/CocoaPods visible in file list—dependencies likely managed via Xcode's Swift Package Manager or checked-in frameworks. Check CLAUDE.md for setup details.
🗺️Map of the codebase
Mac/AppDelegate.swift— Entry point for the macOS application; initializes app lifecycle, window management, and delegates all platform-specific startup logic.Mac/MainWindow/MainWindowController.swift— Core controller managing the three-pane feed reader UI (feeds, timeline, article detail); orchestrates feed selection, article display, and state persistence.Mac/MainWindow/Detail/DetailWebViewController.swift— Renders article content in a WebView with custom styling and article extraction; critical for the article viewing experience.Intents/AddWebFeedIntentHandler.swift— Handles Siri Shortcuts and automation intents for adding feeds; bridges external integrations with core feed management.Mac/AppDefaults.swift— Centralized user preferences and defaults storage using UserDefaults; referenced throughout app for consistent preference access.Mac/MainWindow/AddFeed/AddFeedController.swift— Implements feed discovery, validation, and addition workflow; critical path for onboarding and feed management.Mac/CloudKitStats/CloudKitStatsViewController.swift— Manages CloudKit synchronization statistics and diagnostics; essential for understanding sync health in iCloud-backed instances.
🛠️How to make changes
Add a new Siri Shortcut Intent
- Define the intent in Intents/Base.lproj/Intents.intentdefinition using Xcode's intent editor (
Intents/Base.lproj/Intents.intentdefinition) - Create a new handler class conforming to the generated intent protocol in Intents/ directory (
Intents/AddWebFeedIntentHandler.swift) - Implement the intent handler logic to call core app functions (e.g., feed subscription via MainWindowController) (
Intents/AddWebFeedIntentHandler.swift) - Add localized strings for the intent in Intents/en.lproj/Intents.strings (
Intents/en.lproj/Intents.strings)
Add a new article detail view feature
- Create or modify the HTML template in Mac/MainWindow/Detail/page.html to include new UI elements (
Mac/MainWindow/Detail/page.html) - Add corresponding CSS styling or modify existing styles in the page template (
Mac/MainWindow/Detail/page.html) - Update DetailWebViewController.swift to inject data or handle user interactions for the new feature (
Mac/MainWindow/Detail/DetailWebViewController.swift) - Add JavaScript handlers in Mac/MainWindow/Detail/main_mac.js if interaction is needed (
Mac/MainWindow/Detail/main_mac.js)
Add a new preference setting
- Define the preference key and default value in Mac/AppDefaults.swift as a static property (
Mac/AppDefaults.swift) - Add a UI control (checkbox, dropdown, etc.) to the preferences storyboard in Mac/Base.lproj/Preferences.storyboard (
Mac/Base.lproj/Preferences.storyboard) - Create or update a preferences view controller to bind the UI control to the AppDefaults key via UserDefaults (
Mac/AppDefaults.swift) - Reference the preference throughout the app where behavior should differ, e.g., in MainWindowController or DetailViewController (
Mac/MainWindow/MainWindowController.swift)
Add a new diagnostic view to CloudKit Stats
- Create a new ViewController subclass in Mac/CloudKitStats/ following the Scan or CleanUp pattern (
Mac/CloudKitStats/CloudKitStatsViewController.swift) - Add a ContentView SwiftUI component for the new diagnostic view (
Mac/CloudKitStats/CloudKitStatsLayout.swift) - Register the new view in CloudKitStatsWindowController.swift as a selectable tab or pane (
Mac/CloudKitStats/CloudKitStatsWindowController.swift) - Implement data collection logic (scanning database, checking CloudKit records) in your ViewController (
Mac/CloudKitStats/CloudKitStatsViewController.swift)
🔧Why these technologies
- Swift & SwiftUI (macOS) — Native performance and deep macOS framework integration; modern declarative UI for new components while maintaining AppKit compatibility.
- WebKit (WKWebView) — Renders article HTML with custom styling and extraction; provides sandboxing and efficient rendering of diverse feed content.
- CloudKit — Automatic iCloud sync for feeds, articles, and read states across user's Apple devices; no server infrastructure needed.
- UserDefaults & Codable — Persistent local preferences and app state; lightweight and integrated with macOS standards.
- Core Data (inferred from sync patterns) — Likely used for local feed/article storage with CloudKit integration for multi-device sync.
⚖️Trade-offs already made
- undefined
- Why: undefined
- Consequence: undefined
🪤Traps & gotchas
Code signing complexity: DeveloperSettings.xcconfig is required for local builds but deliberately not checked in; setup.sh automates this but manual path must match ../SharedXcodeSettings/ sibling directory. Xcode project only: no Swift Package Manager workspace file visible—build system is tightly coupled to Xcode, can't easily use command-line swift build. Before PRs: CONTRIBUTING.md enforces mandatory pre-approval discussion (ask before coding), which differs from typical GitHub workflows. AppleScript automation: AppleScript/ files are examples, not part of core app, but suggest macOS automation hooks that may have undocumented dependencies on UI structure. Platform divergence: Mac/ and (implied) iOS/ codebases likely duplicate UI code; changes must be coordinated.
🏗️Architecture
💡Concepts to learn
- Sparkle Framework / Appcast Updates — NetNewsWire uses Sparkle for macOS updates (visible in netnewswire-release.xml); understanding RSS-based update feeds is essential for shipping changes to users without App Store delays
- Feed Formats (RSS, Atom, JSON Feed, RSS-in-JSON) — Core domain: NetNewsWire must parse four distinct syndication formats with different schema structures, error handling, and extension points (iTunes, Media RSS, etc.)
- Siri Intents / Shortcuts Framework — AddWebFeedIntentHandler.swift shows macOS/iOS automation integration; understanding Intents lets users voice-command feed subscription and enables Siri Shortcut workflows
- NSPasteboard / UIPasteboard — Feed readers use clipboard heavily (paste feed URLs, share articles); macOS NSPasteboard and iOS UIPasteboard APIs differ; critical for cross-platform consistency
- Xcode Storyboards & XIB Layout — NetNewsWire's UI is defined in Base.lproj/*.storyboard and *.xib files, not SwiftUI; understanding Interface Builder's segue, outlet, and constraint system is mandatory for UI modifications
- Feed Sync Protocols (OPML, API endpoints) — RSS readers must sync state across devices; OPML export/import is visible in contributing/feature scope; understanding feed sync state machines and conflict resolution is non-trivial
- SwiftLint Code Style Enforcement — .swiftlint.yml present; linting rules are enforced pre-commit; understanding project's style guide (naming, complexity thresholds, etc.) is essential for PR acceptance
🔗Related repos
Automattic/newspack-ios— iOS-only RSS reader from Automattic; similar feed consumption domain but different architecture (mobile-first vs dual-platform)mozilla/pocket-curation-firefox— Article curation pipeline; relevant for understanding feed ranking and personalization that NetNewsWire could adoptAlamofire/Alamofire— HTTP client library commonly used in Swift RSS readers for feed fetching; likely candidate for NetNewsWire's network layerRanchero-Software/RSParser— Sibling repo from Ranchero Software; likely the actual RSS/Atom/JSON Feed parsing engine that NetNewsWire depends onRanchero-Software/Evergreen— Predecessor RSS reader from Ranchero; NetNewsWire is the spiritual successor; study for architectural lessons and feature history
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add unit tests for RSS/Atom/JSON Feed parsing
NetNewsWire supports multiple feed formats (RSS, Atom, JSON Feed, RSS-in-JSON) but the repo structure shows no dedicated test directory for parsing logic. This is critical for a feed reader where parsing reliability directly impacts user experience. Adding comprehensive unit tests would catch regressions when updating feed parsers and validate edge cases in malformed feeds.
- [ ] Create Tests/ directory structure mirroring Mac/ and iOS/ source organization
- [ ] Identify feed parser files in Mac/ and iOS/ directories (likely in Shared frameworks)
- [ ] Write unit tests for RSS parser with sample feeds (well-formed and edge cases)
- [ ] Write unit tests for Atom parser with RFC 4287 compliance samples
- [ ] Write unit tests for JSON Feed parser with jsonfeed.org spec samples
- [ ] Add test cases for common parsing failures (missing required fields, encoding issues)
- [ ] Integrate tests into Xcode schemes so they run on CI
Create GitHub Actions workflow for macOS and iOS builds
The repo lacks visible CI/CD workflows (.github/workflows/ not shown in file structure). For a multi-platform app (macOS + iOS), automated builds on pull requests would catch platform-specific regressions early, ensure code compiles on both targets, and validate that AppStore build configurations remain valid.
- [ ] Create .github/workflows/macos-build.yml to compile Mac target on each PR
- [ ] Create .github/workflows/ios-build.yml to compile iOS target on each PR
- [ ] Configure workflow to run SwiftLint (repo has .swiftlint.yml) and report violations
- [ ] Add build caching for Swift Package Manager dependencies to speed up CI
- [ ] Ensure workflows validate that both Debug and Release configurations build successfully
- [ ] Document required secrets/signing setup in CONTRIBUTING.md if needed
Document feed format support matrix and parsing limitations
While the README mentions support for RSS, Atom, JSON Feed, and RSS-in-JSON, there's no detailed documentation of which specific versions/specifications are supported, known limitations, or unsupported extensions. This is valuable for bug reporters (to understand if an issue is actually a limitation) and contributors (to understand parsing scope).
- [ ] Create Technotes/FeedFormatSupport.md documenting supported specs
- [ ] List RSS versions supported (1.0, 2.0) and any unsupported extensions
- [ ] Document Atom RFC 4287 compliance level and any namespace limitations
- [ ] Document JSON Feed v1 support and any unimplemented optional features
- [ ] Add section on known parsing limitations (e.g., CDATA handling, entity encoding)
- [ ] Include code references showing where each format is parsed (point to actual parser files)
- [ ] Add troubleshooting section for common feed issues users/contributors encounter
🌿Good first issues
- Add unit tests for feed parsing: create Tests/FeedParsingTests.swift to cover RSS, Atom, JSON Feed, and RSS-in-JSON format parsing; currently no test directory visible in file list despite parser complexity
- Expand AppleScript automation examples: add new example scripts to AppleScript/ for common workflows (e.g., save starred articles to markdown, export feed list to JSON); existing examples (Excel, Mail, OmniFocus, Safari) suggest user demand
- Improve onboarding documentation: expand CLAUDE.md with architecture diagrams (Mac vs iOS code split), feed sync model overview, and common debug workflows; current file list shows complex storyboard structure but no architectural guide
📝Recent commits
Click to expand
Recent commits
d97acdc— Update status (brentsimmons)30ced30— Update version. Write release notes. (brentsimmons)43a0649— Update appcasts. (brentsimmons)716bc90— Update status. (brentsimmons)9373dcb— Update version. Write release notes. (brentsimmons)0c4fd3e— Remove no-longer-used vacuumIfNeeded. (brentsimmons)b64de0c— Add logging and signpost for fetching articles. (brentsimmons)a1ce492— Delete some unused code. (brentsimmons)66bdf3a— Delete database ID cache — it was complexity not actually needed. (brentsimmons)f9d8cbd— Merge branch 'feature/authors-json' (brentsimmons)
🔒Security observations
NetNewsWire demonstrates reasonable security posture for a native macOS/iOS application. Primary concerns are: (1) AppleScript files present execution risks and should be clearly documented; (2) Feed content rendering requires robust XSS protection due to untrusted source input; (3) Dependency management visibility is limited without Package.swift content; (4) No obvious hardcoded secrets detected. The codebase lacks web-specific configuration files which is appropriate for a native application. Recommendations focus on feed content sanitization, dependency pinning, and secure documentation of script execution risks.
- Medium · AppleScript Files Present Security Risk —
AppleScript/ directory. AppleScript files in the repository (Excel-CreateFeedStatisticsSpreadsheet.applescript, Mail-CreateOutgoingMessage.applescript, OmniFocus-AddToNNWReadingList.applescript, Safari-OpenAllStarredArticles.applescript) can execute arbitrary commands. If users download and execute untrusted scripts, they could be compromised. Additionally, if these scripts are distributed or embedded, they present a supply chain risk. Fix: 1) Document security implications clearly for users. 2) Implement code signing for distributed scripts. 3) Consider sandboxing or limiting script capabilities. 4) Regularly audit scripts for unsafe operations. 5) Consider moving to more restricted alternatives if possible. - Low · Missing Security Headers Documentation —
Repository root configuration. No evidence of security header configuration in visible configuration files (.editorconfig, .gitignore, .swiftlint.yml). While this is a macOS/iOS application rather than a web application, any web-facing components (feed fetching, AppleScript web integration) should implement proper security headers. Fix: 1) Document security practices for any HTTP/HTTPS communications. 2) Implement certificate pinning for feed updates. 3) Validate and sanitize all feed content before rendering. 4) Add security headers to any web-based components. - Low · Lack of Dependency Pinning Visibility —
Package.swift (not provided). The Package.swift file content was not provided. Without visibility into dependency versions and sources, it's unclear whether dependencies are pinned to specific versions or ranges, which could expose the application to supply chain risks through automatic dependency updates. Fix: 1) Pin all dependencies to specific versions in Package.swift. 2) Regularly audit and update dependencies. 3) Use dependency verification when possible. 4) Document the rationale for each dependency. 5) Consider using a lock file if available in Swift Package Manager. - Low · Potential XSS in Feed Content Rendering —
Mac/MainWindow/Detail/DetailContainerView.swift, Mac/MainWindow/Detail/DetailIconSchemeHandler.swift. As an RSS/Atom/JSON Feed reader, the application parses and renders untrusted feed content. The DetailContainerView.swift and DetailIconSchemeHandler.swift files suggest HTML/web content rendering. Malicious feeds could inject JavaScript or HTML if content is not properly sanitized. Fix: 1) Implement strict HTML sanitization for all feed content. 2) Use a whitelist approach for allowed HTML tags and attributes. 3) Disable or sandbox JavaScript execution in rendered content. 4) Validate URL schemes (e.g., prevent javascript: and file: schemes). 5) Use native text rendering where possible instead of HTML rendering.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.