一键导入
comparable-apps
List 3-5 comparable apps when planning a UX surface to test category fit and surface high-leverage refusals. Use for "what do other apps do", identity, sync state, local-first design.
菜单
List 3-5 comparable apps when planning a UX surface to test category fit and surface high-leverage refusals. Use for "what do other apps do", identity, sync state, local-first design.
How a workspace-backed app under `apps/*` is composed: the isomorphic doc factory (`create<App>`), the environment factories (`open<App>Browser` / `open<App>Extension` / tauri), the `#platform/*` build-time platform DI for multi-platform (Tauri) apps, the `session` singleton, daemon/script placement under per-project `workspaces/<app>/`, and the file layout itself. Use when creating a new app, naming or placing the iso/browser/extension factory, wiring `#platform/*` subpath imports for a Tauri seam, choosing between auth-gated (Shape A) vs module-singleton (Shape B), placing the session singleton, or registering daemon/script bindings.
Create a slash-command `/goal` for long-running Codex or Claude Code work when the user explicitly asks for a `/goal`, agent goal, or completion condition. Outputs one goal line with the objective, starting context, validation evidence, and stop condition.
Run a continuous collapse-and-simplify pass that surgically removes indirection failing to earn its boundary. Use when the user says 'collapse pass', 'simplify pass', 'reduce indirection', 'shrink the surface', 'find what to delete', when asking to audit a package for dead abstractions, when reviewing a pull request, branch, or recent merged change for simplification (isolated in a worktree), or when the goal is a sequence of small refactor commits that delete more than they add. Pairs with code-audit (smell catalog), refactoring (per-change mechanics), one-sentence-test (cohesion gate), cohesive-clean-breaks (deep redesigns), approachability-audit (first-read sanity), and post-implementation-review (second-read after each commit).
Draft a self-contained, copy-pasteable prompt so a fresh agent can continue without this thread. Use when the user says "hand this off", "compact this", "wrap up for the next session", "write a continuation prompt", "draft a prompt", "make a prompt I can copy-paste", "create a delegation brief", or invokes /handoff.
Epicenter workspace API patterns: `defineTable`, `defineKv`, migrations, actions, `createWorkspace`, materializers, `openCollaboration`, and workspace connections. Use when editing workspace schemas, table/KV access, actions, attachments, or collaboration setup.
Epicenter auth packages: `@epicenter/auth` and the Svelte wrapper at `@epicenter/svelte/auth`, OAuth sessions, identity state, auth-owned fetch/WebSocket, and workspace lifecycle binding. Use when editing Epicenter auth clients, session state, hosted sign-in, or auth/workspace integration.
| name | comparable-apps |
| description | List 3-5 comparable apps when planning a UX surface to test category fit and surface high-leverage refusals. Use for "what do other apps do", identity, sync state, local-first design. |
| metadata | {"author":"epicenter","version":"1.0"} |
Related skills: use one-sentence-test to write the cohesion sentence that the comparable-apps check audits against, and cohesive-clean-breaks when the comparison surfaces an asymmetric win (refuse a feature).
Core move. Before designing a user-facing surface, name 3-5 comparable apps and write one line each about what they do for the same problem. Then ask: which category is Epicenter in, and does the proposed design match that category's pattern? When the design diverges from the category, name the reason. When it converges, the comparison is your evidence that the choice is unsurprising.
Show your work. Write the table out in the spec or design doc, visibly. The value is in the reader seeing the pattern (or the deviation from the pattern) explicitly, not hidden inside your reasoning.
Epicenter is a local-first workspace platform. Many design questions ("should we cache email", "should we show identity in chrome", "should the sync state be visible", "do we need multi-account") have well-trodden answers in comparable categories. Asking the question explicitly catches two failure modes:
The skill is a coherence gate, not a recipe. Categories are heuristic. When the comparison says "do X" but Epicenter has a load-bearing reason to do Y, the reason goes in the spec; the comparison surfaced the cost of the deviation.
COMMUNICATION-FIRST identity is the product; you constantly need
to see "who am I sending as"
examples Gmail, Slack, Discord, Twitter, iMessage
chrome email/handle visible, multi-account chip prominent
cache policy aggressive; identity persisted everywhere
multi-account first class
CREDENTIAL VAULT identity disambiguates which secret store
you just unlocked
examples 1Password, Bitwarden
chrome account email on lock screen
cache policy per-vault, persisted
multi-account common (personal + work vaults)
INFRA / IDENTITY TOOL identity disambiguates which network/tenant
you are routing through
examples Tailscale, Cloudflare Warp, AWS CLI profiles
chrome tray menu shows current tenant
cache policy persisted with explicit switch
multi-account common (multi-tailnet, multi-profile)
TOOL WITH IDENTITY identity is a property of the workspace
you are operating inside; recessive in chrome
examples Linear, Notion, Figma, Asana, Height
chrome avatar in sidebar/corner; email behind a click
cache policy session-cached; email shown on demand
multi-account supported, but most users have one
IDE identity is for authoring/syncing artifacts;
you mostly forget it
examples Cursor, VS Code, JetBrains IDEs
chrome account icon; email behind a click
cache policy session-cached
multi-account rare per editor instance
LOCAL-FIRST WORKSPACE identity is a config detail; the workspace
(vault, graph, doc set) is the unit
examples Obsidian, Logseq, Anytype, Tana, Roam
chrome nothing identity-related; vault name at most
cache policy persisted only if needed for offline sync auth
multi-account rare; one workspace = one identity in practice
Epicenter is local-first workspace. Use this row first; deviations need justification.
Three steps. Don't skip.
State the design question concretely. Not "what should the auth UI look like" but "where do we display the signed-in user's email, and is it cached on disk." Concrete questions have concrete comparisons.
Pick 3-5 apps across at least two rows of the taxonomy. Include the row Epicenter belongs to (local-first workspace) plus the row the design is drifting toward. The drift is where the value lives.
Write one line per app, in a table. Columns are usually: app, category, where the relevant surface appears, what is cached, whether multi-instance is supported. Add columns the specific question demands. Then write the implication: which pattern is Epicenter borrowing, and which is it refusing?
Question: where do we show the signed-in user's email, and should it persist on disk?
| App | Category | Email in chrome? | Where it appears | Persisted? |
|---|---|---|---|---|
| Gmail | Communication-first | Yes, prominent | Avatar chip top-right | Yes |
| 1Password | Credential vault | Yes, on unlock | Vault unlock disambiguator | Yes |
| Tailscale | Infra/identity | Yes, in tray | Tray menu | Yes |
| Linear | Tool with identity | Avatar only | Profile menu on click | Yes |
| Notion | Tool with identity | Avatar only | Account settings | Yes |
| Cursor | IDE | Avatar only | Account dropdown | Yes |
| Obsidian | Local-first | No | Sync settings only | Sync only |
| Logseq | Local-first | No | Sync settings only | Sync only |
Implication: Epicenter is local-first; the closest references (Obsidian, Logseq) keep email out of chrome entirely. The tool-with-identity row (Linear/Notion/Cursor) puts an avatar in chrome and reveals email on click. Either is defensible. Gmail's "email everywhere, cached everywhere" pattern is wrong for the category.
Asymmetric win surfaced: refusing the feature of "email in chrome" lets the runtime state stop carrying email at all. Email becomes a fetched query at the one surface that wants to display it.
Question: how should a settings screen present downloadable local models (Whisper, Parakeet, Moonshine) when each is a 0.03 to 1.6 GB download?
| App | Category | Picker pattern | Size on action? |
|---|---|---|---|
| Ollama desktop | Local LLM runtime | Picks a default model, downloads on first use; library is secondary | Yes |
| LM Studio | Local LLM catalog | Full catalog browser with search; "Staff pick" badge | Yes, on every download button |
| Jan | Local LLM app | Hub with "Recommended" tags | Yes |
| superwhisper | Local dictation | Onboarding recommends one model with its size; others in a secondary list | Yes |
| MacWhisper | Local dictation | Model tiers with sizes; recommended default | Yes |
| Handy | Local dictation (OSS) | Flat model list, recommended default preselected | Yes |
| VoiceInk | Local dictation | Reference target for the next local-dictation pass; model-picker details not yet captured in-repo | Verify before relying on it |
| Wispr Flow | Dictation (cloud) | No model picker at all; the surface does not exist | n/a |
Implication: local-model apps converge on default-first (one recommended model per engine, size visible on the download action, full catalog secondary). Whispering borrowed default-first plus size-on-action and refused LM Studio's catalog browser, since its largest catalog is four models. Wispr Flow is the refusal boundary: going cloud deletes the surface entirely, which is not Whispering's category. VoiceInk is in the reference set now, but not yet evidence for the model-picker claim until someone captures its current picker behavior. Resulting design: a status hero plus one "All models" disclosure (first built in PR #1922, then rebuilt on the folder-backed selector from PR #1923; see specs/20260612T164300-local-model-recommended-defaults-rebuild.md).
Question: how should Whispering help users recover when macOS Accessibility is missing or stale after install/update?
| App | Category | Surface to inspect | Repo-local status |
|---|---|---|---|
| Apple System Settings | Platform convention | Privacy & Security > Accessibility, including remove/re-add behavior after app changes | Current source of truth for the settings path |
| Whispering | Local dictation | In-app guide with written steps, "Open System Settings", and optional hosted video | Implemented in MacosAccessibilityGuide.svelte and MacosAccessibilityGuideDialog.svelte |
| Handy | Local dictation (OSS) | Permission, recorder, shortcut, and local transcription architecture | Already used as a technical reference in Whispering specs and comments |
| superwhisper | Local dictation | Permission onboarding and recovery flow | Existing comparable-apps reference only |
| MacWhisper | Local transcription | Permission onboarding and recovery flow | Existing comparable-apps reference only |
| VoiceInk | Local dictation | Permission onboarding and recovery flow | New reference target; no previous repo references |
| Wispr Flow | Dictation (cloud) | Permission onboarding and recovery flow | Existing comparable-apps reference only |
Implication: Apple owns the canonical permission path; dictation apps are UX references for how to make that platform requirement survivable. Whispering's current shape is a good baseline: text steps, an explicit System Settings action, granted-state feedback, and an optional video loaded from release assets rather than bundled into the app. Before changing the onboarding or recovery flow, capture what VoiceInk does alongside superwhisper, MacWhisper, Handy, and Wispr Flow in the relevant spec.
- Should sync status show in chrome, or only on demand?
comm-first: yes; local-first: minimal, often just an icon.
- Should there be a "switch account" affordance?
comm-first / vault / infra: yes; local-first: no, sign out and sign in.
- Should the app open to a workspace picker or directly to the last workspace?
comm-first (Slack): picker (workspaces); local-first (Obsidian): last one.
- Should we persist user preferences/settings on the server, the device, or both?
comm-first: server; local-first: device first, server optionally.
- Should the offline state surface a banner?
comm-first: yes, prominent; local-first: no, it is the default mode.
- Should we show a "verifying account" loading state?
comm-first: yes; local-first: no, local data renders first.
In every row, the local-first answer is "less identity surface, more workspace-centric framing." Use this as a sanity check against the temptation to import patterns from communication apps.
After the move, the design doc has a short comparison table that names the category Epicenter belongs to, the category the design is drifting toward (if any), and the pattern being borrowed or refused. A reader who has never seen the design can tell from the table alone whether the proposal is consistent with the category Epicenter occupies.