RFC-002 — amem Clipper skills catalog UI (v0.1)
- Status: Draft
- Authors: @yiidtw
- Created: 2026-05-09
- Related: RFC-001 (function-based v0.1), RFC-003 (recording orchestration), archived RFC-001 (bridge-first), SPEC.md § Mental model
TL;DR
The amem Clipper sidepanel grows a second tab — Skills — that renders the v0.1 catalog as if it were an installable marketplace. v0.1 ships three hardcoded skills behind that UI: Auto-capture arxiv, LinkedIn inbox glance, CWS demo recording. The skill cards look identical to what v0.2’s actually-installable skills will look like, with one honest difference: a “Custom skills coming v0.2” disclosure underneath the catalog. CWS positioning leans on this UI: the listing claims “the first agent-callable Chrome skills catalog,” which is true — there is a catalog, each entry is agent-callable via MCP, and the catalog will accept custom entries in v0.2. We are shipping the shape of the product before the generality.
Motivation
RFC-001 commits to function-based v0.1 — hardcoded MCP tools in the librarian, no skill engine. That decision optimises engineering throughput to the CWS deadline. It does not, by itself, give us a CWS listing or a narrative.
The sidepanel UI is where the strategic positioning lives:
- Without a catalog UI, we are submitting “another Chrome extension that captures pages and integrates with an MCP server.” Crowded category; forgettable listing.
- With a catalog UI, the listing reads: “amem Clipper turns your browser into an agent-callable skills runtime. Three skills shipped — arxiv auto-capture, LinkedIn inbox glance, demo recording. Custom skills coming v0.2.” This is the differentiator. Nobody else is shipping Chrome skills the agent can list and invoke over MCP.
The catalog UI also pulls future weight: the v0.2 install flow is identical in structure to the v0.1 hardcoded path (skill card → toggle → bridge command). Users who learn the v0.1 model carry the mental model forward unchanged.
Proposal
1. Sidepanel tab strip
The sidepanel grows from a single capture surface to a two-tab strip:
┌────────────────────────────────────┐
│ amem Clipper ⚙ │
├────────────────────────────────────┤
│ [ Captures ] Skills │ ← tabs, [bracketed] = active
├────────────────────────────────────┤
│ │
│ (tab content) │
│ │
└────────────────────────────────────┘
- Captures — the existing capture log (recent items, filters, search). Default tab on first launch.
- Skills — the new catalog tab. The shape this RFC is about.
State is stored in chrome.storage.local; users land on whichever tab
they last closed.
2. Skill card schema (UI-level, not manifest)
Each skill renders as one card. The schema below is the render contract
between the librarian (which owns the catalog truth) and the sidepanel
(which renders it). It is not a manifest on disk in v0.1; it is the
shape returned by amem_list_skills over the bridge.
type SkillCard = {
id: string; // stable, e.g. "arxiv-autocapture"
name: string; // "Auto-capture arxiv"
description: string; // one-liner, ~80 chars
icon: string; // emoji or built-in icon name
kind: "auto" | "run"; // toggle vs button
state: SkillState;
badges?: string[]; // e.g. ["builtin", "v0.1"]
};
type SkillState =
| { kind: "auto"; enabled: boolean } // for auto skills
| { kind: "run"; busy: boolean; last_run?: string } // for run skills
| { kind: "error"; message: string };
Card layout:
┌─────────────────────────────────────────────────────┐
│ 📄 Auto-capture arxiv [ ●─── ] │
│ Captures every arxiv abstract you open. │
│ builtin · v0.1 │
└─────────────────────────────────────────────────────┘
- Top-right control depends on
kind:kind:"auto"→ toggle switch, bound to theenabledbooleankind:"run"→ “Run” button, disabled whilebusy=true, last-run timestamp under the buttonkind:"error"→ red text + “Retry” button
- Badges render as small tags at the bottom of the card.
- Cards are not reorderable in v0.1 (catalog order is hardcoded). v0.2 may add user pinning.
3. The three v0.1 skills
3a. Auto-capture arxiv (id: "arxiv-autocapture", kind: "auto")
Toggle-on means: any time the user navigates to an arxiv URL matching
arxiv.org/abs/* or arxiv.org/pdf/*, the clipper sends an auto_capture
event over the bridge with the URL; the librarian dispatches to the arxiv
adapter (RFC-001 §3b) and ingests.
Default: off. Auto-capturing every arxiv abstract is opinionated; users opt in.
UI behaviour:
- Toggle ON → small toast “Auto-capture armed for arxiv.org”
- On a successful capture → unobtrusive notification dot on the Clipper toolbar icon for ~5s
- On a duplicate (already captured) → silent (don’t spam)
- On error → clipper toolbar icon shows red dot, click for details
Implementation note: the toggle state lives in chrome.storage.local for
fast content-script reads; the librarian’s config.toml mirrors it as the
authoritative copy. Sidepanel reads truth from amem_list_skills on
every render; toggle writes go through amem_invoke_skill("arxiv- autocapture", { enabled: true }).
3b. LinkedIn inbox glance (id: "linkedin-inbox", kind: "run")
User clicks Run → librarian uses chrome_navigate to open
linkedin.com/messaging/, then chrome_extract to read the visible
inbox previews, then renders a digest in the sidepanel: who messaged,
unread count, first line of each thread.
This skill exists for two reasons:
- Demo value. It demonstrates that the agent can operate the user’s already-logged-in Chrome — the v0.1 differentiator. Without a visible flagship for that capability, the CWS reviewer has nothing concrete to evaluate.
- Honest utility. The operator actually uses this. It is not a throwaway skill written for the demo.
UI behaviour:
- Click Run → button disables, spinner, “Reading inbox…”
- Success → digest renders inline below the card; expandable
- Error (e.g. logged out) → “LinkedIn requires sign-in. Please open linkedin.com and sign in, then retry.”
3c. CWS demo recording (id: "cws-demo", kind: "run")
User (or the agent) clicks Run → librarian invokes record_demo() against
the built-in CWS demo script (RFC-003). The sidepanel shows a recording
state: live elapsed time, current step, “Stop” button.
This is the meta-skill: amem records its own CWS demo by driving its own
extension. The recording captures the entire Chrome window including the
sidepanel UI itself, which is why we need window-level macOS screencapture
rather than chrome.tabCapture (full reasoning in RFC-003 §5).
UI behaviour:
- Click Run → card expands with live status (current step, elapsed time)
- “Stop” cancels gracefully, finalises whatever was captured
- On finish → card shows
amem://recording/<uuid>link + path to mp4 - The recorded mp4 lands in
~/.amem/recordings/<uuid>.mp4
4. Auto-fire mechanism for URL-matched skills
The auto-capture flow lives in two places:
- Content script (clipper) — observes URL changes via
chrome.webNavigation.onCommitted. Pattern matches against the active set ofkind:"auto"skills withenabled:true. Patterns live inchrome.storage.local, synced from the librarian via the bridge on connect. - Background service worker (clipper) — receives match events,
forwards to bridge as
auto_capture.
Why store patterns in chrome.storage.local rather than asking the
bridge per navigation:
- Latency. URL change → bridge round-trip → match would add 50–200ms; unacceptable for ambient capture.
- Resilience. If the bridge briefly disconnects, the toggle behaviour shouldn’t change; the next reconnection re-syncs state.
Sync protocol on bridge connect:
clipper → librarian: { action: "skills_subscribe" }
librarian → clipper: { action: "skills_state",
params: { skills: [SkillCard, ...] } }
(thereafter, librarian pushes "skills_state" on any change)
Drift detection: every amem_list_skills MCP call also pushes the
current state to the clipper, so any out-of-band CLI toggle propagates.
5. Bridge command flow for Run-skills
User clicks Run on a kind:"run" skill:
sidepanel UI background.js librarian
│ user clicks Run │ │
├─ "invoke_skill",───────────▶│ │
│ id: "linkedin-inbox" } │ │
│ ├─ WS send ───────────────▶│
│ │ │
│ │ amem_invoke_skill("linkedin-inbox")
│ │ │
│ │ │ ┌─────────────┐
│ │ │ │ runs the │
│ │ │ │ skill → │
│ │ │ │ chrome_* │
│ │ │ │ over bridge │
│ │ │ └─────────────┘
│ │ ◀─ chrome_navigate /
│ │ chrome_extract pulses
│ │ │
│ │◀─ "skills_state",────────│
│ │ { busy: false, │
│ │ last_run: ... } │
│ "skills_state" forwarded │ │
│◀────────────────────────────┤ │
│ re-render card │ │
The skill execution itself is just an MCP tool call (amem_invoke_skill).
The librarian is the orchestrator; the clipper is the executor for DOM
side-effects. The sidepanel only kicks the kickoff and re-renders state.
6. CWS listing positioning
Listing copy (proposed for store page):
amem Clipper The first agent-callable Chrome skills catalog.
amem Clipper turns your browser into a runtime for Chrome skills your AI agent can list and invoke over MCP. Three skills ship today:
- Auto-capture arxiv — every paper you open lands in your local wiki
- LinkedIn inbox glance — your agent can read your inbox without you opening the tab
- CWS demo recording — amem records its own demos by driving its own extension
Custom skills coming v0.2.
Pairs with
amem-librarian, the local Rust binary that runs on your machine. Your data stays on your disk.
Three claims worth defending:
- “First agent-callable Chrome skills catalog.” True if “catalog”
means “a list of skills the agent can enumerate and invoke.” We have
amem_list_skillsandamem_invoke_skillover MCP; that is the catalog interface. v0.2 adds the user-installs-their-own dimension. The claim is honest with the v0.2 disclosure intact. - “Three skills ship today.” True; all three are real and tested.
- “Your data stays on your disk.” True; storage layout in
~/.amem/is unchanged; bridge is loopback only.
7. Honest disclosure: “Custom skills coming v0.2”
Below the catalog, a fixed footer:
┌─────────────────────────────────────────────────────┐
│ ✨ Custom skills coming v0.2 │
│ Bring your own scripts. ==AmemSkill== headers │
│ will install via drag-and-drop or URL paste. │
│ Read the v0.2 design intent → │
└─────────────────────────────────────────────────────┘
The “Read the v0.2 design intent” link goes to docs.amem.sh/skills/v0.2,
which renders the next section (§8) for transparency.
8. v0.2 design intent — Tampermonkey-style headers
When v0.1 hits a rule-of-three trigger (per RFC-001 §6) we ship a real skill engine. Sketch of the v0.2 user-facing format:
// ==AmemSkill==
// @id youtube-autocapture
// @name Auto-capture YouTube
// @description Saves every YouTube video you watch to your wiki
// @kind auto
// @match https://www.youtube.com/watch*
// @capability bridge:chrome_extract
// @capability librarian:capture
// @version 1
// ==/AmemSkill==
export async function onMatch({ url, ctx }) {
const title = await ctx.chrome.extract("h1.ytd-watch-metadata", "text");
await ctx.librarian.capture(url, { title });
}
Key design choices, locked-in for forward-compat:
- Header format borrowed from Tampermonkey/Greasemonkey. Familiar to anyone who’s written userscripts; no new format to learn.
- Capabilities are explicit. Every skill declares which librarian and bridge verbs it touches. Unknown capabilities = install-time rejection.
- Two execution targets. A skill is either DOM-side (runs in clipper) or librarian-side (runs in Rust via JS sandbox). The header decides.
- Install paths. Drag-and-drop a
.amemskill.jsonto the sidepanel, paste a URL pointing to one, or import from a community registry once one exists. - Same MCP surface.
amem_list_skillsandamem_invoke_skillkeep their v0.1 signatures. Custom skills appear in the same catalog, flagged withbadges: ["custom"].
This section is design intent, not commitment. Numbers can change. What is locked-in is the v0.1 MCP surface; v0.2 will not re-shape it.
Privacy
- The catalog UI itself sends no telemetry. Skill card render data comes exclusively from the loopback bridge.
- Auto-fire patterns (URL globs) live in
chrome.storage.localper-user, per-profile. They are not synced with Chrome Sync (we explicitly opt out by not declaringstorage.syncpermission). - Run-skill invocations log to the librarian only (
~/.amem/skills.log, one line per invoke with timestamp, skill id, outcome). Off by default; enable with[skills] log = trueinconfig.toml. - The “LinkedIn inbox glance” skill reads DOM content from the user’s own logged-in tab. It does not exfiltrate anywhere except the librarian’s local storage. The inbox digest is not auto-captured to the wiki — it renders inline only.
Failure modes
| Mode | Cause | Mitigation |
|---|---|---|
| Bridge disconnects mid-render | Librarian crashed or restarted | Cards render in kind:"error" state with “Reconnect” affordance; on reconnect, skills_state re-syncs and cards refresh |
| Auto-skill toggle drift | User toggles in CLI (amem skills enable …) while sidepanel is open | Sidepanel listens for skills_state push; re-renders |
| Run-skill hangs | Skill awaits a selector that never appears | Run buttons have a 60s soft timeout; user sees “Taking longer than usual…” + “Stop” |
| Pattern match fires on wrong URL | Glob too loose | v0.1 patterns are tightly scoped (e.g. arxiv.org/abs/* not *arxiv*); we err narrow |
| Sidepanel renders empty | amem_list_skills returned an empty array | Show “Skills service unavailable. Is amem-librarian running?” with install link |
| LinkedIn UI changes | LinkedIn redesigns inbox | Skill returns kind:"error" with selector-not-found; we patch the selector and ship a librarian update — no extension update needed (selectors are server-side) |
| Recording skill UI conflict | User clicks Run on cws-demo while another chrome_* call in flight | Recording acquires librarian-wide lock; concurrent invocations get RECORDING_IN_PROGRESS (RFC-001 §failure modes) |
Concrete work
In rough order:
- (
amem-clipper) Sidepanel tab strip +Captures/Skillsshell — ~0.5d - (
amem-clipper) Skill card component (auto + run + error variants) — ~1d - (
amem-clipper) Bridge subscribe /skills_statehandler + drift reconciliation — ~0.5d - (
amem-librarian) HardcodedSKILLStable +amem_list_skills/amem_invoke_skillMCP tools (lives in RFC-001 §3d but the wiring to the catalog UI is here) — ~0.5d - (
amem-clipper) Auto-fire content-script — URL pattern matcher,chrome.storage.localcache,auto_captureemitter — ~1d - (
amem-clipper) “Custom skills coming v0.2” footer + link — ~0.25d - (
docs.amem.sh)skills/v0.2.mdpage documenting the design intent header — ~0.5d - (
amem-clipper) CWS listing assets: screenshots of the catalog, listing copy per §6, demo gif (recorded by the cws-demo skill itself) — ~0.5d
Total: ~4.25d (overlaps with RFC-001 §concrete-work step 6, which budgets 1d for the same UI work — net new is ~3.25d.)
Rejected alternatives
- Ship without a “Skills” tab; make capture-only the v0.1 surface. Loses the CWS positioning. We are submitting at the same time as a hundred other capture extensions; we need the catalog story to stand out.
- Render skills as a flat list of MCP tools. Technically accurate, user-hostile. “MCP tool” is jargon; “skill” maps to mental models from Tampermonkey, App Store, Raycast extensions, etc.
- Make custom skills installable in v0.1 by accepting hardcoded patches. Doable but every patch is a librarian release; no actual install flow; misleading. Better to be honest and ship the disclosure.
- Hide the “v0.2 coming soon” disclosure. Considered for marketing cleanliness; rejected for trust. Every user opening the sidepanel will immediately wonder “can I write my own?”; pretending otherwise breeds cynicism.
- Use
manifest_version/ install registry now to keep “skills” honest. Equivalent to building a skill engine; rejected per RFC-001 §5.
Open questions
- Card density. Three skills look fine; do we need pagination / search at 10+? Soft preference: defer to v0.2 when skill count is user-driven.
- Skill icons. Use emoji per skill (📄, 💼, 🎬) or commission custom SVGs? Soft preference: emoji for v0.1 (zero design cost), SVGs if a CWS reviewer flags emoji as low-effort.
- Sidepanel width on narrow screens. The skill cards assume ~360px; Chrome sidepanel can be narrower. Verify on 1280-wide laptop.
- Should
amem_list_skillsfilter by current tab URL? I.e. only show “LinkedIn inbox” when the user is on linkedin.com? Considered; rejected for v0.1 — the catalog is supposed to feel like a marketplace shelf, not a context menu. - Run-skill audit. Do
kind:"run"invocations need a confirmation dialog (“Run LinkedIn inbox glance?”) or fire immediately? Soft preference: immediate for v0.1, confirmation if user feedback says surprising.
Roll-out
- v0.1 (this round): three hardcoded skills, sidepanel UI shipped, CWS submission. The catalog is real but not extensible.
- v0.1.x patches: site adapters and skill cards iterate based on actual usage. Each adapter or card is a librarian release; the extension changes only when the card schema changes (rare).
- v0.2: skill engine ships per the design-intent sketch (§8). Custom skills install via drag-and-drop. Catalog UI gains an “Install” affordance; existing cards keep working unchanged.
- v0.3+: community skills registry, skill versioning, signed skills. Out of scope here; track in a future RFC.