feat(web): refresh marketing site — accurate timeline, live changelog, cross-boundary positioning
The site had drifted ~6 months behind the product. Three problems
addressed in one push:
1. Timeline ("Shipped, not promised") topped out at v0.6–0.8 and
claimed "66 npm releases" — both stale. Adds a v0.9 → 1.34 tier
covering daemon, multi-mesh, multi-session correctness train,
refuse-to-kick on control-plane, env-var fallback. Updates count
to "120+ npm releases through v1.34.15." Rewrites the "next"
block from the now-shipped "Daemon redesign · per-topic
encryption" to the actually-pending "HKDF cross-machine identity
· session capabilities · A2A interop · self-host packaging ·
federation."
2. Hero subhead leaned into the original "Claude Code peer mesh"
framing, which is undercut by Anthropic Agent Teams (Feb 2026,
single-machine native mailbox). Now reframes claudemesh as the
encrypted backbone where Claude Code sessions, autonomous
agents, and humans coordinate "across machines, across users,
across organizations" — the four words that distinguish the
product from anything Anthropic structurally can ship from
inside Claude Code.
3. /changelog had three entries from April 2026 (v0.1.2 → v0.1.4)
and was 70+ versions out of date. Replaced with a curated
16-entry timeline from v0.1.0 → v1.34.15, hand-picked to tell
the story (load-bearing ships, not every patch). Adds links
back to docs/roadmap.md, .artifacts/specs/, and GitHub Releases.
New module: apps/web/src/modules/marketing/home/changelog-data.ts
holds the curated entries as a single source of truth. Imported by
both the /changelog page and a new home-page component
LatestReleases (compact 5-entry strip, slotted between Timeline
and Pricing) so they never disagree.
Misc fixes pulled in:
- timeline.tsx had glyph="layers" which isn't in SectionIcon's
valid set; switched to "grid" (changelog-data.ts uses same).
- changelog data extracted to a non-route module so Next.js's
route-export validator stops complaining about exporting
CHANGELOG_ENTRIES from app/.../changelog/page.tsx.
Pre-existing typecheck noise in packages/ui/web/sidebar.tsx
(csstype version mismatch) + billing modules unrelated to this
change. My files all typecheck clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,55 +1,161 @@
|
|||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
import {
|
||||||
|
CHANGELOG_ENTRIES,
|
||||||
|
CHANGELOG_TYPE_COLOR,
|
||||||
|
CHANGELOG_TYPE_LABELS,
|
||||||
|
} from "~/modules/marketing/home/changelog-data";
|
||||||
|
|
||||||
export const metadata = {
|
export const metadata = {
|
||||||
title: "Changelog — claudemesh",
|
title: "Changelog — claudemesh",
|
||||||
description: "Release history for claudemesh-cli.",
|
description:
|
||||||
|
"Release history for claudemesh-cli — every shipped version, with the why behind it.",
|
||||||
};
|
};
|
||||||
|
|
||||||
const ENTRIES = [
|
|
||||||
{ version: "0.1.4", date: "2026-04-06", type: "feat", summary: "Stateful welcome screen, PROTOCOL.md, THREAT_MODEL.md, Windows CI matrix" },
|
|
||||||
{ version: "0.1.3", date: "2026-04-05", type: "feat", summary: "claudemesh --version, status, doctor commands" },
|
|
||||||
{ version: "0.1.2", date: "2026-04-05", type: "feat", summary: "claudemesh launch command, transparency banner, decrypt fix, Windows support" },
|
|
||||||
];
|
|
||||||
|
|
||||||
const TYPE_LABELS: Record<string, string> = { feat: "Feature", fix: "Fix", docs: "Docs" };
|
|
||||||
const TYPE_COLORS: Record<string, string> = { feat: "bg-[var(--cm-clay)]", fix: "bg-[var(--cm-cactus)]", docs: "bg-[var(--cm-oat)]" };
|
|
||||||
|
|
||||||
export default function ChangelogPage() {
|
export default function ChangelogPage() {
|
||||||
return (
|
return (
|
||||||
<section className="mx-auto max-w-3xl px-6 py-24 md:py-32">
|
<section className="mx-auto max-w-3xl px-6 py-24 md:py-32">
|
||||||
|
<div className="mb-12">
|
||||||
|
<p
|
||||||
|
className="text-[11px] uppercase tracking-[0.2em] text-[var(--cm-fg-tertiary)]"
|
||||||
|
style={{ fontFamily: "var(--cm-font-mono)" }}
|
||||||
|
>
|
||||||
|
claudemesh-cli · release log
|
||||||
|
</p>
|
||||||
<h1
|
<h1
|
||||||
className="text-[clamp(2rem,4.5vw,3rem)] font-medium leading-[1.1] text-[var(--cm-fg)]"
|
className="mt-3 text-[clamp(2rem,4.5vw,3rem)] font-medium leading-[1.1] text-[var(--cm-fg)]"
|
||||||
style={{ fontFamily: "var(--cm-font-serif)" }}
|
style={{ fontFamily: "var(--cm-font-serif)" }}
|
||||||
>
|
>
|
||||||
Changelog
|
Changelog
|
||||||
</h1>
|
</h1>
|
||||||
<p
|
<p
|
||||||
className="mt-4 text-[15px] text-[var(--cm-fg-secondary)]"
|
className="mt-4 max-w-xl text-[15px] leading-[1.65] text-[var(--cm-fg-secondary)]"
|
||||||
style={{ fontFamily: "var(--cm-font-sans)" }}
|
style={{ fontFamily: "var(--cm-font-sans)" }}
|
||||||
>
|
>
|
||||||
Every shipped version of claudemesh-cli.
|
Hand-picked, load-bearing ships from{" "}
|
||||||
</p>
|
<span className="text-[var(--cm-fg)]">v0.1.0</span> through{" "}
|
||||||
<div className="mt-12 space-y-8">
|
<span className="text-[var(--cm-clay)]">v1.34.15</span>. For the
|
||||||
{ENTRIES.map((entry) => (
|
byte-level diff, the canonical{" "}
|
||||||
<article key={entry.version} className="border-b border-[var(--cm-border)] pb-6">
|
<Link
|
||||||
<div className="flex items-center gap-3">
|
href="https://github.com/alezmad/claudemesh/blob/main/apps/cli/CHANGELOG.md"
|
||||||
<span
|
className="underline decoration-[var(--cm-fg-tertiary)] underline-offset-4 transition-colors hover:text-[var(--cm-fg)] hover:decoration-[var(--cm-clay)]"
|
||||||
className={`rounded-[4px] px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider text-[var(--cm-bg)] ${TYPE_COLORS[entry.type] || "bg-[var(--cm-fg-tertiary)]"}`}
|
|
||||||
style={{ fontFamily: "var(--cm-font-mono)" }}
|
|
||||||
>
|
>
|
||||||
{TYPE_LABELS[entry.type] || entry.type}
|
CHANGELOG.md
|
||||||
|
</Link>{" "}
|
||||||
|
lives in the repo.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Vertical timeline rail */}
|
||||||
|
<div className="relative">
|
||||||
|
<div
|
||||||
|
className="absolute left-[7px] top-2 hidden h-full w-px md:block"
|
||||||
|
style={{
|
||||||
|
background:
|
||||||
|
"linear-gradient(to bottom, var(--cm-clay) 0%, var(--cm-fig) 30%, var(--cm-cactus) 60%, transparent 100%)",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="space-y-10">
|
||||||
|
{CHANGELOG_ENTRIES.map((entry, idx) => (
|
||||||
|
<article
|
||||||
|
key={entry.version + entry.date}
|
||||||
|
className="relative md:pl-10"
|
||||||
|
>
|
||||||
|
{/* Dot on rail */}
|
||||||
|
<div
|
||||||
|
className="absolute left-0 top-[10px] hidden h-[15px] w-[15px] rounded-full border-2 md:block"
|
||||||
|
style={{
|
||||||
|
borderColor: CHANGELOG_TYPE_COLOR[entry.type],
|
||||||
|
backgroundColor: "var(--cm-bg)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="absolute inset-[3px] rounded-full"
|
||||||
|
style={{
|
||||||
|
backgroundColor: CHANGELOG_TYPE_COLOR[entry.type],
|
||||||
|
opacity: idx === 0 ? 1 : 0.5,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<header className="mb-3 flex flex-wrap items-baseline gap-x-3 gap-y-1">
|
||||||
|
<span
|
||||||
|
className="rounded-[3px] px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wider"
|
||||||
|
style={{
|
||||||
|
fontFamily: "var(--cm-font-mono)",
|
||||||
|
backgroundColor: CHANGELOG_TYPE_COLOR[entry.type],
|
||||||
|
color: "var(--cm-gray-900)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{CHANGELOG_TYPE_LABELS[entry.type]}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-[18px] font-medium text-[var(--cm-fg)]" style={{ fontFamily: "var(--cm-font-serif)" }}>
|
<span
|
||||||
|
className="text-[18px] font-medium text-[var(--cm-fg)]"
|
||||||
|
style={{ fontFamily: "var(--cm-font-serif)" }}
|
||||||
|
>
|
||||||
v{entry.version}
|
v{entry.version}
|
||||||
</span>
|
</span>
|
||||||
<time dateTime={entry.date} className="text-[11px] text-[var(--cm-fg-tertiary)]" style={{ fontFamily: "var(--cm-font-mono)" }}>
|
<time
|
||||||
{new Date(entry.date).toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric" })}
|
dateTime={entry.date}
|
||||||
|
className="text-[11px] text-[var(--cm-fg-tertiary)]"
|
||||||
|
style={{ fontFamily: "var(--cm-font-mono)" }}
|
||||||
|
>
|
||||||
|
{new Date(entry.date).toLocaleDateString("en-US", {
|
||||||
|
year: "numeric",
|
||||||
|
month: "short",
|
||||||
|
day: "numeric",
|
||||||
|
})}
|
||||||
</time>
|
</time>
|
||||||
</div>
|
</header>
|
||||||
<p className="mt-2 text-[14px] leading-[1.6] text-[var(--cm-fg-secondary)]" style={{ fontFamily: "var(--cm-font-sans)" }}>
|
|
||||||
|
<h2
|
||||||
|
className="text-[15px] font-medium text-[var(--cm-fg)]"
|
||||||
|
style={{ fontFamily: "var(--cm-font-sans)" }}
|
||||||
|
>
|
||||||
|
{entry.title}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p
|
||||||
|
className="mt-2 text-[14px] leading-[1.7] text-[var(--cm-fg-secondary)]"
|
||||||
|
style={{ fontFamily: "var(--cm-font-sans)" }}
|
||||||
|
>
|
||||||
{entry.summary}
|
{entry.summary}
|
||||||
</p>
|
</p>
|
||||||
</article>
|
</article>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer className="mt-20 border-t border-[var(--cm-border)] pt-8">
|
||||||
|
<p
|
||||||
|
className="text-[13px] text-[var(--cm-fg-tertiary)]"
|
||||||
|
style={{ fontFamily: "var(--cm-font-sans)" }}
|
||||||
|
>
|
||||||
|
Tracked at{" "}
|
||||||
|
<Link
|
||||||
|
href="https://github.com/alezmad/claudemesh/blob/main/docs/roadmap.md"
|
||||||
|
className="underline decoration-[var(--cm-fg-tertiary)] underline-offset-4 transition-colors hover:text-[var(--cm-fg)] hover:decoration-[var(--cm-clay)]"
|
||||||
|
>
|
||||||
|
docs/roadmap.md
|
||||||
|
</Link>
|
||||||
|
. Specs at{" "}
|
||||||
|
<Link
|
||||||
|
href="https://github.com/alezmad/claudemesh/tree/main/.artifacts/specs"
|
||||||
|
className="underline decoration-[var(--cm-fg-tertiary)] underline-offset-4 transition-colors hover:text-[var(--cm-fg)] hover:decoration-[var(--cm-clay)]"
|
||||||
|
>
|
||||||
|
.artifacts/specs/
|
||||||
|
</Link>
|
||||||
|
. Tagged binaries on{" "}
|
||||||
|
<Link
|
||||||
|
href="https://github.com/alezmad/claudemesh/releases"
|
||||||
|
className="underline decoration-[var(--cm-fg-tertiary)] underline-offset-4 transition-colors hover:text-[var(--cm-fg)] hover:decoration-[var(--cm-clay)]"
|
||||||
|
>
|
||||||
|
GitHub Releases
|
||||||
|
</Link>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Features } from "~/modules/marketing/home/features";
|
|||||||
import { WhereMeshFits } from "~/modules/marketing/home/where-mesh-fits";
|
import { WhereMeshFits } from "~/modules/marketing/home/where-mesh-fits";
|
||||||
import { WhatIsClaudemesh } from "~/modules/marketing/home/what-is-claudemesh";
|
import { WhatIsClaudemesh } from "~/modules/marketing/home/what-is-claudemesh";
|
||||||
import { Timeline } from "~/modules/marketing/home/timeline";
|
import { Timeline } from "~/modules/marketing/home/timeline";
|
||||||
|
import { LatestReleases } from "~/modules/marketing/home/latest-releases";
|
||||||
import { Pricing } from "~/modules/marketing/home/pricing";
|
import { Pricing } from "~/modules/marketing/home/pricing";
|
||||||
import { FAQ } from "~/modules/marketing/home/faq";
|
import { FAQ } from "~/modules/marketing/home/faq";
|
||||||
import { CallToAction } from "~/modules/marketing/home/cta";
|
import { CallToAction } from "~/modules/marketing/home/cta";
|
||||||
@@ -22,6 +23,7 @@ const HomePage = () => {
|
|||||||
<WhereMeshFits />
|
<WhereMeshFits />
|
||||||
<WhatIsClaudemesh />
|
<WhatIsClaudemesh />
|
||||||
<Timeline />
|
<Timeline />
|
||||||
|
<LatestReleases count={5} />
|
||||||
<Pricing />
|
<Pricing />
|
||||||
<FAQ />
|
<FAQ />
|
||||||
<CallToAction />
|
<CallToAction />
|
||||||
|
|||||||
168
apps/web/src/modules/marketing/home/changelog-data.ts
Normal file
168
apps/web/src/modules/marketing/home/changelog-data.ts
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
/**
|
||||||
|
* Single source of truth for the curated release log surfaced on:
|
||||||
|
* - /changelog (full timeline)
|
||||||
|
* - / (Latest Releases compact strip)
|
||||||
|
*
|
||||||
|
* Lives outside `app/.../page.tsx` because Next.js's app-router type generator
|
||||||
|
* rejects non-conforming exports from route files (only `default`, `metadata`,
|
||||||
|
* `dynamic`, etc. are allowed). Importing data from a plain module sidesteps
|
||||||
|
* the constraint without changing route semantics.
|
||||||
|
*
|
||||||
|
* Hand-picked load-bearing ships, newest first. For the byte-level history
|
||||||
|
* see `apps/cli/CHANGELOG.md` in the repo.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type ChangelogEntry = {
|
||||||
|
version: string;
|
||||||
|
date: string;
|
||||||
|
type: "feat" | "fix" | "docs" | "perf" | "infra";
|
||||||
|
title: string;
|
||||||
|
summary: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CHANGELOG_ENTRIES: ChangelogEntry[] = [
|
||||||
|
{
|
||||||
|
version: "1.34.15",
|
||||||
|
date: "2026-05-04",
|
||||||
|
type: "fix",
|
||||||
|
title: "peer list --mesh scopes; kick refuses control-plane",
|
||||||
|
summary:
|
||||||
|
"Two follow-ups from the multi-session correctness train. peer list --mesh now forwards the slug to the daemon (was aggregating across all attached meshes). The broker refuses no-op kicks against control-plane connections (daemon, dashboard) — they auto-reconnected within seconds — and surfaces them in a new additive ack field. Soft `disconnect` keeps old behavior.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "1.34.14",
|
||||||
|
date: "2026-05-04",
|
||||||
|
type: "fix",
|
||||||
|
title: "stale CLAUDEMESH_CONFIG_DIR falls back",
|
||||||
|
summary:
|
||||||
|
"When the launched-session env leaked into a later CLI invocation and pointed at a tmpdir that no longer existed, the resolver silently used the dead path and showed “No meshes joined”. Now memoized: env unset → default; env points at a real dir → trust; env set but dir gone → TTY-only stderr warning + fallback to ~/.claudemesh.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "1.34.7 → 1.34.13",
|
||||||
|
date: "2026-05-04",
|
||||||
|
type: "fix",
|
||||||
|
title: "multi-session correctness train",
|
||||||
|
summary:
|
||||||
|
"Seven releases over a few hours that took claudemesh from “works for one session” to “internally consistent for N sessions on one daemon.” Per-session SSE demux at the bind layer, inbox per-recipient column, daemon detached by default, MCP forwards session token on /v1/events. Architecture invariant: every shared store / channel scopes by recipient.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "1.32.0",
|
||||||
|
date: "2026-05-04",
|
||||||
|
type: "feat",
|
||||||
|
title: "multi-session UX bundle",
|
||||||
|
summary:
|
||||||
|
"Self-identity via session pubkey, `--self` fan-out for member-pubkey targeting, broker welcome on launch (broker state + peer count + unread inbox). Resolves hex prefixes to full pubkeys before send.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "1.30.0",
|
||||||
|
date: "2026-05-04",
|
||||||
|
type: "feat",
|
||||||
|
title: "per-session broker presence",
|
||||||
|
summary:
|
||||||
|
"Two `claudemesh launch` sessions in the same cwd finally see each other in `peer list`. Each session has a long-lived broker presence row owned by the daemon, identified by a per-launch ephemeral keypair vouched by the member's stable key. Broker `session_hello` handler with parent-attestation TTL and session-signature checks.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "1.26.0 → 1.29.0",
|
||||||
|
date: "2026-05-04",
|
||||||
|
type: "feat",
|
||||||
|
title: "multi-mesh daemon · per-session IPC tokens",
|
||||||
|
summary:
|
||||||
|
"One daemon process attaches to every joined mesh simultaneously. Aggregate read routes (/v1/peers, /v1/skills) tag each record with its mesh; explicit ?mesh=<slug> narrows server-side. Per-session IPC tokens scoped to tmpdir mode-0600 so CLI invocations from inside a launched session auto-attribute to its workspace. Self-healing daemon lifecycle (auto-spawn under file-lock, version probe).",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "1.24.0",
|
||||||
|
date: "2026-05-03",
|
||||||
|
type: "feat",
|
||||||
|
title: "daemon required + thin MCP",
|
||||||
|
summary:
|
||||||
|
"MCP server shrinks from 979 LoC to ~200 LoC of push-pipe. The daemon owns the broker WS and feeds the MCP push channel over IPC SSE. `claudemesh install` auto-installs and starts the daemon service. `claudemesh launch` ensures daemon is running before spawning Claude.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "0.9.0 (1.22.0)",
|
||||||
|
date: "2026-05-03",
|
||||||
|
type: "feat",
|
||||||
|
title: "daemon foundation",
|
||||||
|
summary:
|
||||||
|
"Long-lived process holding one broker WS per attached mesh, durable outbox/inbox in SQLite, IPC over UDS (+ optional loopback TCP w/ bearer), SSE event stream. Caller-stable idempotency on every send. Service install (launchd / systemd-user). Outbox CLI with atomic abort+insert on requeue. Host-fingerprint pin on first run.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "0.7.0 (1.21.0)",
|
||||||
|
date: "2026-05-03",
|
||||||
|
type: "infra",
|
||||||
|
title: "slug = identifier",
|
||||||
|
summary:
|
||||||
|
"Pre-launch correction of generic SaaS scaffolding. mesh.name and mesh.slug collapse — slug IS the identifier. `claudemesh rename <old-slug> <new-slug>` is the entire rename surface. CLI picker drops the (parens). Server PATCH /api/cli/meshes/:slug body becomes `{ slug }`.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "0.4.0 → 0.5.2 (1.10.0–1.18.0)",
|
||||||
|
date: "2026-05-03",
|
||||||
|
type: "feat",
|
||||||
|
title: "me/* cross-mesh aggregation",
|
||||||
|
summary:
|
||||||
|
"First cross-mesh read-aggregating verbs. /v1/me/workspace, /v1/me/topics, /v1/me/notifications, /v1/me/activity, /v1/me/search — every aggregating read verb has CLI + web parity. Default-aggregation for `topic list`, `notification list`, `task list`, `state list`, `memory recall` when no --mesh is passed. file share / get with same-host fast path.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "0.3.0 (1.8.0)",
|
||||||
|
date: "2026-05-02",
|
||||||
|
type: "feat",
|
||||||
|
title: "per-topic encryption (CLI + web)",
|
||||||
|
summary:
|
||||||
|
"Topics generate a 32-byte symmetric key on creation; broker seals via crypto_box for the creator. Pending-seals endpoint, seal POST, claudemesh topic post for encrypted REST sends, decrypt-on-render in topic tail, 30s background re-seal loop. Web side: browser-side persistent ed25519 identity in IndexedDB + encrypt-on-send / decrypt-on-render.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "1.7.0",
|
||||||
|
date: "2026-05-02",
|
||||||
|
type: "feat",
|
||||||
|
title: "demo cut: topic tail, member list, notifications",
|
||||||
|
summary:
|
||||||
|
"Member sidebar in chat panel with names, online dots, presence summaries. Topic search + member-mention autocomplete. Notification feed at /dashboard listing every @<your-name> reference across all meshes (last 7 days). CLI parity: `claudemesh topic tail` (live SSE consumer), `claudemesh member list`, `claudemesh notification list`.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "0.2.0 (1.6.0)",
|
||||||
|
date: "2026-05-02",
|
||||||
|
type: "feat",
|
||||||
|
title: "topics + REST gateway + bridge peers",
|
||||||
|
summary:
|
||||||
|
"Topics (channel pub/sub) with mesh = trust boundary, group = identity tag, topic = conversation scope — three orthogonal axes. API keys for non-WebSocket clients. REST /api/v1/* with bearer-token auth (messages, topics, peers, history). Bridge peers belonging to two meshes forwarding a topic between them. Humans-as-peers — peer_type: human plumbed end-to-end.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "1.5.0",
|
||||||
|
date: "2026-05-02",
|
||||||
|
type: "feat",
|
||||||
|
title: "CLI-first architecture lock-in",
|
||||||
|
summary:
|
||||||
|
"Tool-less MCP — tools/list returns []. Inbound peer messages still arrive as experimental.claude/channel notifications mid-turn. Bundle size −42%. Resource-noun-verb CLI (peer list, message send, memory recall). Bundled claudemesh skill installed to ~/.claude/skills/. Unix-socket bridge for warm WS reuse (~220 ms warm vs ~600 ms cold). Policy engine + audit log.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "1.0.0-alpha",
|
||||||
|
date: "2026-04-15",
|
||||||
|
type: "feat",
|
||||||
|
title: "single-binary distribution + per-peer caps",
|
||||||
|
summary:
|
||||||
|
"curl -fsSL claudemesh.com/install | sh downloads the right binary (darwin/linux/windows × x64/arm64). claudemesh:// URL scheme makes invite emails one-click. Per-peer capability grants: claudemesh grant/revoke/block/grants enforced server-side. Encrypted backup / restore with Argon2id + XChaCha20-Poly1305. Safety numbers (`claudemesh verify <peer>`).",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "0.1.0",
|
||||||
|
date: "2026-04-04",
|
||||||
|
type: "feat",
|
||||||
|
title: "public launch",
|
||||||
|
summary:
|
||||||
|
"Direct peer-to-peer messaging through a hosted broker, ready for real teams. End-to-end encryption — crypto_box direct, crypto_secretbox group. Signed ed25519 identities + signed invite links (ic://join/...). Hello-sig handshake auth. Hosted broker at wss://ic.claudemesh.com/ws. Claude Code MCP tools: list_peers, send_message, check_messages, set_summary, set_status.",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const CHANGELOG_TYPE_LABELS: Record<ChangelogEntry["type"], string> = {
|
||||||
|
feat: "Feature",
|
||||||
|
fix: "Fix",
|
||||||
|
docs: "Docs",
|
||||||
|
perf: "Perf",
|
||||||
|
infra: "Infra",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CHANGELOG_TYPE_COLOR: Record<ChangelogEntry["type"], string> = {
|
||||||
|
feat: "var(--cm-clay)",
|
||||||
|
fix: "var(--cm-cactus)",
|
||||||
|
docs: "var(--cm-oat)",
|
||||||
|
perf: "var(--cm-fig)",
|
||||||
|
infra: "var(--cm-fg-tertiary)",
|
||||||
|
};
|
||||||
@@ -67,9 +67,10 @@ export const HeroWithMesh = () => {
|
|||||||
textShadow: "0 2px 20px rgba(0,0,0,0.8)",
|
textShadow: "0 2px 20px rgba(0,0,0,0.8)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Share context, files, skills, and MCPs across every Claude Code
|
The encrypted backbone where Claude Code sessions, autonomous
|
||||||
session — end-to-end encrypted. Hosted on claudemesh.com or
|
agents, and humans coordinate — across machines, across users,
|
||||||
self-hosted in your VPC. Same CLI, same wire, your choice.
|
across organizations. Hosted on claudemesh.com or self-hosted in
|
||||||
|
your VPC. Same CLI, same wire, your choice.
|
||||||
</p>
|
</p>
|
||||||
</Reveal>
|
</Reveal>
|
||||||
|
|
||||||
|
|||||||
141
apps/web/src/modules/marketing/home/latest-releases.tsx
Normal file
141
apps/web/src/modules/marketing/home/latest-releases.tsx
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
import {
|
||||||
|
CHANGELOG_ENTRIES,
|
||||||
|
CHANGELOG_TYPE_COLOR,
|
||||||
|
CHANGELOG_TYPE_LABELS,
|
||||||
|
} from "./changelog-data";
|
||||||
|
import { Reveal, SectionIcon } from "./_reveal";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compact recent-releases strip for the home page. Pulls the top N entries
|
||||||
|
* from the same data source as the full /changelog page so they never
|
||||||
|
* disagree.
|
||||||
|
*/
|
||||||
|
export const LatestReleases = ({ count = 5 }: { count?: number }) => {
|
||||||
|
const recent = CHANGELOG_ENTRIES.slice(0, count);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="border-b border-[var(--cm-border)] bg-[var(--cm-bg-elevated)] px-6 py-24 md:px-12 md:py-28">
|
||||||
|
<div className="mx-auto max-w-[var(--cm-max-w)]">
|
||||||
|
<Reveal className="mb-6 flex justify-center">
|
||||||
|
<SectionIcon glyph="grid" />
|
||||||
|
</Reveal>
|
||||||
|
|
||||||
|
<Reveal delay={1}>
|
||||||
|
<p
|
||||||
|
className="text-center text-[11px] uppercase tracking-[0.2em] text-[var(--cm-fg-tertiary)]"
|
||||||
|
style={{ fontFamily: "var(--cm-font-mono)" }}
|
||||||
|
>
|
||||||
|
release log · last {count} ships
|
||||||
|
</p>
|
||||||
|
</Reveal>
|
||||||
|
|
||||||
|
<Reveal delay={2}>
|
||||||
|
<h2
|
||||||
|
className="mt-3 text-center text-[clamp(1.75rem,3.5vw,2.5rem)] font-medium leading-[1.15] text-[var(--cm-fg)]"
|
||||||
|
style={{ fontFamily: "var(--cm-font-serif)" }}
|
||||||
|
>
|
||||||
|
What shipped this week
|
||||||
|
</h2>
|
||||||
|
</Reveal>
|
||||||
|
|
||||||
|
<Reveal delay={3}>
|
||||||
|
<p
|
||||||
|
className="mx-auto mt-3 max-w-xl text-center text-[14px] leading-[1.65] text-[var(--cm-fg-secondary)]"
|
||||||
|
style={{ fontFamily: "var(--cm-font-sans)" }}
|
||||||
|
>
|
||||||
|
Every release is in production on{" "}
|
||||||
|
<span
|
||||||
|
className="text-[var(--cm-fg)]"
|
||||||
|
style={{ fontFamily: "var(--cm-font-mono)" }}
|
||||||
|
>
|
||||||
|
wss://ic.claudemesh.com
|
||||||
|
</span>{" "}
|
||||||
|
within minutes. The CLI publishes to npm; the broker auto-deploys.
|
||||||
|
</p>
|
||||||
|
</Reveal>
|
||||||
|
|
||||||
|
<Reveal delay={4}>
|
||||||
|
<ol className="mx-auto mt-12 max-w-3xl space-y-4">
|
||||||
|
{recent.map((entry, idx) => (
|
||||||
|
<li key={entry.version + entry.date}>
|
||||||
|
<Link
|
||||||
|
href="/changelog"
|
||||||
|
className="group block rounded-[var(--cm-radius-md)] border border-[var(--cm-border)] bg-[var(--cm-bg)] p-5 transition-colors hover:border-[var(--cm-clay)]/40"
|
||||||
|
>
|
||||||
|
<div className="flex flex-wrap items-baseline gap-x-3 gap-y-1">
|
||||||
|
<span
|
||||||
|
className="rounded-[3px] px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wider"
|
||||||
|
style={{
|
||||||
|
fontFamily: "var(--cm-font-mono)",
|
||||||
|
backgroundColor: CHANGELOG_TYPE_COLOR[entry.type],
|
||||||
|
color: "var(--cm-gray-900)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{CHANGELOG_TYPE_LABELS[entry.type]}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
className="text-[16px] font-medium text-[var(--cm-fg)]"
|
||||||
|
style={{ fontFamily: "var(--cm-font-serif)" }}
|
||||||
|
>
|
||||||
|
v{entry.version}
|
||||||
|
</span>
|
||||||
|
<time
|
||||||
|
dateTime={entry.date}
|
||||||
|
className="text-[11px] text-[var(--cm-fg-tertiary)]"
|
||||||
|
style={{ fontFamily: "var(--cm-font-mono)" }}
|
||||||
|
>
|
||||||
|
{new Date(entry.date).toLocaleDateString("en-US", {
|
||||||
|
year: "numeric",
|
||||||
|
month: "short",
|
||||||
|
day: "numeric",
|
||||||
|
})}
|
||||||
|
</time>
|
||||||
|
{idx === 0 && (
|
||||||
|
<span
|
||||||
|
className="rounded-full bg-[var(--cm-clay)]/15 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider text-[var(--cm-clay)]"
|
||||||
|
style={{ fontFamily: "var(--cm-font-mono)" }}
|
||||||
|
>
|
||||||
|
latest
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<h3
|
||||||
|
className="mt-2.5 text-[15px] font-medium text-[var(--cm-fg)] transition-colors group-hover:text-[var(--cm-clay)]"
|
||||||
|
style={{ fontFamily: "var(--cm-font-sans)" }}
|
||||||
|
>
|
||||||
|
{entry.title}
|
||||||
|
</h3>
|
||||||
|
<p
|
||||||
|
className="mt-2 line-clamp-2 text-[13px] leading-[1.6] text-[var(--cm-fg-secondary)]"
|
||||||
|
style={{ fontFamily: "var(--cm-font-sans)" }}
|
||||||
|
>
|
||||||
|
{entry.summary}
|
||||||
|
</p>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ol>
|
||||||
|
</Reveal>
|
||||||
|
|
||||||
|
<Reveal delay={5}>
|
||||||
|
<div className="mt-10 flex justify-center">
|
||||||
|
<Link
|
||||||
|
href="/changelog"
|
||||||
|
className="group inline-flex items-center gap-2 text-[13px] font-medium text-[var(--cm-fg-secondary)] transition-colors hover:text-[var(--cm-clay)]"
|
||||||
|
style={{ fontFamily: "var(--cm-font-sans)" }}
|
||||||
|
>
|
||||||
|
<span className="border-b border-dashed border-[var(--cm-fg-tertiary)] pb-0.5 transition-colors group-hover:border-[var(--cm-clay)]">
|
||||||
|
Read the full changelog
|
||||||
|
</span>
|
||||||
|
<span className="transition-transform duration-300 group-hover:translate-x-1">
|
||||||
|
→
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</Reveal>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -85,6 +85,23 @@ const MILESTONES = [
|
|||||||
],
|
],
|
||||||
stat: "43 MCP tools total",
|
stat: "43 MCP tools total",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
version: "v0.9 → 1.34",
|
||||||
|
phase: "Daemon · multi-mesh · multi-session",
|
||||||
|
color: "var(--cm-cactus)",
|
||||||
|
items: [
|
||||||
|
"Persistent daemon — long-lived broker WS, durable outbox/inbox",
|
||||||
|
"Universal multi-mesh daemon — one process, every joined mesh",
|
||||||
|
"Per-session IPC tokens — auto-scope to the launched session",
|
||||||
|
"Per-session broker presence — sibling sessions see each other",
|
||||||
|
"Self-healing daemon lifecycle (auto-spawn, version probe)",
|
||||||
|
"Multi-session correctness train — per-recipient SSE demux + inbox scoping",
|
||||||
|
"Refuse-to-kick on control-plane (no more no-op kicks)",
|
||||||
|
"Caller-stable idempotency on every send",
|
||||||
|
"Stale CLAUDEMESH_CONFIG_DIR fallback",
|
||||||
|
],
|
||||||
|
stat: "1.34.15 shipped",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const Timeline = () => {
|
export const Timeline = () => {
|
||||||
@@ -94,7 +111,7 @@ export const Timeline = () => {
|
|||||||
<section className="border-b border-[var(--cm-border)] bg-[var(--cm-bg)] px-6 py-24 md:px-12 md:py-32">
|
<section className="border-b border-[var(--cm-border)] bg-[var(--cm-bg)] px-6 py-24 md:px-12 md:py-32">
|
||||||
<div className="mx-auto max-w-[var(--cm-max-w)]">
|
<div className="mx-auto max-w-[var(--cm-max-w)]">
|
||||||
<Reveal className="mb-6 flex justify-center">
|
<Reveal className="mb-6 flex justify-center">
|
||||||
<SectionIcon glyph="layers" />
|
<SectionIcon glyph="grid" />
|
||||||
</Reveal>
|
</Reveal>
|
||||||
<Reveal delay={1}>
|
<Reveal delay={1}>
|
||||||
<h2
|
<h2
|
||||||
@@ -109,7 +126,8 @@ export const Timeline = () => {
|
|||||||
className="mx-auto mt-4 max-w-xl text-center text-[15px] leading-[1.6] text-[var(--cm-fg-secondary)]"
|
className="mx-auto mt-4 max-w-xl text-center text-[15px] leading-[1.6] text-[var(--cm-fg-secondary)]"
|
||||||
style={{ fontFamily: "var(--cm-font-sans)" }}
|
style={{ fontFamily: "var(--cm-font-sans)" }}
|
||||||
>
|
>
|
||||||
66 npm releases. Every feature below is in production today.
|
120+ npm releases through v1.34.15. Every feature below is in
|
||||||
|
production today.
|
||||||
</p>
|
</p>
|
||||||
</Reveal>
|
</Reveal>
|
||||||
|
|
||||||
@@ -210,8 +228,8 @@ export const Timeline = () => {
|
|||||||
className="text-[14px] text-[var(--cm-fg-tertiary)]"
|
className="text-[14px] text-[var(--cm-fg-tertiary)]"
|
||||||
style={{ fontFamily: "var(--cm-font-serif)" }}
|
style={{ fontFamily: "var(--cm-font-serif)" }}
|
||||||
>
|
>
|
||||||
Daemon redesign · per-topic encryption · self-host
|
HKDF cross-machine identity · session capabilities · A2A
|
||||||
packaging · federation
|
interop · self-host packaging · federation
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user