feat(workspace): claudemesh me topics + dashboard topics page
Some checks failed
CI / Lint (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Broker tests (Postgres) (push) Has been cancelled
CI / Docker build (linux/amd64) (push) Has been cancelled

ships v0.4.0 phase 2: a cross-mesh topic feed.

api: GET /v1/me/topics aggregates topics across every mesh the
caller belongs to with per-topic unread counts (vs the user's
member-row last_read_at) and last-message timestamps. Sorted by
last activity.

cli (1.11.0): claudemesh me topics renders the feed; --unread
filters to topics with pending reads; --json returns raw.

web: /dashboard/topics ssr's the same view server-side (direct
db queries, no apikey-mint roundtrip) and adds a Topics entry
to the dashboard sidebar between Meshes and Invites.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-05-03 00:39:58 +01:00
parent aa6c7be4eb
commit c795df4fd4
7 changed files with 518 additions and 2 deletions

View File

@@ -124,6 +124,7 @@ Topic (conversation scope, v0.2.0)
claudemesh topic post <t> <msg> encrypted REST post (v0.3.0 v2) [--reply-to <id>]
claudemesh send "#topic" "msg" send to a topic (WS path, v1 plaintext)
claudemesh me cross-mesh workspace overview (v0.4.0)
claudemesh me topics cross-mesh topic list [--unread]
claudemesh member list mesh roster with online state [--online]
claudemesh notification list recent @-mentions of you [--since <ISO>]
@@ -683,9 +684,14 @@ async function main(): Promise<void> {
if (!sub || sub === "workspace" || sub === "overview") {
const { runMe } = await import("~/commands/me.js");
process.exit(await runMe(f));
} else if (sub === "topics") {
const { runMeTopics } = await import("~/commands/me.js");
process.exit(await runMeTopics({ ...f, unread: !!flags.unread }));
} else {
console.error(
"Usage: claudemesh me (cross-mesh overview; future: me topics, me notifications, me activity)",
"Usage: claudemesh me (cross-mesh overview)\n" +
" claudemesh me topics (cross-mesh topic list)\n" +
" claudemesh me topics --unread (only unread topics)",
);
process.exit(EXIT.INVALID_ARGS);
}