rss-cli 0.2.0

An AI-friendly, cache-backed RSS / Atom / JSON Feed CLI that also runs as an MCP server
Documentation
# 4. File-based atomic cache, not an embedded DB

- **Status:** Accepted
- **Date:** 2026-06-01

## Context

The tool needs a small local cache for two jobs: (a) storing HTTP validators (`ETag`,
`Last-Modified`) and bodies so refetches can be conditional GETs
([ADR-0005](0005-conditional-get-always-revalidate-default.md)), and (b) holding the last
body so `rss show` / the MCP `get_item` can resolve an item without a forced network hit.
It must be lightweight (the project's defining adjective), have no C/build-time
dependency, and ideally be inspectable by a curious human or agent.

## Decision

A **file-based cache**, implemented in [`src/cache.rs`](../../src/cache.rs). Each feed is
two files under the OS cache dir (via the `directories` crate, overridable with
`--cache-dir`), keyed by `sha256(feed_url)`:

- `<hash>.json``CacheMeta` (feed_url, etag, last_modified, fetched_at, content_type).
- `<hash>.body` — the raw response bytes.

Writes are **atomic**: write to a uniquely-named temp file in the same directory, then
`rename` over the target (atomic within a filesystem), so a crash or concurrent run can
never observe a torn entry. There is no index file to keep consistent; `cache list` simply
scans `*.json`.

## Consequences

- Zero non-Rust dependencies; nothing to migrate; trivial to reason about and to delete
  (`rss cache clear`, or just `rm` the dir).
- Human/agent-inspectable: the metadata is plain JSON and the body is the literal feed.
- The cache is explicitly **not** responsible for id stability — that is by construction
  ([ADR-0003]0003-deterministic-content-hash-item-ids.md). Its only jobs are conditional
  GET and `show`/`get_item` lookups.
- No global lock: two concurrent processes hitting the same feed may both write, but the
  atomic rename means each write is all-or-nothing and last-writer-wins is harmless (both
  bodies are valid). This is acceptable for a CLI; it is not a transactional store.

## Alternatives considered

- **`redb` (pure-Rust embedded KV) or `sqlite`.** Rejected for v1: transactional integrity
  is overkill for a best-effort HTTP cache, and both add weight / a less inspectable store.
  `redb` is noted as the upgrade path if a future feature genuinely needs transactions.
- **In-memory only (no persistence).** Rejected: defeats conditional GET across
  invocations, which is the main politeness/bandwidth win.