Add cmux omo command for oh-my-openagent integration (#2087)
* Add `cmux omo` command for OpenCode + oh-my-openagent integration Same pattern as `cmux claude-teams`: creates a tmux shim so oh-my-openagent's TmuxSessionManager spawns agents as native cmux splits instead of tmux panes. Sets TMUX/TMUX_PANE env vars, prepends shim to PATH, and execs into opencode. Closes https://github.com/manaflow-ai/cmux/issues/2085 * Auto-install oh-my-opencode plugin when running cmux omo Before launching opencode, cmux omo now: - Checks if oh-my-opencode is registered in ~/.config/opencode/opencode.json - If not, creates/updates the config with the plugin entry - Checks if the npm package is installed in node_modules - If not, runs bun add (or npm install) to install it - Then proceeds with tmux shim setup and exec * Use shadow config dir to avoid modifying user's opencode setup Instead of writing directly to ~/.config/opencode/opencode.json, cmux omo now creates a shadow config at ~/.cmuxterm/omo-config/ that layers oh-my-opencode on top of the user's existing config. Symlinks node_modules, package.json, bun.lock, and plugin config from the original dir. Sets OPENCODE_CONFIG_DIR to the shadow directory. Running plain `opencode` remains unaffected. * Add Agent Integrations docs section with Claude Code Teams and oh-my-opencode pages Adds sectioned sidebar navigation to the docs site. The new Agent Integrations section contains separate pages for cmux claude-teams and cmux omo, documenting usage, tmux shim mechanics, directory layout, environment variables, and the shadow config approach. Both pages include a nightly-only warning. Full English and Japanese translations, nav item keys added to all 19 locales. * Remove uppercase from sidebar section headers * Add more spacing above and below sidebar section headers * Enable tmux mode in oh-my-opencode config, improve docs - cmux omo now writes tmux.enabled=true to the shadow oh-my-opencode.json config. Without this, oh-my-openagent's TmuxSessionManager won't spawn visual panes even though $TMUX is set (the config defaults to false). - Nightly warnings now link to /nightly instead of generic text. - Added "What you get" section to oh-my-opencode docs explaining the visual pane behavior (auto-layout, idle cleanup, queueing). - Added tmux.enabled step to first-run and how-it-works sections. * Add terminal-notifier shim to route oh-my-openagent notifications to cmux oh-my-openagent sends macOS notifications via terminal-notifier (args: -title <t> -message <m> [-activate <id>]). The shim in ~/.cmuxterm/omo-bin/terminal-notifier intercepts these calls and routes them through cmux notify, so notifications appear in cmux's sidebar panel instead of as raw macOS notifications. * Add pane geometry to tmux-compat for oh-my-openagent grid planning oh-my-openagent's TmuxSessionManager needs pane geometry (columns, rows, position, window dimensions) to decide where to spawn agent panes. Without this data, agents run headlessly. Server side: - pane.list v2 response now includes pixel_frame, cell_size, columns, rows per pane, plus container_frame at the top level - Uses BonsplitController.layoutSnapshot() for pixel geometry and ghostty_surface_size() for terminal grid dimensions CLI side: - tmuxEnrichContextWithGeometry() computes character-cell positions from pixel frames and cell dimensions for tmux format variables (pane_width, pane_height, pane_left, pane_top, pane_active, window_width, window_height) - list-panes now resolves pane targets (%uuid) via tmuxResolvePaneTarget instead of failing with "Workspace not found" - display-message enriched with geometry for format strings like #{pane_width},#{window_width} - tmux -V now returns "tmux 3.4" (needed by oh-my-openagent's tmux-path-resolver verification) * Add socket tests for tmux-compat pane geometry 6 tests verifying the geometry enrichment works end-to-end: - pane.list returns pixel_frame, columns, rows, cell_size, container_frame - tmux -V returns version string - list-panes -F renders geometry format variables as integers - list-panes -t %<uuid> resolves pane targets - display -p renders pane_width and window_width - After split, two panes have different positions and halved widths All 6 pass on macmini (cmux-macmini). * Handle tmux -V in shim script directly (no socket needed) oh-my-openagent's tmux-path-resolver runs tmux -V to verify the binary works. The __tmux-compat handler requires a socket connection, which may not be established at verification time. Handle -V in the bash shim directly to avoid the socket dependency. * Lower default tmux pane min widths for cmux omo oh-my-openagent defaults: main_pane_min_width=120, agent_pane_min_width=40, requiring 161+ columns. Most terminal windows are narrower, causing decideSpawnActions to return canSpawn=false and defer agents forever. cmux omo now sets: main_pane_min_width=60, agent_pane_min_width=30, main_pane_size=50, requiring only 91 columns. Also moved tmux -V handling into the bash shim to avoid needing a socket connection for the version check. * Resolve merge conflicts with main (main-vertical layout, focus param) - Keep upstream main-vertical layout anchoring from #2119 - Keep upstream focus param (v2Bool) instead of no_focus - Combine with our -d flag handling: -d sets focus=false - Include customCommands nav item from main * Implement select-layout equalize and resize-pane absolute width When oh-my-openagent spawns agent panes, it calls select-layout main-vertical after each split to redistribute panes evenly, then resize-pane -x <columns> to set the main pane width. Both were previously no-ops, causing cascading uneven splits. Server side: - Add workspace.equalize_splits v2 API that calls the existing TabManager.equalizeSplits (sets all dividers to 0.5) CLI side: - select-layout now calls workspace.equalize_splits before tracking main-vertical state - resize-pane -x <columns> without directional flags now computes the pixel delta from current to desired width and resizes accordingly * Fix equalize to use proportional divider positions The previous equalize set all dividers to 0.5, which in a right- recursive binary tree (from successive splits) gives 50/25/12.5/6.25% instead of equal sizes. New algorithm counts leaf panes on each side of each split and sets the divider to N_left / (N_left + N_right). For 5 panes in a chain: 1/5, 1/4, 1/3, 1/2, giving each pane exactly 20%. * Fix select-layout main-vertical to only equalize vertical splits The proportional equalize was treating the top-level horizontal split (main vs agent column) the same as vertical splits, setting the main pane to 1/6 of the window with 5 agents. For main-vertical layout, only equalize vertical splits (the agent column), leaving the horizontal main/agent divider untouched. The subsequent resize-pane -x handles the main pane width. workspace.equalize_splits now accepts an optional orientation filter ("vertical" or "horizontal") to scope which splits get equalized. * Re-equalize agent column after kill-pane * Address PR review comments - Fix cmux omo --help: remove omo from the help-bypass guard so --help shows usage text instead of trying to launch opencode - Don't overwrite unreadable opencode.json: fail with an error instead of silently resetting to empty config - Drain installer pipes concurrently before waitUntilExit to prevent deadlock from full pipe buffers during bun/npm install --------- Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
This commit is contained in:
parent
ee3460b8d7
commit
84af32c56e
29 changed files with 1421 additions and 61 deletions
|
|
@ -1,11 +1,31 @@
|
|||
export const navItems = [
|
||||
{ titleKey: "gettingStarted" as const, href: "/docs/getting-started" },
|
||||
{ titleKey: "concepts" as const, href: "/docs/concepts" },
|
||||
{ titleKey: "configuration" as const, href: "/docs/configuration" },
|
||||
{ titleKey: "customCommands" as const, href: "/docs/custom-commands" },
|
||||
{ titleKey: "keyboardShortcuts" as const, href: "/docs/keyboard-shortcuts" },
|
||||
{ titleKey: "apiReference" as const, href: "/docs/api" },
|
||||
{ titleKey: "browserAutomation" as const, href: "/docs/browser-automation" },
|
||||
{ titleKey: "notifications" as const, href: "/docs/notifications" },
|
||||
{ titleKey: "changelog" as const, href: "/docs/changelog" },
|
||||
export type NavLink = { titleKey: string; href: string };
|
||||
export type NavSection = { sectionKey: string; children: NavLink[] };
|
||||
export type NavEntry = NavLink | NavSection;
|
||||
|
||||
export function isSection(entry: NavEntry): entry is NavSection {
|
||||
return "sectionKey" in entry;
|
||||
}
|
||||
|
||||
/** Flatten sections into an ordered list of links (for pager prev/next). */
|
||||
export function flatNavItems(entries: NavEntry[]): NavLink[] {
|
||||
return entries.flatMap((e) => (isSection(e) ? e.children : [e]));
|
||||
}
|
||||
|
||||
export const navItems: NavEntry[] = [
|
||||
{ titleKey: "gettingStarted", href: "/docs/getting-started" },
|
||||
{ titleKey: "concepts", href: "/docs/concepts" },
|
||||
{ titleKey: "configuration", href: "/docs/configuration" },
|
||||
{ titleKey: "customCommands", href: "/docs/custom-commands" },
|
||||
{ titleKey: "keyboardShortcuts", href: "/docs/keyboard-shortcuts" },
|
||||
{ titleKey: "apiReference", href: "/docs/api" },
|
||||
{ titleKey: "browserAutomation", href: "/docs/browser-automation" },
|
||||
{ titleKey: "notifications", href: "/docs/notifications" },
|
||||
{
|
||||
sectionKey: "agentIntegrations",
|
||||
children: [
|
||||
{ titleKey: "claudeCodeTeams", href: "/docs/agent-integrations/claude-code-teams" },
|
||||
{ titleKey: "ohMyOpenCode", href: "/docs/agent-integrations/oh-my-opencode" },
|
||||
],
|
||||
},
|
||||
{ titleKey: "changelog", href: "/docs/changelog" },
|
||||
];
|
||||
|
|
|
|||
|
|
@ -2,14 +2,15 @@
|
|||
|
||||
import { useTranslations } from "next-intl";
|
||||
import { Link, usePathname } from "../../../i18n/navigation";
|
||||
import { navItems } from "./docs-nav-items";
|
||||
import { navItems, flatNavItems } from "./docs-nav-items";
|
||||
|
||||
export function DocsPager() {
|
||||
const pathname = usePathname();
|
||||
const t = useTranslations("docs.navItems");
|
||||
const index = navItems.findIndex((item) => item.href === pathname);
|
||||
const prev = index > 0 ? navItems[index - 1] : null;
|
||||
const next = index < navItems.length - 1 ? navItems[index + 1] : null;
|
||||
const flat = flatNavItems(navItems);
|
||||
const index = flat.findIndex((item) => item.href === pathname);
|
||||
const prev = index > 0 ? flat[index - 1] : null;
|
||||
const next = index < flat.length - 1 ? flat[index + 1] : null;
|
||||
|
||||
if (!prev && !next) return null;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,38 @@
|
|||
|
||||
import { useTranslations } from "next-intl";
|
||||
import { Link, usePathname } from "../../../i18n/navigation";
|
||||
import { navItems } from "./docs-nav-items";
|
||||
import { navItems, isSection, type NavLink } from "./docs-nav-items";
|
||||
|
||||
function SidebarLink({
|
||||
item,
|
||||
pathname,
|
||||
onNavigate,
|
||||
indent,
|
||||
t,
|
||||
}: {
|
||||
item: NavLink;
|
||||
pathname: string;
|
||||
onNavigate?: () => void;
|
||||
indent?: boolean;
|
||||
t: (key: string) => string;
|
||||
}) {
|
||||
const active = pathname === item.href;
|
||||
return (
|
||||
<Link
|
||||
href={item.href}
|
||||
onClick={onNavigate}
|
||||
className={`block py-1.5 text-[14px] rounded-md transition-colors ${
|
||||
indent ? "px-5" : "px-3"
|
||||
} ${
|
||||
active
|
||||
? "text-foreground font-medium bg-code-bg"
|
||||
: "text-muted hover:text-foreground"
|
||||
}`}
|
||||
>
|
||||
{t(item.titleKey)}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
export function DocsSidebar({ onNavigate }: { onNavigate?: () => void }) {
|
||||
const pathname = usePathname();
|
||||
|
|
@ -10,21 +41,34 @@ export function DocsSidebar({ onNavigate }: { onNavigate?: () => void }) {
|
|||
|
||||
return (
|
||||
<nav className="space-y-0.5">
|
||||
{navItems.map((item) => {
|
||||
const active = pathname === item.href;
|
||||
{navItems.map((entry) => {
|
||||
if (isSection(entry)) {
|
||||
return (
|
||||
<div key={entry.sectionKey} className="pt-5 pb-2 first:pt-0">
|
||||
<div className="px-3 pb-1 text-[12px] font-medium text-muted tracking-wider">
|
||||
{t(entry.sectionKey)}
|
||||
</div>
|
||||
{entry.children.map((child) => (
|
||||
<SidebarLink
|
||||
key={child.href}
|
||||
item={child}
|
||||
pathname={pathname}
|
||||
onNavigate={onNavigate}
|
||||
indent
|
||||
t={t}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
onClick={onNavigate}
|
||||
className={`block px-3 py-1.5 text-[14px] rounded-md transition-colors ${
|
||||
active
|
||||
? "text-foreground font-medium bg-code-bg"
|
||||
: "text-muted hover:text-foreground"
|
||||
}`}
|
||||
>
|
||||
{t(item.titleKey)}
|
||||
</Link>
|
||||
<SidebarLink
|
||||
key={entry.href}
|
||||
item={entry}
|
||||
pathname={pathname}
|
||||
onNavigate={onNavigate}
|
||||
t={t}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
import { useTranslations } from "next-intl";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import { CodeBlock } from "../../../components/code-block";
|
||||
import { Callout } from "../../../components/callout";
|
||||
import { Link } from "../../../../../i18n/navigation";
|
||||
|
||||
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"),
|
||||
};
|
||||
}
|
||||
|
||||
export default function ClaudeCodeTeamsPage() {
|
||||
const t = useTranslations("docs.claudeCodeTeams");
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1>{t("title")}</h1>
|
||||
|
||||
<Callout type="warn">
|
||||
{t.rich("nightlyWarning", {
|
||||
nightly: (chunks) => <Link href="/nightly" className="underline">{chunks}</Link>,
|
||||
})}
|
||||
</Callout>
|
||||
|
||||
<p>{t("intro")}</p>
|
||||
|
||||
<h2>{t("usage")}</h2>
|
||||
<CodeBlock lang="bash">{`cmux claude-teams
|
||||
cmux claude-teams --continue
|
||||
cmux claude-teams --model sonnet`}</CodeBlock>
|
||||
<p>{t("usageDesc")}</p>
|
||||
|
||||
<h2>{t("howItWorks")}</h2>
|
||||
<p>{t("howItWorksDesc")}</p>
|
||||
<ul>
|
||||
<li>{t("shimStep1")}</li>
|
||||
<li>{t("shimStep2")}</li>
|
||||
<li>{t("shimStep3")}</li>
|
||||
<li>{t("shimStep4")}</li>
|
||||
</ul>
|
||||
|
||||
<h2>{t("envVars")}</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{t("envVarName")}</th>
|
||||
<th>{t("envVarPurpose")}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td><code>TMUX</code></td><td>{t("envTmux")}</td></tr>
|
||||
<tr><td><code>TMUX_PANE</code></td><td>{t("envTmuxPane")}</td></tr>
|
||||
<tr><td><code>CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS</code></td><td>{t("envTeams")}</td></tr>
|
||||
<tr><td><code>CMUX_SOCKET_PATH</code></td><td>{t("envSocket")}</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>{t("directories")}</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{t("dirPath")}</th>
|
||||
<th>{t("dirPurpose")}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td><code>~/.cmuxterm/claude-teams-bin/</code></td><td>{t("dirShim")}</td></tr>
|
||||
<tr><td><code>~/.cmuxterm/tmux-compat-store.json</code></td><td>{t("dirStore")}</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>{t("tmuxCommands")}</h2>
|
||||
<p>{t("tmuxCommandsDesc")}</p>
|
||||
<ul>
|
||||
<li><code>new-session</code>, <code>new-window</code> → {t("mapWorkspace")}</li>
|
||||
<li><code>split-window</code> → {t("mapSplit")}</li>
|
||||
<li><code>send-keys</code> → {t("mapSendText")}</li>
|
||||
<li><code>capture-pane</code> → {t("mapReadText")}</li>
|
||||
<li><code>select-pane</code>, <code>select-window</code> → {t("mapFocus")}</li>
|
||||
<li><code>kill-pane</code>, <code>kill-window</code> → {t("mapClose")}</li>
|
||||
<li><code>list-panes</code>, <code>list-windows</code> → {t("mapList")}</li>
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
}
|
||||
108
web/app/[locale]/docs/agent-integrations/oh-my-opencode/page.tsx
Normal file
108
web/app/[locale]/docs/agent-integrations/oh-my-opencode/page.tsx
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
import { useTranslations } from "next-intl";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import { CodeBlock } from "../../../components/code-block";
|
||||
import { Callout } from "../../../components/callout";
|
||||
import { Link } from "../../../../../i18n/navigation";
|
||||
|
||||
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"),
|
||||
};
|
||||
}
|
||||
|
||||
export default function OhMyOpenCodePage() {
|
||||
const t = useTranslations("docs.ohMyOpenCode");
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1>{t("title")}</h1>
|
||||
|
||||
<Callout type="warn">
|
||||
{t.rich("nightlyWarning", {
|
||||
nightly: (chunks) => <Link href="/nightly" className="underline">{chunks}</Link>,
|
||||
})}
|
||||
</Callout>
|
||||
|
||||
<p>{t("intro")}</p>
|
||||
|
||||
<h2>{t("usage")}</h2>
|
||||
<CodeBlock lang="bash">{`cmux omo
|
||||
cmux omo --continue
|
||||
cmux omo --model claude-sonnet-4-6`}</CodeBlock>
|
||||
<p>{t("usageDesc")}</p>
|
||||
|
||||
<h2>{t("whatYouGet")}</h2>
|
||||
<p>{t("whatYouGetDesc")}</p>
|
||||
<ul>
|
||||
<li>{t("whatYouGet1")}</li>
|
||||
<li>{t("whatYouGet2")}</li>
|
||||
<li>{t("whatYouGet3")}</li>
|
||||
<li>{t("whatYouGet4")}</li>
|
||||
<li>{t("whatYouGet5")}</li>
|
||||
</ul>
|
||||
|
||||
<h2>{t("firstRun")}</h2>
|
||||
<p>{t("firstRunDesc")}</p>
|
||||
<ol>
|
||||
<li>{t("firstRunStep1")}</li>
|
||||
<li>{t("firstRunStep2")}</li>
|
||||
<li>{t("firstRunStep3")}</li>
|
||||
<li>{t("firstRunStep4")}</li>
|
||||
</ol>
|
||||
<p>{t("firstRunSafe")}</p>
|
||||
|
||||
<h2>{t("howItWorks")}</h2>
|
||||
<p>{t("howItWorksDesc")}</p>
|
||||
<ul>
|
||||
<li>{t("shimStep1")}</li>
|
||||
<li>{t("shimStep2")}</li>
|
||||
<li>{t("shimStep3")}</li>
|
||||
<li>{t("shimStep4")}</li>
|
||||
<li>{t("shimStep5")}</li>
|
||||
</ul>
|
||||
|
||||
<h2>{t("directories")}</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{t("dirPath")}</th>
|
||||
<th>{t("dirPurpose")}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td><code>~/.cmuxterm/omo-bin/</code></td><td>{t("dirShim")}</td></tr>
|
||||
<tr><td><code>~/.cmuxterm/omo-config/</code></td><td>{t("dirShadow")}</td></tr>
|
||||
<tr><td><code>~/.cmuxterm/tmux-compat-store.json</code></td><td>{t("dirStore")}</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>{t("shadowConfig")}</h2>
|
||||
<p>{t("shadowConfigDesc")}</p>
|
||||
<ul>
|
||||
<li>{t("shadowStep1")}</li>
|
||||
<li>{t("shadowStep2")}</li>
|
||||
<li>{t("shadowStep3")}</li>
|
||||
<li>{t("shadowStep4")}</li>
|
||||
</ul>
|
||||
|
||||
<h2>{t("envVars")}</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{t("envVarName")}</th>
|
||||
<th>{t("envVarPurpose")}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td><code>TMUX</code></td><td>{t("envTmux")}</td></tr>
|
||||
<tr><td><code>TMUX_PANE</code></td><td>{t("envTmuxPane")}</td></tr>
|
||||
<tr><td><code>OPENCODE_CONFIG_DIR</code></td><td>{t("envConfigDir")}</td></tr>
|
||||
<tr><td><code>CMUX_SOCKET_PATH</code></td><td>{t("envSocket")}</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -621,6 +621,9 @@
|
|||
"apiReference": "مرجع الواجهة البرمجية",
|
||||
"browserAutomation": "أتمتة المتصفح",
|
||||
"notifications": "الإشعارات",
|
||||
"agentIntegrations": "Agent Integrations",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "سجل التغييرات"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -621,6 +621,9 @@
|
|||
"apiReference": "API Referenca",
|
||||
"browserAutomation": "Automatizacija preglednika",
|
||||
"notifications": "Notifikacije",
|
||||
"agentIntegrations": "Agent Integrations",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "Zapisnik promjena"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -621,6 +621,9 @@
|
|||
"apiReference": "API-reference",
|
||||
"browserAutomation": "Browserautomatisering",
|
||||
"notifications": "Notifikationer",
|
||||
"agentIntegrations": "Agent Integrations",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "Ændringslog"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -621,6 +621,9 @@
|
|||
"apiReference": "API-Referenz",
|
||||
"browserAutomation": "Browser-Automatisierung",
|
||||
"notifications": "Benachrichtigungen",
|
||||
"agentIntegrations": "Agent Integrations",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "Changelog"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -612,6 +612,91 @@
|
|||
"metaTitle": "Changelog",
|
||||
"metaDescription": "cmux release notes and version history. New features, bug fixes, and changes for the native macOS terminal."
|
||||
},
|
||||
"claudeCodeTeams": {
|
||||
"title": "Claude Code Teams",
|
||||
"metaTitle": "Claude Code Teams - cmux",
|
||||
"metaDescription": "Run Claude Code with agent teams inside cmux. Teammate agents spawn as native cmux splits instead of tmux panes.",
|
||||
"nightlyWarning": "Available in <nightly>nightly builds</nightly> only.",
|
||||
"intro": "cmux claude-teams launches Claude Code with agent teams enabled. When Claude spawns teammate agents, they appear as native cmux splits instead of tmux panes, with full sidebar metadata and notifications.",
|
||||
"usage": "Usage",
|
||||
"usageDesc": "All arguments after claude-teams are forwarded to Claude Code. The command defaults teammate mode to auto and sets the environment so Claude uses cmux splits.",
|
||||
"howItWorks": "How it works",
|
||||
"howItWorksDesc": "cmux claude-teams creates a tmux shim script and configures the environment so Claude Code thinks it's running inside tmux. When Claude issues tmux commands to manage teammate panes, the shim translates them into cmux socket API calls.",
|
||||
"shimStep1": "Creates a tmux shim at ~/.cmuxterm/claude-teams-bin/tmux that redirects to cmux __tmux-compat",
|
||||
"shimStep2": "Sets TMUX and TMUX_PANE environment variables to simulate a tmux session",
|
||||
"shimStep3": "Prepends the shim directory to PATH so Claude finds the shim before real tmux",
|
||||
"shimStep4": "Enables CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 and sets teammate mode to auto",
|
||||
"envVars": "Environment variables",
|
||||
"envVarName": "Variable",
|
||||
"envVarPurpose": "Purpose",
|
||||
"envTmux": "Fake tmux socket path encoding the current cmux workspace and pane",
|
||||
"envTmuxPane": "Fake tmux pane identifier mapped to the current cmux pane",
|
||||
"envTeams": "Enables Claude Code agent teams feature",
|
||||
"envSocket": "Path to the cmux control socket for the shim to connect to",
|
||||
"directories": "Directories",
|
||||
"dirPath": "Path",
|
||||
"dirPurpose": "Purpose",
|
||||
"dirShim": "Contains the tmux shim script that translates tmux commands to cmux API calls",
|
||||
"dirStore": "Persistent storage for tmux-compat buffers and hooks",
|
||||
"tmuxCommands": "Supported tmux commands",
|
||||
"tmuxCommandsDesc": "The shim translates these tmux commands into cmux operations:",
|
||||
"mapWorkspace": "creates a new cmux workspace",
|
||||
"mapSplit": "splits the current cmux pane",
|
||||
"mapSendText": "sends text to a cmux surface",
|
||||
"mapReadText": "reads terminal text from a cmux surface",
|
||||
"mapFocus": "focuses a cmux pane or workspace",
|
||||
"mapClose": "closes a cmux surface or workspace",
|
||||
"mapList": "lists cmux panes or workspaces"
|
||||
},
|
||||
"ohMyOpenCode": {
|
||||
"title": "oh-my-opencode",
|
||||
"metaTitle": "oh-my-opencode - cmux",
|
||||
"metaDescription": "Run OpenCode with oh-my-openagent inside cmux. Multi-model agent orchestration with native cmux splits.",
|
||||
"nightlyWarning": "Available in <nightly>nightly builds</nightly> only.",
|
||||
"intro": "cmux omo launches OpenCode with the oh-my-openagent plugin in a cmux-aware environment. oh-my-openagent orchestrates multiple AI models (Claude, GPT, Gemini, Grok) as specialized agents working in parallel. When it spawns agent panes, they become native cmux splits.",
|
||||
"usage": "Usage",
|
||||
"usageDesc": "All arguments after omo are forwarded to OpenCode.",
|
||||
"whatYouGet": "What you get",
|
||||
"whatYouGetDesc": "oh-my-openagent's TmuxSessionManager spawns each background agent in its own pane. With cmux omo, those panes become native cmux splits instead of tmux panes:",
|
||||
"whatYouGet1": "Each subagent (Hephaestus, Atlas, Oracle, etc.) gets its own cmux split, visible in the workspace",
|
||||
"whatYouGet2": "Auto-layout management: agents are arranged in a grid (main-vertical by default) and resized as agents come and go",
|
||||
"whatYouGet3": "Idle agents are automatically cleaned up after 3 consecutive idle polls with no new messages",
|
||||
"whatYouGet4": "If the window is too small for a new agent pane, it queues and retries every 2 seconds until space is available",
|
||||
"whatYouGet5": "Your main session stays in the primary pane while agents work beside it",
|
||||
"firstRun": "First run",
|
||||
"firstRunDesc": "On first run, cmux omo automatically sets up everything:",
|
||||
"firstRunStep1": "Creates a shadow config at ~/.cmuxterm/omo-config/ with oh-my-opencode registered in the plugin array",
|
||||
"firstRunStep2": "Installs the oh-my-opencode npm package using bun or npm if not already present",
|
||||
"firstRunStep3": "Symlinks node_modules, package.json, and plugin config from your original ~/.config/opencode/ directory",
|
||||
"firstRunStep4": "Enables tmux mode in the oh-my-opencode config (tmux.enabled defaults to false, cmux omo turns it on)",
|
||||
"firstRunSafe": "Your original ~/.config/opencode/ config is never modified. Running plain opencode works the same as before.",
|
||||
"howItWorks": "How it works",
|
||||
"howItWorksDesc": "Same pattern as cmux claude-teams. A tmux shim intercepts tmux commands from oh-my-openagent's TmuxSessionManager and translates them into cmux API calls.",
|
||||
"shimStep1": "Creates a tmux shim at ~/.cmuxterm/omo-bin/tmux that redirects to cmux __tmux-compat",
|
||||
"shimStep2": "Sets TMUX and TMUX_PANE to simulate a tmux session",
|
||||
"shimStep3": "Enables tmux.enabled in the oh-my-opencode config (required for visual pane spawning)",
|
||||
"shimStep4": "Points OPENCODE_CONFIG_DIR at the shadow config",
|
||||
"shimStep5": "Prepends the shim directory to PATH and execs into opencode",
|
||||
"directories": "Directories",
|
||||
"dirPath": "Path",
|
||||
"dirPurpose": "Purpose",
|
||||
"dirShim": "Contains the tmux shim script",
|
||||
"dirShadow": "Shadow OpenCode config with oh-my-opencode plugin registered and tmux enabled (symlinks to your original config)",
|
||||
"dirStore": "Persistent storage for tmux-compat buffers and hooks",
|
||||
"shadowConfig": "Shadow config",
|
||||
"shadowConfigDesc": "cmux omo uses a shadow config directory so your original OpenCode setup is unaffected:",
|
||||
"shadowStep1": "Copies your ~/.config/opencode/opencode.json with oh-my-opencode added to the plugin array",
|
||||
"shadowStep2": "Symlinks node_modules, package.json, and bun.lock from the original directory",
|
||||
"shadowStep3": "Writes oh-my-opencode.json with tmux.enabled set to true",
|
||||
"shadowStep4": "Sets OPENCODE_CONFIG_DIR to the shadow directory before launching opencode",
|
||||
"envVars": "Environment variables",
|
||||
"envVarName": "Variable",
|
||||
"envVarPurpose": "Purpose",
|
||||
"envTmux": "Fake tmux socket path encoding the current cmux workspace and pane",
|
||||
"envTmuxPane": "Fake tmux pane identifier mapped to the current cmux pane",
|
||||
"envConfigDir": "Points to the shadow config directory with oh-my-opencode enabled",
|
||||
"envSocket": "Path to the cmux control socket for the shim to connect to"
|
||||
},
|
||||
"navItems": {
|
||||
"gettingStarted": "Getting Started",
|
||||
"concepts": "Concepts",
|
||||
|
|
@ -621,6 +706,9 @@
|
|||
"apiReference": "API Reference",
|
||||
"browserAutomation": "Browser Automation",
|
||||
"notifications": "Notifications",
|
||||
"agentIntegrations": "Agent Integrations",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "Changelog"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -621,6 +621,9 @@
|
|||
"apiReference": "Referencia de API",
|
||||
"browserAutomation": "Automatización del navegador",
|
||||
"notifications": "Notificaciones",
|
||||
"agentIntegrations": "Agent Integrations",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "Changelog"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -621,6 +621,9 @@
|
|||
"apiReference": "Référence API",
|
||||
"browserAutomation": "Automatisation du navigateur",
|
||||
"notifications": "Notifications",
|
||||
"agentIntegrations": "Agent Integrations",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "Changelog"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -621,6 +621,9 @@
|
|||
"apiReference": "Riferimento API",
|
||||
"browserAutomation": "Automazione del browser",
|
||||
"notifications": "Notifiche",
|
||||
"agentIntegrations": "Agent Integrations",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "Changelog"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -612,6 +612,81 @@
|
|||
"metaDescription": "cmuxのリリースノートとバージョン履歴。ネイティブmacOSターミナルの新機能、バグ修正、変更点。",
|
||||
"metaTitle": "変更履歴"
|
||||
},
|
||||
"claudeCodeTeams": {
|
||||
"title": "Claude Code Teams",
|
||||
"metaTitle": "Claude Code Teams - cmux",
|
||||
"metaDescription": "cmux内でClaude Codeのエージェントチームを実行。チームメイトエージェントはtmuxペインではなくネイティブのcmuxスプリットとして表示されます。",
|
||||
"nightlyWarning": "<nightly>ナイトリービルド</nightly>でのみ利用可能です。",
|
||||
"intro": "cmux claude-teamsはエージェントチームを有効にしてClaude Codeを起動します。Claudeがチームメイトエージェントを生成すると、tmuxペインではなくネイティブのcmuxスプリットとして表示され、サイドバーのメタデータや通知が利用できます。",
|
||||
"usage": "使い方",
|
||||
"usageDesc": "claude-teamsの後のすべての引数はClaude Codeに転送されます。コマンドはteammate modeをautoに設定し、Claudeがcmuxスプリットを使用する環境を構成します。",
|
||||
"howItWorks": "仕組み",
|
||||
"howItWorksDesc": "cmux claude-teamsはtmux shimスクリプトを作成し、Claude Codeがtmux内で動作していると認識するよう環境を構成します。Claudeがチームメイトペインを管理するためにtmuxコマンドを発行すると、shimがそれをcmuxソケットAPIコールに変換します。",
|
||||
"shimStep1": "~/.cmuxterm/claude-teams-bin/tmuxにtmux shimを作成し、cmux __tmux-compatにリダイレクト",
|
||||
"shimStep2": "TMUXとTMUX_PANE環境変数を設定してtmuxセッションをシミュレート",
|
||||
"shimStep3": "shimディレクトリをPATHの先頭に追加し、Claudeが本物のtmuxより先にshimを見つけるようにする",
|
||||
"shimStep4": "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1を有効にし、teammate modeをautoに設定",
|
||||
"envVars": "環境変数",
|
||||
"envVarName": "変数",
|
||||
"envVarPurpose": "目的",
|
||||
"envTmux": "現在のcmuxワークスペースとペインをエンコードした偽のtmuxソケットパス",
|
||||
"envTmuxPane": "現在のcmuxペインにマッピングされた偽のtmuxペイン識別子",
|
||||
"envTeams": "Claude Codeエージェントチーム機能を有効にする",
|
||||
"envSocket": "shimが接続するcmuxコントロールソケットのパス",
|
||||
"directories": "ディレクトリ",
|
||||
"dirPath": "パス",
|
||||
"dirPurpose": "目的",
|
||||
"dirShim": "tmuxコマンドをcmux APIコールに変換するtmux shimスクリプトを含む",
|
||||
"dirStore": "tmux-compatバッファとフックの永続ストレージ",
|
||||
"tmuxCommands": "対応するtmuxコマンド",
|
||||
"tmuxCommandsDesc": "shimは以下のtmuxコマンドをcmux操作に変換します:",
|
||||
"mapWorkspace": "新しいcmuxワークスペースを作成",
|
||||
"mapSplit": "現在のcmuxペインを分割",
|
||||
"mapSendText": "cmuxサーフェスにテキストを送信",
|
||||
"mapReadText": "cmuxサーフェスからターミナルテキストを読み取り",
|
||||
"mapFocus": "cmuxペインまたはワークスペースにフォーカス",
|
||||
"mapClose": "cmuxサーフェスまたはワークスペースを閉じる",
|
||||
"mapList": "cmuxペインまたはワークスペースを一覧表示"
|
||||
},
|
||||
"ohMyOpenCode": {
|
||||
"title": "oh-my-opencode",
|
||||
"metaTitle": "oh-my-opencode - cmux",
|
||||
"metaDescription": "cmux内でOpenCodeとoh-my-openagentを実行。マルチモデルエージェントオーケストレーションをネイティブcmuxスプリットで。",
|
||||
"nightlyWarning": "<nightly>ナイトリービルド</nightly>でのみ利用可能です。",
|
||||
"intro": "cmux omoはoh-my-openagentプラグインを有効にしてcmux対応環境でOpenCodeを起動します。oh-my-openagentは複数のAIモデル(Claude、GPT、Gemini、Grok)を専門エージェントとして並列にオーケストレーションします。エージェントペインはネイティブのcmuxスプリットになります。",
|
||||
"usage": "使い方",
|
||||
"usageDesc": "omoの後のすべての引数はOpenCodeに転送されます。",
|
||||
"firstRun": "初回実行",
|
||||
"firstRunDesc": "初回実行時、cmux omoはoh-my-opencodeプラグインを自動的にセットアップします:",
|
||||
"firstRunStep1": "~/.cmuxterm/omo-config/にoh-my-opencodeをプラグイン配列に登録したシャドウ設定を作成",
|
||||
"firstRunStep2": "oh-my-opencode npmパッケージがない場合、bunまたはnpmでインストール",
|
||||
"firstRunStep3": "元の~/.config/opencode/ディレクトリからnode_modules、package.json、プラグイン設定をシンボリックリンク",
|
||||
"firstRunSafe": "元の~/.config/opencode/設定は変更されません。通常のopencode実行は以前と同じように動作します。",
|
||||
"howItWorks": "仕組み",
|
||||
"howItWorksDesc": "cmux claude-teamsと同じパターンです。tmux shimがoh-my-openagentのTmuxSessionManagerからのtmuxコマンドを傍受し、cmux APIコールに変換します。",
|
||||
"shimStep1": "~/.cmuxterm/omo-bin/tmuxにtmux shimを作成",
|
||||
"shimStep2": "TMUXとTMUX_PANE環境変数を設定",
|
||||
"shimStep3": "OPENCODE_CONFIG_DIRをoh-my-opencodeが有効なシャドウ設定に指定",
|
||||
"shimStep4": "shimディレクトリをPATHの先頭に追加してopencodeにexec",
|
||||
"directories": "ディレクトリ",
|
||||
"dirPath": "パス",
|
||||
"dirPurpose": "目的",
|
||||
"dirShim": "tmux shimスクリプトを含む",
|
||||
"dirShadow": "oh-my-opencodeプラグインが登録されたOpenCodeのシャドウ設定(元の設定へのシンボリックリンク)",
|
||||
"dirStore": "tmux-compatバッファとフックの永続ストレージ",
|
||||
"shadowConfig": "シャドウ設定",
|
||||
"shadowConfigDesc": "cmux omoはシャドウ設定ディレクトリを使用するため、元のOpenCode設定には影響しません:",
|
||||
"shadowStep1": "~/.config/opencode/opencode.jsonをコピーし、プラグイン配列にoh-my-opencodeを追加",
|
||||
"shadowStep2": "元のディレクトリからnode_modules、package.json、bun.lockをシンボリックリンク",
|
||||
"shadowStep3": "opencode起動前にOPENCODE_CONFIG_DIRをシャドウディレクトリに設定",
|
||||
"envVars": "環境変数",
|
||||
"envVarName": "変数",
|
||||
"envVarPurpose": "目的",
|
||||
"envTmux": "現在のcmuxワークスペースとペインをエンコードした偽のtmuxソケットパス",
|
||||
"envTmuxPane": "現在のcmuxペインにマッピングされた偽のtmuxペイン識別子",
|
||||
"envConfigDir": "oh-my-opencodeが有効なシャドウ設定ディレクトリを指す",
|
||||
"envSocket": "shimが接続するcmuxコントロールソケットのパス"
|
||||
},
|
||||
"navItems": {
|
||||
"gettingStarted": "はじめに",
|
||||
"concepts": "コンセプト",
|
||||
|
|
@ -621,6 +696,9 @@
|
|||
"apiReference": "APIリファレンス",
|
||||
"browserAutomation": "ブラウザ自動化",
|
||||
"notifications": "通知",
|
||||
"agentIntegrations": "エージェント連携",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "変更履歴"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -621,6 +621,9 @@
|
|||
"apiReference": "ឯកសារយោង API",
|
||||
"browserAutomation": "ស្វ័យប្រវត្តិកម្មកម្មវិធីរុករក",
|
||||
"notifications": "ជូនដំណឹង",
|
||||
"agentIntegrations": "Agent Integrations",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "កំណត់ត្រាផ្លាស់ប្ដូរ"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -621,6 +621,9 @@
|
|||
"apiReference": "API 레퍼런스",
|
||||
"browserAutomation": "브라우저 자동화",
|
||||
"notifications": "알림",
|
||||
"agentIntegrations": "Agent Integrations",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "변경 로그"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -621,6 +621,9 @@
|
|||
"apiReference": "API-referanse",
|
||||
"browserAutomation": "Nettleserautomatisering",
|
||||
"notifications": "Varsler",
|
||||
"agentIntegrations": "Agent Integrations",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "Endringslogg"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -621,6 +621,9 @@
|
|||
"apiReference": "Dokumentacja API",
|
||||
"browserAutomation": "Automatyzacja przeglądarki",
|
||||
"notifications": "Powiadomienia",
|
||||
"agentIntegrations": "Agent Integrations",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "Dziennik zmian"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -621,6 +621,9 @@
|
|||
"apiReference": "Referência da API",
|
||||
"browserAutomation": "Automação do Navegador",
|
||||
"notifications": "Notificações",
|
||||
"agentIntegrations": "Agent Integrations",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "Changelog"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -621,6 +621,9 @@
|
|||
"apiReference": "Справочник API",
|
||||
"browserAutomation": "Автоматизация браузера",
|
||||
"notifications": "Уведомления",
|
||||
"agentIntegrations": "Agent Integrations",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "Изменения"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -621,6 +621,9 @@
|
|||
"apiReference": "เอกสาร API",
|
||||
"browserAutomation": "Browser Automation",
|
||||
"notifications": "การแจ้งเตือน",
|
||||
"agentIntegrations": "Agent Integrations",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "Changelog"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -621,6 +621,9 @@
|
|||
"apiReference": "API Referansı",
|
||||
"browserAutomation": "Tarayıcı Otomasyonu",
|
||||
"notifications": "Bildirimler",
|
||||
"agentIntegrations": "Agent Integrations",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "Değişiklik Günlüğü"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -621,6 +621,9 @@
|
|||
"apiReference": "API 参考",
|
||||
"browserAutomation": "浏览器自动化",
|
||||
"notifications": "通知",
|
||||
"agentIntegrations": "Agent Integrations",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "更新日志"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -621,6 +621,9 @@
|
|||
"apiReference": "API 參考",
|
||||
"browserAutomation": "瀏覽器自動化",
|
||||
"notifications": "通知",
|
||||
"agentIntegrations": "Agent Integrations",
|
||||
"claudeCodeTeams": "Claude Code Teams",
|
||||
"ohMyOpenCode": "oh-my-opencode",
|
||||
"changelog": "更新日誌"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue