Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

RFC-001 — Bridge-first architecture + settings/feature-flags

  • Status: Draft
  • Authors: @yiidtw
  • Created: 2026-04-21
  • Supersedes: SPEC.md § Roadmap Day 3 item “standalone mode”
  • Related: RFC-002 (RSS), amem-sh youtube pipeline

TL;DR

Reposition the Chrome extension as amem Clipper (working name, not yet branded) — a thin companion to the native amem binary, explicitly modelled on the Apple Watch → iPhone relationship. Drop standalone mode from the roadmap: the binary is a hard prerequisite. When the bridge is unreachable or a feature flag is off, the relevant UI is grayed out in place with a single-click enable/install affordance, not hidden. Heavy capture features (YouTube, RSS, Drive) are feature-flagged in ~/.amem/config.toml and lazy-loaded on demand.

Positioning and naming

The extension and the CLI are not peers. The CLI is amem; the extension is a peripheral that surfaces two capture moments (a browser tab, a YouTube video) that would otherwise require copying a URL into a terminal. Everything downstream of capture — storage, compile, transcription, MCP, recall — lives in the binary.

Working name: amem Clipper. Inherits the Evernote Web Clipper lineage (users know what “clipper” means), avoids collision with the internal “bridge” process name (amem-bridge server on WS 7600), and leaves the brand “amem” attached to the core product rather than the peripheral. The name is a placeholder — final branding lands with the CWS submission.

Product model:

LayerNameRole
Coreamem (CLI + library + MCP)The product. Storage, compile, recall, agent API.
Peripheralamem Clipper (Chrome extension)Capture UI for the browser. Cannot function without the core.
Internalamem-bridge (the WS 7600 process)Implementation detail — users rarely name this.

This positioning reshapes every downstream decision:

  • “Does the extension need feature X?” → Only if feature X is a capture moment. Storage, recall, etc. always live server-side.
  • “What happens with no binary?” → Clipper is bricked, like an Apple Watch with no paired iPhone. Frontload install; don’t half-ship.
  • “Where do settings live?” → In ~/.amem/config.toml on disk. Clipper renders them via a bridge RPC; it never holds authoritative state.

Motivation

The original SPEC envisioned two extension modes:

ModeDayRequirement
Bridge2Native amem binary + WS 7600
Standalone3No native binary; cloud sync via Drive

After shipping the YouTube pipeline we hit three things that make standalone look worse than we expected:

  1. Standalone is structurally crippled. Compile requires Ollama, transcription requires whisper-rs — neither runs in a Chrome MV3 extension. A standalone capture can store URLs but cannot compile, so the wiki never builds. Agent-side MCP is also dark because MCP is native-only.
  2. Feature cost is real. YouTube alone needs yt-dlp (~20 MB), ffmpeg (~60 MB), whisper model (75 MB–3 GB depending on size). Bundling all of this into default install breaks “offline-first with zero cloud dependencies by default” by shifting the pain from network to disk.
  3. Dual code paths are a maintenance tax. Standalone + bridge would mean two storage backends, two capture pipelines, two sets of bugs. The SPEC’s principle 4 (“complement aide, don’t duplicate”) applies to our own internals too.

Meanwhile, bridge mode is already the richer experience. A 30-second curl amem.sh/install | sh is less friction than a crippled standalone fork.

Proposal

1. Bridge is the only mode — UI degrades by graying out

Clipper on cold-start pings ws://127.0.0.1:7600/status. Based on the response, individual UI regions render as enabled, gray-disabled with a one-click enable, or gray-disabled with install CTA:

StateUI for capture-webUI for YouTubeUI for RSSGlobal banner
Bridge unreachablegray, tooltip “amem not running”graygray“Install amem → curl amem.sh/install | sh” with copy button
Bridge OK, all features offenabledgray, inline “Enable YouTube (~95 MB)” buttongray, inline “Enable RSS” button
Bridge OK, YT enabledenabledenabledgray + enable
Bridge OK, all onenabledenabledenabled

Rationale: grayed controls are discoverable (user sees the feature exists, understands why it’s off) and honest (no hidden states). All-or-nothing install cards punish curious first-run users; per-feature gray-out is the Apple Watch “grey watch face when disconnected” pattern the positioning promises.

2. Feature flags live in ~/.amem/config.toml

Clipper renders a Settings page that maps to keys in this file via a new bridge RPC (settings_get / settings_set). The file is the single source of truth — both CLI and Clipper read/write the same keys. Clipper holds no authoritative config of its own, consistent with the peripheral positioning.

# ~/.amem/config.toml
version = 1

[features]
youtube = false         # enables YT capture + compile (lazy-downloads yt-dlp + whisper model)
rss     = false         # enables RSS subscription ingestion (see RFC-002)
drive   = false         # enables Google Drive backup (Day 3)

[youtube]
whisper_model = "tiny.en"  # tiny.en | base.en | small.en | medium.en

[bridge]
host = "127.0.0.1"      # MUST be loopback (see Security)
port = 7600
token_file = "~/.amem/bridge.token"

3. Lazy-load on feature enable

Enabling a flag from Clipper or CLI triggers a setup routine:

amem youtube setup      # CLI: downloads yt-dlp + whisper model + checks ffmpeg
amem rss setup          # (RFC-002)
amem drive setup        # (Day 3)

Clipper setup button → bridge RPC feature_setup({name}) → server runs the corresponding amem <name> setup, streams progress back over WS so Clipper can show a progress bar inline next to the (still grayed) control.

Graceful degradation in core flows. If a user runs amem capture <youtube-url> when features.youtube = false, the CLI prints:

YouTube capture is not enabled. To turn it on:
  amem youtube setup
This will download yt-dlp (~20 MB) and the tiny.en whisper model (~75 MB).

The MCP tool amem_capture returns an analogous structured error, so agents can surface it to their user.

4. Bridge auto-start

On first install, amem install (the curl|sh script) registers a per-user background service:

  • macOS: launchctl user agent (~/Library/LaunchAgents/sh.amem.bridge.plist)
  • Linux: systemctl --user unit (~/.config/systemd/user/amem-bridge.service)
  • Windows: Task Scheduler at-logon task (deferred; Windows support is a follow-up)

Goal: after first-run setup, the bridge is as available as Ollama is today — it just runs.

Security

Bridge-always means a persistent localhost WebSocket. Three defences, all MUST land before the “always on” posture ships:

DefenceMechanism
Loopback bindingServer binds 127.0.0.1, never 0.0.0.0. Reject --bind CLI flags that widen this.
Origin allow-listWS handshake rejects connections whose Origin: header is not chrome-extension://<amem-clipper-prod-id> (production ID) or chrome-extension://<amem-clipper-dev-id> (dev build).
Token authOn bridge start we mint a 32-byte random token to ~/.amem/bridge.token (mode 0600). Extension retrieves it via native-messaging handshake at install time. All WS messages must carry {"token": "..."} in their envelope. Tokens rotate on bridge restart.

Threat model

ThreatImpactMitigation
Another local program connects to WSCould trigger amem_capture → write files to ~/.amem/raw/Token auth + origin check kill 99% of this
Disk-fill DoS via repeated captureFill user’s diskRate-limit captures per minute; refuse when ~/.amem/ exceeds configurable quota
Malicious browser extension connects as usImpersonates our extension_idChrome refuses to forge Origin: for a different extension_id
RCE via yt-dlp / ffmpeg CVEArbitrary code executionUse pinned versions, track security advisories; same posture as Ollama
Prompt injection in captured contentPoisons MCP amem_recall outputSame risk as today’s arxiv/PDF pipeline; not new from bridge-always

Net risk: slightly higher than CLI-only (persistent WS endpoint exists), lower than an HTTP server accepting remote connections. Comparable to VS Code’s language-server loopback.

Migration

  • SPEC.md §Roadmap: strike Day 3 “standalone mode”; add “bridge security hardening + install polish” and “Drive backup” (Drive stays).
  • amem-clipper (repo renamed from amem-extension 2026-04-21): delete any standalone-only code paths (none should exist yet — Day 2 skeleton is bridge-only; this is a no-op today). Rename the product surface to “amem Clipper” in README, store listing, manifest name, and UI chrome.
  • docs: guide/extension.md renamed to guide/clipper.md; its “Standalone vs Bridge” section is being rewritten as “How install works”.
  • README (amem-hq): clarify install-first story on all public pages, label the repo as “amem Clipper (Chrome MV3 extension)”.

Rejected alternatives

  • “Pure cloud standalone” — extension + Drive only, no native binary. Breaks offline-first and agent-MCP. Also introduces OAuth complexity earlier than Day 3.
  • Bundle everything in the default install. Ships ~3 GB of whisper models most users never use. Opposite of the lazy-load principle.
  • Run whisper.wasm in the browser. Early 2026 performance is still 3–10× slower than native for base.en; model download in the extension also hits MV3 storage limits.

Concrete work

See GitHub issues linked from this RFC.

  1. amem youtube setup subcommand + graceful-degradation prompt in capture (amem-sh)
  2. Bridge: loopback binding + Origin: check + token auth (amem-sh)
  3. Bridge: auto-start service installers (macOS launchd, Linux systemd) (amem-sh)
  4. Clipper: bridge status probe, per-region gray-out UI, Settings page backed by config.toml via bridge RPC (amem-clipper)
  5. Clipper: rename product surface to “amem Clipper” (manifest, store listing copy, in-UI strings) — repo slug already renamed to amem-clipper 2026-04-21 (amem-clipper)
  6. SPEC.md + docs: drop standalone, document bridge-first (amem-hq)

Open questions

  • Do we treat Ollama as a similarly lazy-loaded feature? Arguably yes — PDF compile also blocks without it. Worth a follow-up RFC if so.
  • Drive backup (Day 3): should it require Pro/auth once shipped, or stay free? Product decision, not in scope here.