From 6afd6427a42e5bb0da33f92c91c81a7a890e27e7 Mon Sep 17 00:00:00 2001
From: Anthony Ettinger
Date: Sun, 8 Nov 2026 16:38:49 +0000
Subject: [PATCH 1/3] plugins page: mark unbuilt plugins coming soon, honest
install/default labels
Co-Authored-By: Claude Opus 5.5
---
apps/web/src/app/api/plugins/route.ts | 16 ++++++-
apps/web/src/app/plugins/page.tsx | 47 +++++++++++++++---
apps/web/src/lib/plugins.ts | 66 +++++++++++++++++++++++---
plugins/ad-generator-agent/module.toml | 1 +
plugins/ads-manager/module.toml | 1 +
plugins/coinpay/module.toml | 1 +
plugins/crawl/module.toml | 28 +++++------
plugins/ctv-ads/module.toml | 1 +
plugins/diffusion/module.toml | 2 +
plugins/embed/module.toml | 1 +
plugins/gameserver/module.toml | 1 +
plugins/hosting/module.toml | 1 +
plugins/infernet/module.toml | 2 +
plugins/live-stream/module.toml | 1 +
plugins/ocr/module.toml | 1 +
plugins/podcast-ads/module.toml | 1 +
plugins/podcasting/module.toml | 1 +
plugins/podcasts/module.toml | 1 +
plugins/render/module.toml | 1 +
plugins/secure-chat/module.toml | 2 +
plugins/storage/module.toml | 2 +
plugins/train/module.toml | 1 +
plugins/transcode/module.toml | 2 +
plugins/tts/module.toml | 2 +
plugins/video/module.toml | 2 +
plugins/webhook/module.toml | 2 +
plugins/whisper/module.toml | 2 +
plugins/workflow-step/module.toml | 2 +
28 files changed, 159 insertions(+), 32 deletions(-)
diff --git a/apps/web/src/app/api/plugins/route.ts b/apps/web/src/app/api/plugins/route.ts
index cf89594b..f3c7073d 100644
--- a/apps/web/src/app/api/plugins/route.ts
+++ b/apps/web/src/app/api/plugins/route.ts
@@ -12,6 +12,7 @@ import {
loadAllPlugins,
tagline,
installCommand,
+ installedByDefault,
modelOptions,
} from "@/lib/plugins";
@@ -20,19 +21,30 @@ export function GET() {
// Omitted rather than sent as [] for the plugins that have no model to
// choose, which is most of them.
const models = modelOptions(p).map(({ id, model }) => ({ id, ...model }));
+ const install = installCommand(p);
return {
id: p.id,
name: p.name,
version: p.version,
kind: p.kind,
+ // available | partial | coming-soon. A coming-soon plugin is a spec
+ // with no implementation behind it yet.
+ status: p.status,
+ status_note: p.statusNote,
+ builtin: p.builtin,
+ installed_by_default: installedByDefault(p),
tagline: tagline(p),
description: p.description,
keywords: p.keywords ?? [],
homepage: p.homepage,
source: p.source,
- install_command: installCommand(p),
- install_url: `https://c0mpute.com/plugins/${p.id}/install.sh`,
+ // null when there is nothing to install: built in, coming soon, or no
+ // install.sh in the repo.
+ install_command: install,
+ install_url: install
+ ? `https://c0mpute.com/plugins/${p.id}/install.sh`
+ : null,
web: `https://c0mpute.com/plugins/${p.id}`,
models: models.length > 0 ? models : undefined,
};
diff --git a/apps/web/src/app/plugins/page.tsx b/apps/web/src/app/plugins/page.tsx
index 1bacaa1d..556f91b1 100644
--- a/apps/web/src/app/plugins/page.tsx
+++ b/apps/web/src/app/plugins/page.tsx
@@ -6,6 +6,7 @@ import {
byCategory,
tagline,
installCommand,
+ installedByDefault,
modelOptions,
CATEGORY_LABELS,
CATEGORY_BLURBS,
@@ -64,6 +65,12 @@ export default function PluginsPage() {
is a product built on{" "}
c0mpute — useful, and not something the protocol depends on.
+
+ runs today with a caveat noted on the
+ card.{" "}
+ is a published spec with no
+ implementation yet — nothing to install or run.
+
{groups.map(({ category, plugins }) => (
@@ -74,6 +81,8 @@ export default function PluginsPage() {
{" "}
· {plugins.length}
+ {comingSoonCount(plugins) > 0 &&
+ ` (${comingSoonCount(plugins)} coming soon)`}
@@ -119,6 +128,10 @@ function kindLabel(p: PluginManifest): string {
return p.category === "applications" ? "application" : "service";
}
+function comingSoonCount(plugins: PluginManifest[]): number {
+ return plugins.filter((p) => p.status === "coming-soon").length;
+}
+
function Badge({ label }: { label: string }) {
return (
@@ -134,15 +147,27 @@ function PluginCard({ p }: { p: PluginManifest }) {
: p.dispatch?.mode === "container"
? "container"
: "subprocess";
+ const comingSoon = p.status === "coming-soon";
+ const install = installCommand(p);
return (
-
+
[
{p.id}
]{" "}
{p.name}
+ {p.status !== "available" && (
+ <>
+ {" "}
+
+
+
+ >
+ )}
v{p.version} · {kindLabel(p)} · {dispatchLabel}
@@ -161,14 +186,24 @@ function PluginCard({ p }: { p: PluginManifest }) {
- {p.dispatch?.mode === "in-process" ? (
- ships with c0mpute · installed by default
- ) : (
- {`$ ${installCommand(p)}`}
+ {p.status === "partial" && p.statusNote && (
+
+ partial: {p.statusNote}
+
)}
+ {comingSoon ? (
+
+ coming soon · spec only, not yet implemented
+
+ ) : installedByDefault(p) ? (
+ ships with c0mpute · installed by default
+ ) : install ? (
+ {`$ ${install}`}
+ ) : null}
+