feat(web): refresh marketing site — accurate timeline, live changelog, cross-boundary positioning
Some checks failed
CI / Typecheck (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Broker tests (Postgres) (push) Has been cancelled
CI / Docker build (linux/amd64) (push) Has been cancelled

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:
Alejandro Gutiérrez
2026-05-04 22:55:30 +01:00
parent 7f61a711f1
commit 64d9f9f6f9
6 changed files with 487 additions and 51 deletions

View File

@@ -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 = {
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() {
return (
<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
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)" }}
>
Changelog
</h1>
<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)" }}
>
Every shipped version of claudemesh-cli.
</p>
<div className="mt-12 space-y-8">
{ENTRIES.map((entry) => (
<article key={entry.version} className="border-b border-[var(--cm-border)] pb-6">
<div className="flex items-center gap-3">
<span
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)" }}
Hand-picked, load-bearing ships from{" "}
<span className="text-[var(--cm-fg)]">v0.1.0</span> through{" "}
<span className="text-[var(--cm-clay)]">v1.34.15</span>. For the
byte-level diff, the canonical{" "}
<Link
href="https://github.com/alezmad/claudemesh/blob/main/apps/cli/CHANGELOG.md"
className="underline decoration-[var(--cm-fg-tertiary)] underline-offset-4 transition-colors hover:text-[var(--cm-fg)] hover:decoration-[var(--cm-clay)]"
>
{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 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}
</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
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>
</div>
<p className="mt-2 text-[14px] leading-[1.6] text-[var(--cm-fg-secondary)]" style={{ fontFamily: "var(--cm-font-sans)" }}>
</header>
<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}
</p>
</article>
))}
</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>
);
}

View File

@@ -3,6 +3,7 @@ import { Features } from "~/modules/marketing/home/features";
import { WhereMeshFits } from "~/modules/marketing/home/where-mesh-fits";
import { WhatIsClaudemesh } from "~/modules/marketing/home/what-is-claudemesh";
import { Timeline } from "~/modules/marketing/home/timeline";
import { LatestReleases } from "~/modules/marketing/home/latest-releases";
import { Pricing } from "~/modules/marketing/home/pricing";
import { FAQ } from "~/modules/marketing/home/faq";
import { CallToAction } from "~/modules/marketing/home/cta";
@@ -22,6 +23,7 @@ const HomePage = () => {
<WhereMeshFits />
<WhatIsClaudemesh />
<Timeline />
<LatestReleases count={5} />
<Pricing />
<FAQ />
<CallToAction />

View 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.01.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)",
};

View File

@@ -67,9 +67,10 @@ export const HeroWithMesh = () => {
textShadow: "0 2px 20px rgba(0,0,0,0.8)",
}}
>
Share context, files, skills, and MCPs across every Claude Code
session end-to-end encrypted. Hosted on claudemesh.com or
self-hosted in your VPC. Same CLI, same wire, your choice.
The encrypted backbone where Claude Code sessions, autonomous
agents, and humans coordinate across machines, across users,
across organizations. Hosted on claudemesh.com or self-hosted in
your VPC. Same CLI, same wire, your choice.
</p>
</Reveal>

View 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>
);
};

View File

@@ -85,6 +85,23 @@ const MILESTONES = [
],
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 = () => {
@@ -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">
<div className="mx-auto max-w-[var(--cm-max-w)]">
<Reveal className="mb-6 flex justify-center">
<SectionIcon glyph="layers" />
<SectionIcon glyph="grid" />
</Reveal>
<Reveal delay={1}>
<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)]"
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>
</Reveal>
@@ -210,8 +228,8 @@ export const Timeline = () => {
className="text-[14px] text-[var(--cm-fg-tertiary)]"
style={{ fontFamily: "var(--cm-font-serif)" }}
>
Daemon redesign · per-topic encryption · self-host
packaging · federation
HKDF cross-machine identity · session capabilities · A2A
interop · self-host packaging · federation
</span>
</div>
</div>