Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions web/app/[locale]/components/site-footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,17 @@ export async function SiteFooter() {
<div className="flex items-center justify-between mt-10">
<p className="text-xs text-muted">
{t("copyright", { year })}
<span aria-hidden className="mx-2">
·
</span>
<a
href="https://github.com/manaflow-ai/cmux"
target="_blank"
rel="noopener noreferrer"
className="hover:text-foreground transition-colors"
>
{t("openSource")}
</a>
</p>
<LanguageSwitcher />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { useTranslations } from "next-intl";
import { getTranslations } from "next-intl/server";
import { CodeBlock } from "../../../components/code-block";
import { DocsHeading } from "../../../components/docs-heading";
import { buildAlternates } from "../../../../../i18n/seo";

export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
const t = await getTranslations({ locale, namespace: "docs.claudeCodeTeams" });
return {
title: t("metaTitle"),
description: t("metaDescription"),
alternates: buildAlternates(locale, "/docs/agent-integrations/claude-code-teams"),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { useTranslations } from "next-intl";
import { getTranslations } from "next-intl/server";
import { CodeBlock } from "../../../components/code-block";
import { DocsHeading } from "../../../components/docs-heading";
import { buildAlternates } from "../../../../../i18n/seo";

export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
const t = await getTranslations({ locale, namespace: "docs.ohMyClaudeCode" });
return {
title: t("metaTitle"),
description: t("metaDescription"),
alternates: buildAlternates(locale, "/docs/agent-integrations/oh-my-claudecode"),
};
}

Expand Down
2 changes: 2 additions & 0 deletions web/app/[locale]/docs/agent-integrations/oh-my-codex/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { useTranslations } from "next-intl";
import { getTranslations } from "next-intl/server";
import { CodeBlock } from "../../../components/code-block";
import { DocsHeading } from "../../../components/docs-heading";
import { buildAlternates } from "../../../../../i18n/seo";

export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
const t = await getTranslations({ locale, namespace: "docs.ohMyCodex" });
return {
title: t("metaTitle"),
description: t("metaDescription"),
alternates: buildAlternates(locale, "/docs/agent-integrations/oh-my-codex"),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { useTranslations } from "next-intl";
import { getTranslations } from "next-intl/server";
import { CodeBlock } from "../../../components/code-block";
import { DocsHeading } from "../../../components/docs-heading";
import { buildAlternates } from "../../../../../i18n/seo";

export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
const t = await getTranslations({ locale, namespace: "docs.ohMyOpenCode" });
return {
title: t("metaTitle"),
description: t("metaDescription"),
alternates: buildAlternates(locale, "/docs/agent-integrations/oh-my-opencode"),
};
}

Expand Down
6 changes: 4 additions & 2 deletions web/app/[locale]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,11 @@ export default async function LocaleLayout({
url: "https://cmux.com",
downloadUrl: DOWNLOAD_URL,
description:
"Native macOS terminal built on Ghostty. Works with Claude Code, Codex, OpenCode, Gemini CLI, Kiro, Aider, and any CLI tool. Vertical tabs, notification rings, split panes, and a socket API.",
"Free and open source native macOS terminal built on Ghostty. Works with Claude Code, Codex, OpenCode, Gemini CLI, Kiro, Aider, and any CLI tool. Vertical tabs, notification rings, split panes, and a socket API.",
keywords:
"terminal, macOS, Claude Code, Codex, OpenCode, Gemini CLI, Kiro, Aider, AI coding agents, Ghostty",
"terminal, macOS, open source terminal, Claude Code, Codex, OpenCode, Gemini CLI, Kiro, Aider, AI coding agents, Ghostty",
isAccessibleForFree: true,
license: "https://github.com/manaflow-ai/cmux/blob/main/LICENSE",
offers: { "@type": "Offer", price: "0", priceCurrency: "USD" },
};
const jsonLdScript = JSON.stringify(jsonLd).replace(/</g, "\\u003c");
Expand Down
181 changes: 179 additions & 2 deletions web/app/[locale]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function HomeContent() {
</span>
</p>
<p
className="text-base text-muted"
className="text-base text-muted lg:-mr-32 xl:-mr-48"
data-dev="subtitle"
style={{ lineHeight: 1.5 }}
>
Expand Down Expand Up @@ -106,6 +106,7 @@ function HomeContent() {
["scriptable", "scriptableDesc"],
["gpuAccelerated", "gpuAcceleratedDesc"],
["lightweight", "lightweightDesc"],
["openSource", "openSourceDesc"],
] as const
).map(([title, desc]) => (
<li key={title} className="flex gap-3">
Expand Down Expand Up @@ -183,10 +184,49 @@ function HomeContent() {
<p className="font-medium mb-1">{t("faqPlatformQ")}</p>
<p className="text-muted">{t("faqPlatformA")}</p>
</div>
<div>
<p className="font-medium mb-1">{t("faqIosQ")}</p>
<p className="text-muted">{t("faqIosA")}</p>
</div>
<div>
<p className="font-medium mb-1">{t("faqAgentsQ")}</p>
<p className="text-muted">{t("faqAgentsA")}</p>
</div>
<div>
<p className="font-medium mb-1">{t("faqOrchestrationQ")}</p>
<p className="text-muted">
{t.rich("faqOrchestrationA", {
teamsLink: (chunks) => (
<Link
href="/docs/agent-integrations/claude-code-teams"
className={linkClass}
>
{chunks}
</Link>
),
omoLink: (chunks) => (
<Link
href="/docs/agent-integrations/oh-my-opencode"
className={linkClass}
>
{chunks}
</Link>
),
})}
</p>
</div>
<div>
<p className="font-medium mb-1">{t("faqRemoteQ")}</p>
<p className="text-muted">
{t.rich("faqRemoteA", {
link: (chunks) => (
<Link href="/docs/ssh" className={linkClass}>
{chunks}
</Link>
),
})}
</p>
</div>
<div>
<p className="font-medium mb-1">{t("faqNotificationsQ")}</p>
<p className="text-muted">
Expand All @@ -204,6 +244,55 @@ function HomeContent() {
})}
</p>
</div>
<div>
<p className="font-medium mb-1">{t("faqScriptableQ")}</p>
<p className="text-muted">
{t.rich("faqScriptableA", {
cliLink: (chunks) => (
<Link href="/docs/api" className={linkClass}>
{chunks}
</Link>
),
browserLink: (chunks) => (
<Link href="/docs/browser-automation" className={linkClass}>
{chunks}
</Link>
),
})}
</p>
</div>
<div>
<p className="font-medium mb-1">{t("faqBrowserQ")}</p>
<p className="text-muted">
{t.rich("faqBrowserA", {
link: (chunks) => (
<Link href="/docs/browser-automation" className={linkClass}>
{chunks}
</Link>
),
})}
</p>
</div>
<div>
<p className="font-medium mb-1">{t("faqSkillsQ")}</p>
<p className="text-muted">
{t.rich("faqSkillsA", {
skillsLink: (chunks) => (
<a
href="https://github.com/manaflow-ai/cmux-skills"
className={linkClass}
>
{chunks}
</a>
),
link: (chunks) => (
<Link href="/docs/skills" className={linkClass}>
{chunks}
</Link>
),
})}
</p>
</div>
<div>
<p className="font-medium mb-1">{t("faqShortcutsQ")}</p>
<p className="text-muted">
Expand All @@ -221,9 +310,51 @@ function HomeContent() {
})}
</p>
</div>
<div>
<p className="font-medium mb-1">{t("faqCustomizeQ")}</p>
<p className="text-muted">
{t.rich("faqCustomizeA", {
path: (chunks) => (
<code className="text-xs bg-code-bg px-1.5 py-0.5 rounded">
{chunks}
</code>
),
shortcutsLink: (chunks) => (
<Link href="/docs/keyboard-shortcuts" className={linkClass}>
{chunks}
</Link>
),
link: (chunks) => (
<Link href="/docs/configuration" className={linkClass}>
{chunks}
</Link>
),
})}
</p>
</div>
<div>
<p className="font-medium mb-1">{t("faqSessionsQ")}</p>
<p className="text-muted">
{t.rich("faqSessionsA", {
link: (chunks) => (
<Link href="/docs/session-restore" className={linkClass}>
{chunks}
</Link>
),
})}
</p>
</div>
<div>
<p className="font-medium mb-1">{t("faqTmuxQ")}</p>
<p className="text-muted">{t("faqTmuxA")}</p>
<p className="text-muted">
{t.rich("faqTmuxA", {
link: (chunks) => (
<Link href="/docs/remote-tmux" className={linkClass}>
{chunks}
</Link>
),
})}
</p>
</div>
<div>
<p className="font-medium mb-1">{t("faqFreeQ")}</p>
Expand All @@ -240,6 +371,52 @@ function HomeContent() {
})}
</p>
</div>
<div>
<p className="font-medium mb-1">{t("faqSupportQ")}</p>
<p className="text-muted">
{t.rich("faqSupportA", {
foundersLink: (chunks) => (
<a
href="https://github.com/manaflow-ai/cmux#founders-edition"
className={linkClass}
>
{chunks}
</a>
),
})}
</p>
</div>
<div>
<p className="font-medium mb-1">{t("faqFeatureQ")}</p>
<p className="text-muted">
{t.rich("faqFeatureA", {
issuesLink: (chunks) => (
<a
href="https://github.com/manaflow-ai/cmux/issues"
className={linkClass}
>
{chunks}
</a>
),
prLink: (chunks) => (
<a
href="https://github.com/manaflow-ai/cmux/pulls"
className={linkClass}
>
{chunks}
</a>
),
mailLink: (chunks) => (
<a
href="mailto:founders@manaflow.com?subject=%5Bcmux%20feature%20request%20landing%5D&body=Hi%20cmux%20team%2C%20"
className={linkClass}
>
{chunks}
</a>
),
})}
</p>
</div>
</div>
</section>

Expand Down
33 changes: 32 additions & 1 deletion web/app/lib/agent-page-paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,38 @@ export function buildLlmsText(origin: string): string {
const lines = [
"# cmux",
"",
"Native macOS terminal built on Ghostty for running multiple AI coding agents.",
"> cmux is a free and open source (GPL), fully scriptable native macOS terminal built on libghostty, purpose-built for running AI coding agents. Every action is available through a CLI and a Unix socket API, so agents can drive the terminal itself. It works with the CLI agents you already use (Claude Code, Codex, OpenCode, Gemini CLI, Aider, and any CLI tool) and adds workspace organization, agent notification rings, and vertical tabs on top of a GPU-accelerated terminal.",
"",
"## What cmux is",
"",
"- Native macOS app: written in Swift and AppKit with no Electron, built on libghostty (the Ghostty engine) for GPU-accelerated rendering.",
"- Agent-first: run many AI coding agents in parallel, each in its own workspace, instead of juggling one terminal.",
"- Notification rings: a pane lights up the moment an agent needs your attention, so you are not babysitting prompts.",
"- Workspace organization: a vertical sidebar groups work by workspace, each showing its git branch, working directory, ports, and the latest line of agent output.",
"- Vertical tabs: tabs live in the sidebar instead of a cramped top bar, scaling to dozens of concurrent sessions.",
"- Agent-agnostic and open source (GPL): bring your own agent, no required account to use the terminal.",
"",
"## Programmable",
"",
"cmux is designed to be driven by scripts and agents, not just used by hand. Every command is available through both a `cmux` CLI and a Unix socket, so anything an agent has in its PATH can control the running app:",
"",
"- Control the app: create and switch workspaces, open split panes and surfaces, send input to a terminal, read screen contents, and capture screenshots over the socket API.",
"- Browser automation: open an in-app browser surface and drive it programmatically (navigate, snapshot the DOM, click, type, fill, wait, evaluate JavaScript, inspect console and network, manage cookies and storage), so agents can verify web changes in the same terminal.",
"- Hooks: run your own commands on cmux events to wire it into other tools and notification pipelines.",
"- Skills and custom commands: package reusable agent workflows and bind them to commands.",
"- Sidebar metadata and notifications are scriptable, so external processes can update workspace status and ring panes.",
"",
"## Key facts",
"",
"- Platform: macOS",
"- License: GPL, free to download",
"- Built on: libghostty (the Ghostty terminal engine)",
"- Works with: Claude Code, Codex, OpenCode, Gemini CLI, Aider, and any CLI tool",
"- Automation: `cmux` CLI and Unix socket API, browser automation, hooks, skills, and custom commands",
`- Download: ${origin}/download`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Broken download URL in llms.txt

Medium Severity

buildLlmsText advertises - Download: ${origin}/download, but the app only defines /download/confirmation (with optional dl=1), not a /download page. Crawlers and LLMs that follow that link get a 404 instead of the download flow.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b11493a. Configure here.

"- Source: https://github.com/manaflow-ai/cmux",
"",
"## Page variants",
"",
"Every public HTML page supports Markdown and plain-text variants by appending `.md` or `.txt` to the page path. Text variants include `X-Robots-Tag: noindex, follow` and a canonical link header so search engines keep indexing the canonical HTML page.",
"",
Expand Down
Loading